aboutsummaryrefslogtreecommitdiffstats
path: root/diskdev_cmds
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
commit5fd83771641d15c418f747bd343ba6738d3875f7 (patch)
tree5abf0f78f680d9837dbd93d4d4c3933bb7509599 /diskdev_cmds
downloadapple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip
Import macOS userland
adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106
Diffstat (limited to 'diskdev_cmds')
-rw-r--r--diskdev_cmds/APPLE_LICENSE367
-rw-r--r--diskdev_cmds/dev_mkdb.tproj/dev_mkdb.881
-rw-r--r--diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c202
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj2411
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings8
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme61
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme61
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme61
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme61
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme88
-rw-r--r--diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme88
-rw-r--r--diskdev_cmds/disklib/dkcksum.c77
-rw-r--r--diskdev_cmds/disklib/dkdisklabel.c193
-rw-r--r--diskdev_cmds/disklib/dkopen.c57
-rw-r--r--diskdev_cmds/disklib/dkopen.h56
-rw-r--r--diskdev_cmds/disklib/dksecsize.c75
-rw-r--r--diskdev_cmds/disklib/pathnames.h63
-rw-r--r--diskdev_cmds/disklib/preen.c392
-rw-r--r--diskdev_cmds/disklib/vfslist.c112
-rw-r--r--diskdev_cmds/edquota.tproj/edquota.8184
-rw-r--r--diskdev_cmds/edquota.tproj/edquota.c1228
-rw-r--r--diskdev_cmds/edquota.tproj/pathnames.h61
-rw-r--r--diskdev_cmds/edt_fstab/edt_fstab.c180
-rw-r--r--diskdev_cmds/edt_fstab/edt_fstab.h47
-rw-r--r--diskdev_cmds/fdisk.tproj/auto.c155
-rw-r--r--diskdev_cmds/fdisk.tproj/auto.h31
-rw-r--r--diskdev_cmds/fdisk.tproj/cmd.c507
-rw-r--r--diskdev_cmds/fdisk.tproj/cmd.h105
-rw-r--r--diskdev_cmds/fdisk.tproj/disk.c309
-rw-r--r--diskdev_cmds/fdisk.tproj/disk.h83
-rw-r--r--diskdev_cmds/fdisk.tproj/fdisk.8377
-rw-r--r--diskdev_cmds/fdisk.tproj/fdisk.c289
-rw-r--r--diskdev_cmds/fdisk.tproj/getrawpartition.c87
-rw-r--r--diskdev_cmds/fdisk.tproj/mbr.c553
-rw-r--r--diskdev_cmds/fdisk.tproj/mbr.h114
-rw-r--r--diskdev_cmds/fdisk.tproj/mbrcode.h119
-rw-r--r--diskdev_cmds/fdisk.tproj/misc.c183
-rw-r--r--diskdev_cmds/fdisk.tproj/misc.h74
-rw-r--r--diskdev_cmds/fdisk.tproj/opendev.c111
-rw-r--r--diskdev_cmds/fdisk.tproj/part.c425
-rw-r--r--diskdev_cmds/fdisk.tproj/part.h80
-rw-r--r--diskdev_cmds/fdisk.tproj/user.c275
-rw-r--r--diskdev_cmds/fdisk.tproj/user.h65
-rw-r--r--diskdev_cmds/fdisk.tproj/util.h137
-rw-r--r--diskdev_cmds/fsck.tproj/fsck.8176
-rw-r--r--diskdev_cmds/fsck.tproj/fsck.c1339
-rw-r--r--diskdev_cmds/fsck.tproj/fsck.h121
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp.841
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp.c167
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp_msdos.841
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp_msdos.c213
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp_ntfs.841
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp_ntfs.c206
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp_udf.840
-rw-r--r--diskdev_cmds/fstyp.tproj/fstyp_udf.c306
-rw-r--r--diskdev_cmds/fuser.tproj/fuser.1200
-rwxr-xr-xdiskdev_cmds/fuser.tproj/fuser.pl92
-rw-r--r--diskdev_cmds/mount.tproj/fstab.5222
-rw-r--r--diskdev_cmds/mount.tproj/mount.8293
-rw-r--r--diskdev_cmds/mount.tproj/mount.c1696
-rw-r--r--diskdev_cmds/mount.tproj/mount.entitlements12
-rw-r--r--diskdev_cmds/mount.tproj/pathnames.h63
-rw-r--r--diskdev_cmds/mount_devfs.tproj/mount_devfs.c117
-rw-r--r--diskdev_cmds/mount_fdesc.tproj/mount_fdesc.8171
-rw-r--r--diskdev_cmds/mount_fdesc.tproj/mount_fdesc.c128
-rw-r--r--diskdev_cmds/mount_flags_dir/mount_flags.c88
-rw-r--r--diskdev_cmds/mount_flags_dir/mount_flags.h66
-rw-r--r--diskdev_cmds/quota.tproj/quota.1137
-rw-r--r--diskdev_cmds/quota.tproj/quota.c858
-rw-r--r--diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c169
-rw-r--r--diskdev_cmds/quotacheck.tproj/quotacheck.8156
-rw-r--r--diskdev_cmds/quotacheck.tproj/quotacheck.c972
-rw-r--r--diskdev_cmds/quotacheck.tproj/quotacheck.h87
-rw-r--r--diskdev_cmds/quotaon.tproj/quotaon.8159
-rw-r--r--diskdev_cmds/quotaon.tproj/quotaon.c400
-rw-r--r--diskdev_cmds/repquota.tproj/repquota.8109
-rw-r--r--diskdev_cmds/repquota.tproj/repquota.c630
-rw-r--r--diskdev_cmds/setclass.tproj/setclass.846
-rw-r--r--diskdev_cmds/setclass.tproj/setclass.c153
-rw-r--r--diskdev_cmds/umount.tproj/umount.8133
-rw-r--r--diskdev_cmds/umount.tproj/umount.c655
-rw-r--r--diskdev_cmds/vndevice.tproj/vndevice.c134
-rw-r--r--diskdev_cmds/vsdbutil.tproj/com.apple.vsdbutil.plist21
-rw-r--r--diskdev_cmds/vsdbutil.tproj/vsdbutil.849
-rw-r--r--diskdev_cmds/vsdbutil.tproj/vsdbutil_main.c1213
104 files changed, 23804 insertions, 0 deletions
diff --git a/diskdev_cmds/APPLE_LICENSE b/diskdev_cmds/APPLE_LICENSE
new file mode 100644
index 0000000..fe81a60
--- /dev/null
+++ b/diskdev_cmds/APPLE_LICENSE
@@ -0,0 +1,367 @@
+APPLE PUBLIC SOURCE LICENSE
+Version 2.0 - August 6, 2003
+
+Please read this License carefully before downloading this software.
+By downloading or using this software, you are agreeing to be bound by
+the terms of this License. If you do not or cannot agree to the terms
+of this License, please do not download or use the software.
+
+1. General; Definitions. This License applies to any program or other
+work which Apple Computer, Inc. ("Apple") makes publicly available and
+which contains a notice placed by Apple identifying such program or
+work as "Original Code" and stating that it is subject to the terms of
+this Apple Public Source License version 2.0 ("License"). As used in
+this License:
+
+1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
+the grantor of rights, (i) claims of patents that are now or hereafter
+acquired, owned by or assigned to Apple and (ii) that cover subject
+matter contained in the Original Code, but only to the extent
+necessary to use, reproduce and/or distribute the Original Code
+without infringement; and (b) in the case where You are the grantor of
+rights, (i) claims of patents that are now or hereafter acquired,
+owned by or assigned to You and (ii) that cover subject matter in Your
+Modifications, taken alone or in combination with Original Code.
+
+1.2 "Contributor" means any person or entity that creates or
+contributes to the creation of Modifications.
+
+1.3 "Covered Code" means the Original Code, Modifications, the
+combination of Original Code and any Modifications, and/or any
+respective portions thereof.
+
+1.4 "Externally Deploy" means: (a) to sublicense, distribute or
+otherwise make Covered Code available, directly or indirectly, to
+anyone other than You; and/or (b) to use Covered Code, alone or as
+part of a Larger Work, in any way to provide a service, including but
+not limited to delivery of content, through electronic communication
+with a client other than You.
+
+1.5 "Larger Work" means a work which combines Covered Code or portions
+thereof with code not governed by the terms of this License.
+
+1.6 "Modifications" mean any addition to, deletion from, and/or change
+to, the substance and/or structure of the Original Code, any previous
+Modifications, the combination of Original Code and any previous
+Modifications, and/or any respective portions thereof. When code is
+released as a series of files, a Modification is: (a) any addition to
+or deletion from the contents of a file containing Covered Code;
+and/or (b) any new file or other representation of computer program
+statements that contains any part of Covered Code.
+
+1.7 "Original Code" means (a) the Source Code of a program or other
+work as originally made available by Apple under this License,
+including the Source Code of any updates or upgrades to such programs
+or works made available by Apple under this License, and that has been
+expressly identified by Apple as such in the header file(s) of such
+work; and (b) the object code compiled from such Source Code and
+originally made available by Apple under this License.
+
+1.8 "Source Code" means the human readable form of a program or other
+work that is suitable for making modifications to it, including all
+modules it contains, plus any associated interface definition files,
+scripts used to control compilation and installation of an executable
+(object code).
+
+1.9 "You" or "Your" means an individual or a legal entity exercising
+rights under this License. For legal entities, "You" or "Your"
+includes any entity which controls, is controlled by, or is under
+common control with, You, where "control" means (a) the power, direct
+or indirect, to cause the direction or management of such entity,
+whether by contract or otherwise, or (b) ownership of fifty percent
+(50%) or more of the outstanding shares or beneficial ownership of
+such entity.
+
+2. Permitted Uses; Conditions & Restrictions. Subject to the terms
+and conditions of this License, Apple hereby grants You, effective on
+the date You accept this License and download the Original Code, a
+world-wide, royalty-free, non-exclusive license, to the extent of
+Apple's Applicable Patent Rights and copyrights covering the Original
+Code, to do the following:
+
+2.1 Unmodified Code. You may use, reproduce, display, perform,
+internally distribute within Your organization, and Externally Deploy
+verbatim, unmodified copies of the Original Code, for commercial or
+non-commercial purposes, provided that in each instance:
+
+(a) You must retain and reproduce in all copies of Original Code the
+copyright and other proprietary notices and disclaimers of Apple as
+they appear in the Original Code, and keep intact all notices in the
+Original Code that refer to this License; and
+
+(b) You must include a copy of this License with every copy of Source
+Code of Covered Code and documentation You distribute or Externally
+Deploy, and You may not offer or impose any terms on such Source Code
+that alter or restrict this License or the recipients' rights
+hereunder, except as permitted under Section 6.
+
+2.2 Modified Code. You may modify Covered Code and use, reproduce,
+display, perform, internally distribute within Your organization, and
+Externally Deploy Your Modifications and Covered Code, for commercial
+or non-commercial purposes, provided that in each instance You also
+meet all of these conditions:
+
+(a) You must satisfy all the conditions of Section 2.1 with respect to
+the Source Code of the Covered Code;
+
+(b) You must duplicate, to the extent it does not already exist, the
+notice in Exhibit A in each file of the Source Code of all Your
+Modifications, and cause the modified files to carry prominent notices
+stating that You changed the files and the date of any change; and
+
+(c) If You Externally Deploy Your Modifications, You must make
+Source Code of all Your Externally Deployed Modifications either
+available to those to whom You have Externally Deployed Your
+Modifications, or publicly available. Source Code of Your Externally
+Deployed Modifications must be released under the terms set forth in
+this License, including the license grants set forth in Section 3
+below, for as long as you Externally Deploy the Covered Code or twelve
+(12) months from the date of initial External Deployment, whichever is
+longer. You should preferably distribute the Source Code of Your
+Externally Deployed Modifications electronically (e.g. download from a
+web site).
+
+2.3 Distribution of Executable Versions. In addition, if You
+Externally Deploy Covered Code (Original Code and/or Modifications) in
+object code, executable form only, You must include a prominent
+notice, in the code itself as well as in related documentation,
+stating that Source Code of the Covered Code is available under the
+terms of this License with information on how and where to obtain such
+Source Code.
+
+2.4 Third Party Rights. You expressly acknowledge and agree that
+although Apple and each Contributor grants the licenses to their
+respective portions of the Covered Code set forth herein, no
+assurances are provided by Apple or any Contributor that the Covered
+Code does not infringe the patent or other intellectual property
+rights of any other entity. Apple and each Contributor disclaim any
+liability to You for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a
+condition to exercising the rights and licenses granted hereunder, You
+hereby assume sole responsibility to secure any other intellectual
+property rights needed, if any. For example, if a third party patent
+license is required to allow You to distribute the Covered Code, it is
+Your responsibility to acquire that license before distributing the
+Covered Code.
+
+3. Your Grants. In consideration of, and as a condition to, the
+licenses granted to You under this License, You hereby grant to any
+person or entity receiving or distributing Covered Code under this
+License a non-exclusive, royalty-free, perpetual, irrevocable license,
+under Your Applicable Patent Rights and other intellectual property
+rights (other than patent) owned or controlled by You, to use,
+reproduce, display, perform, modify, sublicense, distribute and
+Externally Deploy Your Modifications of the same scope and extent as
+Apple's licenses under Sections 2.1 and 2.2 above.
+
+4. Larger Works. You may create a Larger Work by combining Covered
+Code with other code not governed by the terms of this License and
+distribute the Larger Work as a single product. In each such instance,
+You must make sure the requirements of this License are fulfilled for
+the Covered Code or any portion thereof.
+
+5. Limitations on Patent License. Except as expressly stated in
+Section 2, no other patent rights, express or implied, are granted by
+Apple herein. Modifications and/or Larger Works may require additional
+patent licenses from Apple which Apple may grant in its sole
+discretion.
+
+6. Additional Terms. You may choose to offer, and to charge a fee for,
+warranty, support, indemnity or liability obligations and/or other
+rights consistent with the scope of the license granted herein
+("Additional Terms") to one or more recipients of Covered Code.
+However, You may do so only on Your own behalf and as Your sole
+responsibility, and not on behalf of Apple or any Contributor. You
+must obtain the recipient's agreement that any such Additional Terms
+are offered by You alone, and You hereby agree to indemnify, defend
+and hold Apple and every Contributor harmless for any liability
+incurred by or claims asserted against Apple or such Contributor by
+reason of any such Additional Terms.
+
+7. Versions of the License. Apple may publish revised and/or new
+versions of this License from time to time. Each version will be given
+a distinguishing version number. Once Original Code has been published
+under a particular version of this License, You may continue to use it
+under the terms of that version. You may also choose to use such
+Original Code under the terms of any subsequent version of this
+License published by Apple. No one other than Apple has the right to
+modify the terms applicable to Covered Code created under this
+License.
+
+8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
+part pre-release, untested, or not fully tested works. The Covered
+Code may contain errors that could cause failures or loss of data, and
+may be incomplete or contain inaccuracies. You expressly acknowledge
+and agree that use of the Covered Code, or any portion thereof, is at
+Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
+WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
+APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
+PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
+ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
+MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
+PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
+PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
+INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
+FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
+THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
+ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
+ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
+AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
+You acknowledge that the Covered Code is not intended for use in the
+operation of nuclear facilities, aircraft navigation, communication
+systems, or air traffic control machines in which case the failure of
+the Covered Code could lead to death, personal injury, or severe
+physical or environmental damage.
+
+9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
+TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
+ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
+TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
+APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
+REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
+TO YOU. In no event shall Apple's total liability to You for all
+damages (other than as may be required by applicable law) under this
+License exceed the amount of fifty dollars ($50.00).
+
+10. Trademarks. This License does not grant any rights to use the
+trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
+"QuickTime", "QuickTime Streaming Server" or any other trademarks,
+service marks, logos or trade names belonging to Apple (collectively
+"Apple Marks") or to any trademark, service mark, logo or trade name
+belonging to any Contributor. You agree not to use any Apple Marks in
+or as part of the name of products derived from the Original Code or
+to endorse or promote products derived from the Original Code other
+than as expressly permitted by and in strict compliance at all times
+with Apple's third party trademark usage guidelines which are posted
+at http://www.apple.com/legal/guidelinesfor3rdparties.html.
+
+11. Ownership. Subject to the licenses granted under this License,
+each Contributor retains all rights, title and interest in and to any
+Modifications made by such Contributor. Apple retains all rights,
+title and interest in and to the Original Code and any Modifications
+made by or on behalf of Apple ("Apple Modifications"), and such Apple
+Modifications will not be automatically subject to this License. Apple
+may, at its sole discretion, choose to license such Apple
+Modifications under this License, or on different terms from those
+contained in this License or may choose not to license them at all.
+
+12. Termination.
+
+12.1 Termination. This License and the rights granted hereunder will
+terminate:
+
+(a) automatically without notice from Apple if You fail to comply with
+any term(s) of this License and fail to cure such breach within 30
+days of becoming aware of such breach;
+
+(b) immediately in the event of the circumstances described in Section
+13.5(b); or
+
+(c) automatically without notice from Apple if You, at any time during
+the term of this License, commence an action for patent infringement
+against Apple; provided that Apple did not first commence
+an action for patent infringement against You in that instance.
+
+12.2 Effect of Termination. Upon termination, You agree to immediately
+stop any further use, reproduction, modification, sublicensing and
+distribution of the Covered Code. All sublicenses to the Covered Code
+which have been properly granted prior to termination shall survive
+any termination of this License. Provisions which, by their nature,
+should remain in effect beyond the termination of this License shall
+survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
+12.2 and 13. No party will be liable to any other for compensation,
+indemnity or damages of any sort solely as a result of terminating
+this License in accordance with its terms, and termination of this
+License will be without prejudice to any other right or remedy of
+any party.
+
+13. Miscellaneous.
+
+13.1 Government End Users. The Covered Code is a "commercial item" as
+defined in FAR 2.101. Government software and technical data rights in
+the Covered Code include only those rights customarily provided to the
+public as defined in this License. This customary commercial license
+in technical data and software is provided in accordance with FAR
+12.211 (Technical Data) and 12.212 (Computer Software) and, for
+Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
+Commercial Items) and 227.7202-3 (Rights in Commercial Computer
+Software or Computer Software Documentation). Accordingly, all U.S.
+Government End Users acquire Covered Code with only those rights set
+forth herein.
+
+13.2 Relationship of Parties. This License will not be construed as
+creating an agency, partnership, joint venture or any other form of
+legal association between or among You, Apple or any Contributor, and
+You will not represent to the contrary, whether expressly, by
+implication, appearance or otherwise.
+
+13.3 Independent Development. Nothing in this License will impair
+Apple's right to acquire, license, develop, have others develop for
+it, market and/or distribute technology or products that perform the
+same or similar functions as, or otherwise compete with,
+Modifications, Larger Works, technology or products that You may
+develop, produce, market or distribute.
+
+13.4 Waiver; Construction. Failure by Apple or any Contributor to
+enforce any provision of this License will not be deemed a waiver of
+future enforcement of that or any other provision. Any law or
+regulation which provides that the language of a contract shall be
+construed against the drafter will not apply to this License.
+
+13.5 Severability. (a) If for any reason a court of competent
+jurisdiction finds any provision of this License, or portion thereof,
+to be unenforceable, that provision of the License will be enforced to
+the maximum extent permissible so as to effect the economic benefits
+and intent of the parties, and the remainder of this License will
+continue in full force and effect. (b) Notwithstanding the foregoing,
+if applicable law prohibits or restricts You from fully and/or
+specifically complying with Sections 2 and/or 3 or prevents the
+enforceability of either of those Sections, this License will
+immediately terminate and You must immediately discontinue any use of
+the Covered Code and destroy all copies of it that are in your
+possession or control.
+
+13.6 Dispute Resolution. Any litigation or other dispute resolution
+between You and Apple relating to this License shall take place in the
+Northern District of California, and You and Apple hereby consent to
+the personal jurisdiction of, and venue in, the state and federal
+courts within that District with respect to this License. The
+application of the United Nations Convention on Contracts for the
+International Sale of Goods is expressly excluded.
+
+13.7 Entire Agreement; Governing Law. This License constitutes the
+entire agreement between the parties with respect to the subject
+matter hereof. This License shall be governed by the laws of the
+United States and the State of California, except that body of
+California law concerning conflicts of law.
+
+Where You are located in the province of Quebec, Canada, the following
+clause applies: The parties hereby confirm that they have requested
+that this License and all related documents be drafted in English. Les
+parties ont exige que le present contrat et tous les documents
+connexes soient rediges en anglais.
+
+EXHIBIT A.
+
+"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
+Reserved.
+
+This file contains Original Code and/or Modifications of Original Code
+as defined in and that are subject to the Apple Public Source License
+Version 2.0 (the 'License'). You may not use this file except in
+compliance with the License. Please obtain a copy of the License at
+http://www.opensource.apple.com/apsl/ and read it before using this
+file.
+
+The Original Code and all software distributed under the License are
+distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+Please see the License for the specific language governing rights and
+limitations under the License."
diff --git a/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8 b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8
new file mode 100644
index 0000000..9369b2b
--- /dev/null
+++ b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.8
@@ -0,0 +1,81 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)dev_mkdb.8 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Os
+.Dt DEV_MKDB 8
+.Sh NAME
+.Nm dev_mkdb
+.Nd create
+.Pa /dev
+database
+.Sh SYNOPSIS
+.Nm dev_mkdb
+.Sh DESCRIPTION
+The
+.Nm dev_mkdb
+command creates a
+.Xr db 3
+hash access method database in
+.Dq Pa /var/run/dev.db
+which contains the names of all of the character and block special
+files in the
+.Dq Pa /dev
+directory, using the file type and the
+.Fa st_rdev
+field as the key.
+.Pp
+Keys are a structure containing a mode_t followed by a dev_t,
+with any padding zero'd out.
+The former is the type of the file (st_mode & S_IFMT),
+the latter is the st_rdev field.
+.Sh FILES
+.Bl -tag -width /var/run/dev.db -compact
+.It Pa /dev
+Device directory.
+.It Pa /var/run/dev.db
+Database file.
+.El
+.Sh SEE ALSO
+.Xr ps 1 ,
+.Xr stat 2 ,
+.Xr db 3 ,
+.Xr devname 3 ,
+.Xr kvm_nlist 3 ,
+.Xr ttyname 3 ,
+.Xr kvm_mkdb 8
+.Sh HISTORY
+The
+.Nm dev_mkdb
+command appeared in
+.Bx 4.4 .
diff --git a/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c
new file mode 100644
index 0000000..82c7429
--- /dev/null
+++ b/diskdev_cmds/dev_mkdb.tproj/dev_mkdb.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/******
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+******/
+
+/******
+static char sccsid[] = "@(#)dev_mkdb.c 8.1 (Berkeley) 6/6/93";
+******/
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#undef DIRBLKSIZ
+#include <dirent.h>
+#include <nlist.h>
+#include <db.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <string.h>
+
+void err __P((const char *, ...));
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register DIR *dirp;
+ register struct dirent *dp;
+ struct stat sb;
+ struct {
+ mode_t type;
+ dev_t dev;
+ } bkey;
+ DB *db;
+ DBT data, key;
+ int ch;
+ u_char buf[MAXNAMLEN + 1];
+ char dbtmp[MAXPATHLEN + 1], dbname[MAXPATHLEN + 1];
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch((char)ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ usage();
+
+ if (chdir(_PATH_DEV))
+ err("%s: %s", _PATH_DEV, strerror(errno));
+
+ dirp = opendir(".");
+
+ (void)snprintf(dbtmp, sizeof(dbtmp), "%sdev.tmp", _PATH_VARRUN);
+ (void)snprintf(dbname, sizeof(dbtmp), "%sdev.db", _PATH_VARRUN);
+ db = dbopen(dbtmp, O_CREAT|O_EXLOCK|O_RDWR|O_TRUNC,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, DB_HASH, NULL);
+ if (db == NULL)
+ err("%s: %s", dbtmp, strerror(errno));
+
+ /*
+ * Keys are a mode_t followed by a dev_t. The former is the type of
+ * the file (mode & S_IFMT), the latter is the st_rdev field. Note
+ * that the structure may contain padding, so we have to clear it
+ * out here.
+ */
+ bzero(&bkey, sizeof(bkey));
+ key.data = &bkey;
+ key.size = sizeof(bkey);
+ data.data = buf;
+ while ((dp = readdir(dirp))) {
+ if (lstat(dp->d_name, &sb)) {
+ (void)fprintf(stderr,
+ "dev_mkdb: %s: %s\n", dp->d_name, strerror(errno));
+ continue;
+ }
+
+ /* Create the key. */
+ if (S_ISCHR(sb.st_mode))
+ bkey.type = S_IFCHR;
+ else if (S_ISBLK(sb.st_mode))
+ bkey.type = S_IFBLK;
+ else
+ continue;
+ bkey.dev = sb.st_rdev;
+
+ /*
+ * Create the data; nul terminate the name so caller doesn't
+ * have to.
+ */
+ bcopy(dp->d_name, buf, dp->d_namlen);
+ buf[dp->d_namlen] = '\0';
+ data.size = dp->d_namlen + 1;
+ if ((db->put)(db, &key, &data, 0))
+ err("dbput %s: %s\n", dbtmp, strerror(errno));
+ }
+ (void)(db->close)(db);
+ if (rename(dbtmp, dbname))
+ err("rename %s to %s: %s", dbtmp, dbname, strerror(errno));
+ exit(0);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage: dev_mkdb\n");
+ exit(1);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+ char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ (void)fprintf(stderr, "dev_mkdb: ");
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ (void)fprintf(stderr, "\n");
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj b/diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..ff896ee
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/project.pbxproj
@@ -0,0 +1,2411 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 4D55934F153CE4CC009F2584 /* Common */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 4D559350153CE4CC009F2584 /* Build configuration list for PBXAggregateTarget "Common" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 4D559357153CE4EA009F2584 /* PBXTargetDependency */,
+ 4D559472153DC87B009F2584 /* PBXTargetDependency */,
+ 4D559359153CE4EC009F2584 /* PBXTargetDependency */,
+ 4D55935B153CE4ED009F2584 /* PBXTargetDependency */,
+ 4D559498153DC9E8009F2584 /* PBXTargetDependency */,
+ 4D5594A7153DCA04009F2584 /* PBXTargetDependency */,
+ 4D5594B9153DCA5E009F2584 /* PBXTargetDependency */,
+ 4D5594DF153DCC73009F2584 /* PBXTargetDependency */,
+ 4D559373153CE5F8009F2584 /* PBXTargetDependency */,
+ 4D559426153DC38F009F2584 /* PBXTargetDependency */,
+ 4D55943A153DC4C0009F2584 /* PBXTargetDependency */,
+ 4D55939C153CE83A009F2584 /* PBXTargetDependency */,
+ 4D559415153DC282009F2584 /* PBXTargetDependency */,
+ 071077D92488A09C003B97C7 /* PBXTargetDependency */,
+ );
+ name = Common;
+ productName = All;
+ };
+ 4D559440153DC57D009F2584 /* All_MacOSX */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 4D559441153DC57D009F2584 /* Build configuration list for PBXAggregateTarget "All_MacOSX" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 4D559447153DC597009F2584 /* PBXTargetDependency */,
+ B12C9C9222A7CDE300B9F497 /* PBXTargetDependency */,
+ B12C9C9422A7CDE300B9F497 /* PBXTargetDependency */,
+ B12C9C9622A7CDE300B9F497 /* PBXTargetDependency */,
+ B12C9C9822A7CDE300B9F497 /* PBXTargetDependency */,
+ B12C9C9A22A7CDE300B9F497 /* PBXTargetDependency */,
+ B12C9C9C22A7CDE300B9F497 /* PBXTargetDependency */,
+ 07747AA21DA8511D00ACE020 /* PBXTargetDependency */,
+ 4D55945C153DC665009F2584 /* PBXTargetDependency */,
+ );
+ name = All_MacOSX;
+ productName = All_MacOSX;
+ };
+ 4D559443153DC587009F2584 /* All_iOS */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 4D559444153DC587009F2584 /* Build configuration list for PBXAggregateTarget "All_iOS" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 4D559449153DC599009F2584 /* PBXTargetDependency */,
+ );
+ name = All_iOS;
+ productName = All_iOS;
+ };
+ 4D559514153DE116009F2584 /* quotaoff */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 4D559515153DE116009F2584 /* Build configuration list for PBXAggregateTarget "quotaoff" */;
+ buildPhases = (
+ 4D55951B153DE1EF009F2584 /* ShellScript */,
+ );
+ dependencies = (
+ 4D55951A153DE1CB009F2584 /* PBXTargetDependency */,
+ );
+ name = quotaoff;
+ productName = quotaoff;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 072AAAA62167CE8F004ED4E2 /* mount_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 072AAAA42167CE8E004ED4E2 /* mount_flags.c */; };
+ 078B970D2190682600674625 /* mount_flags.c in Sources */ = {isa = PBXBuildFile; fileRef = 072AAAA42167CE8E004ED4E2 /* mount_flags.c */; };
+ 07CE4C1821906BB800BF11C0 /* mount.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55936C153CE58E009F2584 /* mount.c */; };
+ 1A9041022091EE830061D05A /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041012091EE830061D05A /* IOKit.framework */; };
+ 1A9041042091EE910061D05A /* APFS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041032091EE910061D05A /* APFS.framework */; };
+ 1A9041062091EE980061D05A /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041052091EE980061D05A /* CoreFoundation.framework */; };
+ 4D07DD57153CA9DC002B57CB /* dkcksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD4D153CA9DC002B57CB /* dkcksum.c */; };
+ 4D07DD58153CA9DC002B57CB /* dkdisklabel.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD4E153CA9DC002B57CB /* dkdisklabel.c */; };
+ 4D07DD59153CA9DC002B57CB /* dkopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD4F153CA9DC002B57CB /* dkopen.c */; };
+ 4D07DD5A153CA9DC002B57CB /* dkopen.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D07DD50153CA9DC002B57CB /* dkopen.h */; };
+ 4D07DD5B153CA9DC002B57CB /* dksecsize.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD51153CA9DC002B57CB /* dksecsize.c */; };
+ 4D07DD5E153CA9DC002B57CB /* pathnames.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D07DD54153CA9DC002B57CB /* pathnames.h */; };
+ 4D07DD5F153CA9DC002B57CB /* preen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD55153CA9DC002B57CB /* preen.c */; };
+ 4D07DD60153CA9DC002B57CB /* vfslist.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D07DD56153CA9DC002B57CB /* vfslist.c */; };
+ 4D559332153CE1D9009F2584 /* auto.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55931E153CE1D9009F2584 /* auto.c */; };
+ 4D559333153CE1D9009F2584 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559320153CE1D9009F2584 /* cmd.c */; };
+ 4D559334153CE1D9009F2584 /* disk.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559322153CE1D9009F2584 /* disk.c */; };
+ 4D559335153CE1D9009F2584 /* fdisk.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559325153CE1D9009F2584 /* fdisk.c */; };
+ 4D559336153CE1D9009F2584 /* getrawpartition.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559326153CE1D9009F2584 /* getrawpartition.c */; };
+ 4D559337153CE1D9009F2584 /* mbr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559327153CE1D9009F2584 /* mbr.c */; };
+ 4D559338153CE1D9009F2584 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932A153CE1D9009F2584 /* misc.c */; };
+ 4D559339153CE1D9009F2584 /* opendev.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932C153CE1D9009F2584 /* opendev.c */; };
+ 4D55933A153CE1D9009F2584 /* part.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932D153CE1D9009F2584 /* part.c */; };
+ 4D55933B153CE1D9009F2584 /* user.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55932F153CE1D9009F2584 /* user.c */; };
+ 4D55933C153CE242009F2584 /* fdisk.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559324153CE1D9009F2584 /* fdisk.8 */; };
+ 4D55934D153CE44E009F2584 /* fsck.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55934B153CE44E009F2584 /* fsck.c */; };
+ 4D55934E153CE4B1009F2584 /* fsck.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55934A153CE44E009F2584 /* fsck.8 */; };
+ 4D55936F153CE5D6009F2584 /* fstab.5 in Copy man5 */ = {isa = PBXBuildFile; fileRef = 4D559369153CE58E009F2584 /* fstab.5 */; };
+ 4D559371153CE5EA009F2584 /* mount.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55936B153CE58E009F2584 /* mount.8 */; };
+ 4D559389153CE794009F2584 /* libdisk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D07DD49153CA9A0002B57CB /* libdisk.a */; };
+ 4D559399153CE826009F2584 /* umount.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559398153CE826009F2584 /* umount.c */; };
+ 4D55939A153CE82E009F2584 /* umount.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559397153CE826009F2584 /* umount.8 */; };
+ 4D55939D153CE8AF009F2584 /* libdisk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D07DD49153CA9A0002B57CB /* libdisk.a */; };
+ 4D5593B2153CEABD009F2584 /* edquota.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593B0153CEABD009F2584 /* edquota.c */; };
+ 4D5593C4153CEB9A009F2584 /* quota.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593C3153CEB9A009F2584 /* quota.c */; };
+ 4D5593C5153CEBB4009F2584 /* edquota.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5593AF153CEABD009F2584 /* edquota.8 */; };
+ 4D5593C6153CEBC3009F2584 /* quota.1 in Copy man1 */ = {isa = PBXBuildFile; fileRef = 4D5593C2153CEB9A009F2584 /* quota.1 */; };
+ 4D5593DC153CED51009F2584 /* hfs_quotacheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593D8153CED51009F2584 /* hfs_quotacheck.c */; };
+ 4D5593DD153CED51009F2584 /* quotacheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593DA153CED51009F2584 /* quotacheck.c */; };
+ 4D5593DE153CED6A009F2584 /* quotacheck.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5593D9153CED51009F2584 /* quotacheck.8 */; };
+ 4D5593DF153CED8D009F2584 /* libdisk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D07DD49153CA9A0002B57CB /* libdisk.a */; };
+ 4D5593EF153CEE66009F2584 /* quotaon.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5593EE153CEE66009F2584 /* quotaon.c */; };
+ 4D5593F0153CEE74009F2584 /* quotaon.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5593ED153CEE66009F2584 /* quotaon.8 */; };
+ 4D559403153DC13D009F2584 /* repquota.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559402153DC13D009F2584 /* repquota.c */; };
+ 4D559404153DC150009F2584 /* repquota.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559401153DC13D009F2584 /* repquota.8 */; };
+ 4D559417153DC2AB009F2584 /* vndevice.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559416153DC2AB009F2584 /* vndevice.c */; };
+ 4D559428153DC3A6009F2584 /* mount_devfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559427153DC3A6009F2584 /* mount_devfs.c */; };
+ 4D55942B153DC427009F2584 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D55942A153DC420009F2584 /* libutil.dylib */; };
+ 4D55943D153DC4DE009F2584 /* mount_fdesc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55943C153DC4DE009F2584 /* mount_fdesc.c */; };
+ 4D55943E153DC4E9009F2584 /* mount_fdesc.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55943B153DC4DE009F2584 /* mount_fdesc.8 */; };
+ 4D55943F153DC534009F2584 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D55942A153DC420009F2584 /* libutil.dylib */; };
+ 4D55945A153DC650009F2584 /* vsdbutil_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559458153DC650009F2584 /* vsdbutil_main.c */; };
+ 4D55945D153DC728009F2584 /* vsdbutil.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559459153DC650009F2584 /* vsdbutil.8 */; };
+ 4D55945F153DC735009F2584 /* com.apple.vsdbutil.plist in Copy com.apple.vsdbutil.plist */ = {isa = PBXBuildFile; fileRef = 4D559457153DC650009F2584 /* com.apple.vsdbutil.plist */; };
+ 4D55946F153DC839009F2584 /* dev_mkdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D55946E153DC839009F2584 /* dev_mkdb.c */; };
+ 4D559470153DC84E009F2584 /* dev_mkdb.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D55946D153DC839009F2584 /* dev_mkdb.8 */; };
+ 4D559482153DC912009F2584 /* fstyp.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559481153DC912009F2584 /* fstyp.c */; };
+ 4D559483153DC92D009F2584 /* fstyp.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559480153DC912009F2584 /* fstyp.8 */; };
+ 4D559495153DC9AE009F2584 /* fstyp_msdos.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D559494153DC9AE009F2584 /* fstyp_msdos.c */; };
+ 4D559496153DC9BC009F2584 /* fstyp_msdos.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D559493153DC9AE009F2584 /* fstyp_msdos.8 */; };
+ 4D5594AA153DCA19009F2584 /* fstyp_ntfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5594A9153DCA19009F2584 /* fstyp_ntfs.c */; };
+ 4D5594BC153DCA74009F2584 /* fstyp_udf.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5594BB153DCA74009F2584 /* fstyp_udf.c */; };
+ 4D5594BD153DCA85009F2584 /* fstyp_udf.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5594BA153DCA74009F2584 /* fstyp_udf.8 */; };
+ 4D5594CD153DCB72009F2584 /* setclass.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D5594CC153DCB72009F2584 /* setclass.c */; };
+ 4D5594CE153DCB82009F2584 /* setclass.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5594CB153DCB72009F2584 /* setclass.8 */; };
+ 4D5594E2153DCCAC009F2584 /* fuser.1 in Copy man1 */ = {isa = PBXBuildFile; fileRef = 4D5594E0153DCC92009F2584 /* fuser.1 */; };
+ 4D5594E6153DCFFB009F2584 /* fstyp_ntfs.8 in Copy man8 */ = {isa = PBXBuildFile; fileRef = 4D5594A8153DCA19009F2584 /* fstyp_ntfs.8 */; };
+ 785314FF227120BD00B25661 /* MediaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 785314FE227120BD00B25661 /* MediaKit.framework */; };
+ B19B239C21C8DF660001F35C /* edt_fstab.c in Sources */ = {isa = PBXBuildFile; fileRef = B19B239A21C8DEF90001F35C /* edt_fstab.c */; };
+ B19B239D21C8DF6E0001F35C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041012091EE830061D05A /* IOKit.framework */; };
+ B19B239E21C8DF740001F35C /* APFS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041032091EE910061D05A /* APFS.framework */; };
+ B19B239F21C8DF7B0001F35C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041052091EE980061D05A /* CoreFoundation.framework */; };
+ B19B23A021C8DFA40001F35C /* edt_fstab.c in Sources */ = {isa = PBXBuildFile; fileRef = B19B239A21C8DEF90001F35C /* edt_fstab.c */; };
+ B19B23A221C8DFC30001F35C /* edt_fstab.c in Sources */ = {isa = PBXBuildFile; fileRef = B19B239A21C8DEF90001F35C /* edt_fstab.c */; };
+ B19B23A321C8DFCF0001F35C /* APFS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041032091EE910061D05A /* APFS.framework */; };
+ B19B23A421C8DFD50001F35C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041012091EE830061D05A /* IOKit.framework */; };
+ B19B23A521C8DFE10001F35C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A9041052091EE980061D05A /* CoreFoundation.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 071077D82488A09C003B97C7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5594C1153DCAFC009F2584;
+ remoteInfo = setclass;
+ };
+ 07747AA11DA8511D00ACE020 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D559476153DC8FC009F2584;
+ remoteInfo = fstyp;
+ };
+ 4D559356153CE4EA009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D07DD48153CA9A0002B57CB;
+ remoteInfo = libdisk;
+ };
+ 4D559358153CE4EC009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D559314153CE198009F2584;
+ remoteInfo = fdisk;
+ };
+ 4D55935A153CE4ED009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D559340153CE41E009F2584;
+ remoteInfo = fsck;
+ };
+ 4D559372153CE5F8009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55935F153CE561009F2584;
+ remoteInfo = mount;
+ };
+ 4D55939B153CE83A009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55938D153CE7FD009F2584;
+ remoteInfo = umount;
+ };
+ 4D55939E153CE8B6009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D07DD48153CA9A0002B57CB;
+ remoteInfo = libdisk;
+ };
+ 4D5593A0153CE8BC009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D07DD48153CA9A0002B57CB;
+ remoteInfo = libdisk;
+ };
+ 4D559414153DC282009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55940A153DC27A009F2584;
+ remoteInfo = vndevice;
+ };
+ 4D559425153DC38F009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55941B153DC383009F2584;
+ remoteInfo = mount_devfs;
+ };
+ 4D559439153DC4C0009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55942F153DC49A009F2584;
+ remoteInfo = mount_fdesc;
+ };
+ 4D559446153DC597009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55934F153CE4CC009F2584;
+ remoteInfo = Common;
+ };
+ 4D559448153DC599009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55934F153CE4CC009F2584;
+ remoteInfo = Common;
+ };
+ 4D55945B153DC665009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55944D153DC634009F2584;
+ remoteInfo = vsdbutil;
+ };
+ 4D559471153DC87B009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D559463153DC808009F2584;
+ remoteInfo = dev_mkdb;
+ };
+ 4D559497153DC9E8009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D559489153DC98D009F2584;
+ remoteInfo = fstyp_msdos;
+ };
+ 4D5594A6153DCA04009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D55949C153DC9FB009F2584;
+ remoteInfo = fstyp_ntfs;
+ };
+ 4D5594B8153DCA5E009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5594AE153DCA53009F2584;
+ remoteInfo = fstyp_udf;
+ };
+ 4D5594DE153DCC73009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5594D4153DCC66009F2584;
+ remoteInfo = fuser;
+ };
+ 4D559519153DE1CB009F2584 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5593E3153CEE4A009F2584;
+ remoteInfo = quotaon;
+ };
+ B12C9C9122A7CDE300B9F497 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5593A5153CEA90009F2584;
+ remoteInfo = edquota;
+ };
+ B12C9C9322A7CDE300B9F497 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5593B8153CEB7E009F2584;
+ remoteInfo = quota;
+ };
+ B12C9C9522A7CDE300B9F497 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5593CC153CED29009F2584;
+ remoteInfo = quotacheck;
+ };
+ B12C9C9722A7CDE300B9F497 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5593E3153CEE4A009F2584;
+ remoteInfo = quotaon;
+ };
+ B12C9C9922A7CDE300B9F497 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D559514153DE116009F2584;
+ remoteInfo = quotaoff;
+ };
+ B12C9C9B22A7CDE300B9F497 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4D07DD2B153CA616002B57CB /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 4D5593F7153DC0DE009F2584;
+ remoteInfo = repquota;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 4D559313153CE198009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D55933C153CE242009F2584 /* fdisk.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55933F153CE41E009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D55934E153CE4B1009F2584 /* fsck.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55935E153CE561009F2584 /* Copy man5 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man5/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D55936F153CE5D6009F2584 /* fstab.5 in Copy man5 */,
+ );
+ name = "Copy man5";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D559370153CE5DC009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D559371153CE5EA009F2584 /* mount.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55938C153CE7FD009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D55939A153CE82E009F2584 /* umount.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5593A4153CEA90009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5593C5153CEBB4009F2584 /* edquota.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5593B7153CEB7E009F2584 /* Copy man1 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5593C6153CEBC3009F2584 /* quota.1 in Copy man1 */,
+ );
+ name = "Copy man1";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5593CB153CED29009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5593DE153CED6A009F2584 /* quotacheck.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5593E2153CEE4A009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5593F0153CEE74009F2584 /* quotaon.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5593F6153DC0DE009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D559404153DC150009F2584 /* repquota.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D559409153DC27A009F2584 /* Copy man1 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ name = "Copy man1";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55941A153DC383009F2584 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55942E153DC49A009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D55943E153DC4E9009F2584 /* mount_fdesc.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55944C153DC634009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D55945D153DC728009F2584 /* vsdbutil.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55945E153DC730009F2584 /* Copy com.apple.vsdbutil.plist */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /System/Library/LaunchDaemons;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D55945F153DC735009F2584 /* com.apple.vsdbutil.plist in Copy com.apple.vsdbutil.plist */,
+ );
+ name = "Copy com.apple.vsdbutil.plist";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D559462153DC808009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D559470153DC84E009F2584 /* dev_mkdb.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D559475153DC8FC009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D559483153DC92D009F2584 /* fstyp.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D559488153DC98D009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D559496153DC9BC009F2584 /* fstyp_msdos.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D55949B153DC9FB009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5594E6153DCFFB009F2584 /* fstyp_ntfs.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5594AD153DCA53009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5594BD153DCA85009F2584 /* fstyp_udf.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5594C0153DCAFC009F2584 /* Copy man8 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/local/share/man/man8/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5594CE153DCB82009F2584 /* setclass.8 in Copy man8 */,
+ );
+ name = "Copy man8";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 4D5594D3153DCC66009F2584 /* Copy man1 */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 4D5594E2153DCCAC009F2584 /* fuser.1 in Copy man1 */,
+ );
+ name = "Copy man1";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 072AAAA42167CE8E004ED4E2 /* mount_flags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mount_flags.c; sourceTree = "<group>"; };
+ 072AAAA52167CE8E004ED4E2 /* mount_flags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mount_flags.h; sourceTree = "<group>"; };
+ 07AF95B12323281D001E9266 /* System.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = System.framework; path = System/Library/Frameworks/System.framework; sourceTree = SDKROOT; };
+ 07AF95B323232837001E9266 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; };
+ 1A9041012091EE830061D05A /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
+ 1A9041032091EE910061D05A /* APFS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = APFS.framework; path = System/Library/PrivateFrameworks/APFS.framework; sourceTree = SDKROOT; };
+ 1A9041052091EE980061D05A /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
+ 4D07DD49153CA9A0002B57CB /* libdisk.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdisk.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D07DD4D153CA9DC002B57CB /* dkcksum.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dkcksum.c; path = disklib/dkcksum.c; sourceTree = "<group>"; };
+ 4D07DD4E153CA9DC002B57CB /* dkdisklabel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dkdisklabel.c; path = disklib/dkdisklabel.c; sourceTree = "<group>"; };
+ 4D07DD4F153CA9DC002B57CB /* dkopen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dkopen.c; path = disklib/dkopen.c; sourceTree = "<group>"; };
+ 4D07DD50153CA9DC002B57CB /* dkopen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dkopen.h; path = disklib/dkopen.h; sourceTree = "<group>"; };
+ 4D07DD51153CA9DC002B57CB /* dksecsize.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dksecsize.c; path = disklib/dksecsize.c; sourceTree = "<group>"; };
+ 4D07DD54153CA9DC002B57CB /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathnames.h; path = disklib/pathnames.h; sourceTree = "<group>"; };
+ 4D07DD55153CA9DC002B57CB /* preen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = preen.c; path = disklib/preen.c; sourceTree = "<group>"; };
+ 4D07DD56153CA9DC002B57CB /* vfslist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vfslist.c; path = disklib/vfslist.c; sourceTree = "<group>"; };
+ 4D559315153CE198009F2584 /* fdisk */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fdisk; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D55931E153CE1D9009F2584 /* auto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = auto.c; path = fdisk.tproj/auto.c; sourceTree = SOURCE_ROOT; };
+ 4D55931F153CE1D9009F2584 /* auto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = auto.h; path = fdisk.tproj/auto.h; sourceTree = SOURCE_ROOT; };
+ 4D559320153CE1D9009F2584 /* cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cmd.c; path = fdisk.tproj/cmd.c; sourceTree = SOURCE_ROOT; };
+ 4D559321153CE1D9009F2584 /* cmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cmd.h; path = fdisk.tproj/cmd.h; sourceTree = SOURCE_ROOT; };
+ 4D559322153CE1D9009F2584 /* disk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = disk.c; path = fdisk.tproj/disk.c; sourceTree = SOURCE_ROOT; };
+ 4D559323153CE1D9009F2584 /* disk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = disk.h; path = fdisk.tproj/disk.h; sourceTree = SOURCE_ROOT; };
+ 4D559324153CE1D9009F2584 /* fdisk.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fdisk.8; path = fdisk.tproj/fdisk.8; sourceTree = SOURCE_ROOT; };
+ 4D559325153CE1D9009F2584 /* fdisk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fdisk.c; path = fdisk.tproj/fdisk.c; sourceTree = SOURCE_ROOT; };
+ 4D559326153CE1D9009F2584 /* getrawpartition.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = getrawpartition.c; path = fdisk.tproj/getrawpartition.c; sourceTree = SOURCE_ROOT; };
+ 4D559327153CE1D9009F2584 /* mbr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mbr.c; path = fdisk.tproj/mbr.c; sourceTree = SOURCE_ROOT; };
+ 4D559328153CE1D9009F2584 /* mbr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mbr.h; path = fdisk.tproj/mbr.h; sourceTree = SOURCE_ROOT; };
+ 4D559329153CE1D9009F2584 /* mbrcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mbrcode.h; path = fdisk.tproj/mbrcode.h; sourceTree = SOURCE_ROOT; };
+ 4D55932A153CE1D9009F2584 /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = misc.c; path = fdisk.tproj/misc.c; sourceTree = SOURCE_ROOT; };
+ 4D55932B153CE1D9009F2584 /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = misc.h; path = fdisk.tproj/misc.h; sourceTree = SOURCE_ROOT; };
+ 4D55932C153CE1D9009F2584 /* opendev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = opendev.c; path = fdisk.tproj/opendev.c; sourceTree = SOURCE_ROOT; };
+ 4D55932D153CE1D9009F2584 /* part.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = part.c; path = fdisk.tproj/part.c; sourceTree = SOURCE_ROOT; };
+ 4D55932E153CE1D9009F2584 /* part.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = part.h; path = fdisk.tproj/part.h; sourceTree = SOURCE_ROOT; };
+ 4D55932F153CE1D9009F2584 /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = user.c; path = fdisk.tproj/user.c; sourceTree = SOURCE_ROOT; };
+ 4D559330153CE1D9009F2584 /* user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = user.h; path = fdisk.tproj/user.h; sourceTree = SOURCE_ROOT; };
+ 4D559331153CE1D9009F2584 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = fdisk.tproj/util.h; sourceTree = SOURCE_ROOT; };
+ 4D559341153CE41E009F2584 /* fsck */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fsck; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D55934A153CE44E009F2584 /* fsck.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fsck.8; path = fsck.tproj/fsck.8; sourceTree = SOURCE_ROOT; };
+ 4D55934B153CE44E009F2584 /* fsck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fsck.c; path = fsck.tproj/fsck.c; sourceTree = SOURCE_ROOT; };
+ 4D55934C153CE44E009F2584 /* fsck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fsck.h; path = fsck.tproj/fsck.h; sourceTree = SOURCE_ROOT; };
+ 4D559360153CE561009F2584 /* mount */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mount; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559369153CE58E009F2584 /* fstab.5 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstab.5; path = mount.tproj/fstab.5; sourceTree = SOURCE_ROOT; };
+ 4D55936B153CE58E009F2584 /* mount.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mount.8; path = mount.tproj/mount.8; sourceTree = SOURCE_ROOT; };
+ 4D55936C153CE58E009F2584 /* mount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mount.c; path = mount.tproj/mount.c; sourceTree = SOURCE_ROOT; };
+ 4D55936D153CE58E009F2584 /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathnames.h; path = mount.tproj/pathnames.h; sourceTree = SOURCE_ROOT; };
+ 4D55938E153CE7FD009F2584 /* umount */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = umount; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559397153CE826009F2584 /* umount.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = umount.8; path = umount.tproj/umount.8; sourceTree = SOURCE_ROOT; };
+ 4D559398153CE826009F2584 /* umount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = umount.c; path = umount.tproj/umount.c; sourceTree = SOURCE_ROOT; };
+ 4D5593A6153CEA90009F2584 /* edquota */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = edquota; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5593AF153CEABD009F2584 /* edquota.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = edquota.8; path = edquota.tproj/edquota.8; sourceTree = SOURCE_ROOT; };
+ 4D5593B0153CEABD009F2584 /* edquota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = edquota.c; path = edquota.tproj/edquota.c; sourceTree = SOURCE_ROOT; };
+ 4D5593B1153CEABD009F2584 /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathnames.h; path = edquota.tproj/pathnames.h; sourceTree = SOURCE_ROOT; };
+ 4D5593B9153CEB7E009F2584 /* quota */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = quota; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5593C2153CEB9A009F2584 /* quota.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = quota.1; path = quota.tproj/quota.1; sourceTree = SOURCE_ROOT; };
+ 4D5593C3153CEB9A009F2584 /* quota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quota.c; path = quota.tproj/quota.c; sourceTree = SOURCE_ROOT; };
+ 4D5593CD153CED29009F2584 /* quotacheck */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = quotacheck; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5593D8153CED51009F2584 /* hfs_quotacheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hfs_quotacheck.c; path = quotacheck.tproj/hfs_quotacheck.c; sourceTree = SOURCE_ROOT; };
+ 4D5593D9153CED51009F2584 /* quotacheck.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = quotacheck.8; path = quotacheck.tproj/quotacheck.8; sourceTree = SOURCE_ROOT; };
+ 4D5593DA153CED51009F2584 /* quotacheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quotacheck.c; path = quotacheck.tproj/quotacheck.c; sourceTree = SOURCE_ROOT; };
+ 4D5593DB153CED51009F2584 /* quotacheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = quotacheck.h; path = quotacheck.tproj/quotacheck.h; sourceTree = SOURCE_ROOT; };
+ 4D5593E4153CEE4A009F2584 /* quotaon */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = quotaon; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5593ED153CEE66009F2584 /* quotaon.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = quotaon.8; path = quotaon.tproj/quotaon.8; sourceTree = SOURCE_ROOT; };
+ 4D5593EE153CEE66009F2584 /* quotaon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = quotaon.c; path = quotaon.tproj/quotaon.c; sourceTree = SOURCE_ROOT; };
+ 4D5593F8153DC0DE009F2584 /* repquota */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = repquota; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559401153DC13D009F2584 /* repquota.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = repquota.8; path = repquota.tproj/repquota.8; sourceTree = SOURCE_ROOT; };
+ 4D559402153DC13D009F2584 /* repquota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = repquota.c; path = repquota.tproj/repquota.c; sourceTree = SOURCE_ROOT; };
+ 4D55940B153DC27A009F2584 /* vndevice */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vndevice; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559416153DC2AB009F2584 /* vndevice.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vndevice.c; path = vndevice.tproj/vndevice.c; sourceTree = SOURCE_ROOT; };
+ 4D55941C153DC383009F2584 /* mount_devfs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mount_devfs; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559427153DC3A6009F2584 /* mount_devfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mount_devfs.c; path = mount_devfs.tproj/mount_devfs.c; sourceTree = SOURCE_ROOT; };
+ 4D55942A153DC420009F2584 /* libutil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libutil.dylib; path = usr/lib/libutil.dylib; sourceTree = SDKROOT; };
+ 4D559430153DC49A009F2584 /* mount_fdesc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mount_fdesc; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D55943B153DC4DE009F2584 /* mount_fdesc.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mount_fdesc.8; path = mount_fdesc.tproj/mount_fdesc.8; sourceTree = SOURCE_ROOT; };
+ 4D55943C153DC4DE009F2584 /* mount_fdesc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mount_fdesc.c; path = mount_fdesc.tproj/mount_fdesc.c; sourceTree = SOURCE_ROOT; };
+ 4D55944E153DC634009F2584 /* vsdbutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = vsdbutil; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559457153DC650009F2584 /* com.apple.vsdbutil.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.vsdbutil.plist; path = vsdbutil.tproj/com.apple.vsdbutil.plist; sourceTree = SOURCE_ROOT; };
+ 4D559458153DC650009F2584 /* vsdbutil_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vsdbutil_main.c; path = vsdbutil.tproj/vsdbutil_main.c; sourceTree = SOURCE_ROOT; };
+ 4D559459153DC650009F2584 /* vsdbutil.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = vsdbutil.8; path = vsdbutil.tproj/vsdbutil.8; sourceTree = SOURCE_ROOT; };
+ 4D559464153DC808009F2584 /* dev_mkdb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dev_mkdb; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D55946D153DC839009F2584 /* dev_mkdb.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dev_mkdb.8; path = dev_mkdb.tproj/dev_mkdb.8; sourceTree = SOURCE_ROOT; };
+ 4D55946E153DC839009F2584 /* dev_mkdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dev_mkdb.c; path = dev_mkdb.tproj/dev_mkdb.c; sourceTree = SOURCE_ROOT; };
+ 4D559477153DC8FC009F2584 /* fstyp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559480153DC912009F2584 /* fstyp.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp.8; path = fstyp.tproj/fstyp.8; sourceTree = SOURCE_ROOT; };
+ 4D559481153DC912009F2584 /* fstyp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp.c; path = fstyp.tproj/fstyp.c; sourceTree = SOURCE_ROOT; };
+ 4D55948A153DC98D009F2584 /* fstyp_msdos */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp_msdos; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D559493153DC9AE009F2584 /* fstyp_msdos.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp_msdos.8; path = fstyp.tproj/fstyp_msdos.8; sourceTree = SOURCE_ROOT; };
+ 4D559494153DC9AE009F2584 /* fstyp_msdos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp_msdos.c; path = fstyp.tproj/fstyp_msdos.c; sourceTree = SOURCE_ROOT; };
+ 4D55949D153DC9FB009F2584 /* fstyp_ntfs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp_ntfs; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5594A8153DCA19009F2584 /* fstyp_ntfs.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp_ntfs.8; path = fstyp.tproj/fstyp_ntfs.8; sourceTree = SOURCE_ROOT; };
+ 4D5594A9153DCA19009F2584 /* fstyp_ntfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp_ntfs.c; path = fstyp.tproj/fstyp_ntfs.c; sourceTree = SOURCE_ROOT; };
+ 4D5594AF153DCA53009F2584 /* fstyp_udf */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fstyp_udf; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5594BA153DCA74009F2584 /* fstyp_udf.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = fstyp_udf.8; path = fstyp.tproj/fstyp_udf.8; sourceTree = SOURCE_ROOT; };
+ 4D5594BB153DCA74009F2584 /* fstyp_udf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fstyp_udf.c; path = fstyp.tproj/fstyp_udf.c; sourceTree = SOURCE_ROOT; };
+ 4D5594C2153DCAFC009F2584 /* setclass */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = setclass; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5594CB153DCB72009F2584 /* setclass.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = setclass.8; path = setclass.tproj/setclass.8; sourceTree = SOURCE_ROOT; };
+ 4D5594CC153DCB72009F2584 /* setclass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = setclass.c; path = setclass.tproj/setclass.c; sourceTree = SOURCE_ROOT; };
+ 4D5594D5153DCC66009F2584 /* fuser */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fuser; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4D5594E0153DCC92009F2584 /* fuser.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = fuser.1; path = fuser.tproj/fuser.1; sourceTree = SOURCE_ROOT; };
+ 4D5594E1153DCC92009F2584 /* fuser.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = fuser.pl; path = fuser.tproj/fuser.pl; sourceTree = SOURCE_ROOT; };
+ 785314FE227120BD00B25661 /* MediaKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaKit.framework; path = System/Library/PrivateFrameworks/MediaKit.framework; sourceTree = SDKROOT; };
+ 785315012277BEA700B25661 /* mount.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = mount.entitlements; path = mount.tproj/mount.entitlements; sourceTree = SOURCE_ROOT; };
+ B19B239A21C8DEF90001F35C /* edt_fstab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = edt_fstab.c; sourceTree = "<group>"; };
+ B19B239B21C8DEFA0001F35C /* edt_fstab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = edt_fstab.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 4D07DD46153CA9A0002B57CB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559312153CE198009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55933E153CE41E009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B19B239F21C8DF7B0001F35C /* CoreFoundation.framework in Frameworks */,
+ B19B239E21C8DF740001F35C /* APFS.framework in Frameworks */,
+ B19B239D21C8DF6E0001F35C /* IOKit.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55935D153CE561009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 785314FF227120BD00B25661 /* MediaKit.framework in Frameworks */,
+ 1A9041062091EE980061D05A /* CoreFoundation.framework in Frameworks */,
+ 1A9041042091EE910061D05A /* APFS.framework in Frameworks */,
+ 1A9041022091EE830061D05A /* IOKit.framework in Frameworks */,
+ 4D559389153CE794009F2584 /* libdisk.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55938B153CE7FD009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B19B23A521C8DFE10001F35C /* CoreFoundation.framework in Frameworks */,
+ B19B23A421C8DFD50001F35C /* IOKit.framework in Frameworks */,
+ B19B23A321C8DFCF0001F35C /* APFS.framework in Frameworks */,
+ 4D55939D153CE8AF009F2584 /* libdisk.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593A3153CEA90009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593B6153CEB7E009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593CA153CED29009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5593DF153CED8D009F2584 /* libdisk.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593E1153CEE4A009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593F5153DC0DE009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559408153DC27A009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559419153DC383009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D55942B153DC427009F2584 /* libutil.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55942D153DC49A009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D55943F153DC534009F2584 /* libutil.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55944B153DC634009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559461153DC808009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559474153DC8FC009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559487153DC98D009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55949A153DC9FB009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5594AC153DCA53009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5594BF153DCAFC009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5594D2153DCC66009F2584 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 072AAAA32167CD68004ED4E2 /* mount_flags_dir */ = {
+ isa = PBXGroup;
+ children = (
+ 072AAAA42167CE8E004ED4E2 /* mount_flags.c */,
+ 072AAAA52167CE8E004ED4E2 /* mount_flags.h */,
+ );
+ path = mount_flags_dir;
+ sourceTree = "<group>";
+ };
+ 1A9041002091EE820061D05A /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 07AF95B323232837001E9266 /* Kernel.framework */,
+ 07AF95B12323281D001E9266 /* System.framework */,
+ 785314FE227120BD00B25661 /* MediaKit.framework */,
+ 1A9041052091EE980061D05A /* CoreFoundation.framework */,
+ 1A9041032091EE910061D05A /* APFS.framework */,
+ 1A9041012091EE830061D05A /* IOKit.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 4D07DD29153CA616002B57CB = {
+ isa = PBXGroup;
+ children = (
+ B1DF3D3D21C27FE00099F594 /* edt_fstab */,
+ 072AAAA32167CD68004ED4E2 /* mount_flags_dir */,
+ 4D559466153DC808009F2584 /* dev_mkdb */,
+ 4D07DD4C153CA9C4002B57CB /* disklib */,
+ 4D5593A8153CEA90009F2584 /* edquota */,
+ 4D559317153CE199009F2584 /* fdisk */,
+ 4D559343153CE41E009F2584 /* fsck */,
+ 4D559479153DC8FC009F2584 /* fstyp */,
+ 4D55948C153DC98D009F2584 /* fstyp_msdos */,
+ 4D55949F153DC9FB009F2584 /* fstyp_ntfs */,
+ 4D5594B1153DCA53009F2584 /* fstyp_udf */,
+ 4D5594D7153DCC66009F2584 /* fuser */,
+ 4D559362153CE561009F2584 /* mount */,
+ 4D55941E153DC384009F2584 /* mount_devfs */,
+ 4D559432153DC49A009F2584 /* mount_fdesc */,
+ 4D5593BB153CEB7E009F2584 /* quota */,
+ 4D5593CF153CED29009F2584 /* quotacheck */,
+ 4D5593E6153CEE4A009F2584 /* quotaon */,
+ 4D5593FA153DC0DE009F2584 /* repquota */,
+ 4D5594C4153DCAFC009F2584 /* setclass */,
+ 4D559390153CE7FD009F2584 /* umount */,
+ 4D55940D153DC27A009F2584 /* vndevice */,
+ 4D559450153DC634009F2584 /* vsdbutil */,
+ 4D559429153DC3F3009F2584 /* Libraries */,
+ 4D07DD35153CA616002B57CB /* Products */,
+ 1A9041002091EE820061D05A /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ 4D07DD35153CA616002B57CB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 4D07DD49153CA9A0002B57CB /* libdisk.a */,
+ 4D559315153CE198009F2584 /* fdisk */,
+ 4D559341153CE41E009F2584 /* fsck */,
+ 4D559360153CE561009F2584 /* mount */,
+ 4D55938E153CE7FD009F2584 /* umount */,
+ 4D5593A6153CEA90009F2584 /* edquota */,
+ 4D5593B9153CEB7E009F2584 /* quota */,
+ 4D5593CD153CED29009F2584 /* quotacheck */,
+ 4D5593E4153CEE4A009F2584 /* quotaon */,
+ 4D5593F8153DC0DE009F2584 /* repquota */,
+ 4D55940B153DC27A009F2584 /* vndevice */,
+ 4D55941C153DC383009F2584 /* mount_devfs */,
+ 4D559430153DC49A009F2584 /* mount_fdesc */,
+ 4D55944E153DC634009F2584 /* vsdbutil */,
+ 4D559464153DC808009F2584 /* dev_mkdb */,
+ 4D559477153DC8FC009F2584 /* fstyp */,
+ 4D55948A153DC98D009F2584 /* fstyp_msdos */,
+ 4D55949D153DC9FB009F2584 /* fstyp_ntfs */,
+ 4D5594AF153DCA53009F2584 /* fstyp_udf */,
+ 4D5594C2153DCAFC009F2584 /* setclass */,
+ 4D5594D5153DCC66009F2584 /* fuser */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4D07DD4C153CA9C4002B57CB /* disklib */ = {
+ isa = PBXGroup;
+ children = (
+ 4D07DD50153CA9DC002B57CB /* dkopen.h */,
+ 4D07DD54153CA9DC002B57CB /* pathnames.h */,
+ 4D07DD4D153CA9DC002B57CB /* dkcksum.c */,
+ 4D07DD4E153CA9DC002B57CB /* dkdisklabel.c */,
+ 4D07DD4F153CA9DC002B57CB /* dkopen.c */,
+ 4D07DD51153CA9DC002B57CB /* dksecsize.c */,
+ 4D07DD55153CA9DC002B57CB /* preen.c */,
+ 4D07DD56153CA9DC002B57CB /* vfslist.c */,
+ );
+ name = disklib;
+ sourceTree = "<group>";
+ };
+ 4D559317153CE199009F2584 /* fdisk */ = {
+ isa = PBXGroup;
+ children = (
+ 4D55931F153CE1D9009F2584 /* auto.h */,
+ 4D559321153CE1D9009F2584 /* cmd.h */,
+ 4D559323153CE1D9009F2584 /* disk.h */,
+ 4D559328153CE1D9009F2584 /* mbr.h */,
+ 4D559329153CE1D9009F2584 /* mbrcode.h */,
+ 4D55932B153CE1D9009F2584 /* misc.h */,
+ 4D55932E153CE1D9009F2584 /* part.h */,
+ 4D559330153CE1D9009F2584 /* user.h */,
+ 4D559331153CE1D9009F2584 /* util.h */,
+ 4D55931E153CE1D9009F2584 /* auto.c */,
+ 4D559320153CE1D9009F2584 /* cmd.c */,
+ 4D559322153CE1D9009F2584 /* disk.c */,
+ 4D559325153CE1D9009F2584 /* fdisk.c */,
+ 4D559326153CE1D9009F2584 /* getrawpartition.c */,
+ 4D559327153CE1D9009F2584 /* mbr.c */,
+ 4D55932A153CE1D9009F2584 /* misc.c */,
+ 4D55932C153CE1D9009F2584 /* opendev.c */,
+ 4D55932D153CE1D9009F2584 /* part.c */,
+ 4D55932F153CE1D9009F2584 /* user.c */,
+ 4D559324153CE1D9009F2584 /* fdisk.8 */,
+ );
+ path = fdisk;
+ sourceTree = "<group>";
+ };
+ 4D559343153CE41E009F2584 /* fsck */ = {
+ isa = PBXGroup;
+ children = (
+ 4D55934C153CE44E009F2584 /* fsck.h */,
+ 4D55934B153CE44E009F2584 /* fsck.c */,
+ 4D55934A153CE44E009F2584 /* fsck.8 */,
+ );
+ path = fsck;
+ sourceTree = "<group>";
+ };
+ 4D559362153CE561009F2584 /* mount */ = {
+ isa = PBXGroup;
+ children = (
+ 4D55936D153CE58E009F2584 /* pathnames.h */,
+ 4D55936C153CE58E009F2584 /* mount.c */,
+ 4D55936B153CE58E009F2584 /* mount.8 */,
+ 4D559369153CE58E009F2584 /* fstab.5 */,
+ 785315012277BEA700B25661 /* mount.entitlements */,
+ );
+ path = mount;
+ sourceTree = "<group>";
+ };
+ 4D559390153CE7FD009F2584 /* umount */ = {
+ isa = PBXGroup;
+ children = (
+ 4D559398153CE826009F2584 /* umount.c */,
+ 4D559397153CE826009F2584 /* umount.8 */,
+ );
+ path = umount;
+ sourceTree = "<group>";
+ };
+ 4D5593A8153CEA90009F2584 /* edquota */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5593B1153CEABD009F2584 /* pathnames.h */,
+ 4D5593B0153CEABD009F2584 /* edquota.c */,
+ 4D5593AF153CEABD009F2584 /* edquota.8 */,
+ );
+ path = edquota;
+ sourceTree = "<group>";
+ };
+ 4D5593BB153CEB7E009F2584 /* quota */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5593C2153CEB9A009F2584 /* quota.1 */,
+ 4D5593C3153CEB9A009F2584 /* quota.c */,
+ );
+ path = quota;
+ sourceTree = "<group>";
+ };
+ 4D5593CF153CED29009F2584 /* quotacheck */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5593DB153CED51009F2584 /* quotacheck.h */,
+ 4D5593D8153CED51009F2584 /* hfs_quotacheck.c */,
+ 4D5593DA153CED51009F2584 /* quotacheck.c */,
+ 4D5593D9153CED51009F2584 /* quotacheck.8 */,
+ );
+ path = quotacheck;
+ sourceTree = "<group>";
+ };
+ 4D5593E6153CEE4A009F2584 /* quotaon */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5593EE153CEE66009F2584 /* quotaon.c */,
+ 4D5593ED153CEE66009F2584 /* quotaon.8 */,
+ );
+ path = quotaon;
+ sourceTree = "<group>";
+ };
+ 4D5593FA153DC0DE009F2584 /* repquota */ = {
+ isa = PBXGroup;
+ children = (
+ 4D559402153DC13D009F2584 /* repquota.c */,
+ 4D559401153DC13D009F2584 /* repquota.8 */,
+ );
+ path = repquota;
+ sourceTree = "<group>";
+ };
+ 4D55940D153DC27A009F2584 /* vndevice */ = {
+ isa = PBXGroup;
+ children = (
+ 4D559416153DC2AB009F2584 /* vndevice.c */,
+ );
+ path = vndevice;
+ sourceTree = "<group>";
+ };
+ 4D55941E153DC384009F2584 /* mount_devfs */ = {
+ isa = PBXGroup;
+ children = (
+ 4D559427153DC3A6009F2584 /* mount_devfs.c */,
+ );
+ path = mount_devfs;
+ sourceTree = "<group>";
+ };
+ 4D559429153DC3F3009F2584 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 4D55942A153DC420009F2584 /* libutil.dylib */,
+ );
+ name = Libraries;
+ sourceTree = "<group>";
+ };
+ 4D559432153DC49A009F2584 /* mount_fdesc */ = {
+ isa = PBXGroup;
+ children = (
+ 4D55943B153DC4DE009F2584 /* mount_fdesc.8 */,
+ 4D55943C153DC4DE009F2584 /* mount_fdesc.c */,
+ );
+ path = mount_fdesc;
+ sourceTree = "<group>";
+ };
+ 4D559450153DC634009F2584 /* vsdbutil */ = {
+ isa = PBXGroup;
+ children = (
+ 4D559458153DC650009F2584 /* vsdbutil_main.c */,
+ 4D559457153DC650009F2584 /* com.apple.vsdbutil.plist */,
+ 4D559459153DC650009F2584 /* vsdbutil.8 */,
+ );
+ path = vsdbutil;
+ sourceTree = "<group>";
+ };
+ 4D559466153DC808009F2584 /* dev_mkdb */ = {
+ isa = PBXGroup;
+ children = (
+ 4D55946D153DC839009F2584 /* dev_mkdb.8 */,
+ 4D55946E153DC839009F2584 /* dev_mkdb.c */,
+ );
+ path = dev_mkdb;
+ sourceTree = "<group>";
+ };
+ 4D559479153DC8FC009F2584 /* fstyp */ = {
+ isa = PBXGroup;
+ children = (
+ 4D559480153DC912009F2584 /* fstyp.8 */,
+ 4D559481153DC912009F2584 /* fstyp.c */,
+ );
+ path = fstyp;
+ sourceTree = "<group>";
+ };
+ 4D55948C153DC98D009F2584 /* fstyp_msdos */ = {
+ isa = PBXGroup;
+ children = (
+ 4D559493153DC9AE009F2584 /* fstyp_msdos.8 */,
+ 4D559494153DC9AE009F2584 /* fstyp_msdos.c */,
+ );
+ path = fstyp_msdos;
+ sourceTree = "<group>";
+ };
+ 4D55949F153DC9FB009F2584 /* fstyp_ntfs */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5594A8153DCA19009F2584 /* fstyp_ntfs.8 */,
+ 4D5594A9153DCA19009F2584 /* fstyp_ntfs.c */,
+ );
+ path = fstyp_ntfs;
+ sourceTree = "<group>";
+ };
+ 4D5594B1153DCA53009F2584 /* fstyp_udf */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5594BA153DCA74009F2584 /* fstyp_udf.8 */,
+ 4D5594BB153DCA74009F2584 /* fstyp_udf.c */,
+ );
+ path = fstyp_udf;
+ sourceTree = "<group>";
+ };
+ 4D5594C4153DCAFC009F2584 /* setclass */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5594CB153DCB72009F2584 /* setclass.8 */,
+ 4D5594CC153DCB72009F2584 /* setclass.c */,
+ );
+ path = setclass;
+ sourceTree = "<group>";
+ };
+ 4D5594D7153DCC66009F2584 /* fuser */ = {
+ isa = PBXGroup;
+ children = (
+ 4D5594E0153DCC92009F2584 /* fuser.1 */,
+ 4D5594E1153DCC92009F2584 /* fuser.pl */,
+ );
+ path = fuser;
+ sourceTree = "<group>";
+ };
+ B1DF3D3D21C27FE00099F594 /* edt_fstab */ = {
+ isa = PBXGroup;
+ children = (
+ B19B239A21C8DEF90001F35C /* edt_fstab.c */,
+ B19B239B21C8DEFA0001F35C /* edt_fstab.h */,
+ );
+ path = edt_fstab;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 4D07DD47153CA9A0002B57CB /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D07DD5A153CA9DC002B57CB /* dkopen.h in Headers */,
+ 4D07DD5E153CA9DC002B57CB /* pathnames.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 4D07DD48153CA9A0002B57CB /* libdisk */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D07DD4A153CA9A0002B57CB /* Build configuration list for PBXNativeTarget "libdisk" */;
+ buildPhases = (
+ 4D07DD45153CA9A0002B57CB /* Sources */,
+ 4D07DD46153CA9A0002B57CB /* Frameworks */,
+ 4D07DD47153CA9A0002B57CB /* Headers */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libdisk;
+ productName = disklib;
+ productReference = 4D07DD49153CA9A0002B57CB /* libdisk.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 4D559314153CE198009F2584 /* fdisk */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D55931C153CE199009F2584 /* Build configuration list for PBXNativeTarget "fdisk" */;
+ buildPhases = (
+ 4D559311153CE198009F2584 /* Sources */,
+ 4D559312153CE198009F2584 /* Frameworks */,
+ 4D559313153CE198009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = fdisk;
+ productName = fdisk;
+ productReference = 4D559315153CE198009F2584 /* fdisk */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D559340153CE41E009F2584 /* fsck */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559348153CE41E009F2584 /* Build configuration list for PBXNativeTarget "fsck" */;
+ buildPhases = (
+ 4D55933D153CE41E009F2584 /* Sources */,
+ 4D55933E153CE41E009F2584 /* Frameworks */,
+ 4D55933F153CE41E009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = fsck;
+ productName = fsck;
+ productReference = 4D559341153CE41E009F2584 /* fsck */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D55935F153CE561009F2584 /* mount */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559367153CE561009F2584 /* Build configuration list for PBXNativeTarget "mount" */;
+ buildPhases = (
+ 4D55935C153CE561009F2584 /* Sources */,
+ 4D55935D153CE561009F2584 /* Frameworks */,
+ 4D55935E153CE561009F2584 /* Copy man5 */,
+ 4D559370153CE5DC009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 4D5593A1153CE8BC009F2584 /* PBXTargetDependency */,
+ );
+ name = mount;
+ productName = mount;
+ productReference = 4D559360153CE561009F2584 /* mount */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D55938D153CE7FD009F2584 /* umount */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559395153CE7FE009F2584 /* Build configuration list for PBXNativeTarget "umount" */;
+ buildPhases = (
+ 4D55938A153CE7FD009F2584 /* Sources */,
+ 4D55938B153CE7FD009F2584 /* Frameworks */,
+ 4D55938C153CE7FD009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 4D55939F153CE8B6009F2584 /* PBXTargetDependency */,
+ );
+ name = umount;
+ productName = umount;
+ productReference = 4D55938E153CE7FD009F2584 /* umount */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5593A5153CEA90009F2584 /* edquota */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5593AD153CEA90009F2584 /* Build configuration list for PBXNativeTarget "edquota" */;
+ buildPhases = (
+ 4D5593A2153CEA90009F2584 /* Sources */,
+ 4D5593A3153CEA90009F2584 /* Frameworks */,
+ 4D5593A4153CEA90009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = edquota;
+ productName = edquota;
+ productReference = 4D5593A6153CEA90009F2584 /* edquota */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5593B8153CEB7E009F2584 /* quota */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5593C0153CEB7E009F2584 /* Build configuration list for PBXNativeTarget "quota" */;
+ buildPhases = (
+ 4D5593B5153CEB7E009F2584 /* Sources */,
+ 4D5593B6153CEB7E009F2584 /* Frameworks */,
+ 4D5593B7153CEB7E009F2584 /* Copy man1 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = quota;
+ productName = quota;
+ productReference = 4D5593B9153CEB7E009F2584 /* quota */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5593CC153CED29009F2584 /* quotacheck */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5593D4153CED29009F2584 /* Build configuration list for PBXNativeTarget "quotacheck" */;
+ buildPhases = (
+ 4D5593C9153CED29009F2584 /* Sources */,
+ 4D5593CA153CED29009F2584 /* Frameworks */,
+ 4D5593CB153CED29009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = quotacheck;
+ productName = quotacheck;
+ productReference = 4D5593CD153CED29009F2584 /* quotacheck */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5593E3153CEE4A009F2584 /* quotaon */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5593EB153CEE4A009F2584 /* Build configuration list for PBXNativeTarget "quotaon" */;
+ buildPhases = (
+ 4D5593E0153CEE4A009F2584 /* Sources */,
+ 4D5593E1153CEE4A009F2584 /* Frameworks */,
+ 4D5593E2153CEE4A009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = quotaon;
+ productName = quotaon;
+ productReference = 4D5593E4153CEE4A009F2584 /* quotaon */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5593F7153DC0DE009F2584 /* repquota */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5593FF153DC0DE009F2584 /* Build configuration list for PBXNativeTarget "repquota" */;
+ buildPhases = (
+ 4D5593F4153DC0DE009F2584 /* Sources */,
+ 4D5593F5153DC0DE009F2584 /* Frameworks */,
+ 4D5593F6153DC0DE009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = repquota;
+ productName = repquota;
+ productReference = 4D5593F8153DC0DE009F2584 /* repquota */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D55940A153DC27A009F2584 /* vndevice */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559412153DC27A009F2584 /* Build configuration list for PBXNativeTarget "vndevice" */;
+ buildPhases = (
+ 4D559407153DC27A009F2584 /* Sources */,
+ 4D559408153DC27A009F2584 /* Frameworks */,
+ 4D559409153DC27A009F2584 /* Copy man1 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = vndevice;
+ productName = vndevice;
+ productReference = 4D55940B153DC27A009F2584 /* vndevice */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D55941B153DC383009F2584 /* mount_devfs */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559423153DC384009F2584 /* Build configuration list for PBXNativeTarget "mount_devfs" */;
+ buildPhases = (
+ 4D559418153DC383009F2584 /* Sources */,
+ 4D559419153DC383009F2584 /* Frameworks */,
+ 4D55941A153DC383009F2584 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = mount_devfs;
+ productName = mount_devfs;
+ productReference = 4D55941C153DC383009F2584 /* mount_devfs */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D55942F153DC49A009F2584 /* mount_fdesc */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559437153DC49A009F2584 /* Build configuration list for PBXNativeTarget "mount_fdesc" */;
+ buildPhases = (
+ 4D55942C153DC49A009F2584 /* Sources */,
+ 4D55942D153DC49A009F2584 /* Frameworks */,
+ 4D55942E153DC49A009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = mount_fdesc;
+ productName = mount_fdesc;
+ productReference = 4D559430153DC49A009F2584 /* mount_fdesc */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D55944D153DC634009F2584 /* vsdbutil */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559455153DC634009F2584 /* Build configuration list for PBXNativeTarget "vsdbutil" */;
+ buildPhases = (
+ 4D55944A153DC634009F2584 /* Sources */,
+ 4D55944B153DC634009F2584 /* Frameworks */,
+ 4D55944C153DC634009F2584 /* Copy man8 */,
+ 4D55945E153DC730009F2584 /* Copy com.apple.vsdbutil.plist */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = vsdbutil;
+ productName = vsdbutil;
+ productReference = 4D55944E153DC634009F2584 /* vsdbutil */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D559463153DC808009F2584 /* dev_mkdb */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D55946B153DC808009F2584 /* Build configuration list for PBXNativeTarget "dev_mkdb" */;
+ buildPhases = (
+ 4D559460153DC808009F2584 /* Sources */,
+ 4D559461153DC808009F2584 /* Frameworks */,
+ 4D559462153DC808009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = dev_mkdb;
+ productName = dev_mkdb;
+ productReference = 4D559464153DC808009F2584 /* dev_mkdb */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D559476153DC8FC009F2584 /* fstyp */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D55947E153DC8FC009F2584 /* Build configuration list for PBXNativeTarget "fstyp" */;
+ buildPhases = (
+ 4D559473153DC8FC009F2584 /* Sources */,
+ 4D559474153DC8FC009F2584 /* Frameworks */,
+ 4D559475153DC8FC009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = fstyp;
+ productName = fstyp;
+ productReference = 4D559477153DC8FC009F2584 /* fstyp */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D559489153DC98D009F2584 /* fstyp_msdos */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D559491153DC98D009F2584 /* Build configuration list for PBXNativeTarget "fstyp_msdos" */;
+ buildPhases = (
+ 4D559486153DC98D009F2584 /* Sources */,
+ 4D559487153DC98D009F2584 /* Frameworks */,
+ 4D559488153DC98D009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = fstyp_msdos;
+ productName = fstyp_msdos;
+ productReference = 4D55948A153DC98D009F2584 /* fstyp_msdos */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D55949C153DC9FB009F2584 /* fstyp_ntfs */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5594A4153DC9FB009F2584 /* Build configuration list for PBXNativeTarget "fstyp_ntfs" */;
+ buildPhases = (
+ 4D559499153DC9FB009F2584 /* Sources */,
+ 4D55949A153DC9FB009F2584 /* Frameworks */,
+ 4D55949B153DC9FB009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = fstyp_ntfs;
+ productName = fstyp_ntfs;
+ productReference = 4D55949D153DC9FB009F2584 /* fstyp_ntfs */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5594AE153DCA53009F2584 /* fstyp_udf */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5594B6153DCA53009F2584 /* Build configuration list for PBXNativeTarget "fstyp_udf" */;
+ buildPhases = (
+ 4D5594AB153DCA53009F2584 /* Sources */,
+ 4D5594AC153DCA53009F2584 /* Frameworks */,
+ 4D5594AD153DCA53009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = fstyp_udf;
+ productName = fstyp_udf;
+ productReference = 4D5594AF153DCA53009F2584 /* fstyp_udf */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5594C1153DCAFC009F2584 /* setclass */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5594C9153DCAFC009F2584 /* Build configuration list for PBXNativeTarget "setclass" */;
+ buildPhases = (
+ 4D5594BE153DCAFC009F2584 /* Sources */,
+ 4D5594BF153DCAFC009F2584 /* Frameworks */,
+ 4D5594C0153DCAFC009F2584 /* Copy man8 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = setclass;
+ productName = setclass;
+ productReference = 4D5594C2153DCAFC009F2584 /* setclass */;
+ productType = "com.apple.product-type.tool";
+ };
+ 4D5594D4153DCC66009F2584 /* fuser */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4D5594DC153DCC66009F2584 /* Build configuration list for PBXNativeTarget "fuser" */;
+ buildPhases = (
+ 4D5594D1153DCC66009F2584 /* Sources */,
+ 4D5594D2153DCC66009F2584 /* Frameworks */,
+ 4D5594E4153DCCD3009F2584 /* Copy fuser */,
+ 4D5594D3153DCC66009F2584 /* Copy man1 */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = fuser;
+ productName = fuser;
+ productReference = 4D5594D5153DCC66009F2584 /* fuser */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 4D07DD2B153CA616002B57CB /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0440;
+ ORGANIZATIONNAME = "Apple Inc.";
+ };
+ buildConfigurationList = 4D07DD2E153CA616002B57CB /* Build configuration list for PBXProject "diskdev_cmds" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ English,
+ en,
+ );
+ mainGroup = 4D07DD29153CA616002B57CB;
+ productRefGroup = 4D07DD35153CA616002B57CB /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 4D559440153DC57D009F2584 /* All_MacOSX */,
+ 4D559443153DC587009F2584 /* All_iOS */,
+ 4D55934F153CE4CC009F2584 /* Common */,
+ 4D07DD48153CA9A0002B57CB /* libdisk */,
+ 4D559463153DC808009F2584 /* dev_mkdb */,
+ 4D5593A5153CEA90009F2584 /* edquota */,
+ 4D559314153CE198009F2584 /* fdisk */,
+ 4D559340153CE41E009F2584 /* fsck */,
+ 4D559476153DC8FC009F2584 /* fstyp */,
+ 4D559489153DC98D009F2584 /* fstyp_msdos */,
+ 4D55949C153DC9FB009F2584 /* fstyp_ntfs */,
+ 4D5594AE153DCA53009F2584 /* fstyp_udf */,
+ 4D5594D4153DCC66009F2584 /* fuser */,
+ 4D55935F153CE561009F2584 /* mount */,
+ 4D55941B153DC383009F2584 /* mount_devfs */,
+ 4D55942F153DC49A009F2584 /* mount_fdesc */,
+ 4D5593B8153CEB7E009F2584 /* quota */,
+ 4D5593CC153CED29009F2584 /* quotacheck */,
+ 4D5593E3153CEE4A009F2584 /* quotaon */,
+ 4D559514153DE116009F2584 /* quotaoff */,
+ 4D5593F7153DC0DE009F2584 /* repquota */,
+ 4D5594C1153DCAFC009F2584 /* setclass */,
+ 4D55938D153CE7FD009F2584 /* umount */,
+ 4D55940A153DC27A009F2584 /* vndevice */,
+ 4D55944D153DC634009F2584 /* vsdbutil */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 4D5594E4153DCCD3009F2584 /* Copy fuser */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/fuser.tproj/fuser.pl",
+ );
+ name = "Copy fuser";
+ outputPaths = (
+ "$(DSTROOT)$(INSTALL_PATH)/fuser",
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "set -x\nset -e\n\ncp ${SCRIPT_INPUT_FILE_0} ${SCRIPT_OUTPUT_FILE_0}\nchmod 555 ${SCRIPT_OUTPUT_FILE_0}\n";
+ showEnvVarsInLog = 0;
+ };
+ 4D55951B153DE1EF009F2584 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ "$(DSTROOT)/usr/sbin/quotaon",
+ "$(DSTROOT)/usr/share/man/man8/quotaon.8",
+ );
+ outputPaths = (
+ "$(DSTROOT)/usr/sbin/quotaoff",
+ "$(DSTROOT)/usr/share/man/man8/quotaoff.8",
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "set -x\nset -e\n\nln -fhv \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\"\nmkdir -p \"${DSTROOT}/usr/share/man/man8\"\nln -fhv \"${SCRIPT_INPUT_FILE_1}\" \"${SCRIPT_OUTPUT_FILE_1}\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 4D07DD45153CA9A0002B57CB /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D07DD57153CA9DC002B57CB /* dkcksum.c in Sources */,
+ 4D07DD5B153CA9DC002B57CB /* dksecsize.c in Sources */,
+ 4D07DD5F153CA9DC002B57CB /* preen.c in Sources */,
+ 4D07DD60153CA9DC002B57CB /* vfslist.c in Sources */,
+ 4D07DD58153CA9DC002B57CB /* dkdisklabel.c in Sources */,
+ 4D07DD59153CA9DC002B57CB /* dkopen.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559311153CE198009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D559333153CE1D9009F2584 /* cmd.c in Sources */,
+ 4D559334153CE1D9009F2584 /* disk.c in Sources */,
+ 4D559335153CE1D9009F2584 /* fdisk.c in Sources */,
+ 4D559336153CE1D9009F2584 /* getrawpartition.c in Sources */,
+ 4D559337153CE1D9009F2584 /* mbr.c in Sources */,
+ 4D559338153CE1D9009F2584 /* misc.c in Sources */,
+ 4D559339153CE1D9009F2584 /* opendev.c in Sources */,
+ 4D55933A153CE1D9009F2584 /* part.c in Sources */,
+ 4D55933B153CE1D9009F2584 /* user.c in Sources */,
+ 4D559332153CE1D9009F2584 /* auto.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55933D153CE41E009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B19B239C21C8DF660001F35C /* edt_fstab.c in Sources */,
+ 4D55934D153CE44E009F2584 /* fsck.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55935C153CE561009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B19B23A021C8DFA40001F35C /* edt_fstab.c in Sources */,
+ 07CE4C1821906BB800BF11C0 /* mount.c in Sources */,
+ 072AAAA62167CE8F004ED4E2 /* mount_flags.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55938A153CE7FD009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B19B23A221C8DFC30001F35C /* edt_fstab.c in Sources */,
+ 4D559399153CE826009F2584 /* umount.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593A2153CEA90009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5593B2153CEABD009F2584 /* edquota.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593B5153CEB7E009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5593C4153CEB9A009F2584 /* quota.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593C9153CED29009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5593DD153CED51009F2584 /* quotacheck.c in Sources */,
+ 4D5593DC153CED51009F2584 /* hfs_quotacheck.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593E0153CEE4A009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5593EF153CEE66009F2584 /* quotaon.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5593F4153DC0DE009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D559403153DC13D009F2584 /* repquota.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559407153DC27A009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D559417153DC2AB009F2584 /* vndevice.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559418153DC383009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D559428153DC3A6009F2584 /* mount_devfs.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55942C153DC49A009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D55943D153DC4DE009F2584 /* mount_fdesc.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D55944A153DC634009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 078B970D2190682600674625 /* mount_flags.c in Sources */,
+ 4D55945A153DC650009F2584 /* vsdbutil_main.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559460153DC808009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D55946F153DC839009F2584 /* dev_mkdb.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559473153DC8FC009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D559482153DC912009F2584 /* fstyp.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559486153DC98D009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D559495153DC9AE009F2584 /* fstyp_msdos.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D559499153DC9FB009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5594AA153DCA19009F2584 /* fstyp_ntfs.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5594AB153DCA53009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5594BC153DCA74009F2584 /* fstyp_udf.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5594BE153DCAFC009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4D5594CD153DCB72009F2584 /* setclass.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D5594D1153DCC66009F2584 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 071077D92488A09C003B97C7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5594C1153DCAFC009F2584 /* setclass */;
+ targetProxy = 071077D82488A09C003B97C7 /* PBXContainerItemProxy */;
+ };
+ 07747AA21DA8511D00ACE020 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D559476153DC8FC009F2584 /* fstyp */;
+ targetProxy = 07747AA11DA8511D00ACE020 /* PBXContainerItemProxy */;
+ };
+ 4D559357153CE4EA009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D07DD48153CA9A0002B57CB /* libdisk */;
+ targetProxy = 4D559356153CE4EA009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559359153CE4EC009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D559314153CE198009F2584 /* fdisk */;
+ targetProxy = 4D559358153CE4EC009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D55935B153CE4ED009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D559340153CE41E009F2584 /* fsck */;
+ targetProxy = 4D55935A153CE4ED009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559373153CE5F8009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55935F153CE561009F2584 /* mount */;
+ targetProxy = 4D559372153CE5F8009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D55939C153CE83A009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55938D153CE7FD009F2584 /* umount */;
+ targetProxy = 4D55939B153CE83A009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D55939F153CE8B6009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D07DD48153CA9A0002B57CB /* libdisk */;
+ targetProxy = 4D55939E153CE8B6009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D5593A1153CE8BC009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D07DD48153CA9A0002B57CB /* libdisk */;
+ targetProxy = 4D5593A0153CE8BC009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559415153DC282009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55940A153DC27A009F2584 /* vndevice */;
+ targetProxy = 4D559414153DC282009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559426153DC38F009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55941B153DC383009F2584 /* mount_devfs */;
+ targetProxy = 4D559425153DC38F009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D55943A153DC4C0009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55942F153DC49A009F2584 /* mount_fdesc */;
+ targetProxy = 4D559439153DC4C0009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559447153DC597009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55934F153CE4CC009F2584 /* Common */;
+ targetProxy = 4D559446153DC597009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559449153DC599009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55934F153CE4CC009F2584 /* Common */;
+ targetProxy = 4D559448153DC599009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D55945C153DC665009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55944D153DC634009F2584 /* vsdbutil */;
+ targetProxy = 4D55945B153DC665009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559472153DC87B009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D559463153DC808009F2584 /* dev_mkdb */;
+ targetProxy = 4D559471153DC87B009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D559498153DC9E8009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D559489153DC98D009F2584 /* fstyp_msdos */;
+ targetProxy = 4D559497153DC9E8009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D5594A7153DCA04009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D55949C153DC9FB009F2584 /* fstyp_ntfs */;
+ targetProxy = 4D5594A6153DCA04009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D5594B9153DCA5E009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5594AE153DCA53009F2584 /* fstyp_udf */;
+ targetProxy = 4D5594B8153DCA5E009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D5594DF153DCC73009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5594D4153DCC66009F2584 /* fuser */;
+ targetProxy = 4D5594DE153DCC73009F2584 /* PBXContainerItemProxy */;
+ };
+ 4D55951A153DE1CB009F2584 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5593E3153CEE4A009F2584 /* quotaon */;
+ targetProxy = 4D559519153DE1CB009F2584 /* PBXContainerItemProxy */;
+ };
+ B12C9C9222A7CDE300B9F497 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5593A5153CEA90009F2584 /* edquota */;
+ targetProxy = B12C9C9122A7CDE300B9F497 /* PBXContainerItemProxy */;
+ };
+ B12C9C9422A7CDE300B9F497 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5593B8153CEB7E009F2584 /* quota */;
+ targetProxy = B12C9C9322A7CDE300B9F497 /* PBXContainerItemProxy */;
+ };
+ B12C9C9622A7CDE300B9F497 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5593CC153CED29009F2584 /* quotacheck */;
+ targetProxy = B12C9C9522A7CDE300B9F497 /* PBXContainerItemProxy */;
+ };
+ B12C9C9822A7CDE300B9F497 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5593E3153CEE4A009F2584 /* quotaon */;
+ targetProxy = B12C9C9722A7CDE300B9F497 /* PBXContainerItemProxy */;
+ };
+ B12C9C9A22A7CDE300B9F497 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D559514153DE116009F2584 /* quotaoff */;
+ targetProxy = B12C9C9922A7CDE300B9F497 /* PBXContainerItemProxy */;
+ };
+ B12C9C9C22A7CDE300B9F497 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4D5593F7153DC0DE009F2584 /* repquota */;
+ targetProxy = B12C9C9B22A7CDE300B9F497 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 4D07DD3D153CA616002B57CB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ DEAD_CODE_STRIPPING = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ INSTALL_MODE_FLAG = "ugo-w,a+rX";
+ OTHER_CFLAGS = "";
+ SDKROOT = macosx.internal;
+ SUPPORTED_PLATFORMS = "macosx iphoneos";
+ WARNING_CFLAGS = "-Wall";
+ };
+ name = Release;
+ };
+ 4D07DD4B153CA9A0002B57CB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
+ PRODUCT_NAME = disk;
+ SKIP_INSTALL = YES;
+ };
+ name = Release;
+ };
+ 4D55931D153CE199009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
+ INSTALL_PATH = /usr/sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559349153CE41E009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ };
+ name = Release;
+ };
+ 4D559351153CE4CC009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559368153CE561009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = mount.tproj/mount.entitlements;
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks";
+ };
+ name = Release;
+ };
+ 4D559396153CE7FE009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ };
+ name = Release;
+ };
+ 4D5593AE153CEA90009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /usr/sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D5593C1153CEB7E009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_MODE_FLAG = 04555;
+ INSTALL_PATH = /usr/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D5593D5153CED29009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D5593EC153CEE4A009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /usr/sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559400153DC0DE009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /usr/sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559413153DC27A009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /usr/libexec;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559424153DC384009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559438153DC49A009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559442153DC57D009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ OTHER_CFLAGS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559445153DC587009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559456153DC634009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /usr/sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D55946C153DC808009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /usr/sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D55947F153DC8FC009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559492153DC98D009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D5594A5153DC9FB009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D5594B7153DCA53009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /sbin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D5594CA153DCAFC009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D5594DD153DCC66009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = /usr/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 4D559516153DE116009F2584 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4D07DD2E153CA616002B57CB /* Build configuration list for PBXProject "diskdev_cmds" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D07DD3D153CA616002B57CB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D07DD4A153CA9A0002B57CB /* Build configuration list for PBXNativeTarget "libdisk" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D07DD4B153CA9A0002B57CB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D55931C153CE199009F2584 /* Build configuration list for PBXNativeTarget "fdisk" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D55931D153CE199009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559348153CE41E009F2584 /* Build configuration list for PBXNativeTarget "fsck" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559349153CE41E009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559350153CE4CC009F2584 /* Build configuration list for PBXAggregateTarget "Common" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559351153CE4CC009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559367153CE561009F2584 /* Build configuration list for PBXNativeTarget "mount" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559368153CE561009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559395153CE7FE009F2584 /* Build configuration list for PBXNativeTarget "umount" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559396153CE7FE009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5593AD153CEA90009F2584 /* Build configuration list for PBXNativeTarget "edquota" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5593AE153CEA90009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5593C0153CEB7E009F2584 /* Build configuration list for PBXNativeTarget "quota" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5593C1153CEB7E009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5593D4153CED29009F2584 /* Build configuration list for PBXNativeTarget "quotacheck" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5593D5153CED29009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5593EB153CEE4A009F2584 /* Build configuration list for PBXNativeTarget "quotaon" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5593EC153CEE4A009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5593FF153DC0DE009F2584 /* Build configuration list for PBXNativeTarget "repquota" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559400153DC0DE009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559412153DC27A009F2584 /* Build configuration list for PBXNativeTarget "vndevice" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559413153DC27A009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559423153DC384009F2584 /* Build configuration list for PBXNativeTarget "mount_devfs" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559424153DC384009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559437153DC49A009F2584 /* Build configuration list for PBXNativeTarget "mount_fdesc" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559438153DC49A009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559441153DC57D009F2584 /* Build configuration list for PBXAggregateTarget "All_MacOSX" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559442153DC57D009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559444153DC587009F2584 /* Build configuration list for PBXAggregateTarget "All_iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559445153DC587009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559455153DC634009F2584 /* Build configuration list for PBXNativeTarget "vsdbutil" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559456153DC634009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D55946B153DC808009F2584 /* Build configuration list for PBXNativeTarget "dev_mkdb" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D55946C153DC808009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D55947E153DC8FC009F2584 /* Build configuration list for PBXNativeTarget "fstyp" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D55947F153DC8FC009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559491153DC98D009F2584 /* Build configuration list for PBXNativeTarget "fstyp_msdos" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559492153DC98D009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5594A4153DC9FB009F2584 /* Build configuration list for PBXNativeTarget "fstyp_ntfs" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5594A5153DC9FB009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5594B6153DCA53009F2584 /* Build configuration list for PBXNativeTarget "fstyp_udf" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5594B7153DCA53009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5594C9153DCAFC009F2584 /* Build configuration list for PBXNativeTarget "setclass" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5594CA153DCAFC009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D5594DC153DCC66009F2584 /* Build configuration list for PBXNativeTarget "fuser" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D5594DD153DCC66009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4D559515153DE116009F2584 /* Build configuration list for PBXAggregateTarget "quotaoff" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4D559516153DE116009F2584 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 4D07DD2B153CA616002B57CB /* Project object */;
+}
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..e0c148d
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:diskdev_cmds.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..08de0be
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
+ <false/>
+</dict>
+</plist>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme
new file mode 100644
index 0000000..844c24e
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_MacOSX.xcscheme
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559440153DC57D009F2584"
+ BuildableName = "All_MacOSX"
+ BlueprintName = "All_MacOSX"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme
new file mode 100644
index 0000000..1b41173
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/All_iOS.xcscheme
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559443153DC587009F2584"
+ BuildableName = "All_iOS"
+ BlueprintName = "All_iOS"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme
new file mode 100644
index 0000000..d077a0a
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/Common.xcscheme
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55934F153CE4CC009F2584"
+ BuildableName = "Common"
+ BlueprintName = "Common"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme
new file mode 100644
index 0000000..da3f116
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/dev_mkdb.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559463153DC808009F2584"
+ BuildableName = "dev_mkdb"
+ BlueprintName = "dev_mkdb"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559463153DC808009F2584"
+ BuildableName = "dev_mkdb"
+ BlueprintName = "dev_mkdb"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559463153DC808009F2584"
+ BuildableName = "dev_mkdb"
+ BlueprintName = "dev_mkdb"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559463153DC808009F2584"
+ BuildableName = "dev_mkdb"
+ BlueprintName = "dev_mkdb"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme
new file mode 100644
index 0000000..aac4a1c
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/edquota.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593A5153CEA90009F2584"
+ BuildableName = "edquota"
+ BlueprintName = "edquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593A5153CEA90009F2584"
+ BuildableName = "edquota"
+ BlueprintName = "edquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593A5153CEA90009F2584"
+ BuildableName = "edquota"
+ BlueprintName = "edquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593A5153CEA90009F2584"
+ BuildableName = "edquota"
+ BlueprintName = "edquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme
new file mode 100644
index 0000000..23af6d2
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fdisk.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559314153CE198009F2584"
+ BuildableName = "fdisk"
+ BlueprintName = "fdisk"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559314153CE198009F2584"
+ BuildableName = "fdisk"
+ BlueprintName = "fdisk"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559314153CE198009F2584"
+ BuildableName = "fdisk"
+ BlueprintName = "fdisk"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559314153CE198009F2584"
+ BuildableName = "fdisk"
+ BlueprintName = "fdisk"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme
new file mode 100644
index 0000000..5405e97
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fsck.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559340153CE41E009F2584"
+ BuildableName = "fsck"
+ BlueprintName = "fsck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559340153CE41E009F2584"
+ BuildableName = "fsck"
+ BlueprintName = "fsck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559340153CE41E009F2584"
+ BuildableName = "fsck"
+ BlueprintName = "fsck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559340153CE41E009F2584"
+ BuildableName = "fsck"
+ BlueprintName = "fsck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme
new file mode 100644
index 0000000..7e5ae37
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559476153DC8FC009F2584"
+ BuildableName = "fstyp"
+ BlueprintName = "fstyp"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559476153DC8FC009F2584"
+ BuildableName = "fstyp"
+ BlueprintName = "fstyp"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559476153DC8FC009F2584"
+ BuildableName = "fstyp"
+ BlueprintName = "fstyp"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559476153DC8FC009F2584"
+ BuildableName = "fstyp"
+ BlueprintName = "fstyp"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme
new file mode 100644
index 0000000..7135b78
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_msdos.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559489153DC98D009F2584"
+ BuildableName = "fstyp_msdos"
+ BlueprintName = "fstyp_msdos"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559489153DC98D009F2584"
+ BuildableName = "fstyp_msdos"
+ BlueprintName = "fstyp_msdos"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559489153DC98D009F2584"
+ BuildableName = "fstyp_msdos"
+ BlueprintName = "fstyp_msdos"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D559489153DC98D009F2584"
+ BuildableName = "fstyp_msdos"
+ BlueprintName = "fstyp_msdos"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme
new file mode 100644
index 0000000..144c15c
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_ntfs.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55949C153DC9FB009F2584"
+ BuildableName = "fstyp_ntfs"
+ BlueprintName = "fstyp_ntfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55949C153DC9FB009F2584"
+ BuildableName = "fstyp_ntfs"
+ BlueprintName = "fstyp_ntfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55949C153DC9FB009F2584"
+ BuildableName = "fstyp_ntfs"
+ BlueprintName = "fstyp_ntfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55949C153DC9FB009F2584"
+ BuildableName = "fstyp_ntfs"
+ BlueprintName = "fstyp_ntfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme
new file mode 100644
index 0000000..8cb1245
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fstyp_udf.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594AE153DCA53009F2584"
+ BuildableName = "fstyp_udf"
+ BlueprintName = "fstyp_udf"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594AE153DCA53009F2584"
+ BuildableName = "fstyp_udf"
+ BlueprintName = "fstyp_udf"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594AE153DCA53009F2584"
+ BuildableName = "fstyp_udf"
+ BlueprintName = "fstyp_udf"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594AE153DCA53009F2584"
+ BuildableName = "fstyp_udf"
+ BlueprintName = "fstyp_udf"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme
new file mode 100644
index 0000000..db85539
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/fuser.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594D4153DCC66009F2584"
+ BuildableName = "fuser"
+ BlueprintName = "fuser"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594D4153DCC66009F2584"
+ BuildableName = "fuser"
+ BlueprintName = "fuser"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594D4153DCC66009F2584"
+ BuildableName = "fuser"
+ BlueprintName = "fuser"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594D4153DCC66009F2584"
+ BuildableName = "fuser"
+ BlueprintName = "fuser"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme
new file mode 100644
index 0000000..0f60716
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/libdisk.xcscheme
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D07DD48153CA9A0002B57CB"
+ BuildableName = "libdisk.a"
+ BlueprintName = "libdisk"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme
new file mode 100644
index 0000000..6a53cec
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55935F153CE561009F2584"
+ BuildableName = "mount"
+ BlueprintName = "mount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55935F153CE561009F2584"
+ BuildableName = "mount"
+ BlueprintName = "mount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55935F153CE561009F2584"
+ BuildableName = "mount"
+ BlueprintName = "mount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55935F153CE561009F2584"
+ BuildableName = "mount"
+ BlueprintName = "mount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme
new file mode 100644
index 0000000..246cbba
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_devfs.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55941B153DC383009F2584"
+ BuildableName = "mount_devfs"
+ BlueprintName = "mount_devfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55941B153DC383009F2584"
+ BuildableName = "mount_devfs"
+ BlueprintName = "mount_devfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55941B153DC383009F2584"
+ BuildableName = "mount_devfs"
+ BlueprintName = "mount_devfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55941B153DC383009F2584"
+ BuildableName = "mount_devfs"
+ BlueprintName = "mount_devfs"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme
new file mode 100644
index 0000000..dad5f9a
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/mount_fdesc.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55942F153DC49A009F2584"
+ BuildableName = "mount_fdesc"
+ BlueprintName = "mount_fdesc"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55942F153DC49A009F2584"
+ BuildableName = "mount_fdesc"
+ BlueprintName = "mount_fdesc"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55942F153DC49A009F2584"
+ BuildableName = "mount_fdesc"
+ BlueprintName = "mount_fdesc"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55942F153DC49A009F2584"
+ BuildableName = "mount_fdesc"
+ BlueprintName = "mount_fdesc"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme
new file mode 100644
index 0000000..df303b9
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quota.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593B8153CEB7E009F2584"
+ BuildableName = "quota"
+ BlueprintName = "quota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593B8153CEB7E009F2584"
+ BuildableName = "quota"
+ BlueprintName = "quota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593B8153CEB7E009F2584"
+ BuildableName = "quota"
+ BlueprintName = "quota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593B8153CEB7E009F2584"
+ BuildableName = "quota"
+ BlueprintName = "quota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme
new file mode 100644
index 0000000..48bf0e6
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotacheck.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593CC153CED29009F2584"
+ BuildableName = "quotacheck"
+ BlueprintName = "quotacheck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593CC153CED29009F2584"
+ BuildableName = "quotacheck"
+ BlueprintName = "quotacheck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593CC153CED29009F2584"
+ BuildableName = "quotacheck"
+ BlueprintName = "quotacheck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593CC153CED29009F2584"
+ BuildableName = "quotacheck"
+ BlueprintName = "quotacheck"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme
new file mode 100644
index 0000000..1a5fcda
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/quotaon.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593E3153CEE4A009F2584"
+ BuildableName = "quotaon"
+ BlueprintName = "quotaon"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593E3153CEE4A009F2584"
+ BuildableName = "quotaon"
+ BlueprintName = "quotaon"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593E3153CEE4A009F2584"
+ BuildableName = "quotaon"
+ BlueprintName = "quotaon"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593E3153CEE4A009F2584"
+ BuildableName = "quotaon"
+ BlueprintName = "quotaon"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme
new file mode 100644
index 0000000..75149cf
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/repquota.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593F7153DC0DE009F2584"
+ BuildableName = "repquota"
+ BlueprintName = "repquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593F7153DC0DE009F2584"
+ BuildableName = "repquota"
+ BlueprintName = "repquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593F7153DC0DE009F2584"
+ BuildableName = "repquota"
+ BlueprintName = "repquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5593F7153DC0DE009F2584"
+ BuildableName = "repquota"
+ BlueprintName = "repquota"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme
new file mode 100644
index 0000000..b249cf1
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/setclass.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594C1153DCAFC009F2584"
+ BuildableName = "setclass"
+ BlueprintName = "setclass"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594C1153DCAFC009F2584"
+ BuildableName = "setclass"
+ BlueprintName = "setclass"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594C1153DCAFC009F2584"
+ BuildableName = "setclass"
+ BlueprintName = "setclass"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D5594C1153DCAFC009F2584"
+ BuildableName = "setclass"
+ BlueprintName = "setclass"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme
new file mode 100644
index 0000000..51ffb5d
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/umount.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55938D153CE7FD009F2584"
+ BuildableName = "umount"
+ BlueprintName = "umount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55938D153CE7FD009F2584"
+ BuildableName = "umount"
+ BlueprintName = "umount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55938D153CE7FD009F2584"
+ BuildableName = "umount"
+ BlueprintName = "umount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55938D153CE7FD009F2584"
+ BuildableName = "umount"
+ BlueprintName = "umount"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme
new file mode 100644
index 0000000..5bb5059
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vndevice.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55940A153DC27A009F2584"
+ BuildableName = "vndevice"
+ BlueprintName = "vndevice"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55940A153DC27A009F2584"
+ BuildableName = "vndevice"
+ BlueprintName = "vndevice"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55940A153DC27A009F2584"
+ BuildableName = "vndevice"
+ BlueprintName = "vndevice"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55940A153DC27A009F2584"
+ BuildableName = "vndevice"
+ BlueprintName = "vndevice"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme
new file mode 100644
index 0000000..6e7d1c4
--- /dev/null
+++ b/diskdev_cmds/diskdev_cmds.xcodeproj/xcshareddata/xcschemes/vsdbutil.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55944D153DC634009F2584"
+ BuildableName = "vsdbutil"
+ BlueprintName = "vsdbutil"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55944D153DC634009F2584"
+ BuildableName = "vsdbutil"
+ BlueprintName = "vsdbutil"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55944D153DC634009F2584"
+ BuildableName = "vsdbutil"
+ BlueprintName = "vsdbutil"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4D55944D153DC634009F2584"
+ BuildableName = "vsdbutil"
+ BlueprintName = "vsdbutil"
+ ReferencedContainer = "container:diskdev_cmds.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+ <InstallAction
+ buildConfiguration = "Release">
+ </InstallAction>
+</Scheme>
diff --git a/diskdev_cmds/disklib/dkcksum.c b/diskdev_cmds/disklib/dkcksum.c
new file mode 100644
index 0000000..e275cb2
--- /dev/null
+++ b/diskdev_cmds/disklib/dkcksum.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+
+#if defined (linux) && defined (__powerpc__)
+#define __ppc__
+#endif
+
+#include <sys/disklabel.h>
+
+u_short
+dkcksum(lp)
+ register struct disklabel *lp;
+{
+ register u_short *start, *end;
+ register u_short sum = 0;
+
+ start = (u_short *)lp;
+ end = (u_short *)&lp->d_partitions[lp->d_npartitions];
+ while (start < end)
+ sum ^= *start++;
+ return (sum);
+}
diff --git a/diskdev_cmds/disklib/dkdisklabel.c b/diskdev_cmds/disklib/dkdisklabel.c
new file mode 100644
index 0000000..3fffce5
--- /dev/null
+++ b/diskdev_cmds/disklib/dkdisklabel.c
@@ -0,0 +1,193 @@
+/* Copyright 1999 Apple Computer, Inc.
+ *
+ * Generate a bsd disk label routine.
+ * Input: open file descriptor to the device node, and
+ * pointer to a disk label structure to fill in
+ * Return: errno status
+ *
+ * HISTORY
+ *
+ * 24 Feb 1999 D. Markarian at Apple
+ * Created.
+ */
+
+#include <string.h> /* memset */
+#include <sys/types.h> /* sys/disklabel.h */
+#include <sys/param.h> /* NBPG */
+
+#include <sys/disk.h> /* DKIOCGETBLOCKSIZE ioctl */
+
+#include <sys/disklabel.h> /* struct disklabel */
+
+u_short dkcksum __P((register struct disklabel *lp));
+int dkdisklabelregenerate __P((int fd, struct disklabel * lp, int newblksize));
+
+/*
+ * The following two constants set the default block and fragment sizes.
+ * Both constants must be a power of 2 and meet the following constraints:
+ * MINBSIZE <= GENBLKSIZE <= MAXBSIZE
+ * sectorsize <= GENFRAGSIZE <= GENBLKSIZE
+ * GENBLKSIZE / GENFRAGSIZE <= 8
+ */
+#define GENFRAGSIZE 1024
+#define GENBLKSIZE NBPG /* 4096 */
+
+/*
+ * Cylinder groups may have up to many cylinders. The actual
+ * number used depends upon how much information can be stored
+ * on a single cylinder. The default is to use 16 cylinders
+ * per group.
+ */
+#define GENCPG 16
+
+/*
+ * Interleave is physical sector interleave, set up by the
+ * formatter or controller when formatting. When interleaving is
+ * in use, logically adjacent sectors are not physically
+ * contiguous, but instead are separated by some number of
+ * sectors. It is specified as the ratio of physical sectors
+ * traversed per logical sector. Thus an interleave of 1:1
+ * implies contiguous layout, while 2:1 implies that logical
+ * sector 0 is separated by one sector from logical sector 1.
+ */
+#define GENINTERLEAVE 1
+
+/*
+ * Rotational speed; # of data sectors per track.
+ */
+#define GENRPM 3600
+#define GENNSECTORS 32
+
+int dkdisklabel(int fd, struct disklabel * lp)
+{
+ return dkdisklabelregenerate(fd, lp, 0);
+}
+
+int dkdisklabelregenerate(int fd, struct disklabel * lp, int newblksize)
+{
+ /*
+ * Generate a bsd-style disk label for the specified device node.
+ */
+
+ int blksize;
+ int error;
+ int index;
+ int64_t numblks;
+
+ /* obtain the size of the media (in blocks) */
+ if ( (error = ioctl(fd, DKIOCGETBLOCKCOUNT, &numblks)) < 0 )
+ return(error);
+
+ /* obtain the block size of the media */
+ if ( (error = ioctl(fd, DKIOCGETBLOCKSIZE, &blksize)) < 0 )
+ return(error);
+
+ /* adjust the size of the media with newblksize should it be specified */
+ if (newblksize)
+ {
+ numblks = ((numblks * blksize) / newblksize);
+ blksize = newblksize;
+ }
+
+ /*
+ * clear the disk label structure and then fill in the appropriate fields;
+ * we comment out lines that are initializations to zero with //, since it
+ * is redundant work
+ */
+ memset(lp, 0, sizeof(struct disklabel));
+
+ lp->d_magic = DISKMAGIC; /* the magic number */
+// lp->d_type = 0; /* drive type */
+// lp->d_subtype = 0; /* controller/d_type specific */
+// lp->d_typename[0] = 0; /* type name, e.g. "eagle" */
+ /*
+ * d_packname contains the pack identifier and is returned when
+ * the disklabel is read off the disk or in-core copy.
+ * d_boot0 and d_boot1 are the (optional) names of the
+ * primary (block 0) and secondary (block 1-15) bootstraps
+ * as found in /usr/mdec. These are returned when using
+ * getdiskbyname(3) to retrieve the values from /etc/disktab.
+ */
+// lp->d_packname[0] = 0; /* pack identifier */
+
+ /* disk geometry: */
+ lp->d_secsize = blksize; /* # of bytes per sector */
+ lp->d_nsectors = GENNSECTORS; /* # of data sectors per track */
+ /* # of tracks per cylinder */
+ if (numblks < 8*32*1024) /* <=528.4 MB */
+ lp->d_ntracks = 16;
+ else if (numblks < 16*32*1024) /* <=1.057 GB */
+ lp->d_ntracks = 32;
+ else if (numblks < 32*32*1024) /* <=2.114 GB */
+ lp->d_ntracks = 54;
+ else if (numblks < 64*32*1024) /* <=4.228 GB */
+ lp->d_ntracks = 128;
+ else /* > 4.228 GB */
+ lp->d_ntracks = 255;
+ /* # of data cylinders per unit */
+ lp->d_ncylinders = numblks / lp->d_ntracks / lp->d_nsectors;
+ /* # of data sectors per cylinder */
+ lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
+ lp->d_secperunit = numblks; /* # of data sectors per unit */
+ /*
+ * Spares (bad sector replacements) below are not counted in
+ * d_nsectors or d_secpercyl. Spare sectors are assumed to
+ * be physical sectors which occupy space at the end of each
+ * track and/or cylinder.
+ */
+// lp->d_sparespertrack = 0; /* # of spare sectors per track */
+// lp->d_sparespercyl = 0; /* # of data sectors per unit */
+ /*
+ * Alternate cylinders include maintenance, replacement, configuration
+ * description areas, etc.
+ */
+// lp->d_acylinders = 0; /* # of alt. cylinders per unit */
+
+ /* hardware characteristics: */
+ /*
+ * d_interleave, d_trackskew and d_cylskew describe perturbations
+ * in the media format used to compensate for a slow controller.
+ * Interleave is physical sector interleave, set up by the
+ * formatter or controller when formatting. When interleaving is
+ * in use, logically adjacent sectors are not physically
+ * contiguous, but instead are separated by some number of
+ * sectors. It is specified as the ratio of physical sectors
+ * traversed per logical sector. Thus an interleave of 1:1
+ * implies contiguous layout, while 2:1 implies that logical
+ * sector 0 is separated by one sector from logical sector 1.
+ * d_trackskew is the offset of sector 0 on track N relative to
+ * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew
+ * is the offset of sector 0 on cylinder N relative to sector 0
+ * on cylinder N-1.
+ */
+ lp->d_rpm = GENRPM; /* rotational speed */
+ lp->d_interleave = GENINTERLEAVE; /* hardware sector interleave */
+// lp->d_trackskew = 0; /* sector 0 skew, per track */
+// lp->d_cylskew = 0; /* sector 0 skew, per cylinder */
+// lp->d_headswitch = 0; /* head switch time, usec */
+// lp->d_trkseek = 0; /* track-to-track seek, usec */
+// lp->d_flags = 0; /* generic flags */
+// lp->d_drivedata[0-4] = 0; /* drive-type specific information */
+// lp->d_spare[0-4] = 0; /* reserved for future use */
+ lp->d_magic2 = DISKMAGIC; /* the magic number (again) */
+// lp->d_checksum = 0; /* xor of data incl. partitions */
+
+ /* filesystem and partition information: */
+ lp->d_npartitions = MAXPARTITIONS; /* number of partitions */
+
+ for (index = 0; index < MAXPARTITIONS; index++)
+ {
+ struct partition * pp = &(lp->d_partitions[index]);
+ pp->p_size = numblks; /* number of sectors */
+// pp->p_offset = 0; /* starting sector */
+ pp->p_fsize = MAX(GENFRAGSIZE, blksize); /* fs fragment size */
+ pp->p_fstype = FS_BSDFFS; /* fs type */
+ pp->p_frag = MIN(8, GENBLKSIZE / pp->p_fsize);/* fs fragments/block */
+ pp->p_cpg = GENCPG; /* fs cylinders/group */
+ }
+
+ /* compute a checksum on the resulting structure */
+ lp->d_checksum = dkcksum(lp);
+
+ return 0; /* success */
+}
diff --git a/diskdev_cmds/disklib/dkopen.c b/diskdev_cmds/disklib/dkopen.c
new file mode 100644
index 0000000..7a94561
--- /dev/null
+++ b/diskdev_cmds/disklib/dkopen.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "dkopen.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int dkopen (const char *path, int flags, int mode)
+{
+#if defined (linux)
+ return (open64 (path, flags, mode));
+#elif defined (__APPLE__)
+ return (open (path, flags, mode));
+#endif
+}
+
+int dkclose (int filedes)
+{
+#if defined (linux)
+ return (close (filedes));
+#elif defined (__APPLE__)
+ return (close (filedes));
+#endif
+}
+
+off64_t dklseek (int filedes, off64_t offset, int whence)
+{
+#if defined (linux)
+ return (lseek64 (filedes, offset, whence));
+#elif defined (__APPLE__)
+ return (lseek (filedes, offset, whence));
+#endif
+}
+
diff --git a/diskdev_cmds/disklib/dkopen.h b/diskdev_cmds/disklib/dkopen.h
new file mode 100644
index 0000000..eb0bdeb
--- /dev/null
+++ b/diskdev_cmds/disklib/dkopen.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * File I/O stubs
+ *
+ * Linux and other OSs may use open64, lseek64 instead of defaulting off_t to
+ * 64-bits like OSX does. This file provides cover functions to always perform
+ * 64-bit file I/O.
+ */
+
+#ifndef _DKOPEN_H_
+#define _DKOPEN_H_
+
+/* Must predefine the large file flags before including sys/types.h */
+#if defined (linux)
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#elif defined (__APPLE__)
+#else
+#error Platform not recognized
+#endif
+
+#include <sys/types.h>
+
+/* Typedef off64_t for platforms that don't have it declared */
+#if defined (__APPLE__) && !defined (linux)
+typedef u_int64_t off64_t;
+#endif
+
+int dkopen (const char *path, int flags, int mode);
+int dkclose (int filedes);
+
+off64_t dklseek (int fileds, off64_t offset, int whence);
+
+#endif
diff --git a/diskdev_cmds/disklib/dksecsize.c b/diskdev_cmds/disklib/dksecsize.c
new file mode 100644
index 0000000..0cfad82
--- /dev/null
+++ b/diskdev_cmds/disklib/dksecsize.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* Copyright 1998 Apple Computer, Inc.
+ *
+ * Get disk label's sector size routine.
+ * Input: pointer to a block device string ie: "/dev/disk1s1"
+ * Return: sector size from the disk label
+ *
+ * HISTORY
+ *
+ * 27 May 1998 K. Crippes at Apple
+ * Rhapsody version created.
+ * 18 Feb 1999 D. Markarian at Apple
+ * DKIOCGLABEL deprecated; using DKIOCBLKSIZE instead, which now returns
+ * the appropriate size for ufs partitions created with wierd block sizes.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/disk.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+char *blockcheck __P((char *));
+
+long dksecsize (dev)
+ char *dev;
+{
+ int fd; /* file descriptor for reading device label */
+ char *cdev;
+ int devblklen;
+ extern int errno;
+
+ /* Convert block device into a character device string */
+ if ((cdev = blockcheck(dev))) {
+ if ((fd = open(cdev, O_RDONLY)) < 0) {
+ fprintf(stderr, "Can't open %s, %s\n", cdev, strerror(errno));
+ return (0);
+ }
+ }
+ else
+ return (0);
+
+ if (ioctl(fd, DKIOCGETBLOCKSIZE, &devblklen) < 0) {
+ (void)close(fd);
+ return (0);
+ }
+ else {
+ (void)close(fd);
+ return (devblklen);
+ }
+}
+
diff --git a/diskdev_cmds/disklib/pathnames.h b/diskdev_cmds/disklib/pathnames.h
new file mode 100644
index 0000000..59cd945
--- /dev/null
+++ b/diskdev_cmds/disklib/pathnames.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
+ */
+
+#include <paths.h>
+
+#define _PATH_DTMP "/etc/dtmp"
+#define _PATH_DUMPDATES "/etc/dumpdates"
+#define _PATH_LOCK "/tmp/dumplockXXXXXX"
+#define _PATH_RMT "rmt"
diff --git a/diskdev_cmds/disklib/preen.c b/diskdev_cmds/disklib/preen.c
new file mode 100644
index 0000000..f7128e0
--- /dev/null
+++ b/diskdev_cmds/disklib/preen.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <fstab.h>
+#include <string.h>
+#include <TargetConditionals.h>
+
+#if TARGET_OS_OSX
+struct part {
+ struct part *next; /* forward link of partitions on disk */
+ char *name; /* device name */
+ char *fsname; /* mounted filesystem name */
+ long auxdata; /* auxillary data for application */
+} *badlist, **badnext = &badlist;
+
+struct disk {
+ char *name; /* disk base name */
+ struct disk *next; /* forward link for list of disks */
+ struct part *part; /* head of list of partitions on disk */
+ int pid; /* If != 0, pid of proc working on */
+} *disks;
+
+int nrun, ndisks;
+char hotroot;
+
+static void addpart (char *name, char *fsname, long auxdata);
+static struct disk *finddisk (char *name);
+static char *rawname (char *name);
+static int startdisk (struct disk *dk,
+ int (*checkit)(char *, char *, long, int));
+static char *unrawname (char *name);
+char* blockcheck (char *name);
+
+int
+checkfstab(preen, maxrun, docheck, chkit)
+ int preen;
+ int maxrun;
+ int (*docheck)(struct fstab *);
+ int (*chkit)(char *, char *, long, int);
+{
+ register struct fstab *fsp;
+ register struct disk *dk, *nextdisk;
+ register struct part *pt;
+ int ret, pid, retcode, passno, sumstatus, status;
+ long auxdata;
+ char *name;
+
+ sumstatus = 0;
+ for (passno = 1; passno <= 2; passno++) {
+ if (setfsent() == 0) {
+ fprintf(stderr, "Can't open checklist file: %s\n",
+ _PATH_FSTAB);
+ return (8);
+ }
+ while ((fsp = getfsent()) != 0) {
+ if ((auxdata = (*docheck)(fsp)) == 0)
+ continue;
+ if (preen == 0 ||
+ (passno == 1 && fsp->fs_passno == 1)) {
+ if ((name = blockcheck(fsp->fs_spec)) != 0) {
+ if ((sumstatus = (*chkit)(name,
+ fsp->fs_file, auxdata, 0)) != 0)
+ return (sumstatus);
+ } else if (preen)
+ return (8);
+ } else if (passno == 2 && fsp->fs_passno > 1) {
+ if ((name = blockcheck(fsp->fs_spec)) == NULL) {
+ fprintf(stderr, "BAD DISK NAME %s\n",
+ fsp->fs_spec);
+ sumstatus |= 8;
+ continue;
+ }
+ addpart(name, fsp->fs_file, auxdata);
+ }
+ }
+ if (preen == 0)
+ return (0);
+ }
+ if (preen) {
+ if (maxrun == 0)
+ maxrun = ndisks;
+ if (maxrun > ndisks)
+ maxrun = ndisks;
+ nextdisk = disks;
+ for (passno = 0; passno < maxrun; ++passno) {
+ while ((ret = startdisk(nextdisk, chkit)) && nrun > 0)
+ sleep(10);
+ if (ret)
+ return (ret);
+ nextdisk = nextdisk->next;
+ }
+ while ((pid = wait(&status)) != -1) {
+ for (dk = disks; dk; dk = dk->next)
+ if (dk->pid == pid)
+ break;
+ if (dk == 0) {
+ printf("Unknown pid %d\n", pid);
+ continue;
+ }
+ if (WIFEXITED(status))
+ retcode = WEXITSTATUS(status);
+ else
+ retcode = 0;
+ if (WIFSIGNALED(status)) {
+ printf("%s (%s): EXITED WITH SIGNAL %d\n",
+ dk->part->name, dk->part->fsname,
+ WTERMSIG(status));
+ retcode = 8;
+ }
+ if (retcode != 0) {
+ sumstatus |= retcode;
+ *badnext = dk->part;
+ badnext = &dk->part->next;
+ dk->part = dk->part->next;
+ *badnext = NULL;
+ } else
+ dk->part = dk->part->next;
+ dk->pid = 0;
+ nrun--;
+ if (dk->part == NULL)
+ ndisks--;
+
+ if (nextdisk == NULL) {
+ if (dk->part) {
+ while ((ret = startdisk(dk, chkit)) &&
+ nrun > 0)
+ sleep(10);
+ if (ret)
+ return (ret);
+ }
+ } else if (nrun < maxrun && nrun < ndisks) {
+ for ( ;; ) {
+ if ((nextdisk = nextdisk->next) == NULL)
+ nextdisk = disks;
+ if (nextdisk->part != NULL &&
+ nextdisk->pid == 0)
+ break;
+ }
+ while ((ret = startdisk(nextdisk, chkit)) &&
+ nrun > 0)
+ sleep(10);
+ if (ret)
+ return (ret);
+ }
+ }
+ }
+ if (sumstatus) {
+ if (badlist == 0)
+ return (sumstatus);
+ fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
+ badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
+ for (pt = badlist; pt; pt = pt->next)
+ fprintf(stderr, "%s (%s)%s", pt->name, pt->fsname,
+ pt->next ? ", " : "\n");
+ return (sumstatus);
+ }
+ (void)endfsent();
+ return (0);
+}
+
+static struct disk *
+finddisk(name)
+ char *name;
+{
+ register struct disk *dk, **dkp;
+ register char *p;
+ size_t len;
+
+ for (len = strlen(name), p = name + len - 1; p >= name; --p)
+ if (isdigit(*p)) {
+ len = p - name + 1;
+ break;
+ }
+
+ for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
+ if (strncmp(dk->name, name, len) == 0 &&
+ dk->name[len] == 0)
+ return (dk);
+ }
+ if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ dk = *dkp;
+ if ((dk->name = malloc(len + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ (void)strncpy(dk->name, name, len);
+ dk->name[len] = '\0';
+ dk->part = NULL;
+ dk->next = NULL;
+ dk->pid = 0;
+ ndisks++;
+ return (dk);
+}
+
+static void
+addpart(name, fsname, auxdata)
+ char *name, *fsname;
+ long auxdata;
+{
+ struct disk *dk = finddisk(name);
+ register struct part *pt, **ppt = &dk->part;
+
+ for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
+ if (strcmp(pt->name, name) == 0) {
+ printf("%s in fstab more than once!\n", name);
+ return;
+ }
+ if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ pt = *ppt;
+ if ((pt->name = strdup(name)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ if ((pt->fsname = strdup(fsname)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ pt->next = NULL;
+ pt->auxdata = auxdata;
+}
+
+static int
+startdisk(dk, checkit)
+ register struct disk *dk;
+ int (*checkit)(char *, char *, long, int);
+{
+ register struct part *pt = dk->part;
+
+ dk->pid = fork();
+ if (dk->pid < 0) {
+ perror("fork");
+ return (8);
+ }
+ if (dk->pid == 0)
+ exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1));
+ nrun++;
+ return (0);
+}
+
+char *
+blockcheck(char* origname) {
+ struct stat stslash, stblock, stchar;
+ char *newname, *raw;
+ int retried = 0;
+
+ hotroot = 0;
+ if (stat("/", &stslash) < 0) {
+ perror("/");
+ printf("Can't stat root\n");
+ return (origname);
+ }
+ newname = origname;
+retry:
+ if (stat(newname, &stblock) < 0) {
+ perror(newname);
+ printf("Can't stat %s\n", newname);
+ return (origname);
+ }
+ if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
+ if (stslash.st_dev == stblock.st_rdev)
+ hotroot++;
+ raw = rawname(newname);
+ if (stat(raw, &stchar) < 0) {
+ perror(raw);
+ printf("Can't stat %s\n", raw);
+ return (origname);
+ }
+ if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
+ return (raw);
+ } else {
+ printf("%s is not a character device\n", raw);
+ return (origname);
+ }
+ } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
+ newname = unrawname(newname);
+ retried++;
+ goto retry;
+ }
+ /*
+ * Not a block or character device, just return name and
+ * let the user decide whether to use it.
+ */
+ return (origname);
+}
+
+static char *
+unrawname(name)
+ char *name;
+{
+ char *dp;
+ struct stat stb;
+ size_t dp_len;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (name);
+ if (stat(name, &stb) < 0)
+ return (name);
+ if ((stb.st_mode & S_IFMT) != S_IFCHR)
+ return (name);
+ if (dp[1] != 'r')
+ return (name);
+ dp_len = strlen(&dp[2]) + 1;
+ (void)memmove(&dp[1], &dp[2], dp_len);
+ return (name);
+}
+
+static char *
+rawname(name)
+ char *name;
+{
+ static char rawbuf[32];
+ char *dp;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (0);
+ *dp = 0;
+ (void)strncpy(rawbuf, name, sizeof(rawbuf));
+ *dp = '/';
+ (void)strlcat(rawbuf, "/r", sizeof(rawbuf));
+ (void)strlcat(rawbuf, &dp[1], sizeof(rawbuf));
+ return (rawbuf);
+}
+
+#endif /* TARGET_OS_OSX */
+
diff --git a/diskdev_cmds/disklib/vfslist.c b/diskdev_cmds/disklib/vfslist.c
new file mode 100644
index 0000000..6ecafcd
--- /dev/null
+++ b/diskdev_cmds/disklib/vfslist.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+
+int checkvfsname __P((const char *, const char **));
+const char **makevfslist __P((char *));
+static int skipvfs;
+
+int
+checkvfsname(vfsname, vfslist)
+ const char *vfsname;
+ const char **vfslist;
+{
+
+ if (vfslist == NULL)
+ return (0);
+ while (*vfslist != NULL) {
+ if (strcmp(vfsname, *vfslist) == 0)
+ return (skipvfs);
+ ++vfslist;
+ }
+ return (!skipvfs);
+}
+
+const char **
+makevfslist(fslist)
+ char *fslist;
+{
+ const char **av;
+ int i;
+ char *nextcp;
+
+ if (fslist == NULL)
+ return (NULL);
+ if (fslist[0] == 'n' && fslist[1] == 'o') {
+ fslist += 2;
+ skipvfs = 1;
+ }
+ for (i = 0, nextcp = fslist; *nextcp; nextcp++)
+ if (*nextcp == ',')
+ i++;
+ if ((av = malloc((size_t)(i + 2) * sizeof(char *))) == NULL) {
+ warn(NULL);
+ return (NULL);
+ }
+ nextcp = fslist;
+ i = 0;
+ av[i++] = nextcp;
+ while ((nextcp = strchr(nextcp, ',')) != NULL) {
+ *nextcp++ = '\0';
+ av[i++] = nextcp;
+ }
+ av[i++] = NULL;
+ return (av);
+}
diff --git a/diskdev_cmds/edquota.tproj/edquota.8 b/diskdev_cmds/edquota.tproj/edquota.8
new file mode 100644
index 0000000..fd52b56
--- /dev/null
+++ b/diskdev_cmds/edquota.tproj/edquota.8
@@ -0,0 +1,184 @@
+.\" Copyright (c) 1983, 1990, 1993, 2002
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)edquota.8 8.2 (Berkeley) 4/27/95
+.\"
+.Dd "March 28, 2002"
+.Dt EDQUOTA 8
+.Os
+.Sh NAME
+.Nm edquota
+.Nd edit user quotas
+.Sh SYNOPSIS
+.Nm edquota
+.Op Fl u
+.Op Fl p Ar proto-username
+.Ar username ...
+.Nm edquota
+.Fl g
+.Op Fl p Ar proto-groupname
+.Ar groupname ...
+.Nm edquota
+.Fl t
+.Op Fl u
+.Nm edquota
+.Fl t
+.Fl g
+.Sh DESCRIPTION
+.Nm Edquota
+is a quota editor.
+By default, or if the
+.Fl u
+flag is specified,
+one or more users may be specified on the command line.
+For each user a temporary file is created
+with an ASCII representation of the current
+disk quotas for that user.
+The list of filesystems with user quotas is determined by
+scanning the mounted filesystems for a
+.Pa .quota.ops.user
+file located at its root.
+An editor is invoked on the ASCII file.
+The editor invoked is
+.Xr vi 1
+unless the environment variable
+.Ev EDITOR
+specifies otherwise.
+.Pp
+The quotas may then be modified, new quotas added, etc.
+Setting a quota to zero indicates that no quota should be imposed.
+Setting a hard limit to one indicates that no allocations should
+be permitted.
+Setting a soft limit to one with a hard limit of zero
+indicates that allocations should be permitted on
+only a temporary basis (see
+.Fl t
+below).
+The current usage information in the file is for informational purposes;
+only the hard and soft limits can be changed.
+.Pp
+On leaving the editor,
+.Nm edquota
+reads the temporary file and modifies the binary
+quota files to reflect the changes made.
+The binary quota file,
+.Pa .quota.user
+is stored at the root of the filesystem.
+The default filename and root location for the user
+quotas cannot be overridden.
+.Pp
+If the
+.Fl p
+flag is specified,
+.Nm edquota
+will duplicate the quotas of the prototypical user
+specified for each user specified.
+This is the normal mechanism used to
+initialize quotas for groups of users.
+.Pp
+If the
+.Fl g
+flag is specified,
+.Nm edquota
+is invoked to edit the quotas of
+one or more groups specified on the command line.
+The list of filesystems with group quotas is determined by
+scanning the mounted filesystems for a
+.Pa .quota.ops.group
+file located at its root.
+Similarly, the binary quota file,
+.Pa .quota.group
+is stored at the root of the filesystem.
+The default filename and root location for group
+quotas cannot be overridden.
+The
+.Fl p
+flag can be specified in conjunction with
+the
+.Fl g
+flag to specify a prototypical group
+to be duplicated among the listed set of groups.
+.Pp
+Users are permitted to exceed their soft limits
+for a grace period that may be specified per filesystem.
+Once the grace period has expired,
+the soft limit is enforced as a hard limit.
+The default grace period for a filesystem is specified in
+.Pa /usr/include/sys/quota.h .
+The
+.Fl t
+flag can be used to change the grace period.
+By default, or when invoked with the
+.Fl u
+flag, the grace period is set for each filesystem with a
+.Pa .quota.ops.user
+file located at its root.
+When invoked with the
+.Fl g
+flag, the grace period is
+set for each filesystem with a
+.Pa .quota.ops.group
+file located at its root.
+The grace period may be specified in days, hours, minutes, or seconds.
+Setting a grace period to zero indicates that the default
+grace period should be imposed.
+Setting a grace period to one second indicates that no
+grace period should be granted.
+.Pp
+Only the super-user may edit quotas.
+.Sh FILES
+Each of the following quota files is located at the root of the
+mounted filesystem. The mount option files are empty files
+whose existence indicates that quotas are to be enabled
+for that filesystem. The binary data files will be
+created by edquota, if they don't already exist.
+.Pp
+.Bl -tag -width .quota.ops.group -compact
+.It Pa .quota.user
+data file containing user quotas
+.It Pa .quota.group
+data file containing group quotas
+.It Pa .quota.ops.user
+mount option file used to enable user quotas
+.It Pa .quota.ops.group
+mount option file used to enable group quotas
+.El
+.Sh SEE ALSO
+.Xr quota 1 ,
+.Xr quotactl 2 ,
+.Xr quotacheck 8 ,
+.Xr quotaon 8 ,
+.Xr repquota 8
+.Sh DIAGNOSTICS
+Various messages about inaccessible files; self-explanatory.
diff --git a/diskdev_cmds/edquota.tproj/edquota.c b/diskdev_cmds/edquota.tproj/edquota.c
new file mode 100644
index 0000000..6dad1cb
--- /dev/null
+++ b/diskdev_cmds/edquota.tproj/edquota.c
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#ifndef lint
+__unused static char copyright[] =
+"@(#) Copyright (c) 1980, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+__unused static char sccsid[] = "@(#)edquota.c 8.3 (Berkeley) 4/27/95";
+#endif /* not lint */
+
+/*
+ * Disk quota editor.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#ifdef __APPLE__
+#include <sys/mount.h>
+#endif /* __APPLE__ */
+#include <sys/wait.h>
+#include <sys/queue.h>
+#include <sys/quota.h>
+#include <errno.h>
+#include <fstab.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include "pathnames.h"
+
+#ifdef __APPLE__
+#include <libkern/OSByteOrder.h>
+#endif /* __APPLE__ */
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+char *quotagroup = QUOTAGROUP;
+char tmpfil[] = _PATH_TMP;
+
+#ifdef __APPLE__
+u_int32_t quotamagic[MAXQUOTAS] = INITQMAGICS;
+#endif /* __APPLE__ */
+
+struct quotause {
+ struct quotause *next;
+ long flags;
+ struct dqblk dqblk;
+ char fsname[MAXPATHLEN + 1];
+ char qfname[1]; /* actually longer */
+} *getprivs();
+#define FOUND 0x01
+
+int alldigits __P((char *));
+int cvtatos __P((time_t, char *, time_t *));
+int editit __P((char *));
+void freeprivs __P((struct quotause *));
+int getentry __P((char *, int));
+int hasquota __P((struct statfs *, int, char **));
+void putprivs __P((uid_t, int, struct quotause *));
+int readprivs __P((struct quotause *, int));
+int readtimes __P((struct quotause *, int));
+void usage __P((void));
+int writeprivs __P((struct quotause *, int, char *, int));
+int writetimes __P((struct quotause *, int, int));
+
+#ifdef __APPLE__
+int qfinit(int, struct statfs *, int);
+int qflookup(int, uid_t, int, struct dqblk *);
+int qfupdate(int, uid_t, int, struct dqblk *);
+#endif /* __APPLE__ */
+
+
+int
+main(argc, argv)
+ register char **argv;
+ int argc;
+{
+ register struct quotause *qup, *protoprivs, *curprivs;
+ extern char *optarg;
+ extern int optind;
+ register uid_t id, protoid;
+ register int quotatype, tmpfd;
+ char *protoname = NULL, ch;
+ int tflag = 0, pflag = 0;
+
+ if (argc < 2)
+ usage();
+ if (getuid()) {
+ fprintf(stderr, "edquota: permission denied\n");
+ exit(1);
+ }
+ quotatype = USRQUOTA;
+
+ while ((ch = getopt(argc, argv, "ugtp:")) != EOF) {
+ switch(ch) {
+ case 'p':
+ protoname = optarg;
+ pflag++;
+ break;
+ case 'g':
+ quotatype = GRPQUOTA;
+ break;
+ case 'u':
+ quotatype = USRQUOTA;
+ break;
+ case 't':
+ tflag++;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (pflag) {
+ if ((protoid = getentry(protoname, quotatype)) == -1)
+ exit(1);
+ protoprivs = getprivs(protoid, quotatype);
+#ifdef __APPLE__
+ if (protoprivs == (struct quotause *) NULL)
+ exit(0);
+#endif /* __APPLE__ */
+ for (qup = protoprivs; qup; qup = qup->next) {
+ qup->dqblk.dqb_btime = 0;
+ qup->dqblk.dqb_itime = 0;
+ }
+ while (argc-- > 0) {
+ if ((id = getentry(*argv++, quotatype)) == -1)
+ continue;
+ /*
+ * Set the ID in each disk quota block to match
+ * the ID it's supposed to go with.
+ */
+ for (qup = protoprivs; qup; qup = qup->next) {
+ qup->dqblk.dqb_id = id;
+ }
+ putprivs(id, quotatype, protoprivs);
+ }
+ exit(0);
+ }
+ tmpfd = mkstemp(tmpfil);
+ fchown(tmpfd, getuid(), getgid());
+ if (tflag) {
+ protoprivs = getprivs(0, quotatype);
+#ifdef __APPLE__
+ if (protoprivs == (struct quotause *) NULL)
+ exit(0);
+#endif /* __APPLE__ */
+ if (writetimes(protoprivs, tmpfd, quotatype) == 0)
+ exit(1);
+ if (editit(tmpfil)) {
+ /*
+ * Re-open tmpfil to be editor independent.
+ */
+ close(tmpfd);
+ tmpfd = open(tmpfil, O_RDWR, 0);
+ if (tmpfd < 0) {
+ freeprivs(protoprivs);
+ unlink(tmpfil);
+ exit(1);
+ }
+ if (readtimes(protoprivs, tmpfd))
+ putprivs(0, quotatype, protoprivs);
+ }
+ freeprivs(protoprivs);
+ exit(0);
+ }
+ for ( ; argc > 0; argc--, argv++) {
+ if ((id = getentry(*argv, quotatype)) == -1)
+ continue;
+ curprivs = getprivs(id, quotatype);
+#ifdef __APPLE__
+ if (curprivs == (struct quotause *) NULL)
+ exit(0);
+#endif /* __APPLE__ */
+
+
+ if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0) {
+ freeprivs(curprivs);
+ continue;
+ }
+ if (editit(tmpfil)) {
+ /*
+ * Re-open tmpfil to be editor independent.
+ */
+ close(tmpfd);
+ tmpfd = open(tmpfil, O_RDWR, 0);
+ if (tmpfd < 0) {
+ freeprivs(curprivs);
+ unlink(tmpfil);
+ exit(1);
+ }
+ if (readprivs(curprivs, tmpfd))
+ putprivs(id, quotatype, curprivs);
+ }
+ freeprivs(curprivs);
+ }
+ close(tmpfd);
+ unlink(tmpfil);
+ exit(0);
+}
+
+void
+usage()
+{
+ fprintf(stderr, "%s%s%s%s",
+ "Usage: edquota [-u] [-p username] username ...\n",
+ "\tedquota -g [-p groupname] groupname ...\n",
+ "\tedquota [-u] -t\n", "\tedquota -g -t\n");
+#ifdef __APPLE__
+ fprintf(stderr, "\nQuota file editing triggers only on filesystems with a\n");
+ fprintf(stderr, "%s.%s or %s.%s file located at its root.\n",
+ QUOTAOPSNAME, qfextension[USRQUOTA],
+ QUOTAOPSNAME, qfextension[GRPQUOTA]);
+#endif /* __APPLE__ */
+ exit(1);
+}
+
+/*
+ * This routine converts a name for a particular quota type to
+ * an identifier. This routine must agree with the kernel routine
+ * getinoquota as to the interpretation of quota types.
+ */
+int
+getentry(name, quotatype)
+ char *name;
+ int quotatype;
+{
+ struct passwd *pw;
+ struct group *gr;
+
+ if (alldigits(name))
+ return (atoi(name));
+ switch(quotatype) {
+ case USRQUOTA:
+ if ((pw = getpwnam(name)) != NULL)
+ return (pw->pw_uid);
+ fprintf(stderr, "%s: no such user\n", name);
+ break;
+ case GRPQUOTA:
+ if ((gr = getgrnam(name)))
+ return (gr->gr_gid);
+ fprintf(stderr, "%s: no such group\n", name);
+ break;
+ default:
+ fprintf(stderr, "%d: unknown quota type\n", quotatype);
+ break;
+ }
+ sleep(1);
+ return (-1);
+}
+
+/*
+ * Collect the requested quota information.
+ */
+#ifdef __APPLE__
+struct quotause *
+getprivs(id, quotatype)
+ register uid_t id;
+ int quotatype;
+{
+ struct statfs *fst;
+ register struct quotause *qup, *quptail;
+ struct quotause *quphead;
+ int qcmd, fd;
+ size_t qupsize;
+ char *qfpathname;
+ size_t qfpathname_len;
+ static int warned = 0;
+ int nfst, i;
+ extern int errno;
+
+
+ quptail = quphead = (struct quotause *)0;
+ qcmd = QCMD(Q_GETQUOTA, quotatype);
+
+ nfst = getmntinfo(&fst, MNT_WAIT);
+ if (nfst==0) {
+ fprintf(stderr, "edquota: no mounted filesystems\n");
+ exit(1);
+ }
+
+ for (i=0; i<nfst; i++) {
+ if (strcmp(fst[i].f_fstypename, "hfs")) {
+ continue;
+ }
+ if (!hasquota(&fst[i], quotatype, &qfpathname))
+ continue;
+ qfpathname_len = strlen(qfpathname);
+ qupsize = sizeof(*qup) + qfpathname_len;
+ if ((qup = (struct quotause *)malloc(qupsize)) == NULL) {
+ fprintf(stderr, "edquota: out of memory\n");
+ exit(2);
+ }
+ if (quotactl(fst[i].f_mntonname, qcmd, id, (char *)&qup->dqblk) != 0) {
+ if (errno == ENOTSUP && !warned) {
+ warned++;
+ fprintf(stderr, "Warning: %s\n",
+ "Quotas are not compiled into this kernel");
+ sleep(3);
+ }
+ if ((fd = open(qfpathname, O_RDONLY)) < 0) {
+ fd = open(qfpathname, O_RDWR|O_CREAT, 0640);
+ if (fd < 0 && errno != ENOENT) {
+ perror(qfpathname);
+ free(qup);
+ continue;
+ }
+ fprintf(stderr, "Creating quota file %s\n",
+ qfpathname);
+ sleep(3);
+ (void) fchown(fd, getuid(),
+ getentry(quotagroup, GRPQUOTA));
+ (void) fchmod(fd, 0640);
+ if (qfinit(fd, &fst[i], quotatype)) {
+ perror(qfpathname);
+ close(fd);
+ free(qup);
+ continue;
+ }
+ }
+ if (qflookup(fd, id, quotatype, &qup->dqblk) != 0) {
+ fprintf(stderr, "edquota: lookup error in ");
+ perror(qfpathname);
+ close(fd);
+ free(qup);
+ continue;
+ }
+ close(fd);
+ }
+ strlcpy(qup->qfname, qfpathname, qfpathname_len); // malloc'd size is correct for this
+ strlcpy(qup->fsname, fst[i].f_mntonname, sizeof(qup->fsname));
+
+ if (quphead == NULL)
+ quphead = qup;
+ else
+ quptail->next = qup;
+ quptail = qup;
+ qup->next = 0;
+ }
+ return (quphead);
+}
+#else
+struct quotause *
+getprivs(id, quotatype)
+ register long id;
+ int quotatype;
+{
+ register struct fstab *fs;
+ register struct quotause *qup, *quptail;
+ struct quotause *quphead;
+ int qcmd, fd;
+ size_t qupsize;
+ char *qfpathname;
+ size_t qfpathname_len;
+ static int warned = 0;
+ extern int errno;
+
+ setfsent();
+ quphead = (struct quotause *)0;
+ qcmd = QCMD(Q_GETQUOTA, quotatype);
+ while (fs = getfsent()) {
+ if (!hasquota(fs, quotatype, &qfpathname))
+ continue;
+ qfpathname_len = strlen(qfpathname);
+ qupsize = sizeof(*qup) + qfpathname_len;
+ if ((qup = (struct quotause *)malloc(qupsize)) == NULL) {
+ fprintf(stderr, "edquota: out of memory\n");
+ exit(2);
+ }
+ if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
+ if (errno == ENOTSUP && !warned) {
+ warned++;
+ fprintf(stderr, "Warning: %s\n",
+ "Quotas are not compiled into this kernel");
+ sleep(3);
+ }
+ if ((fd = open(qfpathname, O_RDONLY)) < 0) {
+ fd = open(qfpathname, O_RDWR|O_CREAT, 0640);
+ if (fd < 0 && errno != ENOENT) {
+ perror(qfpathname);
+ free(qup);
+ continue;
+ }
+ fprintf(stderr, "Creating quota file %s\n",
+ qfpathname);
+ sleep(3);
+ (void) fchown(fd, getuid(),
+ getentry(quotagroup, GRPQUOTA));
+ (void) fchmod(fd, 0640);
+ }
+ lseek(fd, (off_t)(id * sizeof(struct dqblk)), L_SET);
+ switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
+ case 0: /* EOF */
+ /*
+ * Convert implicit 0 quota (EOF)
+ * into an explicit one (zero'ed dqblk)
+ */
+ bzero((caddr_t)&qup->dqblk,
+ sizeof(struct dqblk));
+ break;
+
+ case sizeof(struct dqblk): /* OK */
+ break;
+
+ default: /* ERROR */
+ fprintf(stderr, "edquota: read error in ");
+ perror(qfpathname);
+ close(fd);
+ free(qup);
+ continue;
+ }
+ close(fd);
+ }
+ strlcpy(qup->qfname, qfpathname, qfpathname_len); // malloc'd size is correct for this
+ strlcpy(qup->fsname, fs->fs_file, sizeof(qup->fsname));
+
+ if (quphead == NULL)
+ quphead = qup;
+ else
+ quptail->next = qup;
+ quptail = qup;
+ qup->next = 0;
+ }
+ endfsent();
+ return (quphead);
+}
+#endif /* __APPLE */
+
+#ifdef __APPLE__
+#define ONEGIGABYTE (1024*1024*1024)
+/*
+ * Initialize a new quota file.
+ */
+int
+qfinit(fd, fst, type)
+ int fd;
+ struct statfs *fst;
+ int type;
+{
+ struct dqfilehdr dqhdr = {0};
+ u_int64_t fs_size;
+ int64_t max = 0;
+
+ /*
+ * Calculate the size of the hash table from the size of
+ * the file system. Note that the open addressing hashing
+ * used by the quota file assumes that this table will not
+ * be more than 90% full.
+ */
+ fs_size = (u_int64_t)fst->f_blocks * (u_int64_t)fst->f_bsize;
+
+ if (type == USRQUOTA) {
+ max = QF_USERS_PER_GB * (fs_size / ONEGIGABYTE);
+
+ if (max < QF_MIN_USERS)
+ max = QF_MIN_USERS;
+ else if (max > QF_MAX_USERS)
+ max = QF_MAX_USERS;
+ } else if (type == GRPQUOTA) {
+ max = QF_GROUPS_PER_GB * (fs_size / ONEGIGABYTE);
+
+ if (max < QF_MIN_GROUPS)
+ max = QF_MIN_GROUPS;
+ else if (max > QF_MAX_GROUPS)
+ max = QF_MAX_GROUPS;
+ }
+ /* Round up to a power of 2 */
+ if (max && !powerof2(max)) {
+ int64_t x = max;
+ max = 4;
+ while (x>>1 != 1) {
+ x = x >> 1;
+ max = max << 1;
+ }
+ }
+
+ (void) ftruncate(fd, (off_t)((max + 1) * sizeof(struct dqblk)));
+ dqhdr.dqh_magic = OSSwapHostToBigInt32(quotamagic[type]);
+ dqhdr.dqh_version = OSSwapHostToBigConstInt32(QF_VERSION);
+ dqhdr.dqh_maxentries = OSSwapHostToBigInt32((int32_t)max);
+ dqhdr.dqh_btime = OSSwapHostToBigConstInt32(MAX_DQ_TIME);
+ dqhdr.dqh_itime = OSSwapHostToBigConstInt32(MAX_IQ_TIME);
+ memmove(dqhdr.dqh_string, QF_STRING_TAG, strlen(QF_STRING_TAG));
+ (void) lseek(fd, 0, L_SET);
+ (void) write(fd, &dqhdr, sizeof(dqhdr));
+
+ return (0);
+}
+
+/*
+ * Lookup an entry in a quota file.
+ */
+int
+qflookup(fd, id, type, dqbp)
+ int fd;
+ uid_t id;
+ int type;
+ struct dqblk *dqbp;
+{
+ struct dqfilehdr dqhdr;
+ int i, skip, last, m;
+ int mask;
+
+ bzero(dqbp, sizeof(struct dqblk));
+
+ if (id == 0)
+ return (0);
+
+ lseek(fd, 0, L_SET);
+ if (read(fd, &dqhdr, sizeof(struct dqfilehdr)) != sizeof(struct dqfilehdr))
+ return (-1);
+
+ /* Sanity check the quota file header. */
+ if ((OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type]) ||
+ (OSSwapBigToHostInt32(dqhdr.dqh_version) > 1) ||
+ (!powerof2(OSSwapBigToHostInt32(dqhdr.dqh_maxentries)))) {
+ fprintf(stderr, "quota: invalid quota file header\n");
+ return (-1);
+ }
+
+ m = OSSwapBigToHostInt32(dqhdr.dqh_maxentries);
+ mask = m - 1;
+ i = dqhash1(id, dqhashshift(m), mask);
+ skip = dqhash2(id, mask);
+
+ for (last = (i + (m-1) * skip) & mask;
+ i != last;
+ i = (i + skip) & mask) {
+ lseek(fd, dqoffset(i), L_SET);
+ if (read(fd, dqbp, sizeof(struct dqblk)) < sizeof(struct dqblk))
+ return (-1);
+ /*
+ * Stop when an empty entry is found
+ * or we encounter a matching id.
+ */
+ if (dqbp->dqb_id == 0 || OSSwapBigToHostInt32(dqbp->dqb_id) == id)
+ break;
+ }
+ /* Put data in host native byte order. */
+ dqbp->dqb_bhardlimit = OSSwapBigToHostInt64(dqbp->dqb_bhardlimit);
+ dqbp->dqb_bsoftlimit = OSSwapBigToHostInt64(dqbp->dqb_bsoftlimit);
+ dqbp->dqb_curbytes = OSSwapBigToHostInt64(dqbp->dqb_curbytes);
+ dqbp->dqb_ihardlimit = OSSwapBigToHostInt32(dqbp->dqb_ihardlimit);
+ dqbp->dqb_isoftlimit = OSSwapBigToHostInt32(dqbp->dqb_isoftlimit);
+ dqbp->dqb_curinodes = OSSwapBigToHostInt32(dqbp->dqb_curinodes);
+ dqbp->dqb_btime = OSSwapBigToHostInt32(dqbp->dqb_btime);
+ dqbp->dqb_itime = OSSwapBigToHostInt32(dqbp->dqb_itime);
+ dqbp->dqb_id = OSSwapBigToHostInt32(dqbp->dqb_id);
+
+ return (0);
+}
+#endif /* __APPLE */
+
+
+/*
+ * Store the requested quota information.
+ */
+void
+putprivs(id, quotatype, quplist)
+ uid_t id;
+ int quotatype;
+ struct quotause *quplist;
+{
+ register struct quotause *qup;
+ int qcmd, fd;
+
+ qcmd = QCMD(Q_SETQUOTA, quotatype);
+ for (qup = quplist; qup; qup = qup->next) {
+ if (quotactl(qup->fsname, qcmd, id, (char *)&qup->dqblk) == 0)
+ continue;
+#ifdef __APPLE__
+ if ((fd = open(qup->qfname, O_RDWR)) < 0) {
+ perror(qup->qfname);
+ } else {
+ if (qfupdate(fd, id, quotatype, &qup->dqblk) != 0) {
+ fprintf(stderr, "edquota: ");
+ perror(qup->qfname);
+ }
+#else
+ if ((fd = open(qup->qfname, O_WRONLY)) < 0) {
+ perror(qup->qfname);
+ } else {
+ lseek(fd,
+ (off_t)(id * (long)sizeof (struct dqblk)), L_SET);
+ if (write(fd, &qup->dqblk, sizeof (struct dqblk)) !=
+ sizeof (struct dqblk)) {
+ fprintf(stderr, "edquota: ");
+ perror(qup->qfname);
+ }
+#endif /* __APPLE */
+ close(fd);
+ }
+ }
+}
+
+#ifdef __APPLE__
+/*
+ * Update an entry in a quota file.
+ */
+int
+qfupdate(fd, id, type, dqbp)
+ int fd;
+ uid_t id;
+ int type;
+ struct dqblk *dqbp;
+{
+ struct dqblk dqbuf;
+ struct dqfilehdr dqhdr;
+ int i, skip, last, m;
+ unsigned int mask;
+
+ if (id == 0)
+ return (0);
+
+ lseek(fd, 0, L_SET);
+ if (read(fd, &dqhdr, sizeof(struct dqfilehdr)) != sizeof(struct dqfilehdr))
+ return (-1);
+
+ /* Sanity check the quota file header. */
+ if ((OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type]) ||
+ (OSSwapBigToHostInt32(dqhdr.dqh_version) > QF_VERSION) ||
+ (!powerof2(OSSwapBigToHostInt32(dqhdr.dqh_maxentries)))) {
+ fprintf(stderr, "quota: invalid quota file header\n");
+ return (EINVAL);
+ }
+
+ m = OSSwapBigToHostInt32(dqhdr.dqh_maxentries);
+ mask = m - 1;
+ i = dqhash1(id, dqhashshift(m), mask);
+ skip = dqhash2(id, mask);
+
+ for (last = (i + (m-1) * skip) & mask;
+ i != last;
+ i = (i + skip) & mask) {
+ lseek(fd, dqoffset(i), L_SET);
+ if (read(fd, &dqbuf, sizeof(struct dqblk)) < sizeof(struct dqblk))
+ return (-1);
+ /*
+ * Stop when an empty entry is found
+ * or we encounter a matching id.
+ */
+ if (dqbuf.dqb_id == 0 || OSSwapBigToHostInt32(dqbuf.dqb_id) == id) {
+ /* Convert buffer to big endian before writing. */
+ struct dqblk tblk;
+
+ tblk.dqb_bhardlimit = OSSwapHostToBigInt64(dqbp->dqb_bhardlimit);
+ tblk.dqb_bsoftlimit = OSSwapHostToBigInt64(dqbp->dqb_bsoftlimit);
+ tblk.dqb_curbytes = OSSwapHostToBigInt64(dqbp->dqb_curbytes);
+ tblk.dqb_ihardlimit = OSSwapHostToBigInt32(dqbp->dqb_ihardlimit);
+ tblk.dqb_isoftlimit = OSSwapHostToBigInt32(dqbp->dqb_isoftlimit);
+ tblk.dqb_curinodes = OSSwapHostToBigInt32(dqbp->dqb_curinodes);
+ tblk.dqb_btime = OSSwapHostToBigInt32((int)dqbp->dqb_btime);
+ tblk.dqb_itime = OSSwapHostToBigInt32((int)dqbp->dqb_itime);
+ tblk.dqb_id = OSSwapHostToBigInt32(id);
+
+ lseek(fd, dqoffset(i), L_SET);
+ if (write(fd, &tblk, sizeof (struct dqblk)) !=
+ sizeof (struct dqblk)) {
+ return (-1);
+ }
+ return (0);
+ }
+ }
+ errno = ENOSPC;
+ return (-1);
+}
+#endif /* __APPLE__ */
+
+/*
+ * Take a list of priviledges and get it edited.
+ */
+int
+editit(tmpfile)
+ char *tmpfile;
+{
+ int omask;
+ int pid, stat;
+ extern char *getenv();
+
+ omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
+ top:
+ if ((pid = fork()) < 0) {
+ extern int errno;
+
+ if (errno == EPROCLIM) {
+ fprintf(stderr, "You have too many processes\n");
+ return(0);
+ }
+ if (errno == EAGAIN) {
+ sleep(1);
+ goto top;
+ }
+ perror("fork");
+ return (0);
+ }
+ if (pid == 0) {
+ register char *ed;
+ struct passwd *pwd = getpwuid(getuid());
+ gid_t newgid = getgid();
+
+ setgid(newgid);
+ if (pwd) initgroups(pwd->pw_name, newgid);
+ setuid(getuid());
+ sigsetmask(omask);
+
+ if ((ed = getenv("EDITOR")) == (char *)0)
+ ed = _PATH_VI;
+ execlp(ed, ed, tmpfile, NULL);
+ perror(ed);
+ exit(1);
+ }
+ waitpid(pid, &stat, 0);
+ sigsetmask(omask);
+ if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0)
+ return (0);
+ return (1);
+}
+
+/*
+ * Convert a quotause list to an ASCII file.
+ */
+int
+writeprivs(quplist, outfd, name, quotatype)
+ struct quotause *quplist;
+ int outfd;
+ char *name;
+ int quotatype;
+{
+ register struct quotause *qup;
+ FILE *fd;
+
+ ftruncate(outfd, 0);
+ lseek(outfd, 0, L_SET);
+ if ((fd = fdopen(dup(outfd), "w")) == NULL) {
+ fprintf(stderr, "edquota: ");
+ perror(tmpfil);
+ exit(1);
+ }
+ fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name);
+ for (qup = quplist; qup; qup = qup->next) {
+#ifdef __APPLE__
+ fprintf(fd, "%s: %s %qd, limits (soft = %qd, hard = %qd)\n",
+ qup->fsname, "1K blocks in use:",
+ qup->dqblk.dqb_curbytes / 1024,
+ qup->dqblk.dqb_bsoftlimit / 1024,
+ qup->dqblk.dqb_bhardlimit / 1024);
+#else
+ fprintf(fd, "%s: %s %d, limits (soft = %d, hard = %d)\n",
+ qup->fsname, "blocks in use:",
+ dbtob(qup->dqblk.dqb_curblocks) / 1024,
+ dbtob(qup->dqblk.dqb_bsoftlimit) / 1024,
+ dbtob(qup->dqblk.dqb_bhardlimit) / 1024);
+#endif /* __APPLE__ */
+
+ fprintf(fd, "%s %d, limits (soft = %d, hard = %d)\n",
+ "\tinodes in use:", qup->dqblk.dqb_curinodes,
+ qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit);
+ }
+ fclose(fd);
+ return (1);
+}
+
+/*
+ * Merge changes to an ASCII file into a quotause list.
+ */
+int
+readprivs(quplist, infd)
+ struct quotause *quplist;
+ int infd;
+{
+ register struct quotause *qup;
+ FILE *fd;
+ int cnt;
+ register char *cp;
+ struct dqblk dqblk;
+ char fsp[BUFSIZ], line1[BUFSIZ], line2[BUFSIZ];
+
+ lseek(infd, 0, L_SET);
+ fd = fdopen(dup(infd), "r");
+ if (fd == NULL) {
+ fprintf(stderr, "Can't re-read temp file!!\n");
+ return (0);
+ }
+ /*
+ * Discard title line, then read pairs of lines to process.
+ */
+ (void) fgets(line1, sizeof (line1), fd);
+ while (fgets(line1, sizeof (line1), fd) != NULL &&
+ fgets(line2, sizeof (line2), fd) != NULL) {
+ cp = strstr(line1, ": 1K blocks in use:");
+ if (cp == NULL) {
+ fprintf(stderr, "%s: bad format for line\n", line1);
+ return 0;
+ }
+ /* Copy up to the template text */
+ strlcpy(fsp, line1, cp - line1 + 1);
+ /* And point cp right after it. */
+ cp = line1 + strlen(fsp) + 1;
+#ifdef __APPLE__
+ /* We expect input to be in 1K blocks */
+ cnt = sscanf(cp,
+ " 1K blocks in use: %qd, limits (soft = %qd, hard = %qd)",
+ &dqblk.dqb_curbytes, &dqblk.dqb_bsoftlimit,
+ &dqblk.dqb_bhardlimit);
+ if (cnt != 3) {
+ fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
+ return (0);
+ }
+
+ /* convert default 1K blocks to byte count */
+ dqblk.dqb_curbytes = dqblk.dqb_curbytes * 1024;
+ dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit * 1024;
+ dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit * 1024;
+#else
+ cnt = sscanf(cp,
+ " blocks in use: %d, limits (soft = %d, hard = %d)",
+ &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit,
+ &dqblk.dqb_bhardlimit);
+ if (cnt != 3) {
+ fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
+ return (0);
+ }
+ dqblk.dqb_curblocks = btodb(dqblk.dqb_curblocks * 1024);
+ dqblk.dqb_bsoftlimit = btodb(dqblk.dqb_bsoftlimit * 1024);
+ dqblk.dqb_bhardlimit = btodb(dqblk.dqb_bhardlimit * 1024);
+#endif /* __APPLE__ */
+
+ if ((cp = strtok(line2, "\n")) == NULL) {
+ fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
+ return (0);
+ }
+ cnt = sscanf(cp,
+ "\tinodes in use: %d, limits (soft = %d, hard = %d)",
+ &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit,
+ &dqblk.dqb_ihardlimit);
+ if (cnt != 3) {
+ fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
+ return (0);
+ }
+ for (qup = quplist; qup; qup = qup->next) {
+ if (strcmp(fsp, qup->fsname))
+ continue;
+ /*
+ * Cause time limit to be reset when the quota
+ * is next used if previously had no soft limit
+ * or were under it, but now have a soft limit
+ * and are over it.
+ */
+#ifdef __APPLE__
+ if (dqblk.dqb_bsoftlimit &&
+ qup->dqblk.dqb_curbytes >= dqblk.dqb_bsoftlimit &&
+ (qup->dqblk.dqb_bsoftlimit == 0 ||
+ qup->dqblk.dqb_curbytes <
+ qup->dqblk.dqb_bsoftlimit))
+ qup->dqblk.dqb_btime = 0;
+#else
+ if (dqblk.dqb_bsoftlimit &&
+ qup->dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit &&
+ (qup->dqblk.dqb_bsoftlimit == 0 ||
+ qup->dqblk.dqb_curblocks <
+ qup->dqblk.dqb_bsoftlimit))
+ qup->dqblk.dqb_btime = 0;
+#endif /* __APPLE__ */
+ if (dqblk.dqb_isoftlimit &&
+ qup->dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit &&
+ (qup->dqblk.dqb_isoftlimit == 0 ||
+ qup->dqblk.dqb_curinodes <
+ qup->dqblk.dqb_isoftlimit))
+ qup->dqblk.dqb_itime = 0;
+ qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit;
+ qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit;
+ qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit;
+ qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit;
+ qup->flags |= FOUND;
+#ifdef __APPLE__
+ if (dqblk.dqb_curbytes == qup->dqblk.dqb_curbytes &&
+ dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes)
+ break;
+#else
+ if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks &&
+ dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes)
+ break;
+#endif /* __APPLE__ */
+ fprintf(stderr,
+ "%s: cannot change current allocation\n", fsp);
+ break;
+ }
+ }
+ fclose(fd);
+ /*
+ * Disable quotas for any filesystems that have not been found.
+ */
+ for (qup = quplist; qup; qup = qup->next) {
+ if (qup->flags & FOUND) {
+ qup->flags &= ~FOUND;
+ continue;
+ }
+ qup->dqblk.dqb_bsoftlimit = 0;
+ qup->dqblk.dqb_bhardlimit = 0;
+ qup->dqblk.dqb_isoftlimit = 0;
+ qup->dqblk.dqb_ihardlimit = 0;
+ }
+ return (1);
+}
+
+/*
+ * Convert a quotause list to an ASCII file of grace times.
+ */
+int
+writetimes(quplist, outfd, quotatype)
+ struct quotause *quplist;
+ int outfd;
+ int quotatype;
+{
+ register struct quotause *qup;
+ char *cvtstoa();
+ FILE *fd;
+
+ ftruncate(outfd, 0);
+ lseek(outfd, 0, L_SET);
+ if ((fd = fdopen(dup(outfd), "w")) == NULL) {
+ fprintf(stderr, "edquota: ");
+ perror(tmpfil);
+ exit(1);
+ }
+ fprintf(fd, "Time units may be: days, hours, minutes, or seconds\n");
+ fprintf(fd, "Grace period before enforcing soft limits for %ss:\n",
+ qfextension[quotatype]);
+ for (qup = quplist; qup; qup = qup->next) {
+ fprintf(fd, "%s: block grace period: %s, ",
+ qup->fsname, cvtstoa(qup->dqblk.dqb_btime));
+ fprintf(fd, "file grace period: %s\n",
+ cvtstoa(qup->dqblk.dqb_itime));
+ }
+ fclose(fd);
+ return (1);
+}
+
+/*
+ * Merge changes of grace times in an ASCII file into a quotause list.
+ */
+int
+readtimes(quplist, infd)
+ struct quotause *quplist;
+ int infd;
+{
+ register struct quotause *qup;
+ FILE *fd;
+ int cnt;
+ register char *cp;
+ time_t itime, btime, iseconds, bseconds;
+ char *fsp, bunits[10], iunits[10], line1[BUFSIZ];
+
+ lseek(infd, 0, L_SET);
+ fd = fdopen(dup(infd), "r");
+ if (fd == NULL) {
+ fprintf(stderr, "Can't re-read temp file!!\n");
+ return (0);
+ }
+ /*
+ * Discard two title lines, then read lines to process.
+ */
+ (void) fgets(line1, sizeof (line1), fd);
+ (void) fgets(line1, sizeof (line1), fd);
+ while (fgets(line1, sizeof (line1), fd) != NULL) {
+ if ((fsp = strtok(line1, " \t:")) == NULL) {
+ fprintf(stderr, "%s: bad format\n", line1);
+ return (0);
+ }
+ if ((cp = strtok((char *)0, "\n")) == NULL) {
+ fprintf(stderr, "%s: %s: bad format\n", fsp,
+ &fsp[strlen(fsp) + 1]);
+ return (0);
+ }
+ cnt = sscanf(cp,
+ " block grace period: %ld %s file grace period: %ld %s",
+ &btime, bunits, &itime, iunits);
+ if (cnt != 4) {
+ fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
+ return (0);
+ }
+ if (cvtatos(btime, bunits, &bseconds) == 0)
+ return (0);
+ if (cvtatos(itime, iunits, &iseconds) == 0)
+ return (0);
+ for (qup = quplist; qup; qup = qup->next) {
+ if (strcmp(fsp, qup->fsname))
+ continue;
+ qup->dqblk.dqb_btime = (uint32_t) bseconds;
+ qup->dqblk.dqb_itime = (uint32_t) iseconds;
+ qup->flags |= FOUND;
+ break;
+ }
+ }
+ fclose(fd);
+ /*
+ * reset default grace periods for any filesystems
+ * that have not been found.
+ */
+ for (qup = quplist; qup; qup = qup->next) {
+ if (qup->flags & FOUND) {
+ qup->flags &= ~FOUND;
+ continue;
+ }
+ qup->dqblk.dqb_btime = 0;
+ qup->dqblk.dqb_itime = 0;
+ }
+ return (1);
+}
+
+/*
+ * Convert seconds to ASCII times.
+ */
+char *
+cvtstoa(time)
+ time_t time;
+{
+ static char buf[20];
+
+ if (time % (24 * 60 * 60) == 0) {
+ time /= 24 * 60 * 60;
+ snprintf(buf, sizeof(buf), "%d day%s", (int)time, time == 1 ? "" : "s");
+ } else if (time % (60 * 60) == 0) {
+ time /= 60 * 60;
+ snprintf(buf, sizeof(buf), "%d hour%s", (int)time, time == 1 ? "" : "s");
+ } else if (time % 60 == 0) {
+ time /= 60;
+ snprintf(buf, sizeof(buf), "%d minute%s", (int)time, time == 1 ? "" : "s");
+ } else
+ snprintf(buf, sizeof(buf), "%d second%s", (int)time, time == 1 ? "" : "s");
+ return (buf);
+}
+
+/*
+ * Convert ASCII input times to seconds.
+ */
+int
+cvtatos(time, units, seconds)
+ time_t time;
+ char *units;
+ time_t *seconds;
+{
+
+ if (bcmp(units, "second", 6) == 0)
+ *seconds = time;
+ else if (bcmp(units, "minute", 6) == 0)
+ *seconds = time * 60;
+ else if (bcmp(units, "hour", 4) == 0)
+ *seconds = time * 60 * 60;
+ else if (bcmp(units, "day", 3) == 0)
+ *seconds = time * 24 * 60 * 60;
+ else {
+ printf("%s: bad units, specify %s\n", units,
+ "days, hours, minutes, or seconds");
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Free a list of quotause structures.
+ */
+void
+freeprivs(quplist)
+ struct quotause *quplist;
+{
+ register struct quotause *qup, *nextqup;
+
+ for (qup = quplist; qup; qup = nextqup) {
+ nextqup = qup->next;
+ free(qup);
+ }
+}
+
+/*
+ * Check whether a string is completely composed of digits.
+ */
+int
+alldigits(s)
+ register char *s;
+{
+ register int c;
+
+ c = *s++;
+ do {
+ if (!isdigit(c))
+ return (0);
+ } while ((c = *s++));
+ return (1);
+}
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+#ifdef __APPLE__
+int
+hasquota(fst, type, qfnamep)
+ register struct statfs *fst;
+ int type;
+ char **qfnamep;
+{
+ struct stat sb;
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+
+ /*
+ We only support the default path to the
+ on disk quota files.
+ */
+
+ (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname,
+ QUOTAOPSNAME, qfextension[type] );
+ if (stat(buf, &sb) != 0) {
+ /* There appears to be no mount option file */
+ return(0);
+ }
+
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#else
+hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp, *index(), *strtok();
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strlcpy(buf, fs->fs_mntops, sizeof(buf));
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = index(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp) {
+ *qfnamep = cp;
+ return (1);
+ }
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#endif /* __APPLE */
diff --git a/diskdev_cmds/edquota.tproj/pathnames.h b/diskdev_cmds/edquota.tproj/pathnames.h
new file mode 100644
index 0000000..f1aef1c
--- /dev/null
+++ b/diskdev_cmds/edquota.tproj/pathnames.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#undef _PATH_TMP
+#define _PATH_TMP "/tmp/EdP.aXXXXX"
diff --git a/diskdev_cmds/edt_fstab/edt_fstab.c b/diskdev_cmds/edt_fstab/edt_fstab.c
new file mode 100644
index 0000000..42a53fe
--- /dev/null
+++ b/diskdev_cmds/edt_fstab/edt_fstab.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2018-2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+// edt_fstab.c
+//
+// Created on 12/11/2018.
+//
+
+#include <sys/types.h>
+
+#include "edt_fstab.h"
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+
+/* Some APFS specific goop */
+#include <APFS/APFS.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <os/bsd.h>
+#include <sys/stat.h>
+#include <paths.h>
+
+char boot_container[EDTVolumePropertySize] = {};
+char data_volume[EDTVolumePropertySize] = {};
+
+static uint32_t edt_os_environment = EDT_OS_ENV_MAIN;
+
+const char *
+get_boot_container(uint32_t *os_envp)
+{
+ kern_return_t err;
+ CFMutableDictionaryRef fs_info = NULL;
+ CFStringRef container = NULL;
+ CFDataRef os_env = NULL;
+
+ // already got the boot container
+ if (strnlen(boot_container, sizeof(boot_container)) > 0) {
+ *os_envp = edt_os_environment;
+ return boot_container;
+ }
+
+ fs_info = IORegistryEntryFromPath(kIOMasterPortDefault, kEDTFilesystemEntry);
+ if (fs_info == IO_OBJECT_NULL) {
+ fprintf(stderr, "failed to get filesystem info\n");
+ return NULL;
+ }
+
+ // lookup the OS environment being booted, assumes main OS upon failure
+ os_env = IORegistryEntryCreateCFProperty(fs_info, kEDTOSEnvironment, kCFAllocatorDefault, 0);
+ if (os_env) {
+ CFDataGetBytes(os_env, CFRangeMake(0, CFDataGetLength(os_env)), (UInt8*)(&edt_os_environment));
+ CFRelease(os_env);
+ }
+ IOObjectRelease(fs_info);
+ *os_envp = edt_os_environment;
+
+ // lookup the boot container
+ err = APFSContainerGetBootDevice(&container);
+ if (!err) {
+ strcpy(boot_container, _PATH_DEV);
+ CFStringGetCString(container,
+ boot_container + strlen(_PATH_DEV),
+ EDTVolumePropertySize - strlen(_PATH_DEV),
+ kCFStringEncodingUTF8);
+ CFRelease(container);
+ return boot_container;
+ } else {
+ // just a warning if not booting the main OS (rdar://48693021)
+ fprintf(stderr, "%sfailed to get boot device - %s\n",
+ (edt_os_environment == EDT_OS_ENV_MAIN) ? "" : "warning: ",
+ strerror(err_get_code(err)));
+ return NULL;
+ }
+}
+
+const char *
+get_data_volume(void)
+{
+ const char *container = NULL;
+ CFMutableArrayRef matches = NULL;
+ OSStatus status;
+
+ // already got the data volume
+ if (strnlen(data_volume, sizeof(data_volume)) > 0) {
+ return data_volume;
+ }
+
+ // get the boot container
+ if (strlen(boot_container) > 0) {
+ container = boot_container;
+ } else {
+ uint32_t os_env;
+ container = get_boot_container(&os_env);
+ }
+ if (!container) {
+ return NULL;
+ }
+
+ // lookup the data volume
+ status = APFSVolumeRoleFind(container, APFS_VOL_ROLE_DATA, &matches);
+ if (status) {
+ // just a warning if not booting the main OS
+ fprintf(stderr, "%sfailed to lookup data volume - %s\n",
+ (edt_os_environment == EDT_OS_ENV_MAIN) ? "" : "warning: ",
+ strerror(err_get_code(status)));
+ return NULL;
+ } else if (CFArrayGetCount(matches) > 1) {
+ fprintf(stderr, "found multiple data volumes\n");
+ CFRelease(matches);
+ return NULL;
+ } else {
+ CFStringGetCString(CFArrayGetValueAtIndex(matches, 0),
+ data_volume,
+ EDTVolumePropertySize,
+ kCFStringEncodingUTF8);
+ CFRelease(matches);
+ return data_volume;
+ }
+}
+
+int
+get_boot_manifest_hash(char *boot_manifest_hash, size_t boot_manifest_hash_len)
+{
+ kern_return_t err = 0;
+ io_registry_entry_t chosen;
+ CFDataRef bm_hash = NULL;
+ size_t bm_hash_size;
+ uint8_t bm_hash_buf[EDTVolumePropertyMaxSize] = {};
+ const char *hexmap = "0123456789ABCDEF";
+
+ chosen = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/chosen");
+ if (chosen == IO_OBJECT_NULL) {
+ fprintf(stderr, "failed to get chosen info\n");
+ return ENOENT;
+ }
+
+ bm_hash = IORegistryEntryCreateCFProperty(chosen, CFSTR("boot-manifest-hash"), kCFAllocatorDefault, 0);
+ if (!bm_hash) {
+ fprintf(stderr, "failed to get boot-manifest-hash\n");
+ IOObjectRelease(chosen);
+ return ENOENT;
+ } else {
+ bm_hash_size = CFDataGetLength(bm_hash);
+ CFDataGetBytes(bm_hash, CFRangeMake(0, bm_hash_size), bm_hash_buf);
+
+ if (boot_manifest_hash_len < (bm_hash_size * 2 + 1)) {
+ err = EINVAL;
+ } else {
+ // hexdump the hash into input buffer
+ for (size_t i = 0; i < (2 * bm_hash_size); i++)
+ *boot_manifest_hash++ = hexmap[(bm_hash_buf[i / 2] >> ((i % 2) ? 0 : 4)) & 0xf];
+ *boot_manifest_hash = '\0';
+ }
+ CFRelease(bm_hash);
+ IOObjectRelease(chosen);
+ }
+
+ return err;
+}
+#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
diff --git a/diskdev_cmds/edt_fstab/edt_fstab.h b/diskdev_cmds/edt_fstab/edt_fstab.h
new file mode 100644
index 0000000..1fd4926
--- /dev/null
+++ b/diskdev_cmds/edt_fstab/edt_fstab.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+// edt_fstab.h
+//
+// Created on 12/11/2018.
+//
+
+#ifndef edt_fstab_h
+#define edt_fstab_h
+
+#include <TargetConditionals.h>
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+#define RAMDISK_FS_SPEC "ramdisk"
+
+/*
+ * get_boot_container, get_data_volume - return the bsd name of the requested
+ * device upon success. Null otherwise.
+ */
+const char *get_boot_container(uint32_t *os_env);
+const char *get_data_volume(void);
+
+int get_boot_manifest_hash(char *boot_manifest_hash, size_t boot_manifest_hash_len);
+#endif
+
+#endif /* edt_fstab_h */
diff --git a/diskdev_cmds/fdisk.tproj/auto.c b/diskdev_cmds/fdisk.tproj/auto.c
new file mode 100644
index 0000000..155f7ab
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/auto.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Auto partitioning code.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <err.h>
+#include "disk.h"
+#include "mbr.h"
+#include "auto.h"
+
+int AUTO_boothfs __P((disk_t *, mbr_t *));
+int AUTO_hfs __P((disk_t *, mbr_t *));
+int AUTO_dos __P((disk_t *, mbr_t *));
+int AUTO_raid __P((disk_t *, mbr_t *));
+
+/* The default style is the first one in the list */
+struct _auto_style {
+ char *style_name;
+ int (*style_fn)(disk_t *, mbr_t *);
+ char *description;
+} style_fns[] = {
+ {"boothfs", AUTO_boothfs, "8Mb boot plus HFS+ root partition"},
+ {"hfs", AUTO_hfs, "Entire disk as one HFS+ partition"},
+ {"dos", AUTO_dos, "Entire disk as one DOS partition"},
+ {"raid", AUTO_raid, "Entire disk as one 0xAC partition"},
+ {0,0}
+};
+
+void
+AUTO_print_styles(FILE *f)
+{
+ struct _auto_style *fp;
+ int i;
+
+ for (i=0, fp = &style_fns[0]; fp->style_name != NULL; i++, fp++) {
+ fprintf(f, " %-10s %s%s\n", fp->style_name, fp->description, (i==0) ? " (default)" : "");
+ }
+}
+
+
+int
+AUTO_init(disk_t *disk, char *style, mbr_t *mbr)
+{
+ struct _auto_style *fp;
+
+ for (fp = &style_fns[0]; fp->style_name != NULL; fp++) {
+ /* If style is NULL, use the first (default) style */
+ if (style == NULL || strcasecmp(style, fp->style_name) == 0) {
+ return (*fp->style_fn)(disk, mbr);
+ }
+ }
+ warnx("No such auto-partition style %s", style);
+ return AUTO_ERR;
+}
+
+
+static int
+use_whole_disk(disk_t *disk, unsigned char id, mbr_t *mbr)
+{
+ MBR_clear(mbr);
+ mbr->part[0].id = id;
+ mbr->part[0].bs = 63;
+ mbr->part[0].ns = disk->real->size - 63;
+ PRT_fix_CHS(disk, &mbr->part[0], 0);
+ return AUTO_OK;
+}
+
+/* DOS style: one partition for the whole disk */
+int
+AUTO_dos(disk_t *disk, mbr_t *mbr)
+{
+ int cc;
+ cc = use_whole_disk(disk, 0x0C, mbr);
+ if (cc == AUTO_OK) {
+ mbr->part[0].flag = DOSACTIVE;
+ }
+ return cc;
+}
+
+/* HFS style: one partition for the whole disk */
+int
+AUTO_hfs(disk_t *disk, mbr_t *mbr)
+{
+ int cc;
+ cc = use_whole_disk(disk, 0xAF, mbr);
+ if (cc == AUTO_OK) {
+ mbr->part[0].flag = DOSACTIVE;
+ }
+ return cc;
+}
+
+/* One boot partition, one HFS+ root partition */
+int
+AUTO_boothfs (disk_t *disk, mbr_t *mbr)
+{
+ /* Check disk size. */
+ if (disk->real->size < 16 * 2048) {
+ errx(1, "Disk size must be greater than 16Mb");
+ return AUTO_ERR;
+ }
+
+ MBR_clear(mbr);
+
+ /* 8MB boot partition */
+ mbr->part[0].id = 0xAB;
+ mbr->part[0].bs = 63;
+ mbr->part[0].ns = 8 * 1024 * 2;
+ mbr->part[0].flag = DOSACTIVE;
+ PRT_fix_CHS(disk, &mbr->part[0], 0);
+
+ /* Rest of the disk for rooting */
+ mbr->part[1].id = 0xAF;
+ mbr->part[1].bs = (mbr->part[0].bs + mbr->part[0].ns);
+ mbr->part[1].ns = disk->real->size - mbr->part[0].ns - 63;
+ PRT_fix_CHS(disk, &mbr->part[1], 1);
+
+ return AUTO_OK;
+}
+
+
+
+/* RAID style: one 0xAC partition for the whole disk */
+int
+AUTO_raid(disk_t *disk, mbr_t *mbr)
+{
+ return use_whole_disk(disk, 0xAC, mbr);
+}
+
diff --git a/diskdev_cmds/fdisk.tproj/auto.h b/diskdev_cmds/fdisk.tproj/auto.h
new file mode 100644
index 0000000..c9259d4
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/auto.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "mbr.h"
+
+/* Prototypes */
+void AUTO_print_styles __P((FILE *));
+int AUTO_init __P((disk_t *, char *, mbr_t *));
+
+#define AUTO_OK 0
+#define AUTO_ERR -1
diff --git a/diskdev_cmds/fdisk.tproj/cmd.c b/diskdev_cmds/fdisk.tproj/cmd.c
new file mode 100644
index 0000000..41cee77
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/cmd.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/fcntl.h>
+#include "disk.h"
+#include "misc.h"
+#include "user.h"
+#include "part.h"
+#include "cmd.h"
+#include "auto.h"
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+
+int
+Xerase(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ bzero(mbr->part, sizeof(mbr->part));
+ mbr->signature = MBR_SIGNATURE;
+ return (CMD_DIRTY);
+}
+
+int
+Xreinit(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ /* Copy template MBR */
+ MBR_make(tt);
+ MBR_parse(disk, offset, 0, mbr);
+
+ MBR_init(disk, mbr);
+
+ /* Tell em we did something */
+ printf("In memory copy is initialized to:\n");
+ printf("Offset: %d\t", offset);
+ MBR_print(mbr);
+ printf("Use 'write' to update disk.\n");
+
+ return (CMD_DIRTY);
+}
+
+int
+Xauto(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ if (cmd->args[0] == '\0') {
+ printf("usage: auto <style>\n");
+ printf(" where style is one of:\n");
+ AUTO_print_styles(stdout);
+ return (CMD_CONT);
+ }
+
+ if (AUTO_init(disk, cmd->args, mbr) != AUTO_OK) {
+ return (CMD_CONT);
+ }
+ MBR_make(mbr);
+ return (CMD_DIRTY);
+}
+
+int
+Xdisk(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ int maxcyl = 1024;
+ int maxhead = 256;
+ int maxsec = 63;
+
+ /* Print out disk info */
+ DISK_printmetrics(disk);
+
+#if defined (__powerpc__) || defined (__mips__)
+ maxcyl = 9999999;
+ maxhead = 9999999;
+ maxsec = 9999999;
+#endif
+
+ /* Ask for new info */
+ if (ask_yn("Change disk geometry?", 0)) {
+ disk->real->cylinders = ask_num("BIOS Cylinders", ASK_DEC,
+ disk->real->cylinders, 1, maxcyl, NULL);
+ disk->real->heads = ask_num("BIOS Heads", ASK_DEC,
+ disk->real->heads, 1, maxhead, NULL);
+ disk->real->sectors = ask_num("BIOS Sectors", ASK_DEC,
+ disk->real->sectors, 1, maxsec, NULL);
+
+ disk->real->size = disk->real->cylinders * disk->real->heads
+ * disk->real->sectors;
+ }
+
+ return (CMD_CONT);
+}
+
+int
+Xedit(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ int pn, num, ret;
+ prt_t *pp;
+
+ ret = CMD_CONT;
+
+ if (!isdigit(cmd->args[0])) {
+ printf("Invalid argument: %s <partition number>\n", cmd->cmd);
+ return (ret);
+ }
+ pn = atoi(cmd->args) - 1;
+
+ if (pn < 0 || pn > 3) {
+ printf("Invalid partition number.\n");
+ return (ret);
+ }
+
+ /* Print out current table entry */
+ pp = &mbr->part[pn];
+ PRT_print(0, NULL);
+ PRT_print(pn, pp);
+
+#define EDIT(p, f, v, n, m, h) \
+ if ((num = ask_num(p, f, v, n, m, h)) != v) \
+ ret = CMD_DIRTY; \
+ v = num;
+
+ /* Ask for partition type */
+ EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall);
+
+ /* Unused, so just zero out */
+ if (pp->id == DOSPTYP_UNUSED) {
+ memset(pp, 0, sizeof(*pp));
+ printf("Partition %d is disabled.\n", pn + 1);
+ return (ret);
+ }
+
+ /* Change table entry */
+ if (ask_yn("Do you wish to edit in CHS mode?", 0)) {
+ int maxcyl, maxhead, maxsect;
+
+ /* Shorter */
+ maxcyl = disk->real->cylinders - 1;
+ maxhead = disk->real->heads - 1;
+ maxsect = disk->real->sectors;
+
+ /* Get data */
+ EDIT("BIOS Starting cylinder", ASK_DEC, pp->scyl, 0, maxcyl, NULL);
+ EDIT("BIOS Starting head", ASK_DEC, pp->shead, 0, maxhead, NULL);
+ EDIT("BIOS Starting sector", ASK_DEC, pp->ssect, 1, maxsect, NULL);
+ EDIT("BIOS Ending cylinder", ASK_DEC, pp->ecyl, 0, maxcyl, NULL);
+ EDIT("BIOS Ending head", ASK_DEC, pp->ehead, 0, maxhead, NULL);
+ EDIT("BIOS Ending sector", ASK_DEC, pp->esect, 1, maxsect, NULL);
+ /* Fix up off/size values */
+ PRT_fix_BN(disk, pp, pn);
+ /* Fix up CHS values for LBA */
+ PRT_fix_CHS(disk, pp, pn);
+ } else {
+ u_int m;
+
+ if (pn == 0) {
+ pp->bs = 63 + offset;
+ } else {
+ if (mbr->part[pn-1].id != 0) {
+ pp->bs = mbr->part[pn-1].bs + mbr->part[pn-1].ns;
+ }
+ }
+ /* Get data */
+ EDIT("Partition offset", ASK_DEC, pp->bs, 0,
+ disk->real->size, NULL);
+ m = MAX(pp->ns, disk->real->size - pp->bs);
+ if ( m > disk->real->size - pp->bs) {
+ /* dont have default value extend beyond end of disk */
+ m = disk->real->size - pp->bs;
+ }
+ pp->ns = m;
+ EDIT("Partition size", ASK_DEC, pp->ns, 1,
+ m, NULL);
+
+ /* Fix up CHS values */
+ PRT_fix_CHS(disk, pp, pn);
+ }
+#undef EDIT
+ return (ret);
+}
+
+int
+Xsetpid(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ int pn, num, ret;
+ prt_t *pp;
+
+ ret = CMD_CONT;
+
+ if (!isdigit(cmd->args[0])) {
+ printf("Invalid argument: %s <partition number>\n", cmd->cmd);
+ return (ret);
+ }
+ pn = atoi(cmd->args) - 1;
+
+ if (pn < 0 || pn > 3) {
+ printf("Invalid partition number.\n");
+ return (ret);
+ }
+
+ /* Print out current table entry */
+ pp = &mbr->part[pn];
+ PRT_print(0, NULL);
+ PRT_print(pn, pp);
+
+#define EDIT(p, f, v, n, m, h) \
+ if ((num = ask_num(p, f, v, n, m, h)) != v) \
+ ret = CMD_DIRTY; \
+ v = num;
+
+ /* Ask for partition type */
+ EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall);
+
+#undef EDIT
+ return (ret);
+}
+int
+Xselect(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ static int firstoff = 0;
+ int off;
+ int pn;
+
+ if (!isdigit(cmd->args[0])) {
+ printf("Invalid argument: %s <partition number>\n", cmd->cmd);
+ return (CMD_CONT);
+ }
+
+ pn = atoi(cmd->args) - 1;
+ if (pn < 0 || pn > 3) {
+ printf("Invalid partition number.\n");
+ return (CMD_CONT);
+ }
+
+ off = mbr->part[pn].bs;
+
+ /* Sanity checks */
+ if ((mbr->part[pn].id != DOSPTYP_EXTEND) &&
+ (mbr->part[pn].id != DOSPTYP_EXTENDL)) {
+ printf("Partition %d is not an extended partition.\n", pn + 1);
+ return (CMD_CONT);
+ }
+
+ if (firstoff == 0)
+ firstoff = off;
+
+ if (!off) {
+ printf("Loop to offset 0! Not selected.\n");
+ return (CMD_CONT);
+ } else {
+ printf("Selected extended partition %d\n", pn + 1);
+ printf("New MBR at offset %d.\n", off);
+ }
+
+ /* Recursion is beautifull! */
+ USER_modify(disk, tt, off, firstoff);
+ return (CMD_CONT);
+}
+
+int
+Xprint(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+
+ DISK_printmetrics(disk);
+ printf("Offset: %d\t", offset);
+ MBR_print(mbr);
+
+ return (CMD_CONT);
+}
+
+int
+Xwrite(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ int fd;
+ int shared = 0;
+
+ fd = DISK_openshared(disk->name, O_RDWR, &shared);
+ if(shared) {
+ if(!ask_yn("Device could not be accessed exclusively.\nA reboot will be needed for changes to take effect. OK?", 0)) {
+ close(fd);
+ printf("MBR unchanged\n");
+ return (CMD_CONT);
+ }
+ }
+
+ printf("Writing MBR at offset %d.\n", offset);
+
+ MBR_make(mbr);
+ MBR_write(disk, fd, mbr);
+ close(fd);
+ return (CMD_CLEAN);
+}
+
+int
+Xquit(cmd, disk, r, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *r;
+ mbr_t *tt;
+ int offset;
+{
+
+ /* Nothing to do here */
+ return (CMD_SAVE);
+}
+
+int
+Xabort(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ exit(0);
+
+ /* NOTREACHED */
+ return (CMD_CONT);
+}
+
+
+int
+Xexit(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+
+ /* Nothing to do here */
+ return (CMD_EXIT);
+}
+
+int
+Xhelp(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ cmd_table_t *cmd_table = cmd->table;
+ int i;
+
+ /* Hmm, print out cmd_table here... */
+ for (i = 0; cmd_table[i].cmd != NULL; i++)
+ printf("\t%s\t\t%s\n", cmd_table[i].cmd, cmd_table[i].help);
+ return (CMD_CONT);
+}
+
+int
+Xupdate(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ extern char *mbr_binary;
+ /* Update code */
+ memcpy(mbr->code, mbr_binary, MBR_CODE_SIZE);
+ printf("Machine code updated.\n");
+ return (CMD_DIRTY);
+}
+
+int
+Xflag(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ int i, pn = -1;
+
+ /* Parse partition table entry number */
+ if (!isdigit(cmd->args[0])) {
+ printf("Invalid argument: %s <partition number>\n", cmd->cmd);
+ return (CMD_CONT);
+ }
+ pn = atoi(cmd->args) - 1;
+
+ if (pn < 0 || pn > 3) {
+ printf("Invalid partition number.\n");
+ return (CMD_CONT);
+ }
+
+ /* Set active flag */
+ for (i = 0; i < 4; i++) {
+ if (i == pn)
+ mbr->part[i].flag = DOSACTIVE;
+ else
+ mbr->part[i].flag = 0x00;
+ }
+
+ printf("Partition %d marked active.\n", pn + 1);
+ return (CMD_DIRTY);
+}
+
+int
+Xmanual(cmd, disk, mbr, tt, offset)
+ cmd_t *cmd;
+ disk_t *disk;
+ mbr_t *mbr;
+ mbr_t *tt;
+ int offset;
+{
+ system("man 8 fdisk");
+ return (CMD_CONT);
+}
diff --git a/diskdev_cmds/fdisk.tproj/cmd.h b/diskdev_cmds/fdisk.tproj/cmd.h
new file mode 100644
index 0000000..0c2b727
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/cmd.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CMD_H
+#define _CMD_H
+
+/* Includes */
+#include "disk.h"
+#include "mbr.h"
+
+
+/* Constants (returned by cmd funs) */
+#define CMD_EXIT 0x0000
+#define CMD_SAVE 0x0001
+#define CMD_CONT 0x0002
+#define CMD_CLEAN 0x0003
+#define CMD_DIRTY 0x0004
+
+
+/* Data types */
+struct _cmd_table_t;
+typedef struct _cmd_t {
+ struct _cmd_table_t *table;
+ char cmd[10];
+ char args[100];
+} cmd_t;
+
+typedef struct _cmd_table_t {
+ char *cmd;
+ int (*fcn)(cmd_t *, disk_t *, mbr_t *, mbr_t *, int);
+ char *help;
+} cmd_table_t;
+
+
+/* Prototypes */
+int Xerase __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xreinit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xauto __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xdisk __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xmanual __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xedit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xsetpid __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xselect __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xprint __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xwrite __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xexit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xquit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xabort __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xhelp __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xflag __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+int Xupdate __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int));
+
+#endif /* _CMD_H */
+
+
diff --git a/diskdev_cmds/fdisk.tproj/disk.c b/diskdev_cmds/fdisk.tproj/disk.c
new file mode 100644
index 0000000..2d04113
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/disk.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2002, 2012 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997, 2001 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <util.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/reboot.h>
+#include <sys/disk.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#ifdef __i386__
+#include <pexpert/i386/boot.h>
+#endif
+#include "disk.h"
+
+int
+DISK_open(disk, mode)
+ char *disk;
+ int mode;
+{
+ int fd;
+ struct stat st;
+
+ fd = open(disk, mode);
+ if (fd == -1)
+ err(1, "%s", disk);
+ if (fstat(fd, &st) == -1)
+ err(1, "%s", disk);
+ /* Don't be so picky about needing a character device */
+ if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode))
+ errx(1, "%s is not a character device or a regular file", disk);
+ return (fd);
+}
+
+int
+DISK_openshared(disk, mode, shared)
+ char *disk;
+ int mode;
+ int *shared;
+{
+ int fd;
+ struct stat st;
+ *shared = 0;
+
+ fd = open(disk, mode|O_EXLOCK);
+ if (fd == -1) {
+ // if we can't have exclusive access, attempt
+ // to gracefully degrade to shared access
+ fd = open(disk, mode|O_SHLOCK);
+ if(fd == -1)
+ err(1, "%s", disk);
+
+ *shared = 1;
+ }
+
+ if (fstat(fd, &st) == -1)
+ err(1, "%s", disk);
+ /* Don't be so picky about needing a character device */
+ if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode))
+ errx(1, "%s is not a character device or a regular file", disk);
+ return (fd);
+}
+
+int
+DISK_close(fd)
+ int fd;
+{
+
+ return (close(fd));
+}
+
+/* Given a size in the metrics,
+ * fake up a CHS geometry.
+ */
+void
+DISK_fake_CHS(DISK_metrics *lm)
+{
+ int heads = 4;
+ int spt = 63;
+ int cylinders = (lm->size / heads / spt);
+
+ while (cylinders > 1024 && heads < 256) {
+ heads *= 2;
+ cylinders /= 2;
+ }
+ if (heads == 256) {
+ heads = 255;
+ cylinders = (lm->size / heads / spt);
+ }
+ lm->cylinders = cylinders;
+ lm->heads = heads;
+ lm->sectors = spt;
+}
+
+/* Routine to go after the disklabel for geometry
+ * information. This should work everywhere, but
+ * in the land of PC, things are not always what
+ * they seem.
+ */
+DISK_metrics *
+DISK_getlabelmetrics(name)
+ char *name;
+{
+ DISK_metrics *lm = NULL;
+ long long size;
+ uint32_t sector_size;
+ int fd;
+ struct stat st;
+
+ /* Get label metrics */
+ if ((fd = DISK_open(name, O_RDONLY)) != -1) {
+ lm = malloc(sizeof(DISK_metrics));
+
+ if (fstat(fd, &st) == -1)
+ err(1, "%s", name);
+ if (!S_ISREG(st.st_mode) || S_ISBLK(st.st_mode)) {
+ if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size) == -1) {
+ err(1, "Could not get disk block count");
+ free(lm);
+ return NULL;
+ }
+ if (ioctl(fd, DKIOCGETBLOCKSIZE, &sector_size) == -1) {
+ err(1, "Could not get disk block size");
+ free(lm);
+ return NULL;
+ }
+ } else {
+ sector_size = 512;
+ size = st.st_size / sector_size;
+ }
+
+ lm->sector_size = sector_size;
+ lm->size = size;
+ DISK_fake_CHS(lm);
+ DISK_close(fd);
+ }
+
+ return (lm);
+}
+
+/*
+ * Don't try to get BIOS disk metrics.
+ */
+DISK_metrics *
+DISK_getbiosmetrics(name)
+ char *name;
+{
+ return (NULL);
+}
+
+/* This is ugly, and convoluted. All the magic
+ * for disk geo/size happens here. Basically,
+ * the real size is the one we will use in the
+ * rest of the program, the label size is what we
+ * got from the disklabel. If the disklabel fails,
+ * we assume we are working with a normal file,
+ * and should request the user to specify the
+ * geometry he/she wishes to use.
+ */
+int
+DISK_getmetrics(disk, user)
+ disk_t *disk;
+ DISK_metrics *user;
+{
+
+ disk->label = DISK_getlabelmetrics(disk->name);
+ disk->bios = DISK_getbiosmetrics(disk->name);
+
+ /* If user supplied, use that */
+ if (user) {
+ disk->real = user;
+ return (0);
+ }
+
+ /* Fixup bios metrics to include cylinders past 1023 boundary */
+ if(disk->label && disk->bios){
+ int cyls, secs;
+
+ cyls = disk->label->size / (disk->bios->heads * disk->bios->sectors);
+ secs = cyls * (disk->bios->heads * disk->bios->sectors);
+ if (disk->label->size < secs) {
+ errx(1, "BIOS fixup botch (%u sectors)", disk->label->size - secs);
+ }
+ disk->bios->cylinders = cyls;
+ disk->bios->size = secs;
+ }
+
+ /* If we have a (fixed) BIOS geometry, use that */
+ if (disk->bios) {
+ disk->real = disk->bios;
+ return (0);
+ }
+
+ /* If we have a label, use that */
+ if (disk->label) {
+ disk->real = disk->label;
+ return (0);
+ }
+
+ /* Can not get geometry, punt */
+ disk->real = NULL;
+ return (1);
+}
+
+/* Get the disk's native sector size, updating the metrics' sector_size field.
+ */
+ int
+DISK_get_sector_size(disk, user)
+ disk_t *disk;
+ DISK_metrics *user;
+{
+ int ret;
+ int fd;
+ uint32_t sector_size;
+
+ /* Default to 512 bytes per sector, in case of failure. */
+ user->sector_size = 512;
+ ret = 1;
+
+ fd = DISK_open(disk->name, O_RDONLY);
+ if (fd == -1) {
+ err(1, "Could not open %s", disk->name);
+ } else {
+ if (ioctl(fd, DKIOCGETBLOCKSIZE, &sector_size) == -1) {
+ err(1, "Could not get disk block size");
+ } else {
+ user->sector_size = sector_size;
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+int
+DISK_printmetrics(disk)
+ disk_t *disk;
+{
+
+ printf("Disk: %s\t", disk->name);
+ if (disk->real) {
+ printf("geometry: %u/%u/%u [%u sectors]\n", disk->real->cylinders,
+ disk->real->heads, disk->real->sectors, disk->real->size);
+ if (disk->real->sector_size != 512)
+ printf("Sector size: %u bytes\n", disk->real->sector_size);
+ } else {
+ printf("geometry: <none>\n");
+ }
+
+ return (0);
+}
+
diff --git a/diskdev_cmds/fdisk.tproj/disk.h b/diskdev_cmds/fdisk.tproj/disk.h
new file mode 100644
index 0000000..a8a97ef
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/disk.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2002,2012 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DISK_H
+#define _DISK_H
+
+/* Data types */
+typedef struct _DISK_metrics {
+ unsigned int cylinders;
+ unsigned int heads;
+ unsigned int sectors;
+ unsigned int size; /* Number of sectors in disk */
+ unsigned int sector_size; /* Bytes per sector */
+} DISK_metrics;
+
+typedef struct _disk_t {
+ char *name;
+ DISK_metrics *bios; /* Metrics as reported by BIOS (always NULL) */
+ DISK_metrics *label; /* As reported by device ioctls */
+ DISK_metrics *real; /* Metrics we're using (BIOS, ioctls, user-supplied) */
+} disk_t;
+
+/* Prototypes */
+int DISK_open __P((char *, int));
+int DISK_openshared __P((char *, int, int *));
+int DISK_close __P((int));
+int DISK_getmetrics __P((disk_t *, DISK_metrics *));
+int DISK_get_sector_size __P((disk_t *, DISK_metrics *));
+int DISK_printmetrics __P((disk_t *));
+void DISK_fake_CHS __P((DISK_metrics *));
+
+#endif /* _DISK_H */
+
diff --git a/diskdev_cmds/fdisk.tproj/fdisk.8 b/diskdev_cmds/fdisk.tproj/fdisk.8
new file mode 100644
index 0000000..c74c091
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/fdisk.8
@@ -0,0 +1,377 @@
+.\" $OpenBSD: fdisk.8,v 1.38 2002/01/04 21:20:56 kjell Exp $
+.\"
+.\" Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+.\"
+.\" "Portions Copyright (c) 2002 Apple Computer, Inc. All Rights
+.\" Reserved. This file contains Original Code and/or Modifications of
+.\" Original Code as defined in and that are subject to the Apple Public
+.\" Source License Version 1.2 (the 'License'). You may not use this file
+.\" except in compliance with the License. Please obtain a copy of the
+.\" License at http://www.apple.com/publicsource and read it before using
+.\" this file.
+.\"
+.\" The Original Code and all software distributed under the License are
+.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+.\" License for the specific language governing rights and limitations
+.\" under the License."
+.\"
+.\" Copyright (c) 1997 Tobias Weingartner
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Tobias Weingartner.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd January 3, 2002
+.Dt FDISK 8
+.Os
+.Sh NAME
+.Nm fdisk
+.Nd DOS partition maintenance program
+.Sh SYNOPSIS
+.Nm fdisk
+.Op Fl ieu
+.Op Fl f Ar mbrname
+.Op Fl c Ar cylinders
+.Op Fl h Ar heads
+.Op Fl s Ar sectors
+.Op Fl S Ar size
+.Op Fl b Ar size
+.Ar device
+.Sh DESCRIPTION
+In order for the BIOS to boot the kernel, certain conventions must be
+adhered to.
+Sector 0 of a bootable hard disk must contain boot code,
+an MBR partition table, and a magic number (0xAA55).
+These MBR partitions (also
+known as BIOS partitions) can be used to break the disk up into several
+pieces.
+.Pp
+The BIOS loads sector 0 of the boot disk into memory, verifies
+the magic number, and begins executing the code at the first byte.
+The normal DOS MBR boot code searches the MBR partition table for an
+.Dq active
+partition (indicated by a
+.Ql \&*
+in the first column), and if one
+is found, the boot block from that partition is loaded and executed in
+place of the original (MBR) boot block.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl i
+Initialize the MBR sector.
+.It Fl a Ar style
+Specify an automatic partitioning style.
+.It Fl e
+Edit existing MBR sectors.
+.It Fl f Ar mbrname
+Specifies an alternate MBR template file.
+.It Fl u
+Update MBR code, preserving existing partition table.
+.It Fl y
+Do not ask for confirmation before writing.
+.It Fl d
+Dump partition table in a format readable by the -r option.
+.It Fl r
+Read a partition table from the standard input.
+.It Fl t
+Test if the disk is partitioned.
+.It Xo Fl c Ar cylinders ,
+.Fl h Ar heads ,
+.Fl s Ar sectors
+.Xc
+Specifies an alternate BIOS geometry for
+.Nm
+to use.
+.It Fl S Ar size
+Specify the disk size in blocks.
+.It Fl b Ar size
+Specify the number of bytes per disk block.
+.El
+.Pp
+The DOS
+.Nm
+program can be used to divide space on the disk into partitions and set
+one active.
+This
+.Nm
+program serves a similar purpose to the DOS program.
+When called with no special flags, it prints the MBR partition
+table of the specified device, i.e.,
+.Bd -literal
+ # fdisk fd0
+ Disk: fd0 geometry: 80/2/18 [2880 sectors]
+ Offset: 0 Signature: 0xAA55
+ Starting Ending
+ #: id cyl hd sec - cyl hd sec [ start - size]
+ ----------------------------------------------------------------------
+ *1: A6 0 0 1 - 79 1 18 [ 0 - 2880] OpenBSD
+ 2: 00 0 0 0 - 0 0 0 [ 0 - 0] unused
+ 3: A7 0 0 2 - 79 1 18 [ 1 - 2879] NEXTSTEP
+ 4: 00 0 0 0 - 0 0 0 [ 0 - 0] unused
+.Ed
+.Pp
+The geometry displayed is a synthetic geometry unless another geometry
+has been selected using the
+.Fl c ,
+.Fl h ,
+.Fl s ,
+.Fl S ,
+and
+.Fl b
+options.
+In the future,
+.Nm
+will read the BIOS geometry from the IOKit registry.
+.Pp
+In this example,
+the disk is divided into two partitions that happen to fill the disk.
+The first partition overlaps the third partition.
+(Used for debugging purposes.)
+.Bl -tag -width "start/size"
+.It Em "#"
+Number of partition table entry.
+A
+.Dq \&*
+denotes the bootable partition.
+.It Em "id"
+System identifier.
+.Ox
+reserves the
+magic number 166 decimal (A6 in hex).
+If no 166 partition is found, it will use an older
+.Fx
+partition (with a magic number of 165 or A5 in hex).
+.It Em "cyl/hd/sec"
+These fields provide the starting and ending address of the partition
+in BIOS geometry
+.It Em "start/size"
+These fields provide the starting sector and size in sectors of the
+partition in linear block addresses.
+.El
+.Pp
+.Em NOTE :
+The sectors field is
+.Dq 1 based ,
+and the start field is
+.Dq 0 based .
+The CHS values may need to be in the BIOS's geometry
+for older systems to be able to boot and use the drive correctly;
+most modern systems prefer the starting sector and size
+in preference to the CHS values.
+.Pp
+The
+.Fl i
+flag is used to indicate that the partition data is to be initialized.
+In this mode,
+.Nm
+will completely overwrite the primary MBR and partition table, either
+using the default MBR template, or the one specified by the
+.Fl f
+flag.
+.Pp
+In the default template, partition number 1 will be configured as a
+Darwin boot
+partition spanning from cylinder 0, head 1, sector 1, and extending
+for 8 megabytes.
+Partition number 2 will be configured as a
+Darwin HFS
+partition spanning the rest of the disk.
+This mode is designed to initialize an MBR the very first time,
+or when it has been corrupted beyond repair.
+.Pp
+You can specify other default partition styles with the
+.Fl a
+flag. The available styles are:
+.Bl -tag -width "start/size"
+.It Em "boothfs"
+Creates an 8Mb boot partition (type AB hex)
+and makes the rest of the disk
+a Darwin HFS partition (type AF hex).
+.It Em "hfs"
+Makes the entire disk one HFS+ partition (type AF hex).
+.It Em "dos"
+Makes the entire disk one DOS partition (type 0C hex).
+.It Em "raid"
+Makes the entire disk one type AC hex partition.
+.El
+.Pp
+The
+.Fl u
+flag is used to update the MBR code on a given drive.
+The MBR code extends from offset 0x000 to the start of the partition table
+at offset 0x1BE.
+It is similar to the
+.Fl i
+flag, except the existing partition table is preserved. This
+is useful for writing new MBR code onto an existing drive, and is
+equivalent to the DOS command
+.Dq FDISK /MBR .
+Note that this option will overwrite the NT disk signature, if present.
+The
+.Fl u
+and
+.Fl i
+flags may not be specified together.
+.Pp
+The flag
+.Fl e
+is used to modify a partition table using a interactive edit mode of the
+.Nm
+program.
+This mode is designed to allow you to change any partition on the
+drive you choose, including extended partitions.
+It is a very powerful mode,
+but is safe as long as you do not execute the
+.Em write
+command, or answer in the negative (the default) when
+.Nm
+asks you about writing out changes.
+.Sh COMMAND MODE
+When you first enter this mode, you are presented with a prompt, that looks
+like so:
+.Em "fdisk: 0>" .
+This prompt has two important pieces of information for you.
+It will tell
+you if the in-memory copy of the boot block has been modified or not.
+If it has been modified, the prompt will change to look like:
+.Em "fdisk:*0>" .
+The second piece of information pertains to the number given in the prompt.
+This number specifies the disk offset of the currently selected boot block
+you are editing.
+This number could be something different that zero when
+you are editing extended partitions.
+The list of commands and their explanations are given below.
+.Bl -tag -width "update"
+.It Em help
+Display a list of commands that
+.Nm
+understands in the interactive edit mode.
+.It Em manual
+Display this manual page.
+.It Em reinit
+Initialize the currently selected, in-memory copy of the
+boot block.
+.It Em auto
+Partition the disk with one of the automatic partition styles.
+.It Em disk
+Display the current drive geometry that
+.Nm
+has
+probed.
+You are given a chance to edit it if you wish.
+.It Em edit
+Edit a given table entry in the memory copy of
+the current boot block.
+You may edit either in BIOS geometry mode,
+or in sector offsets and sizes.
+.It Em setpid
+Change the partition
+identifier of the given partition table entry.
+This command is particularly useful for reassigning
+an existing partition to OpenBSD.
+.It Em flag
+Make the given partition table entry bootable.
+Only one entry can be marked bootable.
+If you wish to boot from an extended
+partition, you will need to mark the partition table entry for the
+extended partition as bootable.
+.It Em update
+Update the machine code in the memory copy of the currently selected
+boot block.
+Note that this option will overwrite the NT disk
+signature, if present.
+.It Em select
+Select and load into memory the boot block pointed
+to by the extended partition table entry in the current boot block.
+.It Em print
+Print the currently selected in-memory copy of the boot
+block and its MBR table to the terminal.
+.It Em write
+Write the in-memory copy of the boot block to disk.
+You will be asked to confirm this operation.
+.It Em exit
+Exit the current level of
+.Nm fdisk ,
+either returning to the
+previously selected in-memory copy of a boot block, or exiting the
+program if there is none.
+.It Em quit
+Exit the current level of
+.Nm fdisk ,
+either returning to the
+previously selected in-memory copy of a boot block, or exiting the
+program if there is none.
+Unlike
+.Em exit
+it does write the modified block out.
+.It Em abort
+Quit program without saving current changes.
+.El
+.Sh NOTES
+The automatic calculation of starting cylinder etc. uses
+a set of figures that represent what the BIOS thinks is the
+geometry of the drive.
+These figures are by default taken from the in-core disklabel, or
+values that
+.Em /boot
+has passed to the kernel, but
+.Nm
+gives you an opportunity to change them if there is a need to.
+This allows the user to create a bootblock that can work with drives
+that use geometry translation under a potentially different BIOS.
+.Pp
+If you hand craft your disk layout,
+please make sure that the
+.Ox
+partition starts on a cylinder boundary.
+(This restriction may be changed in the future.)
+.Pp
+Editing an existing partition is risky, and may cause you to
+lose all the data in that partition.
+.Pp
+You should run this program interactively once or twice to see how it works.
+This is completely safe as long as you answer the
+.Dq write
+questions in the
+negative.
+.Sh FILES
+.Bl -tag -width /usr/mdec/mbr -compact
+.It Pa /usr/mdec/mbr
+default MBR template
+.El
+.Sh SEE ALSO
+.Xr gpt 8 ,
+.Xr pdisk 8
+.Sh BUGS
+There are subtleties
+.Nm
+detects that are not explained in this manual page.
+As well, chances are that some of the subtleties it should detect are being
+steamrolled.
+Caveat Emptor.
diff --git a/diskdev_cmds/fdisk.tproj/fdisk.c b/diskdev_cmds/fdisk.tproj/fdisk.c
new file mode 100644
index 0000000..e7b45cb
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/fdisk.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <paths.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include "disk.h"
+#include "user.h"
+#include "auto.h"
+
+#define _PATH_MBR "/usr/standalone/i386/boot0"
+
+void
+usage()
+{
+ extern char * __progname;
+ fprintf(stderr, "usage: %s "
+ "[-ieu] [-f mbrboot] [-c cyl -h head -s sect] [-S size] [-r] [-a style] disk\n"
+ "\t-i: initialize disk with new MBR\n"
+ "\t-u: update MBR code, preserve partition table\n"
+ "\t-e: edit MBRs on disk interactively\n"
+ "\t-f: specify non-standard MBR template\n"
+ "\t-chs: specify disk geometry\n"
+ "\t-S: specify disk size\n"
+ "\t-r: read partition specs from stdin (implies -i)\n"
+ "\t-a: auto-partition with the given style\n"
+ "\t-d: dump partition table\n"
+ "\t-y: don't ask any questions\n"
+ "\t-t: test if disk is partitioned\n"
+ "`disk' is of the form /dev/rdisk0.\n",
+ __progname);
+ fprintf(stderr, "auto-partition styles:\n");
+ AUTO_print_styles(stderr);
+ exit(1);
+}
+
+char *mbr_binary = NULL;
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int ch, fd;
+ int i_flag = 0, m_flag = 0, u_flag = 0, r_flag = 0, d_flag = 0, y_flag = 0, t_flag = 0;
+ int c_arg = 0, h_arg = 0, s_arg = 0;
+ int size_arg = 0;
+ int block_size_arg = 0;
+ disk_t disk;
+ DISK_metrics *usermetrics;
+ char *mbrfile = _PATH_MBR;
+ mbr_t *mp;
+ char *auto_style = NULL;
+
+ while ((ch = getopt(argc, argv, "ieuf:c:h:s:b:S:ra:dyt")) != -1) {
+ switch(ch) {
+ case 'i':
+ i_flag = 1;
+ break;
+ case 'u':
+ u_flag = 1;
+ break;
+ case 'e':
+ m_flag = 1;
+ break;
+ case 'f':
+ mbrfile = optarg;
+ break;
+ case 'c':
+ c_arg = atoi(optarg);
+ if (c_arg < 1 || c_arg > 262144)
+ errx(1, "Cylinder argument out of range.");
+ break;
+ case 'h':
+ h_arg = atoi(optarg);
+ if (h_arg < 1 || h_arg > 256)
+ errx(1, "Head argument out of range.");
+ break;
+ case 's':
+ s_arg = atoi(optarg);
+ if (s_arg < 1 || s_arg > 63)
+ errx(1, "Sector argument out of range.");
+ break;
+ case 'b':
+ block_size_arg = atoi(optarg);
+ if (block_size_arg & (block_size_arg - 1))
+ errx(1, "Block size argument not a power of two.");
+ if (block_size_arg < 512 || block_size_arg > 4096)
+ errx(1, "Block size argument out of range 512..4096.");
+ break;
+ case 'S':
+ size_arg = atoi(optarg);
+ break;
+ case 'r':
+ r_flag = 1;
+ break;
+ case 'a':
+ auto_style = optarg;
+ break;
+ case 'd':
+ d_flag = 1;
+ break;
+ case 'y':
+ y_flag = 1;
+ break;
+ case 't':
+ t_flag = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Argument checking */
+ if (argc != 1)
+ usage();
+ else
+ disk.name = argv[0];
+
+ if (i_flag && u_flag) errx(1, "-i and -u cannot be specified simultaneously");
+
+ /* Put in supplied geometry if there */
+ if (c_arg | h_arg | s_arg | size_arg | block_size_arg) {
+ usermetrics = malloc(sizeof(DISK_metrics));
+ if (usermetrics != NULL) {
+ if (c_arg && h_arg && s_arg) {
+ usermetrics->cylinders = c_arg;
+ usermetrics->heads = h_arg;
+ usermetrics->sectors = s_arg;
+ if (size_arg) {
+ usermetrics->size = size_arg;
+ } else {
+ usermetrics->size = c_arg * h_arg * s_arg;
+ }
+ } else {
+ if (size_arg) {
+ usermetrics->size = size_arg;
+ DISK_fake_CHS(usermetrics);
+ } else {
+ errx(1, "Please specify a full geometry with [-chs].");
+ }
+ }
+ if (block_size_arg) {
+ usermetrics->sector_size = block_size_arg;
+ } else {
+ DISK_get_sector_size(&disk, usermetrics);
+ }
+ }
+ } else {
+ usermetrics = NULL;
+ }
+
+ /* Get the geometry */
+ disk.real = NULL;
+ if (DISK_getmetrics(&disk, usermetrics))
+ errx(1, "Can't get disk geometry, please use [-chs] to specify.");
+
+ /* If only testing, read MBR and silently exit */
+ if (t_flag) {
+ mbr_t *mbr;
+
+ mp = mbr = MBR_read_all(&disk);
+ while (mp) {
+ if (mp->signature != MBR_SIGNATURE) {
+ MBR_free(mbr);
+ exit(1);
+ }
+ mp = mp->next;
+ }
+ MBR_free(mbr);
+ exit(0);
+ }
+
+ /* If not editing the disk, print out current MBRs on disk */
+ if ((i_flag + r_flag + u_flag + m_flag) == 0) {
+ exit(USER_print_disk(&disk, d_flag));
+ }
+
+ /* Parse mbr template or read partition specs, to pass on later */
+ if (auto_style && r_flag) {
+ errx(1, "Can't specify both -r and -a");
+ }
+
+ mbr_binary = (char *)malloc(MBR_CODE_SIZE);
+ if ((fd = open(mbrfile, O_RDONLY)) == -1) {
+ warn("could not open MBR file %s", mbrfile);
+ bzero(mbr_binary, MBR_CODE_SIZE);
+ } else {
+ int cc;
+ cc = read(fd, mbr_binary, MBR_CODE_SIZE);
+ if (cc < MBR_CODE_SIZE) {
+ err(1, "could not read MBR code");
+ }
+ close(fd);
+ }
+
+ if (u_flag) {
+ /* Don't hose the partition table; just write the boot code */
+ mp = MBR_read_all(&disk);
+ bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);
+ MBR_make(mp);
+ } else if (i_flag) {
+ /* If they didn't specify -a, they'll get the default auto style */
+ mp = MBR_alloc(NULL);
+ if (AUTO_init(&disk, auto_style, mp) != AUTO_OK) {
+ errx(1, "error initializing disk");
+ }
+ bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);
+ MBR_make(mp);
+ } else if (r_flag) {
+ mp = MBR_parse_spec(stdin, &disk);
+ bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);
+ MBR_make(mp);
+ } else {
+ /* Use what's on the disk. */
+ mp = MBR_read_all(&disk);
+ }
+
+ /* Now do what we are supposed to */
+ if (i_flag || r_flag || u_flag) {
+ USER_write(&disk, mp, u_flag, y_flag);
+ }
+
+ if (m_flag) {
+ USER_modify(&disk, mp, 0, 0);
+ }
+
+ if (mbr_binary)
+ free(mbr_binary);
+
+ return (0);
+}
diff --git a/diskdev_cmds/fdisk.tproj/getrawpartition.c b/diskdev_cmds/fdisk.tproj/getrawpartition.c
new file mode 100644
index 0000000..9cfcb35
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/getrawpartition.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: getrawpartition.c,v 1.4 1999/07/02 15:49:12 simonb Exp $");
+#endif
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <util.h>
+
+int
+getrawpartition()
+{
+#if 0
+ int rawpart, mib[2];
+ size_t varlen;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_RAWPARTITION;
+ varlen = sizeof(rawpart);
+ if (sysctl(mib, 2, &rawpart, &varlen, NULL, 0) < 0)
+ return (-1);
+
+ return (rawpart);
+#else
+ return 0 - 'a';
+#endif
+}
diff --git a/diskdev_cmds/fdisk.tproj/mbr.c b/diskdev_cmds/fdisk.tproj/mbr.c
new file mode 100644
index 0000000..90c8809
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/mbr.c
@@ -0,0 +1,553 @@
+/*
+ * Copyright (c) 2002, 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <util.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <memory.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if 0
+#include <sys/dkio.h>
+#endif
+#include <machine/param.h>
+#include "disk.h"
+#include "misc.h"
+#include "mbr.h"
+#include "part.h"
+
+
+void
+MBR_init(disk, mbr)
+ disk_t *disk;
+ mbr_t *mbr;
+{
+ /* Fix up given mbr for this disk */
+ mbr->part[0].flag = 0;
+ mbr->part[1].flag = 0;
+ mbr->part[2].flag = 0;
+#if !defined(DOSPTYP_OPENBSD)
+ mbr->part[3].flag = 0;
+ mbr->signature = MBR_SIGNATURE;
+#else
+
+ mbr->part[3].flag = DOSACTIVE;
+ mbr->signature = DOSMBR_SIGNATURE;
+
+ /* Use whole disk, save for first head, on first cyl. */
+ mbr->part[3].id = DOSPTYP_OPENBSD;
+ mbr->part[3].scyl = 0;
+ mbr->part[3].shead = 1;
+ mbr->part[3].ssect = 1;
+
+ /* Go right to the end */
+ mbr->part[3].ecyl = disk->real->cylinders - 1;
+ mbr->part[3].ehead = disk->real->heads - 1;
+ mbr->part[3].esect = disk->real->sectors;
+
+ /* Fix up start/length fields */
+ PRT_fix_BN(disk, &mbr->part[3], 3);
+
+#if defined(__powerpc__) || defined(__mips__)
+ /* Now fix up for the MS-DOS boot partition on PowerPC. */
+ mbr->part[0].flag = DOSACTIVE; /* Boot from dos part */
+ mbr->part[3].flag = 0;
+ mbr->part[3].ns += mbr->part[3].bs;
+ mbr->part[3].bs = mbr->part[0].bs + mbr->part[0].ns;
+ mbr->part[3].ns -= mbr->part[3].bs;
+ PRT_fix_CHS(disk, &mbr->part[3], 3);
+ if ((mbr->part[3].shead != 1) || (mbr->part[3].ssect != 1)) {
+ /* align the partition on a cylinder boundary */
+ mbr->part[3].shead = 0;
+ mbr->part[3].ssect = 1;
+ mbr->part[3].scyl += 1;
+ }
+ /* Fix up start/length fields */
+ PRT_fix_BN(disk, &mbr->part[3], 3);
+#endif
+#endif
+}
+
+void
+MBR_parse(disk, offset, reloff, mbr)
+ disk_t *disk;
+ off_t offset;
+ off_t reloff;
+ mbr_t *mbr;
+{
+ int i;
+ unsigned char *mbr_buf = mbr->buf;
+
+ memcpy(mbr->code, mbr_buf, MBR_CODE_SIZE);
+ mbr->offset = offset;
+ mbr->reloffset = reloff;
+ mbr->signature = getshort(&mbr_buf[MBR_SIG_OFF]);
+
+ for (i = 0; i < NDOSPART; i++)
+ PRT_parse(disk, &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i],
+ offset, reloff, &mbr->part[i], i);
+}
+
+void
+MBR_make(mbr)
+ mbr_t *mbr;
+{
+ int i;
+ unsigned char *mbr_buf = mbr->buf;
+
+ memcpy(mbr_buf, mbr->code, MBR_CODE_SIZE);
+ putshort(&mbr_buf[MBR_SIG_OFF], mbr->signature);
+
+ for (i = 0; i < NDOSPART; i++)
+ PRT_make(&mbr->part[i], mbr->offset, mbr->reloffset,
+ &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i]);
+}
+
+void
+MBR_print(mbr)
+ mbr_t *mbr;
+{
+ int i;
+
+ /* Header */
+ printf("Signature: 0x%X\n",
+ (int)mbr->signature);
+ PRT_print(0, NULL);
+
+ /* Entries */
+ for (i = 0; i < NDOSPART; i++)
+ PRT_print(i, &mbr->part[i]);
+}
+
+int
+MBR_read(disk, fd, where, mbr)
+ disk_t *disk;
+ int fd;
+ off_t where;
+ mbr_t *mbr;
+{
+ off_t off;
+ int len;
+ int size;
+ unsigned char *buf = mbr->buf;
+
+ size = disk->real->sector_size;
+ where *= size;
+ off = lseek(fd, where, SEEK_SET);
+ if (off != where)
+ return (off);
+ len = read(fd, buf, size);
+ if (len != size)
+ return (len);
+ return (0);
+}
+
+int
+MBR_write(disk, fd, mbr)
+ disk_t *disk;
+ int fd;
+ mbr_t *mbr;
+{
+ off_t off;
+ int len;
+ int size;
+ unsigned char *buf = mbr->buf;
+ off_t where;
+
+ size = disk->real->sector_size;
+ where = mbr->offset * size;
+ off = lseek(fd, where, SEEK_SET);
+ if (off != where)
+ return (off);
+ len = write(fd, buf, size);
+ if (len != size)
+ return (len);
+#if defined(DIOCRLDINFO)
+ (void) ioctl(fd, DIOCRLDINFO, 0);
+#endif
+ return (0);
+}
+
+void
+MBR_pcopy(disk, mbr)
+ disk_t *disk;
+ mbr_t *mbr;
+{
+ /*
+ * Copy partition table from the disk indicated
+ * to the supplied mbr structure
+ */
+
+ int i, fd, offset = 0, reloff = 0;
+ mbr_t *mbrd;
+
+ mbrd = MBR_alloc(NULL);
+ fd = DISK_open(disk->name, O_RDONLY);
+ MBR_read(disk, fd, offset, mbrd);
+ DISK_close(fd);
+ MBR_parse(disk, offset, reloff, mbrd);
+ for (i = 0; i < NDOSPART; i++) {
+ PRT_parse(disk, &mbrd->buf[MBR_PART_OFF +
+ MBR_PART_SIZE * i],
+ offset, reloff, &mbr->part[i], i);
+ PRT_print(i, &mbr->part[i]);
+ }
+ MBR_free(mbrd);
+}
+
+
+static int
+parse_number(char *str, int default_val, int base) {
+ if (str != NULL && *str != '\0') {
+ default_val = strtol(str, NULL, base);
+ }
+ return default_val;
+}
+
+static inline int
+null_arg(char *arg) {
+ if (arg == NULL || *arg == 0)
+ return 1;
+ else
+ return 0;
+}
+
+/* Parse a partition spec into a partition structure.
+ * Spec is of the form:
+ * <start>,<size>,<id>,<bootable>[,<c,h,s>,<c,h,s>]
+ * We require passing in the disk and mbr so we can
+ * set reasonable defaults for values, e.g. "the whole disk"
+ * or "starting after the last partition."
+ */
+#define N_ARGS 10
+static int
+MBR_parse_one_spec(char *line, disk_t *disk, mbr_t *mbr, int pn)
+{
+ int i;
+ char *args[N_ARGS];
+ prt_t *part = &mbr->part[pn];
+ int next_start, next_size;
+
+ /* There are up to 10 arguments. */
+ for (i=0; i<N_ARGS; i++) {
+ char *arg;
+ while (isspace(*line))
+ line++;
+ arg = strsep(&line, ",\n");
+ if (arg == NULL || line == NULL) {
+ break;
+ }
+ args[i] = arg;
+ }
+ for (; i<N_ARGS; i++) {
+ args[i] = NULL;
+ }
+ /* Set reasonable defaults. */
+ if (pn == 0) {
+ next_start = 0;
+ } else {
+ next_start = mbr->part[pn-1].bs + mbr->part[pn-1].ns;
+ }
+ next_size = disk->real->size;
+ for(i=0; i<pn; i++) {
+ next_size -= mbr->part[i].ns;
+ }
+
+ part->id = parse_number(args[2], 0xA8, 16);
+ if (!null_arg(args[3]) && *args[3] == '*') {
+ part->flag = 0x80;
+ } else {
+ part->flag = 0;
+ }
+ /* If you specify the start or end sector,
+ you have to give both. */
+ if ((null_arg(args[0]) && !null_arg(args[1])) ||
+ (!null_arg(args[0]) && null_arg(args[1]))) {
+ errx(1, "You must specify both start and size, or neither");
+ return -1;
+ }
+
+ /* If you specify one of the CHS args,
+ you have to give them all. */
+ if (!null_arg(args[4])) {
+ for (i=5; i<10; i++) {
+ if (null_arg(args[i])) {
+ errx(1, "Either all CHS arguments must be specified, or none");
+ return -1;
+ }
+ }
+
+ part->scyl = parse_number(args[4], 0, 10);
+ part->shead = parse_number(args[5], 0, 10);
+ part->ssect = parse_number(args[6], 0, 10);
+ part->scyl = parse_number(args[7], 0, 10);
+ part->shead = parse_number(args[8], 0, 10);
+ part->ssect = parse_number(args[9], 0, 10);
+ if (null_arg(args[0])) {
+ PRT_fix_BN(disk, part, pn);
+ }
+ } else {
+ /* See if they gave no CHS and no start/end */
+ if (null_arg(args[0])) {
+ errx(1, "You must specify either start sector and size or CHS");
+ return -1;
+ }
+ }
+ if (!null_arg(args[0])) {
+ part->bs = parse_number(args[0], next_start, 10);
+ part->ns = parse_number(args[1], next_size, 10);
+ PRT_fix_CHS(disk, part, pn);
+ }
+ return 0;
+}
+
+
+typedef struct _mbr_chain {
+ mbr_t mbr;
+ struct _mbr_chain *next;
+} mbr_chain_t;
+
+/* Parse some number of MBR spec lines.
+ * Spec is of the form:
+ * <start>,<size>,<id>,<bootable>[,<c,h,s>,<c,h,s>]
+ *
+ */
+mbr_t *
+MBR_parse_spec(FILE *f, disk_t *disk)
+{
+ int lineno;
+ int offset, firstoffset;
+ mbr_t *mbr, *head, *prev_mbr;
+
+ head = mbr = prev_mbr = NULL;
+ firstoffset = 0;
+ do {
+
+ offset = 0;
+ for (lineno = 0; lineno < NDOSPART && !feof(f); lineno++) {
+ char line[256];
+ char *str;
+ prt_t *part;
+
+ do {
+ str = fgets(line, 256, f);
+ } while ((str != NULL) && (*str == '\0'));
+ if (str == NULL) {
+ break;
+ }
+
+ if (mbr == NULL) {
+ mbr = MBR_alloc(prev_mbr);
+ if (head == NULL)
+ head = mbr;
+ }
+
+ if (MBR_parse_one_spec(line, disk, mbr, lineno)) {
+ /* MBR_parse_one_spec printed the error message. */
+ return NULL;
+ }
+ part = &mbr->part[lineno];
+ if ((part->id == DOSPTYP_EXTEND) || (part->id == DOSPTYP_EXTENDL)) {
+ offset = part->bs;
+ if (firstoffset == 0) firstoffset = offset;
+ }
+ }
+ /* If fewer lines than partitions, zero out the rest of the partitions */
+ if (mbr != NULL) {
+ for (; lineno < NDOSPART; lineno++) {
+ bzero(&mbr->part[lineno], sizeof(prt_t));
+ }
+ }
+ prev_mbr = mbr;
+ mbr = NULL;
+ } while (offset >= 0 && !feof(f));
+
+ return head;
+}
+
+void
+MBR_dump(mbr_t *mbr)
+{
+ int i;
+ prt_t *part;
+
+ for (i=0; i<NDOSPART; i++) {
+ part = &mbr->part[i];
+ printf("%d,%d,0x%02X,%c,%u,%u,%u,%u,%u,%u\n",
+ part->bs,
+ part->ns,
+ part->id,
+ (part->flag == 0x80) ? '*' : '-',
+ part->scyl,
+ part->shead,
+ part->ssect,
+ part->ecyl,
+ part->ehead,
+ part->esect);
+ }
+}
+
+mbr_t *
+MBR_alloc(mbr_t *parent)
+{
+ mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
+ bzero(mbr, sizeof(mbr_t));
+ if (parent) {
+ parent->next = mbr;
+ }
+ mbr->signature = MBR_SIGNATURE;
+ return mbr;
+}
+
+void
+MBR_free(mbr_t *mbr)
+{
+ mbr_t *tmp;
+ while (mbr) {
+ tmp = mbr->next;
+ free(mbr);
+ mbr = tmp;
+ }
+}
+
+/* Read and parse all the partition tables on the disk,
+ * including extended partitions.
+ */
+mbr_t *
+MBR_read_all(disk_t *disk)
+{
+ mbr_t *mbr = NULL, *head = NULL;
+ int i, fd, offset, firstoff;
+
+ fd = DISK_open(disk->name, O_RDONLY);
+ firstoff = offset = 0;
+ do {
+ mbr = MBR_alloc(mbr);
+ if (head == NULL) {
+ head = mbr;
+ }
+ MBR_read(disk, fd, offset, mbr);
+ MBR_parse(disk, offset, firstoff, mbr);
+ if (mbr->signature != MBR_SIGNATURE) {
+ /* The MBR signature is invalid. */
+ break;
+ }
+ offset = 0;
+ for (i=0; i<NDOSPART; i++) {
+ prt_t *part = &mbr->part[i];
+ if ((part->id == DOSPTYP_EXTEND) || (part->id == DOSPTYP_EXTENDL)) {
+ offset = part->bs;
+ if (firstoff == 0) {
+ firstoff = offset;
+ }
+ }
+ }
+ } while (offset > 0);
+ DISK_close(fd);
+
+ return head;
+}
+
+
+int
+MBR_write_all(disk_t *disk, mbr_t *mbr)
+{
+ int result = 0;
+ int fd;
+
+ fd = DISK_open(disk->name, O_RDWR);
+ while (mbr) {
+ MBR_make(mbr);
+ result = MBR_write(disk, fd, mbr);
+ if (result)
+ break;
+ mbr = mbr->next;
+ }
+ DISK_close(fd);
+ return result;
+}
+
+void
+MBR_print_all(mbr_t *mbr) {
+ while (mbr) {
+ MBR_print(mbr);
+ mbr = mbr->next;
+ }
+}
+
+void
+MBR_dump_all(mbr_t *mbr) {
+ while (mbr) {
+ MBR_dump(mbr);
+ mbr = mbr->next;
+ }
+}
+
+void
+MBR_clear(mbr_t *mbr) {
+ int i;
+ if (mbr->next) {
+ MBR_free(mbr->next);
+ mbr->next = NULL;
+ }
+ for (i=0; i<4; i++) {
+ bzero(&mbr->part[i], sizeof(mbr->part[i]));
+ }
+ bzero(&mbr->buf, sizeof(mbr->buf));
+}
+
diff --git a/diskdev_cmds/fdisk.tproj/mbr.h b/diskdev_cmds/fdisk.tproj/mbr.h
new file mode 100644
index 0000000..52247ee
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/mbr.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MBR_H
+#define _MBR_H
+
+#include "part.h"
+
+#ifndef NDOSPART
+#define NDOSPART 4
+#define DOSPTYP_UNUSED 0
+#define DOSPTYP_EXTEND 5
+#define DOSPTYP_EXTENDL 15
+#define DOSACTIVE 128
+#endif
+
+/* Various constants */
+#define MBR_CODE_SIZE 0x1BE
+#define MBR_PART_SIZE 0x10
+#define MBR_PART_OFF 0x1BE
+#define MBR_SIG_OFF 0x1FE
+/* MBR_BUF_SIZE is the largest sector size we support */
+#define MBR_BUF_SIZE 4096
+
+#define MBR_SIGNATURE 0xAA55
+
+/* MBR type */
+typedef struct _mbr_t {
+ off_t reloffset; /* the offset of the first extended partition that contains all the rest */
+ off_t offset; /* the absolute offset of this partition */
+ struct _mbr_t *next; /* pointer to the next MBR in an extended partition chain */
+ unsigned char code[MBR_CODE_SIZE];
+ unsigned short signature;
+ prt_t part[NDOSPART];
+ unsigned char buf[MBR_BUF_SIZE];
+} mbr_t;
+
+/* Prototypes */
+void MBR_print_disk __P((char *));
+void MBR_print __P((mbr_t *));
+void MBR_print_all __P((mbr_t *));
+void MBR_parse __P((disk_t *, off_t, off_t, mbr_t *));
+void MBR_make __P((mbr_t *));
+void MBR_init __P((disk_t *, mbr_t *));
+int MBR_read __P((disk_t *,int, off_t, mbr_t *));
+int MBR_write __P((disk_t *,int, mbr_t *));
+void MBR_pcopy __P((disk_t *, mbr_t *));
+mbr_t * MBR_parse_spec __P((FILE *, disk_t *));
+void MBR_dump __P((mbr_t *));
+void MBR_dump_all __P((mbr_t *));
+mbr_t *MBR_alloc __P((mbr_t *));
+void MBR_free __P((mbr_t *));
+mbr_t * MBR_read_all __P((disk_t *));
+int MBR_write_all __P((disk_t *, mbr_t *));
+void MBR_clear __P((mbr_t *));
+
+/* Sanity check */
+#include <machine/param.h>
+#if (DEV_BSIZE != 512)
+#error "DEV_BSIZE != 512, somebody better fix me!"
+#endif
+
+#endif /* _MBR_H */
+
diff --git a/diskdev_cmds/fdisk.tproj/mbrcode.h b/diskdev_cmds/fdisk.tproj/mbrcode.h
new file mode 100644
index 0000000..2b8182e
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/mbrcode.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 2000 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* Largely generated by:
+ * hexdump -ve '8/1 "0x%02x, " "\n"' /usr/mdec/mbr
+ */
+0xfa, 0xea, 0x06, 0x00, 0xc0, 0x07, 0x8c, 0xc8,
+0x8e, 0xd8, 0x8e, 0xd0, 0xbc, 0xfc, 0xff, 0xfb,
+0xb0, 0x53, 0xe8, 0xe2, 0x00, 0xb8, 0xa0, 0x07,
+0x8e, 0xc0, 0x31, 0xf6, 0x31, 0xff, 0xb9, 0x00,
+0x02, 0xfc, 0xf2, 0xa4, 0xea, 0x29, 0x00, 0xa0,
+0x07, 0xb0, 0x52, 0xe8, 0xc9, 0x00, 0x1e, 0x07,
+0x0e, 0x1f, 0xf6, 0xc2, 0x80, 0x75, 0x0b, 0x66,
+0xbe, 0x13, 0x01, 0x00, 0x00, 0xe8, 0xab, 0x00,
+0xb2, 0x80, 0x66, 0xbe, 0xbe, 0x01, 0x00, 0x00,
+0x66, 0xb9, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x4c,
+0xe8, 0xa4, 0x00, 0x8a, 0x44, 0x00, 0x3c, 0x80,
+0x74, 0x18, 0x66, 0x83, 0xc6, 0x10, 0xe2, 0xee,
+0x66, 0xbe, 0x3c, 0x01, 0x00, 0x00, 0xe8, 0x82,
+0x00, 0xfa, 0xf4, 0xb0, 0x2e, 0xe8, 0x87, 0x00,
+0xeb, 0xf7, 0xb0, 0x42, 0xe8, 0x80, 0x00, 0x8b,
+0x14, 0x8b, 0x4c, 0x02, 0x66, 0xb8, 0x01, 0x02,
+0x00, 0x00, 0x31, 0xdb, 0xcd, 0x13, 0x73, 0x13,
+0x80, 0xfa, 0x80, 0x75, 0xaa, 0x66, 0xbe, 0x2f,
+0x01, 0x00, 0x00, 0xe8, 0x55, 0x00, 0xe8, 0x33,
+0x00, 0xeb, 0xce, 0xb0, 0x43, 0xe8, 0x57, 0x00,
+0x66, 0x31, 0xc0, 0x66, 0xbb, 0xfe, 0x01, 0x00,
+0x00, 0x67, 0x8b, 0x03, 0x66, 0x3d, 0x55, 0xaa,
+0x00, 0x00, 0x74, 0x0b, 0x66, 0xbe, 0x52, 0x01,
+0x00, 0x00, 0xe8, 0x2e, 0x00, 0xeb, 0xaa, 0xb0,
+0x47, 0xe8, 0x33, 0x00, 0x66, 0xea, 0x00, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x66, 0xbb,
+0x03, 0x01, 0x00, 0x00, 0x50, 0x88, 0xe0, 0x66,
+0x83, 0xe0, 0x0f, 0xd7, 0xe8, 0x18, 0x00, 0x58,
+0x66, 0x83, 0xe0, 0x0f, 0xd7, 0xe8, 0x0f, 0x00,
+0x5b, 0x58, 0xc3, 0x50, 0xfc, 0xac, 0x84, 0xc0,
+0x74, 0x0f, 0xe8, 0x02, 0x00, 0xeb, 0xf6, 0x50,
+0x53, 0xb4, 0x0e, 0x31, 0xdb, 0x43, 0xcd, 0x10,
+0x5b, 0x58, 0xc3, 0x30, 0x31, 0x32, 0x33, 0x34,
+0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
+0x44, 0x45, 0x46, 0x4d, 0x42, 0x52, 0x20, 0x6f,
+0x6e, 0x20, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79,
+0x20, 0x6f, 0x72, 0x20, 0x6f, 0x6c, 0x64, 0x20,
+0x42, 0x49, 0x4f, 0x53, 0x0d, 0x0a, 0x00, 0x52,
+0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f,
+0x72, 0x0d, 0x0a, 0x00, 0x4e, 0x6f, 0x20, 0x61,
+0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x70, 0x61,
+0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x0d,
+0x0a, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69,
+0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74,
+0x75, 0x72, 0x65, 0x0d, 0x0a, 0x00, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x01, 0x00, 0xa6, 0xff, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x55, 0xaa,
diff --git a/diskdev_cmds/fdisk.tproj/misc.c b/diskdev_cmds/fdisk.tproj/misc.c
new file mode 100644
index 0000000..a477001
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/misc.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc.h"
+
+
+int
+ask_cmd(cmd_t *cmd)
+{
+ char lbuf[100], *cp, *buf;
+
+ /* Get input */
+ if (fgets(lbuf, sizeof lbuf, stdin) == NULL)
+ errx(1, "eof");
+ lbuf[strlen(lbuf)-1] = '\0';
+
+ /* Parse input */
+ buf = lbuf;
+ buf = &buf[strspn(buf, " \t")];
+ cp = &buf[strcspn(buf, " \t")];
+ *cp++ = '\0';
+ strncpy(cmd->cmd, buf, 10);
+ buf = &cp[strspn(cp, " \t")];
+ strncpy(cmd->args, buf, 100);
+
+ return (0);
+}
+
+int
+ask_num(const char *str, int flags, unsigned int dflt, unsigned int low, unsigned int high, void (*help) __P((void)))
+{
+ char lbuf[100], *cp;
+ unsigned int num;
+
+ do {
+again:
+ num = dflt;
+ if (flags == ASK_HEX)
+ printf("%s [%X - %X]: [%X] ", str, low, high, num);
+ else
+ printf("%s [%u - %u]: [%u] ", str, low, high, num);
+ if (help)
+ printf("(? for help) ");
+
+ if (fgets(lbuf, sizeof lbuf, stdin) == NULL)
+ errx(1, "eof");
+ lbuf[strlen(lbuf)-1] = '\0';
+
+ if (help && lbuf[0] == '?') {
+ (*help)();
+ goto again;
+ }
+
+ /* Convert */
+ cp = lbuf;
+ num = strtoul(lbuf, &cp, ((flags==ASK_HEX)?16:10));
+
+ /* Make sure only number present */
+ if (cp == lbuf)
+ num = dflt;
+ if (*cp != '\0') {
+ printf("'%s' is not a valid number.\n", lbuf);
+ num = low - 1;
+ } else if (num < low || num > high) {
+ printf("'%u' is out of range.\n", num);
+ }
+ } while (num < low || num > high);
+
+ return (num);
+}
+
+int
+ask_yn(const char *str, int default_answer)
+{
+ int ch, first;
+
+ printf("%s [%c] ", str, default_answer ? 'y' : 'n');
+ fflush(stdout);
+
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+
+ if (ch == EOF || first == EOF)
+ errx(1, "eof");
+
+ if (first == '\n')
+ return default_answer;
+
+ return (first == 'y' || first == 'Y');
+}
+
+u_int16_t
+getshort(void *p)
+{
+ unsigned char *cp = p;
+
+ return (cp[0] | (cp[1] << 8));
+}
+
+void
+putshort(void *p, u_int16_t l)
+{
+ unsigned char *cp = p;
+
+ *cp++ = l;
+ *cp++ = l >> 8;
+}
+
+u_int32_t
+getlong(void *p)
+{
+ unsigned char *cp = p;
+
+ return (cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24));
+}
+
+void
+putlong(void *p, u_int32_t l)
+{
+ unsigned char *cp = p;
+
+ *cp++ = l;
+ *cp++ = l >> 8;
+ *cp++ = l >> 16;
+ *cp++ = l >> 24;
+}
diff --git a/diskdev_cmds/fdisk.tproj/misc.h b/diskdev_cmds/fdisk.tproj/misc.h
new file mode 100644
index 0000000..d3fa6ae
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/misc.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MISC_H
+#define _MISC_H
+
+#include <sys/types.h>
+#include "cmd.h"
+
+/* Constants */
+#define ASK_HEX 0x01
+#define ASK_DEC 0x02
+
+/* Prototypes */
+int ask_cmd __P((cmd_t *));
+int ask_num __P((const char *, int, unsigned int, unsigned int, unsigned int, void (*help) __P((void))));
+int ask_yn __P((const char *, int));
+u_int16_t getshort __P((void *));
+u_int32_t getlong __P((void *));
+void putshort __P((void *, u_int16_t));
+void putlong __P((void *, u_int32_t));
+
+#endif /* _MISC_H */
+
diff --git a/diskdev_cmds/fdisk.tproj/opendev.c b/diskdev_cmds/fdisk.tproj/opendev.c
new file mode 100644
index 0000000..538e4e6
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/opendev.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+/*
+ * Copyright (c) 2000, Todd C. Miller. All rights reserved.
+ * Copyright (c) 1996, Jason Downs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "util.h"
+/*
+ * This routine is a generic rewrite of the original code found in
+ * disklabel(8).
+ */
+
+int
+opendev(path, oflags, dflags, realpath)
+ char *path;
+ int oflags;
+ int dflags;
+ char **realpath;
+{
+ int fd;
+ char *slash, *prefix;
+ static char namebuf[PATH_MAX];
+
+ /* Initial state */
+ if (realpath)
+ *realpath = path;
+ fd = -1;
+ errno = ENOENT;
+
+ if (dflags & OPENDEV_BLCK)
+ prefix = ""; /* block device */
+ else
+ prefix = "r"; /* character device */
+
+ if ((slash = strchr(path, '/')))
+ fd = open(path, oflags);
+ else if (dflags & OPENDEV_PART) {
+ /*
+ * First try raw partition (for removable drives)
+ */
+ if (snprintf(namebuf, sizeof(namebuf), "%s%s%s%c",
+ _PATH_DEV, prefix, path, 'a' + getrawpartition())
+ < sizeof(namebuf)) {
+ fd = open(namebuf, oflags);
+ if (realpath)
+ *realpath = namebuf;
+ } else
+ errno = ENAMETOOLONG;
+ }
+ if (!slash && fd == -1 && errno == ENOENT) {
+ if (snprintf(namebuf, sizeof(namebuf), "%s%s%s",
+ _PATH_DEV, prefix, path) < sizeof(namebuf)) {
+ fd = open(namebuf, oflags);
+ if (realpath)
+ *realpath = namebuf;
+ } else
+ errno = ENAMETOOLONG;
+ }
+ return (fd);
+}
diff --git a/diskdev_cmds/fdisk.tproj/part.c b/diskdev_cmds/fdisk.tproj/part.c
new file mode 100644
index 0000000..7191442
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/part.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <util.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <machine/param.h>
+#include "disk.h"
+#include "misc.h"
+#include "mbr.h"
+
+
+static const struct part_type {
+ int type;
+ char sname[14];
+ char *lname;
+} part_types[] = {
+ { 0x00, "unused ", "unused"},
+ { 0x01, "DOS FAT-12 ", "Primary DOS with 12 bit FAT"},
+ { 0x02, "XENIX / ", "XENIX / filesystem"},
+ { 0x03, "XENIX /usr ", "XENIX /usr filesystem"},
+ { 0x04, "DOS FAT-16 ", "Primary DOS with 16 bit FAT"},
+ { 0x05, "Extended DOS", "Extended DOS"},
+ { 0x06, "DOS > 32MB ", "Primary 'big' DOS (> 32MB)"},
+ { 0x07, "HPFS/QNX/AUX", "OS/2 HPFS, QNX-2 or Advanced UNIX"},
+ { 0x08, "AIX fs ", "AIX filesystem"},
+ { 0x09, "AIX/Coherent", "AIX boot partition or Coherent"},
+ { 0x0A, "OS/2 Bootmgr", "OS/2 Boot Manager or OPUS"},
+ { 0x0B, "Win95 FAT-32", "Primary Win95 w/ 32-bit FAT"},
+ { 0x0C, "Win95 FAT32L", "Primary Win95 w/ 32-bit FAT LBA-mapped"},
+ { 0x0E, "DOS FAT-16 ", "Primary DOS w/ 16-bit FAT, CHS-mapped"},
+ { 0x0F, "Extended LBA", "Extended DOS LBA-mapped"},
+ { 0x10, "OPUS ", "OPUS"},
+ { 0x11, "OS/2 hidden ", "OS/2 BM: hidden DOS 12-bit FAT"},
+ { 0x12, "Compaq Diag.", "Compaq Diagnostics"},
+ { 0x14, "OS/2 hidden ", "OS/2 BM: hidden DOS 16-bit FAT <32M or Novell DOS 7.0 bug"},
+ { 0x16, "OS/2 hidden ", "OS/2 BM: hidden DOS 16-bit FAT >=32M"},
+ { 0x17, "OS/2 hidden ", "OS/2 BM: hidden IFS"},
+ { 0x18, "AST swap ", "AST Windows swapfile"},
+ { 0x19, "Willowtech ", "Willowtech Photon coS"},
+ { 0x20, "Willowsoft ", "Willowsoft OFS1"},
+ { 0x24, "NEC DOS ", "NEC DOS"},
+ { 0x38, "Theos ", "Theos"},
+ { 0x39, "Plan 9 ", "Plan 9"},
+ { 0x40, "VENIX 286 ", "VENIX 286 or LynxOS"},
+ { 0x41, "Lin/Minux DR", "Linux/MINIX (sharing disk with DRDOS) or Personal RISC boot"},
+ { 0x42, "LinuxSwap DR", "SFS or Linux swap (sharing disk with DRDOS)"},
+ { 0x43, "Linux DR ", "Linux native (sharing disk with DRDOS)"},
+ { 0x4D, "QNX 4.2 Pri ", "QNX 4.2 Primary"},
+ { 0x4E, "QNX 4.2 Sec ", "QNX 4.2 Secondary"},
+ { 0x4F, "QNX 4.2 Ter ", "QNX 4.2 Tertiary"},
+ { 0x50, "DM ", "DM (disk manager)"},
+ { 0x51, "DM ", "DM6 Aux1 (or Novell)"},
+ { 0x52, "CP/M or SysV", "CP/M or Microport SysV/AT"},
+ { 0x53, "DM ", "DM6 Aux3"},
+ { 0x54, "Ontrack ", "Ontrack"},
+ { 0x55, "EZ-Drive ", "EZ-Drive (disk manager)"},
+ { 0x56, "Golden Bow ", "Golden Bow (disk manager)"},
+ { 0x5C, "Priam ", "Priam Edisk (disk manager)"},
+ { 0x61, "SpeedStor ", "SpeedStor"},
+ { 0x63, "ISC, HURD, *", "ISC, System V/386, GNU HURD or Mach"},
+ { 0x64, "Netware 2.xx", "Novell Netware 2.xx"},
+ { 0x65, "Netware 3.xx", "Novell Netware 3.xx"},
+ { 0x66, "Netware 386 ", "Novell 386 Netware"},
+ { 0x67, "Novell ", "Novell"},
+ { 0x68, "Novell ", "Novell"},
+ { 0x69, "Novell ", "Novell"},
+ { 0x70, "DiskSecure ", "DiskSecure Multi-Boot"},
+ { 0x75, "PCIX ", "PCIX"},
+ { 0x80, "Minix (old) ", "Minix 1.1 ... 1.4a"},
+ { 0x81, "Minix (new) ", "Minix 1.4b ... 1.5.10"},
+ { 0x82, "Linux swap ", "Linux swap"},
+ { 0x83, "Linux files*", "Linux filesystem"},
+ { 0x93, "Amoeba file*", "Amoeba filesystem"},
+ { 0x94, "Amoeba BBT ", "Amoeba bad block table"},
+ { 0x84, "OS/2 hidden ", "OS/2 hidden C: drive"},
+ { 0x85, "Linux ext. ", "Linux extended"},
+ { 0x86, "NT FAT VS ", "NT FAT volume set"},
+ { 0x87, "NTFS VS ", "NTFS volume set or HPFS mirrored"},
+ { 0x93, "Amoeba FS ", "Amoeba filesystem"},
+ { 0x94, "Amoeba BBT ", "Amoeba bad block table"},
+ { 0x99, "Mylex ", "Mylex EISA SCSI"},
+ { 0x9F, "BSDI ", "BSDI BSD/OS"},
+ { 0xA0, "NotebookSave", "Phoenix NoteBIOS save-to-disk"},
+ { 0xA5, "FreeBSD ", "FreeBSD"},
+ { 0xA6, "OpenBSD ", "OpenBSD"},
+ { 0xA7, "NEXTSTEP ", "NEXTSTEP"},
+ { 0xA8, "Darwin UFS ", "Darwin UFS partition"},
+ { 0xA9, "NetBSD ", "NetBSD"},
+ { 0xAB, "Darwin Boot ", "Darwin boot partition"},
+ { 0xAF, "HFS+ ", "Darwin HFS+ partition"},
+ { 0xB7, "BSDI filesy*", "BSDI BSD/386 filesystem"},
+ { 0xB8, "BSDI swap ", "BSDI BSD/386 swap"},
+ { 0xC0, "CTOS ", "CTOS"},
+ { 0xC1, "DRDOSs FAT12", "DRDOS/sec (FAT-12)"},
+ { 0xC4, "DRDOSs < 32M", "DRDOS/sec (FAT-16, < 32M)"},
+ { 0xC6, "DRDOSs >=32M", "DRDOS/sec (FAT-16, >= 32M)"},
+ { 0xC7, "HPFS Disbled", "Syrinx (Cyrnix?) or HPFS disabled"},
+ { 0xDB, "CPM/C.DOS/C*", "Concurrent CPM or C.DOS or CTOS"},
+ { 0xE1, "SpeedStor ", "DOS access or SpeedStor 12-bit FAT extended partition"},
+ { 0xE3, "SpeedStor ", "DOS R/O or SpeedStor or Storage Dimensions"},
+ { 0xE4, "SpeedStor ", "SpeedStor 16-bit FAT extended partition < 1024 cyl."},
+ { 0xEB, "BeOS/i386 ", "BeOS for Intel"},
+ { 0xF1, "SpeedStor ", "SpeedStor or Storage Dimensions"},
+ { 0xF2, "DOS 3.3+ Sec", "DOS 3.3+ Secondary"},
+ { 0xF4, "SpeedStor ", "SpeedStor >1024 cyl. or LANstep or IBM PS/2 IML"},
+ { 0xFF, "Xenix BBT ", "Xenix Bad Block Table"},
+};
+
+void
+PRT_printall()
+{
+ int i, idrows;
+
+ idrows = ((sizeof(part_types)/sizeof(struct part_type))+3)/4;
+
+ printf("Choose from the following Partition id values:\n");
+ for (i = 0; i < idrows; i++) {
+ printf("%02X %s %02X %s %02X %s"
+ , part_types[i ].type, part_types[i ].sname
+ , part_types[i+idrows ].type, part_types[i+idrows ].sname
+ , part_types[i+idrows*2].type, part_types[i+idrows*2].sname
+ );
+ if ((i+idrows*3) < (sizeof(part_types)/sizeof(struct part_type))) {
+ printf(" %02X %s\n"
+ , part_types[i+idrows*3].type, part_types[i+idrows*3].sname );
+ }
+ else
+ printf( "\n" );
+ }
+}
+
+const char *
+PRT_ascii_id(id)
+ int id;
+{
+ static char unknown[] = "<Unknown ID>";
+ int i;
+
+ for (i = 0; i < sizeof(part_types)/sizeof(struct part_type); i++) {
+ if (part_types[i].type == id)
+ return (part_types[i].sname);
+ }
+
+ return (unknown);
+}
+
+void
+PRT_parse(disk, prt, offset, reloff, partn, pn)
+ disk_t *disk;
+ void *prt;
+ off_t offset;
+ off_t reloff;
+ prt_t *partn;
+ int pn;
+{
+ unsigned char *p = prt;
+ off_t off;
+
+ partn->flag = *p++;
+ partn->shead = *p++;
+
+ partn->ssect = (*p) & 0x3F;
+ partn->scyl = ((*p << 2) & 0xFF00) | (*(p+1));
+ p += 2;
+
+ partn->id = *p++;
+ partn->ehead = *p++;
+ partn->esect = (*p) & 0x3F;
+ partn->ecyl = ((*p << 2) & 0xFF00) | (*(p+1));
+ p += 2;
+
+ if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
+ off = reloff;
+ else
+ off = offset;
+
+ partn->bs = getlong(p) + off;
+ partn->ns = getlong(p+4);
+
+
+ /* Zero out entry if not used */
+ if (partn->id == DOSPTYP_UNUSED ) {
+ memset(partn, 0, sizeof(*partn));
+ }
+}
+
+int
+PRT_check_chs(partn)
+ prt_t *partn;
+{
+ if ( (partn->shead > 255) ||
+ (partn->ssect >63) ||
+ (partn->scyl > 1023) ||
+ (partn->ehead >255) ||
+ (partn->esect >63) ||
+ (partn->ecyl > 1023) )
+ {
+ return 0;
+ }
+ return 1;
+}
+void
+PRT_make(partn, offset, reloff, prt)
+ prt_t *partn;
+ off_t offset;
+ off_t reloff;
+ void *prt;
+{
+ unsigned char *p = prt;
+ prt_t tmp;
+ off_t off;
+
+ tmp.shead = partn->shead;
+ tmp.ssect = partn->ssect;
+ tmp.scyl = (partn->scyl > 1023)? 1023: partn->scyl;
+ tmp.ehead = partn->ehead;
+ tmp.esect = partn->esect;
+ tmp.ecyl = (partn->ecyl > 1023)? 1023: partn->ecyl;
+ if (!PRT_check_chs(partn) && PRT_check_chs(&tmp)) {
+ partn->shead = tmp.shead;
+ partn->ssect = tmp.ssect;
+ partn->scyl = tmp.scyl;
+ partn->ehead = tmp.ehead;
+ partn->esect = tmp.esect;
+ partn->ecyl = tmp.ecyl;
+ printf("Cylinder values are modified to fit in CHS.\n");
+ }
+ if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
+ off = reloff;
+ else
+ off = offset;
+
+ if (PRT_check_chs(partn)) {
+ *p++ = partn->flag & 0xFF;
+
+ *p++ = partn->shead & 0xFF;
+ *p++ = (partn->ssect & 0x3F) | ((partn->scyl & 0x300) >> 2);
+ *p++ = partn->scyl & 0xFF;
+
+ *p++ = partn->id & 0xFF;
+
+ *p++ = partn->ehead & 0xFF;
+ *p++ = (partn->esect & 0x3F) | ((partn->ecyl & 0x300) >> 2);
+ *p++ = partn->ecyl & 0xFF;
+ } else {
+ /* should this really keep flag, id and set others to 0xff? */
+ *p++ = partn->flag & 0xFF;
+ *p++ = 0xFF;
+ *p++ = 0xFF;
+ *p++ = 0xFF;
+ *p++ = partn->id & 0xFF;
+ *p++ = 0xFF;
+ *p++ = 0xFF;
+ *p++ = 0xFF;
+ printf("Warning CHS values out of bounds only saving LBA values\n");
+ }
+
+ putlong(p, partn->bs - off);
+ putlong(p+4, partn->ns);
+}
+
+void
+PRT_print(num, partn)
+ int num;
+ prt_t *partn;
+{
+
+ if (partn == NULL) {
+ printf(" Starting Ending\n");
+ printf(" #: id cyl hd sec - cyl hd sec [ start - size]\n");
+ printf("------------------------------------------------------------------------\n");
+ } else {
+ printf("%c%1d: %.2X %4u %3u %3u - %4u %3u %3u [%10u - %10u] %s\n",
+ (partn->flag == 0x80)?'*':' ',
+ num + 1, partn->id,
+ partn->scyl, partn->shead, partn->ssect,
+ partn->ecyl, partn->ehead, partn->esect,
+ partn->bs, partn->ns,
+ PRT_ascii_id(partn->id));
+ }
+}
+
+void
+PRT_fix_BN(disk, part, pn)
+ disk_t *disk;
+ prt_t *part;
+ int pn;
+{
+ int spt, tpc, spc;
+ int start = 0;
+ int end = 0;
+
+ /* Zero out entry if not used */
+ if (part->id == DOSPTYP_UNUSED ) {
+ memset(part, 0, sizeof(*part));
+ return;
+ }
+
+ /* Disk metrics */
+ spt = disk->real->sectors;
+ tpc = disk->real->heads;
+ spc = spt * tpc;
+
+ start += part->scyl * spc;
+ start += part->shead * spt;
+ start += part->ssect - 1;
+
+ end += part->ecyl * spc;
+ end += part->ehead * spt;
+ end += part->esect - 1;
+
+ /* XXX - Should handle this... */
+ if (start > end)
+ warn("Start of partition #%d after end!", pn);
+
+ part->bs = start;
+ part->ns = (end - start) + 1;
+}
+
+void
+PRT_fix_CHS(disk, part, pn)
+ disk_t *disk;
+ prt_t *part;
+ int pn;
+{
+ int spt, tpc, spc;
+ int start;
+ int cyl, head, sect;
+
+ /* Zero out entry if not used */
+ if (part->id == DOSPTYP_UNUSED ) {
+ memset(part, 0, sizeof(*part));
+ return;
+ }
+
+ /* Disk metrics */
+ spt = disk->real->sectors;
+ tpc = disk->real->heads;
+ spc = spt * tpc;
+
+ start = part->bs;
+
+ if(start <= spt) {
+ /* Figure out "real" starting CHS values */
+ cyl = (start / spc); start -= (cyl * spc);
+ head = (start / spt); start -= (head * spt);
+ sect = (start + 1);
+ } else {
+ cyl = 1023;
+ head = 254;
+ sect = 63;
+ }
+
+ part->scyl = cyl;
+ part->shead = head;
+ part->ssect = sect;
+
+ /* use fake geometry to trigger LBA mode */
+
+ cyl = 1023;
+ head = 254;
+ sect = 63;
+
+ part->ecyl = cyl;
+ part->ehead = head;
+ part->esect = sect;
+}
+
diff --git a/diskdev_cmds/fdisk.tproj/part.h b/diskdev_cmds/fdisk.tproj/part.h
new file mode 100644
index 0000000..049cf2c
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/part.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PART_H
+#define _PART_H
+
+/* Partition type */
+typedef struct _prt_t {
+ int shead, scyl, ssect;
+ int ehead, ecyl, esect;
+ int bs;
+ int ns;
+ unsigned char flag;
+ unsigned char id;
+} prt_t;
+
+/* Prototypes */
+void PRT_printall __P((void));
+const char *PRT_ascii_id __P((int));
+void PRT_parse __P((disk_t *, void *, off_t, off_t, prt_t *, int));
+void PRT_make __P((prt_t *, off_t, off_t, void *));
+void PRT_print __P((int, prt_t *));
+
+/* This does CHS -> bs/ns */
+void PRT_fix_BN __P((disk_t *, prt_t *, int));
+
+/* This does bs/ns -> CHS */
+void PRT_fix_CHS __P((disk_t *, prt_t *, int));
+#endif /* _PART_H */
+
diff --git a/diskdev_cmds/fdisk.tproj/user.c b/diskdev_cmds/fdisk.tproj/user.c
new file mode 100644
index 0000000..d44434e
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/user.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <util.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <machine/param.h>
+#include "user.h"
+#include "disk.h"
+#include "misc.h"
+#include "mbr.h"
+#include "cmd.h"
+
+
+/* Our command table */
+static cmd_table_t cmd_table[] = {
+ {"help", Xhelp, "Command help list"},
+ {"manual", Xmanual, "Show entire man page for fdisk"},
+ {"reinit", Xreinit, "Re-initialize loaded MBR (to defaults)"},
+ {"auto", Xauto, "Auto-partition the disk with a partition style"},
+ {"setpid", Xsetpid, "Set the identifier of a given table entry"},
+ {"disk", Xdisk, "Edit current drive stats"},
+ {"edit", Xedit, "Edit given table entry"},
+ {"erase", Xerase, "Erase current MBR"},
+ {"flag", Xflag, "Flag given table entry as bootable"},
+ {"update", Xupdate, "Update machine code in loaded MBR"},
+ {"select", Xselect, "Select extended partition table entry MBR"},
+ {"print", Xprint, "Print loaded MBR partition table"},
+ {"write", Xwrite, "Write loaded MBR to disk"},
+ {"exit", Xexit, "Exit edit of current MBR, without saving changes"},
+ {"quit", Xquit, "Quit edit of current MBR, saving current changes"},
+ {"abort", Xabort, "Abort program without saving current changes"},
+ {NULL, NULL, NULL}
+};
+
+
+int
+USER_write(disk, tt, preserve, force)
+ disk_t *disk;
+ mbr_t *tt; /* Template MBR to write */
+ int preserve; /* Preserve partition table and just write boot code */
+ int force; /* Don't ask any questions */
+{
+ int fd, yn;
+ char *msgp = "\nDo you wish to write new MBR?";
+ char *msgk = "\nDo you wish to write new MBR and partition table?";
+
+ /* Write sector 0 */
+ if (force) {
+ yn = 1;
+ } else {
+ printf("\a\n"
+ "\t-----------------------------------------------------\n"
+ "\t------ ATTENTION - UPDATING MASTER BOOT RECORD ------\n"
+ "\t-----------------------------------------------------\n");
+ if (preserve)
+ yn = ask_yn(msgp, 0);
+ else
+ yn = ask_yn(msgk, 0);
+ }
+
+ if (yn) {
+ if (preserve) {
+ int shared;
+ /* Only write the first one, if there's more than one in an extended partition chain */
+ /* Since we're updating boot code, we don't require exclusive access */
+ fd = DISK_openshared(disk->name, O_RDWR, &shared);
+ MBR_make(tt);
+ MBR_write(disk, fd, tt);
+ DISK_close(fd);
+ } else {
+ MBR_write_all(disk, tt);
+ }
+ } else {
+ printf("MBR is unchanged\n");
+ }
+
+ return (0);
+}
+
+
+int
+USER_modify(disk, tt, offset, reloff)
+ disk_t *disk;
+ mbr_t *tt;
+ off_t offset;
+ off_t reloff;
+{
+ static int editlevel;
+ mbr_t *mbr;
+ cmd_t cmd;
+ int i, st, fd;
+ int modified = 0;
+
+ /* One level deeper */
+ editlevel += 1;
+
+ /* Set up command table pointer */
+ cmd.table = cmd_table;
+
+ /* Read MBR & partition */
+ mbr = MBR_alloc(NULL);
+ fd = DISK_open(disk->name, O_RDONLY);
+ MBR_read(disk, fd, offset, mbr);
+ DISK_close(fd);
+
+ /* Parse the sucker */
+ MBR_parse(disk, offset, reloff, mbr);
+
+ if (mbr->signature != MBR_SIGNATURE) {
+ int yn = ask_yn("The signature for this MBR is invalid.\nWould you like to initialize the partition table?", 1);
+ if (yn) {
+ strlcpy(cmd.cmd, "erase", sizeof(cmd.cmd));
+ cmd.args[0] = '\0';
+ st = Xerase(&cmd, disk, mbr, tt, offset);
+ modified = 1;
+ }
+ }
+
+ printf("Enter 'help' for information\n");
+
+ /* Edit cycle */
+ do {
+again:
+ printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel);
+ fflush(stdout);
+ ask_cmd(&cmd);
+
+ if (cmd.cmd[0] == '\0')
+ goto again;
+ for (i = 0; cmd_table[i].cmd != NULL; i++)
+ if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd)
+ break;
+
+ /* Quick hack to put in '?' == 'help' */
+ if (!strcmp(cmd.cmd, "?"))
+ i = 0;
+
+ /* Check for valid command */
+ if (cmd_table[i].cmd == NULL) {
+ printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd);
+ continue;
+ } else
+ strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof(cmd.cmd));
+
+ /* Call function */
+ st = cmd_table[i].fcn(&cmd, disk, mbr, tt, offset);
+
+ /* Update status */
+ if (st == CMD_EXIT)
+ break;
+ if (st == CMD_SAVE)
+ break;
+ if (st == CMD_CLEAN)
+ modified = 0;
+ if (st == CMD_DIRTY)
+ modified = 1;
+ } while (1);
+
+ /* Write out MBR */
+ if (modified) {
+ if (st == CMD_SAVE) {
+ int shared = 0;
+ printf("Writing current MBR to disk.\n");
+ fd = DISK_openshared(disk->name, O_RDWR, &shared);
+ if(shared) {
+ if(!ask_yn("Device could not be accessed exclusively.\nA reboot will be needed for changes to take effect. OK?", 0)) {
+ close(fd);
+ goto again;
+ }
+ }
+
+ MBR_make(mbr);
+ MBR_write(disk, fd, mbr);
+ close(fd);
+ } else {
+ int yn = ask_yn("MBR was modified; really quit without saving?", 0);
+ if (yn) {
+ printf("Aborting changes to current MBR.\n");
+ } else {
+ goto again;
+ }
+ }
+ }
+
+ /* One level less */
+ editlevel -= 1;
+
+ MBR_free(mbr);
+
+ return (0);
+}
+
+int
+USER_print_disk(disk, do_dump)
+ disk_t *disk;
+ int do_dump;
+{
+ int fd, offset, firstoff;
+ mbr_t *mbr;
+
+ fd = DISK_open(disk->name, O_RDONLY);
+ offset = firstoff = 0;
+
+ if (!do_dump)
+ DISK_printmetrics(disk);
+
+ mbr = MBR_read_all(disk);
+ if (do_dump)
+ MBR_dump_all(mbr);
+ else
+ MBR_print_all(mbr);
+ MBR_free(mbr);
+
+ return (DISK_close(fd));
+}
+
+
+
diff --git a/diskdev_cmds/fdisk.tproj/user.h b/diskdev_cmds/fdisk.tproj/user.h
new file mode 100644
index 0000000..7234c98
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/user.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Tobias Weingartner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _USER_H
+#define _USER_H
+
+#include "disk.h"
+#include "mbr.h"
+
+/* Prototypes */
+int USER_write __P((disk_t *, mbr_t *, int, int));
+int USER_modify __P((disk_t *, mbr_t *, off_t, off_t));
+int USER_print_disk __P((disk_t *, int));
+#endif /* _USER_H */
+
diff --git a/diskdev_cmds/fdisk.tproj/util.h b/diskdev_cmds/fdisk.tproj/util.h
new file mode 100644
index 0000000..4e1600d
--- /dev/null
+++ b/diskdev_cmds/fdisk.tproj/util.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*-
+ * Copyright (c) 1995
+ * The Regents of the University of California. All rights reserved.
+ * Portions Copyright (c) 1996, Jason Downs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*
+ * fparseln() specific operation flags.
+ */
+#define FPARSELN_UNESCESC 0x01
+#define FPARSELN_UNESCCONT 0x02
+#define FPARSELN_UNESCCOMM 0x04
+#define FPARSELN_UNESCREST 0x08
+#define FPARSELN_UNESCALL 0x0f
+
+/*
+ * opendev() specific operation flags.
+ */
+#define OPENDEV_PART 0x01 /* Try to open the raw partition. */
+#define OPENDEV_DRCT 0x02 /* Obsolete (now default behavior). */
+#define OPENDEV_BLCK 0x04 /* Open block, not character device. */
+
+/*
+ * uucplock(3) specific flags.
+ */
+#define UU_LOCK_INUSE (1)
+#define UU_LOCK_OK (0)
+#define UU_LOCK_OPEN_ERR (-1)
+#define UU_LOCK_READ_ERR (-2)
+#define UU_LOCK_CREAT_ERR (-3)
+#define UU_LOCK_WRITE_ERR (-4)
+#define UU_LOCK_LINK_ERR (-5)
+#define UU_LOCK_TRY_ERR (-6)
+#define UU_LOCK_OWNER_ERR (-7)
+
+/*
+ * stub struct definitions.
+ */
+struct __sFILE;
+struct login_cap;
+struct passwd;
+struct termios;
+struct winsize;
+
+__BEGIN_DECLS
+char *fparseln __P((struct __sFILE *, size_t *, size_t *, const char[3], int));
+int login_tty __P((int));
+int logout __P((const char *));
+void logwtmp __P((const char *, const char *, const char *));
+int opendev __P((char *, int, int, char **));
+int pidfile __P((const char *));
+void pw_setdir __P((const char *));
+char *pw_file __P((const char *));
+int pw_lock __P((int retries));
+int pw_mkdb __P((char *, int));
+int pw_abort __P((void));
+void pw_init __P((void));
+void pw_edit __P((int, const char *));
+void pw_prompt __P((void));
+void pw_copy __P((int, int, struct passwd *));
+void pw_getconf __P((char *, size_t, const char *, const char *));
+int pw_scan __P((char *, struct passwd *, int *));
+void pw_error __P((const char *, int, int));
+int openpty __P((int *, int *, char *, struct termios *,
+ struct winsize *));
+int opendisk __P((const char *path, int flags, char *buf, size_t buflen,
+ int iscooked));
+pid_t forkpty __P((int *, char *, struct termios *, struct winsize *));
+int getmaxpartitions __P((void));
+int getrawpartition __P((void));
+void login_fbtab __P((char *, uid_t, gid_t));
+int login_check_expire __P((struct __sFILE *, struct passwd *, char *, int));
+char *readlabelfs __P((char *, int));
+const char *uu_lockerr __P((int _uu_lockresult));
+int uu_lock __P((const char *_ttyname));
+int uu_lock_txfr __P((const char *_ttyname, pid_t _pid));
+int uu_unlock __P((const char *_ttyname));
+__END_DECLS
+
+#endif /* !_UTIL_H_ */
diff --git a/diskdev_cmds/fsck.tproj/fsck.8 b/diskdev_cmds/fsck.tproj/fsck.8
new file mode 100644
index 0000000..11cf28f
--- /dev/null
+++ b/diskdev_cmds/fsck.tproj/fsck.8
@@ -0,0 +1,176 @@
+.\" Copyright (c) 1980, 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95
+.\"
+.Dd May 18, 2010
+.Dt FSCK 8
+.Os BSD 4
+.Sh NAME
+.Nm fsck
+.Nd filesystem consistency check and interactive repair
+.Sh SYNOPSIS
+.Nm fsck
+.Fl p
+.Op Fl f
+.Nm fsck
+.Op Fl l Ar maxparallel
+.Op Fl q
+.Op Fl y
+.Op Fl n
+.Op Fl d
+.Sh DESCRIPTION
+The first form of
+.Nm fsck
+preens a standard set of filesystems or the specified filesystems.
+It is normally used in the script
+.Pa /etc/rc
+during automatic reboot.
+Here
+.Nm fsck
+reads the filesystem descriptor table (using
+.Xr getfsent 3 )
+to determine which filesystems to check.
+Only partitions that have ``rw,'' ``rq'' or ``ro'' as options,
+and that have non-zero pass number are checked.
+Filesystems with pass number 1 (normally just the root filesystem)
+are checked one at a time.
+When pass 1 completes, all remaining filesystems are checked,
+running one process per disk drive.
+The disk drive containing each filesystem is inferred from the shortest prefix
+of the device name that ends in one or more digits; the remaining characters
+are assumed to be the partition designator.
+In preening mode,
+filesystems that are marked clean are skipped.
+Filesystems are marked clean when they are unmounted,
+when they have been mounted read-only, or when
+.Nm fsck
+runs on them successfully.
+.Pp
+It should be noted that
+.Nm fsck
+is now essentially a wrapper that invokes other
+.Pa fsck_XXX
+utilities as needed. Currently,
+.Nm fsck
+can invoke
+.Pa fsck_hfs ,
+.Pa fsck_apfs ,
+.Pa fsck_msdos ,
+.Pa fsck_exfat ,
+and
+.Pa fsck_udf .
+If this underlying process that
+.Nm fsck
+invokes encounters serious inconsistencies or the filesystem type is not one
+of the above, it exits
+with an abnormal return status and an automatic reboot will then fail.
+For each corrected inconsistency one or more lines will be printed
+identifying the filesystem on which the correction will take place,
+and the nature of the correction.
+.Pp
+If sent a
+.Dv QUIT
+signal,
+.Nm fsck
+will finish the filesystem checks, then exit with an abnormal
+return status that causes an automatic reboot to fail.
+This is useful when you want to finish the filesystem checks during an
+automatic reboot,
+but do not want the machine to come up multiuser after the checks complete.
+.Pp
+Without the
+.Fl p
+option,
+.Nm fsck
+audits and interactively repairs inconsistent conditions for filesystems.
+It should be noted that some of the corrective actions which are not
+correctable under the
+.Fl p
+option will result in some loss of data.
+The amount and severity of data lost may be determined from the diagnostic
+output.
+If the operator does not have write permission on the filesystem
+.Nm fsck
+will default to a
+.Fl n
+action.
+.Pp
+The following flags are interpreted by
+.Nm fsck
+and passed along to the underlying tool that it spawns.
+.Bl -tag
+.It Fl f
+Force fsck to check `clean' filesystems when preening.
+.It Fl l
+Limit the number of parallel checks to the number specified in the following
+argument.
+By default, the limit is the number of disks, running one process per disk.
+If a smaller limit is given, the disks are checked round-robin, one filesystem
+at a time.
+.It Fl R
+Specify a particular passno number for which fsck is to check. You may only specify 1 or 2.
+Only those filesystems matching that particular passno entry (if using fstab) will be checked.
+For more information on the passno field, see
+.Xr fstab 5 .
+.It Fl p
+"Preen" mode, described above.
+.It Fl q
+Do a quick check to determine if the filesystem was unmounted cleanly.
+.It Fl y
+Assume a yes response to all questions asked by
+.Nm fsck ;
+this should be used with great caution as this is a free license
+to continue after essentially unlimited trouble has been encountered.
+.It Fl n
+Assume a no response to all questions asked by
+.Nm fsck
+except for
+.Ql CONTINUE? ,
+which is assumed to be affirmative;
+do not open the filesystem for writing.
+.El
+.Pp
+If no filesystems are given to
+.Nm fsck
+then a default list of filesystems is read using
+.Xr getfsent 3 .
+.Pp
+Because of inconsistencies between the block device and the buffer cache,
+the raw device should always be used.
+.Sh SEE ALSO
+.Xr fs 5 ,
+.Xr fsck_hfs 8 ,
+.Xr fsck_apfs 8 ,
+.Xr fsck_msdos 8 ,
+.Xr getfsent 3 ,
+.Xr fstab 5,
+.Xr reboot 8
diff --git a/diskdev_cmds/fsck.tproj/fsck.c b/diskdev_cmds/fsck.tproj/fsck.c
new file mode 100644
index 0000000..dc44e77
--- /dev/null
+++ b/diskdev_cmds/fsck.tproj/fsck.c
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (c) 2010-2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <fstab.h>
+#include <err.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <signal.h>
+
+#include <TargetConditionals.h>
+
+#include "fsck.h"
+#include "../edt_fstab/edt_fstab.h"
+
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+#include <os/bsd.h>
+#define AUTO_BOOT "auto-boot"
+#endif
+
+/* Local Static Functions */
+static int argtoi(int flag, char *req, char *str, int base);
+static void usage();
+static int startdiskcheck(disk_t* disk);
+
+
+/* Global Variables */
+int preen = 0; /* We're checking all fs'es in 'preen' mode */
+int returntosingle = 0; /* Return a non-zero status to prevent multi-user start up */
+int hotroot= 0; /* We're checking / (slash or root) */
+int fscks_running = 0; /* Number of currently running fs checks */
+int ndisks = 0; /* Total number of disks observed */
+int debug = 0; /* Output Debugging info */
+int force_fsck = 0; /* Force an fsck even if the underlying FS is clean */
+int maximum_running = 0; /* Maximum number of sub-processes we'll allow to be spawned */
+int quick_check = 0; /* Do a quick check. Quick check returns clean, dirty, or fail */
+int live_check = 0; /* Do a live check. This allows fsck to run on a partition which is mounted RW */
+int requested_passno = 0; /* only check the filesystems with the specified passno */
+/*
+ * The two following globals are mutually exclusive; you cannot assume "yes" and "no."
+ * The last one observed will be the one that is honored. e.g. fsck -fdnyny will result
+ * in assume_yes == 1, and assume_no == 0;
+ */
+int assume_no = 0; /* If set, assume a "no" response to repair requests */
+int assume_yes = 0; /* If set, assume a "yes" response to repair requests. */
+
+disk_t *disklist = NULL; /* Disk struct with embedded list to enum. all disks */
+part_t *badlist = NULL; /* List of partitions which may have had errors */
+
+static int argtoi(int flag, char *req, char *str, int base) {
+ char *cp;
+ int ret;
+
+ ret = (int)strtol(str, &cp, base);
+ if (cp == str || *cp)
+ errx(EEXIT, "-%c flag requires a %s", flag, req);
+ return (ret);
+}
+
+static void usage(void) {
+ fprintf(stderr, "fsck usage: fsck [-fdnypqL] [-l number]\n");
+}
+
+#if DEBUG
+void debug_args (void);
+void dump_part (part_t* part);
+void dump_disk (disk_t* disk);
+void dump_fsp (struct fstab *fsp);
+
+void debug_args (void) {
+ if (debug) {
+ printf("debug %d\n", debug);
+ }
+
+ if (force_fsck) {
+ printf("force_fsck %d\n", force_fsck);
+ }
+
+ if (assume_no) {
+ printf("assume_no: %d\n", assume_no);
+ }
+
+ if (assume_yes) {
+ printf("assume_yes: %d\n", assume_yes);
+ }
+
+ if (preen) {
+ printf("preen: %d\n", preen);
+ }
+
+ if (quick_check) {
+ printf("quick check %d\n", quick_check);
+ }
+
+ printf("maximum_running %d\n", maximum_running);
+}
+
+void dump_fsp (struct fstab *fsp) {
+ fprintf (stderr, "**********dumping fstab entry %p**********\n", fsp);
+ fprintf (stderr, "fstab->fs_spec: %s\n", fsp->fs_spec);
+ fprintf (stderr, "fstab->fs_file: %s\n", fsp->fs_file);
+ fprintf (stderr, "fstab->fs_vfstype: %s\n", fsp->fs_vfstype);
+ fprintf (stderr, "fstab->fs_mntops: %s\n", fsp->fs_mntops);
+ fprintf (stderr, "fstab->fs_type: %s\n", fsp->fs_type);
+ fprintf (stderr, "fstab->fs_freq: %d\n", fsp->fs_freq);
+ fprintf (stderr, "fstab->fs_passno: %d\n", fsp->fs_passno);
+ fprintf (stderr, "********** finished dumping fstab entry %p**********\n\n\n", fsp);
+
+}
+
+void dump_disk (disk_t* disk) {
+ part_t *part;
+ fprintf (stderr, "**********dumping disk entry %p**********\n", disk);
+ fprintf (stderr, "disk->name: %s\n", disk->name);
+ fprintf (stderr, "disk->next: %p\n", disk->next);
+ fprintf (stderr, "disk->part: %p\n", disk->part);
+ fprintf (stderr, "disk->pid: %d\n\n", disk->pid);
+
+ part = disk->part;
+ if (part) {
+ fprintf(stderr, "dumping partition entries now... \n");
+ }
+ while (part) {
+ dump_part (part);
+ part = part->next;
+ }
+ fprintf (stderr, "**********done dumping disk entry %p**********\n\n\n", disk);
+
+}
+
+void dump_part (part_t* part) {
+ fprintf (stderr, "**********dumping partition entry %p**********\n", part);
+ fprintf (stderr, "part->next: %p\n", part->next);
+ fprintf (stderr, "part->name: %s\n", part->name);
+ fprintf (stderr, "part->fsname: %s\n", part->fsname);
+ fprintf (stderr, "part->vfstype: %s\n\n", part->vfstype);
+ fprintf (stderr, "**********done dumping partition entry %p**********\n\n\n", part);
+}
+
+#endif
+
+
+
+int main (int argc, char** argv) {
+ /* for getopt */
+ extern char *optarg;
+ extern int optind;
+
+ int ch;
+ int ret;
+
+
+ sync();
+ while ((ch = getopt(argc, argv, "dfpR:qnNyYl:L")) != EOF) {
+ switch (ch) {
+ case 'd':
+ debug++;
+ break;
+
+ case 'l':
+ maximum_running = argtoi('l', "number", optarg, 10);
+ break;
+
+ case 'f':
+ force_fsck++;
+ break;
+
+ case 'R':
+ requested_passno = argtoi('R', "number", optarg, 10);
+ /* only allowed to specify 1 or 2 as argument here */
+ if ((requested_passno < ROOT_PASSNO) || (requested_passno > NONROOT_PASSNO)) {
+ usage();
+ exit(EINVAL);
+ }
+ break;
+
+ case 'N':
+ case 'n':
+ assume_no = 1;
+ assume_yes = 0;
+ break;
+
+ case 'p':
+ preen++;
+ break;
+
+ case 'q':
+ quick_check = 1;
+ break;
+
+ case 'Y':
+ case 'y':
+ assume_yes = 1;
+ assume_no = 0;
+ break;
+
+ case 'L':
+ live_check = 1;
+ break;
+
+ default:
+ errx(EEXIT, "%c option?", ch);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Install our signal handlers */
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
+ (void)signal(SIGINT, catchsig);
+ }
+
+ if (preen) {
+ (void)signal(SIGQUIT, catchquit);
+ }
+
+ if (argc) {
+ /* We do not support any extra arguments at this time */
+ ret = EINVAL;
+ usage();
+ exit(ret);
+ }
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ char arg_val[16];
+ if (os_parse_boot_arg_string(AUTO_BOOT, arg_val, sizeof(arg_val))) {
+ if (strcmp(arg_val, "false")) {
+ fprintf(stderr, "warning: auto-boot is set to %s\n", arg_val);
+ }
+ }
+#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
+
+ /*
+ * checkfstab does the bulk of work for fsck. It will scan through the
+ * fstab and iterate through the devices, as needed
+ */
+ ret = checkfstab();
+ /* Return a non-zero return status so that we'll stay in single-user */
+ if (returntosingle) {
+ exit(2);
+ }
+ /* Return the error value obtained from checking all filesystems in checkfstab */
+ exit(ret);
+
+}
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+#include <APFS/APFSConstants.h> // EDT_OS_ENV_MAIN
+
+static int check_boot_container(void)
+{
+ int error = 0;
+ uint32_t os_env = 0;
+ const char *boot_container = get_boot_container(&os_env);
+ char *rcontainer = NULL;
+ char *container = NULL;
+
+ if ((os_env != EDT_OS_ENV_MAIN) &&
+ (os_env != EDT_OS_ENV_DIAGS)) {
+ fprintf(stdout, "fsck: not booting main or diagnostic OS. Skipping fsck on OS container\n");
+ return (0);
+ }
+
+ if (!boot_container) {
+ fprintf(stderr, "fsck: failed to get boot container\n");
+ return (EEXIT);
+ }
+
+ /* get a non-const copy */
+ container = strdup(boot_container);
+ if (!container) {
+ fprintf(stderr, "fsck: failed to copy boot container\n");
+ return (EEXIT);
+ }
+
+ /* Take the special device name, and do some cursory checks */
+ if ((rcontainer = blockcheck(container)) != 0) {
+ /* Construct a temporary disk_t for checkfilesys */
+ disk_t disk;
+ part_t part;
+
+ disk.name = NULL;
+ disk.next = NULL;
+ disk.part = &part;
+ disk.pid = 0;
+
+ part.next = NULL;
+ part.name = rcontainer;
+ part.vfstype = "apfs";
+
+ /* Run the filesystem check against the filesystem in question */
+ error = checkfilesys(&disk, 0);
+ }
+
+ free(container);
+
+ return (error);
+}
+#endif
+
+/*
+ * This is now the guts of fsck.
+ *
+ * This function will iterate over all of the elements in the fstab and run
+ * fsck-like binaries on all of the filesystems in question if able. The root filesystem
+ * is checked first, and then non-root filesystems are checked in order.
+ */
+int checkfstab(void) {
+ int running_status = 0;
+ int ret;
+
+ /*
+ * fsck boot-task (fsck -q):
+ * iOS - fsck_apfs -q will quick-check the container and volumes.
+ * So no need to obtain and check the fstab entries from EDT,
+ * just check the container.
+ * OSX - See comment in build_disklist(). In short - during early boot
+ * getfsent() will only return a synthetic entry for the root volume ("/")
+ * and additional fstab entries. An invalid entry will fail boot.
+ * To avoid this we require passing the "-R 1" flag to only check
+ * the root volume, which per fsck_apfs behaviour will quick-check the container and
+ * the root volume. We dont need to check the other volumes for boot
+ * (except perhaps for the VM and Data volumes but those are mounted earlier anyway).
+ */
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ if (quick_check && (requested_passno == 0)) {
+ return check_boot_container();
+ }
+#endif
+
+ ret = build_disklist ();
+ /*
+ * If we encountered any errors or if 'preen' was off,
+ * then we must have scanned everything. Either way, return.
+ */
+ if ((ret) || (preen == 0)) {
+ return ret;
+ }
+
+ if (preen) {
+ /* Otherwise, see if we need to do a cursory fsck against the FS. */
+ ret = do_diskchecks();
+ running_status |= ret;
+ }
+
+
+ if (running_status) {
+ part_t *part = NULL;
+
+ if (badlist == NULL) {
+ /* If there were no disk problems, then return the status */
+ return (running_status);
+ }
+ fprintf(stderr, "THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
+ badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
+ for (part = badlist; part; part = part->next) {
+ fprintf(stderr, "%s (%s)%s", part->name, part->fsname, part->next ? ", " : "\n");
+ }
+ return (running_status);
+ }
+
+ endfsent();
+ return (0);
+
+}
+
+/*
+ * This function builds up the list of disks that fsck will need to
+ * process and check.
+ *
+ * If we're not in 'preen' mode, then we'll go ahead and do the full
+ * check on all of them now.
+ *
+ * If we ARE in 'preen' mode, then we'll just check the root fs, and log
+ * all of the other ones that we encounter by scanning through the fstab
+ * for checking a bit later on. See notes below for checking '/' at boot.
+ */
+int build_disklist(void) {
+
+ struct fstab *fsp = NULL;
+ int passno = 0;
+ char *name;
+ int retval;
+ int running_status = 0;
+
+ int starting_passno = ROOT_PASSNO; //1
+ int ending_passno = NONROOT_PASSNO; //2
+
+ if (requested_passno) {
+ if (requested_passno == NONROOT_PASSNO) {
+ starting_passno = NONROOT_PASSNO;
+ }
+ else if (requested_passno == ROOT_PASSNO) {
+ ending_passno = ROOT_PASSNO;
+ }
+ }
+
+ /*
+ * We may need to iterate over the elements in the fstab in non-sequential order.
+ * Thus, we take up to two passes to check all fstab fsck-eligible FSes. The first
+ * pass should focus on the root filesystem, which can be inferred from the fsp->fs_passno
+ * field. The library code used to fill in the fsp structure will specify an
+ * fsp->fs_passno == 1 for the root. All other filesystems should get fsp->fs_passno == 2.
+ * (See fstab manpage for more info.)
+ *
+ * However, note that with the addition of the -R argument to this utility, we might "skip"
+ * one of these two passes. By passing in -R 1 or -R 2, the executor of this utility is
+ * specifying that they only want 'fsck' to run on either the root filesystem (passno == 1)
+ * or the non-root filesystems (passno == 2).
+ */
+#if DEBUG
+ fprintf(stderr, "fsck: iterating fstab - starting passno %d, ending passno %d\n",
+ starting_passno, ending_passno);
+#endif
+
+ for (passno = starting_passno; passno <= ending_passno; passno++) {
+ /* Open or reset the fstab entry */
+ if (setfsent() == 0) {
+ fprintf(stderr, "Can't get filesystem checklist: %s\n", strerror(errno));
+ return EEXIT;
+ }
+ /* Iterate through the fs entries returned from fstab */
+ while ((fsp = getfsent()) != 0) {
+ /*
+ * Determine if the filesystem is worth checking. Ignore it if it
+ * is not checkable.
+ */
+ if (fs_checkable(fsp) == 0) {
+ continue;
+ }
+ /*
+ * 'preen' mode is a holdover from the BSD days of long ago. It is semi-
+ * equivalent to a fsck -q, except that it skips filesystems who say that they
+ * are cleanly unmounted and fsck -q will actually call into fsck_hfs to do a
+ * journaling check.
+ *
+ * If preen is off, then we will wind up checking everything in order, so
+ * go ahead and just check this item now. However, if requested_passno is set, then
+ * the caller is asking us to explicitly only check partitions with a certain passno
+ * identifier.
+ *
+ * Otherwise, only work on the root filesystem in the first pass. We can
+ * tell that the fsp represents the root filesystem if fsp->fs_passno == 1.
+ *
+ * NOTE: On Mac OSX, LibInfo, part of Libsystem is in charge of vending us a valid
+ * fstab entry when we're running 'fsck -q' in early boot to ensure the validity of the
+ * boot disk. Since it's before the volume is mounted read-write, getfsent() will probe
+ * the Mach port for directory services. Since it's not up yet, it will determine the
+ * underlying /dev/disk entry for '/' and mechanically construct a fstab entry for / here.
+ * It correctly fills in the passno field below, which will allow us to fork/exec in order
+ * to call fsck_XXX as necessary.
+ *
+ * Once we're booted to multi-user, this block of code shouldn't ever really check anything
+ * unless it's a valid fstab entry because the synthesized fstab entries don't supply a passno
+ * field. Also, they would have to be valid /dev/disk fstab entries as opposed to
+ * UUID or LABEL ones.
+ *
+ * on iOS the above is not true; we rely on the EDT for all fstab entries.
+ */
+ if ((preen == 0) || (passno == 1 && fsp->fs_passno == 1)) {
+
+ /*
+ * If the caller specified a -R argument for us to examine only a certain
+ * range of passno fields AND that value does not match our current passno,
+ * then let the loop march on.
+ */
+ if (requested_passno && (fsp->fs_passno != requested_passno)) {
+ continue; //skip to the next fsent entry.
+ }
+
+ /* Take the special device name, and do some cursory checks. */
+ if ((name = blockcheck(fsp->fs_spec)) != 0) {
+#if TARGET_OS_IPHONE
+ if (!strcmp(name, RAMDISK_FS_SPEC)) {
+ fprintf(stdout, "Encountered ramdisk definition for location %s - will be created during mount.\n", fsp->fs_file);
+ continue;
+ }
+#endif // TARGET_OS_IPHONE
+
+ /* Construct a temporary disk_t for checkfilesys */
+ disk_t disk;
+ part_t part;
+
+ disk.name = NULL;
+ disk.next = NULL;
+ disk.part = &part;
+ disk.pid = 0;
+
+ part.next = NULL;
+ part.name = name;
+ part.vfstype = fsp->fs_vfstype;
+
+ /* Run the filesystem check against the filesystem in question */
+ if ((retval = checkfilesys(&disk, 0)) != 0) {
+ return (retval);
+ }
+ }
+ else {
+ fprintf(stderr, "BAD DISK NAME %s\n", fsp->fs_spec);
+ /*
+ * If we get here, then blockcheck failed (returned NULL).
+ * Presumably, we couldn't stat the disk device. In this case,
+ * just bail out because we couldn't even find all of the
+ * entries in the fstab.
+ */
+ return EEXIT;
+ }
+ }
+ /*
+ * If we get here, then preen must be ON and we're checking a
+ * non-root filesystem. So we must be on the 2nd pass, and
+ * the passno of the element returned from fstab will be > 1.
+ */
+ else if (passno == 2 && fsp->fs_passno > 1) {
+ /*
+ * If the block device checks tell us the name is bad, mark it in the status
+ * field and continue
+ */
+ if ((name = blockcheck(fsp->fs_spec)) == NULL) {
+ fprintf(stderr, "BAD DISK NAME %s\n", fsp->fs_spec);
+ running_status |= 8;
+ continue;
+ }
+ /*
+ * Since we haven't actually done anything yet, add this partition
+ * to the list of devices to check later on.
+ */
+ addpart(name, fsp->fs_file, fsp->fs_vfstype);
+ }
+ }
+ /* If we're not in preen mode, then we scanned everything already. Just bail out */
+ if (preen == 0) {
+ break;
+ }
+ }
+
+ return running_status;
+
+}
+
+/*
+ * This function only runs if we're operating in 'preen' mode. If so,
+ * then iterate over our list of non-root filesystems and fork/exec 'fsck_XXX'
+ * on them to actually do the checking. Spawn up to 'maximum_running' processes.
+ * If 'maximum_running' was not set, then default to the number of disk devices
+ * that we encounter.
+ */
+int do_diskchecks(void) {
+
+ int fsckno = 0;
+ int pid = 0;
+ int exitstatus = 0;
+ int retval = 0;
+ int running_status = 0;
+ disk_t *disk = NULL;
+ disk_t *nextdisk = NULL;
+
+ /*
+ * If we were not specified a maximum number of FS's to check at once,
+ * or the max exceeded the number of disks we observed, then clip it to
+ * the maximum number of disks.
+ */
+ if ((maximum_running == 0) || (maximum_running > ndisks)) {
+ maximum_running = ndisks;
+ }
+ nextdisk = disklist;
+
+ /* Start as many fscks as we will allow */
+ for (fsckno = 0; fsckno < maximum_running; ++fsckno) {
+ /*
+ * Run the disk check against the disk devices we have seen.
+ * 'fscks_running' is increased for each disk we actually visit.
+ * If we hit an error then sleep for 10 seconds and just try again.
+ */
+ while ((retval = startdiskcheck(nextdisk)) && fscks_running > 0) {
+ sleep(10);
+ }
+ if (retval) {
+ return (retval);
+ }
+ nextdisk = nextdisk->next;
+ }
+
+ /*
+ * Once we get limited by 'maximum_running' as to the maximum
+ * number of processes we can spawn at a time, wait until one of our
+ * child processes exits before spawning another one.
+ */
+ while ((pid = wait(&exitstatus)) != -1) {
+ for (disk = disklist; disk; disk = disk->next) {
+ if (disk->pid == pid) {
+ break;
+ }
+ }
+ if (disk == 0) {
+ /* Couldn't find a new disk to check */
+ printf("Unknown pid %d\n", pid);
+ continue;
+ }
+ /* Check the WIFEXITED macros */
+ if (WIFEXITED(exitstatus)) {
+ retval = WEXITSTATUS(exitstatus);
+ }
+ else {
+ retval = 0;
+ }
+ if (WIFSIGNALED(exitstatus)) {
+ printf("%s (%s): EXITED WITH SIGNAL %d\n",
+ disk->part->name, disk->part->fsname,
+ WTERMSIG(exitstatus));
+ retval = 8;
+ }
+ /* If it hit an error, OR in the value into our running total */
+ if (retval != 0) {
+ part_t *temp_part = badlist;
+
+ /* Add the bad partition to the bad partition list */
+ running_status |= retval;
+ badlist = disk->part;
+ disk->part = disk->part->next;
+ if (temp_part) {
+ badlist->next = temp_part;
+ }
+ } else {
+ /* Just move to the next partition */
+ part_t *temp_part = disk->part;
+ disk->part = disk->part->next;
+ destroy_part (temp_part);
+ }
+ /*
+ * Reset the pid to 0 since this partition was checked.
+ * Decrease the number of running processes. Decrease the
+ * number of disks if we finish one off.
+ */
+ disk->pid = 0;
+ fscks_running--;
+
+ if (disk->part == NULL) {
+ ndisks--;
+ }
+
+ if (nextdisk == NULL) {
+ if (disk->part) {
+ /* Start the next partition up */
+ while ((retval = startdiskcheck(disk)) && fscks_running > 0) {
+ sleep(10);
+ }
+ if (retval) {
+ return (retval);
+ }
+ }
+ }
+ else if (fscks_running < maximum_running && fscks_running < ndisks) {
+ /* If there's more room to go, then find the next valid disk */
+ for ( ;; ) {
+ if ((nextdisk = nextdisk->next) == NULL) {
+ nextdisk = disklist;
+ }
+ if (nextdisk->part != NULL && nextdisk->pid == 0) {
+ break;
+ }
+ }
+
+ while ((retval = startdiskcheck(nextdisk)) && fscks_running > 0) {
+ sleep(10);
+ }
+ if (retval) {
+ return (retval);
+ }
+ }
+ }
+ return running_status;
+
+}
+
+/*
+ * fork/exec in order to spawn a process that will eventually
+ * wait4() on the fsck_XXX process.
+ *
+ * Note: The number of forks/execs here is slightly complicated.
+ * We call fork twice, and exec once. The reason we need three total
+ * processes is that the first will continue on as the main line of execution.
+ * This first fork() will create the second process which calls checkfilesys().
+ * In checkfilesys() we will call fork again, followed by an exec. Observe that
+ * the second process created here will *immediately* call wait4 on the third
+ * process, fsck_XXX. This is so that we can track error dialogs and exit statuses
+ * and tie them to the specific instance of fsck_XXX that created them. Otherwise,
+ * if we just called fork a bunch of times and waited on the first one to finish,
+ * it would be difficult to tell which process exited first, and whether or not the
+ * exit status is meaningful.
+ *
+ * Also note that after we get our result from checkfilesys(), we immediately exit,
+ * so that this process doesn't linger and accidentally continue on.
+ */
+static
+int startdiskcheck(disk_t* disk) {
+
+ /*
+ * Split this process into the one that will go
+ * call fsck_XX and the one that won't
+ */
+ disk->pid = fork();
+ if (disk->pid < 0) {
+ perror("fork");
+ return (8);
+ }
+ if (disk->pid == 0) {
+ /*
+ * Call checkfilesys. Note the exit() call. Also note that
+ * we pass 1 to checkfilesys since we are a child process
+ */
+ exit(checkfilesys(disk, 1));
+ }
+ else {
+ fscks_running++;
+ }
+ return (0);
+}
+
+
+
+
+/*
+ * Call fork/exec in order to spawn instance of fsck_XXX for the filesystem
+ * of the specified vfstype. This will actually spawn the process that does the
+ * checking of the filesystem in question.
+ */
+int checkfilesys(disk_t *disk, int child) {
+#define ARGC_MAX 4 /* cmd-name, options, device, NULL-termination */
+ part_t *part = disk->part;
+ const char *argv[ARGC_MAX];
+ int argc;
+ int error = 0;
+ struct stat buf;
+ pid_t pid;
+ int status = 0;
+ char options[] = "-pdfnyql"; /* constant strings are not on the stack */
+ char progname[NAME_MAX];
+ char execname[MAXPATHLEN + 1];
+ char* filesys = part->name;
+ char* vfstype = part->vfstype;
+
+ if (preen && child) {
+ (void)signal(SIGQUIT, ignore_single_quit);
+ }
+
+#if TARGET_OS_IPHONE
+ if (!strcmp(filesys, RAMDISK_FS_SPEC)) {
+ fprintf(stdout, "No need to check filesys for ramdisk, does not exist yet.\n");
+ return 0;
+ }
+#endif // TARGET_OS_IPHONE
+
+ /*
+ * If there was a vfstype specified, then we can go ahead and fork/exec
+ * the child fsck process if the fsck_XXX binary exists.
+ */
+ if (vfstype) {
+ int exitstatus;
+
+ /*
+ * Not all options are currently supported by all 5 fsck_* binaries.
+ * Specifically:
+ * udf does not support debug, quick or live
+ * msdos does not support quick or live
+ * exfat does not support live
+ * apfs does not support preen
+ * When the System invokes fsck it is during boot (one of launchd's boot-tasks).
+ * This task is run with the quick and live options.
+ * On iOS we can assume all partitions are APFS or HFS.
+ * On OSX we run this only against the System volume which will always be HFS or APFS
+ */
+ bzero(options, sizeof(options));
+ snprintf(options, sizeof(options), "-%s%s%s%s%s%s%s",
+ (preen) ? "p" : "",
+ (debug) ? "d" : "",
+ (force_fsck) ? "f" : "",
+ (assume_no) ? "n" : "",
+ (assume_yes) ? "y" : "",
+ (quick_check) ? "q" : "",
+ (live_check) ? "l" : ""
+ );
+
+ argc = 0;
+ snprintf(progname, sizeof(progname), "fsck_%s", vfstype);
+ argv[argc++] = progname;
+ if (strlen(options) > 1) {
+ argv[argc++] = options;
+ }
+ argv[argc++] = filesys;
+ argv[argc] = NULL;
+
+ /* Create the string to the fsck binary */
+ (void)snprintf(execname, sizeof(execname), "%s/fsck_%s", _PATH_SBIN, vfstype);
+
+ /* Check that the binary exists */
+ error = stat (execname, &buf);
+ if (error != 0) {
+ fprintf(stderr, "Filesystem cannot be checked \n");
+ return EEXIT;
+ }
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ /* The fork failed. */
+ fprintf(stderr, "fork failed for %s \n", filesys);
+ if (preen) {
+ fprintf(stderr, "\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
+ filesys);
+ exit(EEXIT);
+ }
+
+ status = EEXIT;
+ break;
+
+ case 0:
+ /* The child */
+ if (preen) {
+ (void)signal(SIGQUIT, ignore_single_quit);
+ }
+#if DEBUG
+ printf("exec: %s", execname);
+ for (int i = 1; i < argc; i++) {
+ printf(" %s", argv[i]);
+ }
+ printf("\n");
+ exit(0);
+#endif
+ execv(execname, (char * const *)argv);
+ fprintf(stderr, "error attempting to exec %s\n", execname);
+ _exit(8);
+ break;
+
+ default:
+ /* The parent; child is process "pid" */
+ waitpid(pid, &exitstatus, 0);
+ if (WIFEXITED(exitstatus)) {
+ status = WEXITSTATUS(exitstatus);
+ }
+ else {
+ status = 0;
+ }
+ if (WIFSIGNALED(exitstatus)) {
+ printf("%s (%s) EXITED WITH SIGNAL %d\n", filesys, vfstype, WTERMSIG(exitstatus));
+ status = 8;
+ }
+ break;
+ }
+
+ return status;
+ }
+ else {
+ fprintf(stderr, "Filesystem cannot be checked \n");
+ return EEXIT;
+ }
+}
+
+/*
+ * When preening, allow a single quit to signal
+ * a special exit after filesystem checks complete
+ * so that reboot sequence may be interrupted.
+ */
+void catchquit(int sig) {
+ extern int returntosingle;
+
+ printf("returning to single-user after filesystem check\n");
+ returntosingle = 1;
+ (void)signal(SIGQUIT, SIG_DFL);
+}
+
+/* Quit if we catch a signal here. Emit 12 */
+void catchsig(int sig) {
+ exit (12);
+}
+
+
+/*
+ * Determine whether a filesystem should be checked.
+ *
+ * Zero indicates that no check should be performed.
+ */
+int fs_checkable(struct fstab *fsp) {
+
+ /*
+ * APFS, HFS, MSDOS, exfat, and UDF are allowed for now.
+ */
+ if (strcmp(fsp->fs_vfstype, "apfs") &&
+ strcmp(fsp->fs_vfstype, "hfs") &&
+ strcmp(fsp->fs_vfstype, "msdos") &&
+ strcmp(fsp->fs_vfstype, "exfat") &&
+ strcmp(fsp->fs_vfstype, "udf")) {
+ return 0;
+ }
+
+ /* if not RW and not RO (SW or XX?), ignore it */
+ if ((strcmp(fsp->fs_type, FSTAB_RW) && strcmp(fsp->fs_type, FSTAB_RO)) ||
+ fsp->fs_passno == 0) {
+ return 0;
+ }
+
+#define DISKARB_LABEL "LABEL="
+#define DISKARB_UUID "UUID="
+ /* If LABEL or UUID specified, ignore it */
+ if ((strncmp(fsp->fs_spec, DISKARB_LABEL, strlen(DISKARB_LABEL)) == 0)
+ || (strncmp(fsp->fs_spec, DISKARB_UUID, strlen(DISKARB_UUID)) == 0)) {
+ return 0;
+ }
+
+ /* Otherwise, it looks fine. Go ahead and check! */
+ return 1;
+}
+
+/*
+ * Do some cursory checks on the pathname provided to ensure that it's really a block
+ * device. If it is, then generate the raw device name and vend it out.
+ */
+char *blockcheck (char *origname) {
+ struct stat stslash;
+ struct stat stblock;
+ struct stat stchar;
+
+ char *newname;
+ char *raw;
+ int retried = 0;
+ int error = 0;
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ /* Variables for setting up the kqueue listener*/
+#define TIMEOUT_SEC 30l
+ struct kevent kev;
+ struct kevent results;
+ struct timespec ts;
+ int slashdev_fd;
+ int kq = -1;
+ int ct;
+ time_t end;
+ time_t now;
+#endif // (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+
+ hotroot = 0;
+ /* Try to get device info for '/' */
+ if (stat("/", &stslash) < 0) {
+ perror("/");
+ /* If we can't get any info on root, then bail out */
+ printf("Can't stat root\n");
+ return (origname);
+ }
+ newname = origname;
+#if TARGET_OS_IPHONE
+ if (!strcmp(newname, RAMDISK_FS_SPEC)) {
+ // Keyword ramdisk
+ fprintf(stdout, "Encountered ramdisk definition. Do not stat\n");
+ return (newname);
+ }
+#endif // TARGET_OS_IPHONE
+
+retry:
+ /* Poke the block device argument */
+ error = stat(newname, &stblock);
+ if (error < 0) {
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ /*
+ * If the device node is not present, set up
+ * a kqueue and wait for up to 30 seconds for it to be
+ * published.
+ */
+ kq = kqueue();
+ if (kq < 0) {
+ printf("kqueue: could not create kqueue: %d\n", errno);
+ printf("Can't stat %s\n", newname);
+ return NULL;
+ }
+ slashdev_fd = open(_PATH_DEV, O_RDONLY);
+
+ EV_SET(&kev, slashdev_fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0, NULL);
+ ct = kevent(kq, &kev, 1, NULL, 0, NULL);
+ if (ct != 0) {
+ printf("kevent() failed to register: %d\n", errno);
+ printf("Can't stat %s\n", newname);
+ /* If we can't register the kqueue, bail out */
+ close (kq);
+ kq = -1;
+ return NULL;
+ }
+ now = time(NULL);
+ end = now + TIMEOUT_SEC;
+
+ ts.tv_nsec = 0;
+ while ((now = time(NULL)) < end) {
+ ts.tv_sec = end - now;
+ ct = kevent(kq, NULL, 0, &results, 1, &ts);
+ if (results.flags & EV_ERROR) {
+ /* If we register any errors, bail out */
+ printf("kevent: registered errors.\n");
+ error = -1;
+ close (kq);
+ kq = -1;
+ break;
+ }
+ error = stat (newname, &stblock);
+ if (error == 0) {
+ /* found the item. continue on */
+ if (kq >= 0) {
+ close (kq);
+ }
+ break;
+ }
+ }
+ if (error != 0) {
+ /* Time out. bail out */
+ if (kq >= 0) {
+ close(kq);
+ }
+ printf("fsck timed out. Can't stat %s\n", newname);
+ return NULL;
+ }
+
+#else //(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ perror(newname);
+ printf("Can't stat %s\n", newname);
+ return (NULL);
+#endif // (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ }
+
+ if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
+ /*
+ * If the block device we're checking is the same as '/' then
+ * update hotroot global for debugging.
+ */
+ if (stslash.st_dev == stblock.st_rdev) {
+ hotroot++;
+ }
+ raw = rawname(newname);
+ if (stat(raw, &stchar) < 0) {
+ perror(raw);
+ printf("Can't stat %s\n", raw);
+ return (origname);
+ }
+ if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
+ return (raw);
+ } else {
+ printf("%s is not a character device\n", raw);
+ return (origname);
+ }
+ } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
+ newname = unrawname(newname);
+ retried++;
+ goto retry;
+ }
+ /*
+ * Not a block or character device, return NULL and
+ * let the user decide what to do.
+ */
+ return (NULL);
+}
+
+
+/*
+ * Generate a raw disk device pathname from a normal one.
+ *
+ * For input /dev/disk1s2, generate /dev/rdisk1s2
+ */
+char *rawname(char *name) {
+ static char rawbuf[32];
+ char *dp;
+
+ /*
+ * Search for the last '/' in the pathname.
+ * If it's not there, then bail out
+ */
+ if ((dp = strrchr(name, '/')) == 0) {
+ return (0);
+ }
+ /*
+ * Insert a NULL in the place of the final '/' so that we can
+ * copy everything BEFORE that last '/' into a separate buffer.
+ */
+ *dp = 0;
+ (void)strlcpy(rawbuf, name, sizeof(rawbuf));
+ *dp = '/';
+ /* Now add an /r to our buffer, then copy everything after the final / */
+ (void)strlcat(rawbuf, "/r", sizeof(rawbuf));
+ (void)strlcat(rawbuf, &dp[1], sizeof(rawbuf));
+ return (rawbuf);
+}
+
+/*
+ * Generate a regular disk device name from a raw one.
+ *
+ * For input /dev/rdisk1s2, generate /dev/disk1s2
+ */
+char *unrawname(char *name) {
+ char *dp;
+ struct stat stb;
+ size_t length;
+
+ /* Find the last '/' in the pathname */
+ if ((dp = strrchr(name, '/')) == 0) {
+ return (name);
+ }
+
+ /* Stat the disk device argument */
+ if (stat(name, &stb) < 0) {
+ return (name);
+ }
+
+ /* If it's not a character device, error out */
+ if ((stb.st_mode & S_IFMT) != S_IFCHR) {
+ return (name);
+ }
+
+ /* If it's not a real raw name, then error out */
+ if (dp[1] != 'r') {
+ return (name);
+ }
+ length = strlen(&dp[2]);
+ length++; /* to account for trailing NULL */
+
+ memmove(&dp[1], &dp[2], length);
+ return (name);
+}
+
+/*
+ * Given a pathname to a disk device, generate the relevant disk_t for that
+ * disk device. It is assumed that this function will be called for each item in the
+ * fstab that needs to get checked.
+ */
+disk_t *finddisk (char *pathname) {
+ disk_t *disk;
+ disk_t **dkp;
+ char *tmp;
+ size_t len;
+
+ /*
+ * Find the disk name. It is assumed that the disk name ends with the
+ * first run of digit(s) in the last component of the path.
+ */
+ tmp = strrchr(pathname, '/'); /* Find the last component of the path */
+ if (tmp == NULL) {
+ tmp = pathname;
+ }
+ else {
+ tmp++;
+ }
+ for (; *tmp && !isdigit(*tmp); tmp++) { /* Skip non-digits */
+ continue;
+ }
+
+ for (; *tmp && isdigit(*tmp); tmp++){ /* Skip to end of consecutive digits */
+ continue;
+ }
+
+ len = tmp - pathname;
+ if (len == 0) {
+ len = strlen(pathname);
+ }
+
+ /* Iterate through all known disks to see if this item was already seen before */
+ for (disk = disklist, dkp = &disklist; disk; dkp = &disk->next, disk = disk->next) {
+ if ((strncmp(disk->name, pathname, len) == 0) &&
+ (disk->name[len] == 0)) {
+ return (disk);
+ }
+ }
+ /* If not, then allocate a new structure and add it to the end of the list */
+ if ((*dkp = (disk_t*)malloc(sizeof(disk_t))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ /* Make 'disk' point to the newly allocated structure */
+ disk = *dkp;
+ if ((disk->name = malloc(len + 1)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ /* copy the name into place */
+ (void)strncpy(disk->name, pathname, len);
+ disk->name[len] = '\0';
+ /* Initialize 'part' and 'next' to NULL for now */
+ disk->part = NULL;
+ disk->next = NULL;
+ disk->pid = 0;
+ /* Increase total number of disks observed */
+ ndisks++;
+
+ /* Bubble out either the newly created disk_t or the one we found */
+ return (disk);
+}
+
+
+/*
+ * Add this partition to the list of devices to check.
+ */
+void addpart(char *name, char *fsname, char *vfstype) {
+ disk_t *disk;
+ part_t *part;
+ part_t **ppt;
+
+ /* Find the disk_t that corresponds to our element */
+ disk = finddisk(name);
+ ppt = &(disk->part);
+
+ /*
+ * Now iterate through all of the partitions of that disk.
+ * If we see our partition name already in there, then it means the entry
+ * was in the fstab more than once, which is bad.
+ */
+ for (part = disk->part; part; ppt = &part->next, part = part->next) {
+ if (strcmp(part->name, name) == 0) {
+ printf("%s in fstab more than once!\n", name);
+ return;
+ }
+ }
+
+ /* Hopefully we get here. Allocate a new partition structure for the disk */
+ if ((*ppt = (part_t*)malloc(sizeof(part_t))) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ part = *ppt;
+ if ((part->name = strdup(name)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+
+ /* Add the name & vfs info to the partition struct */
+ if ((part->fsname = strdup(fsname)) == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+ part->next = NULL;
+ part->vfstype = strdup(vfstype);
+ if (part->vfstype == NULL) {
+ fprintf(stderr, "out of memory");
+ exit (8);
+ }
+}
+
+/*
+ * Free the partition and its fields.
+ */
+void destroy_part (part_t *part) {
+ if (part->name) {
+ free (part->name);
+ }
+
+ if (part->fsname) {
+ free (part->fsname);
+ }
+
+ if (part->vfstype) {
+ free (part->vfstype);
+ }
+
+ free (part);
+}
+
+
+/*
+ * Ignore a single quit signal; wait and flush just in case.
+ * Used by child processes in preen mode.
+ */
+void
+ignore_single_quit(int sig) {
+
+ sleep(1);
+ (void)signal(SIGQUIT, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_DFL);
+}
+
+
+
diff --git a/diskdev_cmds/fsck.tproj/fsck.h b/diskdev_cmds/fsck.tproj/fsck.h
new file mode 100644
index 0000000..d602029
--- /dev/null
+++ b/diskdev_cmds/fsck.tproj/fsck.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __FSCK_H__
+#define __FSCK_H__
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fstab.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <string.h>
+
+/* Typedef Structures */
+
+/*
+ * Describes the current partition and
+ * contains a link to the next one if avail.
+ */
+typedef struct part {
+ struct part *next; /* forward link of partitions on disk */
+ char *name; /* device name */
+ char *fsname; /* mounted filesystem name */
+ char *vfstype; /* file system type (eg., "hfs" or "msdos") */
+} part_t;
+
+/*
+ * Disk structure that describes the device and contains the list
+ * of partitions available to the disk.
+ */
+typedef struct disk {
+ char *name; /* disk base name */
+ struct disk *next; /* forward link for list of disks */
+ struct part *part; /* head of list of partitions on disk */
+ int pid; /* If != 0, pid of proc working on */
+} disk_t;
+
+
+#define EEXIT 8 /* Standard Error exit code for fsck */
+#define _PATH_SBIN "/sbin" /* Path prefix used for fork/exec */
+
+#define ROOT_PASSNO 1 /* passno field for root FSes */
+#define NONROOT_PASSNO 2 /* passno field for non-root FSes */
+
+
+/* Function prototypes */
+int checkfstab(void);
+void catchquit(int sig);
+void catchsig(int sig);
+int fs_checkable (struct fstab *fsp);
+char *blockcheck(char *origname);
+char *rawname(char *name);
+char *unrawname(char *name);
+void addpart(char *name, char *fsname, char *vfstype);
+void destroy_part (part_t* part);
+disk_t *finddisk (char *name);
+int checkfilesys(disk_t *disk, int child);
+int check_fs(char *vfstype, char *filesys);
+void ignore_single_quit (int sig);
+int build_disklist(void);
+int do_diskchecks(void);
+
+
+#endif
+
+
+
diff --git a/diskdev_cmds/fstyp.tproj/fstyp.8 b/diskdev_cmds/fstyp.tproj/fstyp.8
new file mode 100644
index 0000000..fdc6ca2
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp.8
@@ -0,0 +1,41 @@
+.\"
+.\" (c) 2005 Apple Computer, Inc. All rights reserved.
+.\"
+.\" @APPLE_LICENSE_HEADER_START@
+.\"
+.\" The contents of this file constitute Original Code as defined in and
+.\" are subject to the Apple Public Source License Version 1.1 (the
+.\" "License"). You may not use this file except in compliance with the
+.\" License. Please obtain a copy of the License at
+.\" http://www.apple.com/publicsource and read it before using this file.
+.\"
+.\" This Original Code and all software distributed under the License are
+.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+.\" License for the specific language governing rights and limitations
+.\" under the License.
+.\"
+.\" @APPLE_LICENSE_HEADER_END@
+.\"
+.Dd August 15, 2005
+.Dt FSTYP 8
+.Os
+.Sh NAME
+.Nm fstyp
+.Nd identify a file system
+.Sh SYNOPSIS
+.Nm
+.Ar device
+.Sh DESCRIPTION
+The
+.Nm
+utility attempts to determine what sort of volume is present on the given
+device.
+It operates by iterating over directories that are typically part of the path,
+searching for files matching the pattern fstyp_* and running them.
+If it finds a match, it will print out the file system type name and exit with
+a return value of 1.
+If it does not find a match, it will not print out anything, and the return
+value will be 0.
diff --git a/diskdev_cmds/fstyp.tproj/fstyp.c b/diskdev_cmds/fstyp.tproj/fstyp.c
new file mode 100644
index 0000000..840c4aa
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sysexits.h>
+
+#define FSTYP_PREFIX "fstyp_"
+#define MAX_PATH_LEN 80
+#define MAX_CMD_LEN (MAX_PATH_LEN * 2)
+#define NULL_REDIRECTION ">/dev/null 2>&1"
+
+void usage(void);
+int select_fstyp(const struct dirent * dp);
+int test(const char *dir, const struct dirent * dp, const char *dev);
+void dealloc(struct dirent ** dpp, int numElems);
+
+char *progname;
+
+/*
+ * The fstyp command iterates through the binary directories to look for
+ * commands of the form fstyp_* and runs them, trying to find one that
+ * matches the given device. Once one of the returns success, fstyp
+ * prints out that file system type name and terminates. 1 is returned
+ * if any match is found, and 0 is returned if no match is found.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ /* NULL-terminated list of directories to search for fstyp_* commands */
+ const char *DIRS[] = { "/bin/",
+ "/sbin/",
+ "/usr/bin/",
+ "/usr/sbin/",
+ "/usr/local/bin/",
+ "/usr/local/sbin/",
+ NULL};
+
+ int numMatches, i, j, found;
+ struct stat sb;
+ struct dirent **dpp;
+
+ numMatches = 0;
+ i = 0;
+ j = 0;
+ found = 0;
+
+ if ((progname = strrchr(*argv, '/')))
+ ++progname;
+ else
+ progname = *argv;
+
+ if (argc != 2) {
+ usage();
+ return EX_USAGE;
+ }
+ if (0 == stat(argv[1], &sb)) {
+ for (i = 0; (!found && (NULL != DIRS[i])); i++) {
+ /*
+ * scan DIRS[i] for files that start with
+ * "fstyp_"
+ */
+ numMatches = scandir(DIRS[i], &dpp, select_fstyp, NULL);
+
+ if (numMatches >= 0) {
+ for (j = 0; (!found && (j < numMatches)); j++) {
+ if (test(DIRS[i], dpp[j], argv[1]) == 1) {
+ puts(dpp[j]->d_name + 6);
+
+ found = 1;
+ }
+ }
+
+ dealloc(dpp, numMatches);
+ dpp = NULL;
+ }
+ }
+ }
+ return found;
+}
+
+int
+select_fstyp(const struct dirent * dp)
+{
+ return ((dp != NULL) &&
+ ((dp->d_type == DT_REG) || (dp->d_type == DT_LNK)) &&
+ (dp->d_namlen > strlen(FSTYP_PREFIX)) &&
+ (!strncmp(FSTYP_PREFIX, dp->d_name, strlen(FSTYP_PREFIX))));
+}
+
+/* return dp if successful, else return NULL */
+int
+test(const char *dir, const struct dirent * dp, const char *dev)
+{
+ char cmd[MAX_CMD_LEN + 1] = {0};
+ int status;
+ FILE *fileptr;
+
+ status = 0;
+
+ /* + 1 for white space */
+ if ((strlen(dir) + dp->d_namlen + 1 + strlen(dev) +
+ strlen(NULL_REDIRECTION)) > MAX_CMD_LEN) {
+ return 0;
+ }
+ snprintf(cmd, sizeof(cmd), "%s%s %s", dir, dp->d_name, dev);
+
+ if ((fileptr = popen(cmd, "r")) != NULL) {
+ status = pclose(fileptr);
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 1) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void
+dealloc(struct dirent ** dpp, int numElems)
+{
+ int i;
+
+ for (i = 0; i < numElems; i++) {
+ free(dpp[i]);
+ dpp[i] = NULL;
+ }
+
+ free(dpp);
+
+ return;
+}
+
+
+void
+usage(void)
+{
+ fprintf(stdout, "usage: %s device\n", progname);
+ return;
+}
diff --git a/diskdev_cmds/fstyp.tproj/fstyp_msdos.8 b/diskdev_cmds/fstyp.tproj/fstyp_msdos.8
new file mode 100644
index 0000000..940bc78
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp_msdos.8
@@ -0,0 +1,41 @@
+.\"
+.\" (c) 2005 Apple Computer, Inc. All rights reserved.
+.\"
+.\" @APPLE_LICENSE_HEADER_START@
+.\"
+.\" The contents of this file constitute Original Code as defined in and
+.\" are subject to the Apple Public Source License Version 1.1 (the
+.\" "License"). You may not use this file except in compliance with the
+.\" License. Please obtain a copy of the License at
+.\" http://www.apple.com/publicsource and read it before using this file.
+.\"
+.\" This Original Code and all software distributed under the License are
+.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+.\" License for the specific language governing rights and limitations
+.\" under the License.
+.\"
+.\" @APPLE_LICENSE_HEADER_END@
+.\"
+.Dd August 15, 2005
+.Dt FSTYP_MSDOS 8
+.Os
+.Sh NAME
+.Nm fstyp_msdos
+.Nd check for an MSDOS FAT volume
+.Sh SYNOPSIS
+.Nm
+.Ar device
+.Sh DESCRIPTION
+The
+.Nm
+utility is not intended to be run directly, but rather called by
+.Xr fstyp 8
+while it is trying to determine which file system type is present on the
+given device.
+It returns 1 if it thinks the device contains an MSDOS FAT volume, and 0
+otherwise.
+.Sh SEE ALSO
+.Xr fstyp 8
diff --git a/diskdev_cmds/fstyp.tproj/fstyp_msdos.c b/diskdev_cmds/fstyp.tproj/fstyp_msdos.c
new file mode 100644
index 0000000..edf4551
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp_msdos.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/disk.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+/* copied from diskdev_cmds/fsck_msdos/dosfs.h */
+#define DOSBOOTBLOCKSIZE 512
+#define MAX_SECTOR_SIZE 4096
+
+#define E_OPENDEV -1
+#define E_READ -5
+
+void usage(void);
+char *rawname(char *name);
+char *unrawname(char *name);
+int checkVolHdr(const unsigned char *volhdr);
+char *blockcheck(char *origname);
+
+char *progname;
+
+/*
+ * prefer to use raw device. TODO: suppose block device is valid but
+ * the corresponding raw device is not valid, then we fail. this is
+ * probably no the desired behavior.
+ */
+
+int
+main(int argc, char **argv)
+{
+ unsigned char volhdr[MAX_SECTOR_SIZE] = {0};
+ int fd, retval;
+ char *devname;
+
+ fd = -1;
+ retval = 0;
+
+ if ((progname = strrchr(*argv, '/')))
+ ++progname;
+ else
+ progname = *argv;
+
+ if (argc != 2) {
+ usage();
+ } else {
+ devname = blockcheck(argv[1]);
+
+ if (devname != NULL) {
+ if ((fd = open(devname, O_RDONLY, 0)) < 0) {
+ retval = E_OPENDEV;
+ } else if (read(fd, volhdr, MAX_SECTOR_SIZE) != MAX_SECTOR_SIZE) {
+ retval = E_READ;
+ } else {
+ retval = checkVolHdr(volhdr);
+ }
+
+ if (-1 != fd) {
+ close(fd);
+ fd = -1;
+ }
+ }
+ }
+
+ return retval;
+}
+
+void
+usage(void)
+{
+ fprintf(stdout, "usage: %s device\n", progname);
+ return;
+}
+
+/* copied from diskdev_cmds/fsck_hfs/utilities.c */
+char *
+rawname(char *name)
+{
+ static char rawbuf[32];
+ char *dp;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (0);
+ *dp = 0;
+ (void) strlcpy(rawbuf, name, sizeof(rawbuf));
+ *dp = '/';
+ (void) strlcat(rawbuf, "/r", sizeof(rawbuf));
+ (void) strlcat(rawbuf, &dp[1], sizeof(rawbuf));
+
+ return (rawbuf);
+}
+
+/* copied from diskdev_cmds/fsck_hfs/utilities.c */
+char *
+unrawname(char *name)
+{
+ char *dp;
+ struct stat stb;
+ size_t dp_len;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (name);
+ if (stat(name, &stb) < 0)
+ return (name);
+ if ((stb.st_mode & S_IFMT) != S_IFCHR)
+ return (name);
+ if (dp[1] != 'r')
+ return (name);
+ dp_len = strlen(&dp[2]) + 1;
+ (void)memmove(&dp[1], &dp[2], dp_len);
+
+ return (name);
+}
+
+/*
+ * copied from diskdev_cmds/fsck_hfs/utilities.c, and modified:
+ * 1) remove "hotroot"
+ * 2) if error, return NULL
+ * 3) if not a char device, return NULL (effectively, this is treated
+ * as error even if accessing the block device might have been OK)
+ */
+char *
+blockcheck(char *origname)
+{
+ struct stat stblock, stchar;
+ char *newname, *raw;
+ int retried;
+
+ retried = 0;
+ newname = origname;
+retry:
+ if (stat(newname, &stblock) < 0) {
+ perror(newname);
+ fprintf(stderr, "Can't stat %s\n", newname);
+ return NULL;
+ }
+ if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
+ raw = rawname(newname);
+ if (stat(raw, &stchar) < 0) {
+ perror(raw);
+ fprintf(stderr, "Can't stat %s\n", raw);
+ return NULL;
+ }
+ if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
+ return (raw);
+ } else {
+ fprintf(stderr, "%s is not a character device\n", raw);
+ return NULL;
+ }
+ } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
+ newname = unrawname(newname);
+ retried++;
+ goto retry;
+ }
+ /* not a block or character device */
+ return NULL;
+}
+
+/*
+ * (sanity) check the volume header in volhdr
+ *
+ * return 1 if volhdr is a FAT volhdr, 0 otherwise
+ */
+int
+checkVolHdr(const unsigned char *volhdr)
+{
+ /* NTFS volumes have an OEMid of NTFS followed by four spaces. */
+ const char *ntfs_oemid = "NTFS ";
+ int retval;
+
+ retval = 1;
+
+ /* copied from diskdev_cmds/fsck_msdos/boot.c */
+
+ /*
+ * [2699033]
+ *
+ * The first three bytes are an Intel x86 jump instruction. It should
+ * be one of the following forms: 0xE9 0x?? 0x?? 0xEC 0x?? 0x90 where
+ * 0x?? means any byte value is OK.
+ */
+ if (volhdr[0] != 0xE9 && (volhdr[0] != 0xEB || volhdr[2] != 0x90)) {
+ retval = 0;
+ }
+ if (!memcmp(ntfs_oemid, volhdr + 3, 8))
+ retval = 0;
+ return retval;
+}
diff --git a/diskdev_cmds/fstyp.tproj/fstyp_ntfs.8 b/diskdev_cmds/fstyp.tproj/fstyp_ntfs.8
new file mode 100644
index 0000000..e5efa90
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp_ntfs.8
@@ -0,0 +1,41 @@
+.\"
+.\" (c) 2006 Apple Computer, Inc. All rights reserved.
+.\"
+.\" @APPLE_LICENSE_HEADER_START@
+.\"
+.\" The contents of this file constitute Original Code as defined in and
+.\" are subject to the Apple Public Source License Version 1.1 (the
+.\" "License"). You may not use this file except in compliance with the
+.\" License. Please obtain a copy of the License at
+.\" http://www.apple.com/publicsource and read it before using this file.
+.\"
+.\" This Original Code and all software distributed under the License are
+.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+.\" License for the specific language governing rights and limitations
+.\" under the License.
+.\"
+.\" @APPLE_LICENSE_HEADER_END@
+.\"
+.Dd September 30, 2006
+.Dt FSTYP_NTFS 8
+.Os
+.Sh NAME
+.Nm fstyp_ntfs
+.Nd check for a Windows NT File System (NTFS) volume
+.Sh SYNOPSIS
+.Nm
+.Ar device
+.Sh DESCRIPTION
+The
+.Nm
+utility is not intended to be run directly, but rather called by
+.Xr fstyp 8
+while it is trying to determine which file system type is present on the
+given device.
+It returns 1 if it thinks the device contains a Windows NT File System (NTFS)
+volume, and 0 otherwise.
+.Sh SEE ALSO
+.Xr fstyp 8
diff --git a/diskdev_cmds/fstyp.tproj/fstyp_ntfs.c b/diskdev_cmds/fstyp.tproj/fstyp_ntfs.c
new file mode 100644
index 0000000..88e7568
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp_ntfs.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/disk.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+/* copied from diskdev_cmds/fsck_msdos/dosfs.h */
+#define DOSBOOTBLOCKSIZE 512
+#define MAX_SECTOR_SIZE 4096
+
+#define E_OPENDEV -1
+#define E_READ -5
+
+void usage(void);
+char *rawname(char *name);
+char *unrawname(char *name);
+int checkVolHdr(const unsigned char *volhdr);
+char *blockcheck(char *origname);
+
+char *progname;
+
+/*
+ * prefer to use raw device. TODO: suppose block device is valid but
+ * the corresponding raw device is not valid, then we fail. this is
+ * probably no the desired behavior.
+ */
+
+int
+main(int argc, char **argv)
+{
+ unsigned char volhdr[MAX_SECTOR_SIZE] = {0};
+ int fd, retval;
+ char *devname;
+
+ fd = -1;
+ retval = 0;
+
+ if ((progname = strrchr(*argv, '/')))
+ ++progname;
+ else
+ progname = *argv;
+
+ if (argc != 2) {
+ usage();
+ } else {
+ devname = blockcheck(argv[1]);
+
+ if (devname != NULL) {
+ if ((fd = open(devname, O_RDONLY, 0)) < 0) {
+ retval = E_OPENDEV;
+ } else if (read(fd, volhdr, MAX_SECTOR_SIZE) != MAX_SECTOR_SIZE) {
+ retval = E_READ;
+ } else {
+ retval = checkVolHdr(volhdr);
+ }
+
+ if (-1 != fd) {
+ close(fd);
+ fd = -1;
+ }
+ }
+ }
+
+ return retval;
+}
+
+void
+usage(void)
+{
+ fprintf(stdout, "usage: %s device\n", progname);
+ return;
+}
+
+/* copied from diskdev_cmds/fsck_hfs/utilities.c */
+char *
+rawname(char *name)
+{
+ static char rawbuf[32];
+ char *dp;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (0);
+ *dp = 0;
+ (void) strlcpy(rawbuf, name, sizeof(rawbuf));
+ *dp = '/';
+ (void) strlcat(rawbuf, "/r", sizeof(rawbuf));
+ (void) strlcat(rawbuf, &dp[1], sizeof(rawbuf));
+
+ return (rawbuf);
+}
+
+/* copied from diskdev_cmds/fsck_hfs/utilities.c */
+char *
+unrawname(char *name)
+{
+ char *dp;
+ struct stat stb;
+ size_t dp_len;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (name);
+ if (stat(name, &stb) < 0)
+ return (name);
+ if ((stb.st_mode & S_IFMT) != S_IFCHR)
+ return (name);
+ if (dp[1] != 'r')
+ return (name);
+ dp_len = strlen(&dp[2]) + 1;
+ (void)memmove(&dp[1], &dp[2], dp_len);
+
+ return (name);
+}
+
+/*
+ * copied from diskdev_cmds/fsck_hfs/utilities.c, and modified:
+ * 1) remove "hotroot"
+ * 2) if error, return NULL
+ * 3) if not a char device, return NULL (effectively, this is treated
+ * as error even if accessing the block device might have been OK)
+ */
+char *
+blockcheck(char *origname)
+{
+ struct stat stblock, stchar;
+ char *newname, *raw;
+ int retried;
+
+ retried = 0;
+ newname = origname;
+retry:
+ if (stat(newname, &stblock) < 0) {
+ perror(newname);
+ fprintf(stderr, "Can't stat %s\n", newname);
+ return NULL;
+ }
+ if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
+ raw = rawname(newname);
+ if (stat(raw, &stchar) < 0) {
+ perror(raw);
+ fprintf(stderr, "Can't stat %s\n", raw);
+ return NULL;
+ }
+ if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
+ return (raw);
+ } else {
+ fprintf(stderr, "%s is not a character device\n", raw);
+ return NULL;
+ }
+ } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
+ newname = unrawname(newname);
+ retried++;
+ goto retry;
+ }
+ /* not a block or character device */
+ return NULL;
+}
+
+/*
+ * (sanity) check the volume header in volhdr
+ *
+ * return 1 if volhdr is a NTFS volhdr, 0 otherwise
+ */
+int
+checkVolHdr(const unsigned char *volhdr)
+{
+ /* NTFS volumes have an OEMid of NTFS followed by four spaces. */
+ const char *ntfs_oemid = "NTFS ";
+ int retval;
+
+ retval = 1;
+
+ /*
+ * Only check the OEMid. This should be sufficiently specific so it
+ * does not match anything else. If it ever does it would be easy to
+ * check more bootsector fields for validity...
+ */
+ if (memcmp(ntfs_oemid, volhdr + 3, 8))
+ retval = 0;
+ return retval;
+}
diff --git a/diskdev_cmds/fstyp.tproj/fstyp_udf.8 b/diskdev_cmds/fstyp.tproj/fstyp_udf.8
new file mode 100644
index 0000000..00efe55
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp_udf.8
@@ -0,0 +1,40 @@
+.\"
+.\" (c) 2005 Apple Computer, Inc. All rights reserved.
+.\"
+.\" @APPLE_LICENSE_HEADER_START@
+.\"
+.\" The contents of this file constitute Original Code as defined in and
+.\" are subject to the Apple Public Source License Version 1.1 (the
+.\" "License"). You may not use this file except in compliance with the
+.\" License. Please obtain a copy of the License at
+.\" http://www.apple.com/publicsource and read it before using this file.
+.\"
+.\" This Original Code and all software distributed under the License are
+.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+.\" License for the specific language governing rights and limitations
+.\" under the License.
+.\"
+.\" @APPLE_LICENSE_HEADER_END@
+.\"
+.Dd August 15, 2005
+.Dt FSTYP_UDF 8
+.Os
+.Sh NAME
+.Nm fstyp_udf
+.Nd check for a UDF volume
+.Sh SYNOPSIS
+.Nm
+.Ar device
+.Sh DESCRIPTION
+The
+.Nm
+utility is not intended to be run directly, but rather called by
+.Xr fstyp 8
+while it is trying to determine which file system type is present on the
+given device.
+It returns 1 if it thinks the device contains a UDF volume, and 0 otherwise.
+.Sh SEE ALSO
+.Xr fstyp 8
diff --git a/diskdev_cmds/fstyp.tproj/fstyp_udf.c b/diskdev_cmds/fstyp.tproj/fstyp_udf.c
new file mode 100644
index 0000000..7526524
--- /dev/null
+++ b/diskdev_cmds/fstyp.tproj/fstyp_udf.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fstab.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disk.h>
+
+#define E_OPENDEV -1
+#define E_READ -5
+
+/*
+ * We don't have a (non-C++) standard header for UDF (yet?), so
+ * let's define the basic structures and constants we'll be using.
+ */
+
+typedef struct UDFVolumeSequenceDescriptor {
+ unsigned char type;
+ unsigned char id[5];
+ unsigned char version;
+ unsigned char data[2041];
+} udfVSD;
+
+#define UDFSTART (32*1024) /* First 32k is unused */
+
+void usage(void);
+char *rawname(char *name);
+char *unrawname(char *name);
+int CheckUDF(int, int);
+char *blockcheck(char *origname);
+
+char *progname;
+
+/*
+ * prefer to use raw device. TODO: suppose block device is valid but
+ * the corresponding raw device is not valid, then we fail. this is
+ * probably no the desired behavior.
+ */
+
+int
+main(int argc, char **argv)
+{
+ char *devname = NULL;
+ int fd, retval;
+
+ retval = 0;
+ fd = -1;
+
+ if ((progname = strrchr(*argv, '/')))
+ ++progname;
+ else
+ progname = *argv;
+
+ if (argc != 2) {
+ usage();
+ } else {
+ devname = blockcheck(argv[1]);
+ if (devname != NULL) {
+ if ((fd = open(devname, O_RDONLY, 0)) < 0) {
+ retval = E_OPENDEV;
+ } else {
+ int bsize;
+ if (ioctl(fd, DKIOCGETBLOCKSIZE, (char*)&bsize) == -1) {
+#ifdef DEBUG
+ warn("DKIOCGETBLOCKSIZE ioctl failed for %s", devname);
+#endif
+ bsize = 2048; /* A standard default size */
+ }
+ retval = CheckUDF(fd, bsize) == 1;
+ if (retval == 0 && bsize != 2048) {
+ retval = CheckUDF(fd, 2048) == 1;
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+static int
+IsVSD(udfVSD *vsd) {
+ int retval = memcmp(vsd->id, "BEA01", 5)==0 ||
+ memcmp(vsd->id, "BOOT2", 5)==0 ||
+ memcmp(vsd->id, "NSR02", 5)==0 ||
+ memcmp(vsd->id, "NSR03", 5)==0 ||
+ memcmp(vsd->id, "TEA01", 5)==0 ||
+ memcmp(vsd->id, "CDW02", 5)==0 ||
+ memcmp(vsd->id, "CD001", 5)==0;
+#ifdef DEBUG
+ fprintf(stderr, "IsVSD: Returning %d\n", retval);
+#endif
+ return retval;
+}
+
+/*
+ * This is inspired by the udf25 kext code.
+ * It concludes that a device has a UDF filesystem
+ * if:
+ * 1) It has a Volume Sequence Descriptor;
+ * 2) That VSD has a "BEA01" in it;
+ * 3) That VSD has an "NSR02" or "NSR03" in it before the terminating one.
+ *
+ * It may be necessary to check the AVDP(s), as well.
+ */
+
+int
+CheckUDF(int fd, int blockSize) {
+ ssize_t err;
+ char buf[blockSize];
+ off_t curr, max;
+ char found = 0;
+
+ curr = UDFSTART;
+ max = curr + (512 * blockSize);
+ if (lseek(fd, curr, SEEK_SET) == -1) {
+ warn("Cannot seek to %llu", curr);
+ return -1;
+ }
+
+ while (curr < max) {
+ udfVSD *vsd;
+ err = read(fd, buf, sizeof(buf));
+ if (err != sizeof(buf)) {
+ if (err == -1) {
+ warn("Cannot read %zu bytes", sizeof(buf));
+ } else {
+ warn("Cannot read %zd bytes, only read %zd", sizeof(buf), err);
+ }
+ return -1;
+ }
+ vsd = (udfVSD*)buf;
+ if (!IsVSD(vsd)) {
+ break;
+ }
+ if (vsd->type == 0 &&
+ memcmp(vsd->id, "BEA01", 5) == 0 &&
+ vsd->version == 1) {
+ found = 1;
+ break;
+ }
+ curr += blockSize;
+ }
+ if (found == 0)
+ return 0;
+
+ found = 0;
+
+ while (curr < max) {
+ udfVSD *vsd;
+ err = read(fd, buf, sizeof(buf));
+ if (err != sizeof(buf)) {
+ if (err == -1) {
+ warn("Cannot read %zu bytes", sizeof(buf));
+ } else {
+ warn("Cannot read %zu bytes, only read %zd", sizeof(buf), err);
+ }
+ return -1;
+ }
+ vsd = (udfVSD*)buf;
+ if (!IsVSD(vsd)) {
+ break;
+ }
+ if (vsd->type == 0 &&
+ memcmp(vsd->id, "TEA01", 5) == 0 &&
+ vsd->version == 1) {
+ /* we're at the end */
+ break;
+ } else if (memcmp(vsd->id, "NSR02", 5) == 0 ||
+ memcmp(vsd->id, "NSR03", 5) == 0) {
+ found = 1;
+ break;
+ }
+ curr += blockSize;
+ }
+
+ return found;
+}
+
+void
+usage(void)
+{
+ fprintf(stdout, "usage: %s device\n", progname);
+ return;
+}
+
+/* copied from diskdev_cmds/fsck_hfs/utilities.c */
+char *
+rawname(char *name)
+{
+ static char rawbuf[32];
+ char *dp;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (0);
+ *dp = 0;
+ (void) strlcpy(rawbuf, name, sizeof(rawbuf));
+ *dp = '/';
+ (void) strlcat(rawbuf, "/r", sizeof(rawbuf));
+ (void) strlcat(rawbuf, &dp[1], sizeof(rawbuf));
+
+ return (rawbuf);
+}
+
+/* copied from diskdev_cmds/fsck_hfs/utilities.c */
+char *
+unrawname(char *name)
+{
+ char *dp;
+ struct stat stb;
+ size_t dp_len;
+
+ if ((dp = strrchr(name, '/')) == 0)
+ return (name);
+ if (stat(name, &stb) < 0)
+ return (name);
+ if ((stb.st_mode & S_IFMT) != S_IFCHR)
+ return (name);
+ if (dp[1] != 'r')
+ return (name);
+ dp_len = strlen(&dp[2]) + 1;
+ (void)memmove(&dp[1], &dp[2], dp_len);
+
+ return (name);
+}
+
+/*
+ * copied from diskdev_cmds/fsck_hfs/utilities.c, and modified:
+ * 1) remove "hotroot"
+ * 2) if error, return NULL
+ * 3) if not a char device, return NULL (effectively, this is treated
+ * as error even if accessing the block device might have been OK)
+ */
+char *
+blockcheck(char *origname)
+{
+ struct stat stblock, stchar;
+ char *newname, *raw;
+ int retried = 0;
+
+ newname = origname;
+retry:
+ if (stat(newname, &stblock) < 0) {
+ perror(newname);
+ fprintf(stderr, "Can't stat %s\n", newname);
+ return NULL;
+ }
+ if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
+ raw = rawname(newname);
+ if (stat(raw, &stchar) < 0) {
+ perror(raw);
+ fprintf(stderr, "Can't stat %s\n", raw);
+ return NULL;
+ }
+ if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
+ return (raw);
+ } else {
+ fprintf(stderr, "%s is not a character device\n", raw);
+ return NULL;
+ }
+ } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
+ newname = unrawname(newname);
+ retried++;
+ goto retry;
+ }
+#ifdef DEBUG
+ else if ((stblock.st_mode & S_IFMT) == S_IFREG) {
+ return strdup(origname);
+ }
+#endif
+ /* not a block or character device */
+ return NULL;
+}
+
+
diff --git a/diskdev_cmds/fuser.tproj/fuser.1 b/diskdev_cmds/fuser.tproj/fuser.1
new file mode 100644
index 0000000..fcaf5a2
--- /dev/null
+++ b/diskdev_cmds/fuser.tproj/fuser.1
@@ -0,0 +1,200 @@
+.\" Copyright (c) 2001-2003 The Open Group, All Rights Reserved
+.TH "FUSER" P 2003 "IEEE/The Open Group" "POSIX Programmer's Manual"
+.\" fuser
+.SH NAME
+fuser \- list process IDs of all processes that have one or more files
+open
+.SH SYNOPSIS
+.LP
+\fBfuser\fP \fB[\fP \fB-cfu\fP \fB]\fP \fIfile\fP \fB... \fP
+.SH DESCRIPTION
+.LP
+The \fIfuser\fP utility shall write to standard output the process
+IDs of processes running on the local system that have one
+or more named files open. For block special devices, all processes
+using any file on that device are listed.
+.LP
+The \fIfuser\fP utility shall write to standard error additional information
+about the named files indicating how the file is
+being used.
+.LP
+Any output for processes running on remote systems that have a named
+file open is unspecified.
+.LP
+A user may need appropriate privilege to invoke the \fIfuser\fP utility.
+.SH OPTIONS
+.LP
+The \fIfuser\fP utility shall conform to the Base Definitions volume
+of IEEE\ Std\ 1003.1-2001, Section 12.2, Utility Syntax Guidelines.
+.LP
+The following options shall be supported:
+.TP 7
+\fB-c\fP
+The file is treated as a mount point and the utility shall report
+on any files open in the file system.
+.TP 7
+\fB-f\fP
+The report shall be only for the named files.
+.TP 7
+\fB-u\fP
+The user name, in parentheses, associated with each process ID written
+to standard output shall be written to standard
+error.
+.sp
+.SH OPERANDS
+.LP
+The following operand shall be supported:
+.TP 7
+\fIfile\fP
+A pathname on which the file or file system is to be reported.
+.sp
+.SH STDIN
+.LP
+Not used.
+.SH INPUT FILES
+.LP
+The user database.
+.SH ENVIRONMENT VARIABLES
+.LP
+The following environment variables shall affect the execution of
+\fIfuser\fP:
+.TP 7
+\fILANG\fP
+Provide a default value for the internationalization variables that
+are unset or null. (See the Base Definitions volume of
+IEEE\ Std\ 1003.1-2001, Section 8.2, Internationalization Variables
+for
+the precedence of internationalization variables used to determine
+the values of locale categories.)
+.TP 7
+\fILC_ALL\fP
+If set to a non-empty string value, override the values of all the
+other internationalization variables.
+.TP 7
+\fILC_CTYPE\fP
+Determine the locale for the interpretation of sequences of bytes
+of text data as characters (for example, single-byte as
+opposed to multi-byte characters in arguments).
+.TP 7
+\fILC_MESSAGES\fP
+Determine the locale that should be used to affect the format and
+contents of diagnostic messages written to standard
+error.
+.TP 7
+\fINLSPATH\fP
+Determine the location of message catalogs for the processing of \fILC_MESSAGES
+\&.\fP
+.sp
+.SH ASYNCHRONOUS EVENTS
+.LP
+Default.
+.SH STDOUT
+.LP
+The \fIfuser\fP utility shall write the process ID for each process
+using each file given as an operand to standard output in
+the following format:
+.sp
+.RS
+.nf
+
+\fB"%d", <\fP\fIprocess_id\fP\fB>
+\fP
+.fi
+.RE
+.SH STDERR
+.LP
+The \fIfuser\fP utility shall write diagnostic messages to standard
+error.
+.LP
+The \fIfuser\fP utility also shall write the following to standard
+error:
+.IP " *" 3
+The pathname of each named file is written followed immediately by
+a colon.
+.LP
+.IP " *" 3
+For each process ID written to standard output, the character \fB'c'\fP
+shall be written to standard error if the process is
+using the file as its current directory and the character \fB'r'\fP
+shall be written to standard error if the process is using
+the file as its root directory. Implementations may write other alphabetic
+characters to indicate other uses of files.
+.LP
+.IP " *" 3
+When the \fB-u\fP option is specified, characters indicating the use
+of the file shall be followed immediately by the user
+name, in parentheses, corresponding to the process' real user ID.
+If the user name cannot be resolved from the process' real user
+ID, the process' real user ID shall be written instead of the user
+name.
+.LP
+.LP
+When standard output and standard error are directed to the same file,
+the output shall be interleaved so that the filename
+appears at the start of each line, followed by the process ID and
+characters indicating the use of the file. Then, if the \fB-u\fP
+option is specified, the user name or user ID for each process using
+that file shall be written.
+.LP
+A <newline> shall be written to standard error after the last output
+described above for each \fIfile\fP operand.
+.SH OUTPUT FILES
+.LP
+None.
+.SH EXTENDED DESCRIPTION
+.LP
+None.
+.SH EXIT STATUS
+.LP
+The following exit values shall be returned:
+.TP 7
+\ 0
+Successful completion.
+.TP 7
+>0
+An error occurred.
+.sp
+.SH CONSEQUENCES OF ERRORS
+.LP
+Default.
+.LP
+\fIThe following sections are informative.\fP
+.SH APPLICATION USAGE
+.LP
+None.
+.SH EXAMPLES
+.LP
+The command:
+.sp
+.RS
+.nf
+
+\fBfuser -fu .
+\fP
+.fi
+.RE
+.LP
+writes to standard output the process IDs of processes that are using
+the current directory and writes to standard error an
+indication of how those processes are using the directory and the
+user names associated with the processes that are using the
+current directory.
+.SH RATIONALE
+.LP
+The definition of the \fIfuser\fP utility follows existing practice.
+.SH FUTURE DIRECTIONS
+.LP
+None.
+.SH SEE ALSO
+.LP
+None.
+.SH COPYRIGHT
+Portions of this text are reprinted and reproduced in electronic form
+from IEEE Std 1003.1, 2003 Edition, Standard for Information Technology
+-- Portable Operating System Interface (POSIX), The Open Group Base
+Specifications Issue 6, Copyright (C) 2001-2003 by the Institute of
+Electrical and Electronics Engineers, Inc and The Open Group. In the
+event of any discrepancy between this version and the original IEEE and
+The Open Group Standard, the original IEEE and The Open Group Standard
+is the referee document. The original Standard can be obtained online at
+http://www.opengroup.org/unix/online.html .
diff --git a/diskdev_cmds/fuser.tproj/fuser.pl b/diskdev_cmds/fuser.tproj/fuser.pl
new file mode 100755
index 0000000..0784bfb
--- /dev/null
+++ b/diskdev_cmds/fuser.tproj/fuser.pl
@@ -0,0 +1,92 @@
+#!/usr/bin/perl -w
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+
+use strict;
+use Getopt::Long qw(GetOptions);
+
+sub usage {
+ print "fuser: [-cfu] file ...\n",
+ "\t-c\tfile is treated as mount point\n",
+ "\t-f\tthe report is only for the named files\n",
+ "\t-u\tprint username of pid in parenthesis\n";
+}
+
+Getopt::Long::config('bundling');
+my %o;
+unless (GetOptions(\%o, qw(c f u)) && scalar (@ARGV) > 0) {
+ usage();
+ exit(1);
+}
+
+use IO::Handle;
+STDERR->autoflush(1);
+STDOUT->autoflush(1);
+
+my $exit_value = 0;
+
+my $space = "";
+while (scalar (@ARGV)) {
+ my $file = shift @ARGV;
+ if (-e $file) {
+ my @command;
+ push(@command, q(/usr/sbin/lsof));
+ push(@command, q(-F));
+ if ($o{u}) { # Add user name
+ push(@command, q(pfL));
+ } else {
+ push(@command, q(pf));
+ }
+ push(@command, q(-f)) if ($o{f});
+ push(@command, q(--));
+ push(@command, $file);
+ # This cryptic statement will cause exec(@command) to run in the child,
+ # with the output set up correctl and LSOF's input set up correctly.
+ open (LSOF, "-|") or exec(@command);
+ my @results = <LSOF>;
+ chomp(@results);
+ # fuser man page is very explicit about stdout/stderr output
+ print STDERR $file, qq(: );
+ my $username = "";
+ foreach (@results) {
+ if (/^p(\d+)$/) {
+ if ($username) {
+ print STDERR $username;
+ $username = "";
+ }
+ print $space, $1;
+ $space = q( );
+ }
+ if (/^f(c|r)[wt]d$/) {
+ print STDERR "$1" . $username;
+ $username = "";
+ }
+ $username = "(" . $1 . ")" if (/^L(.+)$/);
+ }
+ print STDERR $username . qq(\n);
+ } else {
+ print STDERR "$0: '$file' does not exist\n";
+ $exit_value = 1;
+ }
+}
+exit($exit_value);
diff --git a/diskdev_cmds/mount.tproj/fstab.5 b/diskdev_cmds/mount.tproj/fstab.5
new file mode 100644
index 0000000..0ba6dc7
--- /dev/null
+++ b/diskdev_cmds/mount.tproj/fstab.5
@@ -0,0 +1,222 @@
+.\" $NetBSD: fstab.5,v 1.5.2.1 1995/11/16 20:11:11 pk Exp $
+.\"
+.\" Copyright (c) 1980, 1989, 1991, 1993, 2002
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fstab.5 8.1 (Berkeley) 6/5/93
+.\"
+.Dd March 28, 2002
+.Dt FSTAB 5
+.Os Darwin
+.Sh NAME
+.Nm fstab
+.Nd static information about the filesystems
+.Sh SYNOPSIS
+.Fd #include <fstab.h>
+.Sh DESCRIPTION
+The file
+.Nm fstab
+contains descriptive information about the various file
+systems.
+.Nm fstab
+is only read by programs, and not written;
+it is the duty of the system administrator to properly create
+and maintain this file, using the
+.Xr vifs 8
+command.
+Each filesystem is described on a separate line;
+fields on each line are separated by tabs or spaces.
+The order of records in
+.Nm fstab
+is important because
+.Xr diskarbitrationd 8 ,
+.Xr fsck 8 ,
+.Xr mount 8 ,
+and
+.Xr umount 8
+sequentially iterate through
+.Nm fstab
+doing their thing.
+.Pp
+The first field,
+.Pq Fa fs_spec ,
+describes the block special device, the local filesystem, or
+the remote filesystem to be mounted. The
+.Xr diskarbitrationd
+program supports the identification of a local filesystem uniquely by its
+UUID or by its volume name, irrespective of hardware configuration and of
+hardware parallelism, using the constructs ``UUID'' and ``LABEL''.
+For APFS volumes, this field should never be the block special device as it is
+not constant. Only the constructs ``UUID'' and ``LABEL'' should be used.
+.Pp
+The second field,
+.Pq Fa fs_file ,
+describes the mount point for the filesystem.
+For swap partitions, this field should be specified as ``none''.
+.Pp
+The third field,
+.Pq Fa fs_vfstype ,
+describes the type of the filesystem.
+The system currently supports different filesystem types, including the following:
+.Bl -tag -width indent -offset indent
+.It Em apfs
+APFS is the Mac OS X default filesystem since version 10.13 (High Sierra).
+.It Em hfs
+HFS+ is the previous Mac OS X default filesystem.
+.It Em nfs
+a Sun Microsystems compatible ``Network File System''
+.It Em msdos
+a DOS compatible filesystem
+.It Em cd9660
+a CD-ROM filesystem (as per ISO 9660)
+.It Em fdesc
+an implementation of /dev/fd
+.It Em union
+a translucent filesystem
+.El
+.Pp
+The fourth field,
+.Pq Fa fs_mntops ,
+describes the mount options associated with the filesystem.
+It is formatted as a comma separated list of options.
+It contains at least the type of mount (see
+.Fa fs_type
+below) plus any additional options
+appropriate to the filesystem type.
+.Pp
+The option ``auto'' can be used in the ``noauto'' form to cause
+a file system not to be mounted automatically (with ``mount -a'',
+or system boot time).
+.Pp
+The type of the mount is extracted from the
+.Fa fs_mntops
+field and stored separately in the
+.Fa fs_type
+field (it is not deleted from the
+.Fa fs_mntops
+field).
+If
+.Fa fs_type
+is ``rw'' or ``ro'' then the filesystem whose name is given in the
+.Fa fs_file
+field is normally mounted read-write or read-only on the
+specified special file.
+If
+.Fa fs_type
+is ``sw'' then the special file is made available as a piece of swap
+space by the
+.Xr swapon 8
+command at the end of the system reboot procedure.
+The fields other than
+.Fa fs_spec
+and
+.Fa fs_type
+are unused.
+If
+.Fa fs_type
+is specified as ``xx'' the entry is ignored.
+This is useful to show disk partitions which are currently unused.
+.Pp
+The fifth field,
+.Pq Fa fs_freq ,
+is used for these filesystems by the
+.Xr dump 8
+command to determine which filesystems need to be dumped.
+If the fifth field is not present, a value of zero is returned and
+.Xr dump
+will assume that the filesystem does not need to be dumped.
+.Pp
+The sixth field,
+.Pq Fa fs_passno ,
+is used by the
+.Xr fsck 8
+program to determine the order in which filesystem checks are done
+at reboot time.
+The root filesystem should be specified with a
+.Fa fs_passno
+of 1, and other filesystems should have a
+.Fa fs_passno
+of 2.
+Filesystems within a drive will be checked sequentially,
+but filesystems on different drives will be checked at the
+same time to utilize parallelism available in the hardware.
+If the sixth field is not present or zero,
+a value of zero is returned and
+.Xr fsck
+will assume that the filesystem does not need to be checked.
+.Bd -literal
+#define FSTAB_RW "rw" /* read-write device */
+#define FSTAB_RO "ro" /* read-only device */
+#define FSTAB_SW "sw" /* swap device */
+#define FSTAB_XX "xx" /* ignore totally */
+
+struct fstab {
+ char *fs_spec; /* block special device name */
+ char *fs_file; /* filesystem path prefix */
+ char *fs_vfstype; /* type of filesystem */
+ char *fs_mntops; /* comma separated mount options */
+ char *fs_type; /* rw, ro, sw, or xx */
+ int fs_freq; /* dump frequency, in days */
+ int fs_passno; /* pass number on parallel fsck */
+};
+.Ed
+.Pp
+The proper way to read records from
+.Pa fstab
+is to use the routines
+.Xr getfsent 3 ,
+.Xr getfsspec 3 ,
+.Xr getfstype 3 ,
+and
+.Xr getfsfile 3 .
+.Sh EXAMPLES
+.Bd -literal
+UUID=2A1B02AD-467D-403A-8CCD-B87E50AD3DA2 none apfs rw
+UUID=DF000C7E-AE0C-3B15-B730-DFD2EF15CB91 /export apfs ro
+UUID=FAB060E9-79F7-33FF-BE85-E1D3ABD3EDEA none hfs rw,noauto
+LABEL=The\\040Volume\\040Name\\040Is\\040This none msdos ro
+.Ed
+.Sh FILES
+.Bl -tag -width /etc/fstab -compact
+.It Pa /etc/fstab
+The file
+.Nm fstab
+resides in
+.Pa /etc .
+.El
+.Sh SEE ALSO
+.Xr getfsent 3 ,
+.Xr diskarbitrationd 8
+.Sh HISTORY
+The
+.Nm
+file format appeared in
+.Bx 4.0 .
diff --git a/diskdev_cmds/mount.tproj/mount.8 b/diskdev_cmds/mount.tproj/mount.8
new file mode 100644
index 0000000..d07ff8d
--- /dev/null
+++ b/diskdev_cmds/mount.tproj/mount.8
@@ -0,0 +1,293 @@
+.\" Copyright (c) 1980, 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mount.8 8.8 (Berkeley) 6/16/94
+.\"
+.Dd June 16, 1994
+.Dt MOUNT 8
+.Os BSD 4
+.Sh NAME
+.Nm mount
+.Nd mount file systems
+.Sh SYNOPSIS
+.Nm mount
+.Op Fl adfruvw
+.Op Fl t Ar lfs | external_type
+.Nm mount
+.Op Fl dfruvw
+.Ar special | mount_point
+.Nm mount
+.Op Fl dfruvw
+.Op Fl o Ar options
+.Op Fl t Ar lfs | external_type
+.Ar special mount_point
+.Sh DESCRIPTION
+The
+.Nm mount
+command
+calls the
+.Xr mount 2
+system call to prepare and graft a
+.Ar "special device"
+or the remote node (rhost:path) on to the file system tree at the point
+.Ar mount_point ,
+which must be a directory. If either
+.Ar special
+or
+.Ar mount_point
+are not provided, the appropriate information is obtained via the
+.Xr getfsent 3
+library routines.
+.Pp
+The system maintains a list of currently mounted file systems.
+If no arguments are given to
+.Nm mount,
+this list is printed.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+All the filesystems listed via
+.Xr getfsent 3
+are mounted.
+Exceptions are those marked as ``noauto;'' excluded by the
+.Fl t
+flag (see below); entries that are neither ``ro,'' ``rw,'' or
+``rq;'' ``nfs'' entries that also have ``net'' as an option; and
+already-mounted ``nfs'' entries.
+.It Fl d
+Causes everything to be done except for the actual system call.
+This option is useful in conjunction with the
+.Fl v
+flag to
+determine what the
+.Nm mount
+command is trying to do.
+.It Fl f
+Forces the revocation of write access when trying to downgrade
+a filesystem mount status from read-write to read-only.
+.It Fl o
+Options are specified with a
+.Fl o
+flag followed by a comma separated string of options.
+The following options are available:
+.Bl -tag -width indent
+.It async
+All
+.Tn I/O
+to the file system should be done asynchronously.
+This can be somewhat dangerous with respect to losing data when faced with
+system crashes and power outages.
+This is also the default.
+It can be avoided with the
+.Em noasync
+option.
+.It force
+The same as
+.Fl f ;
+forces the revocation of write access when trying to downgrade
+a filesystem mount status from read-write to read-only.
+.It noasync
+This filesystem should not force all
+.Tn I/O
+to be written asynchronously.
+.It noauto
+This filesystem should be skipped when mount is run with the
+.Fl a
+flag.
+.It nodev
+Do not interpret character or block special devices on the file system.
+This option is useful for a server that has file systems containing
+special devices for architectures other than its own.
+.It noexec
+Do not allow execution of any binaries on the mounted file system.
+This option is useful for a server that has file systems containing
+binaries for architectures other than its own.
+.It noowners
+Ignore the ownership field for the entire volume.
+This causes all objects to appear as owned by user ID 99 and group ID 99.
+User ID 99 is interpreted as the current effective user ID, while group ID 99
+is used directly and translates to ``unknown''.
+.It nosuid
+Do not allow set-user-identifier or set-group-identifier bits to take effect.
+.It rdonly
+The same as
+.Fl r ;
+mount the file system read-only (even the super-user may not write it).
+.It sync
+All
+.Tn I/O
+to the file system should be done synchronously.
+.It update
+The same as
+.Fl u ;
+indicate that the status of an already mounted file system should be changed.
+.It union
+Causes the namespace to appear as the union of directories
+of the mounted filesystem with corresponding directories in the
+underlying filesystem.
+Lookups will be done in the mounted filesystem first.
+If those operations fail due to a non-existent file the underlying
+directory is then accessed.
+.It noatime
+Do not update the file access time when reading from a file.
+This option is useful on file systems where there are large numbers of files
+and performance is more critical than updating the file access time (which
+is rarely ever important).
+.It strictatime
+Always update the file access time when reading from a file. Without this option the
+filesystem may default to a less strict update mode, where some access time updates
+are skipped for performance reasons. This option could be ignored if it is not supported
+by the filesystem.
+.It nobrowse
+This option indicates that the mount point should not be visible
+via the GUI (i.e., appear on the Desktop as a separate volume).
+.El
+.Pp
+Any additional options specific to a filesystem type that is not
+one of the internally known types (see the
+.Fl t
+option) may be passed as a comma separated list; these options are
+distinguished by a leading
+.Dq \&-
+(dash).
+Options that take a value are specified using the syntax -option=value.
+For example, the mount command:
+.Bd -literal -offset indent
+mount -t hfs -o nosuid,-w,-m=755 /dev/disk2s9 /tmp
+.Ed
+.Pp
+causes
+.Nm mount
+to execute the equivalent of:
+.Bd -literal -offset indent
+/sbin/mount_hfs -o nosuid -w -m 755 /dev/disk2s9 /tmp
+.Ed
+.It Fl r
+Mount the file system read-only (even the super-user may not write it).
+The same as the
+.Dq rdonly
+argument to the
+.Fl o
+option.
+.It Fl t Ar "lfs \\*(Ba external type"
+The argument following the
+.Fl t
+is used to indicate the file system type.
+There is no default local file system for use with mount. A type must
+be specified in order to mount a non-NFS filesystem.
+The \fI-t\fP option can be used
+to indicate that the actions should only be taken on
+filesystems of the specified type.
+More than one type may be specified in a comma separated list.
+The list of filesystem types can be prefixed with
+.Dq no
+to specify the filesystem types for which action should
+.Em not
+be taken.
+For example, the
+.Nm mount
+command:
+.Bd -literal -offset indent
+mount -a -t nonfs,hfs
+.Ed
+.Pp
+mounts all filesystems except those of type
+.Tn NFS
+and
+.Tn HFS .
+.Pp
+If the type is not one of the internally known types,
+mount will attempt to execute a program in
+.Pa /sbin/mount_ Ns Em XXX
+where
+.Em XXX
+is replaced by the type name.
+For example, nfs filesystems are mounted by the program
+.Pa /sbin/mount_nfs .
+.It Fl u
+The
+.Fl u
+flag indicates that the status of an already mounted file
+system should be changed.
+Any of the options discussed above (the
+.Fl o
+option)
+may be changed;
+also a file system can be changed from read-only to read-write
+or vice versa.
+An attempt to change from read-write to read-only will fail if any
+files on the filesystem are currently open for writing unless the
+.Fl f
+flag is also specified.
+The set of options is determined by first extracting the options
+for the file system from the
+filesystem table (see
+.Xr getfsent 3 )
+then applying any options specified by the
+.Fl o
+argument,
+and finally applying the
+.Fl r
+or
+.Fl w
+option.
+.It Fl v
+Verbose mode.
+.It Fl w
+Mount the file system read-write.
+.Pp
+The options specific to NFS filesystems are described in the
+.Xr mount_nfs 8
+manual page.
+.El
+.Sh SEE ALSO
+.Xr mount 2 ,
+.Xr getfsent 3 ,
+.Xr mount_afp 8 ,
+.Xr mount_cd9660 8 ,
+.Xr mount_cddafs 8 ,
+.Xr mount_fdesc 8 ,
+.Xr mount_hfs 8 ,
+.Xr mount_apfs 8 ,
+.Xr mount_msdos 8 ,
+.Xr mount_nfs 8 ,
+.Xr mount_smbfs 8 ,
+.Xr mount_udf 8 ,
+.Xr mount_webdav 8 ,
+.Xr umount 8
+.Sh BUGS
+It is possible for a corrupted file system to cause a crash.
+.Sh HISTORY
+A
+.Nm mount
+command appeared in
+.At v6 .
diff --git a/diskdev_cmds/mount.tproj/mount.c b/diskdev_cmds/mount.tproj/mount.c
new file mode 100644
index 0000000..ace7cbe
--- /dev/null
+++ b/diskdev_cmds/mount.tproj/mount.c
@@ -0,0 +1,1696 @@
+/*
+ * Copyright (c) 1999-2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1980, 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <System/sys/reason.h>
+#include <err.h>
+#include <os/errno.h>
+#include <os/bsd.h>
+#include <os/variant_private.h>
+#include <fstab.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <TargetConditionals.h>
+#include <sysexits.h>
+#include <sys/sysctl.h>
+#include <APFS/APFS.h>
+#include <APFS/APFSConstants.h>
+#include <pthread.h>
+#include <spawn.h>
+#include <crt_externs.h>
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+#include <paths.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/cdefs.h>
+
+/* Some APFS specific goop */
+#include <copyfile.h>
+#include <MediaKit/MKMedia.h>
+#include <MediaKit/MKMediaAccess.h>
+#include <MediaKit/GPTTypes.h>
+#endif
+
+#if TARGET_OS_OSX
+// To unmount the BaseSystem disk image.
+#include <paths.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOMedia.h>
+#endif
+
+#include "mount_flags.h"
+#include "edt_fstab.h"
+#include "pathnames.h"
+#include "fsck.h"
+
+#if TARGET_OS_OSX
+#define APFS_BOOT_UTIL_PATH "/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs_boot_util"
+#define PLATFORM_DATA_VOLUME_MOUNT_POINT "/System/Volumes/Data"
+#define BASE_SYSTEM_PATH "/System/Volumes/BaseSystem"
+#define RECOVERY_PATH "/System/Volumes/Recovery"
+#else
+#define APFS_BOOT_UTIL_PATH "/System/Library/Filesystems/apfs.fs/apfs_boot_util"
+#define PLATFORM_DATA_VOLUME_MOUNT_POINT "/private/var"
+#endif
+
+#define environ (*_NSGetEnviron())
+#define COMMAND_OUTPUT_MAX 1024
+
+int debug;
+int verbose;
+int bootstrap_macos = 0;
+int passno = 0;
+
+int checkvfsname __P((const char *, const char **));
+char *catopt __P((char *, const char *));
+struct statfs *getmntpt __P((const char *));
+int hasopt __P((const char *, const char *));
+const char
+ **makevfslist __P((char *));
+void mangle __P((char *, int *, const char **));
+void prmount __P((struct statfs *));
+void usage __P((void));
+
+int run_command(char **command_argv, char *output, int *rc, int *signal_no);
+void print_mount(const char **vfslist);
+int ismounted(const char *fs_spec, const char *fs_file, long *flags);
+int mountfs(const char *vfstype, const char *fs_spec, const char *fs_file, int flags, const char *options, const char *mntopts);
+int unmount_location(char *mount_point);
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+
+char* parse_parameter_for_token(char * opts, char * search_string);
+int verify_executable_file_existence (char *path);
+int verify_file_existence (char *path);
+int _verify_file_flags (char *path, int flags);
+int preflight_create_mount_ramdisk (char *mnt_opts, size_t *ramdisk_size, char *template);
+char* split_ramdisk_params(char *opts);
+int create_mount_ramdisk(struct fstab *fs, int init_flags, char *options);
+int construct_apfs_volume(char *mounted_device_name);
+int create_partition_table(size_t partition_size, char *device);
+int attach_device(size_t device_size , char* deviceOut);
+void truncate_whitespace(char* str);
+
+#define RAMDISK_BLCK_OFFSET 34
+#define RAMDISK_TMP_MOUNT "/mnt2"
+#define RAMDISK_BCK_MOUNT "/.mb"
+#define RAMDISK_SIZE_TOK "size="
+#define RAMDISK_TPLT_TOK "template="
+#define HDIK_PATH "/usr/sbin/hdik"
+
+#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
+
+//pull in the optnames array from the mount_flags.c file
+extern mountopt_t optnames[];
+#if TARGET_OS_OSX
+static int booted_rosv(void);
+static int booted_apfs(void);
+#endif /* TARGET_OS_OSX */
+static int upgrade_mount(const char *mountpt, int init_flags, char *options);
+
+/*
+ * Map a POSIX error code to a representative sysexits(3) code. Can be disabled
+ * to exit with errno error code by passing -e as a command line argument to mount
+ */
+static int ret_errno = 0;
+static inline int
+errno_or_sysexit(int err, int sysexit)
+{
+ if (sysexit == -1) {
+ sysexit = sysexit_np(err);
+ }
+ return (ret_errno ? err : sysexit);
+}
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+#define BINDFS_MOUNT_TYPE "bindfs"
+#define PREBOOT_VOL_MOUNTPOINT "/private/preboot"
+#define HARDWARE_VOL_MOUNTPOINT "/private/var/hardware"
+
+#define BOOT_MANIFEST_HASH_LEN 256
+
+typedef struct bind_mount {
+ char *bm_mnt_prefix;
+ char *bm_mnt_to;
+ bool bm_mandatory;
+} bind_mount_t;
+
+static void
+do_bindfs_mount(char *from, const char *to, bool required)
+{
+ struct statfs sfs;
+ uint32_t mnt_flags = MNT_RDONLY | MNT_NODEV | MNT_NOSUID | MNT_DONTBROWSE;
+ int err = 0;
+
+ if (debug) {
+ printf("call: mount %s %s %x %s", BINDFS_MOUNT_TYPE, to, mnt_flags, from);
+ return;
+ }
+
+ if ((statfs(from, &sfs) == 0) &&
+ (strncmp(sfs.f_fstypename, BINDFS_MOUNT_TYPE, sizeof(BINDFS_MOUNT_TYPE)) == 0)) {
+ return;
+ }
+
+ err = mount(BINDFS_MOUNT_TYPE, to, mnt_flags, from);
+ if (err) {
+ if ((errno == ENOENT) && !required) {
+ err = 0;
+ } else {
+ errx(errno_or_sysexit(errno, -1), "failed to mount %s -> %s - %s(%d)",
+ from, to, strerror(errno), errno);
+ }
+ }
+}
+
+static void
+setup_preboot_mounts(int pass)
+{
+ int err = 0;
+ const char *mnt_to;
+ char mnt_from[MAXPATHLEN], boot_manifest_hash[BOOT_MANIFEST_HASH_LEN];
+
+ err = get_boot_manifest_hash(boot_manifest_hash, sizeof(boot_manifest_hash));
+ if (err) {
+ errx(errno_or_sysexit(err, -1), "failed to get boot manifest hash - %s",
+ strerror(err));
+ }
+
+ const bind_mount_t preboot_mnts[] = {
+ {.bm_mnt_prefix = PREBOOT_VOL_MOUNTPOINT,
+ .bm_mnt_to = "/usr/standalone/firmware",
+ .bm_mandatory = true},
+ {.bm_mnt_prefix = PREBOOT_VOL_MOUNTPOINT,
+ .bm_mnt_to = "/usr/local/standalone/firmware",
+ .bm_mandatory = false}
+ };
+
+ const bind_mount_t hw_mnts[] = {
+ {.bm_mnt_prefix = HARDWARE_VOL_MOUNTPOINT "/Pearl",
+ .bm_mnt_to = "/System/Library/Pearl/ReferenceFrames",
+ .bm_mandatory = false},
+ {.bm_mnt_prefix = HARDWARE_VOL_MOUNTPOINT "/FactoryData",
+ .bm_mnt_to = "/System/Library/Caches/com.apple.factorydata",
+ .bm_mandatory = true}
+ };
+
+ if (pass == ROOT_PASSNO) {
+ for (int i = 0; i < (sizeof(preboot_mnts) / sizeof(preboot_mnts[0])); i++) {
+ mnt_to = preboot_mnts[i].bm_mnt_to;
+ snprintf(mnt_from, sizeof(mnt_from), "%s/%s%s",
+ preboot_mnts[i].bm_mnt_prefix, boot_manifest_hash, mnt_to);
+
+ do_bindfs_mount(mnt_from, mnt_to, preboot_mnts[i].bm_mandatory);
+ }
+ } else {
+ for (int i = 0; i < (sizeof(hw_mnts) / sizeof(hw_mnts[0])); i++) {
+ mnt_to = hw_mnts[i].bm_mnt_to;
+ snprintf(mnt_from, sizeof(mnt_from), "%s%s",
+ hw_mnts[i].bm_mnt_prefix, mnt_to);
+
+ do_bindfs_mount(mnt_from, mnt_to, hw_mnts[i].bm_mandatory);
+ }
+ }
+}
+#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
+
+/*
+ * mount phases to be used during boot to perform the following operations:
+ * first phase:
+ * TARGET_OS_OSX: (call `apfs_boot_util 1`
+ * TARGET_OS_IPHONE: mount System, Preboot and xART volumes (if present)
+ *
+ * second phase:
+ * TARGET_OS_OSX: unmount base system DMG if needed, upgrade System
+ * volume to RW, and call `apfs_boot_util 2` (on ROSV config)
+ * TARGET_OS_IPHONE: mount remaining volumes
+ *
+ * For more info on mount phases, see apfs_boot_util.
+ */
+#define MOUNT_PHASE_1 1 /* first phase */
+#define MOUNT_PHASE_2 2 /* second phase */
+
+#define NONFS "nonfs"
+
+static void
+bootstrap_apfs(int phase)
+{
+ char * const apfs_util_argv[] = {
+ APFS_BOOT_UTIL_PATH,
+ ((phase == MOUNT_PHASE_1) ? "1" : ((phase == MOUNT_PHASE_2) ? "2" : NULL)),
+ NULL,
+ };
+ execv(APFS_BOOT_UTIL_PATH, apfs_util_argv);
+ errx(errno_or_sysexit(errno, -1), "apfs_boot_util exec failed");
+}
+
+int
+main(argc, argv)
+ int argc;
+ char * const argv[];
+{
+ const char **vfslist, *vfstype;
+ struct fstab *fs;
+ struct statfs *mntbuf;
+ int all, ch, init_flags, rval;
+ char *options, *ep;
+ int mount_phase = 0;
+
+ all = init_flags = 0;
+ options = NULL;
+ vfslist = NULL;
+ vfstype = NULL;
+
+ while ((ch = getopt(argc, argv, "headfo:rwt:uvP:")) != EOF)
+ switch (ch) {
+ case 'a':
+ all = 1;
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'f':
+ init_flags |= MNT_FORCE;
+ break;
+ case 'o':
+ if (*optarg) {
+ options = catopt(options, optarg);
+ if (strstr(optarg, "union"))
+ init_flags |= MNT_UNION;
+ }
+ break;
+ case 'r':
+ init_flags |= MNT_RDONLY;
+ break;
+ case 't':
+ if (vfslist != NULL)
+ errx(errno_or_sysexit(EINVAL, EX_USAGE),
+ "only one -t option may be specified.");
+ vfslist = makevfslist(optarg);
+ vfstype = optarg;
+ break;
+ case 'u':
+ init_flags |= MNT_UPDATE;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'w':
+ init_flags &= ~MNT_RDONLY;
+ break;
+ case 'e':
+ ret_errno = 1;
+ break;
+ case 'P':
+ /* only allowed to specify 1 or 2 as argument here */
+ mount_phase = (int)strtol(optarg, &ep, 10);
+ if ((ep == optarg) || (*ep) ||
+ (mount_phase < MOUNT_PHASE_1) ||
+ (mount_phase > MOUNT_PHASE_2)) {
+ errx(errno_or_sysexit(EINVAL, EX_USAGE),
+ "-P flag requires a valid mount phase number");
+ }
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ argc -= optind;
+ argv += optind;
+
+#define BADTYPE(type) \
+ (strcmp(type, FSTAB_RO) && \
+ strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
+
+// mount boot tasks
+ if (mount_phase != 0) {
+#if TARGET_OS_OSX
+ bootstrap_macos = 1;
+#else /* !TARGET_OS_OSX */
+ if (mount_phase == MOUNT_PHASE_1) {
+ /* mount -vat -nonfs -P 1 */
+ passno = ROOT_PASSNO;
+ } else if (mount_phase == MOUNT_PHASE_2) {
+ /* mount -vat -nonfs -R 2 */
+ passno = NONROOT_PASSNO;
+ }
+ verbose = 1;
+ all = 1;
+ vfslist = makevfslist(NONFS);
+ vfstype = NONFS;
+#endif /* !TARGET_OS_OSX */
+ }
+
+ rval = 0;
+ switch (argc) {
+ case 0:
+ /*
+ * Note - mount should never be called with "-a" on OSX
+ * as per fstab(5) - you may insert entries with UUID=,LABEL=
+ * and mount(8) has no knowledge of these entries
+ */
+ if (all) {
+ int err = 0;
+ long fs_flags = 0;
+
+ if ((setfsent() == 0)) {
+ errx(errno_or_sysexit(errno ? errno : ENXIO, -1),
+ "mount: can't get filesystem checklist");
+ }
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ uint32_t os_env;
+ const char *container_dev = get_boot_container(&os_env);
+ const char *data_vol_dev = get_data_volume();
+ /*
+ * It is a given that the boot container must be present
+ * in order to locate the data volume.
+ *
+ * The data volume is required if it is present in the EDT.
+ * This is always the case when booting the main OS (EDT_OS_ENV_MAIN),
+ * however there are some exceptions.
+ *
+ * When the data volume is required,
+ * we defer checking it is present until the second mount-phase,
+ * when the data volume is actually mounted, in order to allow
+ * MobileObliteration the opportunity to fix the container or fail gracefully.
+ */
+ if (data_vol_dev) {
+ fprintf(stdout, "mount: found boot container: %s, data volume: %s env: %u\n",
+ container_dev, data_vol_dev, os_env);
+ } else if ((os_env == EDT_OS_ENV_MAIN) &&
+ (passno == MOUNT_PHASE_2)) {
+ errx(errno_or_sysexit(errno ? errno : ENXIO, -1),
+ "mount: missing data volume");
+ } else {
+ fprintf(stdout, "mount: data volume missing, but not required in env: %u\n",
+ os_env);
+ }
+#endif
+
+ while ((fs = getfsent()) != NULL) {
+ int ro_mount = !strcmp(fs->fs_type, FSTAB_RO);
+
+ if (BADTYPE(fs->fs_type))
+ continue;
+ if (checkvfsname(fs->fs_vfstype, vfslist))
+ continue;
+ if (hasopt(fs->fs_mntops, "noauto"))
+ continue;
+ if (!strcmp(fs->fs_vfstype, "nfs")) {
+ if (hasopt(fs->fs_mntops, "net"))
+ continue;
+ /* check if already mounted */
+ if (fs->fs_spec == NULL ||
+ fs->fs_file == NULL ||
+ ismounted(fs->fs_spec, fs->fs_file, NULL))
+ continue;
+ }
+
+ /* If this volume is not needed for this pass, skip it. */
+ if (passno && fs->fs_passno != passno)
+ continue;
+
+ /*
+ * Check if already mounted:
+ * 1) If mounted RW this is either an attempt to
+ * downgrade (RW -> RO) or someone else already
+ * mounted this volume as RW.
+ * 2) If mounted RO and not upgrading to RW nothing
+ * nothing need to be done so we should skip this entry.
+ * Skip this entry in both cases (basically only keep going
+ * if this is an acctual mount RW upgrade).
+ */
+ if (ismounted(fs->fs_spec, fs->fs_file, &fs_flags) &&
+ (!(fs_flags & MNT_RDONLY) || ro_mount))
+ continue;
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ if (!strcmp(fs->fs_spec, RAMDISK_FS_SPEC)) {
+ if (verbose) {
+ fprintf(stdout, "mount: encountered ramdisk\n");
+ }
+ rval = create_mount_ramdisk(fs, init_flags, options);
+ continue;
+ } else if (fs->fs_passno > ROOT_PASSNO &&
+ !strcmp(fs->fs_vfstype, EDTVolumeFSType) &&
+ !strcmp(fs->fs_type, FSTAB_RW)) {
+
+ /*
+ * Perform media keys migration if this is the data volume
+ * of the main OS environment
+ */
+ if (!debug && data_vol_dev &&
+ (os_env == EDT_OS_ENV_MAIN) &&
+ (strcmp(data_vol_dev, fs->fs_spec) == 0)) {
+ kern_return_t mig_err = APFSContainerMigrateMediaKeys(container_dev);
+ if (mig_err) {
+ fprintf(stderr, "mount: failed to migrate Media Keys, error = %x\n", mig_err);
+ } else {
+ fprintf(stdout, "mount: successfully migrated Media Keys\n");
+ }
+ }
+ }
+#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
+
+ if ((err = mountfs(fs->fs_vfstype, fs->fs_spec,
+ fs->fs_file, init_flags, options,
+ fs->fs_mntops)))
+ rval = err;
+ }
+ endfsent();
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ /* Setup bindfs mounts */
+ if (os_env != EDT_OS_ENV_OTHER) {
+ setup_preboot_mounts(passno);
+ }
+ /* Hand the rest of the process over to apfs_boot_util */
+ if (os_variant_has_internal_content(APFS_BUNDLE_ID) &&
+ (mount_phase == MOUNT_PHASE_2)) {
+ bootstrap_apfs(MOUNT_PHASE_2);
+ }
+#endif
+ }
+ else if (bootstrap_macos) {
+#if TARGET_OS_OSX
+ if (mount_phase == MOUNT_PHASE_1) {
+ if (booted_apfs()) {
+ bootstrap_apfs(MOUNT_PHASE_1);
+ } else {
+ fprintf(stdout, "Not booted from APFS, skipping apfs_boot_util\n");
+ exit(0);
+ }
+ } else if (mount_phase == MOUNT_PHASE_2) {
+ /*
+ * We centralize the logic for dealing with a read-only system (ROSV) volume here.
+ * If it is not set up, then default to the old logic of a `mount -uw /`
+ *
+ * Note: We can safely do this boot-task even if we are
+ * already mounted RW (e.g. boot from single user mode).
+ * In that case this will effectively be a no-op.
+ */
+ if (booted_rosv()) {
+ /* Hand the rest of the process over to apfs_boot_util */
+ bootstrap_apfs(MOUNT_PHASE_2);
+ } else {
+ /* upgrade mount "/" read-write */
+ rval = upgrade_mount("/", MNT_UPDATE, options);
+ }
+ }
+#endif /* TARGET_OS_OSX */
+ } else {
+ print_mount(vfslist);
+ }
+ exit(rval);
+ case 1:
+ if (vfslist != NULL)
+ usage();
+
+ if (init_flags & MNT_UPDATE) {
+
+ rval = upgrade_mount (*argv, init_flags, options);
+
+ break;
+ }
+
+ if ((fs = getfsfile(*argv)) == NULL &&
+ (fs = getfsspec(*argv)) == NULL)
+ errx(errno_or_sysexit(errno , -1),
+ "%s: unknown special file or file system.",
+ *argv);
+ if (BADTYPE(fs->fs_type))
+ errx(errno_or_sysexit(EINVAL, EX_DATAERR),
+ "%s has unknown file system type.",
+ *argv);
+ if (!strcmp(fs->fs_vfstype, "nfs")) {
+ if (hasopt(fs->fs_mntops, "net"))
+ errx(errno_or_sysexit(EINVAL, EX_DATAERR),
+ "%s is owned by the automounter.",
+ *argv);
+ if (ismounted(fs->fs_spec, fs->fs_file, NULL))
+ errx(errno_or_sysexit(EALREADY, EX_CONFIG),
+ "%s is already mounted at %s.",
+ fs->fs_spec, fs->fs_file);
+ }
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+ if (!strcmp(fs->fs_spec, RAMDISK_FS_SPEC)) {
+ if (verbose) {
+ fprintf(stdout, "Found a ramdisk entry\n");
+ }
+ rval = create_mount_ramdisk(fs, init_flags, options);
+ break;
+ }
+#endif
+ rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file,
+ init_flags, options, fs->fs_mntops);
+ break;
+ case 2:
+ /*
+ * If -t flag has not been specified, and spec contains a ':'
+ * then assume that an NFS filesystem is being specified.
+ */
+ if (vfslist == NULL && strchr(argv[0], ':') != NULL) {
+ vfstype = "nfs";
+ /* check if already mounted */
+ if (ismounted(argv[0], argv[1], NULL))
+ errx(errno_or_sysexit(EALREADY, EX_CONFIG),
+ "%s is already mounted at %s.",
+ argv[0], argv[1]);
+ }
+
+ /* If we have both a devnode and a pathname, and an update mount was requested,
+ * then figure out where the devnode is mounted. We will need to run
+ * an update mount on its path. It wouldn't make sense to do an
+ * update mount on a path other than the one it's already using.
+ *
+ * XXX: Should we implement the same workaround for updating the
+ * root file system at boot time?
+ */
+ if (init_flags & MNT_UPDATE) {
+ if ((mntbuf = getmntpt(*argv)) == NULL)
+ errx(errno_or_sysexit(errno ? errno : ENOENT, -1),
+ "unknown special file or file system %s.",
+ *argv);
+ rval = mountfs(mntbuf->f_fstypename, mntbuf->f_mntfromname,
+ mntbuf->f_mntonname, init_flags, options, 0);
+ }
+ else {
+ /*
+ * If update mount not requested, then go with the vfstype and arguments
+ * specified. If no vfstype specified, then error out.
+ */
+ if (vfstype == NULL) {
+ errx (errno_or_sysexit(EINVAL, EX_USAGE),
+ "You must specify a filesystem type with -t.");
+ }
+ rval = mountfs(vfstype,
+ argv[0], argv[1], init_flags, options, NULL);
+ }
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ exit(rval);
+}
+
+static int
+upgrade_mount (const char *mountpt, int init_flags, char *options) {
+
+ struct statfs *mntbuf = NULL;
+ const char *mntfromname = NULL;
+ struct fstab *fs = NULL;
+
+ if ((mntbuf = getmntpt(mountpt)) == NULL) {
+ errx(errno_or_sysexit(errno, -1),
+ "unknown special file or file system %s.",
+ mountpt);
+ }
+
+ /*
+ * Handle the special case of upgrading the root file
+ * system from read-only to read/write. The root file
+ * system was originally mounted with a "mount from" name
+ * of "root_device". The getfsfile("/") returns non-
+ * NULL at this point, with fs_spec set to the true
+ * path to the root device (regardless of what either the real
+ * or synthesized /etc/fstab contained).
+ */
+ mntfromname = mntbuf->f_mntfromname;
+ if (strchr(mntfromname, '/') == NULL) {
+ fs = getfsfile(mntbuf->f_mntonname);
+ if (fs != NULL)
+ mntfromname = fs->fs_spec;
+ }
+
+ /*
+ * Handle the special case of upgrading a content protected
+ * file system from read-only to read/write. While our caller
+ * is nominally required to pass the protect option to maintain
+ * content protection, the kernel requires it anyway, so just add it
+ * in.
+ */
+ if (mntbuf->f_flags & MNT_CPROTECT) {
+ init_flags |= MNT_CPROTECT;
+ }
+
+
+ /* Do the update mount */
+ return mountfs(mntbuf->f_fstypename, mntfromname,
+ mntbuf->f_mntonname, init_flags, options, 0);
+
+}
+
+int
+hasopt(mntopts, option)
+ const char *mntopts, *option;
+{
+ int negative, found;
+ char *opt, *optbuf;
+
+ if (option[0] == 'n' && option[1] == 'o') {
+ negative = 1;
+ option += 2;
+ } else
+ negative = 0;
+ optbuf = strdup(mntopts);
+ found = 0;
+ for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
+ if (opt[0] == 'n' && opt[1] == 'o') {
+ if (!strcasecmp(opt + 2, option))
+ found = negative;
+ } else if (!strcasecmp(opt, option))
+ found = !negative;
+ }
+ free(optbuf);
+ return (found);
+}
+
+int
+ismounted(const char *fs_spec, const char *fs_file, long *flags)
+{
+ int i, mntsize;
+ struct statfs *mntbuf;
+
+ if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
+ err(errno_or_sysexit(errno , -1), "getmntinfo");
+ for (i = 0; i < mntsize; i++) {
+ if (strcmp(mntbuf[i].f_mntfromname, fs_spec))
+ continue;
+ if (strcmp(mntbuf[i].f_mntonname, fs_file))
+ continue;
+ if (flags)
+ *flags = mntbuf[i].f_flags;
+ return 1;
+ }
+ return 0;
+}
+
+#if TARGET_OS_OSX
+static int
+booted_apfs(void) {
+ struct statfs *mntbuf;
+
+ if ((mntbuf = getmntpt("/")) == NULL) {
+ errx(errno_or_sysexit(errno, -1),
+ "failed to lookup root file system");
+ }
+
+ return (strcmp(mntbuf->f_fstypename, "apfs") == 0);
+}
+
+static int
+booted_rosv(void) {
+ /* use sysctl to query kernel */
+ uint32_t is_rosp = 0;
+ size_t rospsize = sizeof(is_rosp);
+ int err = sysctlbyname ("vfs.generic.apfs.rosp", &is_rosp, &rospsize, NULL, NULL);
+
+ if (!err && is_rosp) {
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* TARGET_OS_OSX */
+
+// prints currently mounted filesystems
+void
+print_mount(const char **vfslist)
+{
+ struct statfs *mntbuf;
+ int mntsize;
+
+ if ( (mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0 )
+ err(errno_or_sysexit(errno , -1), "getmntinfo");
+ for (int i = 0; i < mntsize; i++) {
+ if ( checkvfsname(mntbuf[i].f_fstypename, vfslist) )
+ continue;
+ prmount(&mntbuf[i]);
+ }
+}
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+int
+verify_executable_file_existence (char *path)
+{
+ return _verify_file_flags(path, F_OK | X_OK);
+}
+
+int
+verify_file_existence (char *path)
+{
+ return _verify_file_flags(path, F_OK);
+}
+
+int
+_verify_file_flags (char *path, int flags)
+{
+
+ if ( access(path, flags) ) {
+ fprintf(stderr, "Failed access check for %s with issue %s\n", path, strerror(errno));
+ return errno;
+ }
+ return 0;
+}
+
+int
+preflight_create_mount_ramdisk (char *mnt_opts, size_t *ramdisk_size, char *template)
+{
+ char *special_ramdisk_params;
+
+ if ( mnt_opts == NULL ) {
+ fprintf(stderr, "No mnt_opts provided to ramdisk preflight.\n");
+ return EINVAL;
+ }
+
+ if ( verify_executable_file_existence(HDIK_PATH) != 0 ) {
+ fprintf(stderr, "Failed to find executable hdik at location %s \n", HDIK_PATH);
+ return ENOENT;
+ }
+
+ special_ramdisk_params = split_ramdisk_params(mnt_opts);
+ if ( special_ramdisk_params == NULL ) {
+ fprintf(stderr, "Ramdisk fstab not in expected format.\n");
+ return EINVAL;
+ }
+
+ if ( ramdisk_size ) {
+ char *ramdisk_size_str = parse_parameter_for_token(special_ramdisk_params, RAMDISK_SIZE_TOK);
+
+ if ( ramdisk_size_str != NULL ) {
+ *ramdisk_size = atoi(ramdisk_size_str);
+ free(ramdisk_size_str);
+ }
+
+ if ( *ramdisk_size == 0 ) {
+ fprintf(stderr, "Unexpected ramdisk size %zu\n", *ramdisk_size);
+ return EINVAL;
+ }
+ }
+
+ if ( template ) {
+ char *template_str = parse_parameter_for_token(special_ramdisk_params, RAMDISK_TPLT_TOK);
+ if (template_str != NULL) {
+ strlcpy(template, template_str, PATH_MAX);
+ free(template_str);
+ }
+
+ if ( template == NULL ) {
+ fprintf(stderr, "Ramdisk template path not found\n");
+ return EINVAL;
+ }
+
+ }
+
+ return 0;
+}
+#endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
+
+/*
+ * Helper function that posix_spawn a child process
+ * as defined by command_argv[0].
+ * If `output` is non-null, then the command's stdout will be read
+ * into that buffer.
+ * If `rc` is non-null, then the command's return code will be set
+ * there.
+ * If `signal_no` is non-null, then if the command is signaled, the
+ * signal number will be set there.
+ *
+ *
+ * This function returns
+ * -1, if there's an internal error. errno will be set
+ * 0, if command exit normally with 0 as return code
+ * 1, if command exit abnormally or with a non-zero return code
+ */
+int
+run_command(char **command_argv, char *output, int *rc, int *signal_no)
+{
+ int error = -1;
+ int faulting_errno = 0;
+ int status = -1;
+ int internal_result = -1;
+ pid_t pid;
+ posix_spawn_file_actions_t actions = NULL;
+ int output_pipe[2] = {-1, -1};
+ char *command_out = NULL;
+ FILE *stream = NULL;
+
+ if ( !command_argv ) {
+ fprintf(stderr, "command_argv is NULL\n");
+ errno = EINVAL;
+ goto done;
+ }
+
+ if ( pipe(output_pipe) ) {
+ fprintf(stderr, "Failed to create pipe for command output: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ if ( (internal_result = posix_spawn_file_actions_init(&actions)) != 0 ) {
+ errno = internal_result;
+ fprintf(stderr, "posix_spawn_file_actions_init failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ if ( (internal_result = posix_spawn_file_actions_addclose(&actions, output_pipe[0])) != 0 ) {
+ errno = internal_result;
+ fprintf(stderr, "posix_spawn_file_actions_addclose output_pipe[0] failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ if ( (internal_result = posix_spawn_file_actions_adddup2(&actions, output_pipe[1], STDOUT_FILENO)) != 0 ) {
+ errno = internal_result;
+ fprintf(stderr, "posix_spawn_file_actions_adddup2 output_pipe[1] failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ if ( (internal_result = posix_spawn_file_actions_addclose(&actions, output_pipe[1])) != 0 ) {
+ errno = internal_result;
+ fprintf(stderr, "posix_spawn_file_actions_addclose output_pipe[1] failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ if ( verbose ) {
+ fprintf(stdout, "Executing command: ");
+ for (char **command_segment = command_argv; *command_segment; command_segment++) {
+ fprintf(stdout, "%s ", *command_segment);
+ }
+ fprintf(stdout, "\n");
+ }
+
+ if ( (internal_result = posix_spawn(&pid, command_argv[0], &actions, NULL, command_argv, environ)) != 0 ) {
+ errno = internal_result;
+ fprintf(stderr, "posix_spawn failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ // Close out our side of the pipe
+ close(output_pipe[1]);
+ output_pipe[1] = -1;
+
+ // If caller specified the output buffer, we'll use that
+ // Otherwise allocate a buffer and capture the output ourselves for verbose logging
+ if ( output != NULL ) {
+ command_out = output;
+ } else {
+ command_out = calloc(COMMAND_OUTPUT_MAX, sizeof(char));
+ if (!command_out) {
+ fprintf(stderr, "calloc failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+ }
+
+ stream = fdopen(output_pipe[0], "r");
+ if ( !stream ) {
+ fprintf(stderr, "fdopen failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ size_t length;
+ size_t count = 0;
+ char *line;
+ while ( (line = fgetln(stream, &length)) && (count < COMMAND_OUTPUT_MAX - length - 1) ) {
+ strncat(command_out, line, length);
+ count += length;
+ }
+
+ if ( ferror(stream) ) {
+ fprintf(stderr, "fgetln failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ if ( fclose(stream) ) {
+ fprintf(stderr, "fclose failed: %d (%s)\n", errno, strerror(errno));
+ stream = NULL;
+ goto done;
+ }
+ stream = NULL;
+ close(output_pipe[0]);
+ output_pipe[0] = -1;
+
+ while ( waitpid(pid, &status, 0) < 0 ) {
+ if (errno == EINTR) {
+ continue;
+ }
+ fprintf(stderr, "waitpid failed: %d (%s)\n", errno, strerror(errno));
+ goto done;
+ }
+
+ if ( verbose ) {
+ fprintf(stdout, "Command output:\n%s\n", command_out);
+ }
+
+ if ( WIFEXITED(status) ) {
+ int exit_status = WEXITSTATUS(status);
+ if (rc) *rc = exit_status;
+ if (signal_no) *signal_no = 0;
+
+ if (exit_status != 0) {
+ error = 1;
+ fprintf(stderr, "Command failed: %d\n", exit_status);
+ goto done;
+ }
+ }
+
+ if ( WIFSIGNALED(status) ) {
+ if (rc) *rc = 0;
+ if (signal_no) *signal_no = WTERMSIG(status);
+
+ error = 1;
+ fprintf(stderr, "Command signaled: %d\n", WTERMSIG(status));
+ goto done;
+ }
+
+ error = 0;
+done:
+ // we don't care much about the errno set by the clean up routine
+ // so save the errno here and return to caller
+ faulting_errno = errno;
+
+ if ( actions ) {
+ posix_spawn_file_actions_destroy(&actions);
+ }
+
+ if ( stream ) {
+ fclose(stream);
+ }
+
+ if ( output_pipe[0] >= 0 ) {
+ close(output_pipe[0]);
+ }
+
+ if ( output_pipe[1] >= 0 ) {
+ close(output_pipe[1]);
+ }
+
+ if ( !output && command_out ) {
+ free(command_out);
+ }
+
+ errno = faulting_errno;
+ return error;
+}
+
+#if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+// Helper function that truncates whitespaces
+void
+truncate_whitespace(char* str)
+{
+ size_t idx = strcspn(str, " \n");
+ if ( idx != 0 ) {
+ str[idx] = '\0';
+ }
+}
+
+// Creates a new unmounted ramdisk of size device_size
+int
+attach_device(size_t device_size , char* deviceOut)
+{
+ int return_val = -1;
+ char ram_define [PATH_MAX];
+ snprintf(ram_define, sizeof(ram_define), "ram://%zu", device_size);
+
+ char *command[4] = { HDIK_PATH, "-nomount", ram_define, NULL };
+
+ int status = run_command(command, deviceOut, &return_val, NULL);
+ if ( status == 1 ) {
+ fprintf(stderr, "Failed to create ramdisk. HDIK returned %d.\n", return_val);
+ exit(errno_or_sysexit(errno, -1));
+ } else if (status != 0) {
+ fprintf(stderr, "Failed to execute command %s\n", command[0]);
+ exit(errno_or_sysexit(errno, -1));
+ }
+
+ truncate_whitespace(deviceOut);
+ return return_val;
+}
+
+// Creates the partition table directly through MediaKit.
+int
+create_partition_table(size_t partition_size, char *device)
+{
+
+ MKStatus err = -1;
+ MKMediaRef gpt_ref = NULL;
+ CFMutableArrayRef schemes = NULL;
+ CFMutableArrayRef partitionArray = NULL;
+ CFDictionaryRef partition = NULL;
+ CFMutableDictionaryRef options = NULL;
+ CFMutableDictionaryRef layout = NULL;
+ CFMutableDictionaryRef media = NULL;
+ CFMutableDictionaryRef map = NULL;
+
+ layout = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ if (!layout || !options) {
+ fprintf(stderr, "Failed to create necessary CFDictionaries\n");
+ err = errno;
+ goto done;
+ }
+
+ CFDictionarySetValue(options, kMKMediaPropertyWritableKey, kCFBooleanTrue);
+
+ gpt_ref = MKMediaCreateWithPath(kCFAllocatorDefault, device, options, &err);
+ CFRelease(options);
+
+ if (gpt_ref) {
+ MKStatus mediaErr = 0;
+ partition = MKCFBuildPartition(PMGPTTYPE, apple_apfs, CFSTR(EDTVolumeFSType), CFSTR(RAMDISK_FS_SPEC), 0, RAMDISK_BLCK_OFFSET, &mediaErr, NULL);
+
+ if (!partition) {
+ fprintf(stderr, "Failed to create partition with err %d\n", mediaErr);
+ err = mediaErr;
+ goto done;
+ }
+
+ partitionArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ if (!partitionArray) {
+ fprintf(stderr, "Failed to create partitionArray\n");
+ err = errno;
+ CFRelease(partition);
+ goto done;
+ }
+
+ CFArrayAppendValue(partitionArray, partition);
+ CFRelease(partition);
+
+ CFDictionaryAddValue(layout, CFSTR(MK_PARTITIONS_KEY), partitionArray);
+ CFRelease(partitionArray);
+
+
+ media = MKCFCreateMedia(&schemes, &mediaErr);
+
+ if (!media) {
+ fprintf(stderr, "Failed to create Schemes with error %d\n", mediaErr);
+ err = mediaErr;
+ goto done;
+ }
+
+ map = MKCFCreateMap(PMGPTTYPE, schemes, layout, NULL, NULL, NULL, NULL, NULL, gpt_ref, &mediaErr);
+ if (!map) {
+ fprintf(stderr, "Failed to create map with error %d\n", mediaErr);
+ err = mediaErr;
+ goto done;
+ }
+
+ err = MKCFWriteMedia(media, layout, NULL, NULL, gpt_ref);
+ if (err) {
+ fprintf(stderr, "Failed to WriteMedia with error %d\n", err);
+ goto done;
+ }
+
+ } else {
+ fprintf(stderr, "Failed to create gpt_ref with error %d\n", err);
+ goto done;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Releasing MediaKit objects\n");
+ }
+ err = 0;
+
+done:
+ if (media) {
+ MKCFDisposeMedia(media);
+ }
+
+ if (layout) {
+ CFRelease(layout);
+ }
+
+ if (gpt_ref) {
+ CFRelease(gpt_ref);
+ }
+
+ return err;
+}
+
+// Triggers newfs_apfs for the target device
+int
+construct_apfs_volume(char *mounted_device_name)
+{
+ int return_val = -1;
+ int status = -1;
+ char *command[5] = { "/sbin/newfs_apfs", "-v", "Var", mounted_device_name, NULL };
+
+ status = run_command(command, NULL, &return_val, NULL);
+ if ( status >= 0 ) {
+ return return_val;
+ } else {
+ fprintf(stderr, "Failed to execute command %s\n", command[0]);
+ errno_or_sysexit(errno, -1);
+ }
+
+ // shouldn't reach here. This is to satisfy the compiler
+ return -1;
+}
+
+// unmounts device at location
+int
+unmount_location(char *mount_point)
+{
+ int return_val = -1;
+ int status = -1;
+ char *command[4] = { "/sbin/umount", "-f", mount_point, NULL };
+
+ status = run_command(command, NULL, &return_val, NULL);
+ if ( status >= 0 ) {
+ return return_val;
+ } else {
+ fprintf(stderr, "Failed to execute command %s\n", command[0]);
+ return errno_or_sysexit(errno, -1);
+ }
+}
+
+// The mnt_opts for fstab are standard across the different
+// mount_fs implementations. To create and mount an ephemeral
+// filesystem, it is necessary to provide additional non-standard
+// values in filesystem definition - mainly size and location of
+// the seed files.
+// The fstab definition for a ramdisk fs requires two new parameters:
+// 'size=%zu' and 'template=%s'. To keep the fstab structure
+// consistent with that of other filesystem types, these
+// parameters are appended at the end of the mnt_opts string.
+// It is necessary to split the mnt_opts into two strings, the
+// standard mountfs parameters that are used in the fs-specifnc mount
+// and the ramdisk definition parameters.
+char*
+split_ramdisk_params(char *opts)
+{
+ char* opt = NULL;
+ char* target_str = NULL;
+ char* size_tok = RAMDISK_SIZE_TOK;
+ char* tplt_tok = RAMDISK_TPLT_TOK;
+ char* optbuf = NULL;
+ size_t size_tok_len = strlen(size_tok);
+ size_t tplt_tok_len = strlen(tplt_tok);
+
+ optbuf = strdup(opts);
+ for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
+ size_t opt_len = strlen(opt);
+ if ( (opt_len > size_tok_len && !strncmp(size_tok, opt, size_tok_len) ) ||
+ (opt_len > tplt_tok_len && !strncmp(tplt_tok, opt, tplt_tok_len) ) ) {
+ size_t start_index = opt - optbuf;
+ target_str = opts + start_index;
+ opts[start_index - 1 ] = '\0'; // Break original into two strings.
+ break;
+ }
+ }
+ free(optbuf);
+ return target_str;
+}
+
+// returns string for the parameter after the '=' in the search_string
+// part of the special ramdisk parameters
+char*
+parse_parameter_for_token(char * opts, char * search_string)
+{
+ char *return_str = NULL;
+ char *tmp_str = NULL;
+ char *target_str = strstr(opts, search_string);
+ size_t len = strlen(search_string);
+
+ if ( target_str && strlen(target_str) > len ) {
+ tmp_str = target_str + len;
+ size_t idx = strcspn(tmp_str, ",\0");
+ if ( idx != 0 && (idx < MAXPATHLEN) ) {
+ return_str = calloc(1, idx+1); //for null terminator
+ strncpy(return_str, tmp_str, idx);
+ }
+ }
+ return return_str;
+}
+
+
+static int _copyfile_status(int what, int stage, copyfile_state_t state, const char * src, const char * dst, void * ctx) {
+
+ if (verbose && stage == COPYFILE_START) {
+ if (what == COPYFILE_RECURSE_FILE) {
+ fprintf(stderr, "Copying %s -> %s\n", src, dst);
+ } else if (what == COPYFILE_RECURSE_DIR) {
+ fprintf(stderr, "Creating %s/\n", dst);
+ }
+ }
+
+ return COPYFILE_CONTINUE;
+}
+
+
+// returns 0 upon success and a valid sysexit or errno code upon failure
+int
+create_mount_ramdisk(struct fstab *fs, int init_flags, char *options)
+{
+ int default_flags = init_flags;
+ int mount_return = 0;
+ char ramdisk_partition [PATH_MAX] = { 0 };
+ char ramdisk_volume [PATH_MAX] = { 0 };
+ char ramdisk_container [PATH_MAX] = { 0 };
+ char seed_location [PATH_MAX] = { 0 };
+ char *mnt_point = RAMDISK_TMP_MOUNT; // intermediate
+ char *target_dir = fs->fs_file; // target
+ size_t ram_size = 0;
+
+ if ( verify_file_existence(mnt_point) != 0 ) {
+ if (verbose) {
+ fprintf(stderr, "Default mount %s is not available. Using backup %s.\n", mnt_point, RAMDISK_BCK_MOUNT);
+ }
+ mnt_point = RAMDISK_BCK_MOUNT;
+ if ( verify_file_existence(mnt_point) != 0 ) {
+ fprintf(stderr, "Mountpoints not available. Exiting.\n");
+ return ENOENT;
+ }
+ }
+
+ if ( preflight_create_mount_ramdisk(fs->fs_mntops, &ram_size, seed_location) != 0 ) {
+ fprintf(stderr, "Failed ramdisk preflight. Exiting.\n");
+ return EINVAL;
+ }
+
+ if ( verbose ) {
+ fprintf(stdout, "Attaching device of size %zu\n", ram_size);
+ }
+
+ if( attach_device(ram_size, ramdisk_partition) != 0 ){
+ fprintf(stderr, "Failed to attach the ramdisk.\n");
+ exit(errno_or_sysexit(ECHILD, -1));
+ }
+
+ if ( verbose ) {
+ fprintf(stdout, "Creating partition table for device %s \n", ramdisk_partition);
+ }
+
+ if ( create_partition_table(ram_size, ramdisk_partition) !=0 ) {
+ fprintf(stderr, "Failed to create partition table.\n");
+ exit(errno_or_sysexit(ECHILD, -1));
+ }
+
+ snprintf(ramdisk_container, sizeof(ramdisk_container), "%ss1", ramdisk_partition);
+
+ if ( verbose ) {
+ fprintf(stdout, "Creating apfs volume on partition %s\n", ramdisk_container);
+ }
+
+ if ( construct_apfs_volume(ramdisk_container) != 0 ) {
+ fprintf(stderr, "Failed to construct the apfs volume on the ramdisk.\n");
+ exit(errno_or_sysexit(ECHILD, -1));
+ }
+
+ snprintf(ramdisk_volume, sizeof(ramdisk_volume), "%ss1", ramdisk_container);
+
+ if ( verify_file_existence(ramdisk_volume) != 0 ) {
+ fprintf(stderr, "Failed to verify %s with issue %s\n", ramdisk_volume, strerror(errno));
+ exit(errno_or_sysexit(errno, -1));
+ }
+
+ // Mount volume to RAMDISK_TMP_MOUNT
+ if ( verbose ) {
+ fprintf(stdout, "Mounting to tmp location %s\n", mnt_point);
+ }
+
+ mount_return = mountfs(EDTVolumeFSType, ramdisk_volume, mnt_point, default_flags, NULL, fs->fs_mntops);
+ if ( mount_return > 0 ) {
+ fprintf(stderr, "Initial mount to %s failed with %d\n", mnt_point, mount_return);
+ exit(errno_or_sysexit(errno, -1));
+ }
+
+ // ditto contents of RAMDISK_TMP_MOUNT to /private/var
+ copyfile_state_t state = copyfile_state_alloc();
+ copyfile_state_set(state, COPYFILE_STATE_STATUS_CB, _copyfile_status);
+ if( copyfile(seed_location, mnt_point, state, COPYFILE_ALL | COPYFILE_RECURSIVE) < 0 ) {
+ fprintf(stderr, "Failed to copy contents from %s to %s with error: %s\n", seed_location, mnt_point, strerror(errno));
+ exit(errno_or_sysexit(errno, -1));
+ }
+ copyfile_state_free(state);
+
+ // unount RAMDISK_TMP_MOUNT
+ if( unmount_location(mnt_point) != 0 ){
+ fprintf(stderr, "Failed to unmount device mounted at %s.\n", mnt_point);
+ exit(errno_or_sysexit(ECHILD, -1));
+ }
+
+ if( verbose ) {
+ fprintf(stdout, "Mounting apfs volume %s to %s\n", ramdisk_volume, target_dir);
+ }
+
+ mount_return = mountfs(EDTVolumeFSType, ramdisk_volume, target_dir, default_flags, options, fs->fs_mntops);
+ if ( mount_return > 0 ) {
+ fprintf(stderr, "Followup mount to %s failed with %d\n", target_dir, mount_return);
+ exit(errno_or_sysexit(errno, -1));
+ }
+
+ // Verify contents in stdout
+ if ( verbose ) {
+ print_mount(NULL);
+ }
+
+ return mount_return;
+}
+#endif // (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
+
+// returns 0 upon success and a valid sysexit or errno code upon failure
+int
+mountfs(const char *vfstype, const char *fs_spec, const char *fs_file, int flags,
+ const char *options, const char *mntopts)
+{
+ /* List of directories containing mount_xxx subcommands. */
+ static const char *edirs[] = {
+ _PATH_SBIN,
+ _PATH_USRSBIN,
+ NULL
+ };
+ static const char *bdirs[] = {
+ _PATH_FSBNDL,
+ _PATH_USRFSBNDL,
+ NULL
+ };
+ const char *argv[100], **edir, **bdir;
+ struct statfs sf;
+ pid_t pid;
+ int argc, i, status;
+ char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN];
+
+ if (realpath(fs_file, mntpath) == NULL) {
+ /* Attempt to create missing mountpoints on Data volume */
+ if ((passno == NONROOT_PASSNO) &&
+ (!strncmp(mntpath, PLATFORM_DATA_VOLUME_MOUNT_POINT,
+ MIN(strlen(mntpath), strlen(PLATFORM_DATA_VOLUME_MOUNT_POINT))))) {
+ if (mkdir(mntpath, S_IRWXU)) {
+ warn("mkdir %s", mntpath);
+ return (errno_or_sysexit(errno , -1));
+ }
+ } else {
+ warn("realpath %s", mntpath);
+ return (errno_or_sysexit(errno , -1));
+ }
+ }
+
+ fs_file = mntpath;
+
+ if (mntopts == NULL)
+ mntopts = "";
+ if (options == NULL) {
+ if (*mntopts == '\0') {
+ options = "";
+ } else {
+ options = mntopts;
+ mntopts = "";
+ }
+ }
+ optbuf = catopt(strdup(mntopts), options);
+
+ if ((strcmp(fs_file, "/") == 0) && !(flags & MNT_UNION))
+ flags |= MNT_UPDATE;
+ if (flags & MNT_FORCE)
+ optbuf = catopt(optbuf, "force");
+ if (flags & MNT_RDONLY)
+ optbuf = catopt(optbuf, "ro");
+ if (flags & MNT_UPDATE)
+ optbuf = catopt(optbuf, "update");
+ if (flags & MNT_DONTBROWSE)
+ optbuf = catopt(optbuf, "nobrowse");
+ if (flags & MNT_CPROTECT)
+ optbuf = catopt(optbuf, "protect");
+
+
+ argc = 0;
+ argv[argc++] = vfstype;
+ mangle(optbuf, &argc, argv);
+ argv[argc++] = fs_spec;
+ argv[argc++] = fs_file;
+ argv[argc] = NULL;
+
+ if (debug) {
+ (void)printf("exec: mount_%s", vfstype);
+ for (i = 1; i < argc; i++)
+ (void)printf(" %s", argv[i]);
+ (void)printf("\n");
+ return (0);
+ }
+
+ switch (pid = fork()) {
+ case -1: /* Error. */
+ warn("fork");
+ free(optbuf);
+ return (errno_or_sysexit(errno, EX_OSERR));
+ case 0: /* Child. */
+ /* Go find an executable. */
+ edir = edirs;
+ do {
+ (void)snprintf(execname, sizeof(execname),
+ "%s/mount_%s", *edir, vfstype);
+
+ argv[0] = execname;
+ execv(execname, (char * const *)argv);
+ if (errno != ENOENT)
+ warn("exec %s for %s", execname, fs_file);
+ } while (*++edir != NULL);
+
+ bdir = bdirs;
+ do {
+ /* Special case file system bundle executable path */
+ (void)snprintf(execname, sizeof(execname),
+ "%s/%s.fs/%s/mount_%s", *bdir,
+ vfstype, _PATH_FSBNDLBIN, vfstype);
+
+ argv[0] = execname;
+ execv(execname, (char * const *)argv);
+ if (errno != ENOENT)
+ warn("exec %s for %s", execname, fs_file);
+ } while (*++bdir != NULL);
+
+ if (errno == ENOENT) {
+ warn("exec %s for %s", execname, fs_file);
+ return (errno_or_sysexit(errno, EX_OSFILE));
+ }
+ exit(errno_or_sysexit(errno , -1));
+ /* NOTREACHED */
+ default: /* Parent. */
+ free(optbuf);
+
+ if (waitpid(pid, &status, 0) < 0) {
+ warn("waitpid");
+ return (errno_or_sysexit(errno , -1));
+ }
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0) {
+ warnx("%s failed with %d", fs_file, WEXITSTATUS(status));
+ return (errno_or_sysexit(EINTR, WEXITSTATUS(status)));
+ }
+ } else if (WIFSIGNALED(status)) {
+ warnx("%s: %s", fs_file, sys_siglist[WTERMSIG(status)]);
+ return (errno_or_sysexit(EINTR, EX_UNAVAILABLE));
+ }
+
+ if (verbose) {
+ if (statfs(fs_file, &sf) < 0) {
+ warn("statfs %s", fs_file);
+ return (errno_or_sysexit(errno , -1));
+ }
+ prmount(&sf);
+ }
+ break;
+ }
+
+ return (EX_OK);
+}
+
+static bool
+is_sealed(const char *mntpt)
+{
+ struct vol_attr {
+ uint32_t len;
+ vol_capabilities_attr_t vol_cap;
+ } vol_attrs = {};
+
+ struct attrlist vol_attr_list = {
+ .bitmapcount = ATTR_BIT_MAP_COUNT,
+ .volattr = ATTR_VOL_CAPABILITIES
+ };
+
+ if (!getattrlist(mntpt, &vol_attr_list, &vol_attrs, sizeof(vol_attrs), 0) &&
+ vol_attrs.vol_cap.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_SEALED) {
+ return (vol_attrs.vol_cap.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_SEALED);
+ }
+ return false;
+}
+
+void
+prmount(sfp)
+ struct statfs *sfp;
+{
+ int flags;
+ mountopt_t *o;
+ struct passwd *pw;
+
+ (void)printf("%s on %s (%s", sfp->f_mntfromname, sfp->f_mntonname,
+ sfp->f_fstypename);
+
+ if (is_sealed(sfp->f_mntonname))
+ (void)printf(", sealed");
+ flags = sfp->f_flags & MNT_VISFLAGMASK;
+ for (o = optnames; flags && o->o_opt; o++)
+ if (flags & o->o_opt) {
+ (void)printf(", %s", o->o_name);
+ flags &= ~o->o_opt;
+ }
+ if (sfp->f_owner) {
+ (void)printf(", mounted by ");
+ if ((pw = getpwuid(sfp->f_owner)) != NULL)
+ (void)printf("%s", pw->pw_name);
+ else
+ (void)printf("%d", sfp->f_owner);
+ }
+ (void)printf(")\n");
+}
+
+struct statfs *
+getmntpt(name)
+ const char *name;
+{
+ struct statfs *mntbuf;
+ int i, mntsize;
+
+ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+ for (i = 0; i < mntsize; i++) {
+ if (strcmp(mntbuf[i].f_mntfromname, name) == 0 ||
+ strcmp(mntbuf[i].f_mntonname, name) == 0)
+ return (&mntbuf[i]);
+ }
+ return (NULL);
+}
+
+char *
+catopt(s0, s1)
+ char *s0;
+ const char *s1;
+{
+ size_t i;
+ char *cp;
+
+ if (s0 && *s0) {
+ i = strlen(s0) + strlen(s1) + 1 + 1;
+ if ((cp = malloc(i)) == NULL)
+ err(errno_or_sysexit(errno, EX_TEMPFAIL),
+ "failed to allocate memory for arguments");
+ (void)snprintf(cp, i, "%s,%s", s0, s1);
+ } else
+ cp = strdup(s1);
+
+ if (s0)
+ free(s0);
+ return (cp);
+}
+
+void
+mangle(options, argcp, argv)
+ char *options;
+ int *argcp;
+ const char **argv;
+{
+ char *p, *s;
+ int argc;
+
+ argc = *argcp;
+ for (s = options; (p = strsep(&s, ",")) != NULL;)
+ if (*p != '\0') {
+ if (*p == '-') {
+ argv[argc++] = p;
+ p = strchr(p, '=');
+ if (p) {
+ *p = '\0';
+ argv[argc++] = p+1;
+ }
+ } else {
+ argv[argc++] = "-o";
+ argv[argc++] = p;
+ }
+ }
+
+ *argcp = argc;
+}
+
+void
+usage()
+{
+
+ (void)fprintf(stderr,
+ "usage: mount %s %s\n mount %s\n mount %s\n",
+ "[-dfruvw] [-o options] [-t external_type]",
+ "special mount_point",
+ "[-adfruvw] [-t external_type]",
+ "[-dfruvw] special | mount_point");
+ exit(errno_or_sysexit(EINVAL, EX_USAGE));
+}
diff --git a/diskdev_cmds/mount.tproj/mount.entitlements b/diskdev_cmds/mount.tproj/mount.entitlements
new file mode 100644
index 0000000..c56a334
--- /dev/null
+++ b/diskdev_cmds/mount.tproj/mount.entitlements
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.private.bindfs-allow</key>
+ <true/>
+ <key>com.apple.private.security.disk-device-access</key>
+ <true/>
+ <key>com.apple.security.iokit-user-client-class</key>
+ <string>AppleAPFSUserClient</string>
+</dict>
+</plist>
diff --git a/diskdev_cmds/mount.tproj/pathnames.h b/diskdev_cmds/mount.tproj/pathnames.h
new file mode 100644
index 0000000..009be31
--- /dev/null
+++ b/diskdev_cmds/mount.tproj/pathnames.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.2 (Berkeley) 3/27/94
+ */
+
+#define _PATH_SBIN "/sbin"
+#define _PATH_USRSBIN "/usr/sbin"
+#define _PATH_FSBNDL "/System/Library/Filesystems"
+#define _PATH_USRFSBNDL "/Library/Filesystems"
+#define _PATH_FSBNDLBIN "Contents/Resources"
+#define _PATH_MOUNTDPID "/var/run/mountd.pid"
diff --git a/diskdev_cmds/mount_devfs.tproj/mount_devfs.c b/diskdev_cmds/mount_devfs.tproj/mount_devfs.c
new file mode 100644
index 0000000..f0285b2
--- /dev/null
+++ b/diskdev_cmds/mount_devfs.tproj/mount_devfs.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1992 Jan-Simon Pendry
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <err.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mntopts.h>
+
+struct mntopt mopts[] = {
+ MOPT_STDOPTS,
+ { NULL }
+};
+
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int ch, mntflags;
+ char dir[MAXPATHLEN];
+
+ mntflags = 0;
+ while ((ch = getopt(argc, argv, "o:")) != EOF)
+ switch (ch) {
+ case 'o':
+ getmntopts(optarg, mopts, &mntflags, 0);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ if (realpath(argv[1], dir) == NULL)
+ err(1, "realpath %s", dir);
+
+ if (mount("devfs", dir, mntflags, NULL))
+ err(1, NULL);
+ exit(0);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: mount_devfs [-o options] devfs mount_point\n");
+ exit(1);
+}
diff --git a/diskdev_cmds/mount_fdesc.tproj/mount_fdesc.8 b/diskdev_cmds/mount_fdesc.tproj/mount_fdesc.8
new file mode 100644
index 0000000..a61c952
--- /dev/null
+++ b/diskdev_cmds/mount_fdesc.tproj/mount_fdesc.8
@@ -0,0 +1,171 @@
+.\"
+.\" Copyright (c) 1992, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software donated to Berkeley by
+.\" Jan-Simon Pendry.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mount_fdesc.8 8.2 (Berkeley) 3/27/94
+.\"
+.\"
+.Dd March 27, 1994
+.Dt MOUNT_FDESC 8
+.Os BSD 4.4
+.Sh NAME
+.Nm mount_fdesc
+.Nd mount the file-descriptor file system
+.Sh SYNOPSIS
+.Nm mount_fdesc
+.Op Fl o Ar options
+.Ar fdesc
+.Ar mount_point
+.Sh DESCRIPTION
+The
+.Nm mount_fdesc
+command attaches an instance of the per-process file descriptor
+namespace to the global filesystem namespace.
+The conventional mount point is
+.Pa /dev
+and the filesystem should be union mounted in order to augment,
+rather than replace, the existing entries in
+.Pa /dev .
+This command is normally executed by
+.Xr mount 8
+at boot time.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o
+Options are specified with a
+.Fl o
+flag followed by a comma separated string of options.
+See the
+.Xr mount 8
+man page for possible options and their meanings.
+.El
+.Pp
+The contents of the mount point are
+.Pa fd ,
+.Pa stderr ,
+.Pa stdin ,
+.Pa stdout
+and
+.Pa tty .
+.Pp
+.Pa fd
+is a directory whose contents
+appear as a list of numbered files
+which correspond to the open files of the process reading the
+directory.
+The files
+.Pa /dev/fd/0
+through
+.Pa /dev/fd/#
+refer to file descriptors which can be accessed through the file
+system.
+If the file descriptor is open and the mode the file is being opened
+with is a subset of the mode of the existing descriptor, the call:
+.Bd -literal -offset indent
+fd = open("/dev/fd/0", mode);
+.Ed
+.Pp
+and the call:
+.Bd -literal -offset indent
+fd = fcntl(0, F_DUPFD, 0);
+.Ed
+.Pp
+are equivalent.
+.Pp
+The files
+.Pa /dev/stdin ,
+.Pa /dev/stdout
+and
+.Pa /dev/stderr
+appear as symlinks to the relevant entry in the
+.Pa /dev/fd
+sub-directory.
+Opening them is equivalent to the following calls:
+.Bd -literal -offset indent
+fd = fcntl(STDIN_FILENO, F_DUPFD, 0);
+fd = fcntl(STDOUT_FILENO, F_DUPFD, 0);
+fd = fcntl(STDERR_FILENO, F_DUPFD, 0);
+.Ed
+.Pp
+Flags to the
+.Xr open 2
+call other than
+.Dv O_RDONLY ,
+.Dv O_WRONLY
+and
+.Dv O_RDWR
+are ignored.
+.Pp
+The
+.Pa /dev/tty
+entry is an indirect reference to the current process's controlling terminal.
+It appears as a named pipe (FIFO) but behaves in exactly the same way as
+the real controlling terminal device.
+.Sh FILES
+.Bl -tag -width /dev/stderr -compact
+.It Pa /dev/fd/#
+.It Pa /dev/stdin
+.It Pa /dev/stdout
+.It Pa /dev/stderr
+.It Pa /dev/tty
+.El
+.Sh SEE ALSO
+.Xr mount 2 ,
+.Xr unmount 2 ,
+.Xr tty 4 ,
+.Xr fstab 5 ,
+.Xr mount 8
+.Sh CAVEATS
+No
+.Pa .
+and
+.Pa ..
+entries appear when listing the contents of the
+.Pa /dev/fd
+directory.
+This makes sense in the context of this filesystem, but is inconsistent
+with usual filesystem conventions.
+However, it is still possible to refer to both
+.Pa .
+and
+.Pa ..
+in a pathname.
+.Pp
+This filesystem may not be NFS-exported.
+.Sh HISTORY
+The
+.Nm mount_fdesc
+utility first appeared in 4.4BSD.
diff --git a/diskdev_cmds/mount_fdesc.tproj/mount_fdesc.c b/diskdev_cmds/mount_fdesc.tproj/mount_fdesc.c
new file mode 100644
index 0000000..f49df63
--- /dev/null
+++ b/diskdev_cmds/mount_fdesc.tproj/mount_fdesc.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1990, 1992 Jan-Simon Pendry
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <err.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <mntopts.h>
+
+struct mntopt mopts[] = {
+ MOPT_STDOPTS,
+ { NULL }
+};
+
+void usage __P((void));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int ch, mntflags;
+ char dir[MAXPATHLEN];
+ struct statfs fs;
+
+ mntflags = 0;
+ while ((ch = getopt(argc, argv, "o:")) != EOF)
+ switch (ch) {
+ case 'o':
+ getmntopts(optarg, mopts, &mntflags, 0);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ if (realpath(argv[1], dir) == NULL)
+ err(1, "realpath %s", dir);
+
+ /*
+ * fdesc mount happens automatically now, so no need to do anything.
+ * Just return indicating success.
+ */
+ if (statfs(dir, &fs) == -1) {
+ err(1, "mount point %s", dir);
+ }
+ if (strcmp(fs.f_fstypename, "devfs") != 0) {
+ errx(1, "%s is not devfs", dir);
+ }
+ return 0;
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: mount_fdesc [-o options] fdesc mount_point\n");
+ exit(1);
+}
diff --git a/diskdev_cmds/mount_flags_dir/mount_flags.c b/diskdev_cmds/mount_flags_dir/mount_flags.c
new file mode 100644
index 0000000..3707290
--- /dev/null
+++ b/diskdev_cmds/mount_flags_dir/mount_flags.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1980, 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/mount.h>
+#include <sys/param.h>
+#include "mount_flags.h"
+
+/*
+ * This file is intended to be compiled into whichever projects need
+ * to access the MNT_* bit => string mappings. It could be made into a
+ * library but that's unnecessary at present.
+ */
+
+const mountopt_t optnames[] = {
+ { MNT_ASYNC, "asynchronous", "async", },
+ { MNT_EXPORTED, "NFS exported", NULL, },
+ { MNT_LOCAL, "local", NULL, },
+ { MNT_NODEV, "nodev", "nodev", },
+ { MNT_NOEXEC, "noexec", "noexec", },
+ { MNT_NOSUID, "nosuid", "nosuid", },
+ { MNT_QUOTA, "with quotas", NULL, },
+ { MNT_RDONLY, "read-only", "rdonly", },
+ { MNT_SYNCHRONOUS, "synchronous", "sync", },
+ { MNT_UNION, "union", "union", },
+ { MNT_AUTOMOUNTED, "automounted", NULL, },
+ { MNT_JOURNALED, "journaled", NULL, },
+ { MNT_DEFWRITE, "defwrite", NULL, },
+ { MNT_IGNORE_OWNERSHIP, "noowners", "noowners", },
+ { MNT_NOATIME, "noatime", "noatime", },
+ { MNT_STRICTATIME, "strictatime", "strictatime", },
+ { MNT_QUARANTINE, "quarantine", "quarantine", },
+ { MNT_DONTBROWSE, "nobrowse", "nobrowse", },
+ { MNT_CPROTECT, "protect", "protect", },
+ { 0, NULL, NULL, }, // must be last
+};
+
diff --git a/diskdev_cmds/mount_flags_dir/mount_flags.h b/diskdev_cmds/mount_flags_dir/mount_flags.h
new file mode 100644
index 0000000..cf8b190
--- /dev/null
+++ b/diskdev_cmds/mount_flags_dir/mount_flags.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1980, 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __MOUNT_FLAGS__
+#define __MOUNT_FLAGS__
+
+typedef struct mountopt {
+ int o_opt;
+ const char *o_name;
+ const char *o_cmd;
+} mountopt_t;
+
+#endif
+
diff --git a/diskdev_cmds/quota.tproj/quota.1 b/diskdev_cmds/quota.tproj/quota.1
new file mode 100644
index 0000000..57243c9
--- /dev/null
+++ b/diskdev_cmds/quota.tproj/quota.1
@@ -0,0 +1,137 @@
+.\" Copyright (c) 1983, 1990, 1993, 2002
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)quota.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd March 28, 2002
+.Dt QUOTA 1
+.Os BSD 4.2
+.Sh NAME
+.Nm quota
+.Nd display disk usage and limits
+.Sh SYNOPSIS
+.Nm quota
+.Op Fl g
+.Op Fl u
+.Op Fl v | Fl q
+.Nm quota
+.Op Fl u
+.Op Fl v | Fl q
+.Ar user
+.Nm quota
+.Op Fl g
+.Op Fl v | Fl q
+.Ar group
+.Sh DESCRIPTION
+.Nm Quota
+displays users' disk usage and limits.
+By default only the user quotas are printed.
+.Pp
+Options:
+.Pp
+.Bl -tag -width Ds
+.It Fl g
+Print group quotas for the group
+of which the user is a member.
+The optional
+.Fl u
+flag is equivalent to the default.
+.It Fl v
+.Nm quota
+will display quotas on filesystems
+where no storage is allocated.
+.It Fl q
+Print a more terse message,
+containing only information
+on filesystems where usage is over quota.
+.El
+.Pp
+Specifying both
+.Fl g
+and
+.Fl u
+displays both the user quotas and the group quotas (for
+the user).
+.Pp
+Only the super-user may use the
+.Fl u
+flag and the optional
+.Ar user
+argument to view the limits of other users.
+Non-super-users can use the
+.Fl g
+flag and optional
+.Ar group
+argument to view only the limits of groups of which they are members.
+.Pp
+The
+.Fl q
+flag takes precedence over the
+.Fl v
+flag.
+.Pp
+.Nm Quota
+reports the quotas of all the filesystems that have
+a mount option file located at its root.
+If
+.Nm quota
+exits with a non-zero status, then one or more filesystems
+are over quota.
+.Sh FILES
+Each of the following quota files is located at the root of the
+mounted filesystem. The mount option files are empty files
+whose existence indicates that quotas are to be enabled
+for that filesystem.
+.Pp
+.Bl -tag -width .quota.ops.group -compact
+.It Pa .quota.user
+data file containing user quotas
+.It Pa .quota.group
+data file containing group quotas
+.It Pa .quota.ops.user
+mount option file used to enable user quotas
+.It Pa .quota.ops.group
+mount option file used to enable group quotas
+.El
+.Sh HISTORY
+The
+.Nm quota
+command appeared in
+.Bx 4.2 .
+.Sh SEE ALSO
+.Xr quotactl 2 ,
+.Xr edquota 8 ,
+.Xr quotacheck 8 ,
+.Xr quotaon 8 ,
+.Xr repquota 8
diff --git a/diskdev_cmds/quota.tproj/quota.c b/diskdev_cmds/quota.tproj/quota.c
new file mode 100644
index 0000000..87cb531
--- /dev/null
+++ b/diskdev_cmds/quota.tproj/quota.c
@@ -0,0 +1,858 @@
+/*
+ * Copyright (c) 2002-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * Disk quota reporting program.
+ */
+#include <sys/param.h>
+#include <sys/file.h>
+#ifdef __APPLE__
+#include <sys/mount.h>
+#endif /* __APPLE */
+#include <sys/stat.h>
+#include <sys/queue.h>
+
+#include <sys/quota.h>
+#include <libkern/OSByteOrder.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fstab.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+
+#ifdef __APPLE__
+u_int32_t quotamagic[MAXQUOTAS] = INITQMAGICS;
+#endif /* __APPLE__ */
+
+struct quotause {
+ struct quotause *next;
+ long flags;
+ struct dqblk dqblk;
+ char fsname[MAXPATHLEN + 1];
+} *getprivs();
+#define FOUND 0x01
+
+int qflag;
+int vflag;
+
+int alldigits __P((char *));
+int hasquota __P((struct statfs *, int, char **));
+void heading __P((int, u_long, char *, char *));
+void showgid __P((u_long));
+void showuid __P((u_long));
+void showgrpname __P((char *));
+void showquotas __P((int, u_long, char *));
+void showusrname __P((char *));
+void usage __P((void));
+
+#ifdef __APPLE__
+int qflookup(int, u_long, int, struct dqblk *);
+#endif /* __APPLE__ */
+
+int
+main(argc, argv)
+ char *argv[];
+{
+ int ngroups;
+ gid_t gidset[NGROUPS];
+ int i, gflag = 0, uflag = 0;
+ char ch;
+
+#if 0
+ if (quotactl("/", 0, 0, (caddr_t)0) < 0 && errno == ENOTSUP) {
+ fprintf(stderr, "There are no quotas on this system\n");
+ exit(0);
+ }
+#endif
+
+ while ((ch = getopt(argc, argv, "ugvq")) != EOF) {
+ switch(ch) {
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case 'q':
+ qflag++;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (!uflag && !gflag)
+ uflag++;
+ if (argc == 0) {
+ if (uflag)
+ showuid(getuid());
+ if (gflag) {
+ ngroups = getgroups(NGROUPS, gidset);
+ if (ngroups < 0) {
+ perror("quota: getgroups");
+ exit(1);
+ }
+ for (i = 1; i < ngroups; i++)
+ showgid(gidset[i]);
+ }
+ exit(0);
+ }
+ if (uflag && gflag)
+ usage();
+ if (uflag) {
+ for (; argc > 0; argc--, argv++) {
+ if (alldigits(*argv))
+ showuid(atoi(*argv));
+ else
+ showusrname(*argv);
+ }
+ exit(0);
+ }
+ if (gflag) {
+ for (; argc > 0; argc--, argv++) {
+ if (alldigits(*argv))
+ showgid(atoi(*argv));
+ else
+ showgrpname(*argv);
+ }
+ exit(0);
+ }
+ exit(0);
+}
+
+void
+usage()
+{
+
+ fprintf(stderr, "%s\n%s\n%s\n",
+ "Usage: quota [-guqv]",
+ "\tquota [-qv] -u username ...",
+ "\tquota [-qv] -g groupname ...");
+ exit(1);
+}
+
+/*
+ * Print out quotas for a specified user identifier.
+ */
+void
+showuid(uid)
+ u_long uid;
+{
+ struct passwd *pwd = getpwuid(uid);
+ u_long myuid;
+ char *name;
+
+ if (pwd == NULL)
+ name = "(no account)";
+ else
+ name = pwd->pw_name;
+ myuid = getuid();
+ if (uid != myuid && myuid != 0) {
+ printf("quota: %s (uid %ld): permission denied\n", name, uid);
+ return;
+ }
+ showquotas(USRQUOTA, uid, name);
+}
+
+/*
+ * Print out quotas for a specifed user name.
+ */
+void
+showusrname(name)
+ char *name;
+{
+ struct passwd *pwd = getpwnam(name);
+ u_long myuid;
+
+ if (pwd == NULL) {
+ fprintf(stderr, "quota: %s: unknown user\n", name);
+ return;
+ }
+ myuid = getuid();
+ if (pwd->pw_uid != myuid && myuid != 0) {
+ fprintf(stderr, "quota: %s (uid %d): permission denied\n",
+ name, pwd->pw_uid);
+ return;
+ }
+ showquotas(USRQUOTA, pwd->pw_uid, name);
+}
+
+/*
+ * Print out quotas for a specified group identifier.
+ */
+void
+showgid(gid)
+ u_long gid;
+{
+ struct group *grp = getgrgid(gid);
+ int ngroups;
+ gid_t gidset[NGROUPS];
+ register int i;
+ char *name;
+
+ if (grp == NULL)
+ name = "(no entry)";
+ else
+ name = grp->gr_name;
+ ngroups = getgroups(NGROUPS, gidset);
+ if (ngroups < 0) {
+ perror("quota: getgroups");
+ return;
+ }
+ for (i = 1; i < ngroups; i++)
+ if (gid == gidset[i])
+ break;
+ if (i >= ngroups && getuid() != 0) {
+ fprintf(stderr, "quota: %s (gid %ld): permission denied\n",
+ name, gid);
+ return;
+ }
+ showquotas(GRPQUOTA, gid, name);
+}
+
+/*
+ * Print out quotas for a specifed group name.
+ */
+void
+showgrpname(name)
+ char *name;
+{
+ struct group *grp = getgrnam(name);
+ int ngroups;
+ gid_t gidset[NGROUPS];
+ register int i;
+
+ if (grp == NULL) {
+ fprintf(stderr, "quota: %s: unknown group\n", name);
+ return;
+ }
+ ngroups = getgroups(NGROUPS, gidset);
+ if (ngroups < 0) {
+ perror("quota: getgroups");
+ return;
+ }
+ for (i = 1; i < ngroups; i++)
+ if (grp->gr_gid == gidset[i])
+ break;
+ if (i >= ngroups && getuid() != 0) {
+ fprintf(stderr, "quota: %s (gid %d): permission denied\n",
+ name, grp->gr_gid);
+ return;
+ }
+ showquotas(GRPQUOTA, grp->gr_gid, name);
+}
+
+void
+showquotas(type, id, name)
+ int type;
+ u_long id;
+ char *name;
+{
+ register struct quotause *qup;
+ struct quotause *quplist, *getprivs();
+ char *msgi, *msgb, *timeprt();
+ int lines = 0;
+ static time_t now;
+
+ if (now == 0)
+ time(&now);
+ quplist = getprivs(id, type);
+ for (qup = quplist; qup; qup = qup->next) {
+ if (!vflag &&
+ qup->dqblk.dqb_isoftlimit == 0 &&
+ qup->dqblk.dqb_ihardlimit == 0 &&
+ qup->dqblk.dqb_bsoftlimit == 0 &&
+ qup->dqblk.dqb_bhardlimit == 0)
+ continue;
+ msgi = (char *)0;
+ if (qup->dqblk.dqb_ihardlimit &&
+ qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit) {
+ msgi = "File limit reached on";
+ } else if (qup->dqblk.dqb_isoftlimit &&
+ qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit) {
+ if (qup->dqblk.dqb_itime > now) {
+ msgi = "In file grace period on";
+ } else {
+ msgi = "Over file quota on";
+ }
+ }
+ msgb = (char *)0;
+#ifdef __APPLE__
+ if (qup->dqblk.dqb_bhardlimit &&
+ qup->dqblk.dqb_curbytes >= qup->dqblk.dqb_bhardlimit) {
+ msgb = "Block limit reached on";
+ } else if (qup->dqblk.dqb_bsoftlimit &&
+ qup->dqblk.dqb_curbytes >= qup->dqblk.dqb_bsoftlimit) {
+ if (qup->dqblk.dqb_btime > now) {
+ msgb = "In block grace period on";
+ } else {
+ msgb = "Over block quota on";
+ }
+ }
+#else
+ if (qup->dqblk.dqb_bhardlimit &&
+ qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit) {
+ msgb = "Block limit reached on";
+ } else if (qup->dqblk.dqb_bsoftlimit &&
+ qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit) {
+ if (qup->dqblk.dqb_btime > now) {
+ msgb = "In block grace period on";
+ } else {
+ msgb = "Over block quota on";
+ }
+ }
+#endif /* __APPLE__ */
+
+ if (qflag) {
+ if ((msgi != (char *)0 || msgb != (char *)0) &&
+ lines++ == 0)
+ heading(type, id, name, "");
+ if (msgi != (char *)0)
+ printf("\t%s %s\n", msgi, qup->fsname);
+ if (msgb != (char *)0)
+ printf("\t%s %s\n", msgb, qup->fsname);
+ continue;
+ }
+#ifdef __APPLE__
+ if (vflag ||
+ qup->dqblk.dqb_curbytes ||
+ qup->dqblk.dqb_curinodes) {
+ if (lines++ == 0)
+ heading(type, id, name, "");
+
+ printf("%15s %12qd%c %12qd %12qd %8s"
+ , qup->fsname
+ , qup->dqblk.dqb_curbytes / 1024
+ , (msgb == (char *)0) ? ' ' : '*'
+ , qup->dqblk.dqb_bsoftlimit / 1024
+ , qup->dqblk.dqb_bhardlimit / 1024
+ , (msgb == (char *)0) ? ""
+ : timeprt(qup->dqblk.dqb_btime));
+#else
+ if (vflag ||
+ qup->dqblk.dqb_curblocks ||
+ qup->dqblk.dqb_curinodes) {
+ if (lines++ == 0)
+ heading(type, id, name, "");
+
+ printf("%15s%8d%c%7d%8d%8s"
+ , qup->fsname
+ , dbtob(qup->dqblk.dqb_curblocks) / 1024
+ , (msgb == (char *)0) ? ' ' : '*'
+ , dbtob(qup->dqblk.dqb_bsoftlimit) / 1024
+ , dbtob(qup->dqblk.dqb_bhardlimit) / 1024
+ , (msgb == (char *)0) ? ""
+ : timeprt(qup->dqblk.dqb_btime));
+#endif /* __APPLE__ */
+ printf("%8d%c%7d%8d%8s\n"
+ , qup->dqblk.dqb_curinodes
+ , (msgi == (char *)0) ? ' ' : '*'
+ , qup->dqblk.dqb_isoftlimit
+ , qup->dqblk.dqb_ihardlimit
+ , (msgi == (char *)0) ? ""
+ : timeprt(qup->dqblk.dqb_itime)
+ );
+ continue;
+ }
+ }
+ if (!qflag && lines == 0)
+ heading(type, id, name, "none");
+}
+
+void
+heading(type, id, name, tag)
+ int type;
+ u_long id;
+ char *name, *tag;
+{
+
+ printf("Disk quotas for %s %s (%cid %ld): %s\n", qfextension[type],
+ name, *qfextension[type], id, tag);
+ if (!qflag && tag[0] == '\0') {
+#ifdef __APPLE__
+ printf("%15s %12s %12s %12s %8s%8s %7s%8s%8s\n"
+ , "Filesystem"
+ , "1K blocks"
+#else
+ printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n"
+ , "Filesystem"
+ , "blocks"
+#endif /* __APPLE __*/
+ , "quota"
+ , "limit"
+ , "grace"
+ , "files"
+ , "quota"
+ , "limit"
+ , "grace"
+ );
+ }
+}
+
+/*
+ * Calculate the grace period and return a printable string for it.
+ */
+char *
+timeprt(seconds)
+ time_t seconds;
+{
+ time_t hours, minutes;
+ static char buf[20];
+ static time_t now;
+
+ if (now == 0)
+ time(&now);
+ if (now > seconds)
+ return ("none");
+ seconds -= now;
+ minutes = (seconds + 30) / 60;
+ hours = (minutes + 30) / 60;
+ if (hours >= 36) {
+ snprintf(buf, sizeof(buf), "%ddays", (int)((hours + 12) / 24));
+ return (buf);
+ }
+ if (minutes >= 60) {
+ snprintf(buf, sizeof(buf), "%2d:%d", (int)(minutes / 60), (int)(minutes % 60));
+ return (buf);
+ }
+ snprintf(buf, sizeof(buf), "%2d", (int)minutes);
+ return (buf);
+}
+
+typedef struct {
+ int alloced;
+ int nels;
+ char **strings;
+} mount_list_t;
+
+static void *
+init_list(int max)
+{
+ mount_list_t *retval = NULL;
+ retval = malloc(sizeof(*retval));
+ if (retval) {
+ retval->strings = malloc(sizeof(char*) * max);
+ if (retval->strings) {
+ retval->alloced = max;
+ } else {
+ retval->alloced = 0;
+ }
+ retval->nels = 0;
+ }
+ return retval;
+}
+static void
+free_list(void *list)
+{
+ mount_list_t *tmp = list;
+ int i;
+
+ if (tmp == NULL)
+ return;
+ for (i = 0; i < tmp->nels; i++) {
+ free(tmp->strings[i]);
+ }
+ free(tmp);
+ return;
+}
+
+static int
+hasseen(void *tmp, const char *mp)
+{
+ int retval = 0;
+ mount_list_t *list = tmp;
+ int i;
+
+ if (tmp == NULL || mp == NULL)
+ goto done;
+
+ /*
+ * This could also be a binary search, but then we'd have to sort
+ * after each addition. We may want to change the behaviour based
+ * on the number of elements in the array.
+ */
+
+ for (i = 0; i < list->nels; i++) {
+ if (strcmp(list->strings[i], mp) == 0) {
+ retval = 1;
+ goto done;
+ }
+ }
+ if (list->nels <= list->alloced) {
+ char **a = realloc(list->strings, (list->alloced + 10) * sizeof(char*));
+ if (a) {
+ list->alloced = list->alloced + 10;
+ list->strings = a;
+ } else {
+ goto done;
+ }
+ }
+ list->strings[list->nels++] = strdup(mp);
+
+done:
+ return retval;
+}
+
+/*
+ * Collect the requested quota information.
+ */
+#ifdef __APPLE__
+struct quotause *
+getprivs(id, quotatype)
+ register long id;
+ int quotatype;
+{
+ struct statfs *fst;
+ register struct quotause *qup, *quptail;
+ struct quotause *quphead;
+ struct dqblk dqb;
+ char *qfpathname;
+ int qcmd, fd;
+ int nfst, i;
+ int error;
+ void *cache;
+
+ quptail = quphead = (struct quotause *)0;
+ qcmd = QCMD(Q_GETQUOTA, quotatype);
+
+ nfst = getmntinfo(&fst, MNT_WAIT);
+ if (nfst==0) {
+ fprintf(stderr, "quota: no mounted filesystems\n");
+ exit(1);
+ }
+
+ cache = init_list(nfst);
+
+ for (i=0; i<nfst; i++) {
+ if (hasseen(cache, fst[i].f_mntonname))
+ continue;
+ error = quotactl(fst[i].f_mntonname, qcmd, id, (char *)&dqb);
+ if (error) {
+ if (strcmp(fst[i].f_fstypename, "hfs"))
+ continue;
+ if (!hasquota(&fst[i], quotatype, &qfpathname))
+ continue;
+ }
+ if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) {
+ fprintf(stderr, "quota: out of memory\n");
+ exit(2);
+ }
+ if (!error) {
+ bcopy(&dqb, &qup->dqblk, sizeof(dqb));
+ } else {
+ if ((fd = open(qfpathname, O_RDONLY)) < 0) {
+ perror(qfpathname);
+ free(qup);
+ continue;
+ }
+ if ((error = qflookup(fd, id, quotatype, &qup->dqblk))) {
+ perror(qfpathname);
+ close(fd);
+ free(qup);
+ continue;
+ }
+ close(fd);
+ }
+ strlcpy(qup->fsname, fst[i].f_mntonname, sizeof(qup->fsname));
+ if (quphead == NULL)
+ quphead = qup;
+ else
+ quptail->next = qup;
+ quptail = qup;
+ qup->next = 0;
+ }
+ free_list(cache);
+
+ return (quphead);
+}
+#else
+struct quotause *
+getprivs(id, quotatype)
+ register long id;
+ int quotatype;
+{
+ register struct fstab *fs;
+ register struct quotause *qup, *quptail;
+ struct quotause *quphead;
+ char *qfpathname;
+ int qcmd, fd;
+
+ setfsent();
+ quphead = (struct quotause *)0;
+ qcmd = QCMD(Q_GETQUOTA, quotatype);
+ while (fs = getfsent()) {
+ if (strcmp(fs->fs_vfstype, "ufs"))
+ continue;
+ if (!hasquota(fs, quotatype, &qfpathname))
+ continue;
+ if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) {
+ fprintf(stderr, "quota: out of memory\n");
+ exit(2);
+ }
+ if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
+ if ((fd = open(qfpathname, O_RDONLY)) < 0) {
+ perror(qfpathname);
+ free(qup);
+ continue;
+ }
+ lseek(fd, (off_t)(id * sizeof(struct dqblk)), L_SET);
+ switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
+ case 0: /* EOF */
+ /*
+ * Convert implicit 0 quota (EOF)
+ * into an explicit one (zero'ed dqblk)
+ */
+ bzero((caddr_t)&qup->dqblk,
+ sizeof(struct dqblk));
+ break;
+
+ case sizeof(struct dqblk): /* OK */
+ break;
+
+ default: /* ERROR */
+ fprintf(stderr, "quota: read error");
+ perror(qfpathname);
+ close(fd);
+ free(qup);
+ continue;
+ }
+ close(fd);
+ }
+ strlcpy(qup->fsname, fs->fs_file, sizeof(qup->fsname));
+
+ if (quphead == NULL)
+ quphead = qup;
+ else
+ quptail->next = qup;
+ quptail = qup;
+ qup->next = 0;
+ }
+ endfsent();
+ return (quphead);
+}
+#endif /* __APPLE__ */
+
+
+#ifdef __APPLE__
+/*
+ * Lookup an entry in the quota file.
+ */
+int
+qflookup(fd, id, type, dqbp)
+ int fd;
+ u_long id;
+ int type;
+ struct dqblk *dqbp;
+{
+ struct dqfilehdr dqhdr;
+ int i, skip, last, m;
+ u_long mask;
+
+ bzero(dqbp, sizeof(struct dqblk));
+
+ if (id == 0)
+ return (0);
+
+ lseek(fd, 0, L_SET);
+ if (read(fd, &dqhdr, sizeof(struct dqfilehdr)) != sizeof(struct dqfilehdr)) {
+ fprintf(stderr, "quota: read error\n");
+ return (errno);
+ }
+
+ /* Sanity check the quota file header. */
+ if ((OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type]) ||
+ (OSSwapBigToHostInt32(dqhdr.dqh_version) > QF_VERSION) ||
+ (!powerof2(OSSwapBigToHostInt32(dqhdr.dqh_maxentries)))) {
+ fprintf(stderr, "quota: invalid quota file header\n");
+ return (EINVAL);
+ }
+
+ m = OSSwapBigToHostInt32(dqhdr.dqh_maxentries);
+ mask = m - 1;
+ i = dqhash1(id, dqhashshift(m), mask);
+ skip = dqhash2(id, mask);
+
+ for (last = (i + (m-1) * skip) & mask;
+ i != last;
+ i = (i + skip) & mask) {
+ lseek(fd, dqoffset(i), L_SET);
+ if (read(fd, dqbp, sizeof(struct dqblk)) < sizeof(struct dqblk)) {
+ fprintf(stderr, "quota: read error at index %d\n", i);
+ return (errno);
+ }
+ /*
+ * Stop when an empty entry is found
+ * or we encounter a matching id.
+ */
+ if (dqbp->dqb_id == 0 || OSSwapBigToHostInt32(dqbp->dqb_id) == id)
+ break;
+ }
+ /* Put data in host native byte order. */
+ dqbp->dqb_bhardlimit = OSSwapBigToHostInt64(dqbp->dqb_bhardlimit);
+ dqbp->dqb_bsoftlimit = OSSwapBigToHostInt64(dqbp->dqb_bsoftlimit);
+ dqbp->dqb_curbytes = OSSwapBigToHostInt64(dqbp->dqb_curbytes);
+ dqbp->dqb_ihardlimit = OSSwapBigToHostInt32(dqbp->dqb_ihardlimit);
+ dqbp->dqb_isoftlimit = OSSwapBigToHostInt32(dqbp->dqb_isoftlimit);
+ dqbp->dqb_curinodes = OSSwapBigToHostInt32(dqbp->dqb_curinodes);
+ dqbp->dqb_btime = OSSwapBigToHostInt32(dqbp->dqb_btime);
+ dqbp->dqb_itime = OSSwapBigToHostInt32(dqbp->dqb_itime);
+ dqbp->dqb_id = OSSwapBigToHostInt32(dqbp->dqb_id);
+
+ return (0);
+}
+#endif /* __APPLE__ */
+
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+#ifdef __APPLE__
+int
+hasquota(fst, type, qfnamep)
+ register struct statfs *fst;
+ int type;
+ char **qfnamep;
+{
+ struct stat sb;
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ /*
+ We only support the default path to the
+ on disk quota files.
+ */
+
+ (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname,
+ QUOTAOPSNAME, qfextension[type] );
+ if (stat(buf, &sb) != 0) {
+ /* There appears to be no mount option file */
+ return(0);
+ }
+
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#else
+hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp, *index(), *strtok();
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strlcpy(buf, fs->fs_mntops, sizeof(buf));
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = index(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp) {
+ *qfnamep = cp;
+ return (1);
+ }
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#endif /* __APPLE__ */
+
+int
+alldigits(s)
+ register char *s;
+{
+ register int c;
+
+ c = *s++;
+ do {
+ if (!isdigit(c))
+ return (0);
+ } while ((c = *s++));
+ return (1);
+}
diff --git a/diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c b/diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c
new file mode 100644
index 0000000..31bb0f5
--- /dev/null
+++ b/diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <sys/param.h>
+#include <sys/attr.h>
+#include <sys/quota.h>
+#include <sys/vnode.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "quotacheck.h"
+
+
+/*
+ * Query is based on uid
+ */
+#define QQ_COMMON (ATTR_CMN_OWNERID)
+
+struct quota_query {
+ u_int32_t qq_len;
+ uid_t qq_uid;
+};
+
+/*
+ * Desired atttributes for quota checking
+ */
+#define QA_COMMON (ATTR_CMN_OBJTYPE | ATTR_CMN_OWNERID | ATTR_CMN_GRPID)
+#define QA_FILE (ATTR_FILE_ALLOCSIZE)
+#define QA_DIR (0)
+
+struct quota_attr {
+ u_int32_t qa_attrlen;
+ fsobj_type_t qa_type;
+ uid_t qa_uid;
+ gid_t qa_gid;
+ off_t qa_bytes;
+};
+
+#define ITEMS_PER_SEARCH 2500
+
+void collectdata(const char*, struct quotaname *);
+
+
+/*
+ * Scan an HFS filesystem to check quota(s) present on it.
+ */
+int
+chkquota_hfs(fsname, mntpt, qnp)
+ char *fsname, *mntpt;
+ register struct quotaname *qnp;
+{
+ int errs = 0;
+
+ sync();
+
+ collectdata(mntpt, qnp);
+
+ if (qnp->flags & HASUSR)
+ errs = update(mntpt, qnp->usrqfname, USRQUOTA);
+ if (qnp->flags & HASGRP)
+ errs = update(mntpt, qnp->grpqfname, GRPQUOTA);
+
+ return (errs);
+}
+
+
+void
+collectdata(const char* path, struct quotaname *qnp)
+{
+ struct fssearchblock searchblk = {0};
+ struct attrlist attrlist = {0};
+ struct searchstate state;
+ struct quota_attr *qap;
+ struct quota_query query;
+ u_long nummatches;
+ u_int options;
+
+ int i;
+ int result;
+ int vntype;
+ off_t filebytes;
+ register struct fileusage *fup;
+
+ qap = malloc(ITEMS_PER_SEARCH * sizeof(struct quota_attr));
+ if (qap == NULL)
+ err(1, "%s", strerror(errno));
+
+ options = SRCHFS_START |SRCHFS_MATCHDIRS | SRCHFS_MATCHFILES;
+
+ /* Search for items with uid != 0 */
+ query.qq_len = sizeof(struct quota_query);
+ query.qq_uid = 0;
+ options |= SRCHFS_NEGATEPARAMS | SRCHFS_SKIPLINKS;
+ searchblk.searchattrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+ searchblk.searchattrs.commonattr = QQ_COMMON;
+ searchblk.searchparams1 = &query;
+ searchblk.searchparams2 = &query;
+ searchblk.sizeofsearchparams1 = sizeof(query);
+ searchblk.sizeofsearchparams2 = sizeof(query);
+
+ /* Ask for type, uid, gid and file bytes */
+ searchblk.returnattrs = &attrlist;
+ attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attrlist.commonattr = QA_COMMON;
+ attrlist.dirattr = QA_DIR;
+ attrlist.fileattr = QA_FILE;
+
+ /* Collect 2,500 items at a time (~60K) */
+ searchblk.returnbuffer = qap;
+ searchblk.returnbuffersize = ITEMS_PER_SEARCH * sizeof(struct quota_attr);
+ searchblk.maxmatches = ITEMS_PER_SEARCH;
+
+ for (;;) {
+ nummatches = 0;
+ result = searchfs(path, &searchblk, &nummatches, 0, options, &state);
+ if (result && errno != EAGAIN && errno != EBUSY) {
+ fprintf(stderr, "%d \n", errno);
+ err(1, "searchfs %s", strerror(errno));
+ }
+ if (result == 0 && nummatches == 0)
+ break; /* all done */
+ options &= ~SRCHFS_START;
+
+ for (i = 0; i < nummatches; ++i) {
+ vntype = qap[i].qa_type;
+ filebytes = (vntype == VDIR) ? 0 : qap[i].qa_bytes;
+
+ if (qnp->flags & HASGRP) {
+ fup = addid(qap[i].qa_gid, GRPQUOTA);
+ fup->fu_curinodes++;
+ if (vntype == VREG || vntype == VDIR || vntype == VLNK)
+ fup->fu_curbytes += filebytes;
+ }
+ if (qnp->flags & HASUSR) {
+ fup = addid(qap[i].qa_uid, USRQUOTA);
+ fup->fu_curinodes++;
+ if (vntype == VREG || vntype == VDIR || vntype == VLNK)
+ fup->fu_curbytes += filebytes;
+ }
+ }
+ }
+
+ free(qap);
+}
diff --git a/diskdev_cmds/quotacheck.tproj/quotacheck.8 b/diskdev_cmds/quotacheck.tproj/quotacheck.8
new file mode 100644
index 0000000..92e547e
--- /dev/null
+++ b/diskdev_cmds/quotacheck.tproj/quotacheck.8
@@ -0,0 +1,156 @@
+.\" Copyright (c) 1983, 1990, 1991, 1993, 2002
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)quotacheck.8 8.1 (Berkeley) 6/5/93
+.\"
+.Dd October 17, 2002
+.Dt QUOTACHECK 8
+.Os BSD 4.2
+.Sh NAME
+.Nm quotacheck
+.Nd filesystem quota consistency checker
+.Sh SYNOPSIS
+.Nm quotacheck
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Ar filesystem Ar ...
+.Nm quotacheck
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Fl a
+.Sh DESCRIPTION
+.Nm Quotacheck
+examines each filesystem,
+builds a table of current disk usage,
+and compares this table against that recorded
+in the disk quota file for the filesystem.
+If any inconsistencies are detected, both the
+quota file and the current system copy of the
+incorrect quotas are updated (the latter only
+occurs if an active filesystem is checked).
+By default both user and group quotas are checked.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+If the
+.Fl a
+flag is supplied in place of any filesystem names,
+.Nm quotacheck
+will check all the read-write filesystems with an existing
+mount option file at its root.
+The mount option file specifies the types of quotas that
+are to be checked.
+.It Fl g
+Only group quotas are checked. The mount option file,
+.Pa .quota.ops.group ,
+must exist at the root of the filesystem.
+.It Fl u
+Only user quotas are checked. The mount option file,
+.Pa .quota.ops.user ,
+must exist at the root of the filesystem.
+.It Fl v
+.Nm quotacheck
+reports discrepancies between the
+calculated and recorded disk quotas.
+.El
+.Pp
+Specifying both
+.Fl g
+and
+.Fl u
+is equivalent to the default.
+Parallel passes are run on the filesystems required,
+in an identical fashion to
+.Xr fsck 8 .
+.Pp
+Normally
+.Nm quotacheck
+operates silently.
+.Pp
+.Nm Quotacheck
+expects each filesystem being checked to have
+quota data files named
+.Pa .quota.user
+and/or
+.Pa .quota.group
+located at the filesystem root.
+If a binary data file is not present,
+.Nm quotacheck
+will create it.
+The default filename and root location cannot be overridden.
+.Pp
+.Nm Quotacheck
+is normally run at
+.Pa fsck
+time.
+.Pp
+.Nm Quotacheck
+accesses the raw device in calculating the actual
+disk usage for each user.
+Thus, the filesystems
+checked should be quiescent while
+.Nm quotacheck
+is running.
+.Sh FILES
+Each of the following quota files is located at the root of the
+mounted filesystem. The mount option files are empty files
+whose existence indicates that quotas are to be enabled
+for that filesystem. The binary data files will be created by
+quotacheck, if they don't already exist.
+.Pp
+.Bl -tag -width .quota.ops.group -compact
+.It Pa .quota.user
+data file containing user quotas
+.It Pa .quota.group
+data file containing group quotas
+.It Pa .quota.ops.user
+mount option file used to enable user quotas
+.It Pa .quota.ops.group
+mount option file used to enable group quotas
+.El
+.Sh SEE ALSO
+.Xr quota 1 ,
+.Xr quotactl 2 ,
+.Xr edquota 8 ,
+.Xr fsck 8 ,
+.Xr quotaon 8 ,
+.Xr repquota 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/diskdev_cmds/quotacheck.tproj/quotacheck.c b/diskdev_cmds/quotacheck.tproj/quotacheck.c
new file mode 100644
index 0000000..20b5dde
--- /dev/null
+++ b/diskdev_cmds/quotacheck.tproj/quotacheck.c
@@ -0,0 +1,972 @@
+/*
+ * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * Fix up / report on disk quotas & usage
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#ifdef __APPLE__
+#include <sys/mount.h>
+#endif /* __APPLE__ */
+
+#include <sys/quota.h>
+
+#include <fcntl.h>
+#include <fstab.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+
+#ifdef __APPLE__
+#include <libkern/OSByteOrder.h>
+#endif /* __APPLE__ */
+
+#include "quotacheck.h"
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+char *quotagroup = QUOTAGROUP;
+
+#ifdef __APPLE__
+u_int32_t quotamagic[MAXQUOTAS] = INITQMAGICS;
+#endif /* __APPLE__ */
+
+
+#define FUHASH 1024 /* must be power of two */
+struct fileusage *fuhead[MAXQUOTAS][FUHASH];
+
+int aflag; /* all file systems */
+int gflag; /* check group quotas */
+int uflag; /* check user quotas */
+int vflag; /* verbose */
+
+#ifdef __APPLE__
+int maxentries; /* maximum entries in disk quota file */
+#else
+u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
+#endif /* __APPLE__ */
+
+
+#ifdef __APPLE__
+char * blockcheck(char *);
+int chkquota(char *, char *, char *, struct quotaname *);
+int getquotagid(void);
+int hasquota(struct statfs *, int, char **);
+struct fileusage *
+ lookup(u_long, int);
+void * needchk(struct statfs *);
+int oneof(char *, char*[], int);
+int qfinsert(FILE *, struct dqblk *, int, int);
+int qfmaxentries(char *, int);
+void usage(void);
+void dqbuftohost(struct dqblk *dqbp);
+
+#else
+struct fileusage *
+ addid __P((uid_t, int, char *));
+char *blockcheck __P((char *));
+int chkquota __P((char *, char *, struct quotaname *));
+int getquotagid __P((void));
+int hasquota __P((struct fstab *, int, char **));
+struct fileusage *
+ lookup __P((u_long, int));
+void *needchk __P((struct fstab *));
+int oneof __P((char *, char*[], int));
+int update __P((char *, char *, int));
+void usage __P((void));
+#endif /* __APPLE__ */
+
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifndef __APPLE__
+ register struct fstab *fs;
+ register struct passwd *pw;
+ register struct group *gr;
+#endif /* !__APPLE__ */
+ struct quotaname *auxdata;
+ int i, argnum, maxrun, errs;
+ long done = 0;
+ char ch, *name;
+
+#ifdef __APPLE__
+ int nfst;
+ struct statfs *fst;
+#endif /* __APPLE__ */
+
+ errs = maxrun = 0;
+ while ((ch = getopt(argc, argv, "aguvl:")) != EOF) {
+ switch(ch) {
+ case 'a':
+ aflag++;
+ break;
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case 'l':
+ maxrun = atoi(optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if ((argc == 0 && !aflag) || (argc > 0 && aflag))
+ usage();
+ if (!gflag && !uflag) {
+ gflag++;
+ uflag++;
+ }
+
+#ifdef __APPLE__
+ nfst = getmntinfo(&fst, MNT_WAIT);
+ if (nfst==0) {
+ fprintf(stderr, "quotacheck: no mounted filesystems\n");
+ exit(1);
+ }
+
+ for (i=0; i<nfst; i++) {
+ if(strcmp(fst[i].f_fstypename, "hfs")) {
+ continue;
+ }
+
+ if (aflag) {
+ if ((auxdata = needchk(&fst[i])) &&
+ (name = blockcheck(fst[i].f_mntfromname))) {
+ errs += chkquota(fst[i].f_fstypename, name, fst[i].f_mntonname, auxdata);
+ }
+
+ if (i+1 == nfst)
+ exit (errs);
+ else
+ continue;
+ }
+
+ if (((argnum = oneof(fst[i].f_mntonname, argv, argc)) >= 0 ||
+ (argnum = oneof(fst[i].f_mntfromname, argv, argc)) >= 0) &&
+ (auxdata = needchk(&fst[i])) &&
+ (name = blockcheck(fst[i].f_mntfromname))) {
+ done |= 1 << argnum;
+ errs += chkquota(fst[i].f_fstypename, name, fst[i].f_mntonname, auxdata);
+ }
+ } /* end for loop */
+
+ for (i = 0; i < argc; i++)
+ if ((done & (1 << i)) == 0)
+ fprintf(stderr, "%s not identified as a quota filesystem\n",
+ argv[i]);
+
+ exit(errs);
+#else
+ if (gflag) {
+ setgrent();
+ while ((gr = getgrent()) != 0)
+ (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
+ endgrent();
+ }
+ if (uflag) {
+ setpwent();
+ while ((pw = getpwent()) != 0)
+ (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
+ endpwent();
+ }
+ if (aflag)
+ exit(checkfstab(1, maxrun, needchk, chkquota));
+ if (setfsent() == 0)
+ err(1, "%s: can't open", FSTAB);
+ while ((fs = getfsent()) != NULL) {
+ if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
+ (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) &&
+ (auxdata = needchk(fs)) &&
+ (name = blockcheck(fs->fs_spec))) {
+ done |= 1 << argnum;
+ errs += chkquota(name, fs->fs_file, auxdata);
+ }
+ }
+ endfsent();
+ for (i = 0; i < argc; i++)
+ if ((done & (1 << i)) == 0)
+ fprintf(stderr, "%s not found in %s\n",
+ argv[i], FSTAB);
+ exit(errs);
+#endif /* __APPLE__ */
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr, "usage:\t%s\n\t%s\n",
+ "quotacheck -a [-guv]",
+ "quotacheck [-guv] filesys ...");
+ exit(1);
+}
+
+#ifdef __APPLE__
+void *
+needchk(fst)
+ struct statfs *fst;
+{
+ register struct quotaname *qnp;
+ char *qfnp;
+
+ if(strcmp(fst->f_fstypename, "hfs")) {
+ return(NULL);
+ }
+ if(fst->f_flags & MNT_RDONLY)
+ return (NULL);
+ if ((qnp = malloc(sizeof(*qnp))) == NULL)
+ err(1, "%s", strerror(errno));
+ qnp->flags = 0;
+ if (gflag && hasquota(fst, GRPQUOTA, &qfnp)) {
+ strlcpy(qnp->grpqfname, qfnp, sizeof(qnp->grpqfname));
+ qnp->flags |= HASGRP;
+ }
+ if (uflag && hasquota(fst, USRQUOTA, &qfnp)) {
+ strlcpy(qnp->usrqfname, qfnp, sizeof(qnp->usrqfname));
+ qnp->flags |= HASUSR;
+ }
+ if (qnp->flags)
+ return (qnp);
+ free(qnp);
+ return (NULL);
+}
+#else
+void *
+needchk(fs)
+ register struct fstab *fs;
+{
+ register struct quotaname *qnp;
+ char *qfnp;
+
+ if (strcmp(fs->fs_type, FSTAB_RW))
+ return (NULL);
+
+ if ((qnp = malloc(sizeof(*qnp))) == NULL)
+ err(1, "%s", strerror(errno));
+ qnp->flags = 0;
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) {
+ strlcpy(qnp->grpqfname, qfnp, sizeof(qnp->grpqfname));
+ qnp->flags |= HASGRP;
+ }
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp)) {
+ strlcpy(qnp->usrqfname, qfnp, sizeof(qnp->usrqfname));
+ qnp->flags |= HASUSR;
+ }
+ if (qnp->flags)
+ return (qnp);
+ free(qnp);
+ return (NULL);
+}
+#endif /* __APPLE__ */
+
+/*
+ * Scan the specified filesystem to check quota(s) present on it.
+ */
+int
+chkquota(fstype, fsname, mntpt, qnp)
+ char *fstype, *fsname, *mntpt;
+ register struct quotaname *qnp;
+{
+ int errs = 1;
+
+ if (vflag) {
+ fprintf(stdout, "*** Checking ");
+ if (qnp->flags & HASUSR)
+ fprintf(stdout, "%s%s", qfextension[USRQUOTA],
+ (qnp->flags & HASGRP) ? " and " : "");
+ if (qnp->flags & HASGRP)
+ fprintf(stdout, "%s", qfextension[GRPQUOTA]);
+ fprintf(stdout, " quotas for %s (%s)\n", fsname, mntpt);
+ }
+
+ if(strcmp(fstype, "hfs") == 0)
+ errs = chkquota_hfs(fsname, mntpt, qnp);
+
+ return (errs);
+}
+
+/*
+ * Update a specified quota file.
+ */
+#ifdef __APPLE__
+int
+update(fsname, quotafile, type)
+ char *fsname, *quotafile;
+ register int type;
+{
+ register struct fileusage *fup;
+ register FILE *qfi, *qfo;
+ register u_long i;
+ struct dqblk dqbuf;
+ struct dqfilehdr dqhdr = {0};
+ int m, shift;
+ int idcnt = 0;
+ static int warned = 0;
+ static struct dqblk zerodqbuf;
+ static struct fileusage zerofileusage;
+
+ if ((qfo = fopen(quotafile, "r+")) == NULL) {
+ if (errno == ENOENT)
+ qfo = fopen(quotafile, "w+");
+ if (qfo) {
+ fprintf(stderr,
+ "quotacheck: creating quota file %s\n", quotafile);
+#define MODE (S_IRUSR|S_IWUSR|S_IRGRP)
+ (void) fchown(fileno(qfo), getuid(), getquotagid());
+ (void) fchmod(fileno(qfo), MODE);
+ } else {
+ fprintf(stderr,
+ "quotacheck: %s: %s\n", quotafile, strerror(errno));
+ return (1);
+ }
+ }
+ if ((qfi = fopen(quotafile, "r")) == NULL) {
+ fprintf(stderr,
+ "quotacheck: %s: %s\n", quotafile, strerror(errno));
+ (void) fclose(qfo);
+ return (1);
+ }
+ if (quotactl(fsname, QCMD(Q_SYNC, type), 0, 0) < 0 &&
+ errno == ENOTSUP && !warned && vflag) {
+ warned++;
+ fprintf(stdout, "*** Warning: %s\n",
+ "Quotas are not compiled into this kernel");
+ }
+
+ /* Read in the quota file header. */
+ if (fread((char *)&dqhdr, sizeof(struct dqfilehdr), 1, qfi) > 0) {
+ /* Check for reverse endian file. */
+ if (OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type] &&
+ OSSwapInt32(dqhdr.dqh_magic) == quotamagic[type]) {
+ fprintf(stderr,
+ "quotacheck: %s: not in big endian byte order\n",
+ quotafile);
+ (void) fclose(qfo);
+ (void) fclose(qfi);
+ return (1);
+ }
+ /* Sanity check the quota file header. */
+ if ((OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type]) ||
+ (OSSwapBigToHostInt32(dqhdr.dqh_version) > QF_VERSION) ||
+ (!powerof2(OSSwapBigToHostInt32(dqhdr.dqh_maxentries)))) {
+ fprintf(stderr,
+ "quotacheck: %s: not a valid quota file\n",
+ quotafile);
+ (void) fclose(qfo);
+ (void) fclose(qfi);
+ return (1);
+ }
+ m = OSSwapBigToHostInt32(dqhdr.dqh_maxentries);
+ } else /* empty file */ {
+ if (maxentries)
+ m = maxentries;
+ else
+ m = qfmaxentries(fsname, type);
+
+ ftruncate(fileno(qfo), (off_t)((m + 1) * sizeof(struct dqblk)));
+
+ /* Initialize file header in big endian. */
+ dqhdr.dqh_magic = OSSwapHostToBigInt32(quotamagic[type]);
+ dqhdr.dqh_version = OSSwapHostToBigConstInt32(QF_VERSION);
+ dqhdr.dqh_maxentries = OSSwapHostToBigInt32(m);
+ dqhdr.dqh_btime = OSSwapHostToBigConstInt32(MAX_DQ_TIME);
+ dqhdr.dqh_itime = OSSwapHostToBigConstInt32(MAX_IQ_TIME);
+ memmove(dqhdr.dqh_string, QF_STRING_TAG, strlen(QF_STRING_TAG));
+ goto orphans; /* just insert all new records */
+ }
+
+ /* Examine all the entries in the quota file. */
+ for (i = 0; i < m; i++) {
+ if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0) {
+ fprintf(stderr,
+ "quotacheck: problem reading at index %ld\n", i);
+ continue;
+ }
+ if (dqbuf.dqb_id == 0)
+ continue;
+
+ ++idcnt;
+ if ((fup = lookup(OSSwapBigToHostInt32(dqbuf.dqb_id), type)) == 0)
+ fup = &zerofileusage;
+ else
+ fup->fu_checked = 1;
+
+ if (OSSwapBigToHostInt32(dqbuf.dqb_curinodes) == fup->fu_curinodes &&
+ OSSwapBigToHostInt64(dqbuf.dqb_curbytes) == fup->fu_curbytes) {
+ fup->fu_curinodes = 0;
+ fup->fu_curbytes = 0;
+ continue;
+ }
+ if (vflag) {
+ if (aflag)
+ fprintf(stdout, "%s: ", fsname);
+ fprintf(stdout, "%-12s fixed:", fup->fu_name);
+ if (OSSwapBigToHostInt32(dqbuf.dqb_curinodes) != fup->fu_curinodes)
+ fprintf(stdout, "\tinodes %u -> %u",
+ OSSwapBigToHostInt32(dqbuf.dqb_curinodes), fup->fu_curinodes);
+ if (OSSwapBigToHostInt64(dqbuf.dqb_curbytes) != fup->fu_curbytes)
+ fprintf(stdout, "\t1K blocks %qd -> %qd",
+ (OSSwapBigToHostInt64(dqbuf.dqb_curbytes)/1024), (fup->fu_curbytes/1024));
+ fprintf(stdout, "\n");
+ }
+ /*
+ * Reset time limit if have a soft limit and were
+ * previously under it, but are now over it.
+ */
+ if (dqbuf.dqb_bsoftlimit != 0 &&
+ OSSwapBigToHostInt64(dqbuf.dqb_curbytes) < OSSwapBigToHostInt64(dqbuf.dqb_bsoftlimit) &&
+ fup->fu_curbytes >= OSSwapBigToHostInt64(dqbuf.dqb_bsoftlimit))
+ dqbuf.dqb_btime = 0;
+ if (dqbuf.dqb_isoftlimit != 0 &&
+ OSSwapBigToHostInt32(dqbuf.dqb_curinodes) < OSSwapBigToHostInt32(dqbuf.dqb_isoftlimit) &&
+ fup->fu_curinodes >= OSSwapBigToHostInt32(dqbuf.dqb_isoftlimit))
+ dqbuf.dqb_itime = 0;
+ dqbuf.dqb_curinodes = OSSwapHostToBigInt32(fup->fu_curinodes);
+ dqbuf.dqb_curbytes = OSSwapHostToBigInt64(fup->fu_curbytes);
+
+ /* Write dqblk in big endian. */
+ fseek(qfo, dqoffset(i), SEEK_SET);
+ fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo);
+
+ dqbuftohost(&dqbuf);
+ (void) quotactl(fsname, QCMD(Q_SETUSE, type), dqbuf.dqb_id,
+ (caddr_t)&dqbuf);
+ fup->fu_curinodes = 0;
+ fup->fu_curbytes = 0;
+ }
+orphans:
+ /* Look for any fileusage orphans */
+
+ shift = dqhashshift(m);
+ for (i = 0; i < FUHASH; ++i) {
+ for (fup = fuhead[type][i]; fup != 0; fup = fup->fu_next) {
+ if (fup->fu_checked || fup->fu_id == 0)
+ continue;
+ if (vflag) {
+ if (aflag)
+ fprintf(stdout, "%s: ", fsname);
+ fprintf(stdout,
+ "%-12s added:\tinodes %u\t1K blocks %qd\n",
+ fup->fu_name, fup->fu_curinodes,
+ (fup->fu_curbytes/1024));
+ }
+ /* Initialize dqbuf in big endian. */
+ dqbuf = zerodqbuf;
+ dqbuf.dqb_id = OSSwapHostToBigInt32(fup->fu_id);
+ dqbuf.dqb_curinodes = OSSwapHostToBigInt32(fup->fu_curinodes);
+ dqbuf.dqb_curbytes = OSSwapHostToBigInt64(fup->fu_curbytes);
+ /* insert this dqb */
+ if (qfinsert(qfo, &dqbuf, m, shift)) {
+ i = FUHASH;
+ break;
+ }
+
+ dqbuftohost(&dqbuf);
+ (void) quotactl(fsname, QCMD(Q_SETUSE, type),
+ dqbuf.dqb_id, (caddr_t)&dqbuf);
+ ++idcnt;
+ }
+ }
+
+ /* Write the quota file header */
+ dqhdr.dqh_entrycnt = OSSwapHostToBigInt32(idcnt);
+ fseek(qfo, (long)0, SEEK_SET);
+ fwrite((char *)&dqhdr, sizeof(struct dqfilehdr), 1, qfo);
+
+ fclose(qfi);
+ fflush(qfo);
+ fclose(qfo);
+ return (0);
+}
+
+/* Convert a dqblk to host native byte order. */
+void
+dqbuftohost(struct dqblk *dqbp)
+{
+ dqbp->dqb_bhardlimit = OSSwapBigToHostInt64(dqbp->dqb_bhardlimit);
+ dqbp->dqb_bsoftlimit = OSSwapBigToHostInt64(dqbp->dqb_bsoftlimit);
+ dqbp->dqb_curbytes = OSSwapBigToHostInt64(dqbp->dqb_curbytes);
+ dqbp->dqb_ihardlimit = OSSwapBigToHostInt32(dqbp->dqb_ihardlimit);
+ dqbp->dqb_isoftlimit = OSSwapBigToHostInt32(dqbp->dqb_isoftlimit);
+ dqbp->dqb_curinodes = OSSwapBigToHostInt32(dqbp->dqb_curinodes);
+ dqbp->dqb_btime = OSSwapBigToHostInt32(dqbp->dqb_btime);
+ dqbp->dqb_itime = OSSwapBigToHostInt32(dqbp->dqb_itime);
+ dqbp->dqb_id = OSSwapBigToHostInt32(dqbp->dqb_id);
+}
+
+#else
+int
+update(fsname, quotafile, type)
+ char *fsname, *quotafile;
+ register int type;
+{
+ register struct fileusage *fup;
+ register FILE *qfi, *qfo;
+ register u_long id, lastid;
+ struct dqblk dqbuf;
+ static int warned = 0;
+ static struct dqblk zerodqbuf;
+ static struct fileusage zerofileusage;
+
+ if ((qfo = fopen(quotafile, "r+")) == NULL) {
+ if (errno == ENOENT)
+ qfo = fopen(quotafile, "w+");
+ if (qfo) {
+ (void) fprintf(stderr,
+ "quotacheck: creating quota file %s\n", quotafile);
+#define MODE (S_IRUSR|S_IWUSR|S_IRGRP)
+ (void) fchown(fileno(qfo), getuid(), getquotagid());
+ (void) fchmod(fileno(qfo), MODE);
+ } else {
+ (void) fprintf(stderr,
+ "quotacheck: %s: %s\n", quotafile, strerror(errno));
+ return (1);
+ }
+ }
+ if ((qfi = fopen(quotafile, "r")) == NULL) {
+ (void) fprintf(stderr,
+ "quotacheck: %s: %s\n", quotafile, strerror(errno));
+ (void) fclose(qfo);
+ return (1);
+ }
+ if (quotactl(fsname, QCMD(Q_SYNC, type), (u_long)0, (caddr_t)0) < 0 &&
+ errno == ENOTSUP && !warned && vflag) {
+ warned++;
+ (void)printf("*** Warning: %s\n",
+ "Quotas are not compiled into this kernel");
+ }
+ for (lastid = highid[type], id = 0; id <= lastid; id++) {
+ if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0)
+ dqbuf = zerodqbuf;
+ if ((fup = lookup(id, type)) == 0)
+ fup = &zerofileusage;
+ if (dqbuf.dqb_curinodes == fup->fu_curinodes &&
+ dqbuf.dqb_curblocks == fup->fu_curblocks) {
+ fup->fu_curinodes = 0;
+ fup->fu_curblocks = 0;
+ fseek(qfo, (long)sizeof(struct dqblk), 1);
+ continue;
+ }
+ if (vflag) {
+ if (aflag)
+ printf("%s: ", fsname);
+ printf("%-8s fixed:", fup->fu_name);
+ if (dqbuf.dqb_curinodes != fup->fu_curinodes)
+ (void)printf("\tinodes %d -> %d",
+ dqbuf.dqb_curinodes, fup->fu_curinodes);
+ if (dqbuf.dqb_curblocks != fup->fu_curblocks)
+ (void)printf("\tblocks %d -> %d",
+ dqbuf.dqb_curblocks, fup->fu_curblocks);
+ (void)printf("\n");
+ }
+ /*
+ * Reset time limit if have a soft limit and were
+ * previously under it, but are now over it.
+ */
+ if (dqbuf.dqb_bsoftlimit &&
+ dqbuf.dqb_curblocks < dqbuf.dqb_bsoftlimit &&
+ fup->fu_curblocks >= dqbuf.dqb_bsoftlimit)
+ dqbuf.dqb_btime = 0;
+ if (dqbuf.dqb_isoftlimit &&
+ dqbuf.dqb_curblocks < dqbuf.dqb_isoftlimit &&
+ fup->fu_curblocks >= dqbuf.dqb_isoftlimit)
+ dqbuf.dqb_itime = 0;
+ dqbuf.dqb_curinodes = fup->fu_curinodes;
+ dqbuf.dqb_curblocks = fup->fu_curblocks;
+ fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo);
+ (void) quotactl(fsname, QCMD(Q_SETUSE, type), id,
+ (caddr_t)&dqbuf);
+ fup->fu_curinodes = 0;
+ fup->fu_curblocks = 0;
+ }
+ fclose(qfi);
+ fflush(qfo);
+ ftruncate(fileno(qfo),
+ (off_t)((highid[type] + 1) * sizeof(struct dqblk)));
+ fclose(qfo);
+ return (0);
+}
+#endif /* __APPLE__ */
+
+#ifdef __APPLE__
+/*
+ * Insert an entry into a quota file.
+ *
+ * The dqblk pointed to by dqbp is in big endian.
+ */
+int
+qfinsert(file, dqbp, maxentries, shift)
+ FILE *file;
+ struct dqblk *dqbp;
+ int maxentries, shift;
+{
+ struct dqblk dqbuf;
+ int i, skip, last;
+ u_int32_t mask;
+ u_int32_t id;
+ off_t offset;
+
+ id = OSSwapBigToHostInt32(dqbp->dqb_id);
+ if (id == 0)
+ return (0);
+ mask = maxentries - 1;
+ i = dqhash1(id, dqhashshift(maxentries), mask);
+ skip = dqhash2(id, mask);
+
+ for (last = (i + (maxentries-1) * skip) & mask;
+ i != last;
+ i = (i + skip) & mask) {
+ offset = dqoffset(i);
+ fseek(file, (long)offset, SEEK_SET);
+ if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, file) == 0) {
+ fprintf(stderr, "quotacheck: read error at index %d\n", i);
+ return (EIO);
+ }
+ /*
+ * Stop when an empty entry is found
+ * or we encounter a matching id.
+ */
+ if (dqbuf.dqb_id == 0 || dqbuf.dqb_id == dqbp->dqb_id) {
+ dqbuf = *dqbp;
+ fseek(file, (long)offset, SEEK_SET);
+ fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, file);
+ return (0);
+ }
+ }
+ fprintf(stderr, "quotacheck: exceeded maximum entries (%d)\n", maxentries);
+ return (ENOSPC);
+}
+
+#define ONEGIGABYTE (1024*1024*1024)
+
+/*
+ * Calculate the size of the hash table from the size of
+ * the file system. The open addressing hashing used on
+ * the quota file assumes that this table will never be
+ * more than 90% full.
+ */
+int
+qfmaxentries(mntpt, type)
+ char *mntpt;
+ int type;
+{
+ struct statfs fs_stat;
+ u_int64_t fs_size;
+ int max = 0;
+
+ if (statfs(mntpt, &fs_stat)) {
+ fprintf(stderr, "quotacheck: %s: %s\n",
+ mntpt, strerror(errno));
+ return (0);
+ }
+ fs_size = (u_int64_t)fs_stat.f_blocks * (u_int64_t)fs_stat.f_bsize;
+
+ if (type == USRQUOTA) {
+ max = QF_USERS_PER_GB * (fs_size / ONEGIGABYTE);
+
+ if (max < QF_MIN_USERS)
+ max = QF_MIN_USERS;
+ else if (max > QF_MAX_USERS)
+ max = QF_MAX_USERS;
+ } else if (type == GRPQUOTA) {
+ max = QF_GROUPS_PER_GB * (fs_size / ONEGIGABYTE);
+
+ if (max < QF_MIN_GROUPS)
+ max = QF_MIN_GROUPS;
+ else if (max > QF_MAX_GROUPS)
+ max = QF_MAX_GROUPS;
+ }
+ /* Round up to a power of 2 */
+ if (max && !powerof2(max)) {
+ int x = max;
+ max = 4;
+ while (x>>1 != 1) {
+ x = x >> 1;
+ max = max << 1;
+ }
+ }
+ return (max);
+}
+#endif /* __APPLE__ */
+
+/*
+ * Check to see if target appears in list of size cnt.
+ */
+int
+oneof(target, list, cnt)
+ register char *target, *list[];
+ int cnt;
+{
+ register int i;
+
+ for (i = 0; i < cnt; i++)
+ if (strcmp(target, list[i]) == 0)
+ return (i);
+ return (-1);
+}
+
+/*
+ * Determine the group identifier for quota files.
+ */
+int
+getquotagid()
+{
+ struct group *gr;
+
+ if ((gr = getgrnam(quotagroup)))
+ return (gr->gr_gid);
+ return (-1);
+}
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+#ifdef __APPLE__
+int
+hasquota(fst, type, qfnamep)
+ struct statfs *fst;
+ int type;
+ char **qfnamep;
+{
+ struct stat sb;
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ (void)snprintf(usrname, sizeof(usrname),
+ "%s%s", qfextension[USRQUOTA], qfname);
+ (void)snprintf(grpname, sizeof(grpname),
+ "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+
+ /*
+ We only support the default path to the
+ on disk quota files.
+ */
+
+ (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname,
+ QUOTAOPSNAME, qfextension[type] );
+ if (stat(buf, &sb) != 0) {
+ /* There appears to be no mount option file */
+ return(0);
+ }
+
+ (void)snprintf(buf, sizeof(buf),
+ "%s/%s.%s", fst->f_mntonname, qfname, qfextension[type]);
+ *qfnamep = buf;
+
+ return (1);
+}
+#else
+int
+hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp;
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ (void)snprintf(usrname, sizeof(usrname),
+ "%s%s", qfextension[USRQUOTA], qfname);
+ (void)snprintf(grpname, sizeof(grpname),
+ "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strlcpy(buf, fs->fs_mntops, sizeof(buf));
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = strchr(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp)
+ *qfnamep = cp;
+ else {
+ (void)snprintf(buf, sizeof(buf),
+ "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ }
+ return (1);
+}
+#endif /* __APPLE__ */
+
+/*
+ * Routines to manage the file usage table.
+ *
+ * Lookup an id of a specific type.
+ */
+struct fileusage *
+lookup(id, type)
+ u_long id;
+ int type;
+{
+ register struct fileusage *fup;
+
+ for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next)
+ if (fup->fu_id == id)
+ return (fup);
+ return (NULL);
+}
+
+/*
+ * Add a new file usage id if it does not already exist.
+ */
+#ifdef __APPLE__
+struct fileusage *
+addid(id, type)
+ uid_t id;
+ int type;
+{
+ struct fileusage *fup, **fhp;
+ struct passwd *pw;
+ struct group *gr;
+ char *name;
+ size_t len;
+
+ if ((fup = lookup(id, type)))
+ return (fup);
+
+ name = NULL;
+ len = 10;
+ switch (type) {
+ case USRQUOTA:
+ if ((pw = getpwuid(id)) != 0) {
+ name = pw->pw_name;
+ len = strlen(name);
+ }
+ break;
+ case GRPQUOTA:
+ if ((gr = getgrgid(id)) != 0) {
+ name = gr->gr_name;
+ len = strlen(name);
+ }
+ break;
+ }
+
+ if ((fup = calloc(1, sizeof(*fup) + len)) == NULL)
+ err(1, "%s", strerror(errno));
+ fhp = &fuhead[type][id & (FUHASH - 1)];
+ fup->fu_next = *fhp;
+ *fhp = fup;
+ fup->fu_id = id;
+ if (name)
+ memmove(fup->fu_name, name, len + 1);
+ else
+ (void)snprintf(fup->fu_name, len + 1, "%u", (unsigned int)id);
+
+ return (fup);
+}
+#else
+struct fileusage *
+addid(id, type, name)
+ u_long id;
+ int type;
+ char *name;
+{
+ struct fileusage *fup, **fhp;
+ int len;
+
+ if (fup = lookup(id, type))
+ return (fup);
+ if (name)
+ len = strlen(name);
+ else
+ len = 10;
+ if ((fup = calloc(1, sizeof(*fup) + len)) == NULL)
+ err(1, "%s", strerror(errno));
+ fhp = &fuhead[type][id & (FUHASH - 1)];
+ fup->fu_next = *fhp;
+ *fhp = fup;
+ fup->fu_id = id;
+ if (id > highid[type])
+ highid[type] = id;
+ if (name)
+ memmove(fup->fu_name, name, len + 1);
+ else
+ (void)snprintf(fup->fu_name, len + 1, "%u", id);
+ return (fup);
+}
+#endif /* __APPLE__ */
+
diff --git a/diskdev_cmds/quotacheck.tproj/quotacheck.h b/diskdev_cmds/quotacheck.tproj/quotacheck.h
new file mode 100644
index 0000000..da1bbdc
--- /dev/null
+++ b/diskdev_cmds/quotacheck.tproj/quotacheck.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+struct fileusage {
+ struct fileusage *fu_next;
+ u_int32_t fu_curinodes;
+ u_int64_t fu_curbytes;
+ u_int32_t fu_id;
+ char fu_checked;
+ char fu_name[1];
+ /* actually bigger */
+};
+
+
+extern int vflag; /* verbose mode */
+
+
+struct quotaname {
+ long flags;
+ char grpqfname[MAXPATHLEN + 1];
+ char usrqfname[MAXPATHLEN + 1];
+};
+#define HASUSR 1
+#define HASGRP 2
+
+
+extern struct fileusage *
+ addid(uid_t, int);
+extern int update(char *, char *, int);
+
+extern int chkquota_hfs(char *, char *, struct quotaname *);
diff --git a/diskdev_cmds/quotaon.tproj/quotaon.8 b/diskdev_cmds/quotaon.tproj/quotaon.8
new file mode 100644
index 0000000..a3bafe6
--- /dev/null
+++ b/diskdev_cmds/quotaon.tproj/quotaon.8
@@ -0,0 +1,159 @@
+.\" Copyright (c) 1983, 1990, 1991, 1993, 2002
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)quotaon.8 8.2 (Berkeley) 12/11/93
+.\"
+.Dd October 17, 2002
+.Dt QUOTAON 8
+.Os BSD 4.2
+.Sh NAME
+.Nm quotaon ,
+.Nm quotaoff
+.Nd turn filesystem quotas on and off
+.Sh SYNOPSIS
+.Nm quotaon
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Ar filesystem Ar ...
+.Nm quotaon
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Fl a
+.Nm quotaoff
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Ar filesystem Ar ...
+.Nm quotaoff
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Fl a
+.Sh DESCRIPTION
+.Nm Quotaon
+announces to the system that disk quotas should be enabled on one or more
+filesystems.
+.Nm Quotaoff
+announces to the system that the specified
+filesystems should have disk quotas
+turned off.
+The filesystem must be mounted and it
+must have the
+appropriate mount option file located at its root, the
+.Pa .quota.ops.user
+file for user quota configuration, and the
+.Pa .quota.ops.group
+file for group quota configuration.
+.Nm Quotaon
+also expects each filesystem to have the appropriate
+quota data files located at its root, the
+.Pa .quota.user
+file for user data, and the
+.Pa .quota.group
+file for group data.
+These filenames and their root location cannot be overridden.
+By default,
+.Nm quotaon
+will attempt to enable both
+user and group quotas.
+By default,
+.Nm quotaoff
+will disable both
+user and group quotas.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+If the
+.Fl a
+flag is supplied in place of any filesystem names,
+.Nm quotaon Ns / Ns Nm quotaoff
+will enable/disable any filesystems with an existing
+mount option file at its root. The mount option file
+specifies the types of quotas that are to be configured.
+.It Fl g
+Only group quotas will be enabled/disabled.
+The mount option file,
+.Pa .quota.ops.group ,
+must exist at the root of the filesystem.
+.It Fl u
+Only user quotas will be enabled/disabled.
+The mount option file,
+.Pa .quota.ops.user ,
+must exist at the root of the filesystem.
+.It Fl v
+Causes
+.Nm quotaon
+and
+.Nm quotaoff
+to print a message for each filesystem where quotas are turned on or off.
+.El
+.Pp
+Specifying both
+.Fl g
+and
+.Fl u
+is equivalent to the default.
+.Pp
+Quotas for both users and groups will automatically be turned
+on at filesystem mount if the appropriate mount option file
+and binary data file is in place at its root.
+.Sh FILES
+Each of the following quota files is located at the root of the
+mounted filesystem. The mount option files are empty files
+whose existence indicates that quotas are to be enabled
+for that filesystem.
+.Pp
+.Bl -tag -width .quota.ops.group -compact
+.It Pa .quota.user
+data file containing user quotas
+.It Pa .quota.group
+data file containing group quotas
+.It Pa .quota.ops.user
+mount option file used to enable user quotas
+.It Pa .quota.ops.group
+mount option file used to enable group quotas
+.El
+.Sh SEE ALSO
+.Xr quota 1 ,
+.Xr quotactl 2 ,
+.Xr edquota 8 ,
+.Xr quotacheck 8 ,
+.Xr repquota 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/diskdev_cmds/quotaon.tproj/quotaon.c b/diskdev_cmds/quotaon.tproj/quotaon.c
new file mode 100644
index 0000000..a94be7b
--- /dev/null
+++ b/diskdev_cmds/quotaon.tproj/quotaon.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 1999, 2002, 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#ifndef lint
+__unused static char copyright[] =
+"@(#) Copyright (c) 1980, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+__unused static char sccsid[] = "@(#)quotaon.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+/*
+ * Turn quota on/off for a filesystem.
+ */
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/mount.h>
+#ifdef __APPLE__
+#include <sys/stat.h>
+#endif /* __APPLE__ */
+#include <sys/appleapiopts.h>
+#include <sys/quota.h>
+#include <stdio.h>
+#include <fstab.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Internal functions */
+void usage(char *whoami);
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+
+int aflag; /* all file systems */
+int gflag; /* operate on group quotas */
+int uflag; /* operate on user quotas */
+int vflag; /* verbose */
+
+/* Function prototypes */
+#ifdef __APPLE__
+int hasquota(register struct statfs *, int, char **);
+int quotaonoff(register struct statfs *, int, int, char *);
+#else
+int hasquota(register struct fstab *, int, char **);
+int quotaonoff(register struct fstab *, int, int, char *);
+#endif /* __APPLE__ */
+
+int oneof(register char *, register char **, int);
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char ch, *qfnp, *whoami, *rindex();
+ long argnum, done = 0;
+ int i, offmode = 0, errs = 0;
+#ifdef __APPLE__
+ int nfst;
+ struct statfs *fst;
+#endif /* __APPLE__ */
+
+ whoami = rindex(*argv, '/') + 1;
+ if (whoami == (char *)1)
+ whoami = *argv;
+ if (strcmp(whoami, "quotaoff") == 0)
+ offmode++;
+ else if (strcmp(whoami, "quotaon") != 0) {
+ fprintf(stderr, "Name must be quotaon or quotaoff not %s\n",
+ whoami);
+ exit(1);
+ }
+ while ((ch = getopt(argc, argv, "avug")) != EOF) {
+ switch(ch) {
+ case 'a':
+ aflag++;
+ break;
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ usage(whoami);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc <= 0 && !aflag)
+ usage(whoami);
+ if (!gflag && !uflag) {
+ gflag++;
+ uflag++;
+ }
+
+#ifdef __APPLE__
+ nfst = getmntinfo(&fst, MNT_WAIT);
+ if (nfst==0) {
+ fprintf(stderr, "no filesystems mounted");
+ return(1);
+ }
+
+ for (i=0; i<nfst; i++) {
+ if(strcmp(fst[i].f_fstypename, "hfs")) {
+ continue;
+ }
+ if(fst[i].f_flags & MNT_RDONLY) {
+ errs++;
+ continue;
+ }
+
+ if (aflag) {
+ if (gflag && hasquota(&fst[i], GRPQUOTA, &qfnp))
+ errs += quotaonoff(&fst[i], offmode, GRPQUOTA, qfnp);
+ if (uflag && hasquota(&fst[i], USRQUOTA, &qfnp))
+ errs += quotaonoff(&fst[i], offmode, USRQUOTA, qfnp);
+ continue;
+ }
+ if ((argnum = oneof(fst[i].f_mntonname, argv, argc)) >= 0 ||
+ (argnum = oneof(fst[i].f_mntfromname, argv, argc)) >= 0) {
+ done |= 1 << argnum;
+ if (gflag && hasquota(&fst[i], GRPQUOTA, &qfnp))
+ errs += quotaonoff(&fst[i], offmode, GRPQUOTA, qfnp);
+ if (uflag && hasquota(&fst[i], USRQUOTA, &qfnp))
+ errs += quotaonoff(&fst[i], offmode, USRQUOTA, qfnp);
+ }
+ }
+#else
+ register struct fstab *fs;
+ setfsent();
+ while ((fs = getfsent()) != NULL) {
+ if (strcmp(fs->fs_vfstype, "ufs") ||
+ strcmp(fs->fs_type, FSTAB_RW))
+ continue;
+ if (aflag) {
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
+ continue;
+ }
+ if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
+ (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
+ done |= 1 << argnum;
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
+ }
+ }
+ endfsent();
+#endif /* __APPLE__ */
+ for (i = 0; i < argc; i++)
+ if ((done & (1 << i)) == 0)
+ fprintf(stderr, "%s not found in fstab\n",
+ argv[i]);
+ exit(errs);
+}
+
+void usage(whoami)
+ char *whoami;
+{
+
+ fprintf(stderr, "Usage:\n\t%s [-g] [-u] [-v] -a\n", whoami);
+ fprintf(stderr, "\t%s [-g] [-u] [-v] filesys ...\n", whoami);
+ exit(1);
+}
+
+#ifdef __APPLE__
+int quotaonoff(fst, offmode, type, qfpathname)
+ register struct statfs *fst;
+ int offmode, type;
+ char *qfpathname;
+{
+ if (strcmp(fst->f_mntonname, "/") && (fst->f_flags & MNT_RDONLY))
+ return (1);
+ if (offmode) {
+ if (quotactl(fst->f_mntonname, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
+ fprintf(stderr, "quotaoff: ");
+ perror(fst->f_mntonname);
+ return (1);
+ }
+ if (vflag)
+ printf("%s: %s quotas turned off\n", fst->f_mntonname,
+ qfextension[type]);
+ return (0);
+ }
+ if (quotactl(fst->f_mntonname, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
+ fprintf(stderr, "quotaon: using %s on ", qfpathname);
+ perror(fst->f_mntonname);
+ return (1);
+ }
+ if (vflag)
+ printf("%s: %s quotas turned on\n", fst->f_mntonname,
+ qfextension[type]);
+ return (0);
+}
+#else
+int quotaonoff(fs, offmode, type, qfpathname)
+ register struct fstab *fs;
+ int offmode, type;
+ char *qfpathname;
+{
+
+ if (strcmp(fs->fs_file, "/") && readonly(fs))
+ return (1);
+ if (offmode) {
+ if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
+ fprintf(stderr, "quotaoff: ");
+ perror(fs->fs_file);
+ return (1);
+ }
+ if (vflag)
+ printf("%s: quotas turned off\n", fs->fs_file);
+ return (0);
+ }
+ if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
+ fprintf(stderr, "quotaon: using %s on", qfpathname);
+ perror(fs->fs_file);
+ return (1);
+ }
+ if (vflag)
+ printf("%s: %s quotas turned on\n", fs->fs_file,
+ qfextension[type]);
+ return (0);
+}
+#endif /* __APPLE__ */
+
+/*
+ * Check to see if target appears in list of size cnt.
+ */
+int oneof(target, list, cnt)
+ register char *target, *list[];
+ int cnt;
+{
+ register int i;
+
+ for (i = 0; i < cnt; i++)
+ if (strcmp(target, list[i]) == 0)
+ return (i);
+ return (-1);
+}
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+#ifdef __APPLE__
+int hasquota(fst, type, qfnamep)
+ register struct statfs *fst;
+ int type;
+ char **qfnamep;
+{
+ struct stat sb;
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+
+ /*
+ We only support the default path to the
+ on disk quota files.
+ */
+
+ (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname,
+ QUOTAOPSNAME, qfextension[type] );
+ if (stat(buf, &sb) != 0) {
+ /* There appears to be no mount option file */
+ return(0);
+ }
+
+
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#else
+int hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp, *index(), *strtok();
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strlcpy(buf, fs->fs_mntops, sizeof(buf));
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = index(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp) {
+ *qfnamep = cp;
+ return (1);
+ }
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#endif /* __APPLE__ */
+
+
+/*
+ * Verify file system is mounted and not readonly.
+ */
+int readonly(fs)
+ register struct fstab *fs;
+{
+ struct statfs fsbuf;
+
+ if (statfs(fs->fs_file, &fsbuf) < 0 ||
+ strcmp(fsbuf.f_mntonname, fs->fs_file) ||
+ strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
+ printf("%s: not mounted\n", fs->fs_file);
+ return (1);
+ }
+ if (fsbuf.f_flags & MNT_RDONLY) {
+ printf("%s: mounted read-only\n", fs->fs_file);
+ return (1);
+ }
+ return (0);
+}
diff --git a/diskdev_cmds/repquota.tproj/repquota.8 b/diskdev_cmds/repquota.tproj/repquota.8
new file mode 100644
index 0000000..9b8a7b9
--- /dev/null
+++ b/diskdev_cmds/repquota.tproj/repquota.8
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1983, 1990, 1991, 1993, 2002
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)repquota.8 8.1 (Berkeley) 6/2/93
+.\"
+.Dd March 28, 2002
+.Dt REPQUOTA 8
+.Os BSD 4.2
+.Sh NAME
+.Nm repquota
+.Nd summarize quotas for a file system
+.Sh SYNOPSIS
+.Nm repquota
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Ar filesystem Ar ...
+.Nm repquota
+.Op Fl g
+.Op Fl u
+.Op Fl v
+.Fl a
+.Sh DESCRIPTION
+.Nm Repquota
+prints a summary of the disk usage and quotas for the
+specified file systems.
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+Print the quotas of all the filesystems configured with
+a quota mount option file at its root.
+.It Fl g
+Print only group quotas (the default is to print both
+group and user quotas if they exist).
+.It Fl u
+Print only user quotas (the default is to print both
+group and user quotas if they exist).
+.It Fl v
+Print a header line before printing each filesystem quotas.
+.El
+.Pp
+For each user or group, the current
+number of files and amount of space (in kilobytes) is
+printed, along with any quotas created with
+.Xr edquota 8 .
+.Pp
+Only members of the operator group or the super-user may
+use this command.
+.Sh FILES
+Each of the following quota files is located at the root of the
+mounted filesystem. The mount option files are empty files
+whose existence indicates that quotas are to be enabled
+for that filesystem.
+.Pp
+.Bl -tag -width .quota.ops.group -compact
+.It Pa .quota.user
+data file containing user quotas
+.It Pa .quota.group
+data file containing group quotas
+.It Pa .quota.ops.user
+mount option file used to enable user quotas
+.It Pa .quota.ops.group
+mount option file used to enable group quotas
+.El
+.Sh SEE ALSO
+.Xr quota 1 ,
+.Xr quotactl 2 ,
+.Xr edquota 8 ,
+.Xr quotacheck 8 ,
+.Xr quotaon 8
+.Sh DIAGNOSTICS
+Various messages about inaccessible files; self-explanatory.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/diskdev_cmds/repquota.tproj/repquota.c b/diskdev_cmds/repquota.tproj/repquota.c
new file mode 100644
index 0000000..87c1d8c
--- /dev/null
+++ b/diskdev_cmds/repquota.tproj/repquota.c
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#ifndef lint
+__unused static char copyright[] =
+"@(#) Copyright (c) 1980, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+__unused static char sccsid[] = "@(#)repquota.c 8.2 (Berkeley) 11/22/94";
+#endif /* not lint */
+
+/*
+ * Quota report
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#include <sys/quota.h>
+
+#ifdef __APPLE__
+#include <sys/mount.h>
+#endif /* __APPLE__ */
+#include <errno.h>
+#include <fstab.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __APPLE__
+#include <libkern/OSByteOrder.h>
+#endif /* __APPLE__ */
+
+char *qfname = QUOTAFILENAME;
+char *qfextension[] = INITQFNAMES;
+#ifdef __APPLE__
+u_int32_t quotamagic[MAXQUOTAS] = INITQMAGICS;
+#endif /* __APPLE__ */
+
+#ifndef __APPLE__
+struct fileusage {
+ struct fileusage *fu_next;
+ struct dqblk fu_dqblk;
+ u_long fu_id;
+ char fu_name[1];
+ /* actually bigger */
+};
+struct fileusage * addid(u_long, int);
+struct fileusage * lookup(u_long, int);
+
+#define FUHASH 1024 /* must be power of two */
+struct fileusage *fuhead[MAXQUOTAS][FUHASH];
+u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
+#endif /* NOT __APPLE__ */
+
+int vflag; /* verbose */
+int aflag; /* all file systems */
+
+int hasquota(struct statfs *, int, char **);
+int repquota(struct statfs *, int, char *);
+int oneof(char *, char **, int);
+void usage(void);
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+#ifndef __APPLE__
+ register struct fstab *fs;
+ register struct passwd *pw;
+ register struct group *gr;
+#endif /* __APPLE__ */
+ int gflag = 0, uflag = 0, errs = 0;
+ long i, argnum, done = 0;
+#ifdef __APPLE__
+ int nfst;
+ struct statfs *fst;
+#endif /* __APPLE__ */
+ char ch, *qfnp;
+
+ while ((ch = getopt(argc, argv, "aguv")) != EOF) {
+ switch(ch) {
+ case 'a':
+ aflag++;
+ break;
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc == 0 && !aflag)
+ usage();
+ if (!gflag && !uflag) {
+ if (aflag)
+ gflag++;
+ uflag++;
+ }
+
+#ifdef __APPLE__
+ nfst = getmntinfo(&fst, MNT_WAIT);
+ if (nfst==0) {
+ fprintf(stderr, "repquota: no filesystems mounted");
+ return(1);
+ }
+
+ for (i=0; i<nfst; i++) {
+ if(strcmp(fst[i].f_fstypename, "hfs")) {
+ continue;
+ }
+ if (aflag) {
+ if (gflag && hasquota(&fst[i], GRPQUOTA, &qfnp))
+ errs += repquota(&fst[i], GRPQUOTA, qfnp);
+ if (uflag && hasquota(&fst[i], USRQUOTA, &qfnp))
+ errs += repquota(&fst[i], USRQUOTA, qfnp);
+ continue;
+ }
+ if ((argnum = oneof(fst[i].f_mntonname, argv, argc)) >= 0 ||
+ (argnum = oneof(fst[i].f_mntfromname, argv, argc)) >= 0) {
+ done |= 1 << argnum;
+ if (gflag && hasquota(&fst[i], GRPQUOTA, &qfnp))
+ errs += repquota(&fst[i], GRPQUOTA, qfnp);
+ if (uflag && hasquota(&fst[i], USRQUOTA, &qfnp))
+ errs += repquota(&fst[i], USRQUOTA, qfnp);
+ }
+ }
+#else
+ if (gflag) {
+ setgrent();
+ while ((gr = getgrent()) != 0)
+ (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
+ endgrent();
+ }
+ if (uflag) {
+ setpwent();
+ while ((pw = getpwent()) != 0)
+ (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
+ endpwent();
+ }
+
+ setfsent();
+ while ((fs = getfsent()) != NULL) {
+ if (strcmp(fs->fs_vfstype, "ufs"))
+ continue;
+ if (aflag) {
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += repquota(fs, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += repquota(fs, USRQUOTA, qfnp);
+ continue;
+ }
+ if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
+ (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
+ done |= 1 << argnum;
+ if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
+ errs += repquota(fs, GRPQUOTA, qfnp);
+ if (uflag && hasquota(fs, USRQUOTA, &qfnp))
+ errs += repquota(fs, USRQUOTA, qfnp);
+ }
+ }
+ endfsent();
+#endif /* __APPLE */
+ for (i = 0; i < argc; i++)
+ if ((done & (1 << i)) == 0)
+ fprintf(stderr, "%s not found in fstab\n", argv[i]);
+ exit(errs);
+}
+
+void
+usage()
+{
+ fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
+ "repquota [-v] [-g] [-u] -a",
+ "repquota [-v] [-g] [-u] filesys ...");
+ exit(1);
+}
+
+#ifdef __APPLE__
+int
+repquota(fst, type, qfpathname)
+ struct statfs *fst;
+ int type;
+ char *qfpathname;
+{
+ FILE *qf;
+ uid_t id;
+ struct dqblk dqbuf;
+ char *timeprt();
+ char *name;
+ struct dqfilehdr dqhdr;
+ static int warned = 0;
+ static int multiple = 0;
+ extern int errno;
+ int i;
+ struct passwd *pw;
+ struct group *gr;
+ int maxentries;
+ u_int64_t bsoftlimit;
+ u_int32_t isoftlimit;
+ u_int64_t curbytes;
+ u_int32_t curinodes;
+
+
+ if (quotactl(fst->f_mntonname, QCMD(Q_SYNC, type), 0, 0) < 0 &&
+ errno == ENOTSUP && !warned && vflag) {
+ warned++;
+ fprintf(stdout,
+ "*** Warning: Quotas are not compiled into this kernel\n");
+ }
+ if (multiple++)
+ printf("\n");
+ if (vflag)
+ fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
+ qfextension[type], fst->f_mntonname, fst->f_mntfromname);
+ if ((qf = fopen(qfpathname, "r")) == NULL) {
+ perror(qfpathname);
+ return (1);
+ }
+
+ /* Read in the quota file header. */
+ if (fread((char *)&dqhdr, sizeof(struct dqfilehdr), 1, qf) > 0) {
+ /* Check for non big endian file. */
+ if (OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type] &&
+ OSSwapInt32(dqhdr.dqh_magic) == quotamagic[type]) {
+ (void) fprintf(stderr,
+ "*** Error: %s: not in big endian byte order\n", qfpathname);
+ (void) fclose(qf);
+ return (1);
+ }
+ /* Sanity check the quota file header. */
+ if ((OSSwapBigToHostInt32(dqhdr.dqh_magic) != quotamagic[type]) ||
+ (OSSwapBigToHostInt32(dqhdr.dqh_version) > QF_VERSION) ||
+ (!powerof2(OSSwapBigToHostInt32(dqhdr.dqh_maxentries)))) {
+ (void) fprintf(stderr,
+ "repquota: %s: not a valid quota file\n", qfpathname);
+ (void) fclose(qf);
+ return (1);
+ }
+ }
+
+ printf(" 1K Block limits File limits\n");
+ printf("User used soft hard grace used soft hard grace\n");
+
+ maxentries = OSSwapBigToHostInt32(dqhdr.dqh_maxentries);
+
+ /* Read the entries in the quota file. */
+ for (i = 0; i < maxentries; i++) {
+ if (fread(&dqbuf, sizeof(struct dqblk), 1, qf) == 0 && feof(qf))
+ break;
+ id = OSSwapBigToHostInt32(dqbuf.dqb_id);
+ if (id == 0)
+ continue;
+ if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curbytes == 0LL)
+ continue;
+ name = NULL;
+ switch (type) {
+ case USRQUOTA:
+ if ((pw = getpwuid(id)) != 0)
+ name = pw->pw_name;
+ break;
+ case GRPQUOTA:
+ if ((gr = getgrgid(id)) != 0)
+ name = gr->gr_name;
+ break;
+ }
+ if (name)
+ printf("%-10s", name);
+ else
+ printf("%-10u", (unsigned int)id);
+
+ bsoftlimit = OSSwapBigToHostInt64( dqbuf.dqb_bsoftlimit );
+ isoftlimit = OSSwapBigToHostInt32( dqbuf.dqb_isoftlimit );
+ curbytes = OSSwapBigToHostInt64( dqbuf.dqb_curbytes );
+ curinodes = OSSwapBigToHostInt32( dqbuf.dqb_curinodes );
+
+ printf("%c%c%12qd%12qd%12qd%7s",
+ bsoftlimit &&
+ curbytes >=
+ bsoftlimit ? '+' : '-',
+ isoftlimit &&
+ curinodes >=
+ isoftlimit ? '+' : '-',
+ curbytes / 1024,
+ bsoftlimit / 1024,
+ OSSwapBigToHostInt64( dqbuf.dqb_bhardlimit ) / 1024,
+ bsoftlimit &&
+ curbytes >=
+ bsoftlimit ?
+ timeprt(OSSwapBigToHostInt32(dqbuf.dqb_btime)) : "");
+ printf(" %6d%6d%6d%7s\n",
+ curinodes,
+ isoftlimit,
+ OSSwapBigToHostInt32( dqbuf.dqb_ihardlimit ),
+ isoftlimit &&
+ curinodes >=
+ isoftlimit ?
+ timeprt(OSSwapBigToHostInt32(dqbuf.dqb_itime)) : "");
+ }
+ fclose(qf);
+
+ return (0);
+}
+#else
+repquota(fs, type, qfpathname)
+ register struct fstab *fs;
+ int type;
+ char *qfpathname;
+{
+ register struct fileusage *fup;
+ FILE *qf;
+ u_long id;
+ struct dqblk dqbuf;
+ char *timeprt();
+ static struct dqblk zerodqblk;
+ static int warned = 0;
+ static int multiple = 0;
+ extern int errno;
+
+ if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 &&
+ errno == ENOTSUP && !warned && vflag) {
+ warned++;
+ fprintf(stdout,
+ "*** Warning: Quotas are not compiled into this kernel\n");
+ }
+ if (multiple++)
+ printf("\n");
+ if (vflag)
+ fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
+ qfextension[type], fs->fs_file, fs->fs_spec);
+ if ((qf = fopen(qfpathname, "r")) == NULL) {
+ perror(qfpathname);
+ return (1);
+ }
+ for (id = 0; ; id++) {
+ fread(&dqbuf, sizeof(struct dqblk), 1, qf);
+ if (feof(qf))
+ break;
+ if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)
+ continue;
+ if ((fup = lookup(id, type)) == 0)
+ fup = addid(id, type, (char *)0);
+ fup->fu_dqblk = dqbuf;
+ }
+ fclose(qf);
+ printf(" Block limits File limits\n");
+ printf("User used soft hard grace used soft hard grace\n");
+
+ for (id = 0; id <= highid[type]; id++) {
+ fup = lookup(id, type);
+ if (fup == 0)
+ continue;
+ if (fup->fu_dqblk.dqb_curinodes == 0 &&
+ fup->fu_dqblk.dqb_curblocks == 0)
+ continue;
+ printf("%-10s", fup->fu_name);
+ printf("%c%c%8d%8d%8d%7s",
+ fup->fu_dqblk.dqb_bsoftlimit &&
+ fup->fu_dqblk.dqb_curblocks >=
+ fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-',
+ fup->fu_dqblk.dqb_isoftlimit &&
+ fup->fu_dqblk.dqb_curinodes >=
+ fup->fu_dqblk.dqb_isoftlimit ? '+' : '-',
+ dbtob(fup->fu_dqblk.dqb_curblocks) / 1024,
+ dbtob(fup->fu_dqblk.dqb_bsoftlimit) / 1024,
+ dbtob(fup->fu_dqblk.dqb_bhardlimit) / 1024,
+ fup->fu_dqblk.dqb_bsoftlimit &&
+ fup->fu_dqblk.dqb_curblocks >=
+ fup->fu_dqblk.dqb_bsoftlimit ?
+ timeprt(fup->fu_dqblk.dqb_btime) : "");
+ printf(" %6d%6d%6d%7s\n",
+ fup->fu_dqblk.dqb_curinodes,
+ fup->fu_dqblk.dqb_isoftlimit,
+ fup->fu_dqblk.dqb_ihardlimit,
+ fup->fu_dqblk.dqb_isoftlimit &&
+ fup->fu_dqblk.dqb_curinodes >=
+ fup->fu_dqblk.dqb_isoftlimit ?
+ timeprt(fup->fu_dqblk.dqb_itime) : "");
+ fup->fu_dqblk = zerodqblk;
+ }
+ return (0);
+}
+#endif /* __APPLE */
+
+/*
+ * Check to see if target appears in list of size cnt.
+ */
+int
+oneof(target, list, cnt)
+ register char *target, **list;
+ int cnt;
+{
+ register int i;
+
+ for (i = 0; i < cnt; i++)
+ if (strcmp(target, list[i]) == 0)
+ return (i);
+ return (-1);
+}
+
+/*
+ * Check to see if a particular quota is to be enabled.
+ */
+#ifdef __APPLE__
+int
+hasquota(fst, type, qfnamep)
+ register struct statfs *fst;
+ int type;
+ char **qfnamep;
+{
+ struct stat sb;
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizeof(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+
+ /*
+ We only support the default path to the
+ on disk quota files.
+ */
+
+ (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname,
+ QUOTAOPSNAME, qfextension[type] );
+ if (stat(buf, &sb) != 0) {
+ /* There appears to be no mount option file */
+ return(0);
+ }
+
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fst->f_mntonname, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#else
+hasquota(fs, type, qfnamep)
+ register struct fstab *fs;
+ int type;
+ char **qfnamep;
+{
+ register char *opt;
+ char *cp, *index(), *strtok();
+ static char initname, usrname[100], grpname[100];
+ static char buf[BUFSIZ];
+
+ if (!initname) {
+ snprintf(usrname, sizoef(usrname), "%s%s", qfextension[USRQUOTA], qfname);
+ snprintf(grpname, sizeof(grpname), "%s%s", qfextension[GRPQUOTA], qfname);
+ initname = 1;
+ }
+ strlcpy(buf, fs->fs_mntops, sizeof(buf));
+ for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
+ if (cp = index(opt, '='))
+ *cp++ = '\0';
+ if (type == USRQUOTA && strcmp(opt, usrname) == 0)
+ break;
+ if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
+ break;
+ }
+ if (!opt)
+ return (0);
+ if (cp) {
+ *qfnamep = cp;
+ return (1);
+ }
+ (void) snprintf(buf, sizeof(buf), "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
+ *qfnamep = buf;
+ return (1);
+}
+#endif /* __APPLE__ */
+
+
+#ifndef __APPLE__
+
+/*
+ * Routines to manage the file usage table.
+ *
+ * Lookup an id of a specific type.
+ */
+struct fileusage *
+lookup(id, type)
+ u_long id;
+ int type;
+{
+ register struct fileusage *fup;
+
+ for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next)
+ if (fup->fu_id == id)
+ return (fup);
+ return ((struct fileusage *)0);
+}
+
+/*
+ * Add a new file usage id if it does not already exist.
+ */
+struct fileusage *
+addid(id, type, name)
+ u_long id;
+ int type;
+ char *name;
+{
+ struct fileusage *fup, **fhp;
+ int len;
+ extern char *calloc();
+
+ if (fup = lookup(id, type))
+ return (fup);
+ if (name)
+ len = strlen(name);
+ else
+ len = 10;
+ if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) {
+ fprintf(stderr, "out of memory for fileusage structures\n");
+ exit(1);
+ }
+ fhp = &fuhead[type][id & (FUHASH - 1)];
+ fup->fu_next = *fhp;
+ *fhp = fup;
+ fup->fu_id = id;
+ if (id > highid[type])
+ highid[type] = id;
+ if (name) {
+ bcopy(name, fup->fu_name, len + 1);
+ } else {
+ snprintf(fup->fu_name, len + 1, "%u", id);
+ }
+ return (fup);
+}
+#endif /* !__APPLE__ */
+
+/*
+ * Calculate the grace period and return a printable string for it.
+ */
+char *
+timeprt(seconds)
+ time_t seconds;
+{
+ time_t hours, minutes;
+ static char buf[20];
+ static time_t now;
+
+ if (now == 0)
+ time(&now);
+ if (now > seconds)
+ return ("none");
+ seconds -= now;
+ minutes = (seconds + 30) / 60;
+ hours = (minutes + 30) / 60;
+ if (hours >= 36) {
+ snprintf(buf, sizeof(buf), "%lddays", (hours + 12) / 24);
+ return (buf);
+ }
+ if (minutes >= 60) {
+ snprintf(buf, sizeof(buf), "%2ld:%ld", minutes / 60, minutes % 60);
+ return (buf);
+ }
+ snprintf(buf, sizeof(buf), "%2ld", minutes);
+ return (buf);
+}
diff --git a/diskdev_cmds/setclass.tproj/setclass.8 b/diskdev_cmds/setclass.tproj/setclass.8
new file mode 100644
index 0000000..90d0c80
--- /dev/null
+++ b/diskdev_cmds/setclass.tproj/setclass.8
@@ -0,0 +1,46 @@
+.\" Copyright (c) 2010-2012 Apple Inc. All rights reserved.
+.\"
+.\" The contents of this file constitute Original Code as defined in and
+.\" are subject to the Apple Public Source License Version 1.1 (the
+.\" "License"). You may not use this file except in compliance with the
+.\" License. Please obtain a copy of the License at
+.\" http://www.apple.com/publicsource and read it before using this file.
+.\"
+.\" This Original Code and all software distributed under the License are
+.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+.\" License for the specific language governing rights and limitations
+.\" under the License.
+.\"
+.\" @(#)setclass.8
+.Dd June 20, 2012
+.Dt SETCLASS 8
+.Os "Mac OS X"
+.Sh NAME
+.Nm setclass
+.Nd content protection utility
+.Sh SYNOPSIS
+.Nm setclass
+.Ar file
+.Op A-E
+.Sh DESCRIPTION
+.Pp
+The
+.Nm
+utility sets and gets the content protection class of a given file.
+.Pp
+If a class from A to E is specified,
+.Nm
+will attempt to set
+.Ar file
+to that class.
+If no class is given,
+.Nm
+will report the current protection class of
+.Ar file.
+.Pp
+Note that the ability to change the content protection class of a file is restricted by the
+runtime status of the device in question. If the device is locked with a PIN code, then
+you may not be able to modify the protection class, even as root.
diff --git a/diskdev_cmds/setclass.tproj/setclass.c b/diskdev_cmds/setclass.tproj/setclass.c
new file mode 100644
index 0000000..306547b
--- /dev/null
+++ b/diskdev_cmds/setclass.tproj/setclass.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2010-2020 Apple Inc. All rights reserved.
+ */
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/attr.h>
+
+/* from sys/cprotect.h */
+
+#define PROTECTION_CLASS_A 1
+#define PROTECTION_CLASS_B 2
+#define PROTECTION_CLASS_C 3
+#define PROTECTION_CLASS_D 4
+#define PROTECTION_CLASS_E 5
+#define PROTECTION_CLASS_F 6
+
+void
+usage(void)
+{
+ printf("usage: setclass <path> [A-F]\n");
+ printf("\tsets <path> to a protection class from A to F.\n");
+ printf("\tIf no class is specified, reports the current class for <path>.\n");
+ exit(0);
+}
+
+int
+chartoclass(char c)
+{
+ switch (c) {
+ /* directory 'unset' operation */
+ case '0':
+ return 0;
+ case 'A':
+ case 'a':
+ return PROTECTION_CLASS_A;
+ case 'B':
+ case 'b':
+ return PROTECTION_CLASS_B;
+ case 'C':
+ case 'c':
+ return PROTECTION_CLASS_C;
+ case 'D':
+ case 'd':
+ return PROTECTION_CLASS_D;
+ case 'E':
+ case 'e':
+ return PROTECTION_CLASS_E;
+ case 'F':
+ case 'f':
+ return PROTECTION_CLASS_F;
+ default:
+ usage();
+ exit(0);
+ }
+ return 0;
+}
+
+char
+classtochar(int class)
+{
+ if (class < 0) {
+ /* negative classes are invalid */
+ return -1;
+ }
+
+ /* otherwise, it must be >= 0... */
+ if (class == 0) {
+ /* Directories are allowed to be "unset" */
+ return 0;
+ }
+ return 'A' + (class - 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int error = 0, class = 0, do_set = 0;
+ static struct attrlist req = {
+ .bitmapcount = ATTR_BIT_MAP_COUNT,
+ .commonattr = ATTR_CMN_DATA_PROTECT_FLAGS
+ };
+
+ if ((argc < 2) || (argc > 3))
+ usage();
+
+ if (argv[2]) {
+ do_set = 1;
+ class = chartoclass(*argv[2]);
+ }
+
+ /*
+ * setclass and getclass for `argv[1]` using setattrlist(2) and
+ * getattrlist(2) respectively.
+ */
+ if (do_set) {
+ struct {
+ uint32_t prot_class;
+ } __attribute__((packed, aligned(4))) attrs = {
+ .prot_class = class
+ };
+
+ error = setattrlist(argv[1], (void *)&req, &attrs, sizeof(attrs),
+ FSOPT_NOFOLLOW);
+ if (error) {
+ char new_class = classtochar(class);
+ if (new_class == 0) {
+ warn("could not set protection class of %s to (directory none)",
+ argv[1]);
+ }
+ else {
+ warn("could not set protection class of %s to %c", argv[1],
+ new_class);
+ }
+ }
+ }
+ else {
+ req.commonattr |= ATTR_CMN_RETURNED_ATTRS;
+
+ struct {
+ uint32_t len;
+ attribute_set_t returned;
+ uint32_t prot_class;
+ } __attribute__((packed, aligned(4))) attrs;
+
+ error = getattrlist(argv[1], (void *)&req, &attrs, sizeof(attrs),
+ FSOPT_NOFOLLOW);
+ if (error == -1 || attrs.len != sizeof(attrs) ||
+ attrs.returned.commonattr != req.commonattr) {
+ if (error == -1) {
+ error = errno;
+ }
+ else {
+ error = EINVAL;
+ }
+ err(error, "could not get protection class");
+ }
+ else {
+ class = attrs.prot_class;
+ char new_class = classtochar(class);
+ if (new_class == 0) {
+ printf("%s is in protection class (directory none) \n", argv[1]);
+ }
+ else {
+ printf("%s is in protection class %c\n", argv[1], new_class);
+ }
+ }
+ }
+
+ return error;
+}
diff --git a/diskdev_cmds/umount.tproj/umount.8 b/diskdev_cmds/umount.tproj/umount.8
new file mode 100644
index 0000000..b914134
--- /dev/null
+++ b/diskdev_cmds/umount.tproj/umount.8
@@ -0,0 +1,133 @@
+.\" Copyright (c) 1980, 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
+.\"
+.Dd May 8, 1995
+.Dt UMOUNT 8
+.Os BSD 4
+.Sh NAME
+.Nm umount
+.Nd unmount filesystems
+.Sh SYNOPSIS
+.Nm umount
+.Op Fl fv
+.Ar special | node
+.Nm umount
+.Fl a | A
+.Op Fl fv
+.Op Fl h Ar host
+.Op Fl t Ar type
+.Sh DESCRIPTION
+The
+.Nm umount
+command
+calls the
+.Xr unmount 2
+system call to remove a
+.Ar "special device"
+or the remote node (rhost:path) from the filesystem tree at the point
+.Ar node .
+If either
+.Ar special
+or
+.Ar node
+are not provided, the appropriate information is taken from the
+list of filesystems provided by
+.Xr getfsent 3 .
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+All the filesystems described via
+.Xr getfsent 3
+are unmounted.
+.It Fl A
+All the currently mounted filesystems except
+the root are unmounted.
+.It Fl f
+The filesystem is forcibly unmounted.
+Active special devices continue to work,
+but all other files return errors if further accesses are attempted.
+The root filesystem cannot be forcibly unmounted.
+.It Fl h Ar host
+Only filesystems mounted from the specified host will be
+unmounted.
+This option implies the
+.Fl A
+option and, unless otherwise specified with the
+.Fl t
+option, will only unmount NFS filesystems.
+.It Fl t Ar type
+Is used to indicate the actions should only be taken on
+filesystems of the specified type.
+More than one type may be specified in a comma separated list.
+The list of filesystem types can be prefixed with
+.Dq no
+to specify the filesystem types for which action should
+.Em not
+be taken.
+For example, the
+.Nm umount
+command:
+.Bd -literal -offset indent
+umount -A -t nfs,hfs
+.Ed
+.Pp
+umounts all currently-mounted filesystems of the type
+.Tn NFS
+and
+.Tn HFS .
+(The
+.Fl a
+option only unmounts entries in the
+.Pa /etc/fstab
+list.)
+.It Fl v
+Verbose, additional information is printed out as each filesystem
+is unmounted.
+.El
+.Sh NOTES
+Due to the complex and interwoven nature of Mac OS X,
+.Nm umount
+may fail often. It is recommended that
+.Xr diskutil 1
+(as in, ``diskutil unmount /mnt'') be used instead.
+.Sh SEE ALSO
+.Xr unmount 2 ,
+.Xr getfsent 3 ,
+.Xr mount 8 ,
+.Xr diskutil 1
+.Sh HISTORY
+A
+.Nm umount
+command appeared in
+.At v6 .
diff --git a/diskdev_cmds/umount.tproj/umount.c b/diskdev_cmds/umount.tproj/umount.c
new file mode 100644
index 0000000..26e9ba4
--- /dev/null
+++ b/diskdev_cmds/umount.tproj/umount.c
@@ -0,0 +1,655 @@
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+/*
+ * Copyright (c) 1999-2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1980, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <System/sys/fsctl.h>
+
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <fstab.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <pthread.h>
+
+#include "../edt_fstab/edt_fstab.h"
+
+struct syncarg {
+ const char *mntname;
+ int wakeup_flag;
+ pthread_cond_t *wakeup_cond;
+ pthread_mutex_t *wakeup_lock;
+};
+
+typedef enum { MNTON, MNTFROM } mntwhat;
+
+int fake, fflag, vflag;
+char *nfshost;
+
+int checkvfsname(const char *, char **);
+char *getmntname(const char *, mntwhat, char **);
+int getmntfsid(const char *, fsid_t *);
+int sysctl_fsid(int, fsid_t *, void *, size_t *, void *, size_t);
+int unmount_by_fsid(const char *mntpt, int flag);
+char **makevfslist(char *);
+int selected(int);
+int namematch(struct hostent *);
+int umountall(char **);
+int umountfs(char *, char **);
+void usage(void);
+
+static void*
+syncit(void *vap) {
+ int rv;
+ pthread_mutex_t *lock;
+ int full_sync = FSCTL_SYNC_WAIT;
+ struct syncarg *args = vap;
+
+ rv = fsctl(args->mntname, FSIOC_SYNC_VOLUME, &full_sync, 0);
+ if (rv == -1) {
+#ifdef DEBUG
+ warn("fsctl %s", args->mntname);
+#endif
+ }
+
+ lock = args->wakeup_lock;
+ (void)pthread_mutex_lock(lock);
+ args->wakeup_flag = 1;
+ pthread_cond_signal(args->wakeup_cond);
+ (void)pthread_mutex_unlock(lock);
+
+ return NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int all, ch, errs, mnts;
+ char **typelist = NULL;
+ struct statfs *mntbuf;
+
+ /*
+ * We used to call sync(2) here, but this should be unneccessary
+ * given that a sync occurs at a more proper level (VFS_SYNC()
+ * in dounmount() in the non-forced unmount case).
+ *
+ * We add the sync() back in for the -f case below to cover the
+ * situation where the filesystem was mounted RW and force
+ * unmounted when it really didn't have to be.
+ *
+ * See 5328558 for some context.
+ */
+
+ all = 0;
+ while ((ch = getopt(argc, argv, "AaFfh:t:v")) != EOF)
+ switch (ch) {
+ case 'A':
+ all = 2;
+ break;
+ case 'a':
+ all = 1;
+ break;
+ case 'F':
+ fake = 1;
+ break;
+ case 'f':
+ fflag = MNT_FORCE;
+ break;
+ case 'h': /* -h implies -A. */
+ all = 2;
+ nfshost = optarg;
+ break;
+ case 't':
+ if (typelist != NULL)
+ errx(1, "only one -t option may be specified.");
+ typelist = makevfslist(optarg);
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((argc == 0 && !all) || (argc != 0 && all))
+ usage();
+
+ /* -h implies "-t nfs" if no -t flag. */
+ if ((nfshost != NULL) && (typelist == NULL))
+ typelist = makevfslist("nfs");
+
+ if (fflag & MNT_FORCE) {
+ /*
+ * If we really mean business, we don't want to get hung up on
+ * any remote file systems. So, we set the "noremotehang" flag.
+ */
+ pid_t pid;
+ pid = getpid();
+ errs = sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &pid, sizeof(pid));
+ if ((errs != 0) && vflag)
+ warn("sysctl vfs.generic.noremotehang");
+ }
+
+ errs = EXIT_SUCCESS;
+ switch (all) {
+ case 2:
+ if ((mnts = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
+ warn("getmntinfo");
+ errs = 1;
+ break;
+ }
+ for (errs = 0, mnts--; mnts > 0; mnts--) {
+ if (checkvfsname(mntbuf[mnts].f_fstypename, typelist))
+ continue;
+ if (umountfs(mntbuf[mnts].f_mntonname, typelist) != 0)
+ errs = 1;
+ }
+ break;
+ case 1:
+ if ((setfsent() == 0)) {
+ fprintf(stderr, "Can't get filesystem checklist: %s\n", strerror(errno));
+ exit(1);
+ }
+ errs = umountall(typelist);
+ break;
+ case 0:
+ for (errs = 0; *argv != NULL; ++argv)
+ if (umountfs(*argv, typelist) != 0)
+ errs = 1;
+ break;
+ }
+ exit(errs);
+}
+
+int
+umountall(char **typelist)
+{
+ struct fstab *fs;
+ int rval;
+ size_t cp_len;
+ char *cp;
+
+ while ((fs = getfsent()) != NULL) {
+ /* Ignore the root. */
+ if (strcmp(fs->fs_file, "/") == 0)
+ continue;
+ /*
+ * !!!
+ * Historic practice: ignore unknown FSTAB_* fields.
+ */
+ if (strcmp(fs->fs_type, FSTAB_RW) &&
+ strcmp(fs->fs_type, FSTAB_RO) &&
+ strcmp(fs->fs_type, FSTAB_RQ))
+ continue;
+#if 0
+ /* If an unknown file system type, complain. */
+ if (getvfsbyname(fs->fs_vfstype, &vfc) < 0) {
+ warnx("%s: unknown mount type `%s'", fs->fs_spec, fs->fs_vfstype);
+ continue;
+ }
+ if (checkvfsname(fs->fs_vfstype, typelist))
+ continue;
+#endif
+
+ /*
+ * We want to unmount the file systems in the reverse order
+ * that they were mounted. So, we save off the file name
+ * in some allocated memory, and then call recursively.
+ */
+ cp_len = (size_t)strlen(fs->fs_file) + 1;
+ if ((cp = malloc(cp_len)) == NULL)
+ err(1, NULL);
+ (void)strlcpy(cp, fs->fs_file, cp_len);
+ rval = umountall(typelist);
+ rval = umountfs(cp, typelist) || rval;
+ free(cp);
+ return (rval);
+ }
+ return (0);
+}
+
+int
+umountfs(char *name, char **typelist)
+{
+ struct hostent *hp, *hp6;
+ struct stat sb;
+ int isftpfs, errnum;
+ char *type, *delimp, *hostname, *mntpt, rname[MAXPATHLEN], *tname;
+ char *pname = name; /* save the name parameter */
+
+ /*
+ * First directly check the
+ * current mount list for a match. If we find it,
+ * we skip the realpath()/stat() below.
+ */
+ tname = name;
+ /* check if name is a non-device "mount from" name */
+ if ((mntpt = getmntname(tname, MNTON, &type)) == NULL) {
+ /* or if name is a mounted-on directory */
+ mntpt = tname;
+ tname = getmntname(mntpt, MNTFROM, &type);
+ }
+ if (mntpt && tname) {
+ if (fflag & MNT_FORCE) {
+ /*
+ * The bulk of this block is to try to do a sync on the filesystem
+ * being unmounted. We want to do this in another thread, so we
+ * can avoid blocking for a hardware or network reason. We will
+ * wait 10 seconds for the sync to finish; after that, we just
+ * ignore it and go ahead with the unmounting.
+ *
+ * We only want to do this in the event of a forced unmount.
+ */
+ int rv;
+ pthread_t tid;
+ pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+ pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+ struct syncarg args;
+ struct timespec timeout;
+
+ /* we found a match */
+ name = tname;
+
+ args.mntname = mntpt;
+ args.wakeup_flag = 0;
+ args.wakeup_cond = &cond;
+ args.wakeup_lock = &lock;
+
+ timeout.tv_sec = time(NULL) + 10; /* Wait 10 seconds */
+ timeout.tv_nsec = 0;
+
+ rv = pthread_create(&tid, NULL, &syncit, &args);
+ if (rv == 0 && pthread_mutex_lock(&lock) == 0) {
+ while (args.wakeup_flag == 0 && rv == 0)
+ rv = pthread_cond_timedwait(&cond, &lock, &timeout);
+
+ /* If this fails, not much we can do at this point... */
+ (void)pthread_mutex_unlock(&lock);
+ if (rv != 0) {
+ errno = rv;
+ warn("pthread_cond_timeout failed; continuing with unmount");
+ }
+ }
+ }
+ goto got_mount_point;
+ }
+
+ /*
+ * Note: in the face of path resolution errors (realpath/stat),
+ * we just try using the name passed in as is.
+ */
+ /* even if path resolution succeeds, but can't find mountpoint
+ * with the resolved path, we still want to try using the name
+ * as passed in.
+ */
+
+ if (realpath(name, rname) == NULL) {
+ if (vflag)
+ warn("realpath(%s)", rname);
+ } else {
+ name = rname;
+ }
+
+ /* we could just try MNTON and MNTFROM on name and again (if
+ * name is not the passed in param) MNTON and MNTFROM on
+ * pname.
+ *
+ * but we stat(name) here to avoid umounting the wrong thing
+ * if the mount table has an entry with the MNTFROM that is
+ * the same as the MNTON in another entry.
+ */
+
+ if (stat(name, &sb) < 0) {
+ if (vflag)
+ warn("stat(%s)", name);
+ /* maybe name is a non-device "mount from" name? */
+ if ((mntpt = getmntname(name, MNTON, &type)))
+ goto got_mount_point;
+ mntpt = name;
+ /* or name is a directory we simply can't reach? */
+ if ((name = getmntname(mntpt, MNTFROM, &type)))
+ goto got_mount_point;
+ } else if (S_ISBLK(sb.st_mode)) {
+ if ((mntpt = getmntname(name, MNTON, &type)))
+ goto got_mount_point;
+ } else if (S_ISDIR(sb.st_mode)) {
+ mntpt = name;
+ if ((name = getmntname(mntpt, MNTFROM, &type)))
+ goto got_mount_point;
+ } else {
+ warnx("%s: not a directory or special device", name);
+ }
+
+ /* haven't found mountpoint.
+ *
+ * if we were not using the name as passed in, then try using it.
+ */
+ if ((NULL == name) || (strcmp(name, pname) != 0)) {
+ name = pname;
+
+ if ((mntpt = getmntname(name, MNTON, &type)))
+ goto got_mount_point;
+ mntpt = name;
+ if ((name = getmntname(mntpt, MNTFROM, &type)))
+ goto got_mount_point;
+ }
+
+ warnx("%s: not currently mounted", pname);
+ return (1);
+
+got_mount_point:
+
+ if (checkvfsname(type, typelist))
+ return (1);
+
+ if (!strncmp("ftp://", name, 6))
+ isftpfs = 1;
+ else
+ isftpfs = 0;
+
+ hp = hp6 = NULL;
+ delimp = NULL;
+ if (nfshost && !strcmp(type, "nfs") && !isftpfs) {
+ /*
+ * Parse the NFS host out of the name.
+ *
+ * If it starts with '[' then skip IPv6 literal characters
+ * until we find ']'. If we find other characters (or the
+ * closing ']' isn't followed by a ':', then don't consider
+ * it to be an IPv6 literal address.
+ *
+ * Scan the name string to find ":/" (or just ":"). The name
+ * is the portion of the string preceding the first ":/" (or ":").
+ */
+ char *p, *colon, *colonslash, c;
+ hostname = colon = colonslash = NULL;
+ p = name;
+ if (*p == '[') { /* Looks like an IPv6 literal address */
+ p++;
+ while (isxdigit(*p) || (*p == ':')) {
+ if (*p == ':') {
+ if (!colon)
+ colon = p;
+ if (!colonslash && (*(p+1) == '/'))
+ colonslash = p;
+ }
+ p++;
+ }
+ if ((*p == ']') && (*(p+1) == ':')) {
+ /* Found "[IPv6]:", double check that it's acceptable and use it. */
+ struct sockaddr_in6 sin6;
+ c = *p;
+ *p = '\0';
+ if (inet_pton(AF_INET6, name+1, &sin6))
+ hostname = name + 1;
+ *p = c;
+ }
+ }
+ /* if hostname not found yet, search for ":/" and ":" */
+ while (!hostname && *p && (!colon || !colonslash)) {
+ if (*p == ':') {
+ if (!colon)
+ colon = p;
+ if (!colonslash && (*(p+1) == '/'))
+ colonslash = p;
+ }
+ p++;
+ }
+ if (!hostname && (colonslash || colon)) {
+ /* host name is the string preceding the colon(slash) */
+ hostname = name;
+ if (colonslash)
+ p = colonslash;
+ else if (colon)
+ p = colon;
+ }
+ if (hostname) {
+ c = *p;
+ *p = '\0';
+ /* we just want all the names/aliases */
+ hp = getipnodebyname(hostname, AF_INET, 0, &errnum);
+ hp6 = getipnodebyname(hostname, AF_INET6, 0, &errnum);
+ *p = c;
+ }
+ }
+
+ if (nfshost && (hp || hp6)) {
+ int match = (namematch(hp) || namematch(hp6));
+ if (hp)
+ freehostent(hp);
+ if (hp6)
+ freehostent(hp6);
+ if (!match)
+ return (1);
+ }
+
+ if (vflag)
+ (void)printf("%s unmount from %s\n", name, mntpt);
+ if (fake)
+ return (0);
+
+ if (unmount(mntpt, fflag) < 0) {
+ /*
+ * If we're root and it looks like the error is that the
+ * mounted on directory is just not reachable or if we really
+ * want this filesystem unmounted (MNT_FORCE), then try doing
+ * the unmount by fsid. (Note: the sysctl only works for root)
+ */
+ if ((getuid() == 0) &&
+ ((errno == ESTALE) || (errno == ENOENT) || (fflag & MNT_FORCE))) {
+ if (vflag)
+ warn("unmount(%s)", mntpt);
+ if (unmount_by_fsid(mntpt, fflag) < 0) {
+ warn("unmount(%s)", mntpt);
+ return (1);
+ }
+ } else if (errno == EBUSY) {
+ fprintf(stderr, "umount(%s): %s -- try 'diskutil unmount'\n", mntpt, strerror(errno));
+ return (1);
+ } else {
+ warn("unmount(%s)", mntpt);
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+static struct statfs *mntbuf;
+static int mntsize;
+
+char *
+getmntname(const char *name, mntwhat what, char **type)
+{
+ int i;
+
+ if (mntbuf == NULL &&
+ (mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
+ warn("getmntinfo");
+ return (NULL);
+ }
+ for (i = mntsize-1; i >= 0; i--) {
+ if ((what == MNTON) && !strcmp(mntbuf[i].f_mntfromname, name)) {
+ if (type)
+ *type = mntbuf[i].f_fstypename;
+ return (mntbuf[i].f_mntonname);
+ }
+ if ((what == MNTFROM) && !strcmp(mntbuf[i].f_mntonname, name)) {
+ if (type)
+ *type = mntbuf[i].f_fstypename;
+ return (mntbuf[i].f_mntfromname);
+ }
+ }
+ return (NULL);
+}
+
+int
+getmntfsid(const char *name, fsid_t *fsid)
+{
+ int i;
+
+ if (mntbuf == NULL &&
+ (mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
+ warn("getmntinfo");
+ return (-1);
+ }
+ for (i = mntsize-1; i >= 0; i--) {
+ if (!strcmp(mntbuf[i].f_mntonname, name)) {
+ *fsid = mntbuf[i].f_fsid;
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+int
+namematch(struct hostent *hp)
+{
+ char *cp, **np;
+
+ if (nfshost == NULL)
+ return (1);
+
+ if (hp == NULL)
+ return (0);
+
+ if (strcasecmp(nfshost, hp->h_name) == 0)
+ return (1);
+
+ if ((cp = strchr(hp->h_name, '.')) != NULL) {
+ *cp = '\0';
+ if (strcasecmp(nfshost, hp->h_name) == 0)
+ return (1);
+ }
+ for (np = hp->h_aliases; *np; np++) {
+ if (strcasecmp(nfshost, *np) == 0)
+ return (1);
+ if ((cp = strchr(*np, '.')) != NULL) {
+ *cp = '\0';
+ if (strcasecmp(nfshost, *np) == 0)
+ return (1);
+ }
+ }
+ return (0);
+}
+
+
+int
+sysctl_fsid(
+ int op,
+ fsid_t *fsid,
+ void *oldp,
+ size_t *oldlenp,
+ void *newp,
+ size_t newlen)
+{
+ int ctlname[CTL_MAXNAME+2];
+ size_t ctllen;
+ const char *sysstr = "vfs.generic.ctlbyfsid";
+ struct vfsidctl vc;
+
+ ctllen = CTL_MAXNAME+2;
+ if (sysctlnametomib(sysstr, ctlname, &ctllen) == -1) {
+ warn("sysctlnametomib(%s)", sysstr);
+ return (-1);
+ };
+ ctlname[ctllen] = op;
+
+ bzero(&vc, sizeof(vc));
+ vc.vc_vers = VFS_CTL_VERS1;
+ vc.vc_fsid = *fsid;
+ vc.vc_ptr = newp;
+ vc.vc_len = newlen;
+ return (sysctl(ctlname, (uint32_t)(ctllen + 1), oldp, oldlenp, &vc, sizeof(vc)));
+}
+
+
+int
+unmount_by_fsid(const char *mntpt, int flag)
+{
+ fsid_t fsid;
+ if (getmntfsid(mntpt, &fsid) < 0)
+ return (-1);
+ if (vflag)
+ printf("attempting to unmount %s by fsid\n", mntpt);
+ return sysctl_fsid(VFS_CTL_UMOUNT, &fsid, NULL, 0, &flag, sizeof(flag));
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: %s\n %s\n",
+ "umount [-fv] [-t fstypelist] special | node",
+ "umount -a[fv] [-h host] [-t fstypelist]");
+ exit(1);
+}
diff --git a/diskdev_cmds/vndevice.tproj/vndevice.c b/diskdev_cmds/vndevice.tproj/vndevice.c
new file mode 100644
index 0000000..9610ddf
--- /dev/null
+++ b/diskdev_cmds/vndevice.tproj/vndevice.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * History:
+ * March 25, 2002 Dieter Siegmund (dieter@apple.com)
+ * - created
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioccom.h>
+#include <sys/vnioctl.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <mach/boolean.h>
+#include <sys/disk.h>
+
+void
+usage()
+{
+ fprintf(stderr, "usage: vncontrol <command> <args>\n"
+ "vncontrol attach <dev_node> <image_file>\n"
+ "vncontrol shadow <dev_node> <shadow_file>\n"
+ "vncontrol detach <dev_node>\n");
+ exit(1);
+}
+
+enum {
+ kAttach,
+ kDetach,
+ kShadow,
+};
+
+int
+main(int argc, char * argv[])
+{
+ int fd;
+ struct vn_ioctl vn;
+ int op = kAttach;
+ struct stat sb;
+
+ if (argc < 2) {
+ usage();
+ }
+ if (strcmp(argv[1], "attach") == 0) {
+ if (argc < 4) {
+ usage();
+ }
+ op = kAttach;
+ }
+ else if (strcmp(argv[1], "detach") == 0) {
+ if (argc < 3) {
+ usage();
+ }
+ op = kDetach;
+ }
+ else if (strcmp(argv[1], "shadow") == 0) {
+ if (argc < 4) {
+ usage();
+ }
+ op = kShadow;
+ }
+ else {
+ usage();
+ }
+ fd = open(argv[2], O_RDONLY, 0);
+ if (fd < 0) {
+ perror(argv[2]);
+ exit(2);
+ }
+ switch (op) {
+ case kAttach:
+ case kShadow:
+ if (stat(argv[3], &sb) < 0) {
+ perror(argv[3]);
+ exit(2);
+ }
+ break;
+ default:
+ break;
+ }
+ bzero(&vn, sizeof(vn));
+ switch (op) {
+ case kAttach:
+ vn.vn_file = argv[3];
+ vn.vn_control = vncontrol_readwrite_io_e;
+
+ if (ioctl(fd, VNIOCATTACH, &vn) < 0) {
+ perror("VNIOCATTACH");
+ exit(2);
+ }
+ break;
+ case kDetach:
+ if (ioctl(fd, VNIOCDETACH, &vn) < 0) {
+ perror("VNIOCDETACH");
+ exit(2);
+ }
+ break;
+ case kShadow:
+ vn.vn_file = argv[3];
+ if (ioctl(fd, VNIOCSHADOW, &vn) < 0) {
+ perror("VNIOCSHADOW");
+ exit(2);
+ }
+ break;
+ }
+ close(fd);
+ exit(0);
+ return (0);
+}
diff --git a/diskdev_cmds/vsdbutil.tproj/com.apple.vsdbutil.plist b/diskdev_cmds/vsdbutil.tproj/com.apple.vsdbutil.plist
new file mode 100644
index 0000000..18bf10e
--- /dev/null
+++ b/diskdev_cmds/vsdbutil.tproj/com.apple.vsdbutil.plist
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.apple.vsdbutil</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/sbin/vsdbutil</string>
+ <string>-i</string>
+ </array>
+ <key>KeepAlive</key>
+ <dict>
+ <key>PathState</key>
+ <dict>
+ <key>/var/db/volinfo.database</key>
+ <false/>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/diskdev_cmds/vsdbutil.tproj/vsdbutil.8 b/diskdev_cmds/vsdbutil.tproj/vsdbutil.8
new file mode 100644
index 0000000..1be7d10
--- /dev/null
+++ b/diskdev_cmds/vsdbutil.tproj/vsdbutil.8
@@ -0,0 +1,49 @@
+.Dd December 19, 2001
+.Dt VSDBUTIL 8
+.Os Darwin
+.Sh NAME
+.Nm vsdbutil
+.Nd manipulates the volume status DB.
+.Sh SYNOPSIS
+.Nm
+.Op Fl a Ar path
+.Pp
+.Nm
+.Op Fl c Ar path
+.Op Fl d Ar path
+.Op Fl i
+.Pp
+.Nm
+.Op Fl h
+.Sh DESCRIPTION
+.Nm
+manipulates the volume status DB.
+The following options are available:
+.Bl -tag -width -indent
+.It Fl a
+adopts (activates) on-disk ownership on the specified path
+.It Fl c
+checks the status of the ownership usage on the specified path
+.It Fl d
+disowns (deactivates) the on-disk ownership on the specified path
+.It Fl i
+initializes the ownership database to include all mounted HFS+ and APFS volumes
+.It Fl h
+prints out a simple help message
+.El
+.Pp
+The
+.Nm
+command is deprecated; using a volume UUID in
+.Xr fstab 5
+is preferred.
+.Sh FILES
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /var/db/volinfo.database
+Database of volumes managed via
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr diskutil 8 ,
+.Xr mount 8 ,
+.Xr fstab 5
diff --git a/diskdev_cmds/vsdbutil.tproj/vsdbutil_main.c b/diskdev_cmds/vsdbutil.tproj/vsdbutil_main.c
new file mode 100644
index 0000000..c9647fe
--- /dev/null
+++ b/diskdev_cmds/vsdbutil.tproj/vsdbutil_main.c
@@ -0,0 +1,1213 @@
+/*
+ * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ About vsdbutil.c:
+ Contains code to manipulate the volume status DB (/var/db/volinfo.database).
+
+ Change History:
+ 18-Apr-2000 Pat Dirks New Today.
+
+ */
+
+
+/* ************************************** I N C L U D E S ***************************************** */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/ucred.h>
+#include <sys/resource.h>
+#include <sys/vmmeter.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <err.h>
+#include <errno.h>
+#include <dirent.h>
+#include <strings.h>
+
+#include <sys/attr.h>
+#include <uuid/uuid.h>
+#include <System/uuid/namespace.h>
+
+// This flags array is shared with the mount(8) tool.
+#include "../mount_flags_dir/mount_flags.h"
+
+//from mount_flags_dir/mount_flags.c
+extern mountopt_t optnames[];
+
+
+/*
+ * CommonCrypto is meant to be a more stable API than OpenSSL.
+ * Defining COMMON_DIGEST_FOR_OPENSSL gives API-compatibility
+ * with OpenSSL, so we don't have to change the code.
+ */
+#define COMMON_DIGEST_FOR_OPENSSL
+#include <CommonCrypto/CommonDigest.h>
+#include <libkern/OSByteOrder.h>
+
+static char usage[] = "Usage: %s [-a path] | [-c path ] [-d path] [-i]\n";
+
+static char gHFSTypeName[] = "hfs";
+static char gAPFSTypeName[] = "apfs";
+
+/*****************************************************************************
+ *
+ * The following should really be in some system header file:
+ *
+ *****************************************************************************/
+
+typedef struct VolumeUUID {
+ uuid_t uuid;
+} VolumeUUID;
+
+#define VOLUMEUUID64LENGTH 16
+
+#define VOLUME_USEPERMISSIONS 0x00000001
+#define VOLUME_VALIDSTATUSBITS ( VOLUME_USEPERMISSIONS )
+
+typedef void *VolumeStatusDBHandle;
+
+void ConvertVolumeUUIDString64ToUUID(const char *UUIDString64, VolumeUUID *volumeID);
+
+int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr);
+int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle);
+int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, u_int32_t *VolumeStatus);
+int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, u_int32_t VolumeStatus);
+int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID);
+int CloseVolumeStatusDB(VolumeStatusDBHandle DBHandle);
+
+/*****************************************************************************
+ *
+ * Internal function prototypes:
+ *
+ *****************************************************************************/
+
+static void check_uid(void);
+static int GetVolumeUUID(const char *path, VolumeUUID *volumeUUIDPtr);
+static int AdoptAllLocalVolumes(void);
+static int AdoptVolume(const char *path);
+static int DisownVolume(const char *path);
+static int ClearVolumeUUID(const char *path);
+static int DisplayVolumeStatus(const char *path);
+static int UpdateMountStatus(const char *path, u_int32_t volstatus);
+
+
+static int isVolumeHFS(const char*path);
+
+int main (int argc, const char *argv[])
+{
+ int arg;
+ char option;
+ int result = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, usage, argv[0]);
+ exit(1);
+ };
+
+ for (arg = 1; arg < argc; ++arg) {
+ if ((argv[arg][0] == '-') &&
+ ((option = argv[arg][1]) != (char)0) &&
+ (argv[arg][2] == (char)0)) {
+ switch (option) {
+ case 'a':
+ case 'A':
+ /* Pick out the pathname argument: */
+ if (++arg >= argc) {
+ fprintf(stderr, usage, argv[0]);
+ exit(1);
+ }
+
+ check_uid();
+ result = AdoptVolume(argv[arg]);
+ break;
+
+ case 'c':
+ case 'C':
+ /* Pick out the pathname argument: */
+ if (++arg >= argc) {
+ fprintf(stderr, usage, argv[0]);
+ exit(1);
+ };
+
+ result = DisplayVolumeStatus(argv[arg]);
+ break;
+
+ case 'd':
+ case 'D':
+ /* Pick out the pathname argument: */
+ if (++arg >= argc) {
+ fprintf(stderr, usage, argv[0]);
+ exit(1);
+ };
+
+ check_uid();
+ result = DisownVolume(argv[arg]);
+ break;
+
+ case 'h':
+ case 'H':
+ printf(usage, argv[0]);
+ printf("where\n");
+ printf("\t-a adopts (activates) on-disk permissions on the specified path,\n");
+ printf("\t-c checks the status of the permissions usage on the specified path\n");
+ printf("\t-d disowns (deactivates) the on-disk permissions on the specified path\n");
+ printf("\t-i initializes the permissions database to include all mounted HFS/HFS+ volumes\n");
+ break;
+
+ case 'i':
+ case 'I':
+ check_uid();
+ result = AdoptAllLocalVolumes();
+ break;
+
+ case 'x':
+ case 'X':
+ /* Pick out the pathname argument: */
+ if (++arg >= argc) {
+ fprintf(stderr, usage, argv[0]);
+ exit(1);
+ };
+
+ check_uid();
+ result = ClearVolumeUUID(argv[arg]);
+ break;
+
+ default:
+ fprintf(stderr, usage, argv[0]);
+ exit(1);
+ }
+ }
+ }
+
+ if (result < 0) result = 1; // Make sure only positive exit status codes are generated
+
+ exit(result); // ensure the process exit status is returned
+ return result; // ...and make main fit the ANSI spec.
+}
+
+
+
+static void check_uid(void) {
+ if (geteuid() != 0) {
+ fprintf(stderr, "###\n");
+ fprintf(stderr, "### You must be root to perform this operation.\n");
+ fprintf(stderr, "###\n");
+ exit(1);
+ };
+}
+
+
+
+/*
+ -- UpdateMountStatus
+ --
+ -- Returns: error code (0 if successful).
+ */
+static int
+UpdateMountStatus(const char *path, u_int32_t volstatus) {
+ struct statfs mntstat;
+ int result;
+ union wait status;
+ int pid;
+
+ /*
+ * selectors to determine whether or not certain features
+ * should be re-enabled via mount -u
+ */
+#ifndef MAXMOUNTLEN
+#define MAXMOUNTLEN 255
+#endif
+
+ char mountline[MAXMOUNTLEN];
+ char mountstring[MAXMOUNTLEN];
+
+ mountopt_t* opt = NULL;
+ uint64_t flags;
+ uint64_t flags_mask = (MNT_NOSUID | MNT_NODEV |
+ MNT_NOEXEC | MNT_RDONLY |
+ MNT_CPROTECT | MNT_QUARANTINE |
+ MNT_UNION | MNT_DONTBROWSE);
+
+ result = statfs(path, &mntstat);
+ if (result != 0) {
+ warn("couldn't look up mount status for '%s'", path);
+ return errno;
+ }
+
+ bzero (mountline, MAXMOUNTLEN);
+ bzero (mountstring, MAXMOUNTLEN);
+
+ /* first, check for permissions */
+ if (volstatus & VOLUME_USEPERMISSIONS) {
+ strlcpy(mountline, "perm", MAXMOUNTLEN);
+ }
+ else {
+ strlcpy(mountline, "noperm", MAXMOUNTLEN);
+ }
+
+ /* check the flags */
+ flags = (mntstat.f_flags & flags_mask);
+
+ /*
+ * now iterate over all of the strings in the optname array and
+ * add them into the "mount" string if the flag they represent is set.
+ * The optnames array is extern'd (at the top of this file), and is defined
+ * in a .c file within the mount_flags directory
+ */
+ for (opt = optnames; flags && opt->o_opt; opt++) {
+ if ((flags & opt->o_opt) && opt->o_cmd) {
+ snprintf(mountstring, sizeof(mountstring), ",%s", opt->o_cmd);
+ result = strlcat(mountline, mountstring, MAXMOUNTLEN);
+ if (result >= MAXMOUNTLEN) {
+ // bail out, string is too long.
+ return EINVAL;
+ }
+ flags &= ~opt->o_opt;
+ bzero (mountstring, MAXMOUNTLEN);
+ }
+ }
+
+#ifdef MAXMOUNTLEN
+#undef MAXMOUNTLEN
+#endif
+
+ pid = fork();
+ if (pid == 0) {
+ result = execl("/sbin/mount", "mount",
+ "-t", mntstat.f_fstypename,
+ "-u","-o", mountline,
+ mntstat.f_mntfromname, mntstat.f_mntonname, NULL);
+ /* IF WE ARE HERE, WE WERE UNSUCCESFULL */
+ return (1);
+ }
+
+ if (pid == -1) {
+ warn("couldn't fork to execute mount command");
+ return errno;
+ };
+
+ /* Success! */
+ if ((wait4(pid, (int *)&status, 0, NULL) == pid) && (WIFEXITED(status))) {
+ result = status.w_retcode;
+ } else {
+ result = -1;
+ };
+
+ return result;
+}
+
+
+
+/*
+ -- AdoptAllLocalVolumes
+ --
+ -- Returns: error code (0 if successful).
+ */
+static int
+AdoptAllLocalVolumes(void) {
+ struct statfs *mntstatptr;
+ int fscount;
+
+ fscount = getmntinfo(&mntstatptr, MNT_WAIT);
+ if (fscount == 0) {
+ warn("couldn't get information on mounted volumes");
+ return errno;
+ };
+
+ while (fscount > 0) {
+ if ((strncmp(mntstatptr->f_fstypename, gHFSTypeName, MFSNAMELEN) == 0) ||
+ (strncmp(mntstatptr->f_fstypename, gAPFSTypeName, MFSNAMELEN) == 0)) {
+ (void)AdoptVolume(mntstatptr->f_mntonname);
+ };
+
+ ++mntstatptr;
+ --fscount;
+ };
+
+ return 0;
+}
+
+
+
+/*
+ -- AdoptVolume
+ --
+ -- Returns: error code (0 if successful).
+ */
+static int
+AdoptVolume(const char *path) {
+ VolumeUUID targetuuid;
+ VolumeStatusDBHandle vsdb;
+ u_int32_t volstatus;
+ int result = 0;
+
+ /* Look up the target volume UUID: */
+ result = GetVolumeUUID(path, &targetuuid);
+ if (result != 0) {
+ warnx("no valid volume UUID found on '%s': %s", path, strerror(result));
+ return result;
+ };
+
+ if (uuid_is_null(targetuuid.uuid)) {
+ warnx("internal error: incomplete UUID generated.");
+ return EINVAL;
+ };
+
+ /* Open the volume status DB to look up the entry for the volume in question: */
+ if ((result = OpenVolumeStatusDB(&vsdb)) != 0) {
+ warnx("couldn't access volume status database: %s", strerror(result));
+ return result;
+ };
+
+ /* Check to see if an entry exists. If not, prepare a default initial status value: */
+ if ((result = GetVolumeStatusDBEntry(vsdb, &targetuuid, &volstatus)) != 0) {
+ volstatus = 0;
+ };
+
+ /* Enable permissions on the specified volume: */
+ volstatus = (volstatus & VOLUME_VALIDSTATUSBITS) | VOLUME_USEPERMISSIONS;
+
+ /* Update the entry in the volume status database: */
+ if ((result = SetVolumeStatusDBEntry(vsdb, &targetuuid, volstatus)) != 0) {
+ warnx("couldn't update volume status database: %s", strerror(result));
+ return result;
+ };
+
+ (void)CloseVolumeStatusDB(vsdb);
+
+ if ((result = UpdateMountStatus(path, volstatus)) != 0) {
+ warnx("couldn't update mount status of '%s': %s", path, strerror(result));
+ return result;
+ };
+
+ return 0;
+}
+
+
+
+/*
+ -- DisownVolume
+ --
+ -- Returns: error code (0 if successful).
+ */
+static int
+DisownVolume(const char *path) {
+ VolumeUUID targetuuid;
+ VolumeStatusDBHandle vsdb;
+ u_int32_t volstatus;
+ int result = 0;
+
+ /* Look up the target volume UUID: */
+ result = GetVolumeUUID(path, &targetuuid);
+ if (result != 0) {
+ warnx("no valid volume UUID found on '%s': %s", path, strerror(result));
+ return result;
+ };
+
+ volstatus = 0;
+ if (!uuid_is_null(targetuuid.uuid)) {
+ /* Open the volume status DB to look up the entry for the volume in question: */
+ if ((result = OpenVolumeStatusDB(&vsdb)) != 0) {
+ warnx("couldn't access volume status database: %s", strerror(result));
+ return result;
+ };
+
+ /* Check to see if an entry exists. If not, prepare a default initial status value: */
+ if ((result = GetVolumeStatusDBEntry(vsdb, &targetuuid, &volstatus)) != 0) {
+ volstatus = 0;
+ };
+
+ /* Disable permissions on the specified volume: */
+ volstatus = (volstatus & VOLUME_VALIDSTATUSBITS) & ~VOLUME_USEPERMISSIONS;
+
+ /* Update the entry in the volume status database: */
+ if ((result = SetVolumeStatusDBEntry(vsdb, &targetuuid, volstatus)) != 0) {
+ warnx("couldn't update volume status database: %s", strerror(result));
+ return result;
+ };
+
+ (void)CloseVolumeStatusDB(vsdb);
+
+ };
+
+ if ((result = UpdateMountStatus(path, volstatus)) != 0) {
+ warnx("couldn't update mount status of '%s': %s", path, strerror(result));
+ return result;
+ };
+
+ return result;
+};
+
+
+
+/*
+ -- ClearVolumeUUID
+ --
+ -- Returns: error code (0 if successful).
+ */
+static int
+ClearVolumeUUID(const char *path) {
+ VolumeUUID targetuuid;
+ VolumeStatusDBHandle vsdb;
+ u_int32_t volstatus;
+ int result = 0;
+
+ /* Check to see whether the target volume has an assigned UUID: */
+ result = GetVolumeUUID(path, &targetuuid);
+ if (result != 0) {
+ warnx("couldn't read volume UUID on '%s': %s", path, strerror(result));
+ return result;
+ };
+
+ if (uuid_is_null(targetuuid.uuid) == 0) {
+ /* Open the volume status DB to look up the entry for the volume in question: */
+ if ((result = OpenVolumeStatusDB(&vsdb)) != 0) {
+ warnx("couldn't access volume status database: %s", strerror(result));
+ return result;
+ };
+
+ /* Check to see if an entry exists: */
+ if (GetVolumeStatusDBEntry(vsdb, &targetuuid, &volstatus) == 0) {
+ /* Remove the entry from the volume status database: */
+ if ((result = DeleteVolumeStatusDBEntry(vsdb, &targetuuid)) != 0) {
+ warnx("couldn't update volume status database: %s", strerror(result));
+ return result;
+ };
+ };
+
+ (void)CloseVolumeStatusDB(vsdb);
+
+ if ((result = UpdateMountStatus(path, 0)) != 0) {
+ warnx("couldn't update mount status of '%s': %s", path, strerror(result));
+ return result;
+ };
+
+ };
+
+ return result;
+};
+
+
+
+/*
+ -- DisplayVolumeStatus
+ --
+ -- Returns: error code (0 if successful).
+ */
+static int
+DisplayVolumeStatus(const char *path) {
+ VolumeUUID targetuuid;
+ VolumeStatusDBHandle vsdb;
+ u_int32_t volstatus;
+ int result = 0;
+
+ /* Look up the target volume UUID, exactly as stored on disk: */
+ result = GetVolumeUUID(path, &targetuuid);
+ if (result != 0) {
+ warnx("couldn't read volume UUID on '%s': %s", path, strerror(result));
+ return result;
+ };
+
+ if (uuid_is_null(targetuuid.uuid)) {
+ warnx("no valid volume UUID found on '%s': permissions are disabled.", path);
+ return 0;
+ };
+
+ /* Open the volume status DB to look up the entry for the volume in question: */
+ if ((result = OpenVolumeStatusDB(&vsdb)) != 0) {
+ warnx("couldn't access volume status database: %s", strerror(result));
+ return result;
+ };
+
+ if ((result = GetVolumeStatusDBEntry(vsdb, &targetuuid, &volstatus)) != 0) {
+ printf("No entry found for '%s'.\n", path);
+ goto Std_Exit;
+ };
+
+ if (volstatus & VOLUME_USEPERMISSIONS) {
+ printf("Permissions on '%s' are enabled.\n", path);
+ } else {
+ printf("Permissions on '%s' are disabled.\n", path);
+ };
+
+Std_Exit:
+ (void)CloseVolumeStatusDB(vsdb);
+
+ return result;
+}
+
+static int isVolumeHFS (const char* path) {
+
+ /* default to no */
+ int result = 0;
+ int isHFS = 0;
+
+ struct statfs statfs_buf;
+
+ result = statfs (path, &statfs_buf);
+ if (result == 0) {
+ if (!strncmp(statfs_buf.f_fstypename, gHFSTypeName, 3)) {
+ isHFS = 1;
+ }
+ }
+
+ return isHFS;
+}
+
+
+
+//struct definition for calling getattrlist for finderinfos
+typedef struct FinderInfoBuf {
+ uint32_t info_length;
+ uint32_t finderinfo[8];
+} FinderInfoBuf_t;
+
+typedef struct hfsUUID {
+ uint32_t high;
+ uint32_t low;
+} hfsUUID_t;
+
+/*
+ -- GetVolumeUUID
+ --
+ -- Returns: error code (0 if successful).
+ */
+
+static int
+GetVolumeUUID(const char *path, VolumeUUID *volumeUUIDPtr) {
+ struct attrlist alist;
+ struct { uint32_t size; uuid_t uuid; } volUUID;
+
+ FinderInfoBuf_t finfo;
+
+ int result;
+
+ /*
+ * For a bit more definition on why we have to do this, check out
+ * hfs.util source. The gist is that IFF the volume is HFS, then
+ * we must check the finderinfo UUID FIRST before querying the
+ * fs for its full UUID via the getattrlist volume call.
+ */
+
+ if (isVolumeHFS(path)) {
+ /* then go get the finderinfo, first... */
+ memset (&alist, 0, sizeof(alist));
+ alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ alist.reserved = 0;
+ alist.commonattr = ATTR_CMN_FNDRINFO;
+ alist.volattr = ATTR_VOL_INFO;
+ alist.dirattr = 0;
+ alist.fileattr = 0;
+ alist.forkattr = 0;
+
+ result = getattrlist (path, &alist, &finfo, sizeof(finfo), 0);
+ if (result) {
+ warn ("failed to getattrlist finderinfo for %s", path);
+ result = errno;
+ goto Err_Exit;
+ }
+
+ hfsUUID_t* hfs_finfo_uuid = (hfsUUID_t*)(&finfo.finderinfo[6]);
+
+ /*
+ * Note: this is a bit of HFS-specific chicanery. When HFS+ generates
+ * the volume UUID, the formula it uses to generate the 8 bytes of internal
+ * UUID is re-looped/restarted if either high or low is zero. Thus, if we
+ * see either word as '0' then that means we should treat it as an uninitialized
+ * UUID.
+ *
+ * As a result, if we see either word as zero, then clear out the caller's buffer
+ * and return the NULL UUID. Otherwise, we'd get the 8 bytes which potentially include
+ * one or more zeroes run through HFS+'s MD5 algorithm which is not what we want.
+ */
+ //technically should endian-swap this but not necessary here
+ if ((hfs_finfo_uuid->high == 0) || (hfs_finfo_uuid->low == 0)) {
+ uuid_clear (volumeUUIDPtr->uuid);
+ return 0;
+ }
+ }
+
+
+ /* Set up the attrlist structure to get the volume's UUID: */
+ alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ alist.reserved = 0;
+ alist.commonattr = 0;
+ alist.volattr = (ATTR_VOL_INFO | ATTR_VOL_UUID);
+ alist.dirattr = 0;
+ alist.fileattr = 0;
+ alist.forkattr = 0;
+
+ result = getattrlist(path, &alist, &volUUID, sizeof(volUUID), 0);
+ if (result) {
+ warn("Couldn't get volume information for '%s'", path);
+ result = errno;
+ goto Err_Exit;
+ }
+
+ uuid_copy(volumeUUIDPtr->uuid, volUUID.uuid);
+ result = 0;
+
+Err_Exit:
+ return result;
+};
+
+
+
+
+
+/******************************************************************************
+ *
+ * V O L U M E S T A T U S D A T A B A S E R O U T I N E S
+ *
+ *****************************************************************************/
+
+#define DBHANDLESIGNATURE 0x75917737
+
+/* Flag values for operation options: */
+#define DBMARKPOSITION 1
+
+static char gVSDBPath[] = "/var/db/volinfo.database";
+
+#define MAXIOMALLOC 16384
+
+/* Database layout: */
+
+struct VSDBKey {
+ char uuidString[36];
+};
+
+struct VSDBRecord {
+ char statusFlags[8];
+};
+
+struct VSDBEntry {
+ struct VSDBKey key;
+ char keySeparator;
+ char space;
+ struct VSDBRecord record;
+ char terminator;
+};
+
+struct VSDBKey64 {
+ char uuid[16];
+};
+
+struct VSDBEntry64 {
+ struct VSDBKey64 key;
+ char keySeparator;
+ char space;
+ struct VSDBRecord record;
+ char terminator;
+};
+
+#define DBKEYSEPARATOR ':'
+#define DBBLANKSPACE ' '
+#define DBRECORDTERMINATOR '\n'
+
+/* In-memory data structures: */
+
+struct VSDBState {
+ u_int32_t signature;
+ int dbfile;
+ int dbmode;
+ off_t recordPosition;
+};
+
+typedef struct VSDBState *VSDBStatePtr;
+
+
+
+/* Internal function prototypes: */
+static int LockDB(VSDBStatePtr dbstateptr, int lockmode);
+static int UnlockDB(VSDBStatePtr dbstateptr);
+
+static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, VolumeUUID *volumeID, struct VSDBEntry *dbentry, u_int32_t options);
+static int AddVolumeRecord(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry);
+static int UpdateVolumeRecord(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry);
+static int GetVSDBEntry(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry);
+static int CompareVSDBKeys(struct VSDBKey *key1, struct VSDBKey *key2);
+
+static void FormatULong(u_int32_t u, char *s);
+static void FormatDBKey(VolumeUUID *volumeID, struct VSDBKey *dbkey);
+static void FormatDBRecord(u_int32_t volumeStatusFlags, struct VSDBRecord *dbrecord);
+static void FormatDBEntry(VolumeUUID *volumeID, u_int32_t volumeStatusFlags, struct VSDBEntry *dbentry);
+static u_int32_t ConvertHexStringToULong(const char *hs, long maxdigits);
+
+
+
+/******************************************************************************
+ *
+ * P U B L I S H E D I N T E R F A C E R O U T I N E S
+ *
+ *****************************************************************************/
+
+void ConvertVolumeUUIDString64ToUUID(const char *UUIDString64, VolumeUUID *volumeID) {
+ int i;
+ char c;
+ u_int32_t nextdigit;
+ u_int32_t high = 0;
+ u_int32_t low = 0;
+ u_int32_t carry;
+ MD5_CTX ctx;
+
+ for (i = 0; (i < VOLUMEUUID64LENGTH) && ((c = UUIDString64[i]) != (char)0) ; ++i) {
+ if ((c >= '0') && (c <= '9')) {
+ nextdigit = c - '0';
+ } else if ((c >= 'A') && (c <= 'F')) {
+ nextdigit = c - 'A' + 10;
+ } else if ((c >= 'a') && (c <= 'f')) {
+ nextdigit = c - 'a' + 10;
+ } else {
+ nextdigit = 0;
+ };
+ carry = ((low & 0xF0000000) >> 28) & 0x0000000F;
+ high = (high << 4) | carry;
+ low = (low << 4) | nextdigit;
+ };
+
+ high = OSSwapHostToBigInt32(high);
+ low = OSSwapHostToBigInt32(low);
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, kFSUUIDNamespaceSHA1, sizeof(uuid_t));
+ MD5_Update(&ctx, &high, sizeof(high));
+ MD5_Update(&ctx, &low, sizeof(low));
+ MD5_Final(volumeID->uuid, &ctx);
+
+ volumeID->uuid[6] = (volumeID->uuid[6] & 0x0F) | 0x30;
+ volumeID->uuid[8] = (volumeID->uuid[8] & 0x3F) | 0x80;
+}
+
+
+
+int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr) {
+ VSDBStatePtr dbstateptr;
+
+ *DBHandlePtr = NULL;
+
+ dbstateptr = (VSDBStatePtr)malloc(sizeof(*dbstateptr));
+ if (dbstateptr == NULL) {
+ return ENOMEM;
+ };
+
+ dbstateptr->dbmode = O_RDWR;
+ dbstateptr->dbfile = open(gVSDBPath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (dbstateptr->dbfile == -1) {
+ /*
+ The file couldn't be opened for read/write access:
+ try read-only access before giving up altogether.
+ */
+ dbstateptr->dbmode = O_RDONLY;
+ dbstateptr->dbfile = open(gVSDBPath, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ if (dbstateptr->dbfile == -1) {
+ return errno;
+ };
+ };
+
+ dbstateptr->signature = DBHANDLESIGNATURE;
+ *DBHandlePtr = (VolumeStatusDBHandle)dbstateptr;
+ ConvertVolumeStatusDB(*DBHandlePtr);
+ return 0;
+}
+
+
+
+int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
+ VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
+ struct VSDBEntry64 entry64;
+ struct stat dbinfo;
+ int result;
+ u_int32_t iobuffersize;
+ void *iobuffer = NULL;
+ int i;
+
+ if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
+
+ if ((result = LockDB(dbstateptr, LOCK_EX)) != 0) return result;
+
+ lseek(dbstateptr->dbfile, 0, SEEK_SET);
+ result = read(dbstateptr->dbfile, &entry64, sizeof(entry64));
+ if ((result != sizeof(entry64)) ||
+ (entry64.keySeparator != DBKEYSEPARATOR) ||
+ (entry64.space != DBBLANKSPACE) ||
+ (entry64.terminator != DBRECORDTERMINATOR)) {
+ result = 0;
+ goto ErrExit;
+ } else {
+ if ((result = stat(gVSDBPath, &dbinfo)) != 0) goto ErrExit;
+ iobuffersize = dbinfo.st_size;
+ iobuffer = malloc(iobuffersize);
+ if (iobuffer == NULL) {
+ result = ENOMEM;
+ goto ErrExit;
+ };
+
+ lseek(dbstateptr->dbfile, 0, SEEK_SET);
+ result = read(dbstateptr->dbfile, iobuffer, iobuffersize);
+ if (result != iobuffersize) {
+ result = errno;
+ goto ErrExit;
+ };
+ if ((result = ftruncate(dbstateptr->dbfile, 0)) != 0) {
+ goto ErrExit;
+ };
+
+ for (i = 0; i < iobuffersize / sizeof(entry64); i++) {
+ VolumeUUID volumeID;
+ u_int32_t VolumeStatus;
+ struct VSDBEntry dbentry;
+
+ entry64 = *(((struct VSDBEntry64 *)iobuffer) + i);
+ if ((entry64.keySeparator != DBKEYSEPARATOR) ||
+ (entry64.space != DBBLANKSPACE) ||
+ (entry64.terminator != DBRECORDTERMINATOR)) {
+ continue;
+ }
+
+ ConvertVolumeUUIDString64ToUUID(entry64.key.uuid, &volumeID);
+ VolumeStatus = ConvertHexStringToULong(entry64.record.statusFlags, sizeof(entry64.record.statusFlags));
+
+ FormatDBEntry(&volumeID, VolumeStatus, &dbentry);
+ if ((result = AddVolumeRecord(dbstateptr, &dbentry)) != sizeof(dbentry)) {
+ warnx("couldn't convert volume status database: %s", strerror(result));
+ goto ErrExit;
+ };
+ };
+
+ fsync(dbstateptr->dbfile);
+
+ result = 0;
+ };
+
+ErrExit:
+ if (iobuffer) free(iobuffer);
+ UnlockDB(dbstateptr);
+ return result;
+}
+
+
+
+int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, u_int32_t *VolumeStatus) {
+ VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
+ struct VSDBEntry dbentry;
+ int result;
+
+ if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
+
+ if ((result = LockDB(dbstateptr, LOCK_SH)) != 0) return result;
+
+ if ((result = FindVolumeRecordByUUID(dbstateptr, volumeID, &dbentry, 0)) != 0) {
+ goto ErrExit;
+ };
+ *VolumeStatus = ConvertHexStringToULong(dbentry.record.statusFlags, sizeof(dbentry.record.statusFlags));
+
+ result = 0;
+
+ErrExit:
+ UnlockDB(dbstateptr);
+ return result;
+}
+
+
+
+int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, u_int32_t VolumeStatus) {
+ VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
+ struct VSDBEntry dbentry;
+ int result;
+
+ if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
+ if (VolumeStatus & ~VOLUME_VALIDSTATUSBITS) return EINVAL;
+
+ if ((result = LockDB(dbstateptr, LOCK_EX)) != 0) return result;
+
+ FormatDBEntry(volumeID, VolumeStatus, &dbentry);
+ if ((result = FindVolumeRecordByUUID(dbstateptr, volumeID, NULL, DBMARKPOSITION)) == 0) {
+ result = UpdateVolumeRecord(dbstateptr, &dbentry);
+ } else if (result == -1) {
+ result = AddVolumeRecord(dbstateptr, &dbentry);
+ } else {
+ goto ErrExit;
+ };
+
+ fsync(dbstateptr->dbfile);
+
+ result = 0;
+
+ErrExit:
+ UnlockDB(dbstateptr);
+ return result;
+}
+
+
+
+int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID) {
+ VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
+ struct stat dbinfo;
+ int result;
+ u_int32_t iobuffersize;
+ void *iobuffer = NULL;
+ off_t dataoffset;
+ u_int32_t iotransfersize;
+ u_int32_t bytestransferred;
+
+ if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
+
+ if ((result = LockDB(dbstateptr, LOCK_EX)) != 0) return result;
+
+ if ((result = FindVolumeRecordByUUID(dbstateptr, volumeID, NULL, DBMARKPOSITION)) != 0) {
+ if (result == -1) result = 0; /* Entry wasn't in the database to begin with? */
+ goto StdEdit;
+ } else {
+ if ((result = stat(gVSDBPath, &dbinfo)) != 0) goto ErrExit;
+ if ((dbinfo.st_size - dbstateptr->recordPosition - sizeof(struct VSDBEntry)) <= MAXIOMALLOC) {
+ iobuffersize = dbinfo.st_size - dbstateptr->recordPosition - sizeof(struct VSDBEntry);
+ } else {
+ iobuffersize = MAXIOMALLOC;
+ };
+ if (iobuffersize > 0) {
+ iobuffer = malloc(iobuffersize);
+ if (iobuffer == NULL) {
+ result = ENOMEM;
+ goto ErrExit;
+ };
+
+ dataoffset = dbstateptr->recordPosition + sizeof(struct VSDBEntry);
+ do {
+ iotransfersize = dbinfo.st_size - dataoffset;
+ if (iotransfersize > 0) {
+ if (iotransfersize > iobuffersize) iotransfersize = iobuffersize;
+
+ lseek(dbstateptr->dbfile, dataoffset, SEEK_SET);
+ bytestransferred = read(dbstateptr->dbfile, iobuffer, iotransfersize);
+ if (bytestransferred != iotransfersize) {
+ result = errno;
+ goto ErrExit;
+ };
+
+ lseek(dbstateptr->dbfile, dataoffset - (off_t)sizeof(struct VSDBEntry), SEEK_SET);
+ bytestransferred = write(dbstateptr->dbfile, iobuffer, iotransfersize);
+ if (bytestransferred != iotransfersize) {
+ result = errno;
+ goto ErrExit;
+ };
+
+ dataoffset += (off_t)iotransfersize;
+ };
+ } while (iotransfersize > 0);
+ };
+ if ((result = ftruncate(dbstateptr->dbfile, dbinfo.st_size - (off_t)(sizeof(struct VSDBEntry)))) != 0) {
+ goto ErrExit;
+ };
+
+ fsync(dbstateptr->dbfile);
+
+ result = 0;
+ };
+
+ErrExit:
+ if (iobuffer) free(iobuffer);
+ UnlockDB(dbstateptr);
+
+StdEdit:
+ return result;
+}
+
+
+
+int CloseVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
+ VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
+
+ if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
+
+ dbstateptr->signature = 0;
+
+ close(dbstateptr->dbfile); /* Nothing we can do about any errors... */
+ dbstateptr->dbfile = 0;
+
+ free(dbstateptr);
+
+ return 0;
+}
+
+
+
+/******************************************************************************
+ *
+ * I N T E R N A L O N L Y D A T A B A S E R O U T I N E S
+ *
+ *****************************************************************************/
+
+static int LockDB(VSDBStatePtr dbstateptr, int lockmode) {
+ return flock(dbstateptr->dbfile, lockmode);
+}
+
+
+
+static int UnlockDB(VSDBStatePtr dbstateptr) {
+ return flock(dbstateptr->dbfile, LOCK_UN);
+}
+
+
+
+static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, VolumeUUID *volumeID, struct VSDBEntry *targetEntry, u_int32_t options) {
+ struct VSDBKey searchkey;
+ struct VSDBEntry dbentry;
+ int result;
+
+ FormatDBKey(volumeID, &searchkey);
+ lseek(dbstateptr->dbfile, 0, SEEK_SET);
+
+ do {
+ result = GetVSDBEntry(dbstateptr, &dbentry);
+ if ((result == 0) && (CompareVSDBKeys(&dbentry.key, &searchkey) == 0)) {
+ if (targetEntry != NULL) {
+ memcpy(targetEntry, &dbentry, sizeof(*targetEntry));
+ };
+ return 0;
+ };
+ } while (result == 0);
+
+ return -1;
+}
+
+
+
+static int AddVolumeRecord(VSDBStatePtr dbstateptr , struct VSDBEntry *dbentry) {
+ lseek(dbstateptr->dbfile, 0, SEEK_END);
+ return write(dbstateptr->dbfile, dbentry, sizeof(struct VSDBEntry));
+}
+
+
+
+
+static int UpdateVolumeRecord(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry) {
+ lseek(dbstateptr->dbfile, dbstateptr->recordPosition, SEEK_SET);
+ return write(dbstateptr->dbfile, dbentry, sizeof(*dbentry));
+}
+
+
+
+static int GetVSDBEntry(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry) {
+ struct VSDBEntry entry;
+ int result;
+
+ dbstateptr->recordPosition = lseek(dbstateptr->dbfile, 0, SEEK_CUR);
+ result = read(dbstateptr->dbfile, &entry, sizeof(entry));
+ if ((result != sizeof(entry)) ||
+ (entry.keySeparator != DBKEYSEPARATOR) ||
+ (entry.space != DBBLANKSPACE) ||
+ (entry.terminator != DBRECORDTERMINATOR)) {
+ return -1;
+ };
+
+ memcpy(dbentry, &entry, sizeof(*dbentry));
+ return 0;
+};
+
+
+
+static int CompareVSDBKeys(struct VSDBKey *key1, struct VSDBKey *key2) {
+ return memcmp(key1->uuidString, key2->uuidString, sizeof(key1->uuidString));
+}
+
+
+
+/******************************************************************************
+ *
+ * F O R M A T T I N G A N D C O N V E R S I O N R O U T I N E S
+ *
+ *****************************************************************************/
+
+static void FormatULong(u_int32_t u, char *s) {
+ u_int32_t d;
+ int i;
+ char *digitptr = s;
+
+ for (i = 0; i < 8; ++i) {
+ d = ((u & 0xF0000000) >> 28) & 0x0000000F;
+ if (d < 10) {
+ *digitptr++ = (char)(d + '0');
+ } else {
+ *digitptr++ = (char)(d - 10 + 'A');
+ };
+ u = u << 4;
+ };
+}
+
+
+
+static void FormatDBKey(VolumeUUID *volumeID, struct VSDBKey *dbkey) {
+ uuid_string_t uuid_str;
+
+ uuid_unparse(volumeID->uuid, uuid_str);
+ memcpy(dbkey->uuidString, uuid_str, sizeof(dbkey->uuidString));
+}
+
+
+
+static void FormatDBRecord(u_int32_t volumeStatusFlags, struct VSDBRecord *dbrecord) {
+ FormatULong(volumeStatusFlags, dbrecord->statusFlags);
+}
+
+
+
+static void FormatDBEntry(VolumeUUID *volumeID, u_int32_t volumeStatusFlags, struct VSDBEntry *dbentry) {
+ FormatDBKey(volumeID, &dbentry->key);
+ dbentry->keySeparator = DBKEYSEPARATOR;
+ dbentry->space = DBBLANKSPACE;
+ FormatDBRecord(volumeStatusFlags, &dbentry->record);
+ dbentry->terminator = DBRECORDTERMINATOR;
+}
+
+
+
+static u_int32_t ConvertHexStringToULong(const char *hs, long maxdigits) {
+ int i;
+ char c;
+ u_int32_t nextdigit;
+ u_int32_t n;
+
+ n = 0;
+ for (i = 0; (i < 8) && ((c = hs[i]) != (char)0) ; ++i) {
+ if ((c >= '0') && (c <= '9')) {
+ nextdigit = c - '0';
+ } else if ((c >= 'A') && (c <= 'F')) {
+ nextdigit = c - 'A' + 10;
+ } else if ((c >= 'a') && (c <= 'f')) {
+ nextdigit = c - 'a' + 10;
+ } else {
+ nextdigit = 0;
+ };
+ n = (n << 4) + nextdigit;
+ };
+
+ return n;
+}