Move Source From Main Repo

Based on libutil-57 source
This commit is contained in:
Thomas A 2023-02-05 07:21:14 -08:00
commit 79b03e8a11
37 changed files with 5142 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
build/
xcuserdata/
project.xcworkspace/
*~

50
CMakeLists.txt Normal file
View File

@ -0,0 +1,50 @@
project(libutil)
cmake_minimum_required(VERSION 3.10)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
include(InstallSymlink)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc -D__DARWIN_UNIX03 -fPIC -w")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc -nostdinc++ -D__DARWIN_UNIX03 -fPIC -w")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -nostdlib")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(util_SRCS
ExtentManager.cpp
getmntopts.c
humanize_number.c
pidfile.c
realhostname.c
reexec_to_match_kernel.c
trimdomain.c
tzlink.c
wipefs.cpp
)
set(DYLIB_INSTALL_NAME "/usr/lib/libutil1.0.dylib")
set(DYLIB_COMPAT_VERSION "1.0.0")
set(DYLIB_CURRENT_VERSION "1.0.0")
add_darling_library(util SHARED ${util_SRCS})
make_fat(util)
target_link_libraries(util PRIVATE system cxx)
set_target_properties(util PROPERTIES OUTPUT_NAME "util1.0")
install(TARGETS util DESTINATION libexec/darling/usr/lib)
install(FILES
reexec_to_match_kernel.3
realhostname.3
humanize_number.3
getmntopts.3
realhostname_sa.3
pidfile.3
wipefs.3
trimdomain.3
DESTINATION
libexec/darling/usr/share/man/man3
)
InstallSymlink("libutil1.0.dylib" "${CMAKE_INSTALL_PREFIX}/libexec/darling/usr/lib/libutil.dylib")

305
ExtentManager.cpp Normal file
View File

@ -0,0 +1,305 @@
/*
* Copyright (c) 2008-2009,2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
//
// ExtentManager.cpp
//
#include "ExtentManager.h"
void
ExtentManager::Init(uint32_t theBlockSize, uint32_t theNativeBlockSize, off_t theTotalBytes)
{
blockSize = theBlockSize;
nativeBlockSize = theNativeBlockSize;
totalBytes = theTotalBytes;
totalBlocks = howmany(totalBytes, blockSize);
// add sentry empty extents at both sides so empty partition doesn't need to be handled specially
AddBlockRangeExtent(0, 0);
AddBlockRangeExtent(totalBlocks, 0);
}
void
ExtentManager::MergeExtent(const ExtentInfo &a, const ExtentInfo &b, ExtentInfo *c)
{
// merge ext into *curIt
c->blockAddr = min(a.blockAddr, b.blockAddr);
c->numBlocks = max(a.blockAddr + a.numBlocks, b.blockAddr + b.numBlocks) - c->blockAddr;
}
void
ExtentManager::AddBlockRangeExtent(off_t blockAddr, off_t numBlocks)
{
struct ExtentInfo ext, newExt;
ListExtIt curIt, newIt;
bool merged = false;
// make the range a valid range
if ((blockAddr > totalBlocks) || (blockAddr + numBlocks < 0)) { // totally out of range, do nothing
return;
}
if (blockAddr < 0) {
numBlocks = blockAddr + numBlocks;
blockAddr = 0;
}
if (blockAddr + numBlocks > totalBlocks) {
numBlocks = totalBlocks - blockAddr;
}
ext.blockAddr = blockAddr;
ext.numBlocks = numBlocks;
for (curIt = extentList.begin(); curIt != extentList.end(); curIt++) {
if (BeforeExtent(ext, *curIt))
break;
if (!BeforeExtent(*curIt, ext)) { // overlapped extents
MergeExtent(ext, *curIt, &newExt);
*curIt = newExt;
merged = true;
break;
}
}
// insert ext before curIt
if (!merged) {
curIt = extentList.insert(curIt, ext); // throws bad_alloc when out of memory
}
// merge the extents
newIt = curIt;
curIt = extentList.begin();
while (curIt != extentList.end()) {
if (curIt == newIt || BeforeExtent(*curIt, *newIt)) { // curIt is before newIt
curIt++;
continue;
}
if (BeforeExtent(*newIt, *curIt)) { // curIt is after newIt now, we are done
break;
}
// merge the two extents
MergeExtent(*curIt, *newIt, &newExt);
*newIt = newExt;
curIt = extentList.erase(curIt);
}
// printf("After %s(%lld, %lld)\n", __func__, blockAddr, numBlocks); DebugPrint();
} // ExtentManager::AddBlockRangeExtent
void
ExtentManager::RemoveBlockRangeExtent(off_t blockAddr, off_t numBlocks)
{
struct ExtentInfo ext, newExt;
ListExtIt curIt;
ext.blockAddr = blockAddr;
ext.numBlocks = numBlocks;
curIt = extentList.begin();
while (curIt != extentList.end()) {
if (BeforeExtent(*curIt, ext)) {
curIt++;
continue;
}
if (BeforeExtent(ext, *curIt)) // we are done
break;
//
// If we get here, the input extent and *curIt have at least one block in common.
// That is, they overlap in some way. Thus *curIt needs to change, be removed,
// or be split into two non-contiguous extents.
//
if (curIt->blockAddr >= ext.blockAddr &&
curIt->blockAddr + curIt->numBlocks <= ext.blockAddr + ext.numBlocks) {
//
// The input extent totally contains *curIt, so remove *curIt.
//
curIt = extentList.erase(curIt);
} else if (curIt->blockAddr < ext.blockAddr &&
curIt->blockAddr + curIt->numBlocks > ext.blockAddr + ext.numBlocks) {
//
// The input extent does not include the start of *curIt, nor the end of *curIt,
// so split *curIt into two extents.
//
newExt.blockAddr = ext.blockAddr + ext.numBlocks;
newExt.numBlocks = curIt->blockAddr + curIt->numBlocks - newExt.blockAddr;
curIt->numBlocks = ext.blockAddr - curIt->blockAddr;
curIt++;
extentList.insert(curIt, newExt); // throws bad_alloc when out of memory
curIt++;
} else {
//
// The input extent contains either the start or the end of *curIt, but not both.
// The remove will leave either the end or the start of *curIt (respectively) and
// not change the number of extents in the list.
//
if (curIt->blockAddr >= ext.blockAddr) {
//
// Remove the start of *curIt by updating both its starting block and size.
//
assert(curIt->blockAddr + curIt->numBlocks > ext.blockAddr + ext.numBlocks);
newExt.blockAddr = ext.blockAddr + ext.numBlocks;
newExt.numBlocks = curIt->blockAddr + curIt->numBlocks - newExt.blockAddr;
*curIt = newExt;
} else {
//
// Remove the end of *curIt by updating its size.
//
curIt->numBlocks = ext.blockAddr - curIt->blockAddr;
}
curIt++;
}
}
//printf("After %s(%lld, %lld)\n", __func__, blockAddr, numBlocks); DebugPrint();
}
void
ExtentManager::AddByteRangeExtent(off_t byteAddr, off_t numBytes)
{
off_t blockAddr = byteAddr / blockSize;
off_t blockAddrOfLastByte = (byteAddr + numBytes - 1) / blockSize;
off_t numBlocks = blockAddrOfLastByte - blockAddr + 1;
AddBlockRangeExtent(blockAddr, numBlocks);
}
void
ExtentManager::DebugPrint()
{
ListExtIt it;
for (it = extentList.begin(); it != extentList.end(); it++) {
printf("[%lld, %lld] ", it->blockAddr, it->numBlocks);
}
printf("\n");
}
#if UNIT_TEST
/*
clang++ -arch i386 -arch x86_64 -DUNIT_TEST ExtentManager.cpp -o ExtentManager && ./ExtentManager
*/
#include <cstdio>
#include <cstdlib>
const char *DebugDescription(class ExtentManager *extMan)
{
char *result = strdup("");
char *temp;
ListExtIt it;
for (it = extMan->extentList.begin(); it != extMan->extentList.end(); it++) {
temp = result;
asprintf(&result, "%s[%lld, %lld] ", temp, it->blockAddr, it->numBlocks);
free(temp);
}
return result;
}
int SimpleTestCase(off_t addAddr, off_t addBlocks, off_t removeAddr, off_t removeBlocks, const char *expectedResult)
{
class ExtentManager extMan;
const char *actualResult;
int result = 0;
extMan.Init(512, 512, 512*999);
extMan.AddBlockRangeExtent(addAddr, addBlocks);
extMan.RemoveBlockRangeExtent(removeAddr, removeBlocks);
actualResult = DebugDescription(&extMan);
if (strcmp(actualResult, expectedResult))
{
fprintf(stderr,
"SimpleTestCase(%lld, %lld, %lld, %lld) failed.\n"
" Expected result: %s\n"
" Actual result: %s\n",
addAddr, addBlocks, removeAddr, removeBlocks,
expectedResult, actualResult);
result = 1;
}
free((void *)actualResult);
return result;
}
int main(void)
{
int failed = 0;
class ExtentManager *extMan;
// Create an extent, and remove one contained inside,
// leaving the start and end of the original extent.
// Create: [xxxxxxxxxx]
// Remove: [......]
failed |= SimpleTestCase(10, 10, 12, 6, "[0, 0] [10, 2] [18, 2] [999, 0] ");
// Create an extent, and remove the whole extent.
// Create: [xxxxxxxxxx]
// Remove: [..........]
failed |= SimpleTestCase(10, 10, 10, 10, "[0, 0] [999, 0] ");
// Create an extent, and remove the first part of the extent.
// Create: [xxxxxxxxxx]
// Remove: [......]
failed |= SimpleTestCase(10, 10, 10, 6, "[0, 0] [16, 4] [999, 0] ");
// Create an extent, and remove the last part of the extent.
// Create: [xxxxxxxxxx]
// Remove: [......]
failed |= SimpleTestCase(10, 10, 14, 6, "[0, 0] [10, 4] [999, 0] ");
// Create an extent and remove before the start, through the middle.
// Create: [xxxxxxxxxx]
// Remove: [..........]
failed |= SimpleTestCase(10, 10, 6, 10, "[0, 0] [16, 4] [999, 0] ");
// Create an extent and remove from middle to past the end.
// Create: [xxxxxxxxxx]
// Remove: [..........]
failed |= SimpleTestCase(10, 10, 14, 10, "[0, 0] [10, 4] [999, 0] ");
// Create an extent and remove from before through past end.
// Create: [xxxxxxxxxx]
// Remove: [..............]
failed |= SimpleTestCase(10, 10, 6, 18, "[0, 0] [999, 0] ");
// Create an extent and remove purely before the extent.
// Create: [xxxxxxxxxx]
// Remove: [...]
failed |= SimpleTestCase(10, 10, 2, 5, "[0, 0] [10, 10] [999, 0] ");
// Create an extent and remove purely after the extent.
// Create: [xxxxxxxxxx]
// Remove: [...]
failed |= SimpleTestCase(10, 10, 22, 5, "[0, 0] [10, 10] [999, 0] ");
if (failed)
printf("FAIL!\n");
else
printf("Success.\n");
return failed;
}
#endif /* UNIT_TEST */

74
ExtentManager.h Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2008 Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
//
// ExtentManager.h
//
#ifndef EXTENTMANAGER_H
#define EXTENTMANAGER_H
#include <list>
#include <vector>
#include <algorithm>
#include <sys/types.h>
#include <sys/errno.h>
#include <cstdio>
#include <cassert>
using namespace std;
struct ExtentInfo {
off_t blockAddr;
off_t numBlocks;
};
inline bool BeforeExtent(const ExtentInfo &a, const ExtentInfo &b)
{
return (a.blockAddr + a.numBlocks) < b.blockAddr;
}
typedef list<ExtentInfo>::iterator ListExtIt;
class ExtentManager {
public:
ExtentManager() : blockSize(0), totalBytes(0), totalBlocks(0) {};
~ExtentManager() {};
void Init(uint32_t theBlockSize, uint32_t theNativeBlockSize, off_t theTotalBytes);
void AddBlockRangeExtent(off_t blockAddr, off_t numBlocks);
void AddByteRangeExtent(off_t byteAddr, off_t numBytes);
void RemoveBlockRangeExtent(off_t blockAddr, off_t numBlocks);
void DebugPrint();
protected:
void MergeExtent(const ExtentInfo &a, const ExtentInfo &b, ExtentInfo *c);
public:
size_t blockSize;
size_t nativeBlockSize;
off_t totalBytes;
off_t totalBlocks;
list<ExtentInfo> extentList;
};
#endif // #ifndef EXTENTMANAGER_H

296
getmntopts.3 Normal file
View File

@ -0,0 +1,296 @@
.\" $NetBSD: getmntopts.3,v 1.12 2010/08/24 12:05:01 christos Exp $
.\"
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95
.\"
.Dd May 4, 2010
.Dt GETMNTOPTS 3
.Os
.Sh NAME
.Nm getmntopts
.Nd scan mount options
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In mntopts.h
.Ft mntoptparse_t
.Fn getmntopts "const char *options" "const struct mntopt *mopts" "int *flagp" "int *altflagp"
.Ft const char *
.Fn getmntoptstr "mntoptparse_t mp" "const char *opt"
.Ft long
.Fn getmntoptnum "mntoptparse_t mp" "const char *opt"
.Ft void
.Fn freemntopts "mntoptparse_t mp"
.Sh DESCRIPTION
The
.Fn getmntopts
function takes a comma separated option list and a list
of valid option names, and computes the bitmasks
corresponding to the requested set of options.
.Pp
The string
.Ar options
is broken down into a sequence of comma separated tokens.
Each token is looked up in the table described by
.Ar mopts
and the bits in
the word referenced by either
.Ar flagp
or
.Ar altflagp
(depending on the
.Dv m_altloc
field of the option's table entry)
are updated.
The flag words are not initialized by
.Fn getmntopts .
The table,
.Ar mopts ,
has the following format:
.Bd -literal
struct mntopt {
const char *m_option; /* option name */
int m_inverse; /* negative option, e.g., "dev" */
int m_flag; /* bit to set, e.g., MNT_RDONLY */
int m_altloc; /* use altflagp rather than flagp */
};
.Ed
.Pp
The members of this structure are:
.Bl -tag -width m_inverse
.It Fa m_option
the option name,
for example
.Dq suid .
.It Fa m_inverse
tells
.Fn getmntopts
that the name has the inverse meaning of the bit.
For example,
.Dq suid
is the string, whereas the mount flag is
.Dv MNT_NOSUID .
In this case, the sense of the string and the flag
are inverted, so the
.Fa m_inverse
flag should be set.
.It Fa m_flag
the value of the bit to be set or cleared in
the flag word when the option is recognized.
The bit is set when the option is discovered,
but cleared if the option name was preceded
by the letters
.Dq no .
The
.Fa m_inverse
flag causes these two operations to be reversed.
.It Fa m_altloc
the bit should be set or cleared in
.Ar altflagp
rather than
.Ar flagp .
.El
.Pp
Each of the user visible
.Dv MNT_
flags has a corresponding
.Dv MOPT_
macro which defines an appropriate
.Li "struct mntopt"
entry.
To simplify the program interface and ensure consistency across all
programs, a general purpose macro,
.Dv MOPT_STDOPTS ,
is defined which contains an entry for all the generic VFS options:
.Bd -literal -offset indent
MOPT_USERQUOTA,
MOPT_GROUPQUOTA,
MOPT_FSTAB_COMPAT,
MOPT_NODEV,
MOPT_NOEXEC,
MOPT_NOSUID,
MOPT_RDONLY,
MOPT_UNION,
MOPT_BROWSE,
MOPT_AUTOMOUNTED,
MOPT_DEFWRITE,
MOPT_NOATIME,
MOPT_PERMISSIONS,
MOPT_IGNORE_OWNERSHIP,
MOPT_QUARANTINE,
MOPT_CPROTECT
.Ed
.Pp
In addition, the macros
.Dv MOPT_FORCE
and
.Dv MOPT_UPDATE
exist to enable the
.Dv MNT_FORCE
and
.Dv MNT_UPDATE
flags to be set.
Finally, the table must be terminated by an entry with a
.Dv NULL
first element.
.Pp
.Fn getmntopts
returns a
.Li "mntoptparse_t"
handle that can be used in subsequent
.Fn getmntoptstr
and
.Fn getmntoptnum
calls to fetch a value for an option and that must be freed with a call
to
.Fn freemntopts .
If an error occurred, then if the external integer value
.Va getmnt_silent
is zero then
.Fn getmntopts
prints an error message and exits;
if
.Va getmnt_silent
is non-zero then
.Fn getmntopts
returns
.Dv NULL .
.Pp
The
.Fn getmntoptstr
function returns the string value of the named option, if such a value
was set in the option string.
If the value was not set, then if the external integer value
.Va getmnt_silent
is zero then
.Fn getmntoptstr
prints an error message and exits;
if
.Va getmnt_silent
is non-zero then
.Fn getmntoptstr
returns
.Dv NULL .
.Pp
The
.Fn getmntoptnum
returns the long value of the named option, if such a value was set in the
option string.
If the value was not set, or could not be converted from a string to a
long, then if the external integer value
.Va getmnt_silent
is zero then
.Fn getmntoptnum
prints an error message and exits;
if
.Va getmnt_silent
is non-zero then
.Fn getmntoptnum
returns \-1.
.Pp
The
.Fn freemntopts
frees the storage used by
.Fn getmntopts .
.Sh RETURN VALUES
.Fn getmntopts
returns
.Dv NULL
if an error occurred.
Note that some bits may already have been set in
.Va flagp
and
.Va altflagp
even if
.Dv NULL
is returned.
.Fn getmntoptstr
returns
.Dv NULL
if an error occurred.
.Fn getmntoptnum
returns \-1 if an error occurred.
.Sh EXAMPLES
Most commands will use the standard option set.
Local filesystems which support the
.Dv MNT_UPDATE
flag, would also have an
.Dv MOPT_UPDATE
entry.
This can be declared and used as follows:
.Bd -literal -offset indent
#include \*[Lt]mntopts.h\*[Gt]
static const struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
{ NULL }
};
\&...
long val;
mntoptparse_t mp;
mntflags = mntaltflags = 0;
\&...
mp = getmntopts(options, mopts, \*[Am]mntflags, \*[Am]mntaltflags);
if (mp == NULL)
err(EXIT_FAILURE, "getmntopts");
\&...
val = getmntoptnum(mp, "rsize");
freemntopts(mp);
.Ed
.Sh DIAGNOSTICS
If the external integer variable
.Va getmnt_silent
is zero then the
.Fn getmntopts ,
.Fn getmntoptstr ,
and
.Fn getmntoptnum
functions display an error message and exit if an error occurred.
By default
.Va getmnt_silent
is zero.
.Sh SEE ALSO
.Xr err 3 ,
.Xr mount 8
.Sh HISTORY
The
.Fn getmntopts
function appeared in
.Bx 4.4 .
It was moved to the utilities library and enhanced to retrieve option
values in
.Nx 2.0 .

188
getmntopts.c Normal file
View File

@ -0,0 +1,188 @@
/* $NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
#else
__RCSID("$NetBSD: getmntopts.c,v 1.3 2003/08/07 16:44:58 agc Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <err.h>
#include <errno.h>
#include <fstab.h>
#include <stdlib.h>
#include <string.h>
#include <mntopts.h>
int getmnt_silent = 0;
static const char errmsg[] = "-o %s: option not supported";
struct mntoptparse {
const char *options;
const struct mntopt *mopts;
char *optbuf;
char **optarg;
};
const char *
getmntoptstr(mntoptparse_t mp, const char *opt)
{
const struct mntopt *m;
for (m = mp->mopts; m->m_option != NULL; m++)
if (strcasecmp(opt, m->m_option) == 0)
break;
if (m->m_option == NULL) {
if (getmnt_silent == 0)
errx(1, errmsg, opt);
else
return NULL;
}
return mp->optarg[m - mp->mopts];
}
long
getmntoptnum(mntoptparse_t mp, const char *opt)
{
char *ep;
long rv;
void (*fun)(int, const char *, ...) = NULL;
const char *val = getmntoptstr(mp, opt);
if (val == NULL) {
if (getmnt_silent == 0)
errx(1, "Missing %s argument", opt);
else
return -1;
}
errno = 0;
rv = strtol(val, &ep, 0);
if (*ep)
fun = errx;
if (errno == ERANGE && (rv == LONG_MAX || rv == LONG_MIN))
fun = err;
if (fun) {
if (getmnt_silent != 0)
return -1;
(*fun)(1, "Invalid %s argument `%s'", opt, val);
}
return rv;
}
void
freemntopts(mntoptparse_t mp)
{
free(mp->optbuf);
free(mp->optarg);
free(mp);
}
mntoptparse_t
getmntopts(const char *options, const struct mntopt *m0, int *flagp,
int *altflagp)
{
const struct mntopt *m;
int negative;
char *opt, *p, *ctx = NULL;
int *thisflagp;
size_t nopts;
mntoptparse_t mp;
for (nopts = 0, m = m0; m->m_option != NULL; ++m, nopts++)
continue;
if ((mp = malloc(sizeof(struct mntoptparse))) == NULL)
return NULL;
/* Copy option string, since it is about to be torn asunder... */
if ((mp->optbuf = strdup(options)) == NULL) {
free(mp);
return NULL;
}
if ((mp->optarg = calloc(nopts, sizeof(char *))) == NULL) {
free(mp->optbuf);
free(mp);
return NULL;
}
mp->mopts = m0;
mp->options = options;
for (opt = mp->optbuf; (opt = strtok_r(opt, ",", &ctx)) != NULL; opt = NULL) {
/* Check for "no" prefix. */
if (opt[0] == 'n' && opt[1] == 'o') {
negative = 1;
opt += 2;
} else
negative = 0;
/*
* for options with assignments in them (ie. quotas)
* ignore the assignment as it's handled elsewhere
*/
p = strchr(opt, '=');
if (p) {
*p++ = '\0';
}
/* Scan option table. */
for (m = m0; m->m_option != NULL; ++m)
if (strcasecmp(opt, m->m_option) == 0)
break;
/* Save flag, or fail if option is not recognised. */
if (m->m_option) {
mp->optarg[m - m0] = p;
thisflagp = m->m_altloc ? altflagp : flagp;
if (negative == m->m_inverse)
*thisflagp |= m->m_flag;
else
*thisflagp &= ~m->m_flag;
} else if (!getmnt_silent) {
errx(1, errmsg, opt);
}
}
return mp;
}

202
humanize_number.3 Normal file
View File

@ -0,0 +1,202 @@
.\" $NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $
.\" $FreeBSD$
.\"
.\" Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Luke Mewburn and by Tomas Svensson.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd October 7, 2013
.Dt HUMANIZE_NUMBER 3
.Os
.Sh NAME
.Nm humanize_number
.Nd format a number into a human readable form
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In libutil.h
.Ft int
.Fo humanize_number
.Fa "char *buf" "size_t len" "int64_t number" "const char *suffix"
.Fa "int scale" "int flags"
.Fc
.Sh DESCRIPTION
The
.Fn humanize_number
function formats the signed 64-bit quantity given in
.Fa number
into
.Fa buf .
A space and then
.Fa suffix
is appended to the end.
The buffer pointed to by
.Fa buf
must be at least
.Fa len
bytes long.
.Pp
If the formatted number (including
.Fa suffix )
would be too long to fit into
.Fa buf ,
then divide
.Fa number
by 1024 until it will.
In this case, prefix
.Fa suffix
with the appropriate designator.
The
.Fn humanize_number
function follows the traditional computer science conventions by
default, rather than the IEE/IEC (and now also SI) power of two
convention or the power of ten notion.
This behaviour however can be altered by specifying the
.Dv HN_DIVISOR_1000
and
.Dv HN_IEC_PREFIXES
flags.
.Pp
The traditional
.Pq default
prefixes are:
.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier" Ta Sy "Multiplier 1000x"
.It Li (note) Ta No kilo Ta 1024 Ta 1000
.It Li M Ta No mega Ta 1048576 Ta 1000000
.It Li G Ta No giga Ta 1073741824 Ta 1000000000
.It Li T Ta No tera Ta 1099511627776 Ta 1000000000000
.It Li P Ta No peta Ta 1125899906842624 Ta 1000000000000000
.It Li E Ta No exa Ta 1152921504606846976 Ta 1000000000000000000
.El
.Pp
Note:
An uppercase K indicates a power of two, a lowercase k a power of ten.
.Pp
The IEE/IEC (and now also SI) power of two prefixes are:
.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
.It Li Ki Ta No kibi Ta 1024
.It Li Mi Ta No mebi Ta 1048576
.It Li Gi Ta No gibi Ta 1073741824
.It Li Ti Ta No tebi Ta 1099511627776
.It Li Pi Ta No pebi Ta 1125899906842624
.It Li Ei Ta No exbi Ta 1152921504606846976
.El
.Pp
The
.Fa len
argument must be at least 4 plus the length of
.Fa suffix ,
in order to ensure a useful result is generated into
.Fa buf .
To use a specific prefix, specify this as
.Fa scale
.Po multiplier = 1024 ^ scale;
when
.Dv HN_DIVISOR_1000
is specified,
multiplier = 1000 ^ scale
.Pc .
This cannot be combined with any of the
.Fa scale
flags below.
.Pp
The following flags may be passed in
.Fa scale :
.Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
.It Dv HN_AUTOSCALE
Format the buffer using the lowest multiplier possible.
.It Dv HN_GETSCALE
Return the prefix index number (the number of times
.Fa number
must be divided to fit) instead of formatting it to the buffer.
.El
.Pp
The following flags may be passed in
.Fa flags :
.Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
.It Dv HN_DECIMAL
If the final result is less than 10, display it using one decimal place.
.It Dv HN_NOSPACE
Do not put a space between
.Fa number
and the prefix.
.It Dv HN_B
Use
.Ql B
(bytes) as prefix if the original result does not have a prefix.
.It Dv HN_DIVISOR_1000
Divide
.Fa number
with 1000 instead of 1024.
.It Dv HN_IEC_PREFIXES
Use the IEE/IEC notion of prefixes (Ki, Mi, Gi...).
This flag has no effect when
.Dv HN_DIVISOR_1000
is also specified.
.El
.Sh RETURN VALUES
Upon success, the
.Nm
function returns the number of characters that would have been stored in
.Fa buf
(excluding the terminating
.Dv NUL )
if
.Fa buf
was large enough, or \-1 upon failure.
Even upon failure, the contents of
.Fa buf
may be modified.
If
.Dv HN_GETSCALE
is specified, the prefix index number will be returned instead.
.\" .Sh SEE ALSO
.\" .Xr expand_number 3
.Sh STANDARDS
The
.Dv HN_DIVISOR_1000
and
.Dv HN_IEC_PREFIXES
flags
conform to
.Tn ISO/IEC
Std\~80000-13:2008
and
.Tn IEEE
Std\~1541-2002.
.Sh HISTORY
The
.Fn humanize_number
function first appeared in
.Nx 2.0
and then in
.Fx 5.3 .
The
.Dv HN_IEC_PREFIXES
flag was introduced in
.Fx 9.0 .

179
humanize_number.c Normal file
View File

@ -0,0 +1,179 @@
/* $NetBSD: humanize_number.c,v 1.14 2008/04/28 20:22:59 martin Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
* Copyright 2013 John-Mark Gurney <jmg@FreeBSD.org>
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <libutil.h>
static const int maxscale = 7;
int
humanize_number(char *buf, size_t len, int64_t quotient,
const char *suffix, int scale, int flags)
{
const char *prefixes, *sep;
int i, r, remainder, s1, s2, sign;
int divisordeccut;
int64_t divisor, max;
size_t baselen;
/* Since so many callers don't check -1, NUL terminate the buffer */
if (len > 0)
buf[0] = '\0';
/* validate args */
if (buf == NULL || suffix == NULL)
return (-1);
if (scale < 0)
return (-1);
else if (scale >= maxscale &&
((scale & ~(HN_AUTOSCALE|HN_GETSCALE)) != 0))
return (-1);
if ((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES))
return (-1);
/* setup parameters */
remainder = 0;
if (flags & HN_IEC_PREFIXES) {
baselen = 2;
/*
* Use the prefixes for power of two recommended by
* the International Electrotechnical Commission
* (IEC) in IEC 80000-3 (i.e. Ki, Mi, Gi...).
*
* HN_IEC_PREFIXES implies a divisor of 1024 here
* (use of HN_DIVISOR_1000 would have triggered
* an assertion earlier).
*/
divisor = 1024;
divisordeccut = 973; /* ceil(.95 * 1024) */
if (flags & HN_B)
prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
else
prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
} else {
baselen = 1;
if (flags & HN_DIVISOR_1000) {
divisor = 1000;
divisordeccut = 950;
if (flags & HN_B)
prefixes = "B\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
else
prefixes = "\0\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
} else {
divisor = 1024;
divisordeccut = 973; /* ceil(.95 * 1024) */
if (flags & HN_B)
prefixes = "B\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
else
prefixes = "\0\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
}
}
#define SCALE2PREFIX(scale) (&prefixes[(scale) * 3])
if (quotient < 0) {
sign = -1;
quotient = -quotient;
baselen += 2; /* sign, digit */
} else {
sign = 1;
baselen += 1; /* digit */
}
if (flags & HN_NOSPACE)
sep = "";
else {
sep = " ";
baselen++;
}
baselen += strlen(suffix);
/* Check if enough room for `x y' + suffix + `\0' */
if (len < baselen + 1)
return (-1);
if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
/* See if there is additional columns can be used. */
for (max = 1, i = len - baselen; i-- > 0 && max <= (INT64_MAX / 10);)
max *= 10;
/*
* Divide the number until it fits the given column.
* If there will be an overflow by the rounding below,
* divide once more.
*/
for (i = 0;
(quotient >= max || (quotient == max - 1 &&
remainder >= divisordeccut)) && i < maxscale; i++) {
remainder = quotient % divisor;
quotient /= divisor;
}
if (scale & HN_GETSCALE)
return (i);
} else {
for (i = 0; i < scale && i < maxscale; i++) {
remainder = quotient % divisor;
quotient /= divisor;
}
}
/* If a value <= 9.9 after rounding and ... */
/*
* XXX - should we make sure there is enough space for the decimal
* place and if not, don't do HN_DECIMAL?
*/
if (((quotient == 9 && remainder < divisordeccut) || quotient < 9) &&
i > 0 && flags & HN_DECIMAL) {
s1 = (int)quotient + ((remainder * 10 + divisor / 2) /
divisor / 10);
s2 = ((remainder * 10 + divisor / 2) / divisor) % 10;
r = snprintf(buf, len, "%d%s%d%s%s%s",
sign * s1, localeconv()->decimal_point, s2,
sep, SCALE2PREFIX(i), suffix);
} else
r = snprintf(buf, len, "%" PRId64 "%s%s%s",
sign * (quotient + (remainder + divisor / 2) / divisor),
sep, SCALE2PREFIX(i), suffix);
return (r);
}

20
libutil.exports Normal file
View File

@ -0,0 +1,20 @@
_freemntopts
_getmnt_silent
_getmntoptnum
_getmntopts
_getmntoptstr
_humanize_number
_pidfile_close
_pidfile_open
_pidfile_remove
_pidfile_write
_realhostname
_realhostname_sa
_reexec_to_match_kernel
_reexec_to_match_lp64ness
_tzlink
_wipefs_alloc
_wipefs_except_blocks
_wipefs_free
_wipefs_include_blocks
_wipefs_wipe

95
libutil.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 1996 Peter Wemm <peter@FreeBSD.org>.
* All rights reserved.
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* Portions of this software were developed for the FreeBSD Project by
* ThinkSec AS and NAI Labs, the Security Research Division of Network
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
* ("CBOSS"), as part of the DARPA CHATS research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/lib/libutil/libutil.h,v 1.42 2006/02/18 11:25:28 des Exp $
*/
#ifndef _LIBUTIL_H_
#define _LIBUTIL_H_
#include <unistd.h>
#include <stdbool.h>
#ifdef _SYS_PARAM_H_
/* for pidfile.c */
struct pidfh {
int pf_fd;
char pf_path[MAXPATHLEN + 1];
dev_t pf_dev;
ino_t pf_ino;
};
#else
struct pidfh;
#endif
struct in_addr;
struct sockaddr;
__BEGIN_DECLS
int humanize_number(char *_buf, size_t _len, int64_t _number,
const char *_suffix, int _scale, int _flags);
int realhostname(char *host, size_t hsize, const struct in_addr *ip);
int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr,
int addrlen);
struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
int pidfile_write(struct pidfh *pfh);
int pidfile_close(struct pidfh *pfh);
int pidfile_remove(struct pidfh *pfh);
int reexec_to_match_kernel(void);
int reexec_to_match_lp64ness(bool isLP64);
__END_DECLS
/* return values from realhostname() */
#define HOSTNAME_FOUND (0)
#define HOSTNAME_INCORRECTNAME (1)
#define HOSTNAME_INVALIDADDR (2)
#define HOSTNAME_INVALIDNAME (3)
/* Values for humanize_number(3)'s flags parameter. */
#define HN_DECIMAL 0x01
#define HN_NOSPACE 0x02
#define HN_B 0x04
#define HN_DIVISOR_1000 0x08
#define HN_IEC_PREFIXES 0x10
/* Values for humanize_number(3)'s scale parameter. */
#define HN_GETSCALE 0x10
#define HN_AUTOSCALE 0x20
#endif /* !_LIBUTIL_H_ */

34
libutil.plist Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>OpenSourceSCM</key>
<string>cvs -d freebsdanoncvs@anoncvs.FreeBSD.org:/home/ncvs co libutil</string>
<key>OpenSourceImportDate</key>
<string>2006-05-20</string>
<key>OpenSourceLicense</key>
<string>BSD</string>
<key>OpenSourceLicenseFile</key>
<string>libutil.txt</string>
<key>OpenSourceProject</key>
<string>libutil</string>
<key>OpenSourceVersion</key>
<string>2005-02-13</string>
</dict>
<dict>
<key>OpenSourceImportDate</key>
<string>2006-05-20</string>
<key>OpenSourceLicense</key>
<string>BSD</string>
<key>OpenSourceLicenseFile</key>
<string>libutil.txt</string>
<key>OpenSourceProject</key>
<string>libutil</string>
<key>OpenSourceVersion</key>
<string>1.3</string>
<key>OpenSourceURL</key>
<string>http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/lib/libutil/getmntopts.c?rev=1.3</string>
</dict>
</array>
</plist>

238
libutil.txt Normal file
View File

@ -0,0 +1,238 @@
_secure_path.c:
/*-
* Based on code copyright (c) 1995,1997 by
* Berkeley Software Design, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice immediately at the beginning of the file, without modification,
* this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. This work was done expressly for inclusion into FreeBSD. Other use
* is permitted provided this notation is included.
* 4. Absolutely no warranty of function or purpose is made by the authors.
* 5. Modifications may be freely made to this file providing the above
* conditions are met.
*/
fparseln.c:
/*
* Copyright (c) 1997 Christos Zoulas. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christos Zoulas.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
humanize_number.c:
/*
* Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
pidfile.c:
/*-
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
property.c:
/*
*
* Simple property list handling code.
*
* Copyright (c) 1998
* Jordan "Perky" Hubbard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* verbatim and that no modifications are made prior to this
* point in the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
realhostname.c:
/*-
* Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
trimdomain.c:
/*-
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
* Based on original work by Atsushi Murai <amurai@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
uucplock.c:
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

View File

@ -0,0 +1,827 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXAggregateTarget section */
3EB206C51F5096F100B150D3 /* bridgeos */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 3EB206CC1F5096F100B150D3 /* Build configuration list for PBXAggregateTarget "bridgeos" */;
buildPhases = (
);
dependencies = (
3EB206C61F5096F100B150D3 /* PBXTargetDependency */,
3EB206C81F5096F100B150D3 /* PBXTargetDependency */,
);
name = bridgeos;
productName = ios;
};
FDA4990F199D69B800A32E83 /* tests */ = {
isa = PBXAggregateTarget;
buildConfigurationList = FDA49910199D69B800A32E83 /* Build configuration list for PBXAggregateTarget "tests" */;
buildPhases = (
FDA46DEB1D6D10DE00C63528 /* CopyFiles */,
);
dependencies = (
FDA49918199D69C800A32E83 /* PBXTargetDependency */,
);
name = tests;
productName = tests;
};
FDBC26E41741B09300CA4B2B /* osx */ = {
isa = PBXAggregateTarget;
buildConfigurationList = FDBC26E71741B09300CA4B2B /* Build configuration list for PBXAggregateTarget "osx" */;
buildPhases = (
);
dependencies = (
FDBC27001741B1B300CA4B2B /* PBXTargetDependency */,
FDA49916199D69C600A32E83 /* PBXTargetDependency */,
3EB98B671E37CEFE0059EC72 /* PBXTargetDependency */,
);
name = osx;
productName = OSX;
};
FDBC26E81741B09D00CA4B2B /* ios */ = {
isa = PBXAggregateTarget;
buildConfigurationList = FDBC26E91741B09D00CA4B2B /* Build configuration list for PBXAggregateTarget "ios" */;
buildPhases = (
);
dependencies = (
FDBC27021741B1B500CA4B2B /* PBXTargetDependency */,
FDA49914199D69C100A32E83 /* PBXTargetDependency */,
FDBC27041741B1B700CA4B2B /* PBXTargetDependency */,
);
name = ios;
productName = ios;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
BA79F9CB13BB7207006A292D /* ExtentManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9A313BB70FF006A292D /* ExtentManager.cpp */; };
BA79F9CC13BB7207006A292D /* getmntopts.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9A613BB70FF006A292D /* getmntopts.c */; };
BA79F9CD13BB7207006A292D /* humanize_number.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9A813BB70FF006A292D /* humanize_number.c */; };
BA79F9CE13BB7207006A292D /* pidfile.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9B013BB70FF006A292D /* pidfile.c */; };
BA79F9D013BB7207006A292D /* realhostname.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9B513BB70FF006A292D /* realhostname.c */; };
BA79F9D113BB7207006A292D /* reexec_to_match_kernel.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9B713BB70FF006A292D /* reexec_to_match_kernel.c */; };
BA79F9D213BB7207006A292D /* trimdomain.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9B913BB70FF006A292D /* trimdomain.c */; };
BA79F9D413BB7207006A292D /* wipefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9BD13BB70FF006A292D /* wipefs.cpp */; };
BA79F9D513BB7235006A292D /* libutil.h in Headers */ = {isa = PBXBuildFile; fileRef = BA79F9AA13BB70FF006A292D /* libutil.h */; settings = {ATTRIBUTES = (Private, ); }; };
BA79F9D613BB7235006A292D /* mntopts.h in Headers */ = {isa = PBXBuildFile; fileRef = BA79F9AE13BB70FF006A292D /* mntopts.h */; settings = {ATTRIBUTES = (Private, ); }; };
BA79F9D713BB7235006A292D /* wipefs.h in Headers */ = {isa = PBXBuildFile; fileRef = BA79F9BE13BB70FF006A292D /* wipefs.h */; settings = {ATTRIBUTES = (Private, ); }; };
BA79F9D813BB7243006A292D /* ExtentManager.h in Headers */ = {isa = PBXBuildFile; fileRef = BA79F9A413BB70FF006A292D /* ExtentManager.h */; };
BA79F9DD13BB76B0006A292D /* getmntopts.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9A513BB70FF006A292D /* getmntopts.3 */; };
BA79F9DE13BB76B0006A292D /* humanize_number.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9A713BB70FF006A292D /* humanize_number.3 */; };
BA79F9DF13BB76B0006A292D /* pidfile.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9AF13BB70FF006A292D /* pidfile.3 */; };
BA79F9E113BB76B0006A292D /* realhostname_sa.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9B313BB70FF006A292D /* realhostname_sa.3 */; };
BA79F9E213BB76B0006A292D /* realhostname.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9B413BB70FF006A292D /* realhostname.3 */; };
BA79F9E313BB76B0006A292D /* reexec_to_match_kernel.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9B613BB70FF006A292D /* reexec_to_match_kernel.3 */; };
BA79F9E413BB76B0006A292D /* trimdomain.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9B813BB70FF006A292D /* trimdomain.3 */; };
BA79F9E613BB76B0006A292D /* wipefs.3 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9BC13BB70FF006A292D /* wipefs.3 */; };
BA79F9E913BB77FA006A292D /* libutil.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9AB13BB70FF006A292D /* libutil.plist */; };
BA79F9EA13BB77FF006A292D /* libutil.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = BA79F9AC13BB70FF006A292D /* libutil.txt */; };
FDA46DED1D6D110000C63528 /* libutil.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = FDA46DEC1D6D110000C63528 /* libutil.plist */; };
FDA4991B199D6A0400A32E83 /* humanize_number_test.c in Sources */ = {isa = PBXBuildFile; fileRef = FDA4991A199D6A0400A32E83 /* humanize_number_test.c */; };
FDA4991C199D6B9300A32E83 /* libutil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BA79F9C513BB718B006A292D /* libutil.dylib */; };
FDBC27051741B1C300CA4B2B /* com.apple.tzlinkd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = FDBC26FA1741B19000CA4B2B /* com.apple.tzlinkd.plist */; };
FDBC27061741B1CF00CA4B2B /* tzlinkd.c in Sources */ = {isa = PBXBuildFile; fileRef = FDBC26FE1741B19000CA4B2B /* tzlinkd.c */; };
FDBC27071741B1D600CA4B2B /* tzlink.c in Sources */ = {isa = PBXBuildFile; fileRef = FDBC26F91741B18500CA4B2B /* tzlink.c */; };
FDBC270B1741B55400CA4B2B /* tzlink.h in Headers */ = {isa = PBXBuildFile; fileRef = FDBC27091741B47200CA4B2B /* tzlink.h */; settings = {ATTRIBUTES = (Private, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
3EB206C71F5096F100B150D3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = BA79F9C413BB718B006A292D;
remoteInfo = util;
};
3EB206C91F5096F100B150D3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FDA4990F199D69B800A32E83;
remoteInfo = tests;
};
3EB98B661E37CEFE0059EC72 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FDBC26EF1741B13400CA4B2B;
remoteInfo = tzlinkd;
};
FDA49913199D69C100A32E83 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FDA4990F199D69B800A32E83;
remoteInfo = tests;
};
FDA49915199D69C600A32E83 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FDA4990F199D69B800A32E83;
remoteInfo = tests;
};
FDA49917199D69C800A32E83 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FDA49902199D69B000A32E83;
remoteInfo = humanize_number_test;
};
FDBC26FF1741B1B300CA4B2B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = BA79F9C413BB718B006A292D;
remoteInfo = util;
};
FDBC27011741B1B500CA4B2B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = BA79F9C413BB718B006A292D;
remoteInfo = util;
};
FDBC27031741B1B700CA4B2B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BA79F99713BB70D7006A292D /* Project object */;
proxyType = 1;
remoteGlobalIDString = FDBC26EF1741B13400CA4B2B;
remoteInfo = tzlinkd;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
BA79F9DB13BB7698006A292D /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/local/share/man/man3;
dstSubfolderSpec = 0;
files = (
BA79F9DD13BB76B0006A292D /* getmntopts.3 in CopyFiles */,
BA79F9DE13BB76B0006A292D /* humanize_number.3 in CopyFiles */,
BA79F9DF13BB76B0006A292D /* pidfile.3 in CopyFiles */,
BA79F9E113BB76B0006A292D /* realhostname_sa.3 in CopyFiles */,
BA79F9E213BB76B0006A292D /* realhostname.3 in CopyFiles */,
BA79F9E313BB76B0006A292D /* reexec_to_match_kernel.3 in CopyFiles */,
BA79F9E413BB76B0006A292D /* trimdomain.3 in CopyFiles */,
BA79F9E613BB76B0006A292D /* wipefs.3 in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
BA79F9E713BB77BB006A292D /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/local/OpenSourceVersions;
dstSubfolderSpec = 0;
files = (
BA79F9E913BB77FA006A292D /* libutil.plist in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
BA79F9E813BB77D6006A292D /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/local/OpenSourceLicenses;
dstSubfolderSpec = 0;
files = (
BA79F9EA13BB77FF006A292D /* libutil.txt in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
FDA46DEB1D6D10DE00C63528 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /AppleInternal/CoreOS/BATS/unit_tests;
dstSubfolderSpec = 0;
files = (
FDA46DED1D6D110000C63528 /* libutil.plist in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FDBC26EE1741B13400CA4B2B /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /System/Library/LaunchDaemons;
dstSubfolderSpec = 0;
files = (
FDBC27051741B1C300CA4B2B /* com.apple.tzlinkd.plist in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
3F09C378186D1F73007AF93C /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = "<group>"; };
3F7A5E8820510D34007087AF /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = "<group>"; };
BA79F9A313BB70FF006A292D /* ExtentManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ExtentManager.cpp; sourceTree = "<group>"; };
BA79F9A413BB70FF006A292D /* ExtentManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtentManager.h; sourceTree = "<group>"; };
BA79F9A513BB70FF006A292D /* getmntopts.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getmntopts.3; sourceTree = "<group>"; };
BA79F9A613BB70FF006A292D /* getmntopts.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = getmntopts.c; sourceTree = "<group>"; };
BA79F9A713BB70FF006A292D /* humanize_number.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = humanize_number.3; sourceTree = "<group>"; };
BA79F9A813BB70FF006A292D /* humanize_number.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = humanize_number.c; sourceTree = "<group>"; };
BA79F9A913BB70FF006A292D /* libutil.exports */ = {isa = PBXFileReference; lastKnownFileType = text; path = libutil.exports; sourceTree = "<group>"; };
BA79F9AA13BB70FF006A292D /* libutil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libutil.h; sourceTree = "<group>"; };
BA79F9AB13BB70FF006A292D /* libutil.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = libutil.plist; sourceTree = "<group>"; };
BA79F9AC13BB70FF006A292D /* libutil.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = libutil.txt; sourceTree = "<group>"; };
BA79F9AE13BB70FF006A292D /* mntopts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mntopts.h; sourceTree = "<group>"; };
BA79F9AF13BB70FF006A292D /* pidfile.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = pidfile.3; sourceTree = "<group>"; };
BA79F9B013BB70FF006A292D /* pidfile.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pidfile.c; sourceTree = "<group>"; };
BA79F9B313BB70FF006A292D /* realhostname_sa.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = realhostname_sa.3; sourceTree = "<group>"; };
BA79F9B413BB70FF006A292D /* realhostname.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = realhostname.3; sourceTree = "<group>"; };
BA79F9B513BB70FF006A292D /* realhostname.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = realhostname.c; sourceTree = "<group>"; };
BA79F9B613BB70FF006A292D /* reexec_to_match_kernel.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = reexec_to_match_kernel.3; sourceTree = "<group>"; };
BA79F9B713BB70FF006A292D /* reexec_to_match_kernel.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = reexec_to_match_kernel.c; sourceTree = "<group>"; };
BA79F9B813BB70FF006A292D /* trimdomain.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = trimdomain.3; sourceTree = "<group>"; };
BA79F9B913BB70FF006A292D /* trimdomain.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = trimdomain.c; sourceTree = "<group>"; };
BA79F9BC13BB70FF006A292D /* wipefs.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = wipefs.3; sourceTree = "<group>"; };
BA79F9BD13BB70FF006A292D /* wipefs.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wipefs.cpp; sourceTree = "<group>"; };
BA79F9BE13BB70FF006A292D /* wipefs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wipefs.h; sourceTree = "<group>"; };
BA79F9C513BB718B006A292D /* libutil.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libutil.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
FDA46DEC1D6D110000C63528 /* libutil.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = libutil.plist; sourceTree = "<group>"; };
FDA49903199D69B000A32E83 /* humanize_number_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = humanize_number_test; sourceTree = BUILT_PRODUCTS_DIR; };
FDA4991A199D6A0400A32E83 /* humanize_number_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = humanize_number_test.c; sourceTree = "<group>"; };
FDA4991D199D6CB800A32E83 /* test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = test.xcconfig; sourceTree = "<group>"; };
FDBC26F01741B13400CA4B2B /* tzlinkd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tzlinkd; sourceTree = BUILT_PRODUCTS_DIR; };
FDBC26F91741B18500CA4B2B /* tzlink.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tzlink.c; sourceTree = "<group>"; };
FDBC26FA1741B19000CA4B2B /* com.apple.tzlinkd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.tzlinkd.plist; sourceTree = "<group>"; };
FDBC26FB1741B19000CA4B2B /* com.apple.tzlinkd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.tzlinkd.sb; sourceTree = "<group>"; };
FDBC26FE1741B19000CA4B2B /* tzlinkd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tzlinkd.c; sourceTree = "<group>"; };
FDBC27081741B47200CA4B2B /* tzlink_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tzlink_internal.h; sourceTree = "<group>"; };
FDBC27091741B47200CA4B2B /* tzlink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tzlink.h; sourceTree = "<group>"; };
FDBC270D1741B66500CA4B2B /* tzlinkd.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = tzlinkd.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
BA79F9C213BB718B006A292D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
FDA49900199D69B000A32E83 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FDA4991C199D6B9300A32E83 /* libutil.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FDBC26ED1741B13400CA4B2B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
7259A9711D519321008F83F6 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
BA79F99513BB70D7006A292D = {
isa = PBXGroup;
children = (
BA79F9A313BB70FF006A292D /* ExtentManager.cpp */,
BA79F9A413BB70FF006A292D /* ExtentManager.h */,
BA79F9A513BB70FF006A292D /* getmntopts.3 */,
BA79F9A613BB70FF006A292D /* getmntopts.c */,
BA79F9A713BB70FF006A292D /* humanize_number.3 */,
BA79F9A813BB70FF006A292D /* humanize_number.c */,
BA79F9A913BB70FF006A292D /* libutil.exports */,
BA79F9AA13BB70FF006A292D /* libutil.h */,
BA79F9AB13BB70FF006A292D /* libutil.plist */,
BA79F9AC13BB70FF006A292D /* libutil.txt */,
BA79F9AE13BB70FF006A292D /* mntopts.h */,
BA79F9AF13BB70FF006A292D /* pidfile.3 */,
BA79F9B013BB70FF006A292D /* pidfile.c */,
BA79F9B313BB70FF006A292D /* realhostname_sa.3 */,
BA79F9B413BB70FF006A292D /* realhostname.3 */,
BA79F9B513BB70FF006A292D /* realhostname.c */,
BA79F9B613BB70FF006A292D /* reexec_to_match_kernel.3 */,
BA79F9B713BB70FF006A292D /* reexec_to_match_kernel.c */,
FDA49919199D6A0400A32E83 /* tests */,
BA79F9B813BB70FF006A292D /* trimdomain.3 */,
BA79F9B913BB70FF006A292D /* trimdomain.c */,
FDBC26F91741B18500CA4B2B /* tzlink.c */,
FDBC27091741B47200CA4B2B /* tzlink.h */,
FDBC27081741B47200CA4B2B /* tzlink_internal.h */,
FDBC26F11741B13400CA4B2B /* tzlinkd */,
BA79F9BC13BB70FF006A292D /* wipefs.3 */,
BA79F9BD13BB70FF006A292D /* wipefs.cpp */,
BA79F9BE13BB70FF006A292D /* wipefs.h */,
FDBC270C1741B66500CA4B2B /* xcconfigs */,
BA79F9C613BB718B006A292D /* Products */,
7259A9711D519321008F83F6 /* Frameworks */,
);
sourceTree = "<group>";
};
BA79F9C613BB718B006A292D /* Products */ = {
isa = PBXGroup;
children = (
BA79F9C513BB718B006A292D /* libutil.dylib */,
FDBC26F01741B13400CA4B2B /* tzlinkd */,
FDA49903199D69B000A32E83 /* humanize_number_test */,
);
name = Products;
sourceTree = "<group>";
};
FDA49919199D6A0400A32E83 /* tests */ = {
isa = PBXGroup;
children = (
FDA46DEC1D6D110000C63528 /* libutil.plist */,
FDA4991A199D6A0400A32E83 /* humanize_number_test.c */,
);
path = tests;
sourceTree = "<group>";
};
FDBC26F11741B13400CA4B2B /* tzlinkd */ = {
isa = PBXGroup;
children = (
FDBC26FA1741B19000CA4B2B /* com.apple.tzlinkd.plist */,
FDBC26FB1741B19000CA4B2B /* com.apple.tzlinkd.sb */,
FDBC26FE1741B19000CA4B2B /* tzlinkd.c */,
);
path = tzlinkd;
sourceTree = "<group>";
};
FDBC270C1741B66500CA4B2B /* xcconfigs */ = {
isa = PBXGroup;
children = (
3F09C378186D1F73007AF93C /* base.xcconfig */,
3F7A5E8820510D34007087AF /* lib.xcconfig */,
FDA4991D199D6CB800A32E83 /* test.xcconfig */,
FDBC270D1741B66500CA4B2B /* tzlinkd.xcconfig */,
);
path = xcconfigs;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
BA79F9C313BB718B006A292D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
BA79F9D513BB7235006A292D /* libutil.h in Headers */,
BA79F9D613BB7235006A292D /* mntopts.h in Headers */,
FDBC270B1741B55400CA4B2B /* tzlink.h in Headers */,
BA79F9D713BB7235006A292D /* wipefs.h in Headers */,
BA79F9D813BB7243006A292D /* ExtentManager.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
BA79F9C413BB718B006A292D /* util */ = {
isa = PBXNativeTarget;
buildConfigurationList = BA79F9C713BB718B006A292D /* Build configuration list for PBXNativeTarget "util" */;
buildPhases = (
BA79F9C113BB718B006A292D /* Sources */,
BA79F9C213BB718B006A292D /* Frameworks */,
BA79F9C313BB718B006A292D /* Headers */,
BA79F9DA13BB750E006A292D /* ShellScript */,
BA79F9EB13BB7864006A292D /* ShellScript */,
BA79F9DB13BB7698006A292D /* CopyFiles */,
BA79F9E713BB77BB006A292D /* CopyFiles */,
BA79F9E813BB77D6006A292D /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = util;
productName = util;
productReference = BA79F9C513BB718B006A292D /* libutil.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
FDA49902199D69B000A32E83 /* humanize_number_test */ = {
isa = PBXNativeTarget;
buildConfigurationList = FDA4990E199D69B000A32E83 /* Build configuration list for PBXNativeTarget "humanize_number_test" */;
buildPhases = (
FDA498FF199D69B000A32E83 /* Sources */,
FDA49900199D69B000A32E83 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = humanize_number_test;
productName = humanize_number_test;
productReference = FDA49903199D69B000A32E83 /* humanize_number_test */;
productType = "com.apple.product-type.tool";
};
FDBC26EF1741B13400CA4B2B /* tzlinkd */ = {
isa = PBXNativeTarget;
buildConfigurationList = FDBC26F81741B13400CA4B2B /* Build configuration list for PBXNativeTarget "tzlinkd" */;
buildPhases = (
FDBC26EC1741B13400CA4B2B /* Sources */,
FDBC26ED1741B13400CA4B2B /* Frameworks */,
FDBC26EE1741B13400CA4B2B /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = tzlinkd;
productName = tzlinkd;
productReference = FDBC26F01741B13400CA4B2B /* tzlinkd */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
BA79F99713BB70D7006A292D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
};
buildConfigurationList = BA79F99A13BB70D7006A292D /* Build configuration list for PBXProject "libutil" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = BA79F99513BB70D7006A292D;
productRefGroup = BA79F9C613BB718B006A292D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
FDBC26E81741B09D00CA4B2B /* ios */,
3EB206C51F5096F100B150D3 /* bridgeos */,
FDBC26E41741B09300CA4B2B /* osx */,
BA79F9C413BB718B006A292D /* util */,
FDBC26EF1741B13400CA4B2B /* tzlinkd */,
FDA4990F199D69B800A32E83 /* tests */,
FDA49902199D69B000A32E83 /* humanize_number_test */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
BA79F9DA13BB750E006A292D /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
"$(BUILT_PRODUCTS_DIR)/libutil1.0.dylib",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -e\nset -x\n\nln -sf ${EXECUTABLE_NAME} \"${BUILT_PRODUCTS_DIR}/libutil1.0.dylib\"\n";
};
BA79F9EB13BB7864006A292D /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
);
outputPaths = (
"$(DSTROOT)/$(INSTALL_PATH)/libutil1.0.dylib",
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = "set -e\nset -x\n\nln -sf ${EXECUTABLE_NAME} \"${DSTROOT}/${INSTALL_PATH}/libutil1.0.dylib\"\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
BA79F9C113BB718B006A292D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BA79F9CB13BB7207006A292D /* ExtentManager.cpp in Sources */,
BA79F9CC13BB7207006A292D /* getmntopts.c in Sources */,
BA79F9CD13BB7207006A292D /* humanize_number.c in Sources */,
BA79F9CE13BB7207006A292D /* pidfile.c in Sources */,
BA79F9D013BB7207006A292D /* realhostname.c in Sources */,
BA79F9D113BB7207006A292D /* reexec_to_match_kernel.c in Sources */,
BA79F9D213BB7207006A292D /* trimdomain.c in Sources */,
FDBC27071741B1D600CA4B2B /* tzlink.c in Sources */,
BA79F9D413BB7207006A292D /* wipefs.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FDA498FF199D69B000A32E83 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FDA4991B199D6A0400A32E83 /* humanize_number_test.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FDBC26EC1741B13400CA4B2B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FDBC27061741B1CF00CA4B2B /* tzlinkd.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
3EB206C61F5096F100B150D3 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = BA79F9C413BB718B006A292D /* util */;
targetProxy = 3EB206C71F5096F100B150D3 /* PBXContainerItemProxy */;
};
3EB206C81F5096F100B150D3 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FDA4990F199D69B800A32E83 /* tests */;
targetProxy = 3EB206C91F5096F100B150D3 /* PBXContainerItemProxy */;
};
3EB98B671E37CEFE0059EC72 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FDBC26EF1741B13400CA4B2B /* tzlinkd */;
targetProxy = 3EB98B661E37CEFE0059EC72 /* PBXContainerItemProxy */;
};
FDA49914199D69C100A32E83 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FDA4990F199D69B800A32E83 /* tests */;
targetProxy = FDA49913199D69C100A32E83 /* PBXContainerItemProxy */;
};
FDA49916199D69C600A32E83 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FDA4990F199D69B800A32E83 /* tests */;
targetProxy = FDA49915199D69C600A32E83 /* PBXContainerItemProxy */;
};
FDA49918199D69C800A32E83 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FDA49902199D69B000A32E83 /* humanize_number_test */;
targetProxy = FDA49917199D69C800A32E83 /* PBXContainerItemProxy */;
};
FDBC27001741B1B300CA4B2B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = BA79F9C413BB718B006A292D /* util */;
targetProxy = FDBC26FF1741B1B300CA4B2B /* PBXContainerItemProxy */;
};
FDBC27021741B1B500CA4B2B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = BA79F9C413BB718B006A292D /* util */;
targetProxy = FDBC27011741B1B500CA4B2B /* PBXContainerItemProxy */;
};
FDBC27041741B1B700CA4B2B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FDBC26EF1741B13400CA4B2B /* tzlinkd */;
targetProxy = FDBC27031741B1B700CA4B2B /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
3EB206CD1F5096F100B150D3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
3EB206CE1F5096F100B150D3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
BA79F99C13BB70D7006A292D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F09C378186D1F73007AF93C /* base.xcconfig */;
buildSettings = {
APPLY_RULES_IN_COPY_FILES = YES;
"PLIST_FILE_OUTPUT_FORMAT[sdk=iphoneos*]" = binary;
"PLIST_FILE_OUTPUT_FORMAT[sdk=macosx*]" = XML;
USE_HEADERMAP = NO;
};
name = Debug;
};
BA79F99D13BB70D7006A292D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F09C378186D1F73007AF93C /* base.xcconfig */;
buildSettings = {
APPLY_RULES_IN_COPY_FILES = YES;
"PLIST_FILE_OUTPUT_FORMAT[sdk=iphoneos*]" = binary;
"PLIST_FILE_OUTPUT_FORMAT[sdk=macosx*]" = XML;
USE_HEADERMAP = NO;
};
name = Release;
};
BA79F9C813BB718B006A292D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F7A5E8820510D34007087AF /* lib.xcconfig */;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
DYLIB_COMPATIBILITY_VERSION = 1.0;
DYLIB_CURRENT_VERSION = 1.0;
EXECUTABLE_PREFIX = lib;
EXPORTED_SYMBOLS_FILE = libutil.exports;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "$(SRCROOT)";
INSTALL_PATH = /usr/lib;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_TEXT_BASED_API = YES;
TAPI_VERIFY_MODE = Pedantic;
WARNING_CFLAGS = "-Wall";
};
name = Debug;
};
BA79F9C913BB718B006A292D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3F7A5E8820510D34007087AF /* lib.xcconfig */;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
DYLIB_COMPATIBILITY_VERSION = 1.0;
DYLIB_CURRENT_VERSION = 1.0;
EXECUTABLE_PREFIX = lib;
EXPORTED_SYMBOLS_FILE = libutil.exports;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "$(SRCROOT)";
INSTALL_PATH = /usr/lib;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_TEXT_BASED_API = YES;
TAPI_VERIFY_MODE = Pedantic;
WARNING_CFLAGS = "-Wall";
};
name = Release;
};
FDA4990C199D69B000A32E83 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FDA4991D199D6CB800A32E83 /* test.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
FDA4990D199D69B000A32E83 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FDA4991D199D6CB800A32E83 /* test.xcconfig */;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
FDA49911199D69B800A32E83 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
FDA49912199D69B800A32E83 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
FDBC26E51741B09300CA4B2B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
FDBC26E61741B09300CA4B2B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
FDBC26EA1741B09D00CA4B2B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
FDBC26EB1741B09D00CA4B2B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
FDBC26F61741B13400CA4B2B /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FDBC270D1741B66500CA4B2B /* tzlinkd.xcconfig */;
buildSettings = {
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
};
name = Debug;
};
FDBC26F71741B13400CA4B2B /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FDBC270D1741B66500CA4B2B /* tzlinkd.xcconfig */;
buildSettings = {
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3EB206CC1F5096F100B150D3 /* Build configuration list for PBXAggregateTarget "bridgeos" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3EB206CD1F5096F100B150D3 /* Debug */,
3EB206CE1F5096F100B150D3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
BA79F99A13BB70D7006A292D /* Build configuration list for PBXProject "libutil" */ = {
isa = XCConfigurationList;
buildConfigurations = (
BA79F99C13BB70D7006A292D /* Debug */,
BA79F99D13BB70D7006A292D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
BA79F9C713BB718B006A292D /* Build configuration list for PBXNativeTarget "util" */ = {
isa = XCConfigurationList;
buildConfigurations = (
BA79F9C813BB718B006A292D /* Debug */,
BA79F9C913BB718B006A292D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FDA4990E199D69B000A32E83 /* Build configuration list for PBXNativeTarget "humanize_number_test" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FDA4990C199D69B000A32E83 /* Debug */,
FDA4990D199D69B000A32E83 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FDA49910199D69B800A32E83 /* Build configuration list for PBXAggregateTarget "tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FDA49911199D69B800A32E83 /* Debug */,
FDA49912199D69B800A32E83 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FDBC26E71741B09300CA4B2B /* Build configuration list for PBXAggregateTarget "osx" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FDBC26E51741B09300CA4B2B /* Debug */,
FDBC26E61741B09300CA4B2B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FDBC26E91741B09D00CA4B2B /* Build configuration list for PBXAggregateTarget "ios" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FDBC26EA1741B09D00CA4B2B /* Debug */,
FDBC26EB1741B09D00CA4B2B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FDBC26F81741B13400CA4B2B /* Build configuration list for PBXNativeTarget "tzlinkd" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FDBC26F61741B13400CA4B2B /* Debug */,
FDBC26F71741B13400CA4B2B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = BA79F99713BB70D7006A292D /* Project object */;
}

138
mntopts.h Normal file
View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/* $NetBSD: mntopts.h,v 1.7 2006/02/12 01:32:06 chs Exp $ */
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mntopts.h 8.7 (Berkeley) 3/29/95
*/
#ifndef _MNTOPTS_H_
#define _MNTOPTS_H_
#ifdef __cplusplus
extern "C" {
#endif
struct mntopt {
const char *m_option; /* option name */
int m_inverse; /* if a negative option, eg "dev" */
int m_flag; /* bit to set, eg. MNT_RDONLY */
int m_altloc; /* 1 => set bit in altflags */
};
/* User-visible MNT_ flags. */
#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 }
#define MOPT_NODEV { "dev", 1, MNT_NODEV, 0 }
#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 }
#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 }
#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 }
#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 }
#define MOPT_UNION { "union", 0, MNT_UNION, 0 }
#define MOPT_USERQUOTA { "userquota", 0, 0, 0 }
#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 }
#define MOPT_BROWSE { "browse", 1, MNT_DONTBROWSE, 0 }
#define MOPT_AUTOMOUNTED { "automounted",0, MNT_AUTOMOUNTED, 0 }
#define MOPT_DEFWRITE { "defwrite", 0, MNT_DEFWRITE, 0}
#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0}
#define MOPT_IGNORE_OWNERSHIP { "owners", 1, MNT_IGNORE_OWNERSHIP, 0}
/* alias the deprecated name for compatibility */
#define MOPT_PERMISSIONS { "perm", 1, MNT_IGNORE_OWNERSHIP, 0}
#define MOPT_QUARANTINE { "quarantine", 0, MNT_QUARANTINE, 0}
#define MOPT_CPROTECT { "protect", 0, MNT_CPROTECT, 0 }
/* Control flags. */
#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 }
#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 }
#define MOPT_RELOAD { "reload", 0, MNT_RELOAD, 0 }
/* Support for old-style "ro", "rw" flags. */
#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 }
#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 }
/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */
#define MOPT_AUTO { "auto", 0, 0, 0 }
#define MOPT_FSTAB_COMPAT \
MOPT_RO, \
MOPT_RW, \
MOPT_AUTO
/* Standard options which all mounts can understand. */
#define MOPT_STDOPTS \
MOPT_USERQUOTA, \
MOPT_GROUPQUOTA, \
MOPT_FSTAB_COMPAT, \
MOPT_NODEV, \
MOPT_NOEXEC, \
MOPT_NOSUID, \
MOPT_RDONLY, \
MOPT_UNION, \
MOPT_BROWSE, \
MOPT_AUTOMOUNTED, \
MOPT_DEFWRITE, \
MOPT_NOATIME, \
MOPT_PERMISSIONS, \
MOPT_IGNORE_OWNERSHIP, \
MOPT_QUARANTINE, \
MOPT_CPROTECT
typedef struct mntoptparse *mntoptparse_t;
mntoptparse_t getmntopts(const char *, const struct mntopt *, int *, int *);
const char *getmntoptstr(mntoptparse_t, const char *);
long getmntoptnum(mntoptparse_t, const char *);
void freemntopts(mntoptparse_t);
extern int getmnt_silent;
#ifdef __cplusplus
}
#endif
#endif /* _MNTOPTS_H_ */

249
pidfile.3 Normal file
View File

@ -0,0 +1,249 @@
.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libutil/pidfile.3,v 1.5 2006/03/04 15:20:28 keramida Exp $
.\"
.Dd August 22, 2005
.Dt PIDFILE 3
.Os
.Sh NAME
.Nm pidfile_open ,
.Nm pidfile_write ,
.Nm pidfile_close ,
.Nm pidfile_remove
.Nd "library for PID files handling"
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In sys/param.h
.In libutil.h
.Ft "struct pidfh *"
.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
.Ft int
.Fn pidfile_write "struct pidfh *pfh"
.Ft int
.Fn pidfile_close "struct pidfh *pfh"
.Ft int
.Fn pidfile_remove "struct pidfh *pfh"
.Sh DESCRIPTION
The
.Nm pidfile
family of functions allows daemons to handle PID files.
It uses
.Xr flock 2
to lock a pidfile and detect already running daemons.
.Pp
The
.Fn pidfile_open
function opens (or creates) a file specified by the
.Fa path
argument and locks it with the
.Xr flock 2
system call.
If a file can not be locked, a PID of an already running daemon is returned in
the
.Fa pidptr
argument (if it is not
.Dv NULL ) .
The function does not write process' PID into the file here, so it can be
used before
.Fn fork Ns ing
and exit with a proper error message when needed.
If the
.Fa path
argument is
.Dv NULL ,
.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
file will be used.
.Pp
The
.Fn pidfile_write
function writes process' PID into a previously opened file.
.Pp
The
.Fn pidfile_close
function closes a pidfile.
It should be used after daemon
.Fn fork Ns s
to start a child process.
.Pp
The
.Fn pidfile_remove
function closes and removes a pidfile.
.Sh RETURN VALUES
The
.Fn pidfile_open
function returns a valid pointer to a
.Vt pidfh
structure on success, or
.Dv NULL
if an error occurs.
If an error occurs,
.Va errno
will be set.
.Rv -std pidfile_write pidfile_close pidfile_remove
.Sh EXAMPLES
The following example shows in which order these functions should be used.
Note that it is safe to pass
.Dv NULL
to
.Fn pidfile_write ,
.Fn pidfile_remove
and
.Fn pidfile_close
functions.
.Bd -literal
struct pidfh *pfh;
pid_t otherpid, childpid;
pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
if (pfh == NULL) {
if (errno == EEXIST) {
errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
(intmax_t)otherpid);
}
/* If we cannot create pidfile from other reasons, only warn. */
warn("Cannot open or create pidfile");
}
if (daemon(0, 0) == -1) {
warn("Cannot daemonize");
pidfile_remove(pfh);
exit(EXIT_FAILURE);
}
pidfile_write(pfh);
for (;;) {
/* Do work. */
childpid = fork();
switch (childpid) {
case -1:
syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
break;
case 0:
pidfile_close(pfh);
/* Do child work. */
break;
default:
syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
break;
}
}
pidfile_remove(pfh);
exit(EXIT_SUCCESS);
.Ed
.Sh ERRORS
The
.Fn pidfile_open
function will fail if:
.Bl -tag -width Er
.It Bq Er EEXIST
Some process already holds the lock on the given pidfile, meaning that a
daemon is already running.
.It Bq Er ENAMETOOLONG
Specified pidfile's name is too long.
.It Bq Er EINVAL
Some process already holds the lock on the given pidfile, but PID read
from there is invalid.
.El
.Pp
The
.Fn pidfile_open
function may also fail and set
.Va errno
for any errors specified for the
.Xr fstat 2 ,
.Xr open 2 ,
and
.Xr read 2
calls.
.Pp
The
.Fn pidfile_write
function will fail if:
.Bl -tag -width Er
.It Bq Er EDOOFUS
Improper function use.
Probably called before
.Fn pidfile_open .
.El
.Pp
The
.Fn pidfile_write
function may also fail and set
.Va errno
for any errors specified for the
.Xr fstat 2 ,
.Xr ftruncate 2 ,
and
.Xr write 2
calls.
.Pp
The
.Fn pidfile_close
function may fail and set
.Va errno
for any errors specified for the
.Xr close 2
and
.Xr fstat 2
calls.
.Pp
The
.Fn pidfile_remove
function will fail if:
.Bl -tag -width Er
.It Bq Er EDOOFUS
Improper function use.
Probably called not from the process which made
.Fn pidfile_write .
.El
.Pp
The
.Fn pidfile_remove
function may also fail and set
.Va errno
for any errors specified for the
.Xr close 2 ,
.Xr flock 2 ,
.Xr fstat 2 ,
.Xr write 2 ,
and
.Xr unlink 2
calls.
.Sh SEE ALSO
.Xr flock 2 ,
.Xr open 2 ,
.Xr daemon 3
.Sh AUTHORS
.An -nosplit
The
.Nm pidfile
functionality is based on ideas from
.An John-Mark Gurney Aq jmg@FreeBSD.org .
.Pp
The code and manual page was written by
.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org .

243
pidfile.c Normal file
View File

@ -0,0 +1,243 @@
/*-
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <err.h>
#include <errno.h>
#include <libutil.h>
static int _pidfile_remove(struct pidfh *pfh, int freeit);
static int
pidfile_verify(struct pidfh *pfh)
{
struct stat sb;
if (pfh == NULL || pfh->pf_fd == -1)
return EINVAL;
/*
* Check remembered descriptor.
*/
if (fstat(pfh->pf_fd, &sb) == -1)
return (errno);
if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
return EINVAL;
return (0);
}
static int
pidfile_read(const char *path, pid_t *pidptr)
{
char buf[16], *endptr;
int error, fd, i;
fd = open(path, O_RDONLY);
if (fd == -1)
return (errno);
i = read(fd, buf, sizeof(buf) - 1);
error = errno; /* Remember errno in case close() wants to change it. */
close(fd);
if (i == -1)
return (error);
buf[i] = '\0';
*pidptr = strtol(buf, &endptr, 10);
if (endptr != &buf[i])
return (EINVAL);
return (0);
}
struct pidfh *
pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
{
struct pidfh *pfh;
struct stat sb;
int error, fd;
pfh = malloc(sizeof(*pfh));
if (pfh == NULL)
return (NULL);
if (path == NULL) {
snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid",
getprogname());
} else {
strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path));
}
if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) {
free(pfh);
errno = ENAMETOOLONG;
return (NULL);
}
/*
* Open the PID file and obtain exclusive lock.
* We truncate PID file here only to remove old PID immediatelly,
* PID file will be truncated again in pidfile_write(), so
* pidfile_write() can be called multiple times.
*/
fd = open(pfh->pf_path,
O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode);
if (fd == -1) {
if (errno == EWOULDBLOCK && pidptr != NULL) {
errno = pidfile_read(pfh->pf_path, pidptr);
if (errno == 0)
errno = EEXIST;
}
free(pfh);
return (NULL);
}
/*
* Remember file information, so in pidfile_write() we are sure we write
* to the proper descriptor.
*/
if (fstat(fd, &sb) == -1) {
error = errno;
unlink(pfh->pf_path);
close(fd);
free(pfh);
errno = error;
return (NULL);
}
pfh->pf_fd = fd;
pfh->pf_dev = sb.st_dev;
pfh->pf_ino = sb.st_ino;
return (pfh);
}
int
pidfile_write(struct pidfh *pfh)
{
char pidstr[16];
int error, fd;
/*
* Check remembered descriptor, so we don't overwrite some other
* file if pidfile was closed and descriptor reused.
*/
errno = pidfile_verify(pfh);
if (errno != 0) {
/*
* Don't close descriptor, because we are not sure if it's ours.
*/
return (-1);
}
fd = pfh->pf_fd;
/*
* Truncate PID file, so multiple calls of pidfile_write() are allowed.
*/
if (ftruncate(fd, 0) == -1) {
error = errno;
_pidfile_remove(pfh, 0);
errno = error;
return (-1);
}
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
error = errno;
_pidfile_remove(pfh, 0);
errno = error;
return (-1);
}
return (0);
}
int
pidfile_close(struct pidfh *pfh)
{
int error;
error = pidfile_verify(pfh);
if (error != 0) {
errno = error;
return (-1);
}
if (close(pfh->pf_fd) == -1)
error = errno;
free(pfh);
if (error != 0) {
errno = error;
return (-1);
}
return (0);
}
static int
_pidfile_remove(struct pidfh *pfh, int freeit)
{
int error;
error = pidfile_verify(pfh);
if (error != 0) {
errno = error;
return (-1);
}
if (unlink(pfh->pf_path) == -1)
error = errno;
if (flock(pfh->pf_fd, LOCK_UN) == -1) {
if (error == 0)
error = errno;
}
if (close(pfh->pf_fd) == -1) {
if (error == 0)
error = errno;
}
if (freeit)
free(pfh);
else
pfh->pf_fd = -1;
if (error != 0) {
errno = error;
return (-1);
}
return (0);
}
int
pidfile_remove(struct pidfh *pfh)
{
return (_pidfile_remove(pfh, 1));
}

105
realhostname.3 Normal file
View File

@ -0,0 +1,105 @@
.\" Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libutil/realhostname.3,v 1.10 2005/02/13 22:25:14 ru Exp $
.\"
.Dd April 6, 1999
.Os
.Dt REALHOSTNAME 3
.Sh NAME
.Nm realhostname
.Nd "convert an IP number to the real host name"
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In netinet/in.h
.In libutil.h
.Ft int
.Fn realhostname "char *host" "size_t hsize" "const struct in_addr *ip"
.Sh DESCRIPTION
The function
.Fn realhostname
converts
.Ar ip
to the corresponding host name.
This is done by resolving
.Ar ip
to a host name and then ensuring that the host name resolves
back to
.Ar ip .
.Pp
.Ar host
must point to a buffer of at least
.Ar hsize
bytes, and will always be written to by this function.
.Pp
If the name resolution does not work both ways or if the host name is longer
than
.Ar hsize
bytes,
.Xr inet_ntoa 3
is used to convert
.Ar ip
to an ASCII form.
.Pp
If the string written to
.Ar host
is
.Ar hsize
bytes long,
.Ar host
will not be NUL terminated.
.Sh RETURN VALUES
The
.Fn realhostname
function will return one of the following constants which are defined in
.In libutil.h :
.Pp
.Bl -tag -width XXX -offset XXX
.It Li HOSTNAME_FOUND
A valid host name was found.
.It Li HOSTNAME_INCORRECTNAME
A host name was found, but it did not resolve back to the passed
.Ar ip .
.Ar host
now contains the numeric value of
.Ar ip .
.It Li HOSTNAME_INVALIDADDR
.Ar ip
could not be resolved.
.Ar host
now contains the numeric value of
.Ar ip .
.It Li HOSTNAME_INVALIDNAME
A host name was found, but it could not be resolved back to any ip number.
.Ar host
now contains the numeric value of
.Ar ip .
.El
.Sh SEE ALSO
.Xr gethostbyaddr 3 ,
.Xr gethostbyname 3 ,
.Xr inet_ntoa 3 ,
.Xr realhostname_sa 3

186
realhostname.c Normal file
View File

@ -0,0 +1,186 @@
/*-
* Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include "libutil.h"
struct sockinet {
u_char si_len;
u_char si_family;
u_short si_port;
};
void trimdomain(char *_fullhost, size_t _hostsize);
int
realhostname(char *host, size_t hsize, const struct in_addr *ip)
{
char trimmed[MAXHOSTNAMELEN];
int result;
struct hostent *hp;
result = HOSTNAME_INVALIDADDR;
hp = gethostbyaddr((const char *)ip, sizeof(*ip), AF_INET);
if (hp != NULL) {
strlcpy(trimmed, hp->h_name, sizeof(trimmed));
trimdomain(trimmed, strlen(trimmed));
if (strlen(trimmed) <= hsize) {
char lookup[MAXHOSTNAMELEN];
strncpy(lookup, hp->h_name, sizeof(lookup) - 1);
lookup[sizeof(lookup) - 1] = '\0';
hp = gethostbyname(lookup);
if (hp == NULL)
result = HOSTNAME_INVALIDNAME;
else for (; ; hp->h_addr_list++) {
if (*hp->h_addr_list == NULL) {
result = HOSTNAME_INCORRECTNAME;
break;
}
if (!memcmp(*hp->h_addr_list, ip, sizeof(*ip))) {
strncpy(host, trimmed, hsize);
return HOSTNAME_FOUND;
}
}
}
}
strncpy(host, inet_ntoa(*ip), hsize);
return result;
}
int
realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen)
{
int result, error;
char buf[NI_MAXHOST];
result = HOSTNAME_INVALIDADDR;
#ifdef INET6
/* IPv4 mapped IPv6 addr consideraton, specified in rfc2373. */
if (addr->sa_family == AF_INET6 &&
addrlen == sizeof(struct sockaddr_in6) &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr)) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)addr;
memset(&lsin, 0, sizeof(lsin));
lsin.sin_len = sizeof(struct sockaddr_in);
lsin.sin_family = AF_INET;
lsin.sin_port = sin6->sin6_port;
memcpy(&lsin.sin_addr, &sin6->sin6_addr.s6_addr[12],
sizeof(struct in_addr));
addr = (struct sockaddr *)&lsin;
addrlen = lsin.sin_len;
}
#endif
error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
NI_NAMEREQD);
if (error == 0) {
struct addrinfo hints, *res, *ores;
struct sockaddr *sa;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = addr->sa_family;
hints.ai_flags = AI_CANONNAME | AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(buf, NULL, &hints, &res);
if (error) {
result = HOSTNAME_INVALIDNAME;
goto numeric;
}
for (ores = res; ; res = res->ai_next) {
if (res == NULL) {
freeaddrinfo(ores);
result = HOSTNAME_INCORRECTNAME;
goto numeric;
}
sa = res->ai_addr;
if (sa == NULL) {
freeaddrinfo(ores);
result = HOSTNAME_INCORRECTNAME;
goto numeric;
}
if (sa->sa_len == addrlen &&
sa->sa_family == addr->sa_family) {
((struct sockinet *)sa)->si_port = ((struct sockinet *)addr)->si_port;
#ifdef INET6
/*
* XXX: sin6_socpe_id may not been
* filled by DNS
*/
if (sa->sa_family == AF_INET6 &&
((struct sockaddr_in6 *)sa)->sin6_scope_id == 0)
((struct sockaddr_in6 *)sa)->sin6_scope_id = ((struct sockaddr_in6 *)addr)->sin6_scope_id;
#endif
if (!memcmp(sa, addr, sa->sa_len)) {
result = HOSTNAME_FOUND;
if (ores->ai_canonname == NULL) {
freeaddrinfo(ores);
goto numeric;
}
strlcpy(buf, ores->ai_canonname,
sizeof(buf));
trimdomain(buf, hsize);
if (strlen(buf) > hsize &&
addr->sa_family == AF_INET) {
freeaddrinfo(ores);
goto numeric;
}
strncpy(host, buf, hsize);
break;
}
}
}
freeaddrinfo(ores);
} else {
numeric:
if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
NI_NUMERICHOST) == 0)
strncpy(host, buf, hsize);
}
return result;
}

133
realhostname_sa.3 Normal file
View File

@ -0,0 +1,133 @@
.\" Copyright (C) 1995, 1996, 1997, 1998, 1999, and 2000 WIDE Project.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the project nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libutil/realhostname_sa.3,v 1.11 2005/02/13 22:25:14 ru Exp $
.\"
.Dd January 11, 2000
.Os
.Dt REALHOSTNAME_SA 3
.Sh NAME
.Nm realhostname_sa
.Nd "convert a"
.Vt "struct sockaddr"
to the real host name
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In netinet/in.h
.In libutil.h
.Ft int
.Fn realhostname_sa "char *host" "size_t hsize" "struct sockaddr *addr" "int addrlen"
.Sh DESCRIPTION
The function
.Fn realhostname_sa
converts
.Ar addr
to the corresponding host name.
This is done by resolving
.Ar addr
to a host name and then ensuring that the host name resolves
back to
.Ar addr .
.Pp
.Ar host
must point to a buffer of at least
.Ar hsize
bytes, and will always be written to by this function.
.Pp
If the name resolution does not work both ways or if the host name is longer
than
.Ar hsize
bytes,
.Xr getnameinfo 3
with NI_NUMERICHOST specified, is used to convert
.Ar addr
to an ASCII form.
.Pp
If the string written to
.Ar host
is
.Ar hsize
bytes long,
.Ar host
will not be NUL terminated.
.Sh RETURN VALUES
The
.Fn realhostname_sa
function will return one of the following constants which are defined in
.In libutil.h :
.Pp
.Bl -tag -width XXX -offset XXX
.It Li HOSTNAME_FOUND
A valid host name was found.
.It Li HOSTNAME_INCORRECTNAME
A host name was found, but it did not resolve back to the passed
.Ar ip .
.Ar host
now contains the numeric value of
.Ar ip .
.It Li HOSTNAME_INVALIDADDR
.Ar ip
could not be resolved.
.Ar host
now contains the numeric value of
.Ar ip .
.It Li HOSTNAME_INVALIDNAME
A host name was found, but it could not be resolved back to any ip number.
.Ar host
now contains the numeric value of
.Ar ip .
.El
.Sh SEE ALSO
.Xr getaddrinfo 3 ,
.Xr getnameinfo 3 ,
.Xr realhostname 3

50
reexec_to_match_kernel.3 Normal file
View File

@ -0,0 +1,50 @@
.Dd Apr 14, 2008
.Dt REEXEC_TO_MATCH_KERNEL 3
.Os "Mac OS X"
.Sh NAME
.Nm reexec_to_match_kernel
.Nd Re-exec the current binary to match the ABI of the running kernel
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In libutil.h
.Ft int
.Fo reexec_to_match_kernel
.Fa "void"
.Fc
.Ft int
.Fo reexec_to_match_lp64ness
.Fa "bool isLP64"
.Fc
.Sh DESCRIPTION
The
.Fn reexec_to_match_kernel
function re-executes the current binary to match the ABI of the running kernel.
That is, if the current kernel is a 64-bit Intel kernel, it will attempt to
execute the 64-bit x86_64 userspace slice of the universal binary. The API
intentionally does not take arguments because its use should be transparent
to the program and to the user.
.Pp
The
.Fn reexec_to_match_lp64ness
is coarser-grained, and only attempts to match the word width that is requested.
For example, if the current system defaults to executing the 64-bit x86_64
userspace slice, but the program should instead run in 32-bit i386 mode,
this routine can be used.
.Pp
Both
.Fn reexec_to_match_kernel
and
.Fn reexec_to_match_lp64ness
can each be used exactly once in a program's lifetime. In certain circumstances,
it may even be desirable to use one, and then the other.
.Sh RETURN VALUES
The
.Fn reexec_to_match_kernel
and
.Fn reexec_to_match_lp64ness
functions return 0 if re-execution was not required. It returns -1 and
sets errno if there was an error performing the re-execution, for example
if the binary is not universal, or does not contain a slice to match the running
kernel's ABI. If the function succeeds, control never returns to the caller
and the program starts from main() again.

222
reexec_to_match_kernel.c Normal file
View File

@ -0,0 +1,222 @@
/*
* Copyright (c) 2008-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <sys/cdefs.h>
#include <spawn.h>
#include <errno.h>
#include <crt_externs.h>
#include <mach/mach.h>
#include <mach-o/loader.h>
#include <mach-o/dyld.h>
#include <sys/sysctl.h>
#include <stdlib.h>
#include <stdio.h>
#include "libutil.h"
static cpu_type_t current_program_arch(void);
static cpu_type_t current_kernel_arch(void);
static int reexec(cpu_type_t cputype, const char *guardenv);
#define kReExecToMatchKernel "REEXEC_TO_MATCH_KERNEL"
#define kReExecToMatchLP64 "REEXEC_TO_MATCH_LP64NESS"
int reexec_to_match_kernel(void)
{
cpu_type_t kernarch, progarch;
char *alreadyenv;
alreadyenv = getenv(kReExecToMatchKernel);
if (alreadyenv) {
/* we've done this at least once, assume
another try won't help */
return 0;
}
kernarch = current_kernel_arch();
progarch = current_program_arch();
if (kernarch == 0) {
/* could not determine kernel arch */
errno = EINVAL;
return -1;
}
if (kernarch == progarch) {
/* nothing to do here */
return 0;
}
/* Now we need to re-exec */
return reexec(kernarch, kReExecToMatchKernel);
}
int reexec_to_match_lp64ness(bool isLP64)
{
cpu_type_t kernarch, progarch, targetarch;
char *alreadyenv;
alreadyenv = getenv(kReExecToMatchLP64);
if (alreadyenv) {
/* we've done this at least once, assume
another try won't help */
return 0;
}
progarch = current_program_arch();
/* Check if the program is already the correct lp64ness */
if((!isLP64 && 0 == (progarch & CPU_ARCH_ABI64)) ||
(isLP64 && 0 != (progarch & CPU_ARCH_ABI64))) {
return 0;
}
kernarch = current_kernel_arch();
if (kernarch == 0) {
/* could not determine kernel arch */
errno = EINVAL;
return -1;
}
if (isLP64) {
targetarch = kernarch | CPU_ARCH_ABI64;
} else {
targetarch = kernarch & ~CPU_ARCH_ABI64;
}
if (targetarch == progarch) {
/* nothing to do here */
return 0;
}
/* Now we need to re-exec */
return reexec(targetarch, kReExecToMatchLP64);
}
static cpu_type_t current_program_arch(void)
{
cpu_type_t current_arch = (_NSGetMachExecuteHeader())->cputype;
return current_arch;
}
static cpu_type_t current_kernel_arch(void)
{
struct host_basic_info hi;
unsigned int size;
kern_return_t kret;
cpu_type_t current_arch;
int ret, mib[4];
size_t len;
struct kinfo_proc kp;
size = sizeof(hi)/sizeof(int);
kret = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hi, &size);
if (kret != KERN_SUCCESS) {
return 0;
}
current_arch = hi.cpu_type;
/* Now determine if the kernel is running in 64-bit mode */
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = 0; /* kernproc, pid 0 */
len = sizeof(kp);
ret = sysctl(mib, sizeof(mib)/sizeof(mib[0]), &kp, &len, NULL, 0);
if (ret == -1) {
return 0;
}
if (kp.kp_proc.p_flag & P_LP64) {
current_arch |= CPU_ARCH_ABI64;
}
return current_arch;
}
static int reexec(cpu_type_t cputype, const char *guardenv)
{
posix_spawnattr_t attr;
int ret, envcount;
size_t copied = 0;
char **argv, **oldenvp, **newenvp;
char execpath[MAXPATHLEN+1];
uint32_t execsize;
char guardstr[32];
argv = *_NSGetArgv();
oldenvp = *_NSGetEnviron();
for (envcount = 0; oldenvp[envcount]; envcount++);
// if there are 4 elements and a NULL, envcount will be 4
newenvp = calloc(envcount+2, sizeof(newenvp[0]));
for (envcount = 0; oldenvp[envcount]; envcount++) {
newenvp[envcount] = oldenvp[envcount];
}
snprintf(guardstr, sizeof(guardstr), "%s=1", guardenv);
newenvp[envcount++] = guardstr;
newenvp[envcount] = NULL;
execsize = (uint32_t)sizeof(execpath);
ret = _NSGetExecutablePath(execpath, &execsize);
if (ret != 0) {
return -1;
}
ret = posix_spawnattr_init(&attr);
if (ret != 0) {
return -1;
}
ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC);
if (ret != 0) {
return -1;
}
ret = posix_spawnattr_setbinpref_np(&attr, 1, &cputype, &copied);
if (ret != 0 || copied != 1) {
return -1;
}
#if 0
fprintf(stderr, "reexec: %s (arch=%d)\n", execpath, cputype);
for (envcount=0; newenvp[envcount]; envcount++) {
fprintf(stderr, "env[%d] = %s\n", envcount, newenvp[envcount]);
}
for (envcount=0; argv[envcount]; envcount++) {
fprintf(stderr, "argv[%d] = %s\n", envcount, argv[envcount]);
}
#endif
ret = posix_spawn(NULL, execpath, NULL, &attr, argv, newenvp);
if (ret != 0) {
errno = ret;
return -1;
}
/* should not be reached */
return 0;
}

85
trimdomain.3 Normal file
View File

@ -0,0 +1,85 @@
.\" Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libutil/trimdomain.3,v 1.8 2004/07/02 23:52:20 ru Exp $
.\"
.Dd April 7, 1999
.Os
.Dt TRIMDOMAIN 3
.Sh NAME
.Nm trimdomain
.Nd "trim the current domain name from a host name"
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In libutil.h
.Ft void
.Fn trimdomain "char *fullhost" "int hostsize"
.Sh DESCRIPTION
The function
.Fn trimdomain
removes the current domain name from the passed
.Ar fullhost
name by writing a
.Dv NUL
character over the first period of the passed name.
The current domain
name is determined by calling
.Xr gethostname 3
and removing everything up to the first period.
The name is determined
the first time this function is called and is cached for future use.
.Pp
The
.Fn trimdomain
function will only trim the domain name if the passed
.Ar fullname
ends with the current domain name and if the length of the resulting host
name does not exceed
.Ar hostsize .
.Pp
If the passed
.Ar fullname
is actually a
.Dv DISPLAY
specification of the form
.Sm off
.Ar host . domain : nn Oo .
.Ar nn
.Oc
.Sm on
and the domain name is the same as the local domain name,
.Fn trimdomain
will remove the embedded domain name, copying the screen and display
numbers to the end of the base host name and resulting in
.Sm off
.Ar host : nn Op . Ar nn .
.Sm on
.Sh RETURN VALUES
The
.Fn trimdomain
function does not return a value.
.Sh SEE ALSO
.Xr gethostname 3

116
trimdomain.c Normal file
View File

@ -0,0 +1,116 @@
/*-
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
* Based on original work by Atsushi Murai <amurai@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <libutil.h>
#include <string.h>
#include <unistd.h>
void trimdomain(char *_fullhost, size_t _hostsize);
static int isDISP(const char *);
/*-
* Trim the current domain name from fullhost, but only if the result
* is less than or equal to hostsize in length.
*
* This function understands $DISPLAY type fullhosts.
*
* For example:
*
* trimdomain("abcde.my.domain", 5) -> "abcde"
* trimdomain("abcde.my.domain", 4) -> "abcde.my.domain"
* trimdomain("abcde.my.domain:0.0", 9) -> "abcde:0.0"
* trimdomain("abcde.my.domain:0.0", 8) -> "abcde.my.domain:0.0"
*/
void
trimdomain(char *fullhost, size_t hostsize)
{
static size_t dlen;
static int first = 1;
static char domain[MAXHOSTNAMELEN];
char *end, *s;
size_t len;
if (first) {
/* XXX: Should we assume that our domain is this persistent ? */
first = 0;
if (gethostname(domain, sizeof(domain) - 1) == 0 &&
(s = strchr(domain, '.')) != NULL)
memmove(domain, s + 1, strlen(s + 1) + 1);
else
domain[0] = '\0';
dlen = strlen(domain);
}
if (domain[0] == '\0')
return;
s = fullhost;
end = (char *)((uintptr_t)s + hostsize + 1);
if ((s = memchr(s, '.', (size_t)(end - s))) != NULL) {
if (strncasecmp(s + 1, domain, dlen) == 0) {
if (s[dlen + 1] == '\0') {
/* Found -- lose the domain. */
*s = '\0';
} else if (s[dlen + 1] == ':' &&
isDISP(s + dlen + 2) &&
(len = strlen(s + dlen + 1)) < (size_t)(end - s)) {
/* Found -- shuffle the DISPLAY back. */
memmove(s, s + dlen + 1, len + 1);
}
}
}
}
/*
* Is the given string NN or NN.NN where ``NN'' is an all-numeric string ?
*/
static int
isDISP(const char *disp)
{
size_t w;
int res;
w = strspn(disp, "0123456789");
res = 0;
if (w > 0) {
if (disp[w] == '\0')
res = 1; /* NN */
else if (disp[w] == '.') {
disp += w + 1;
w = strspn(disp, "0123456789");
if (w > 0 && disp[w] == '\0')
res = 1; /* NN.NN */
}
}
return (res);
}

67
tzlink.c Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2013 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <TargetConditionals.h>
#include <xpc/xpc.h>
#include <errno.h>
#include "tzlink.h"
#include "tzlink_internal.h"
errno_t
tzlink(const char *tz)
{
#if TARGET_OS_IPHONE || TARGET_OS_OSX && !TARGET_OS_SIMULATOR
xpc_connection_t connection;
xpc_object_t request, reply;
errno_t e;
if (tz == NULL) {
return EINVAL;
}
connection = xpc_connection_create_mach_service(TZLINK_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
xpc_connection_set_event_handler(connection, ^(__unused xpc_object_t event) {
});
xpc_connection_resume(connection);
request = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(request, TZLINK_KEY_REQUEST_TIMEZONE, tz);
reply = xpc_connection_send_message_with_reply_sync(connection, request);
if (xpc_get_type(reply) == XPC_TYPE_DICTIONARY) {
e = (errno_t)xpc_dictionary_get_uint64(reply, TZLINK_KEY_REPLY_ERROR);
} else {
e = EIO;
}
xpc_release(reply);
xpc_release(request);
xpc_release(connection);
return e;
#else /* !TARGET_OS_IPHONE */
#pragma unused (tz)
return ENOTSUP;
#endif /* TARGET_OS_IPHONE */
}

58
tzlink.h Normal file
View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2013 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef _TZLINK_H_
#define _TZLINK_H_
#include <errno.h>
/*!
* @function tzlink
* Create the timezone link at TZDEFAULT
*
* @param tz
* New timezone, e.g. "America/Los_Angeles". This path is relative to TZDIR,
* and must not contain any relative path components or stray slashes.
* The file must exist and must be a valid timezone file with correct
* ownership (root:wheel) and permissions (0644).
*
* @result
* If the call succeeds, will return zero. Otherwise, returns an error:
* EINVAL: Invalid input, e.g. NULL or a path with relative components.
* ENAMETOOLONG: Input too long (generates a path > PATH_MAX)
* ENOENT: Specified file doesn't exist or fails owner/perm check.
* EPERM: Entitlement check failed.
* EIO: Failed to communicate with backing daemon.
* ENOTSUP: Always returned on OS X.
* And possibly others not documented here.
*
* @discussion
* This call can be used by any sufficiently-entitled client to overwrite
* the timezone link at TZDEFAULT (see <tzfile.h>). It communicates with a
* root daemon that does the necessary validation and file system work.
* Upon success, the "SignificantTimeChangeNotification" notification is
* posted.
*/
errno_t tzlink(const char *tz);
#endif /* !_TZLINK_H_ */

29
tzlink_internal.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2013 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#define TZLINK_SERVICE_NAME "com.apple.tzlink"
#define TZLINK_ENTITLEMENT "com.apple.tzlink.allow"
#define TZLINK_KEY_REQUEST_TIMEZONE "tz" // string
#define TZLINK_KEY_REPLY_ERROR "error" // uint64

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnableTransactions</key>
<true/>
<key>JetsamProperties</key>
<dict>
<key>JetsamMemoryLimit</key>
<integer>300</integer>
<key>JetsamPriority</key>
<integer>-49</integer>
</dict>
<key>Label</key>
<string>com.apple.tzlinkd</string>
<key>MachServices</key>
<dict>
<key>com.apple.tzlink</key>
<true/>
</dict>
<key>POSIXSpawnType</key>
<string>Adaptive</string>
<key>Program</key>
<string>/usr/libexec/tzlinkd</string>
</dict>
</plist>

View File

@ -0,0 +1,11 @@
(version 1)
(deny default)
(import "system.sb")
(allow file-write-create file-write-unlink
(literal "/private/var/db/timezone/localtime"))
(allow file-read*
(literal "/private/var/db/timezone/zoneinfo"))

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>seatbelt-profiles</key>
<array>
<string>com.apple.tzlinkd</string>
</array>
<key>com.apple.rootless.storage.timezone</key>
<true/>
</dict>
</plist>

201
tzlinkd/tzlinkd.c Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 2013 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <xpc/xpc.h>
#include <xpc/private.h>
#include <notify.h>
#include <tzfile.h>
#include <os/log.h>
#include "tzlink_internal.h"
static bool peer_entitled(xpc_connection_t);
static int set_timezone(const char *);
static int build_source_path(char *, size_t, const char *);
static int validate_source_path(const char *);
int
main(void)
{
dispatch_queue_t queue;
xpc_connection_t listener;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
xpc_track_activity();
#pragma clang diagnostic pop
queue = dispatch_queue_create(TZLINK_SERVICE_NAME, NULL);
listener = xpc_connection_create_mach_service(TZLINK_SERVICE_NAME, queue, XPC_CONNECTION_MACH_SERVICE_LISTENER);
xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) {
if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) {
return;
}
xpc_connection_set_target_queue(peer, queue);
xpc_connection_set_event_handler(peer, ^(xpc_object_t request) {
xpc_object_t reply;
const char *tz;
int error;
if (xpc_get_type(request) != XPC_TYPE_DICTIONARY) {
return;
}
if (peer_entitled(peer)) {
tz = xpc_dictionary_get_string(request, TZLINK_KEY_REQUEST_TIMEZONE);
error = tz ? set_timezone(tz) : EINVAL;
} else {
error = EPERM;
}
reply = xpc_dictionary_create_reply(request);
xpc_dictionary_set_uint64(reply, TZLINK_KEY_REPLY_ERROR, (uint64_t)error);
xpc_connection_send_message(peer, reply);
xpc_release(reply);
});
xpc_connection_resume(peer);
});
xpc_connection_resume(listener);
dispatch_main();
}
static bool
peer_entitled(xpc_connection_t peer)
{
xpc_object_t val;
bool entitled;
entitled = false;
val = xpc_connection_copy_entitlement_value(peer, TZLINK_ENTITLEMENT);
if (val != NULL) {
entitled = xpc_bool_get_value(val);
xpc_release(val);
}
return entitled;
}
static int
set_timezone(const char *tz)
{
char srcpath[PATH_MAX];
int error;
error = build_source_path(srcpath, sizeof(srcpath), tz);
if (error != 0) {
return error;
}
error = validate_source_path(srcpath);
if (error != 0) {
return error;
}
(void)unlink(TZDEFAULT);
if (symlink(srcpath, TZDEFAULT) != 0) {
return errno ? errno : EFAULT;
}
/*
* notifyd posts "com.apple.system.timezone" automatically,
* but we also need post this. Sigh.
*/
(void)notify_post("SignificantTimeChangeNotification");
return 0;
}
/* Create path from input. */
static int
build_source_path(char *path, size_t size, const char *tz)
{
char *str, *str0;
char *pathcomp;
int error;
if (strlcpy(path, TZDIR, size) >= size) {
return ENAMETOOLONG;
}
error = 0;
/* Attempt to validate the input; construct a clean path as we go. */
str0 = str = strdup(tz);
while ((pathcomp = strsep(&str, "/")) != NULL) {
if (pathcomp[0] == '\0' || pathcomp[0] == '.') {
error = EINVAL;
break;
}
if (strlcat(path, "/", size) >= size) {
error = ENAMETOOLONG;
break;
}
if (strlcat(path, pathcomp, size) >= size) {
error = ENAMETOOLONG;
break;
}
}
free(str0);
return error;
}
/* Validate path. */
static int
validate_source_path(const char *path)
{
struct stat sb;
if (lstat(path, &sb) != 0) {
return errno ? errno : EFAULT;
}
/* Ensure that the time zone file is... */
/* ... a regular file. */
if (!S_ISREG(sb.st_mode)) {
os_log_fault(OS_LOG_DEFAULT, "tzlink failed; \"%{public}s\" is not a regular file", path);
return ENOENT;
}
/* ... owned by root:wheel */
if (sb.st_uid != 0 || sb.st_gid != 0) {
os_log_fault(OS_LOG_DEFAULT, "tzlink failed; \"%{public}s\" is owned by %d:%d", path, sb.st_uid, sb.st_gid);
return ENOENT;
}
/* ... 0644 perms */
if ((sb.st_mode & ACCESSPERMS) != 0644) {
os_log_fault(OS_LOG_DEFAULT, "tzlink failed; \"%{public}s\" has access permissions %o", path, sb.st_mode);
return ENOENT;
}
/* ... is a real tzfile (starts with TZif) */
// TODO: Validate contents of file.
return 0;
}

162
wipefs.3 Normal file
View File

@ -0,0 +1,162 @@
.\"
.\" Copyright (c) 2008,2011 Apple Inc. All rights reserved.
.\"
.\" @APPLE_LICENSE_HEADER_START@
.\"
.\" This file contains Original Code and/or Modifications of Original Code
.\" as defined in and that are subject to the Apple Public Source License
.\" Version 2.0 (the 'License'). You may not use this file except in
.\" compliance with the License. Please obtain a copy of the License at
.\" http://www.opensource.apple.com/apsl/ and read it before using this
.\" file.
.\"
.\" The Original Code and all software distributed under the License are
.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
.\" Please see the License for the specific language governing rights and
.\" limitations under the License.
.\"
.\" @APPLE_LICENSE_HEADER_END@
.\"
.Dd 6/30/11 \" DATE
.Dt libutil 3 \" Program name and manual section number
.Os Mac OS X
.Sh NAME \" Section Header - required - don't modify
.\" The following lines are read in generating the apropos(man -k) database. Use only key
.\" words here as the database is built based on the words here and in the .ND line.
.Nm wipefs_alloc ,
.Nm wipefs_except_blocks ,
.Nm wipefs_wipe ,
.Nm wipefs_free
.\" Use .Nm macro to designate other names for the documented program.
.Nd wipes existing file systems on a volume
.Sh LIBRARY \" Section Header - required - don't modify
.Lb libutil
.Sh SYNOPSIS
.In wipefs.h
.Ft int
.Fo wipefs_alloc
.Fa "int fd"
.Fa "size_t block_size"
.Fa "wipefs_ctx *handle"
.Fc
.Ft int
.Fo wipefs_include_blocks
.Fa "wipefs_ctx handle"
.Fa "off_t block_offset"
.Fa "off_t nblocks"
.Fc
.Ft int
.Fo wipefs_except_blocks
.Fa "wipefs_ctx handle"
.Fa "off_t block_offset"
.Fa "off_t nblocks"
.Fc
.Ft int
.Fo wipefs_wipe
.Fa "wipefs_ctx handle"
.Fc
.Ft void
.Fo wipefs_free
.Fa "wipefs_ctx *handle"
.Fc
.Sh DESCRIPTION \" Section Header - required - don't modify
The wipefs family of functions wipe existing file systems on a volume. A
.Li DKIOCUNMAP
ioctl is sent to the device to invalidate all of its content.
Then zeroes are written to various locations that are used by various file systems to recognize their content and mount their volumes.
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.
.Pp
.Sy NOTE:
These routines do not overwrite all volume structures.
These routines do not securely erase the previous content.
They only overwrite enough to make sure that the normal utilities will no longer recognize any file system content.
It is possible that previous file system content could be recovered by other means.
.Pp
The
.Fn wipefs_alloc
function initializes a
.Fa wipefs_ctx
object (which is an opaque data type).
.Fa file_desc
is the file handle of the volume to be wiped, which can be a block device node, a character device node, or a file.
.Fa file_desc
must be opened with write access. If
.Fa block_size
is 0, this function calls
.Xr ioctl 2
to get the block size. A valid
.Fa block_size
must be supplied if
.Fa file_desc
is a regular file. This function does not write any data to the volume.
.Pp
The
.Fn wipefs_include_blocks
function tells wipefs to write zeroes in the block range provided, in addition to any other ranges
it would normally write. This may be more efficient than if the caller were to write this range
separately, especially if the block range overlaps or is contiguous with other ranges that wipefs
will write. This function does not write any data to the volume. If this function is called
multiple times, the union of all the ranges provided will be written by
.Fn wipefs_wipe .
.Pp
The
.Fn wipefs_except_blocks
function tells wipefs not to write anything in the block range provided. This function is used for performance
optimizations if the caller will write to these blocks. It is the caller's responsibility to write to these blocks.
Otherwise, some file systems may still be recognized on the volume. This function does not write any data to the
volume. If this function is called multiple times, the union of all the ranges provided will be excluded from being
written by
.Fn wipefs_wipe .
.Pp
The
.Fn wipefs_wipe
function sends a
.Li DKIOCUNMAP
ioctl and then writes data to the volume to wipe out existing file systems on it.
.Sy CAUTION:
this function destroys any file system or partition scheme on the volume represented by
.Fa file_desc .
If
.Fa file_desc
represents the entire disk (e.g. /dev/diskX), the partition map of the disk will be destroyed. If
.Fa file_desc
represents a partition (e.g., /dev/diskXsY), only the file system in that partition is destroyed. Although the partition scheme or file system on
.Fa file_desc
may be beyond repair after
.Fn wipefs_wipe ,
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.
.Pp
The
.Fn wipefs_free
function frees the allocated
.Fa wipefs_ctx
handle and set
.Fa *handlep
to NULL.
.Sh RETURN VALUES
The
.Fn wipefs_alloc ,
.Fn wipefs_include_blocks ,
.Fn wipefs_except_blocks
and
.Fn wipefs_wipe
functions return 0 on success, or will fail and return an error code.
Each function may return
.Fa ENOMEM
if insufficient memory is available. In addition, if
.Fa block_size
is not provided,
.Fn wipefs_alloc
may return any error
.Xr ioctl 2
returns;
.Fn wipefs_wipe
may return any error
.Xr pwrite 2
returns.
.\" .Sh BUGS \" Document known, unremedied bugs
.\".Sh HISTORY \" Document history if command behaves in a unique manner
.\"The wipefs family of functions first appeared in Mac OS X Leopard (10.5.3).

456
wipefs.cpp Normal file
View File

@ -0,0 +1,456 @@
/*
* Copyright (c) 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
//
// wipefs.cpp
//
#include <fcntl.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <sys/disk.h>
#include <sys/stat.h>
#include <sys/syslimits.h>
#include <string.h>
#include <spawn.h>
#include <os/log.h>
#include "ExtentManager.h"
#include "wipefs.h"
#define wipefs_roundup(x, y) ((((x)+((y)-1))/(y))*(y))
struct __wipefs_ctx {
int fd;
class ExtentManager extMan;
// xartutil information
char *diskname;
};
static void
AddExtentsForFutureFS(class ExtentManager *extMan)
{
// we don't know what blocks future FS will use to recognize itself. But we'd better be safe than sorry and write
// the first and last 2MB of the volume
off_t size = 2 * 1024 * 1024;
extMan->AddByteRangeExtent(0, size);
extMan->AddByteRangeExtent(extMan->totalBytes - size, size);
}
static void
AddExtentsForHFS(class ExtentManager *extMan)
{
// first 1KB is boot block, last 512B is reserved
// the Volume Header (512B) is after 1KB and before the last 512B
extMan->AddByteRangeExtent(0, 1024 + 512);
extMan->AddByteRangeExtent(extMan->totalBytes - 1024, 1024);
}
static void
AddExtentsForMSDOS(class ExtentManager *extMan)
{
// MSDOS needs the first block (in theory, up to 32KB)
extMan->AddByteRangeExtent(0, 32 * 1024);
}
static void
AddExtentsForNTFS(class ExtentManager *extMan)
{
// NTFS supports block size from 256B to 32768B. The first, middle and last block are needed
extMan->AddByteRangeExtent(0, 32 * 1024);
extMan->AddByteRangeExtent(extMan->totalBytes - 32 * 1024, 32 * 1024);
// to be safe, add the rage from (mid_point - 32KB) to (mid_point + 32KB)
extMan->AddByteRangeExtent(extMan->totalBytes / 2 - 32 * 1024, 64 * 1024);
}
static void
AddExtentsForUDF(class ExtentManager *extMan)
{
off_t lastBlockAddr = extMan->totalBlocks - 1;
// Volume Recognization Sequence (VRS) starts at 32KB, usually less than 7 Volume Structure Descriptors (2KB each)
extMan->AddByteRangeExtent(32 * 1024, 14 * 1024);
// AVDP is on 256, 512, last block, last block - 256
extMan->AddBlockRangeExtent(256, 1);
extMan->AddBlockRangeExtent(512, 1);
extMan->AddBlockRangeExtent(lastBlockAddr, 1);
extMan->AddBlockRangeExtent(lastBlockAddr - 256, 1);
// to be safe, assume the device has 2KB block size and do it again
if (extMan->blockSize != 2048) {
off_t blockSize = 2048;
// AVDP is on 256, 512, last block, last block - 256
extMan->AddByteRangeExtent(256 * blockSize, blockSize);
extMan->AddByteRangeExtent(512 * blockSize, blockSize);
extMan->AddByteRangeExtent(extMan->totalBytes - blockSize, blockSize);
extMan->AddByteRangeExtent(extMan->totalBytes - 256 * blockSize, blockSize);
}
}
static void
AddExtentsForUFS(class ExtentManager *extMan)
{
// UFS super block is 8KB at offset 8KB
extMan->AddByteRangeExtent(8192, 8192);
}
static void
AddExtentsForZFS(class ExtentManager *extMan)
{
// ZFS needs the first 512KB and last 512KB for all the 4 disk labels
extMan->AddByteRangeExtent(0, 512 * 1024);
extMan->AddByteRangeExtent(extMan->totalBytes - 512 * 1024, 512 * 1024);
}
static void
AddExtentsForPartitions(class ExtentManager *extMan)
{
// MBR (Master Boot Record) needs the first sector
// APM (Apple Partition Map) needs the second sector
// GPT (GUID Partition Table) needs the first 34 and last 33 sectors
extMan->AddByteRangeExtent(0, 512 * 34);
extMan->AddByteRangeExtent(extMan->totalBytes - 512 * 33, 512 * 33);
}
static void
AddExtentsForCoreStorage(class ExtentManager *extMan)
{
// the CoreStorage VolumeHeader structures reside in the first/last 512 bytes of each PV
extMan->AddByteRangeExtent(0, 512);
extMan->AddByteRangeExtent(extMan->totalBytes - 512, 512);
}
static char *
query_disk_info(int fd) {
char disk_path[PATH_MAX];
char *disk_name;
// Fetch the path
if (fcntl(fd, F_GETPATH, disk_path) == -1) {
return (NULL);
}
// Find the last pathname component.
disk_name = strrchr(disk_path, '/');
if (disk_name == NULL) {
// Not that we expect this to happen...
disk_name = disk_path;
} else {
// Skip over the '/'.
disk_name++;
}
if (*disk_name == 'r') {
// Raw device; skip over leading 'r'.
disk_name++;
}
// ...and make sure it's really a disk.
if (strncmp(disk_name, "disk", strlen("disk")) != 0) {
return (NULL);
}
return (strdup(disk_name));
}
static
int run_xartutil(char *const diskname)
{
pid_t child_pid, wait_pid;
posix_spawn_file_actions_t fileActions;
bool haveFileActions = false;
int child_status = 0;
int result = 0;
char arg1[] = "xartutil";
char arg2[] = "--erase-disk";
char *const xartutil_argv[] = {arg1, arg2, diskname, NULL};
result = posix_spawn_file_actions_init(&fileActions);
if (result) {
os_log_error(OS_LOG_DEFAULT, "Warning, init xartutil file actions error: %d", result);
result = -1;
goto out;
}
haveFileActions = true;
// Redirect stdout & stderr (results not critical, so we ignore return values).
posix_spawn_file_actions_addopen(&fileActions, STDOUT_FILENO, "/dev/null", O_WRONLY, 0);
posix_spawn_file_actions_addopen(&fileActions, STDERR_FILENO, "/dev/null", O_WRONLY, 0);
result = posix_spawn(&child_pid, "/usr/sbin/xartutil", &fileActions, NULL, xartutil_argv, NULL);
if (result) {
os_log_error(OS_LOG_DEFAULT, "Warning, unable to start xartutil, spawn error: %d", result);
result = -1;
goto out;
}
do {
wait_pid = waitpid(child_pid, &child_status, 0);
} while (wait_pid == -1 && errno == EINTR);
if (wait_pid == -1) {
os_log_error(OS_LOG_DEFAULT, "Warning, unable to start xartutil, waitpid error: %d", errno);
result = -1;
goto out;
}
if (WIFEXITED(child_status)) {
// xartutil terminated normally, get exit status
result = WEXITSTATUS(child_status);
if (result) {
os_log_error(OS_LOG_DEFAULT, "Warning, xartutil returned status %d", result);
}
} else {
result = -1;
if (WIFSIGNALED(child_status)) {
os_log_error(OS_LOG_DEFAULT, "Warning, xartutil terminated by signal: %u", WTERMSIG(child_status));
} else if (WIFSTOPPED(child_status)) {
os_log_error(OS_LOG_DEFAULT, "Warning, xartutil stopped by signal: %u", WSTOPSIG(child_status));
} else {
os_log_error(OS_LOG_DEFAULT, "Warning, xartutil terminated abnormally, status 0x%x", child_status);
}
}
out:
if (haveFileActions) {
posix_spawn_file_actions_destroy(&fileActions);
}
return (result);
}
extern "C" int
wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle)
{
int err = 0;
uint64_t numBlocks = 0;
uint32_t nativeBlockSize = 0;
off_t totalSizeInBytes = 0;
class ExtentManager *extMan = NULL;
struct stat sbuf = { 0 };
char *diskname = NULL;
*handle = NULL;
(void)fstat(fd, &sbuf);
switch (sbuf.st_mode & S_IFMT) {
case S_IFCHR:
case S_IFBLK:
if (ioctl(fd, DKIOCGETBLOCKSIZE, (char *)&nativeBlockSize) < 0) {
err = errno;
goto labelExit;
}
if (ioctl(fd, DKIOCGETBLOCKCOUNT, (char *)&numBlocks) < 0) {
err = errno;
goto labelExit;
}
totalSizeInBytes = numBlocks * nativeBlockSize;
diskname = query_disk_info(fd);
break;
case S_IFREG:
nativeBlockSize = sbuf.st_blksize;
numBlocks = sbuf.st_size / sbuf.st_blksize;
totalSizeInBytes = sbuf.st_size;
break;
default:
errno = EINVAL;
goto labelExit;
}
if (block_size == 0) {
block_size = nativeBlockSize;
}
if (block_size == 0 || totalSizeInBytes == 0) {
err = EINVAL;
goto labelExit;
}
try {
*handle = new __wipefs_ctx;
if (*handle == NULL) {
bad_alloc e;
throw e;
}
(*handle)->fd = fd;
(*handle)->diskname = NULL;
extMan = &(*handle)->extMan;
extMan->Init(block_size, nativeBlockSize, totalSizeInBytes);
AddExtentsForFutureFS(extMan);
AddExtentsForHFS(extMan);
AddExtentsForMSDOS(extMan);
AddExtentsForNTFS(extMan);
AddExtentsForUDF(extMan);
AddExtentsForUFS(extMan);
AddExtentsForZFS(extMan);
AddExtentsForPartitions(extMan);
AddExtentsForCoreStorage(extMan);
(*handle)->diskname = diskname;
}
catch (bad_alloc &e) {
err = ENOMEM;
}
catch (...) { // currently only ENOMEM is possible
err = ENOMEM;
}
labelExit:
if (err != 0) {
if (diskname != NULL)
free(diskname);
wipefs_free(handle);
}
return err;
} // wipefs_alloc
extern "C" int
wipefs_include_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks)
{
int err = 0;
try {
handle->extMan.AddBlockRangeExtent(block_offset, nblocks);
}
catch (bad_alloc &e) {
err = ENOMEM;
}
catch (...) { // currently only ENOMEM is possible
err = ENOMEM;
}
return err;
}
extern "C" int
wipefs_except_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks)
{
int err = 0;
try {
handle->extMan.RemoveBlockRangeExtent(block_offset, nblocks);
}
catch (bad_alloc &e) {
err = ENOMEM;
}
catch (...) { // currently only ENOMEM is possible
err = ENOMEM;
}
return err;
}
extern "C" int
wipefs_wipe(wipefs_ctx handle)
{
int err = 0;
uint8_t *bufZero = NULL;
ListExtIt curExt;
size_t bufSize;
dk_extent_t extent;
dk_unmap_t unmap;
if (handle->diskname != NULL) {
// Remove this disk's entry from the xART.
run_xartutil(handle->diskname);
}
memset(&extent, 0, sizeof(dk_extent_t));
extent.length = handle->extMan.totalBytes;
memset(&unmap, 0, sizeof(dk_unmap_t));
unmap.extents = &extent;
unmap.extentsCount = 1;
//
// Don't bother to check the return value since this is mostly
// informational for the lower-level drivers.
//
ioctl(handle->fd, DKIOCUNMAP, (caddr_t)&unmap);
bufSize = 128 * 1024; // issue large I/O to get better performance
if (handle->extMan.nativeBlockSize > bufSize) {
bufSize = handle->extMan.nativeBlockSize;
}
bufZero = new uint8_t[bufSize];
bzero(bufZero, bufSize);
off_t byteOffset, totalBytes;
size_t numBytes, numBytesToWrite, blockSize;
blockSize = handle->extMan.blockSize;
totalBytes = handle->extMan.totalBytes;
// write zero to all extents
for (curExt = handle->extMan.extentList.begin(); curExt != handle->extMan.extentList.end(); curExt++) {
byteOffset = curExt->blockAddr * blockSize;
numBytes = curExt->numBlocks * blockSize;
// make both offset and numBytes on native block boundary
if (byteOffset % handle->extMan.nativeBlockSize != 0 ||
numBytes % handle->extMan.nativeBlockSize != 0) {
size_t nativeBlockSize = handle->extMan.nativeBlockSize;
off_t newOffset, newEndOffset;
newOffset = byteOffset / nativeBlockSize * nativeBlockSize;
newEndOffset = wipefs_roundup(byteOffset + numBytes, nativeBlockSize);
byteOffset = newOffset;
numBytes = newEndOffset - newOffset;
}
if (byteOffset + (off_t)numBytes > totalBytes) {
numBytes = totalBytes - byteOffset;
}
while (numBytes > 0) {
numBytesToWrite = min(numBytes, bufSize);
if (pwrite(handle->fd, bufZero, numBytesToWrite, byteOffset) != (ssize_t)numBytesToWrite) {
err = errno;
goto labelExit;
}
numBytes -= numBytesToWrite;
byteOffset += numBytesToWrite;
}
}
labelExit:
(void)ioctl(handle->fd, DKIOCSYNCHRONIZECACHE);
if (bufZero != NULL)
delete[] bufZero;
return err;
} // wipefs_wipe
extern "C" void
wipefs_free(wipefs_ctx *handle)
{
if (*handle != NULL) {
char *diskname;
if ((diskname = (*handle)->diskname) != NULL)
free(diskname);
delete *handle;
*handle = NULL;
}
}

48
wipefs.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
//
// wipefs.h
//
#ifndef WIPEFS_H
#define WIPEFS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct __wipefs_ctx *wipefs_ctx;
__BEGIN_DECLS
extern int wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle);
extern int wipefs_include_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks);
extern int wipefs_except_blocks(wipefs_ctx handle, off_t block_offset, off_t nblocks);
extern int wipefs_wipe(wipefs_ctx handle);
extern void wipefs_free(wipefs_ctx *handle);
__END_DECLS
#ifdef __cplusplus
}
#endif
#endif // #ifndef WIPEFS_H

1
xcconfigs/base.xcconfig Normal file
View File

@ -0,0 +1 @@
#include "<DEVELOPER_DIR>/Makefiles/CoreOS/Xcode/BSD.xcconfig"

3
xcconfigs/lib.xcconfig Normal file
View File

@ -0,0 +1,3 @@
PUBLIC_HEADERS_FOLDER_PATH = /usr/include
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include
IS_ZIPPERED = YES

1
xcconfigs/test.xcconfig Normal file
View File

@ -0,0 +1 @@
INSTALL_PATH = /AppleInternal/Tests/libutil

View File

@ -0,0 +1,28 @@
INSTALL_PATH = /usr/libexec
PRODUCT_NAME = tzlinkd
CODE_SIGN_IDENTITY = -
CODE_SIGN_ENTITLEMENTS = tzlinkd/entitlements.plist
USER_HEADER_SEARCH_PATHS = $(SRCROOT)
ALWAYS_SEARCH_USER_PATHS = NO
GCC_TREAT_WARNINGS_AS_ERRORS = YES
CLANG_WARN_BOOL_CONVERSION = YES
CLANG_WARN_CONSTANT_CONVERSION = YES
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR
CLANG_WARN_EMPTY_BODY = YES
CLANG_WARN_ENUM_CONVERSION = YES
CLANG_WARN_INT_CONVERSION = YES
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
GCC_WARN_64_TO_32_BIT_CONVERSION = YES
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR
GCC_WARN_UNDECLARED_SELECTOR = YES
GCC_WARN_UNINITIALIZED_AUTOS = YES
GCC_WARN_UNUSED_FUNCTION = YES
GCC_WARN_UNUSED_VARIABLE = YES
GCC_WARN_UNKNOWN_PRAGMAS = YES
GCC_WARN_UNUSED_LABEL = YES
GCC_WARN_UNUSED_PARAMETER = YES