diff options
author | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
---|---|---|
committer | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
commit | 5fd83771641d15c418f747bd343ba6738d3875f7 (patch) | |
tree | 5abf0f78f680d9837dbd93d4d4c3933bb7509599 /diskdev_cmds | |
download | apple_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')
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, §or_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, §or_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 = ∂ + 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 = ∂ + 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; +} |