···11+/*
22+ * Copyright (c) 2008-2009,2011 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+//
2424+// ExtentManager.cpp
2525+//
2626+2727+#include "ExtentManager.h"
2828+2929+void
3030+ExtentManager::Init(uint32_t theBlockSize, uint32_t theNativeBlockSize, off_t theTotalBytes)
3131+{
3232+ blockSize = theBlockSize;
3333+ nativeBlockSize = theNativeBlockSize;
3434+ totalBytes = theTotalBytes;
3535+ totalBlocks = howmany(totalBytes, blockSize);
3636+3737+ // add sentry empty extents at both sides so empty partition doesn't need to be handled specially
3838+ AddBlockRangeExtent(0, 0);
3939+ AddBlockRangeExtent(totalBlocks, 0);
4040+}
4141+4242+void
4343+ExtentManager::MergeExtent(const ExtentInfo &a, const ExtentInfo &b, ExtentInfo *c)
4444+{
4545+ // merge ext into *curIt
4646+ c->blockAddr = min(a.blockAddr, b.blockAddr);
4747+ c->numBlocks = max(a.blockAddr + a.numBlocks, b.blockAddr + b.numBlocks) - c->blockAddr;
4848+}
4949+5050+void
5151+ExtentManager::AddBlockRangeExtent(off_t blockAddr, off_t numBlocks)
5252+{
5353+ struct ExtentInfo ext, newExt;
5454+ ListExtIt curIt, newIt;
5555+ bool merged = false;
5656+5757+ // make the range a valid range
5858+ if ((blockAddr > totalBlocks) || (blockAddr + numBlocks < 0)) { // totally out of range, do nothing
5959+ return;
6060+ }
6161+ if (blockAddr < 0) {
6262+ numBlocks = blockAddr + numBlocks;
6363+ blockAddr = 0;
6464+ }
6565+ if (blockAddr + numBlocks > totalBlocks) {
6666+ numBlocks = totalBlocks - blockAddr;
6767+ }
6868+6969+ ext.blockAddr = blockAddr;
7070+ ext.numBlocks = numBlocks;
7171+7272+ for (curIt = extentList.begin(); curIt != extentList.end(); curIt++) {
7373+ if (BeforeExtent(ext, *curIt))
7474+ break;
7575+ if (!BeforeExtent(*curIt, ext)) { // overlapped extents
7676+ MergeExtent(ext, *curIt, &newExt);
7777+ *curIt = newExt;
7878+ merged = true;
7979+ break;
8080+ }
8181+ }
8282+8383+ // insert ext before curIt
8484+ if (!merged) {
8585+ curIt = extentList.insert(curIt, ext); // throws bad_alloc when out of memory
8686+ }
8787+8888+ // merge the extents
8989+ newIt = curIt;
9090+ curIt = extentList.begin();
9191+ while (curIt != extentList.end()) {
9292+ if (curIt == newIt || BeforeExtent(*curIt, *newIt)) { // curIt is before newIt
9393+ curIt++;
9494+ continue;
9595+ }
9696+ if (BeforeExtent(*newIt, *curIt)) { // curIt is after newIt now, we are done
9797+ break;
9898+ }
9999+ // merge the two extents
100100+ MergeExtent(*curIt, *newIt, &newExt);
101101+ *newIt = newExt;
102102+ curIt = extentList.erase(curIt);
103103+ }
104104+ // printf("After %s(%lld, %lld)\n", __func__, blockAddr, numBlocks); DebugPrint();
105105+} // ExtentManager::AddBlockRangeExtent
106106+107107+void
108108+ExtentManager::RemoveBlockRangeExtent(off_t blockAddr, off_t numBlocks)
109109+{
110110+ struct ExtentInfo ext, newExt;
111111+ ListExtIt curIt;
112112+113113+ ext.blockAddr = blockAddr;
114114+ ext.numBlocks = numBlocks;
115115+116116+ curIt = extentList.begin();
117117+ while (curIt != extentList.end()) {
118118+ if (BeforeExtent(*curIt, ext)) {
119119+ curIt++;
120120+ continue;
121121+ }
122122+ if (BeforeExtent(ext, *curIt)) // we are done
123123+ break;
124124+125125+ //
126126+ // If we get here, the input extent and *curIt have at least one block in common.
127127+ // That is, they overlap in some way. Thus *curIt needs to change, be removed,
128128+ // or be split into two non-contiguous extents.
129129+ //
130130+131131+ if (curIt->blockAddr >= ext.blockAddr &&
132132+ curIt->blockAddr + curIt->numBlocks <= ext.blockAddr + ext.numBlocks) {
133133+ //
134134+ // The input extent totally contains *curIt, so remove *curIt.
135135+ //
136136+ curIt = extentList.erase(curIt);
137137+ } else if (curIt->blockAddr < ext.blockAddr &&
138138+ curIt->blockAddr + curIt->numBlocks > ext.blockAddr + ext.numBlocks) {
139139+ //
140140+ // The input extent does not include the start of *curIt, nor the end of *curIt,
141141+ // so split *curIt into two extents.
142142+ //
143143+ newExt.blockAddr = ext.blockAddr + ext.numBlocks;
144144+ newExt.numBlocks = curIt->blockAddr + curIt->numBlocks - newExt.blockAddr;
145145+ curIt->numBlocks = ext.blockAddr - curIt->blockAddr;
146146+ curIt++;
147147+ extentList.insert(curIt, newExt); // throws bad_alloc when out of memory
148148+ curIt++;
149149+ } else {
150150+ //
151151+ // The input extent contains either the start or the end of *curIt, but not both.
152152+ // The remove will leave either the end or the start of *curIt (respectively) and
153153+ // not change the number of extents in the list.
154154+ //
155155+ if (curIt->blockAddr >= ext.blockAddr) {
156156+ //
157157+ // Remove the start of *curIt by updating both its starting block and size.
158158+ //
159159+ assert(curIt->blockAddr + curIt->numBlocks > ext.blockAddr + ext.numBlocks);
160160+ newExt.blockAddr = ext.blockAddr + ext.numBlocks;
161161+ newExt.numBlocks = curIt->blockAddr + curIt->numBlocks - newExt.blockAddr;
162162+ *curIt = newExt;
163163+ } else {
164164+ //
165165+ // Remove the end of *curIt by updating its size.
166166+ //
167167+ curIt->numBlocks = ext.blockAddr - curIt->blockAddr;
168168+ }
169169+ curIt++;
170170+ }
171171+ }
172172+ //printf("After %s(%lld, %lld)\n", __func__, blockAddr, numBlocks); DebugPrint();
173173+}
174174+175175+void
176176+ExtentManager::AddByteRangeExtent(off_t byteAddr, off_t numBytes)
177177+{
178178+ off_t blockAddr = byteAddr / blockSize;
179179+ off_t blockAddrOfLastByte = (byteAddr + numBytes - 1) / blockSize;
180180+ off_t numBlocks = blockAddrOfLastByte - blockAddr + 1;
181181+ AddBlockRangeExtent(blockAddr, numBlocks);
182182+}
183183+184184+void
185185+ExtentManager::DebugPrint()
186186+{
187187+ ListExtIt it;
188188+189189+ for (it = extentList.begin(); it != extentList.end(); it++) {
190190+ printf("[%lld, %lld] ", it->blockAddr, it->numBlocks);
191191+ }
192192+ printf("\n");
193193+}
194194+195195+196196+#if UNIT_TEST
197197+198198+/*
199199+clang++ -arch i386 -arch x86_64 -DUNIT_TEST ExtentManager.cpp -o ExtentManager && ./ExtentManager
200200+*/
201201+202202+#include <cstdio>
203203+#include <cstdlib>
204204+205205+const char *DebugDescription(class ExtentManager *extMan)
206206+{
207207+ char *result = strdup("");
208208+ char *temp;
209209+210210+ ListExtIt it;
211211+212212+ for (it = extMan->extentList.begin(); it != extMan->extentList.end(); it++) {
213213+ temp = result;
214214+ asprintf(&result, "%s[%lld, %lld] ", temp, it->blockAddr, it->numBlocks);
215215+ free(temp);
216216+ }
217217+218218+ return result;
219219+}
220220+221221+int SimpleTestCase(off_t addAddr, off_t addBlocks, off_t removeAddr, off_t removeBlocks, const char *expectedResult)
222222+{
223223+ class ExtentManager extMan;
224224+ const char *actualResult;
225225+ int result = 0;
226226+227227+ extMan.Init(512, 512, 512*999);
228228+ extMan.AddBlockRangeExtent(addAddr, addBlocks);
229229+ extMan.RemoveBlockRangeExtent(removeAddr, removeBlocks);
230230+ actualResult = DebugDescription(&extMan);
231231+ if (strcmp(actualResult, expectedResult))
232232+ {
233233+ fprintf(stderr,
234234+ "SimpleTestCase(%lld, %lld, %lld, %lld) failed.\n"
235235+ " Expected result: %s\n"
236236+ " Actual result: %s\n",
237237+ addAddr, addBlocks, removeAddr, removeBlocks,
238238+ expectedResult, actualResult);
239239+ result = 1;
240240+ }
241241+ free((void *)actualResult);
242242+243243+ return result;
244244+}
245245+246246+int main(void)
247247+{
248248+ int failed = 0;
249249+ class ExtentManager *extMan;
250250+251251+ // Create an extent, and remove one contained inside,
252252+ // leaving the start and end of the original extent.
253253+ // Create: [xxxxxxxxxx]
254254+ // Remove: [......]
255255+ failed |= SimpleTestCase(10, 10, 12, 6, "[0, 0] [10, 2] [18, 2] [999, 0] ");
256256+257257+ // Create an extent, and remove the whole extent.
258258+ // Create: [xxxxxxxxxx]
259259+ // Remove: [..........]
260260+ failed |= SimpleTestCase(10, 10, 10, 10, "[0, 0] [999, 0] ");
261261+262262+ // Create an extent, and remove the first part of the extent.
263263+ // Create: [xxxxxxxxxx]
264264+ // Remove: [......]
265265+ failed |= SimpleTestCase(10, 10, 10, 6, "[0, 0] [16, 4] [999, 0] ");
266266+267267+ // Create an extent, and remove the last part of the extent.
268268+ // Create: [xxxxxxxxxx]
269269+ // Remove: [......]
270270+ failed |= SimpleTestCase(10, 10, 14, 6, "[0, 0] [10, 4] [999, 0] ");
271271+272272+ // Create an extent and remove before the start, through the middle.
273273+ // Create: [xxxxxxxxxx]
274274+ // Remove: [..........]
275275+ failed |= SimpleTestCase(10, 10, 6, 10, "[0, 0] [16, 4] [999, 0] ");
276276+277277+ // Create an extent and remove from middle to past the end.
278278+ // Create: [xxxxxxxxxx]
279279+ // Remove: [..........]
280280+ failed |= SimpleTestCase(10, 10, 14, 10, "[0, 0] [10, 4] [999, 0] ");
281281+282282+ // Create an extent and remove from before through past end.
283283+ // Create: [xxxxxxxxxx]
284284+ // Remove: [..............]
285285+ failed |= SimpleTestCase(10, 10, 6, 18, "[0, 0] [999, 0] ");
286286+287287+ // Create an extent and remove purely before the extent.
288288+ // Create: [xxxxxxxxxx]
289289+ // Remove: [...]
290290+ failed |= SimpleTestCase(10, 10, 2, 5, "[0, 0] [10, 10] [999, 0] ");
291291+292292+ // Create an extent and remove purely after the extent.
293293+ // Create: [xxxxxxxxxx]
294294+ // Remove: [...]
295295+ failed |= SimpleTestCase(10, 10, 22, 5, "[0, 0] [10, 10] [999, 0] ");
296296+297297+ if (failed)
298298+ printf("FAIL!\n");
299299+ else
300300+ printf("Success.\n");
301301+302302+ return failed;
303303+}
304304+305305+#endif /* UNIT_TEST */
+74
src/libutil/ExtentManager.h
···11+/*
22+ * Copyright (c) 2008 Computer, Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+//
2424+// ExtentManager.h
2525+//
2626+#ifndef EXTENTMANAGER_H
2727+#define EXTENTMANAGER_H
2828+2929+#include <list>
3030+#include <vector>
3131+#include <algorithm>
3232+#include <sys/types.h>
3333+#include <sys/errno.h>
3434+#include <cstdio>
3535+#include <cassert>
3636+using namespace std;
3737+3838+struct ExtentInfo {
3939+ off_t blockAddr;
4040+ off_t numBlocks;
4141+};
4242+4343+inline bool BeforeExtent(const ExtentInfo &a, const ExtentInfo &b)
4444+{
4545+ return (a.blockAddr + a.numBlocks) < b.blockAddr;
4646+}
4747+4848+typedef list<ExtentInfo>::iterator ListExtIt;
4949+5050+class ExtentManager {
5151+public:
5252+ ExtentManager() : blockSize(0), totalBytes(0), totalBlocks(0) {};
5353+ ~ExtentManager() {};
5454+5555+ void Init(uint32_t theBlockSize, uint32_t theNativeBlockSize, off_t theTotalBytes);
5656+5757+ void AddBlockRangeExtent(off_t blockAddr, off_t numBlocks);
5858+ void AddByteRangeExtent(off_t byteAddr, off_t numBytes);
5959+ void RemoveBlockRangeExtent(off_t blockAddr, off_t numBlocks);
6060+6161+ void DebugPrint();
6262+6363+protected:
6464+ void MergeExtent(const ExtentInfo &a, const ExtentInfo &b, ExtentInfo *c);
6565+6666+public:
6767+ size_t blockSize;
6868+ size_t nativeBlockSize;
6969+ off_t totalBytes;
7070+ off_t totalBlocks;
7171+ list<ExtentInfo> extentList;
7272+};
7373+7474+#endif // #ifndef EXTENTMANAGER_H
+296
src/libutil/getmntopts.3
···11+.\" $NetBSD: getmntopts.3,v 1.12 2010/08/24 12:05:01 christos Exp $
22+.\"
33+.\" Copyright (c) 1994
44+.\" The Regents of the University of California. All rights reserved.
55+.\"
66+.\" Redistribution and use in source and binary forms, with or without
77+.\" modification, are permitted provided that the following conditions
88+.\" are met:
99+.\" 1. Redistributions of source code must retain the above copyright
1010+.\" notice, this list of conditions and the following disclaimer.
1111+.\" 2. Redistributions in binary form must reproduce the above copyright
1212+.\" notice, this list of conditions and the following disclaimer in the
1313+.\" documentation and/or other materials provided with the distribution.
1414+.\" 3. Neither the name of the University nor the names of its contributors
1515+.\" may be used to endorse or promote products derived from this software
1616+.\" without specific prior written permission.
1717+.\"
1818+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1919+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2020+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2121+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2222+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2323+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2424+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2525+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2626+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2727+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2828+.\" SUCH DAMAGE.
2929+.\"
3030+.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95
3131+.\"
3232+.Dd May 4, 2010
3333+.Dt GETMNTOPTS 3
3434+.Os
3535+.Sh NAME
3636+.Nm getmntopts
3737+.Nd scan mount options
3838+.Sh LIBRARY
3939+.Lb libutil
4040+.Sh SYNOPSIS
4141+.In mntopts.h
4242+.Ft mntoptparse_t
4343+.Fn getmntopts "const char *options" "const struct mntopt *mopts" "int *flagp" "int *altflagp"
4444+.Ft const char *
4545+.Fn getmntoptstr "mntoptparse_t mp" "const char *opt"
4646+.Ft long
4747+.Fn getmntoptnum "mntoptparse_t mp" "const char *opt"
4848+.Ft void
4949+.Fn freemntopts "mntoptparse_t mp"
5050+.Sh DESCRIPTION
5151+The
5252+.Fn getmntopts
5353+function takes a comma separated option list and a list
5454+of valid option names, and computes the bitmasks
5555+corresponding to the requested set of options.
5656+.Pp
5757+The string
5858+.Ar options
5959+is broken down into a sequence of comma separated tokens.
6060+Each token is looked up in the table described by
6161+.Ar mopts
6262+and the bits in
6363+the word referenced by either
6464+.Ar flagp
6565+or
6666+.Ar altflagp
6767+(depending on the
6868+.Dv m_altloc
6969+field of the option's table entry)
7070+are updated.
7171+The flag words are not initialized by
7272+.Fn getmntopts .
7373+The table,
7474+.Ar mopts ,
7575+has the following format:
7676+.Bd -literal
7777+struct mntopt {
7878+ const char *m_option; /* option name */
7979+ int m_inverse; /* negative option, e.g., "dev" */
8080+ int m_flag; /* bit to set, e.g., MNT_RDONLY */
8181+ int m_altloc; /* use altflagp rather than flagp */
8282+};
8383+.Ed
8484+.Pp
8585+The members of this structure are:
8686+.Bl -tag -width m_inverse
8787+.It Fa m_option
8888+the option name,
8989+for example
9090+.Dq suid .
9191+.It Fa m_inverse
9292+tells
9393+.Fn getmntopts
9494+that the name has the inverse meaning of the bit.
9595+For example,
9696+.Dq suid
9797+is the string, whereas the mount flag is
9898+.Dv MNT_NOSUID .
9999+In this case, the sense of the string and the flag
100100+are inverted, so the
101101+.Fa m_inverse
102102+flag should be set.
103103+.It Fa m_flag
104104+the value of the bit to be set or cleared in
105105+the flag word when the option is recognized.
106106+The bit is set when the option is discovered,
107107+but cleared if the option name was preceded
108108+by the letters
109109+.Dq no .
110110+The
111111+.Fa m_inverse
112112+flag causes these two operations to be reversed.
113113+.It Fa m_altloc
114114+the bit should be set or cleared in
115115+.Ar altflagp
116116+rather than
117117+.Ar flagp .
118118+.El
119119+.Pp
120120+Each of the user visible
121121+.Dv MNT_
122122+flags has a corresponding
123123+.Dv MOPT_
124124+macro which defines an appropriate
125125+.Li "struct mntopt"
126126+entry.
127127+To simplify the program interface and ensure consistency across all
128128+programs, a general purpose macro,
129129+.Dv MOPT_STDOPTS ,
130130+is defined which contains an entry for all the generic VFS options:
131131+.Bd -literal -offset indent
132132+MOPT_USERQUOTA,
133133+MOPT_GROUPQUOTA,
134134+MOPT_FSTAB_COMPAT,
135135+MOPT_NODEV,
136136+MOPT_NOEXEC,
137137+MOPT_NOSUID,
138138+MOPT_RDONLY,
139139+MOPT_UNION,
140140+MOPT_BROWSE,
141141+MOPT_AUTOMOUNTED,
142142+MOPT_DEFWRITE,
143143+MOPT_NOATIME,
144144+MOPT_PERMISSIONS,
145145+MOPT_IGNORE_OWNERSHIP,
146146+MOPT_QUARANTINE,
147147+MOPT_CPROTECT
148148+.Ed
149149+.Pp
150150+In addition, the macros
151151+.Dv MOPT_FORCE
152152+and
153153+.Dv MOPT_UPDATE
154154+exist to enable the
155155+.Dv MNT_FORCE
156156+and
157157+.Dv MNT_UPDATE
158158+flags to be set.
159159+Finally, the table must be terminated by an entry with a
160160+.Dv NULL
161161+first element.
162162+.Pp
163163+.Fn getmntopts
164164+returns a
165165+.Li "mntoptparse_t"
166166+handle that can be used in subsequent
167167+.Fn getmntoptstr
168168+and
169169+.Fn getmntoptnum
170170+calls to fetch a value for an option and that must be freed with a call
171171+to
172172+.Fn freemntopts .
173173+If an error occurred, then if the external integer value
174174+.Va getmnt_silent
175175+is zero then
176176+.Fn getmntopts
177177+prints an error message and exits;
178178+if
179179+.Va getmnt_silent
180180+is non-zero then
181181+.Fn getmntopts
182182+returns
183183+.Dv NULL .
184184+.Pp
185185+The
186186+.Fn getmntoptstr
187187+function returns the string value of the named option, if such a value
188188+was set in the option string.
189189+If the value was not set, then if the external integer value
190190+.Va getmnt_silent
191191+is zero then
192192+.Fn getmntoptstr
193193+prints an error message and exits;
194194+if
195195+.Va getmnt_silent
196196+is non-zero then
197197+.Fn getmntoptstr
198198+returns
199199+.Dv NULL .
200200+.Pp
201201+The
202202+.Fn getmntoptnum
203203+returns the long value of the named option, if such a value was set in the
204204+option string.
205205+If the value was not set, or could not be converted from a string to a
206206+long, then if the external integer value
207207+.Va getmnt_silent
208208+is zero then
209209+.Fn getmntoptnum
210210+prints an error message and exits;
211211+if
212212+.Va getmnt_silent
213213+is non-zero then
214214+.Fn getmntoptnum
215215+returns \-1.
216216+.Pp
217217+The
218218+.Fn freemntopts
219219+frees the storage used by
220220+.Fn getmntopts .
221221+.Sh RETURN VALUES
222222+.Fn getmntopts
223223+returns
224224+.Dv NULL
225225+if an error occurred.
226226+Note that some bits may already have been set in
227227+.Va flagp
228228+and
229229+.Va altflagp
230230+even if
231231+.Dv NULL
232232+is returned.
233233+.Fn getmntoptstr
234234+returns
235235+.Dv NULL
236236+if an error occurred.
237237+.Fn getmntoptnum
238238+returns \-1 if an error occurred.
239239+.Sh EXAMPLES
240240+Most commands will use the standard option set.
241241+Local filesystems which support the
242242+.Dv MNT_UPDATE
243243+flag, would also have an
244244+.Dv MOPT_UPDATE
245245+entry.
246246+This can be declared and used as follows:
247247+.Bd -literal -offset indent
248248+#include \*[Lt]mntopts.h\*[Gt]
249249+250250+static const struct mntopt mopts[] = {
251251+ MOPT_STDOPTS,
252252+ MOPT_UPDATE,
253253+ { NULL }
254254+};
255255+256256+\&...
257257+258258+long val;
259259+mntoptparse_t mp;
260260+mntflags = mntaltflags = 0;
261261+262262+\&...
263263+264264+mp = getmntopts(options, mopts, \*[Am]mntflags, \*[Am]mntaltflags);
265265+266266+if (mp == NULL)
267267+ err(EXIT_FAILURE, "getmntopts");
268268+269269+\&...
270270+271271+val = getmntoptnum(mp, "rsize");
272272+freemntopts(mp);
273273+.Ed
274274+.Sh DIAGNOSTICS
275275+If the external integer variable
276276+.Va getmnt_silent
277277+is zero then the
278278+.Fn getmntopts ,
279279+.Fn getmntoptstr ,
280280+and
281281+.Fn getmntoptnum
282282+functions display an error message and exit if an error occurred.
283283+By default
284284+.Va getmnt_silent
285285+is zero.
286286+.Sh SEE ALSO
287287+.Xr err 3 ,
288288+.Xr mount 8
289289+.Sh HISTORY
290290+The
291291+.Fn getmntopts
292292+function appeared in
293293+.Bx 4.4 .
294294+It was moved to the utilities library and enhanced to retrieve option
295295+values in
296296+.Nx 2.0 .
+188
src/libutil/getmntopts.c
···11+/* $NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $ */
22+33+/*-
44+ * Copyright (c) 1994
55+ * The Regents of the University of California. All rights reserved.
66+ *
77+ * Redistribution and use in source and binary forms, with or without
88+ * modification, are permitted provided that the following conditions
99+ * are met:
1010+ * 1. Redistributions of source code must retain the above copyright
1111+ * notice, this list of conditions and the following disclaimer.
1212+ * 2. Redistributions in binary form must reproduce the above copyright
1313+ * notice, this list of conditions and the following disclaimer in the
1414+ * documentation and/or other materials provided with the distribution.
1515+ * 3. Neither the name of the University nor the names of its contributors
1616+ * may be used to endorse or promote products derived from this software
1717+ * without specific prior written permission.
1818+ *
1919+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2020+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2121+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2222+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2323+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2424+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2525+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2626+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2727+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2828+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2929+ * SUCH DAMAGE.
3030+ */
3131+3232+#include <sys/cdefs.h>
3333+#ifndef lint
3434+#if 0
3535+static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
3636+#else
3737+__RCSID("$NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $");
3838+#endif
3939+#endif /* not lint */
4040+4141+#include <sys/param.h>
4242+4343+#include <err.h>
4444+#include <errno.h>
4545+#include <fstab.h>
4646+#include <stdlib.h>
4747+#include <string.h>
4848+4949+#include <mntopts.h>
5050+5151+int getmnt_silent = 0;
5252+5353+static const char errmsg[] = "-o %s: option not supported";
5454+5555+struct mntoptparse {
5656+ const char *options;
5757+ const struct mntopt *mopts;
5858+ char *optbuf;
5959+ char **optarg;
6060+};
6161+6262+const char *
6363+getmntoptstr(mntoptparse_t mp, const char *opt)
6464+{
6565+ const struct mntopt *m;
6666+6767+ for (m = mp->mopts; m->m_option != NULL; m++)
6868+ if (strcasecmp(opt, m->m_option) == 0)
6969+ break;
7070+7171+ if (m->m_option == NULL) {
7272+ if (getmnt_silent == 0)
7373+ errx(1, errmsg, opt);
7474+ else
7575+ return NULL;
7676+ }
7777+7878+ return mp->optarg[m - mp->mopts];
7979+}
8080+8181+long
8282+getmntoptnum(mntoptparse_t mp, const char *opt)
8383+{
8484+ char *ep;
8585+ long rv;
8686+ void (*fun)(int, const char *, ...) = NULL;
8787+ const char *val = getmntoptstr(mp, opt);
8888+8989+ if (val == NULL) {
9090+ if (getmnt_silent == 0)
9191+ errx(1, "Missing %s argument", opt);
9292+ else
9393+ return -1;
9494+ }
9595+9696+ errno = 0;
9797+ rv = strtol(val, &ep, 0);
9898+9999+ if (*ep)
100100+ fun = errx;
101101+102102+ if (errno == ERANGE && (rv == LONG_MAX || rv == LONG_MIN))
103103+ fun = err;
104104+105105+ if (fun) {
106106+ if (getmnt_silent != 0)
107107+ return -1;
108108+ (*fun)(1, "Invalid %s argument `%s'", opt, val);
109109+ }
110110+ return rv;
111111+}
112112+113113+void
114114+freemntopts(mntoptparse_t mp)
115115+{
116116+ free(mp->optbuf);
117117+ free(mp->optarg);
118118+ free(mp);
119119+}
120120+121121+mntoptparse_t
122122+getmntopts(const char *options, const struct mntopt *m0, int *flagp,
123123+ int *altflagp)
124124+{
125125+ const struct mntopt *m;
126126+ int negative;
127127+ char *opt, *p, *ctx = NULL;
128128+ int *thisflagp;
129129+ size_t nopts;
130130+ mntoptparse_t mp;
131131+132132+ for (nopts = 0, m = m0; m->m_option != NULL; ++m, nopts++)
133133+ continue;
134134+135135+ if ((mp = malloc(sizeof(struct mntoptparse))) == NULL)
136136+ return NULL;
137137+138138+ /* Copy option string, since it is about to be torn asunder... */
139139+ if ((mp->optbuf = strdup(options)) == NULL) {
140140+ free(mp);
141141+ return NULL;
142142+ }
143143+144144+ if ((mp->optarg = calloc(nopts, sizeof(char *))) == NULL) {
145145+ free(mp->optbuf);
146146+ free(mp);
147147+ return NULL;
148148+ }
149149+150150+ mp->mopts = m0;
151151+ mp->options = options;
152152+153153+ for (opt = mp->optbuf; (opt = strtok_r(opt, ",", &ctx)) != NULL; opt = NULL) {
154154+ /* Check for "no" prefix. */
155155+ if (opt[0] == 'n' && opt[1] == 'o') {
156156+ negative = 1;
157157+ opt += 2;
158158+ } else
159159+ negative = 0;
160160+161161+ /*
162162+ * for options with assignments in them (ie. quotas)
163163+ * ignore the assignment as it's handled elsewhere
164164+ */
165165+ p = strchr(opt, '=');
166166+ if (p) {
167167+ *p++ = '\0';
168168+ }
169169+170170+ /* Scan option table. */
171171+ for (m = m0; m->m_option != NULL; ++m)
172172+ if (strcasecmp(opt, m->m_option) == 0)
173173+ break;
174174+175175+ /* Save flag, or fail if option is not recognised. */
176176+ if (m->m_option) {
177177+ mp->optarg[m - m0] = p;
178178+ thisflagp = m->m_altloc ? altflagp : flagp;
179179+ if (negative == m->m_inverse)
180180+ *thisflagp |= m->m_flag;
181181+ else
182182+ *thisflagp &= ~m->m_flag;
183183+ } else if (!getmnt_silent) {
184184+ errx(1, errmsg, opt);
185185+ }
186186+ }
187187+ return mp;
188188+}
+148
src/libutil/humanize_number.3
···11+.\" $NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $
22+.\" $FreeBSD: src/lib/libutil/humanize_number.3,v 1.8 2005/04/10 12:15:25 delphij Exp $
33+.\"
44+.\" Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
55+.\" All rights reserved.
66+.\"
77+.\" This code is derived from software contributed to The NetBSD Foundation
88+.\" by Luke Mewburn and by Tomas Svensson.
99+.\"
1010+.\" Redistribution and use in source and binary forms, with or without
1111+.\" modification, are permitted provided that the following conditions
1212+.\" are met:
1313+.\" 1. Redistributions of source code must retain the above copyright
1414+.\" notice, this list of conditions and the following disclaimer.
1515+.\" 2. Redistributions in binary form must reproduce the above copyright
1616+.\" notice, this list of conditions and the following disclaimer in the
1717+.\" documentation and/or other materials provided with the distribution.
1818+.\" 3. All advertising materials mentioning features or use of this software
1919+.\" must display the following acknowledgement:
2020+.\" This product includes software developed by the NetBSD
2121+.\" Foundation, Inc. and its contributors.
2222+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
2323+.\" contributors may be used to endorse or promote products derived
2424+.\" from this software without specific prior written permission.
2525+.\"
2626+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2727+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2828+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2929+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
3030+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3131+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3232+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3333+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3434+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3535+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3636+.\" POSSIBILITY OF SUCH DAMAGE.
3737+.\"
3838+.Dd May 25, 2004
3939+.Dt HUMANIZE_NUMBER 3
4040+.Os
4141+.Sh NAME
4242+.Nm humanize_number
4343+.Nd format a number into a human readable form
4444+.Sh LIBRARY
4545+.Lb libutil
4646+.Sh SYNOPSIS
4747+.In libutil.h
4848+.Ft int
4949+.Fo humanize_number
5050+.Fa "char *buf" "size_t len" "int64_t number" "const char *suffix"
5151+.Fa "int scale" "int flags"
5252+.Fc
5353+.Sh DESCRIPTION
5454+The
5555+.Fn humanize_number
5656+function formats the signed 64-bit quantity given in
5757+.Fa number
5858+into
5959+.Fa buffer .
6060+A space and then
6161+.Fa suffix
6262+is appended to the end.
6363+The buffer pointed to by
6464+.Fa buffer
6565+must be at least
6666+.Fa len
6767+bytes long.
6868+.Pp
6969+If the formatted number (including
7070+.Fa suffix )
7171+would be too long to fit into
7272+.Fa buffer ,
7373+then divide
7474+.Fa number
7575+by 1024 until it will.
7676+In this case, prefix
7777+.Fa suffix
7878+with the appropriate SI designator.
7979+.Pp
8080+The prefixes are:
8181+.Bl -column "Prefix" "Description" "Multiplier" -offset indent
8282+.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
8383+.It Li k Ta No kilo Ta 1024
8484+.It Li M Ta No mega Ta 1048576
8585+.It Li G Ta No giga Ta 1073741824
8686+.It Li T Ta No tera Ta 1099511627776
8787+.It Li P Ta No peta Ta 1125899906842624
8888+.It Li E Ta No exa Ta 1152921504606846976
8989+.El
9090+.Pp
9191+The
9292+.Fa len
9393+argument must be at least 4 plus the length of
9494+.Fa suffix ,
9595+in order to ensure a useful result is generated into
9696+.Fa buffer .
9797+To use a specific prefix, specify this as
9898+.Fa scale
9999+(multiplier = 1024 ^ scale).
100100+This cannot be combined with any of the
101101+.Fa scale
102102+flags below.
103103+.Pp
104104+The following flags may be passed in
105105+.Fa scale :
106106+.Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
107107+.It Dv HN_AUTOSCALE
108108+Format the buffer using the lowest multiplier possible.
109109+.It Dv HN_GETSCALE
110110+Return the prefix index number (the number of times
111111+.Fa number
112112+must be divided to fit) instead of formatting it to the buffer.
113113+.El
114114+.Pp
115115+The following flags may be passed in
116116+.Fa flags :
117117+.Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
118118+.It Dv HN_DECIMAL
119119+If the final result is less than 10, display it using one digit.
120120+.It Dv HN_NOSPACE
121121+Do not put a space between
122122+.Fa number
123123+and the prefix.
124124+.It Dv HN_B
125125+Use
126126+.Ql B
127127+(bytes) as prefix if the original result does not have a prefix.
128128+.It Dv HN_DIVISOR_1000
129129+Divide
130130+.Fa number
131131+with 1000 instead of 1024.
132132+.El
133133+.Sh RETURN VALUES
134134+The
135135+.Fn humanize_number
136136+function returns the number of characters stored in
137137+.Fa buffer
138138+(excluding the terminating
139139+.Dv NUL )
140140+upon success, or \-1 upon failure.
141141+If
142142+.Dv HN_GETSCALE
143143+is specified, the prefix index number will be returned instead.
144144+.Sh HISTORY
145145+The
146146+.Fn humanize_number
147147+function first appeared in
148148+.Nx 2.0 .
+159
src/libutil/humanize_number.c
···11+/* $NetBSD: humanize_number.c,v 1.8 2004/07/27 01:56:24 enami Exp $ */
22+33+/*
44+ * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
55+ * All rights reserved.
66+ *
77+ * This code is derived from software contributed to The NetBSD Foundation
88+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
99+ * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
1010+ *
1111+ * Redistribution and use in source and binary forms, with or without
1212+ * modification, are permitted provided that the following conditions
1313+ * are met:
1414+ * 1. Redistributions of source code must retain the above copyright
1515+ * notice, this list of conditions and the following disclaimer.
1616+ * 2. Redistributions in binary form must reproduce the above copyright
1717+ * notice, this list of conditions and the following disclaimer in the
1818+ * documentation and/or other materials provided with the distribution.
1919+ * 3. All advertising materials mentioning features or use of this software
2020+ * must display the following acknowledgement:
2121+ * This product includes software developed by the NetBSD
2222+ * Foundation, Inc. and its contributors.
2323+ * 4. Neither the name of The NetBSD Foundation nor the names of its
2424+ * contributors may be used to endorse or promote products derived
2525+ * from this software without specific prior written permission.
2626+ *
2727+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2828+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2929+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3030+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
3131+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3232+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3333+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3434+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3535+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3636+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3737+ * POSSIBILITY OF SUCH DAMAGE.
3838+ */
3939+4040+#include <sys/cdefs.h>
4141+4242+#include <sys/types.h>
4343+#include <assert.h>
4444+#include <stdio.h>
4545+#include <stdlib.h>
4646+#include <string.h>
4747+#include <locale.h>
4848+#include <libutil.h>
4949+#include <stdint.h>
5050+#include <limits.h>
5151+5252+int
5353+humanize_number(char *buf, size_t len, int64_t bytes,
5454+ const char *suffix, int scale, int flags)
5555+{
5656+ const char *prefixes, *sep;
5757+ int b, i, r, maxscale, s1, s2, sign;
5858+ int64_t divisor, max;
5959+ // We multiply bytes by 100 to deal with rounding, so we need something
6060+ // big enough to hold LLONG_MAX * 100. On 64-bit we can use 128-bit wide
6161+ // integers with __int128_t, but on 32-bit we have to use long double.
6262+#ifdef __LP64__
6363+ __int128_t scalable = (__int128_t)bytes;
6464+#else
6565+ long double scalable = (long double)bytes;
6666+#endif
6767+ size_t baselen;
6868+6969+ assert(buf != NULL);
7070+ assert(suffix != NULL);
7171+ assert(scale >= 0);
7272+7373+ if (flags & HN_DIVISOR_1000) {
7474+ /* SI for decimal multiplies */
7575+ divisor = 1000;
7676+ if (flags & HN_B)
7777+ prefixes = "B\0k\0M\0G\0T\0P\0E";
7878+ else
7979+ prefixes = "\0\0k\0M\0G\0T\0P\0E";
8080+ } else {
8181+ /*
8282+ * binary multiplies
8383+ * XXX IEC 60027-2 recommends Ki, Mi, Gi...
8484+ */
8585+ divisor = 1024;
8686+ if (flags & HN_B)
8787+ prefixes = "B\0K\0M\0G\0T\0P\0E";
8888+ else
8989+ prefixes = "\0\0K\0M\0G\0T\0P\0E";
9090+ }
9191+9292+#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1])
9393+ maxscale = 7;
9494+9595+ if (scale >= maxscale &&
9696+ (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
9797+ return (-1);
9898+9999+ if (buf == NULL || suffix == NULL)
100100+ return (-1);
101101+102102+ if (len > 0)
103103+ buf[0] = '\0';
104104+ if (bytes < 0) {
105105+ sign = -1;
106106+ scalable *= -100;
107107+ baselen = 3; /* sign, digit, prefix */
108108+ } else {
109109+ sign = 1;
110110+ scalable *= 100;
111111+ baselen = 2; /* digit, prefix */
112112+ }
113113+ if (flags & HN_NOSPACE)
114114+ sep = "";
115115+ else {
116116+ sep = " ";
117117+ baselen++;
118118+ }
119119+ baselen += strlen(suffix);
120120+121121+ /* Check if enough room for `x y' + suffix + `\0' */
122122+ if (len < baselen + 1)
123123+ return (-1);
124124+125125+ if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
126126+ /* See if there is additional columns can be used. */
127127+ for (max = 100, i = len - baselen; i-- > 0;)
128128+ max *= 10;
129129+130130+ for (i = 0; scalable >= max && i < maxscale; i++)
131131+ scalable /= divisor;
132132+133133+ if (scale & HN_GETSCALE)
134134+ return (i);
135135+ } else
136136+ for (i = 0; i < scale && i < maxscale; i++)
137137+ scalable /= divisor;
138138+139139+ /* If a value <= 9.9 after rounding and ... */
140140+ if (scalable < 995 && i > 0 && flags & HN_DECIMAL) {
141141+ /* baselen + \0 + .N */
142142+ if (len < baselen + 1 + 2)
143143+ return (-1);
144144+ b = ((int)scalable + 5) / 10;
145145+ s1 = b / 10;
146146+ s2 = b % 10;
147147+ r = snprintf(buf, len, "%s%d%s%d%s%s%s",
148148+ ((sign == -1) ? "-" : ""),
149149+ s1, localeconv()->decimal_point, s2,
150150+ sep, SCALE2PREFIX(i), suffix);
151151+ } else
152152+ r = snprintf(buf, len, "%s%lld%s%s%s",
153153+ /* LONGLONG */
154154+ ((sign == -1) ? "-" : ""),
155155+ (long long)((scalable + 50) / 100),
156156+ sep, SCALE2PREFIX(i), suffix);
157157+158158+ return (r);
159159+}
···11+/*
22+ * Copyright (c) 1996 Peter Wemm <peter@FreeBSD.org>.
33+ * All rights reserved.
44+ * Copyright (c) 2002 Networks Associates Technology, Inc.
55+ * All rights reserved.
66+ *
77+ * Portions of this software were developed for the FreeBSD Project by
88+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
99+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
1010+ * ("CBOSS"), as part of the DARPA CHATS research program.
1111+ *
1212+ * Redistribution and use in source and binary forms, with or without
1313+ * modification, is permitted provided that the following conditions
1414+ * are met:
1515+ * 1. Redistributions of source code must retain the above copyright
1616+ * notice, this list of conditions and the following disclaimer.
1717+ * 2. Redistributions in binary form must reproduce the above copyright
1818+ * notice, this list of conditions and the following disclaimer in the
1919+ * documentation and/or other materials provided with the distribution.
2020+ * 3. The name of the author may not be used to endorse or promote
2121+ * products derived from this software without specific prior written
2222+ * permission.
2323+ *
2424+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2525+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2626+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2727+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2828+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2929+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3030+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3131+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3232+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3333+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3434+ * SUCH DAMAGE.
3535+ *
3636+ * $FreeBSD: src/lib/libutil/libutil.h,v 1.42 2006/02/18 11:25:28 des Exp $
3737+ */
3838+3939+#ifndef _LIBUTIL_H_
4040+#define _LIBUTIL_H_
4141+4242+#include <unistd.h>
4343+#include <stdbool.h>
4444+4545+#ifdef _SYS_PARAM_H_
4646+/* for pidfile.c */
4747+struct pidfh {
4848+ int pf_fd;
4949+ char pf_path[MAXPATHLEN + 1];
5050+ dev_t pf_dev;
5151+ ino_t pf_ino;
5252+};
5353+#endif
5454+5555+struct in_addr;
5656+struct sockaddr;
5757+5858+__BEGIN_DECLS
5959+int humanize_number(char *_buf, size_t _len, int64_t _number,
6060+ const char *_suffix, int _scale, int _flags);
6161+6262+int realhostname(char *host, size_t hsize, const struct in_addr *ip);
6363+int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr,
6464+ int addrlen);
6565+6666+#ifdef _SYS_PARAM_H_
6767+struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
6868+int pidfile_write(struct pidfh *pfh);
6969+int pidfile_close(struct pidfh *pfh);
7070+int pidfile_remove(struct pidfh *pfh);
7171+#endif
7272+7373+int reexec_to_match_kernel(void);
7474+int reexec_to_match_lp64ness(bool isLP64);
7575+7676+__END_DECLS
7777+7878+/* return values from realhostname() */
7979+#define HOSTNAME_FOUND (0)
8080+#define HOSTNAME_INCORRECTNAME (1)
8181+#define HOSTNAME_INVALIDADDR (2)
8282+#define HOSTNAME_INVALIDNAME (3)
8383+8484+/* humanize_number(3) */
8585+#define HN_DECIMAL 0x01
8686+#define HN_NOSPACE 0x02
8787+#define HN_B 0x04
8888+#define HN_DIVISOR_1000 0x08
8989+9090+#define HN_GETSCALE 0x10
9191+#define HN_AUTOSCALE 0x20
9292+9393+#endif /* !_LIBUTIL_H_ */
···11+_secure_path.c:
22+/*-
33+ * Based on code copyright (c) 1995,1997 by
44+ * Berkeley Software Design, Inc.
55+ * All rights reserved.
66+ *
77+ * Redistribution and use in source and binary forms, with or without
88+ * modification, is permitted provided that the following conditions
99+ * are met:
1010+ * 1. Redistributions of source code must retain the above copyright
1111+ * notice immediately at the beginning of the file, without modification,
1212+ * this list of conditions, and the following disclaimer.
1313+ * 2. Redistributions in binary form must reproduce the above copyright
1414+ * notice, this list of conditions and the following disclaimer in the
1515+ * documentation and/or other materials provided with the distribution.
1616+ * 3. This work was done expressly for inclusion into FreeBSD. Other use
1717+ * is permitted provided this notation is included.
1818+ * 4. Absolutely no warranty of function or purpose is made by the authors.
1919+ * 5. Modifications may be freely made to this file providing the above
2020+ * conditions are met.
2121+ */
2222+2323+fparseln.c:
2424+/*
2525+ * Copyright (c) 1997 Christos Zoulas. All rights reserved.
2626+ *
2727+ * Redistribution and use in source and binary forms, with or without
2828+ * modification, are permitted provided that the following conditions
2929+ * are met:
3030+ * 1. Redistributions of source code must retain the above copyright
3131+ * notice, this list of conditions and the following disclaimer.
3232+ * 2. Redistributions in binary form must reproduce the above copyright
3333+ * notice, this list of conditions and the following disclaimer in the
3434+ * documentation and/or other materials provided with the distribution.
3535+ * 3. All advertising materials mentioning features or use of this software
3636+ * must display the following acknowledgement:
3737+ * This product includes software developed by Christos Zoulas.
3838+ * 4. The name of the author may not be used to endorse or promote products
3939+ * derived from this software without specific prior written permission.
4040+ *
4141+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4242+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4343+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4444+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4545+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4646+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4747+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4848+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4949+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5050+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5151+ */
5252+5353+humanize_number.c:
5454+/*
5555+ * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
5656+ * All rights reserved.
5757+ *
5858+ * This code is derived from software contributed to The NetBSD Foundation
5959+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
6060+ * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
6161+ *
6262+ * Redistribution and use in source and binary forms, with or without
6363+ * modification, are permitted provided that the following conditions
6464+ * are met:
6565+ * 1. Redistributions of source code must retain the above copyright
6666+ * notice, this list of conditions and the following disclaimer.
6767+ * 2. Redistributions in binary form must reproduce the above copyright
6868+ * notice, this list of conditions and the following disclaimer in the
6969+ * documentation and/or other materials provided with the distribution.
7070+ * 3. All advertising materials mentioning features or use of this software
7171+ * must display the following acknowledgement:
7272+ * This product includes software developed by the NetBSD
7373+ * Foundation, Inc. and its contributors.
7474+ * 4. Neither the name of The NetBSD Foundation nor the names of its
7575+ * contributors may be used to endorse or promote products derived
7676+ * from this software without specific prior written permission.
7777+ *
7878+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
7979+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
8080+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
8181+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
8282+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
8383+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
8484+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
8585+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
8686+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
8787+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8888+ * POSSIBILITY OF SUCH DAMAGE.
8989+ */
9090+9191+pidfile.c:
9292+/*-
9393+ * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
9494+ * All rights reserved.
9595+ *
9696+ * Redistribution and use in source and binary forms, with or without
9797+ * modification, are permitted provided that the following conditions
9898+ * are met:
9999+ * 1. Redistributions of source code must retain the above copyright
100100+ * notice, this list of conditions and the following disclaimer.
101101+ * 2. Redistributions in binary form must reproduce the above copyright
102102+ * notice, this list of conditions and the following disclaimer in the
103103+ * documentation and/or other materials provided with the distribution.
104104+ *
105105+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
106106+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
107107+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
108108+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
109109+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
110110+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
111111+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
112112+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
113113+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
114114+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
115115+ * SUCH DAMAGE.
116116+ */
117117+118118+property.c:
119119+/*
120120+ *
121121+ * Simple property list handling code.
122122+ *
123123+ * Copyright (c) 1998
124124+ * Jordan "Perky" Hubbard. All rights reserved.
125125+ *
126126+ * Redistribution and use in source and binary forms, with or without
127127+ * modification, are permitted provided that the following conditions
128128+ * are met:
129129+ * 1. Redistributions of source code must retain the above copyright
130130+ * notice, this list of conditions and the following disclaimer,
131131+ * verbatim and that no modifications are made prior to this
132132+ * point in the file.
133133+ * 2. Redistributions in binary form must reproduce the above copyright
134134+ * notice, this list of conditions and the following disclaimer in the
135135+ * documentation and/or other materials provided with the distribution.
136136+ *
137137+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
138138+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
139139+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
140140+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
141141+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
142142+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
143143+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
144144+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
145145+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
146146+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
147147+ * SUCH DAMAGE.
148148+ */
149149+150150+realhostname.c:
151151+/*-
152152+ * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
153153+ * All rights reserved.
154154+ *
155155+ * Redistribution and use in source and binary forms, with or without
156156+ * modification, are permitted provided that the following conditions
157157+ * are met:
158158+ * 1. Redistributions of source code must retain the above copyright
159159+ * notice, this list of conditions and the following disclaimer.
160160+ * 2. Redistributions in binary form must reproduce the above copyright
161161+ * notice, this list of conditions and the following disclaimer in the
162162+ * documentation and/or other materials provided with the distribution.
163163+ *
164164+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
165165+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166166+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
167167+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
168168+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
169169+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
170170+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
171171+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
172172+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
173173+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
174174+ * SUCH DAMAGE.
175175+ */
176176+177177+trimdomain.c:
178178+/*-
179179+ * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
180180+ * Based on original work by Atsushi Murai <amurai@FreeBSD.org>
181181+ * All rights reserved.
182182+ *
183183+ * Redistribution and use in source and binary forms, with or without
184184+ * modification, are permitted provided that the following conditions
185185+ * are met:
186186+ * 1. Redistributions of source code must retain the above copyright
187187+ * notice, this list of conditions and the following disclaimer.
188188+ * 2. Redistributions in binary form must reproduce the above copyright
189189+ * notice, this list of conditions and the following disclaimer in the
190190+ * documentation and/or other materials provided with the distribution.
191191+ *
192192+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
193193+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
194194+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
195195+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
196196+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
197197+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
198198+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
199199+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
200200+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
201201+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
202202+ * SUCH DAMAGE.
203203+ *
204204+ */
205205+206206+uucplock.c:
207207+/*
208208+ * Copyright (c) 1988, 1993
209209+ * The Regents of the University of California. All rights reserved.
210210+ *
211211+ * Redistribution and use in source and binary forms, with or without
212212+ * modification, are permitted provided that the following conditions
213213+ * are met:
214214+ * 1. Redistributions of source code must retain the above copyright
215215+ * notice, this list of conditions and the following disclaimer.
216216+ * 2. Redistributions in binary form must reproduce the above copyright
217217+ * notice, this list of conditions and the following disclaimer in the
218218+ * documentation and/or other materials provided with the distribution.
219219+ * 3. All advertising materials mentioning features or use of this software
220220+ * must display the following acknowledgement:
221221+ * This product includes software developed by the University of
222222+ * California, Berkeley and its contributors.
223223+ * 4. Neither the name of the University nor the names of its contributors
224224+ * may be used to endorse or promote products derived from this software
225225+ * without specific prior written permission.
226226+ *
227227+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228228+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229229+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
230230+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
231231+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
232232+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
233233+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
234234+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
235235+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
236236+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
237237+ * SUCH DAMAGE.
238238+ */
···11+/*
22+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+/* $NetBSD: mntopts.h,v 1.7 2006/02/12 01:32:06 chs Exp $ */
2525+2626+/*-
2727+ * Copyright (c) 1994
2828+ * The Regents of the University of California. All rights reserved.
2929+ *
3030+ * Redistribution and use in source and binary forms, with or without
3131+ * modification, are permitted provided that the following conditions
3232+ * are met:
3333+ * 1. Redistributions of source code must retain the above copyright
3434+ * notice, this list of conditions and the following disclaimer.
3535+ * 2. Redistributions in binary form must reproduce the above copyright
3636+ * notice, this list of conditions and the following disclaimer in the
3737+ * documentation and/or other materials provided with the distribution.
3838+ * 3. Neither the name of the University nor the names of its contributors
3939+ * may be used to endorse or promote products derived from this software
4040+ * without specific prior written permission.
4141+ *
4242+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4343+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4444+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4545+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4646+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4747+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4848+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4949+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5050+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5151+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5252+ * SUCH DAMAGE.
5353+ *
5454+ * @(#)mntopts.h 8.7 (Berkeley) 3/29/95
5555+ */
5656+#ifndef _MNTOPTS_H_
5757+#define _MNTOPTS_H_
5858+5959+#ifdef __cplusplus
6060+extern "C" {
6161+#endif
6262+6363+struct mntopt {
6464+ const char *m_option; /* option name */
6565+ int m_inverse; /* if a negative option, eg "dev" */
6666+ int m_flag; /* bit to set, eg. MNT_RDONLY */
6767+ int m_altloc; /* 1 => set bit in altflags */
6868+};
6969+7070+/* User-visible MNT_ flags. */
7171+#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 }
7272+#define MOPT_NODEV { "dev", 1, MNT_NODEV, 0 }
7373+#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 }
7474+#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 }
7575+#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 }
7676+#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 }
7777+#define MOPT_UNION { "union", 0, MNT_UNION, 0 }
7878+#define MOPT_USERQUOTA { "userquota", 0, 0, 0 }
7979+#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 }
8080+#define MOPT_BROWSE { "browse", 1, MNT_DONTBROWSE, 0 }
8181+#define MOPT_AUTOMOUNTED { "automounted",0, MNT_AUTOMOUNTED, 0 }
8282+#define MOPT_DEFWRITE { "defwrite", 0, MNT_DEFWRITE, 0}
8383+#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0}
8484+#define MOPT_IGNORE_OWNERSHIP { "owners", 1, MNT_IGNORE_OWNERSHIP, 0}
8585+/* alias the deprecated name for compatibility */
8686+#define MOPT_PERMISSIONS { "perm", 1, MNT_IGNORE_OWNERSHIP, 0}
8787+#define MOPT_QUARANTINE { "quarantine", 0, MNT_QUARANTINE, 0}
8888+#define MOPT_CPROTECT { "protect", 0, MNT_CPROTECT, 0 }
8989+9090+/* Control flags. */
9191+#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 }
9292+#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 }
9393+#define MOPT_RELOAD { "reload", 0, MNT_RELOAD, 0 }
9494+9595+/* Support for old-style "ro", "rw" flags. */
9696+#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 }
9797+#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 }
9898+9999+/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */
100100+#define MOPT_AUTO { "auto", 0, 0, 0 }
101101+102102+#define MOPT_FSTAB_COMPAT \
103103+ MOPT_RO, \
104104+ MOPT_RW, \
105105+ MOPT_AUTO
106106+107107+/* Standard options which all mounts can understand. */
108108+#define MOPT_STDOPTS \
109109+ MOPT_USERQUOTA, \
110110+ MOPT_GROUPQUOTA, \
111111+ MOPT_FSTAB_COMPAT, \
112112+ MOPT_NODEV, \
113113+ MOPT_NOEXEC, \
114114+ MOPT_NOSUID, \
115115+ MOPT_RDONLY, \
116116+ MOPT_UNION, \
117117+ MOPT_BROWSE, \
118118+ MOPT_AUTOMOUNTED, \
119119+ MOPT_DEFWRITE, \
120120+ MOPT_NOATIME, \
121121+ MOPT_PERMISSIONS, \
122122+ MOPT_IGNORE_OWNERSHIP, \
123123+ MOPT_QUARANTINE, \
124124+ MOPT_CPROTECT
125125+126126+typedef struct mntoptparse *mntoptparse_t;
127127+mntoptparse_t getmntopts(const char *, const struct mntopt *, int *, int *);
128128+const char *getmntoptstr(mntoptparse_t, const char *);
129129+long getmntoptnum(mntoptparse_t, const char *);
130130+void freemntopts(mntoptparse_t);
131131+132132+extern int getmnt_silent;
133133+134134+#ifdef __cplusplus
135135+}
136136+#endif
137137+138138+#endif /* _MNTOPTS_H_ */
+249
src/libutil/pidfile.3
···11+.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
22+.\" All rights reserved.
33+.\"
44+.\" Redistribution and use in source and binary forms, with or without
55+.\" modification, are permitted provided that the following conditions
66+.\" are met:
77+.\" 1. Redistributions of source code must retain the above copyright
88+.\" notice, this list of conditions and the following disclaimer.
99+.\" 2. Redistributions in binary form must reproduce the above copyright
1010+.\" notice, this list of conditions and the following disclaimer in the
1111+.\" documentation and/or other materials provided with the distribution.
1212+.\"
1313+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1414+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1515+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1616+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
1717+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1818+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1919+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2020+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2121+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2222+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2323+.\" SUCH DAMAGE.
2424+.\"
2525+.\" $FreeBSD: src/lib/libutil/pidfile.3,v 1.5 2006/03/04 15:20:28 keramida Exp $
2626+.\"
2727+.Dd August 22, 2005
2828+.Dt PIDFILE 3
2929+.Os
3030+.Sh NAME
3131+.Nm pidfile_open ,
3232+.Nm pidfile_write ,
3333+.Nm pidfile_close ,
3434+.Nm pidfile_remove
3535+.Nd "library for PID files handling"
3636+.Sh LIBRARY
3737+.Lb libutil
3838+.Sh SYNOPSIS
3939+.In sys/param.h
4040+.In libutil.h
4141+.Ft "struct pidfh *"
4242+.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
4343+.Ft int
4444+.Fn pidfile_write "struct pidfh *pfh"
4545+.Ft int
4646+.Fn pidfile_close "struct pidfh *pfh"
4747+.Ft int
4848+.Fn pidfile_remove "struct pidfh *pfh"
4949+.Sh DESCRIPTION
5050+The
5151+.Nm pidfile
5252+family of functions allows daemons to handle PID files.
5353+It uses
5454+.Xr flock 2
5555+to lock a pidfile and detect already running daemons.
5656+.Pp
5757+The
5858+.Fn pidfile_open
5959+function opens (or creates) a file specified by the
6060+.Fa path
6161+argument and locks it with the
6262+.Xr flock 2
6363+system call.
6464+If a file can not be locked, a PID of an already running daemon is returned in
6565+the
6666+.Fa pidptr
6767+argument (if it is not
6868+.Dv NULL ) .
6969+The function does not write process' PID into the file here, so it can be
7070+used before
7171+.Fn fork Ns ing
7272+and exit with a proper error message when needed.
7373+If the
7474+.Fa path
7575+argument is
7676+.Dv NULL ,
7777+.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
7878+file will be used.
7979+.Pp
8080+The
8181+.Fn pidfile_write
8282+function writes process' PID into a previously opened file.
8383+.Pp
8484+The
8585+.Fn pidfile_close
8686+function closes a pidfile.
8787+It should be used after daemon
8888+.Fn fork Ns s
8989+to start a child process.
9090+.Pp
9191+The
9292+.Fn pidfile_remove
9393+function closes and removes a pidfile.
9494+.Sh RETURN VALUES
9595+The
9696+.Fn pidfile_open
9797+function returns a valid pointer to a
9898+.Vt pidfh
9999+structure on success, or
100100+.Dv NULL
101101+if an error occurs.
102102+If an error occurs,
103103+.Va errno
104104+will be set.
105105+.Rv -std pidfile_write pidfile_close pidfile_remove
106106+.Sh EXAMPLES
107107+The following example shows in which order these functions should be used.
108108+Note that it is safe to pass
109109+.Dv NULL
110110+to
111111+.Fn pidfile_write ,
112112+.Fn pidfile_remove
113113+and
114114+.Fn pidfile_close
115115+functions.
116116+.Bd -literal
117117+struct pidfh *pfh;
118118+pid_t otherpid, childpid;
119119+120120+pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
121121+if (pfh == NULL) {
122122+ if (errno == EEXIST) {
123123+ errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
124124+ (intmax_t)otherpid);
125125+ }
126126+ /* If we cannot create pidfile from other reasons, only warn. */
127127+ warn("Cannot open or create pidfile");
128128+}
129129+130130+if (daemon(0, 0) == -1) {
131131+ warn("Cannot daemonize");
132132+ pidfile_remove(pfh);
133133+ exit(EXIT_FAILURE);
134134+}
135135+136136+pidfile_write(pfh);
137137+138138+for (;;) {
139139+ /* Do work. */
140140+ childpid = fork();
141141+ switch (childpid) {
142142+ case -1:
143143+ syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
144144+ break;
145145+ case 0:
146146+ pidfile_close(pfh);
147147+ /* Do child work. */
148148+ break;
149149+ default:
150150+ syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
151151+ break;
152152+ }
153153+}
154154+155155+pidfile_remove(pfh);
156156+exit(EXIT_SUCCESS);
157157+.Ed
158158+.Sh ERRORS
159159+The
160160+.Fn pidfile_open
161161+function will fail if:
162162+.Bl -tag -width Er
163163+.It Bq Er EEXIST
164164+Some process already holds the lock on the given pidfile, meaning that a
165165+daemon is already running.
166166+.It Bq Er ENAMETOOLONG
167167+Specified pidfile's name is too long.
168168+.It Bq Er EINVAL
169169+Some process already holds the lock on the given pidfile, but PID read
170170+from there is invalid.
171171+.El
172172+.Pp
173173+The
174174+.Fn pidfile_open
175175+function may also fail and set
176176+.Va errno
177177+for any errors specified for the
178178+.Xr fstat 2 ,
179179+.Xr open 2 ,
180180+and
181181+.Xr read 2
182182+calls.
183183+.Pp
184184+The
185185+.Fn pidfile_write
186186+function will fail if:
187187+.Bl -tag -width Er
188188+.It Bq Er EDOOFUS
189189+Improper function use.
190190+Probably called before
191191+.Fn pidfile_open .
192192+.El
193193+.Pp
194194+The
195195+.Fn pidfile_write
196196+function may also fail and set
197197+.Va errno
198198+for any errors specified for the
199199+.Xr fstat 2 ,
200200+.Xr ftruncate 2 ,
201201+and
202202+.Xr write 2
203203+calls.
204204+.Pp
205205+The
206206+.Fn pidfile_close
207207+function may fail and set
208208+.Va errno
209209+for any errors specified for the
210210+.Xr close 2
211211+and
212212+.Xr fstat 2
213213+calls.
214214+.Pp
215215+The
216216+.Fn pidfile_remove
217217+function will fail if:
218218+.Bl -tag -width Er
219219+.It Bq Er EDOOFUS
220220+Improper function use.
221221+Probably called not from the process which made
222222+.Fn pidfile_write .
223223+.El
224224+.Pp
225225+The
226226+.Fn pidfile_remove
227227+function may also fail and set
228228+.Va errno
229229+for any errors specified for the
230230+.Xr close 2 ,
231231+.Xr flock 2 ,
232232+.Xr fstat 2 ,
233233+.Xr write 2 ,
234234+and
235235+.Xr unlink 2
236236+calls.
237237+.Sh SEE ALSO
238238+.Xr flock 2 ,
239239+.Xr open 2 ,
240240+.Xr daemon 3
241241+.Sh AUTHORS
242242+.An -nosplit
243243+The
244244+.Nm pidfile
245245+functionality is based on ideas from
246246+.An John-Mark Gurney Aq jmg@FreeBSD.org .
247247+.Pp
248248+The code and manual page was written by
249249+.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org .
+243
src/libutil/pidfile.c
···11+/*-
22+ * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
33+ * All rights reserved.
44+ *
55+ * Redistribution and use in source and binary forms, with or without
66+ * modification, are permitted provided that the following conditions
77+ * are met:
88+ * 1. Redistributions of source code must retain the above copyright
99+ * notice, this list of conditions and the following disclaimer.
1010+ * 2. Redistributions in binary form must reproduce the above copyright
1111+ * notice, this list of conditions and the following disclaimer in the
1212+ * documentation and/or other materials provided with the distribution.
1313+ *
1414+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1515+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1616+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1717+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
1818+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1919+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2020+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2121+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2222+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2323+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2424+ * SUCH DAMAGE.
2525+ */
2626+2727+#include <sys/cdefs.h>
2828+2929+#include <sys/param.h>
3030+#include <sys/file.h>
3131+#include <sys/stat.h>
3232+3333+#include <stdio.h>
3434+#include <stdlib.h>
3535+#include <unistd.h>
3636+#include <fcntl.h>
3737+#include <string.h>
3838+#include <err.h>
3939+#include <errno.h>
4040+#include <libutil.h>
4141+4242+static int _pidfile_remove(struct pidfh *pfh, int freeit);
4343+4444+static int
4545+pidfile_verify(struct pidfh *pfh)
4646+{
4747+ struct stat sb;
4848+4949+ if (pfh == NULL || pfh->pf_fd == -1)
5050+ return EINVAL;
5151+ /*
5252+ * Check remembered descriptor.
5353+ */
5454+ if (fstat(pfh->pf_fd, &sb) == -1)
5555+ return (errno);
5656+ if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
5757+ return EINVAL;
5858+ return (0);
5959+}
6060+6161+static int
6262+pidfile_read(const char *path, pid_t *pidptr)
6363+{
6464+ char buf[16], *endptr;
6565+ int error, fd, i;
6666+6767+ fd = open(path, O_RDONLY);
6868+ if (fd == -1)
6969+ return (errno);
7070+7171+ i = read(fd, buf, sizeof(buf) - 1);
7272+ error = errno; /* Remember errno in case close() wants to change it. */
7373+ close(fd);
7474+ if (i == -1)
7575+ return (error);
7676+ buf[i] = '\0';
7777+7878+ *pidptr = strtol(buf, &endptr, 10);
7979+ if (endptr != &buf[i])
8080+ return (EINVAL);
8181+8282+ return (0);
8383+}
8484+8585+struct pidfh *
8686+pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
8787+{
8888+ struct pidfh *pfh;
8989+ struct stat sb;
9090+ int error, fd;
9191+9292+ pfh = malloc(sizeof(*pfh));
9393+ if (pfh == NULL)
9494+ return (NULL);
9595+9696+ if (path == NULL) {
9797+ snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid",
9898+ getprogname());
9999+ } else {
100100+ strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path));
101101+ }
102102+ if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) {
103103+ free(pfh);
104104+ errno = ENAMETOOLONG;
105105+ return (NULL);
106106+ }
107107+108108+ /*
109109+ * Open the PID file and obtain exclusive lock.
110110+ * We truncate PID file here only to remove old PID immediatelly,
111111+ * PID file will be truncated again in pidfile_write(), so
112112+ * pidfile_write() can be called multiple times.
113113+ */
114114+ fd = open(pfh->pf_path,
115115+ O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode);
116116+ if (fd == -1) {
117117+ if (errno == EWOULDBLOCK && pidptr != NULL) {
118118+ errno = pidfile_read(pfh->pf_path, pidptr);
119119+ if (errno == 0)
120120+ errno = EEXIST;
121121+ }
122122+ free(pfh);
123123+ return (NULL);
124124+ }
125125+ /*
126126+ * Remember file information, so in pidfile_write() we are sure we write
127127+ * to the proper descriptor.
128128+ */
129129+ if (fstat(fd, &sb) == -1) {
130130+ error = errno;
131131+ unlink(pfh->pf_path);
132132+ close(fd);
133133+ free(pfh);
134134+ errno = error;
135135+ return (NULL);
136136+ }
137137+138138+ pfh->pf_fd = fd;
139139+ pfh->pf_dev = sb.st_dev;
140140+ pfh->pf_ino = sb.st_ino;
141141+142142+ return (pfh);
143143+}
144144+145145+int
146146+pidfile_write(struct pidfh *pfh)
147147+{
148148+ char pidstr[16];
149149+ int error, fd;
150150+151151+ /*
152152+ * Check remembered descriptor, so we don't overwrite some other
153153+ * file if pidfile was closed and descriptor reused.
154154+ */
155155+ errno = pidfile_verify(pfh);
156156+ if (errno != 0) {
157157+ /*
158158+ * Don't close descriptor, because we are not sure if it's ours.
159159+ */
160160+ return (-1);
161161+ }
162162+ fd = pfh->pf_fd;
163163+164164+ /*
165165+ * Truncate PID file, so multiple calls of pidfile_write() are allowed.
166166+ */
167167+ if (ftruncate(fd, 0) == -1) {
168168+ error = errno;
169169+ _pidfile_remove(pfh, 0);
170170+ errno = error;
171171+ return (-1);
172172+ }
173173+174174+ snprintf(pidstr, sizeof(pidstr), "%u", getpid());
175175+ if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
176176+ error = errno;
177177+ _pidfile_remove(pfh, 0);
178178+ errno = error;
179179+ return (-1);
180180+ }
181181+182182+ return (0);
183183+}
184184+185185+int
186186+pidfile_close(struct pidfh *pfh)
187187+{
188188+ int error;
189189+190190+ error = pidfile_verify(pfh);
191191+ if (error != 0) {
192192+ errno = error;
193193+ return (-1);
194194+ }
195195+196196+ if (close(pfh->pf_fd) == -1)
197197+ error = errno;
198198+ free(pfh);
199199+ if (error != 0) {
200200+ errno = error;
201201+ return (-1);
202202+ }
203203+ return (0);
204204+}
205205+206206+static int
207207+_pidfile_remove(struct pidfh *pfh, int freeit)
208208+{
209209+ int error;
210210+211211+ error = pidfile_verify(pfh);
212212+ if (error != 0) {
213213+ errno = error;
214214+ return (-1);
215215+ }
216216+217217+ if (unlink(pfh->pf_path) == -1)
218218+ error = errno;
219219+ if (flock(pfh->pf_fd, LOCK_UN) == -1) {
220220+ if (error == 0)
221221+ error = errno;
222222+ }
223223+ if (close(pfh->pf_fd) == -1) {
224224+ if (error == 0)
225225+ error = errno;
226226+ }
227227+ if (freeit)
228228+ free(pfh);
229229+ else
230230+ pfh->pf_fd = -1;
231231+ if (error != 0) {
232232+ errno = error;
233233+ return (-1);
234234+ }
235235+ return (0);
236236+}
237237+238238+int
239239+pidfile_remove(struct pidfh *pfh)
240240+{
241241+242242+ return (_pidfile_remove(pfh, 1));
243243+}
+105
src/libutil/realhostname.3
···11+.\" Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
22+.\" All rights reserved.
33+.\"
44+.\" Redistribution and use in source and binary forms, with or without
55+.\" modification, are permitted provided that the following conditions
66+.\" are met:
77+.\" 1. Redistributions of source code must retain the above copyright
88+.\" notice, this list of conditions and the following disclaimer.
99+.\" 2. Redistributions in binary form must reproduce the above copyright
1010+.\" notice, this list of conditions and the following disclaimer in the
1111+.\" documentation and/or other materials provided with the distribution.
1212+.\"
1313+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1414+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1515+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1616+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1717+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1818+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1919+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2020+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2121+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2222+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2323+.\" SUCH DAMAGE.
2424+.\"
2525+.\" $FreeBSD: src/lib/libutil/realhostname.3,v 1.10 2005/02/13 22:25:14 ru Exp $
2626+.\"
2727+.Dd April 6, 1999
2828+.Os
2929+.Dt REALHOSTNAME 3
3030+.Sh NAME
3131+.Nm realhostname
3232+.Nd "convert an IP number to the real host name"
3333+.Sh LIBRARY
3434+.Lb libutil
3535+.Sh SYNOPSIS
3636+.In sys/types.h
3737+.In netinet/in.h
3838+.In libutil.h
3939+.Ft int
4040+.Fn realhostname "char *host" "size_t hsize" "const struct in_addr *ip"
4141+.Sh DESCRIPTION
4242+The function
4343+.Fn realhostname
4444+converts
4545+.Ar ip
4646+to the corresponding host name.
4747+This is done by resolving
4848+.Ar ip
4949+to a host name and then ensuring that the host name resolves
5050+back to
5151+.Ar ip .
5252+.Pp
5353+.Ar host
5454+must point to a buffer of at least
5555+.Ar hsize
5656+bytes, and will always be written to by this function.
5757+.Pp
5858+If the name resolution does not work both ways or if the host name is longer
5959+than
6060+.Ar hsize
6161+bytes,
6262+.Xr inet_ntoa 3
6363+is used to convert
6464+.Ar ip
6565+to an ASCII form.
6666+.Pp
6767+If the string written to
6868+.Ar host
6969+is
7070+.Ar hsize
7171+bytes long,
7272+.Ar host
7373+will not be NUL terminated.
7474+.Sh RETURN VALUES
7575+The
7676+.Fn realhostname
7777+function will return one of the following constants which are defined in
7878+.In libutil.h :
7979+.Pp
8080+.Bl -tag -width XXX -offset XXX
8181+.It Li HOSTNAME_FOUND
8282+A valid host name was found.
8383+.It Li HOSTNAME_INCORRECTNAME
8484+A host name was found, but it did not resolve back to the passed
8585+.Ar ip .
8686+.Ar host
8787+now contains the numeric value of
8888+.Ar ip .
8989+.It Li HOSTNAME_INVALIDADDR
9090+.Ar ip
9191+could not be resolved.
9292+.Ar host
9393+now contains the numeric value of
9494+.Ar ip .
9595+.It Li HOSTNAME_INVALIDNAME
9696+A host name was found, but it could not be resolved back to any ip number.
9797+.Ar host
9898+now contains the numeric value of
9999+.Ar ip .
100100+.El
101101+.Sh SEE ALSO
102102+.Xr gethostbyaddr 3 ,
103103+.Xr gethostbyname 3 ,
104104+.Xr inet_ntoa 3 ,
105105+.Xr realhostname_sa 3
+186
src/libutil/realhostname.c
···11+/*-
22+ * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
33+ * All rights reserved.
44+ *
55+ * Redistribution and use in source and binary forms, with or without
66+ * modification, are permitted provided that the following conditions
77+ * are met:
88+ * 1. Redistributions of source code must retain the above copyright
99+ * notice, this list of conditions and the following disclaimer.
1010+ * 2. Redistributions in binary form must reproduce the above copyright
1111+ * notice, this list of conditions and the following disclaimer in the
1212+ * documentation and/or other materials provided with the distribution.
1313+ *
1414+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1515+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1616+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1717+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1818+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1919+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2020+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2121+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2222+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2323+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2424+ * SUCH DAMAGE.
2525+ */
2626+2727+#include <sys/cdefs.h>
2828+2929+#include <sys/param.h>
3030+#include <sys/socket.h>
3131+3232+#include <netdb.h>
3333+#include <netinet/in.h>
3434+#include <arpa/inet.h>
3535+3636+#include <stdio.h>
3737+#include <string.h>
3838+3939+#include "libutil.h"
4040+4141+struct sockinet {
4242+ u_char si_len;
4343+ u_char si_family;
4444+ u_short si_port;
4545+};
4646+4747+void trimdomain(char *_fullhost, size_t _hostsize);
4848+4949+int
5050+realhostname(char *host, size_t hsize, const struct in_addr *ip)
5151+{
5252+ char trimmed[MAXHOSTNAMELEN];
5353+ int result;
5454+ struct hostent *hp;
5555+5656+ result = HOSTNAME_INVALIDADDR;
5757+ hp = gethostbyaddr((const char *)ip, sizeof(*ip), AF_INET);
5858+5959+ if (hp != NULL) {
6060+ strlcpy(trimmed, hp->h_name, sizeof(trimmed));
6161+ trimdomain(trimmed, strlen(trimmed));
6262+ if (strlen(trimmed) <= hsize) {
6363+ char lookup[MAXHOSTNAMELEN];
6464+6565+ strncpy(lookup, hp->h_name, sizeof(lookup) - 1);
6666+ lookup[sizeof(lookup) - 1] = '\0';
6767+ hp = gethostbyname(lookup);
6868+ if (hp == NULL)
6969+ result = HOSTNAME_INVALIDNAME;
7070+ else for (; ; hp->h_addr_list++) {
7171+ if (*hp->h_addr_list == NULL) {
7272+ result = HOSTNAME_INCORRECTNAME;
7373+ break;
7474+ }
7575+ if (!memcmp(*hp->h_addr_list, ip, sizeof(*ip))) {
7676+ strncpy(host, trimmed, hsize);
7777+ return HOSTNAME_FOUND;
7878+ }
7979+ }
8080+ }
8181+ }
8282+8383+ strncpy(host, inet_ntoa(*ip), hsize);
8484+8585+ return result;
8686+}
8787+8888+int
8989+realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen)
9090+{
9191+ int result, error;
9292+ char buf[NI_MAXHOST];
9393+9494+ result = HOSTNAME_INVALIDADDR;
9595+9696+#ifdef INET6
9797+ /* IPv4 mapped IPv6 addr consideraton, specified in rfc2373. */
9898+ if (addr->sa_family == AF_INET6 &&
9999+ addrlen == sizeof(struct sockaddr_in6) &&
100100+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr)) {
101101+ struct sockaddr_in6 *sin6;
102102+103103+ sin6 = (struct sockaddr_in6 *)addr;
104104+105105+ memset(&lsin, 0, sizeof(lsin));
106106+ lsin.sin_len = sizeof(struct sockaddr_in);
107107+ lsin.sin_family = AF_INET;
108108+ lsin.sin_port = sin6->sin6_port;
109109+ memcpy(&lsin.sin_addr, &sin6->sin6_addr.s6_addr[12],
110110+ sizeof(struct in_addr));
111111+ addr = (struct sockaddr *)&lsin;
112112+ addrlen = lsin.sin_len;
113113+ }
114114+#endif
115115+116116+ error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
117117+ NI_NAMEREQD);
118118+ if (error == 0) {
119119+ struct addrinfo hints, *res, *ores;
120120+ struct sockaddr *sa;
121121+122122+ memset(&hints, 0, sizeof(struct addrinfo));
123123+ hints.ai_family = addr->sa_family;
124124+ hints.ai_flags = AI_CANONNAME | AI_PASSIVE;
125125+ hints.ai_socktype = SOCK_STREAM;
126126+127127+ error = getaddrinfo(buf, NULL, &hints, &res);
128128+ if (error) {
129129+ result = HOSTNAME_INVALIDNAME;
130130+ goto numeric;
131131+ }
132132+ for (ores = res; ; res = res->ai_next) {
133133+ if (res == NULL) {
134134+ freeaddrinfo(ores);
135135+ result = HOSTNAME_INCORRECTNAME;
136136+ goto numeric;
137137+ }
138138+ sa = res->ai_addr;
139139+ if (sa == NULL) {
140140+ freeaddrinfo(ores);
141141+ result = HOSTNAME_INCORRECTNAME;
142142+ goto numeric;
143143+ }
144144+ if (sa->sa_len == addrlen &&
145145+ sa->sa_family == addr->sa_family) {
146146+ ((struct sockinet *)sa)->si_port = ((struct sockinet *)addr)->si_port;
147147+#ifdef INET6
148148+ /*
149149+ * XXX: sin6_socpe_id may not been
150150+ * filled by DNS
151151+ */
152152+ if (sa->sa_family == AF_INET6 &&
153153+ ((struct sockaddr_in6 *)sa)->sin6_scope_id == 0)
154154+ ((struct sockaddr_in6 *)sa)->sin6_scope_id = ((struct sockaddr_in6 *)addr)->sin6_scope_id;
155155+#endif
156156+ if (!memcmp(sa, addr, sa->sa_len)) {
157157+ result = HOSTNAME_FOUND;
158158+ if (ores->ai_canonname == NULL) {
159159+ freeaddrinfo(ores);
160160+ goto numeric;
161161+ }
162162+ strlcpy(buf, ores->ai_canonname,
163163+ sizeof(buf));
164164+ trimdomain(buf, hsize);
165165+ if (strlen(buf) > hsize &&
166166+ addr->sa_family == AF_INET) {
167167+ freeaddrinfo(ores);
168168+ goto numeric;
169169+ }
170170+ strncpy(host, buf, hsize);
171171+ break;
172172+ }
173173+ }
174174+ }
175175+ freeaddrinfo(ores);
176176+ } else {
177177+ numeric:
178178+ if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
179179+ NI_NUMERICHOST) == 0)
180180+ strncpy(host, buf, hsize);
181181+ }
182182+183183+ return result;
184184+}
185185+186186+
+133
src/libutil/realhostname_sa.3
···11+.\" Copyright (C) 1995, 1996, 1997, 1998, 1999, and 2000 WIDE Project.
22+.\" All rights reserved.
33+.\"
44+.\" Redistribution and use in source and binary forms, with or without
55+.\" modification, are permitted provided that the following conditions
66+.\" are met:
77+.\" 1. Redistributions of source code must retain the above copyright
88+.\" notice, this list of conditions and the following disclaimer.
99+.\" 2. Redistributions in binary form must reproduce the above copyright
1010+.\" notice, this list of conditions and the following disclaimer in the
1111+.\" documentation and/or other materials provided with the distribution.
1212+.\" 3. Neither the name of the project nor the names of its contributors
1313+.\" may be used to endorse or promote products derived from this software
1414+.\" without specific prior written permission.
1515+.\"
1616+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1717+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1818+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1919+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2020+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2121+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2222+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2323+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2424+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2525+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2626+.\" SUCH DAMAGE.
2727+.\"
2828+.\" Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
2929+.\" All rights reserved.
3030+.\"
3131+.\" Redistribution and use in source and binary forms, with or without
3232+.\" modification, are permitted provided that the following conditions
3333+.\" are met:
3434+.\" 1. Redistributions of source code must retain the above copyright
3535+.\" notice, this list of conditions and the following disclaimer.
3636+.\" 2. Redistributions in binary form must reproduce the above copyright
3737+.\" notice, this list of conditions and the following disclaimer in the
3838+.\" documentation and/or other materials provided with the distribution.
3939+.\"
4040+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4141+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4242+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4343+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4444+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4545+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4646+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4747+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4848+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4949+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5050+.\" SUCH DAMAGE.
5151+.\"
5252+.\" $FreeBSD: src/lib/libutil/realhostname_sa.3,v 1.11 2005/02/13 22:25:14 ru Exp $
5353+.\"
5454+.Dd January 11, 2000
5555+.Os
5656+.Dt REALHOSTNAME_SA 3
5757+.Sh NAME
5858+.Nm realhostname_sa
5959+.Nd "convert a"
6060+.Vt "struct sockaddr"
6161+to the real host name
6262+.Sh LIBRARY
6363+.Lb libutil
6464+.Sh SYNOPSIS
6565+.In sys/types.h
6666+.In netinet/in.h
6767+.In libutil.h
6868+.Ft int
6969+.Fn realhostname_sa "char *host" "size_t hsize" "struct sockaddr *addr" "int addrlen"
7070+.Sh DESCRIPTION
7171+The function
7272+.Fn realhostname_sa
7373+converts
7474+.Ar addr
7575+to the corresponding host name.
7676+This is done by resolving
7777+.Ar addr
7878+to a host name and then ensuring that the host name resolves
7979+back to
8080+.Ar addr .
8181+.Pp
8282+.Ar host
8383+must point to a buffer of at least
8484+.Ar hsize
8585+bytes, and will always be written to by this function.
8686+.Pp
8787+If the name resolution does not work both ways or if the host name is longer
8888+than
8989+.Ar hsize
9090+bytes,
9191+.Xr getnameinfo 3
9292+with NI_NUMERICHOST specified, is used to convert
9393+.Ar addr
9494+to an ASCII form.
9595+.Pp
9696+If the string written to
9797+.Ar host
9898+is
9999+.Ar hsize
100100+bytes long,
101101+.Ar host
102102+will not be NUL terminated.
103103+.Sh RETURN VALUES
104104+The
105105+.Fn realhostname_sa
106106+function will return one of the following constants which are defined in
107107+.In libutil.h :
108108+.Pp
109109+.Bl -tag -width XXX -offset XXX
110110+.It Li HOSTNAME_FOUND
111111+A valid host name was found.
112112+.It Li HOSTNAME_INCORRECTNAME
113113+A host name was found, but it did not resolve back to the passed
114114+.Ar ip .
115115+.Ar host
116116+now contains the numeric value of
117117+.Ar ip .
118118+.It Li HOSTNAME_INVALIDADDR
119119+.Ar ip
120120+could not be resolved.
121121+.Ar host
122122+now contains the numeric value of
123123+.Ar ip .
124124+.It Li HOSTNAME_INVALIDNAME
125125+A host name was found, but it could not be resolved back to any ip number.
126126+.Ar host
127127+now contains the numeric value of
128128+.Ar ip .
129129+.El
130130+.Sh SEE ALSO
131131+.Xr getaddrinfo 3 ,
132132+.Xr getnameinfo 3 ,
133133+.Xr realhostname 3
+50
src/libutil/reexec_to_match_kernel.3
···11+.Dd Apr 14, 2008
22+.Dt REEXEC_TO_MATCH_KERNEL 3
33+.Os "Mac OS X"
44+.Sh NAME
55+.Nm reexec_to_match_kernel
66+.Nd Re-exec the current binary to match the ABI of the running kernel
77+.Sh LIBRARY
88+.Lb libutil
99+.Sh SYNOPSIS
1010+.In libutil.h
1111+.Ft int
1212+.Fo reexec_to_match_kernel
1313+.Fa "void"
1414+.Fc
1515+.Ft int
1616+.Fo reexec_to_match_lp64ness
1717+.Fa "bool isLP64"
1818+.Fc
1919+.Sh DESCRIPTION
2020+The
2121+.Fn reexec_to_match_kernel
2222+function re-executes the current binary to match the ABI of the running kernel.
2323+That is, if the current kernel is a 64-bit Intel kernel, it will attempt to
2424+execute the 64-bit x86_64 userspace slice of the universal binary. The API
2525+intentionally does not take arguments because its use should be transparent
2626+to the program and to the user.
2727+.Pp
2828+The
2929+.Fn reexec_to_match_lp64ness
3030+is coarser-grained, and only attempts to match the word width that is requested.
3131+For example, if the current system defaults to executing the 64-bit x86_64
3232+userspace slice, but the program should instead run in 32-bit i386 mode,
3333+this routine can be used.
3434+.Pp
3535+Both
3636+.Fn reexec_to_match_kernel
3737+and
3838+.Fn reexec_to_match_lp64ness
3939+can each be used exactly once in a program's lifetime. In certain circumstances,
4040+it may even be desirable to use one, and then the other.
4141+.Sh RETURN VALUES
4242+The
4343+.Fn reexec_to_match_kernel
4444+and
4545+.Fn reexec_to_match_lp64ness
4646+functions return 0 if re-execution was not required. It returns -1 and
4747+sets errno if there was an error performing the re-execution, for example
4848+if the binary is not universal, or does not contain a slice to match the running
4949+kernel's ABI. If the function succeeds, control never returns to the caller
5050+and the program starts from main() again.
+215
src/libutil/reexec_to_match_kernel.c
···11+/*
22+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#include <sys/cdefs.h>
2525+2626+#include <spawn.h>
2727+#include <errno.h>
2828+#include <crt_externs.h>
2929+#include <mach/mach.h>
3030+#include <mach-o/loader.h>
3131+#include <mach-o/dyld.h>
3232+#include <sys/sysctl.h>
3333+#include <stdlib.h>
3434+#include <stdio.h>
3535+3636+#include "libutil.h"
3737+3838+static cpu_type_t current_program_arch(void);
3939+static cpu_type_t current_kernel_arch(void);
4040+static int reexec(cpu_type_t cputype, const char *guardenv);
4141+4242+#define kReExecToMatchKernel "REEXEC_TO_MATCH_KERNEL"
4343+#define kReExecToMatchLP64 "REEXEC_TO_MATCH_LP64NESS"
4444+4545+int reexec_to_match_kernel(void)
4646+{
4747+ cpu_type_t kernarch, progarch;
4848+ char *alreadyenv;
4949+5050+ alreadyenv = getenv(kReExecToMatchKernel);
5151+ if (alreadyenv) {
5252+ /* we've done this at least once, assume
5353+ another try won't help */
5454+ return 0;
5555+ }
5656+5757+ kernarch = current_kernel_arch();
5858+ progarch = current_program_arch();
5959+6060+ if (kernarch == 0) {
6161+ /* could not determine kernel arch */
6262+ errno = EINVAL;
6363+ return -1;
6464+ }
6565+6666+ if (kernarch == progarch) {
6767+ /* nothing to do here */
6868+ return 0;
6969+ }
7070+7171+ /* Now we need to re-exec */
7272+ return reexec(kernarch, kReExecToMatchKernel);
7373+}
7474+7575+int reexec_to_match_lp64ness(bool isLP64)
7676+{
7777+ cpu_type_t kernarch, progarch, targetarch;
7878+ char *alreadyenv;
7979+8080+ alreadyenv = getenv(kReExecToMatchLP64);
8181+ if (alreadyenv) {
8282+ /* we've done this at least once, assume
8383+ another try won't help */
8484+ return 0;
8585+ }
8686+8787+ kernarch = current_kernel_arch();
8888+ progarch = current_program_arch();
8989+9090+ if (kernarch == 0) {
9191+ /* could not determine kernel arch */
9292+ errno = EINVAL;
9393+ return -1;
9494+ }
9595+9696+ if (isLP64) {
9797+ targetarch = kernarch | CPU_ARCH_ABI64;
9898+ } else {
9999+ targetarch = kernarch & ~CPU_ARCH_ABI64;
100100+ }
101101+102102+ if (targetarch == progarch) {
103103+ /* nothing to do here */
104104+ return 0;
105105+ }
106106+107107+ /* Now we need to re-exec */
108108+ return reexec(targetarch, kReExecToMatchLP64);
109109+}
110110+111111+static cpu_type_t current_program_arch(void)
112112+{
113113+ cpu_type_t current_arch = (_NSGetMachExecuteHeader())->cputype;
114114+115115+ return current_arch;
116116+}
117117+118118+static cpu_type_t current_kernel_arch(void)
119119+{
120120+ struct host_basic_info hi;
121121+ unsigned int size;
122122+ kern_return_t kret;
123123+ cpu_type_t current_arch;
124124+ int ret, mib[4];
125125+ size_t len;
126126+ struct kinfo_proc kp;
127127+128128+ size = sizeof(hi)/sizeof(int);
129129+ kret = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hi, &size);
130130+ if (kret != KERN_SUCCESS) {
131131+ return 0;
132132+ }
133133+134134+ current_arch = hi.cpu_type;
135135+136136+ /* Now determine if the kernel is running in 64-bit mode */
137137+ mib[0] = CTL_KERN;
138138+ mib[1] = KERN_PROC;
139139+ mib[2] = KERN_PROC_PID;
140140+ mib[3] = 0; /* kernproc, pid 0 */
141141+ len = sizeof(kp);
142142+ ret = sysctl(mib, sizeof(mib)/sizeof(mib[0]), &kp, &len, NULL, 0);
143143+ if (ret == -1) {
144144+ return 0;
145145+ }
146146+147147+ if (kp.kp_proc.p_flag & P_LP64) {
148148+ current_arch |= CPU_ARCH_ABI64;
149149+ }
150150+151151+ return current_arch;
152152+}
153153+154154+static int reexec(cpu_type_t cputype, const char *guardenv)
155155+{
156156+ posix_spawnattr_t attr;
157157+ int ret, envcount;
158158+ size_t copied = 0;
159159+ char **argv, **oldenvp, **newenvp;
160160+ char execpath[MAXPATHLEN+1];
161161+ uint32_t execsize;
162162+ char guardstr[32];
163163+164164+ argv = *_NSGetArgv();
165165+ oldenvp = *_NSGetEnviron();
166166+ for (envcount = 0; oldenvp[envcount]; envcount++);
167167+ // if there are 4 elements and a NULL, envcount will be 4
168168+169169+ newenvp = calloc(envcount+2, sizeof(newenvp[0]));
170170+ for (envcount = 0; oldenvp[envcount]; envcount++) {
171171+ newenvp[envcount] = oldenvp[envcount];
172172+ }
173173+174174+ snprintf(guardstr, sizeof(guardstr), "%s=1", guardenv);
175175+ newenvp[envcount++] = guardstr;
176176+ newenvp[envcount] = NULL;
177177+178178+ execsize = (uint32_t)sizeof(execpath);
179179+ ret = _NSGetExecutablePath(execpath, &execsize);
180180+ if (ret != 0) {
181181+ return -1;
182182+ }
183183+184184+ ret = posix_spawnattr_init(&attr);
185185+ if (ret != 0) {
186186+ return -1;
187187+ }
188188+ ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC);
189189+ if (ret != 0) {
190190+ return -1;
191191+ }
192192+ ret = posix_spawnattr_setbinpref_np(&attr, 1, &cputype, &copied);
193193+ if (ret != 0 || copied != 1) {
194194+ return -1;
195195+ }
196196+197197+#if 0
198198+ fprintf(stderr, "reexec: %s (arch=%d)\n", execpath, cputype);
199199+ for (envcount=0; newenvp[envcount]; envcount++) {
200200+ fprintf(stderr, "env[%d] = %s\n", envcount, newenvp[envcount]);
201201+ }
202202+ for (envcount=0; argv[envcount]; envcount++) {
203203+ fprintf(stderr, "argv[%d] = %s\n", envcount, argv[envcount]);
204204+ }
205205+#endif
206206+207207+ ret = posix_spawn(NULL, execpath, NULL, &attr, argv, newenvp);
208208+ if (ret != 0) {
209209+ errno = ret;
210210+ return -1;
211211+ }
212212+213213+ /* should not be reached */
214214+ return 0;
215215+}
+85
src/libutil/trimdomain.3
···11+.\" Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
22+.\" All rights reserved.
33+.\"
44+.\" Redistribution and use in source and binary forms, with or without
55+.\" modification, are permitted provided that the following conditions
66+.\" are met:
77+.\" 1. Redistributions of source code must retain the above copyright
88+.\" notice, this list of conditions and the following disclaimer.
99+.\" 2. Redistributions in binary form must reproduce the above copyright
1010+.\" notice, this list of conditions and the following disclaimer in the
1111+.\" documentation and/or other materials provided with the distribution.
1212+.\"
1313+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1414+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1515+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1616+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1717+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1818+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1919+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2020+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2121+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2222+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2323+.\" SUCH DAMAGE.
2424+.\"
2525+.\" $FreeBSD: src/lib/libutil/trimdomain.3,v 1.8 2004/07/02 23:52:20 ru Exp $
2626+.\"
2727+.Dd April 7, 1999
2828+.Os
2929+.Dt TRIMDOMAIN 3
3030+.Sh NAME
3131+.Nm trimdomain
3232+.Nd "trim the current domain name from a host name"
3333+.Sh LIBRARY
3434+.Lb libutil
3535+.Sh SYNOPSIS
3636+.In sys/types.h
3737+.In libutil.h
3838+.Ft void
3939+.Fn trimdomain "char *fullhost" "int hostsize"
4040+.Sh DESCRIPTION
4141+The function
4242+.Fn trimdomain
4343+removes the current domain name from the passed
4444+.Ar fullhost
4545+name by writing a
4646+.Dv NUL
4747+character over the first period of the passed name.
4848+The current domain
4949+name is determined by calling
5050+.Xr gethostname 3
5151+and removing everything up to the first period.
5252+The name is determined
5353+the first time this function is called and is cached for future use.
5454+.Pp
5555+The
5656+.Fn trimdomain
5757+function will only trim the domain name if the passed
5858+.Ar fullname
5959+ends with the current domain name and if the length of the resulting host
6060+name does not exceed
6161+.Ar hostsize .
6262+.Pp
6363+If the passed
6464+.Ar fullname
6565+is actually a
6666+.Dv DISPLAY
6767+specification of the form
6868+.Sm off
6969+.Ar host . domain : nn Oo .
7070+.Ar nn
7171+.Oc
7272+.Sm on
7373+and the domain name is the same as the local domain name,
7474+.Fn trimdomain
7575+will remove the embedded domain name, copying the screen and display
7676+numbers to the end of the base host name and resulting in
7777+.Sm off
7878+.Ar host : nn Op . Ar nn .
7979+.Sm on
8080+.Sh RETURN VALUES
8181+The
8282+.Fn trimdomain
8383+function does not return a value.
8484+.Sh SEE ALSO
8585+.Xr gethostname 3
+116
src/libutil/trimdomain.c
···11+/*-
22+ * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
33+ * Based on original work by Atsushi Murai <amurai@FreeBSD.org>
44+ * All rights reserved.
55+ *
66+ * Redistribution and use in source and binary forms, with or without
77+ * modification, are permitted provided that the following conditions
88+ * are met:
99+ * 1. Redistributions of source code must retain the above copyright
1010+ * notice, this list of conditions and the following disclaimer.
1111+ * 2. Redistributions in binary form must reproduce the above copyright
1212+ * notice, this list of conditions and the following disclaimer in the
1313+ * documentation and/or other materials provided with the distribution.
1414+ *
1515+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1616+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1717+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1818+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1919+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2020+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2121+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2222+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2323+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2424+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2525+ * SUCH DAMAGE.
2626+ *
2727+ */
2828+2929+#include <sys/cdefs.h>
3030+3131+#include <sys/param.h>
3232+3333+#include <libutil.h>
3434+#include <string.h>
3535+#include <unistd.h>
3636+3737+void trimdomain(char *_fullhost, size_t _hostsize);
3838+3939+static int isDISP(const char *);
4040+4141+/*-
4242+ * Trim the current domain name from fullhost, but only if the result
4343+ * is less than or equal to hostsize in length.
4444+ *
4545+ * This function understands $DISPLAY type fullhosts.
4646+ *
4747+ * For example:
4848+ *
4949+ * trimdomain("abcde.my.domain", 5) -> "abcde"
5050+ * trimdomain("abcde.my.domain", 4) -> "abcde.my.domain"
5151+ * trimdomain("abcde.my.domain:0.0", 9) -> "abcde:0.0"
5252+ * trimdomain("abcde.my.domain:0.0", 8) -> "abcde.my.domain:0.0"
5353+ */
5454+void
5555+trimdomain(char *fullhost, size_t hostsize)
5656+{
5757+ static size_t dlen;
5858+ static int first = 1;
5959+ static char domain[MAXHOSTNAMELEN];
6060+ char *end, *s;
6161+ size_t len;
6262+6363+ if (first) {
6464+ /* XXX: Should we assume that our domain is this persistent ? */
6565+ first = 0;
6666+ if (gethostname(domain, sizeof(domain) - 1) == 0 &&
6767+ (s = strchr(domain, '.')) != NULL)
6868+ memmove(domain, s + 1, strlen(s + 1) + 1);
6969+ else
7070+ domain[0] = '\0';
7171+ dlen = strlen(domain);
7272+ }
7373+7474+ if (domain[0] == '\0')
7575+ return;
7676+7777+ s = fullhost;
7878+ end = (char *)((uintptr_t)s + hostsize + 1);
7979+ if ((s = memchr(s, '.', (size_t)(end - s))) != NULL) {
8080+ if (strncasecmp(s + 1, domain, dlen) == 0) {
8181+ if (s[dlen + 1] == '\0') {
8282+ /* Found -- lose the domain. */
8383+ *s = '\0';
8484+ } else if (s[dlen + 1] == ':' &&
8585+ isDISP(s + dlen + 2) &&
8686+ (len = strlen(s + dlen + 1)) < (size_t)(end - s)) {
8787+ /* Found -- shuffle the DISPLAY back. */
8888+ memmove(s, s + dlen + 1, len + 1);
8989+ }
9090+ }
9191+ }
9292+}
9393+9494+/*
9595+ * Is the given string NN or NN.NN where ``NN'' is an all-numeric string ?
9696+ */
9797+static int
9898+isDISP(const char *disp)
9999+{
100100+ size_t w;
101101+ int res;
102102+103103+ w = strspn(disp, "0123456789");
104104+ res = 0;
105105+ if (w > 0) {
106106+ if (disp[w] == '\0')
107107+ res = 1; /* NN */
108108+ else if (disp[w] == '.') {
109109+ disp += w + 1;
110110+ w = strspn(disp, "0123456789");
111111+ if (w > 0 && disp[w] == '\0')
112112+ res = 1; /* NN.NN */
113113+ }
114114+ }
115115+ return (res);
116116+}
+70
src/libutil/tzlink.c
···11+// Modified by Lubos Dolezel for Darling build
22+/*
33+ * Copyright (c) 2013 Apple Inc. All rights reserved.
44+ *
55+ * @APPLE_LICENSE_HEADER_START@
66+ *
77+ * This file contains Original Code and/or Modifications of Original Code
88+ * as defined in and that are subject to the Apple Public Source License
99+ * Version 2.0 (the 'License'). You may not use this file except in
1010+ * compliance with the License. Please obtain a copy of the License at
1111+ * http://www.opensource.apple.com/apsl/ and read it before using this
1212+ * file.
1313+ *
1414+ * The Original Code and all software distributed under the License are
1515+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1616+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1717+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1818+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1919+ * Please see the License for the specific language governing rights and
2020+ * limitations under the License.
2121+ *
2222+ * @APPLE_LICENSE_HEADER_END@
2323+ */
2424+2525+#include <TargetConditionals.h>
2626+#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
2727+# include <xpc/xpc.h>
2828+#endif
2929+#include <errno.h>
3030+3131+#include "tzlink.h"
3232+#include "tzlink_internal.h"
3333+3434+errno_t
3535+tzlink(const char *tz)
3636+{
3737+#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
3838+ xpc_connection_t connection;
3939+ xpc_object_t request, reply;
4040+ errno_t e;
4141+4242+ if (tz == NULL) {
4343+ return EINVAL;
4444+ }
4545+4646+ connection = xpc_connection_create_mach_service(TZLINK_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
4747+ xpc_connection_set_event_handler(connection, ^(__unused xpc_object_t event) {
4848+ });
4949+ xpc_connection_resume(connection);
5050+5151+ request = xpc_dictionary_create(NULL, NULL, 0);
5252+ xpc_dictionary_set_string(request, TZLINK_KEY_REQUEST_TIMEZONE, tz);
5353+5454+ reply = xpc_connection_send_message_with_reply_sync(connection, request);
5555+ if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
5656+ e = (errno_t)xpc_dictionary_get_uint64(reply, TZLINK_KEY_REPLY_ERROR);
5757+ } else {
5858+ e = EIO;
5959+ }
6060+6161+ xpc_release(reply);
6262+ xpc_release(request);
6363+ xpc_release(connection);
6464+6565+ return e;
6666+#else /* !TARGET_OS_IPHONE */
6767+#pragma unused (tz)
6868+ return ENOTSUP;
6969+#endif /* TARGET_OS_IPHONE */
7070+}
+56
src/libutil/tzlink.h
···11+/*
22+ * Copyright (c) 2013 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#ifndef _TZLINK_H_
2525+#define _TZLINK_H_
2626+2727+/*!
2828+ * @function tzlink
2929+ * Create the timezone link at TZDEFAULT
3030+ *
3131+ * @param tz
3232+ * New timezone, e.g. "America/Los_Angeles". This path is relative to TZDIR,
3333+ * and must not contain any relative path components or stray slashes.
3434+ * The file must exist and must be a valid timezone file with correct
3535+ * ownership (root:wheel) and permissions (0644).
3636+ *
3737+ * @result
3838+ * If the call succeeds, will return zero. Otherwise, returns an error:
3939+ * EINVAL: Invalid input, e.g. NULL or a path with relative components.
4040+ * ENAMETOOLONG: Input too long (generates a path > PATH_MAX)
4141+ * ENOENT: Specified file doesn't exist or fails owner/perm check.
4242+ * EPERM: Entitlement check failed.
4343+ * EIO: Failed to communicate with backing daemon.
4444+ * ENOTSUP: Always returned on OS X.
4545+ * And possibly others not documented here.
4646+ *
4747+ * @discussion
4848+ * This call can be used by any sufficiently-entitled client to overwrite
4949+ * the timezone link at TZDEFAULT (see <tzfile.h>). It communicates with a
5050+ * root daemon that does the necessary validation and file system work.
5151+ * Upon success, the "SignificantTimeChangeNotification" notification is
5252+ * posted.
5353+ */
5454+errno_t tzlink(const char *tz);
5555+5656+#endif /* !_TZLINK_H_ */
+29
src/libutil/tzlink_internal.h
···11+/*
22+ * Copyright (c) 2013 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#define TZLINK_SERVICE_NAME "com.apple.tzlink"
2525+2626+#define TZLINK_ENTITLEMENT "com.apple.tzlink.allow"
2727+2828+#define TZLINK_KEY_REQUEST_TIMEZONE "tz" // string
2929+#define TZLINK_KEY_REPLY_ERROR "error" // uint64
···11+/*
22+ * Copyright (c) 2013 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#include <xpc/xpc.h>
2525+#include <xpc/private.h>
2626+#include <notify.h>
2727+#include <tzfile.h>
2828+2929+#include "tzlink_internal.h"
3030+3131+static bool peer_entitled(xpc_connection_t);
3232+static int set_timezone(const char *);
3333+static int build_source_path(char *, size_t, const char *);
3434+static int validate_source_path(const char *);
3535+3636+int
3737+main(void)
3838+{
3939+ dispatch_queue_t queue;
4040+ xpc_connection_t listener;
4141+4242+ xpc_track_activity();
4343+4444+ queue = dispatch_queue_create(TZLINK_SERVICE_NAME, NULL);
4545+4646+ listener = xpc_connection_create_mach_service(TZLINK_SERVICE_NAME, queue, XPC_CONNECTION_MACH_SERVICE_LISTENER);
4747+ xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) {
4848+ if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) {
4949+ return;
5050+ }
5151+5252+ xpc_connection_set_target_queue(peer, queue);
5353+ xpc_connection_set_event_handler(peer, ^(xpc_object_t request) {
5454+ xpc_object_t reply;
5555+ const char *tz;
5656+ int error;
5757+5858+ if (xpc_get_type(request) != XPC_TYPE_DICTIONARY) {
5959+ return;
6060+ }
6161+6262+ if (peer_entitled(peer)) {
6363+ tz = xpc_dictionary_get_string(request, TZLINK_KEY_REQUEST_TIMEZONE);
6464+ error = tz ? set_timezone(tz) : EINVAL;
6565+ } else {
6666+ error = EPERM;
6767+ }
6868+6969+ reply = xpc_dictionary_create_reply(request);
7070+ xpc_dictionary_set_uint64(reply, TZLINK_KEY_REPLY_ERROR, (uint64_t)error);
7171+ xpc_connection_send_message(peer, reply);
7272+ xpc_release(reply);
7373+ });
7474+ xpc_connection_resume(peer);
7575+ });
7676+ xpc_connection_resume(listener);
7777+7878+ dispatch_main();
7979+}
8080+8181+static bool
8282+peer_entitled(xpc_connection_t peer)
8383+{
8484+ xpc_object_t val;
8585+ bool entitled;
8686+8787+ entitled = false;
8888+8989+ val = xpc_connection_copy_entitlement_value(peer, TZLINK_ENTITLEMENT);
9090+ if (val != NULL) {
9191+ entitled = xpc_bool_get_value(val);
9292+ xpc_release(val);
9393+ }
9494+9595+ return entitled;
9696+}
9797+9898+static int
9999+set_timezone(const char *tz)
100100+{
101101+ char srcpath[PATH_MAX];
102102+ int error;
103103+104104+ error = build_source_path(srcpath, sizeof(srcpath), tz);
105105+ if (error != 0) {
106106+ return error;
107107+ }
108108+109109+ error = validate_source_path(srcpath);
110110+ if (error != 0) {
111111+ return error;
112112+ }
113113+114114+ (void)unlink(TZDEFAULT);
115115+ if (symlink(srcpath, TZDEFAULT) != 0) {
116116+ return errno ? errno : EFAULT;
117117+ }
118118+119119+ /*
120120+ * notifyd posts "com.apple.system.timezone" automatically,
121121+ * but we also need post this. Sigh.
122122+ */
123123+ (void)notify_post("SignificantTimeChangeNotification");
124124+125125+ return 0;
126126+}
127127+128128+/* Create path from input. */
129129+static int
130130+build_source_path(char *path, size_t size, const char *tz)
131131+{
132132+ char *str, *str0;
133133+ char *pathcomp;
134134+ int error;
135135+136136+ if (strlcpy(path, TZDIR, size) >= size) {
137137+ return ENAMETOOLONG;
138138+ }
139139+140140+ error = 0;
141141+142142+ /* Attempt to validate the input; construct a clean path as we go. */
143143+ str0 = str = strdup(tz);
144144+ while ((pathcomp = strsep(&str, "/")) != NULL) {
145145+ if (pathcomp[0] == '\0' || pathcomp[0] == '.') {
146146+ error = EINVAL;
147147+ break;
148148+ }
149149+ if (strlcat(path, "/", size) >= size) {
150150+ error = ENAMETOOLONG;
151151+ break;
152152+ }
153153+ if (strlcat(path, pathcomp, size) >= size) {
154154+ error = ENAMETOOLONG;
155155+ break;
156156+ }
157157+ }
158158+ free(str0);
159159+160160+ return error;
161161+}
162162+163163+/* Validate path. */
164164+static int
165165+validate_source_path(const char *path)
166166+{
167167+ struct stat sb;
168168+169169+ if (lstat(path, &sb) != 0) {
170170+ return errno ? errno : EFAULT;
171171+ }
172172+173173+ /* Ensure that the time zone file is... */
174174+175175+ /* ... a regular file. */
176176+ if (!S_ISREG(sb.st_mode)) {
177177+ return ENOENT;
178178+ }
179179+180180+ /* ... owned by root:wheel */
181181+ if (sb.st_uid != 0 || sb.st_gid != 0) {
182182+ return ENOENT;
183183+ }
184184+185185+ /* ... 0644 perms */
186186+ if ((sb.st_mode & ACCESSPERMS) != 0644) {
187187+ return ENOENT;
188188+ }
189189+190190+ /* ... is a real tzfile (starts with TZif) */
191191+ // TODO: Validate contents of file.
192192+193193+ return 0;
194194+}
+162
src/libutil/wipefs.3
···11+.\"
22+.\" Copyright (c) 2008,2011 Apple Inc. All rights reserved.
33+.\"
44+.\" @APPLE_LICENSE_HEADER_START@
55+.\"
66+.\" This file contains Original Code and/or Modifications of Original Code
77+.\" as defined in and that are subject to the Apple Public Source License
88+.\" Version 2.0 (the 'License'). You may not use this file except in
99+.\" compliance with the License. Please obtain a copy of the License at
1010+.\" http://www.opensource.apple.com/apsl/ and read it before using this
1111+.\" file.
1212+.\"
1313+.\" The Original Code and all software distributed under the License are
1414+.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+.\" Please see the License for the specific language governing rights and
1919+.\" limitations under the License.
2020+.\"
2121+.\" @APPLE_LICENSE_HEADER_END@
2222+.\"
2323+.Dd 6/30/11 \" DATE
2424+.Dt libutil 3 \" Program name and manual section number
2525+.Os Mac OS X
2626+.Sh NAME \" Section Header - required - don't modify
2727+.\" The following lines are read in generating the apropos(man -k) database. Use only key
2828+.\" words here as the database is built based on the words here and in the .ND line.
2929+.Nm wipefs_alloc ,
3030+.Nm wipefs_except_blocks ,
3131+.Nm wipefs_wipe ,
3232+.Nm wipefs_free
3333+.\" Use .Nm macro to designate other names for the documented program.
3434+.Nd wipes existing file systems on a volume
3535+.Sh LIBRARY \" Section Header - required - don't modify
3636+.Lb libutil
3737+.Sh SYNOPSIS
3838+.In wipefs.h
3939+.Ft int
4040+.Fo wipefs_alloc
4141+.Fa "int fd"
4242+.Fa "size_t block_size"
4343+.Fa "wipefs_ctx *handle"
4444+.Fc
4545+.Ft int
4646+.Fo wipefs_include_blocks
4747+.Fa "wipefs_ctx handle"
4848+.Fa "off_t block_offset"
4949+.Fa "off_t nblocks"
5050+.Fc
5151+.Ft int
5252+.Fo wipefs_except_blocks
5353+.Fa "wipefs_ctx handle"
5454+.Fa "off_t block_offset"
5555+.Fa "off_t nblocks"
5656+.Fc
5757+.Ft int
5858+.Fo wipefs_wipe
5959+.Fa "wipefs_ctx handle"
6060+.Fc
6161+.Ft void
6262+.Fo wipefs_free
6363+.Fa "wipefs_ctx *handle"
6464+.Fc
6565+.Sh DESCRIPTION \" Section Header - required - don't modify
6666+The wipefs family of functions wipe existing file systems on a volume. A
6767+.Li DKIOCUNMAP
6868+ioctl is sent to the device to invalidate all of its content.
6969+Then zeroes are written to various locations that are used by various file systems to recognize their content and mount their volumes.
7070+This is usually used by the newfs_* utilities before they create new file systems on the volume, so that the existing file system will not be mounted accidentally after the new file system is created.
7171+.Pp
7272+.Sy NOTE:
7373+These routines do not overwrite all volume structures.
7474+These routines do not securely erase the previous content.
7575+They only overwrite enough to make sure that the normal utilities will no longer recognize any file system content.
7676+It is possible that previous file system content could be recovered by other means.
7777+.Pp
7878+The
7979+.Fn wipefs_alloc
8080+function initializes a
8181+.Fa wipefs_ctx
8282+object (which is an opaque data type).
8383+.Fa file_desc
8484+is the file handle of the volume to be wiped, which can be a block device node, a character device node, or a file.
8585+.Fa file_desc
8686+must be opened with write access. If
8787+.Fa block_size
8888+is 0, this function calls
8989+.Xr ioctl 2
9090+to get the block size. A valid
9191+.Fa block_size
9292+must be supplied if
9393+.Fa file_desc
9494+is a regular file. This function does not write any data to the volume.
9595+.Pp
9696+The
9797+.Fn wipefs_include_blocks
9898+function tells wipefs to write zeroes in the block range provided, in addition to any other ranges
9999+it would normally write. This may be more efficient than if the caller were to write this range
100100+separately, especially if the block range overlaps or is contiguous with other ranges that wipefs
101101+will write. This function does not write any data to the volume. If this function is called
102102+multiple times, the union of all the ranges provided will be written by
103103+.Fn wipefs_wipe .
104104+.Pp
105105+The
106106+.Fn wipefs_except_blocks
107107+function tells wipefs not to write anything in the block range provided. This function is used for performance
108108+optimizations if the caller will write to these blocks. It is the caller's responsibility to write to these blocks.
109109+Otherwise, some file systems may still be recognized on the volume. This function does not write any data to the
110110+volume. If this function is called multiple times, the union of all the ranges provided will be excluded from being
111111+written by
112112+.Fn wipefs_wipe .
113113+.Pp
114114+The
115115+.Fn wipefs_wipe
116116+function sends a
117117+.Li DKIOCUNMAP
118118+ioctl and then writes data to the volume to wipe out existing file systems on it.
119119+.Sy CAUTION:
120120+this function destroys any file system or partition scheme on the volume represented by
121121+.Fa file_desc .
122122+If
123123+.Fa file_desc
124124+represents the entire disk (e.g. /dev/diskX), the partition map of the disk will be destroyed. If
125125+.Fa file_desc
126126+represents a partition (e.g., /dev/diskXsY), only the file system in that partition is destroyed. Although the partition scheme or file system on
127127+.Fa file_desc
128128+may be beyond repair after
129129+.Fn wipefs_wipe ,
130130+this function is not designed as a means to safely delete all data. It is possible that some user data (or intact file systems in some partitions) may still be recovered.
131131+.Pp
132132+The
133133+.Fn wipefs_free
134134+function frees the allocated
135135+.Fa wipefs_ctx
136136+handle and set
137137+.Fa *handlep
138138+to NULL.
139139+.Sh RETURN VALUES
140140+The
141141+.Fn wipefs_alloc ,
142142+.Fn wipefs_include_blocks ,
143143+.Fn wipefs_except_blocks
144144+and
145145+.Fn wipefs_wipe
146146+functions return 0 on success, or will fail and return an error code.
147147+Each function may return
148148+.Fa ENOMEM
149149+if insufficient memory is available. In addition, if
150150+.Fa block_size
151151+is not provided,
152152+.Fn wipefs_alloc
153153+may return any error
154154+.Xr ioctl 2
155155+returns;
156156+.Fn wipefs_wipe
157157+may return any error
158158+.Xr pwrite 2
159159+returns.
160160+.\" .Sh BUGS \" Document known, unremedied bugs
161161+.\".Sh HISTORY \" Document history if command behaves in a unique manner
162162+.\"The wipefs family of functions first appeared in Mac OS X Leopard (10.5.3).
+317
src/libutil/wipefs.cpp
···11+/*
22+ * Copyright (c) 2008 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+//
2424+// wipefs.cpp
2525+//
2626+2727+#include <fcntl.h>
2828+#include <unistd.h>
2929+#include <sys/uio.h>
3030+#include <sys/ioctl.h>
3131+#include <sys/disk.h>
3232+#include <sys/stat.h>
3333+#include <cstring>
3434+#include <strings.h>
3535+3636+#include "ExtentManager.h"
3737+#include "wipefs.h"
3838+3939+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
4040+4141+struct __wipefs_ctx {
4242+ int fd;
4343+ class ExtentManager extMan;
4444+};
4545+4646+static void
4747+AddExtentsForFutureFS(class ExtentManager *extMan)
4848+{
4949+ // we don't know what blocks future FS will use to recognize itself. But we'd better be safe than sorry and write
5050+ // the first and last 2MB of the volume
5151+ off_t size = 2 * 1024 * 1024;
5252+ extMan->AddByteRangeExtent(0, size);
5353+ extMan->AddByteRangeExtent(extMan->totalBytes - size, size);
5454+}
5555+5656+static void
5757+AddExtentsForHFS(class ExtentManager *extMan)
5858+{
5959+ // first 1KB is boot block, last 512B is reserved
6060+ // the Volume Header (512B) is after 1KB and before the last 512B
6161+ extMan->AddByteRangeExtent(0, 1024 + 512);
6262+ extMan->AddByteRangeExtent(extMan->totalBytes - 1024, 1024);
6363+}
6464+6565+static void
6666+AddExtentsForMSDOS(class ExtentManager *extMan)
6767+{
6868+ // MSDOS needs the first block (in theory, up to 32KB)
6969+ extMan->AddByteRangeExtent(0, 32 * 1024);
7070+}
7171+7272+static void
7373+AddExtentsForNTFS(class ExtentManager *extMan)
7474+{
7575+ // NTFS supports block size from 256B to 32768B. The first, middle and last block are needed
7676+ extMan->AddByteRangeExtent(0, 32 * 1024);
7777+ extMan->AddByteRangeExtent(extMan->totalBytes - 32 * 1024, 32 * 1024);
7878+ // to be safe, add the rage from (mid_point - 32KB) to (mid_point + 32KB)
7979+ extMan->AddByteRangeExtent(extMan->totalBytes / 2 - 32 * 1024, 64 * 1024);
8080+}
8181+8282+static void
8383+AddExtentsForUDF(class ExtentManager *extMan)
8484+{
8585+ off_t lastBlockAddr = extMan->totalBlocks - 1;
8686+8787+ // Volume Recognization Sequence (VRS) starts at 32KB, usually less than 7 Volume Structure Descriptors (2KB each)
8888+ extMan->AddByteRangeExtent(32 * 1024, 14 * 1024);
8989+9090+ // AVDP is on 256, 512, last block, last block - 256
9191+ extMan->AddBlockRangeExtent(256, 1);
9292+ extMan->AddBlockRangeExtent(512, 1);
9393+ extMan->AddBlockRangeExtent(lastBlockAddr, 1);
9494+ extMan->AddBlockRangeExtent(lastBlockAddr - 256, 1);
9595+9696+ // to be safe, assume the device has 2KB block size and do it again
9797+ if (extMan->blockSize != 2048) {
9898+ off_t blockSize = 2048;
9999+ // AVDP is on 256, 512, last block, last block - 256
100100+ extMan->AddByteRangeExtent(256 * blockSize, blockSize);
101101+ extMan->AddByteRangeExtent(512 * blockSize, blockSize);
102102+ extMan->AddByteRangeExtent(extMan->totalBytes - blockSize, blockSize);
103103+ extMan->AddByteRangeExtent(extMan->totalBytes - 256 * blockSize, blockSize);
104104+ }
105105+}
106106+107107+static void
108108+AddExtentsForUFS(class ExtentManager *extMan)
109109+{
110110+ // UFS super block is 8KB at offset 8KB
111111+ extMan->AddByteRangeExtent(8192, 8192);
112112+}
113113+114114+static void
115115+AddExtentsForZFS(class ExtentManager *extMan)
116116+{
117117+ // ZFS needs the first 512KB and last 512KB for all the 4 disk labels
118118+ extMan->AddByteRangeExtent(0, 512 * 1024);
119119+ extMan->AddByteRangeExtent(extMan->totalBytes - 512 * 1024, 512 * 1024);
120120+}
121121+122122+static void
123123+AddExtentsForPartitions(class ExtentManager *extMan)
124124+{
125125+ // MBR (Master Boot Record) needs the first sector
126126+ // APM (Apple Partition Map) needs the second sector
127127+ // GPT (GUID Partition Table) needs the first 34 and last 33 sectors
128128+ extMan->AddByteRangeExtent(0, 512 * 34);
129129+ extMan->AddByteRangeExtent(extMan->totalBytes - 512 * 33, 512 * 33);
130130+}
131131+132132+extern "C" int
133133+wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle)
134134+{
135135+ int err = 0;
136136+ uint64_t numBlocks = 0;
137137+ uint32_t nativeBlockSize = 0;
138138+ off_t totalSizeInBytes = 0;
139139+ class ExtentManager *extMan = NULL;
140140+ struct stat sbuf = { 0 };
141141+142142+ *handle = NULL;
143143+ (void)fstat(fd, &sbuf);
144144+ switch (sbuf.st_mode & S_IFMT) {
145145+ case S_IFCHR:
146146+ case S_IFBLK:
147147+ if (ioctl(fd, DKIOCGETBLOCKSIZE, (char *)&nativeBlockSize) < 0) {
148148+ err = errno;
149149+ goto labelExit;
150150+ }
151151+ if (ioctl(fd, DKIOCGETBLOCKCOUNT, (char *)&numBlocks) < 0) {
152152+ err = errno;
153153+ goto labelExit;
154154+ }
155155+ totalSizeInBytes = numBlocks * nativeBlockSize;
156156+ break;
157157+ case S_IFREG:
158158+ nativeBlockSize = sbuf.st_blksize;
159159+ numBlocks = sbuf.st_size / sbuf.st_blksize;
160160+ totalSizeInBytes = sbuf.st_size;
161161+ break;
162162+ default:
163163+ errno = EINVAL;
164164+ goto labelExit;
165165+ }
166166+ if (block_size == 0) {
167167+ block_size = nativeBlockSize;
168168+ }
169169+ if (block_size == 0 || totalSizeInBytes == 0) {
170170+ err = EINVAL;
171171+ goto labelExit;
172172+ }
173173+174174+ try {
175175+ *handle = new __wipefs_ctx;
176176+ if (*handle == NULL) {
177177+ bad_alloc e;
178178+ throw e;
179179+ }
180180+181181+ (*handle)->fd = fd;
182182+ extMan = &(*handle)->extMan;
183183+184184+ extMan->Init(block_size, nativeBlockSize, totalSizeInBytes);
185185+ AddExtentsForFutureFS(extMan);
186186+ AddExtentsForHFS(extMan);
187187+ AddExtentsForMSDOS(extMan);
188188+ AddExtentsForNTFS(extMan);
189189+ AddExtentsForUDF(extMan);
190190+ AddExtentsForUFS(extMan);
191191+ AddExtentsForZFS(extMan);
192192+ AddExtentsForPartitions(extMan);
193193+ }
194194+ catch (bad_alloc &e) {
195195+ err = ENOMEM;
196196+ }
197197+ catch (...) { // currently only ENOMEM is possible
198198+ err = ENOMEM;
199199+ }
200200+201201+ labelExit:
202202+ if (err != 0) {
203203+ wipefs_free(handle);
204204+ }
205205+ return err;
206206+} // wipefs_alloc
207207+208208+extern "C" int
209209+wipefs_include_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks)
210210+{
211211+ int err = 0;
212212+ try {
213213+ handle->extMan.AddBlockRangeExtent(block_offset, nblocks);
214214+ }
215215+ catch (bad_alloc &e) {
216216+ err = ENOMEM;
217217+ }
218218+ catch (...) { // currently only ENOMEM is possible
219219+ err = ENOMEM;
220220+ }
221221+ return err;
222222+}
223223+224224+extern "C" int
225225+wipefs_except_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks)
226226+{
227227+ int err = 0;
228228+ try {
229229+ handle->extMan.RemoveBlockRangeExtent(block_offset, nblocks);
230230+ }
231231+ catch (bad_alloc &e) {
232232+ err = ENOMEM;
233233+ }
234234+ catch (...) { // currently only ENOMEM is possible
235235+ err = ENOMEM;
236236+ }
237237+ return err;
238238+}
239239+240240+extern "C" int
241241+wipefs_wipe(wipefs_ctx handle)
242242+{
243243+ int err = 0;
244244+ uint8_t *bufZero = NULL;
245245+ ListExtIt curExt;
246246+ size_t bufSize;
247247+ dk_extent_t extent;
248248+ dk_unmap_t unmap;
249249+250250+ memset(&extent, 0, sizeof(dk_extent_t));
251251+ extent.length = handle->extMan.totalBytes;
252252+253253+ memset(&unmap, 0, sizeof(dk_unmap_t));
254254+ unmap.extents = &extent;
255255+ unmap.extentsCount = 1;
256256+257257+ //
258258+ // Don't bother to check the return value since this is mostly
259259+ // informational for the lower-level drivers.
260260+ //
261261+ ioctl(handle->fd, DKIOCUNMAP, (caddr_t)&unmap);
262262+263263+264264+ bufSize = 128 * 1024; // issue large I/O to get better performance
265265+ if (handle->extMan.nativeBlockSize > bufSize) {
266266+ bufSize = handle->extMan.nativeBlockSize;
267267+ }
268268+ bufZero = new uint8_t[bufSize];
269269+ bzero(bufZero, bufSize);
270270+271271+ off_t byteOffset, totalBytes;
272272+ size_t numBytes, numBytesToWrite, blockSize;
273273+274274+ blockSize = handle->extMan.blockSize;
275275+ totalBytes = handle->extMan.totalBytes;
276276+ // write zero to all extents
277277+ for (curExt = handle->extMan.extentList.begin(); curExt != handle->extMan.extentList.end(); curExt++) {
278278+ byteOffset = curExt->blockAddr * blockSize;
279279+ numBytes = curExt->numBlocks * blockSize;
280280+ // make both offset and numBytes on native block boundary
281281+ if (byteOffset % handle->extMan.nativeBlockSize != 0 ||
282282+ numBytes % handle->extMan.nativeBlockSize != 0) {
283283+ size_t nativeBlockSize = handle->extMan.nativeBlockSize;
284284+ off_t newOffset, newEndOffset;
285285+ newOffset = byteOffset / nativeBlockSize * nativeBlockSize;
286286+ newEndOffset = roundup(byteOffset + numBytes, nativeBlockSize);
287287+ byteOffset = newOffset;
288288+ numBytes = newEndOffset - newOffset;
289289+ }
290290+ if (byteOffset + (off_t)numBytes > totalBytes) {
291291+ numBytes = totalBytes - byteOffset;
292292+ }
293293+ while (numBytes > 0) {
294294+ numBytesToWrite = min(numBytes, bufSize);
295295+ if (pwrite(handle->fd, bufZero, numBytesToWrite, byteOffset) != (ssize_t)numBytesToWrite) {
296296+ err = errno;
297297+ goto labelExit;
298298+ }
299299+ numBytes -= numBytesToWrite;
300300+ byteOffset += numBytesToWrite;
301301+ }
302302+ }
303303+304304+ labelExit:
305305+ if (bufZero != NULL)
306306+ delete[] bufZero;
307307+ return err;
308308+} // wipefs_wipe
309309+310310+extern "C" void
311311+wipefs_free(wipefs_ctx *handle)
312312+{
313313+ if (*handle != NULL) {
314314+ delete *handle;
315315+ *handle = NULL;
316316+ }
317317+}
+48
src/libutil/wipefs.h
···11+/*
22+ * Copyright (c) 2008 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+//
2424+// wipefs.h
2525+//
2626+#ifndef WIPEFS_H
2727+#define WIPEFS_H
2828+2929+#ifdef __cplusplus
3030+extern "C" {
3131+#endif
3232+3333+typedef struct __wipefs_ctx *wipefs_ctx;
3434+3535+__BEGIN_DECLS
3636+extern int wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle);
3737+extern int wipefs_include_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks);
3838+extern int wipefs_except_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks);
3939+extern int wipefs_wipe(wipefs_ctx handle);
4040+extern void wipefs_free(wipefs_ctx *handle);
4141+__END_DECLS
4242+4343+#ifdef __cplusplus
4444+}
4545+#endif
4646+4747+#endif // #ifndef WIPEFS_H
4848+
+11
src/libutil/xcconfigs/base.xcconfig
···11+#include "<DEVELOPER_DIR>/Makefiles/CoreOS/Xcode/BSD.xcconfig"
22+#include "<DEVELOPER_DIR>/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig"
33+44+// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable
55+INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL)
66+77+// Use $(INSTALL_PATH_PREFIX) instead of $(SDKROOT) as a prefix for other
88+// variables as appropriate
99+PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/include
1010+PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include
1111+