diff --git a/etc/dylib.conf b/etc/dylib.conf index 4ec207a28..173cf100b 100644 --- a/etc/dylib.conf +++ b/etc/dylib.conf @@ -3,4 +3,5 @@ /usr/lib/libc++.1.dylib=libc++.so.1 /usr/lib/libc++abi.dylib=libc++abi.so.1 /usr/lib/libiconv.2.dylib=libiconv.so +/usr/lib/libutil.dylib=libutil.so diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 38dddc213..20868f793 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,6 +59,7 @@ add_subdirectory(libinfo) add_subdirectory(libmalloc) add_subdirectory(libunwind) add_subdirectory(libsystem) +add_subdirectory(libutil) add_subdirectory(keymgr) add_subdirectory(libiconv) add_subdirectory(duct/src) diff --git a/src/dyld/CMakeLists.txt b/src/dyld/CMakeLists.txt index d985d67fd..518ffac53 100644 --- a/src/dyld/CMakeLists.txt +++ b/src/dyld/CMakeLists.txt @@ -29,11 +29,11 @@ endif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} S add_executable(dyld-bin ${dyld_SRCS}) set_target_properties(dyld-bin PROPERTIES OUTPUT_NAME dyld${SUFFIX}) -target_link_libraries(dyld-bin dyld util mach-o) +target_link_libraries(dyld-bin dyld darling-util mach-o) #if (NOT DEFINED SUFFIX OR SUFFIX STREQUAL "64") add_executable(dyldd dyldd.cpp) - target_link_libraries(dyldd dyld util mach-o) + target_link_libraries(dyldd dyld darling-util mach-o) install(TARGETS dyldd DESTINATION bin) #endif (NOT DEFINED SUFFIX OR SUFFIX STREQUAL "64") diff --git a/src/external/libcxx b/src/external/libcxx index a943d0247..13005b173 160000 --- a/src/external/libcxx +++ b/src/external/libcxx @@ -1 +1 @@ -Subproject commit a943d024709012d9e1ac6f8db0502509ba574ea6 +Subproject commit 13005b1738a889b0cc1a871548016d4a5adf9c4a diff --git a/src/libc/locale/FreeBSD/mbtowc.c b/src/libc/locale/FreeBSD/mbtowc.c index aeb75b7be..5f7d57fd4 100644 --- a/src/libc/locale/FreeBSD/mbtowc.c +++ b/src/libc/locale/FreeBSD/mbtowc.c @@ -43,7 +43,7 @@ mbtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, NORMALIZE_LOCALE(loc); if (s == NULL) { /* No support for state dependent encodings. */ - loc->__mbs_mbtowc = initial; + // loc->__mbs_mbtowc = initial; return (0); } rval = loc->__lc_ctype->__mbrtowc(pwc, s, n, &loc->__mbs_mbtowc, loc); diff --git a/src/libdyld/CMakeLists.txt b/src/libdyld/CMakeLists.txt index f414c978e..f2339632e 100644 --- a/src/libdyld/CMakeLists.txt +++ b/src/libdyld/CMakeLists.txt @@ -57,7 +57,7 @@ SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) add_library(dyld SHARED ${dyld_SRCS}) -target_link_libraries(dyld -ldl -lpthread mach-o util) +target_link_libraries(dyld -ldl -lpthread mach-o darling-util) install(TARGETS dyld DESTINATION lib${SUFFIX}/darling) diff --git a/src/libmach-o/CMakeLists.txt b/src/libmach-o/CMakeLists.txt index 0617164ac..960591c32 100644 --- a/src/libmach-o/CMakeLists.txt +++ b/src/libmach-o/CMakeLists.txt @@ -23,7 +23,7 @@ set(mach-o_SRCS add_library(mach-o SHARED ${mach-o_SRCS}) set_target_properties(mach-o PROPERTIES VERSION 1.0.0 SOVERSION 1.0) set_target_properties(mach-o PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") -target_link_libraries(mach-o -ldl -lpthread util) +target_link_libraries(mach-o -ldl -lpthread darling-util) install(TARGETS mach-o DESTINATION "lib${SUFFIX}/darling") diff --git a/src/libutil/CMakeLists.txt b/src/libutil/CMakeLists.txt new file mode 100644 index 000000000..c06e1928e --- /dev/null +++ b/src/libutil/CMakeLists.txt @@ -0,0 +1,36 @@ +project(libutil) + +cmake_minimum_required(VERSION 2.4.0) + +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + + +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 -Wl,--unresolved-symbols=ignore-all -Wl,--version-script=${DARLING_TOP_DIRECTORY}/darwin.map") +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${DARLING_TOP_DIRECTORY}/src/libc/include) +include_directories(${DARLING_TOP_DIRECTORY}/src/external/libcxx/include) + +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(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib${SUFFIX}/darling") +SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +add_library(util SHARED ${util_SRCS}) +target_link_libraries(util system) + +install(TARGETS util DESTINATION lib${SUFFIX}/darling) diff --git a/src/libutil/ExtentManager.cpp b/src/libutil/ExtentManager.cpp new file mode 100644 index 000000000..905b4325a --- /dev/null +++ b/src/libutil/ExtentManager.cpp @@ -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 +#include + +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 */ diff --git a/src/libutil/ExtentManager.h b/src/libutil/ExtentManager.h new file mode 100644 index 000000000..2dc25f6ec --- /dev/null +++ b/src/libutil/ExtentManager.h @@ -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 +#include +#include +#include +#include +#include +#include +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::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 extentList; +}; + +#endif // #ifndef EXTENTMANAGER_H diff --git a/src/libutil/getmntopts.3 b/src/libutil/getmntopts.3 new file mode 100644 index 000000000..c421b5ec5 --- /dev/null +++ b/src/libutil/getmntopts.3 @@ -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 . diff --git a/src/libutil/getmntopts.c b/src/libutil/getmntopts.c new file mode 100644 index 000000000..20d89bd15 --- /dev/null +++ b/src/libutil/getmntopts.c @@ -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 +#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 + +#include +#include +#include +#include +#include + +#include + +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; +} diff --git a/src/libutil/humanize_number.3 b/src/libutil/humanize_number.3 new file mode 100644 index 000000000..aa712a7f7 --- /dev/null +++ b/src/libutil/humanize_number.3 @@ -0,0 +1,148 @@ +.\" $NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $ +.\" $FreeBSD: src/lib/libutil/humanize_number.3,v 1.8 2005/04/10 12:15:25 delphij Exp $ +.\" +.\" 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. +.\" 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. +.\" +.Dd May 25, 2004 +.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 buffer . +A space and then +.Fa suffix +is appended to the end. +The buffer pointed to by +.Fa buffer +must be at least +.Fa len +bytes long. +.Pp +If the formatted number (including +.Fa suffix ) +would be too long to fit into +.Fa buffer , +then divide +.Fa number +by 1024 until it will. +In this case, prefix +.Fa suffix +with the appropriate SI designator. +.Pp +The prefixes are: +.Bl -column "Prefix" "Description" "Multiplier" -offset indent +.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier" +.It Li k Ta No kilo Ta 1024 +.It Li M Ta No mega Ta 1048576 +.It Li G Ta No giga Ta 1073741824 +.It Li T Ta No tera Ta 1099511627776 +.It Li P Ta No peta Ta 1125899906842624 +.It Li E Ta No exa 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 buffer . +To use a specific prefix, specify this as +.Fa scale +(multiplier = 1024 ^ scale). +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 digit. +.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. +.El +.Sh RETURN VALUES +The +.Fn humanize_number +function returns the number of characters stored in +.Fa buffer +(excluding the terminating +.Dv NUL ) +upon success, or \-1 upon failure. +If +.Dv HN_GETSCALE +is specified, the prefix index number will be returned instead. +.Sh HISTORY +The +.Fn humanize_number +function first appeared in +.Nx 2.0 . diff --git a/src/libutil/humanize_number.c b/src/libutil/humanize_number.c new file mode 100644 index 000000000..5f801cfe7 --- /dev/null +++ b/src/libutil/humanize_number.c @@ -0,0 +1,159 @@ +/* $NetBSD: humanize_number.c,v 1.8 2004/07/27 01:56:24 enami Exp $ */ + +/* + * 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. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +humanize_number(char *buf, size_t len, int64_t bytes, + const char *suffix, int scale, int flags) +{ + const char *prefixes, *sep; + int b, i, r, maxscale, s1, s2, sign; + int64_t divisor, max; + // We multiply bytes by 100 to deal with rounding, so we need something + // big enough to hold LLONG_MAX * 100. On 64-bit we can use 128-bit wide + // integers with __int128_t, but on 32-bit we have to use long double. +#ifdef __LP64__ + __int128_t scalable = (__int128_t)bytes; +#else + long double scalable = (long double)bytes; +#endif + size_t baselen; + + assert(buf != NULL); + assert(suffix != NULL); + assert(scale >= 0); + + if (flags & HN_DIVISOR_1000) { + /* SI for decimal multiplies */ + divisor = 1000; + if (flags & HN_B) + prefixes = "B\0k\0M\0G\0T\0P\0E"; + else + prefixes = "\0\0k\0M\0G\0T\0P\0E"; + } else { + /* + * binary multiplies + * XXX IEC 60027-2 recommends Ki, Mi, Gi... + */ + divisor = 1024; + if (flags & HN_B) + prefixes = "B\0K\0M\0G\0T\0P\0E"; + else + prefixes = "\0\0K\0M\0G\0T\0P\0E"; + } + +#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1]) + maxscale = 7; + + if (scale >= maxscale && + (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0) + return (-1); + + if (buf == NULL || suffix == NULL) + return (-1); + + if (len > 0) + buf[0] = '\0'; + if (bytes < 0) { + sign = -1; + scalable *= -100; + baselen = 3; /* sign, digit, prefix */ + } else { + sign = 1; + scalable *= 100; + baselen = 2; /* digit, prefix */ + } + 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 = 100, i = len - baselen; i-- > 0;) + max *= 10; + + for (i = 0; scalable >= max && i < maxscale; i++) + scalable /= divisor; + + if (scale & HN_GETSCALE) + return (i); + } else + for (i = 0; i < scale && i < maxscale; i++) + scalable /= divisor; + + /* If a value <= 9.9 after rounding and ... */ + if (scalable < 995 && i > 0 && flags & HN_DECIMAL) { + /* baselen + \0 + .N */ + if (len < baselen + 1 + 2) + return (-1); + b = ((int)scalable + 5) / 10; + s1 = b / 10; + s2 = b % 10; + r = snprintf(buf, len, "%s%d%s%d%s%s%s", + ((sign == -1) ? "-" : ""), + s1, localeconv()->decimal_point, s2, + sep, SCALE2PREFIX(i), suffix); + } else + r = snprintf(buf, len, "%s%lld%s%s%s", + /* LONGLONG */ + ((sign == -1) ? "-" : ""), + (long long)((scalable + 50) / 100), + sep, SCALE2PREFIX(i), suffix); + + return (r); +} diff --git a/src/libutil/libutil.exports b/src/libutil/libutil.exports new file mode 100644 index 000000000..7609d9d80 --- /dev/null +++ b/src/libutil/libutil.exports @@ -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 diff --git a/src/libutil/libutil.h b/src/libutil/libutil.h new file mode 100644 index 000000000..16a935ffd --- /dev/null +++ b/src/libutil/libutil.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1996 Peter Wemm . + * 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 +#include + +#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; +}; +#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); + +#ifdef _SYS_PARAM_H_ +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); +#endif + +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) + +/* humanize_number(3) */ +#define HN_DECIMAL 0x01 +#define HN_NOSPACE 0x02 +#define HN_B 0x04 +#define HN_DIVISOR_1000 0x08 + +#define HN_GETSCALE 0x10 +#define HN_AUTOSCALE 0x20 + +#endif /* !_LIBUTIL_H_ */ diff --git a/src/libutil/libutil.plist b/src/libutil/libutil.plist new file mode 100644 index 000000000..8633e1c78 --- /dev/null +++ b/src/libutil/libutil.plist @@ -0,0 +1,34 @@ + + + + + + OpenSourceSCM + cvs -d freebsdanoncvs@anoncvs.FreeBSD.org:/home/ncvs co libutil + OpenSourceImportDate + 2006-05-20 + OpenSourceLicense + BSD + OpenSourceLicenseFile + libutil.txt + OpenSourceProject + libutil + OpenSourceVersion + 2005-02-13 + + + OpenSourceImportDate + 2006-05-20 + OpenSourceLicense + BSD + OpenSourceLicenseFile + libutil.txt + OpenSourceProject + libutil + OpenSourceVersion + 1.3 + OpenSourceURL + http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/lib/libutil/getmntopts.c?rev=1.3 + + + diff --git a/src/libutil/libutil.txt b/src/libutil/libutil.txt new file mode 100644 index 000000000..02cb9934f --- /dev/null +++ b/src/libutil/libutil.txt @@ -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 + * 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 + * 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 + * Based on original work by Atsushi Murai + * 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. + */ diff --git a/src/libutil/libutil.xcodeproj/project.pbxproj b/src/libutil/libutil.xcodeproj/project.pbxproj new file mode 100644 index 000000000..965c679a4 --- /dev/null +++ b/src/libutil/libutil.xcodeproj/project.pbxproj @@ -0,0 +1,575 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + FDBC26E41741B09300CA4B2B /* osx */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDBC26E71741B09300CA4B2B /* Build configuration list for PBXAggregateTarget "osx" */; + buildPhases = ( + ); + dependencies = ( + FDBC27001741B1B300CA4B2B /* PBXTargetDependency */, + ); + name = osx; + productName = OSX; + }; + FDBC26E81741B09D00CA4B2B /* ios */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FDBC26E91741B09D00CA4B2B /* Build configuration list for PBXAggregateTarget "ios" */; + buildPhases = ( + ); + dependencies = ( + FDBC27021741B1B500CA4B2B /* 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 */; }; + 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 */ + 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 = "$(INSTALL_PATH_PREFIX)/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 = "$(INSTALL_PATH_PREFIX)/usr/local/OpenSourceVersions"; + dstSubfolderSpec = 0; + files = ( + BA79F9E913BB77FA006A292D /* libutil.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + BA79F9E813BB77D6006A292D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = "$(INSTALL_PATH_PREFIX)/usr/local/OpenSourceLicenses"; + dstSubfolderSpec = 0; + files = ( + BA79F9EA13BB77FF006A292D /* libutil.txt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + FDBC26EE1741B13400CA4B2B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(INSTALL_PATH_PREFIX)/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; name = base.xcconfig; path = xcconfigs/base.xcconfig; sourceTree = ""; }; + BA79F9A313BB70FF006A292D /* ExtentManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ExtentManager.cpp; sourceTree = ""; }; + BA79F9A413BB70FF006A292D /* ExtentManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtentManager.h; sourceTree = ""; }; + BA79F9A513BB70FF006A292D /* getmntopts.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getmntopts.3; sourceTree = ""; }; + BA79F9A613BB70FF006A292D /* getmntopts.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = getmntopts.c; sourceTree = ""; }; + BA79F9A713BB70FF006A292D /* humanize_number.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = humanize_number.3; sourceTree = ""; }; + BA79F9A813BB70FF006A292D /* humanize_number.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = humanize_number.c; sourceTree = ""; }; + BA79F9A913BB70FF006A292D /* libutil.exports */ = {isa = PBXFileReference; lastKnownFileType = text; path = libutil.exports; sourceTree = ""; }; + BA79F9AA13BB70FF006A292D /* libutil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libutil.h; sourceTree = ""; }; + BA79F9AB13BB70FF006A292D /* libutil.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = libutil.plist; sourceTree = ""; }; + BA79F9AC13BB70FF006A292D /* libutil.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = libutil.txt; sourceTree = ""; }; + BA79F9AE13BB70FF006A292D /* mntopts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mntopts.h; sourceTree = ""; }; + BA79F9AF13BB70FF006A292D /* pidfile.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = pidfile.3; sourceTree = ""; }; + BA79F9B013BB70FF006A292D /* pidfile.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pidfile.c; sourceTree = ""; }; + BA79F9B313BB70FF006A292D /* realhostname_sa.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = realhostname_sa.3; sourceTree = ""; }; + BA79F9B413BB70FF006A292D /* realhostname.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = realhostname.3; sourceTree = ""; }; + BA79F9B513BB70FF006A292D /* realhostname.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = realhostname.c; sourceTree = ""; }; + BA79F9B613BB70FF006A292D /* reexec_to_match_kernel.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = reexec_to_match_kernel.3; sourceTree = ""; }; + BA79F9B713BB70FF006A292D /* reexec_to_match_kernel.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = reexec_to_match_kernel.c; sourceTree = ""; }; + BA79F9B813BB70FF006A292D /* trimdomain.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = trimdomain.3; sourceTree = ""; }; + BA79F9B913BB70FF006A292D /* trimdomain.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = trimdomain.c; sourceTree = ""; }; + BA79F9BC13BB70FF006A292D /* wipefs.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = wipefs.3; sourceTree = ""; }; + BA79F9BD13BB70FF006A292D /* wipefs.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wipefs.cpp; sourceTree = ""; }; + BA79F9BE13BB70FF006A292D /* wipefs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wipefs.h; sourceTree = ""; }; + BA79F9C513BB718B006A292D /* libutil.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libutil.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + 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 = ""; }; + FDBC26FA1741B19000CA4B2B /* com.apple.tzlinkd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.tzlinkd.plist; sourceTree = ""; }; + FDBC26FB1741B19000CA4B2B /* com.apple.tzlinkd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.tzlinkd.sb; sourceTree = ""; }; + FDBC26FE1741B19000CA4B2B /* tzlinkd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tzlinkd.c; sourceTree = ""; }; + FDBC27081741B47200CA4B2B /* tzlink_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tzlink_internal.h; sourceTree = ""; }; + FDBC27091741B47200CA4B2B /* tzlink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tzlink.h; sourceTree = ""; }; + FDBC270D1741B66500CA4B2B /* tzlinkd.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = tzlinkd.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + BA79F9C213BB718B006A292D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDBC26ED1741B13400CA4B2B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + BA79F99513BB70D7006A292D = { + isa = PBXGroup; + children = ( + 3F09C378186D1F73007AF93C /* base.xcconfig */, + 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 */, + 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 */, + ); + sourceTree = ""; + }; + BA79F9C613BB718B006A292D /* Products */ = { + isa = PBXGroup; + children = ( + BA79F9C513BB718B006A292D /* libutil.dylib */, + FDBC26F01741B13400CA4B2B /* tzlinkd */, + ); + name = Products; + sourceTree = ""; + }; + FDBC26F11741B13400CA4B2B /* tzlinkd */ = { + isa = PBXGroup; + children = ( + FDBC26FA1741B19000CA4B2B /* com.apple.tzlinkd.plist */, + FDBC26FB1741B19000CA4B2B /* com.apple.tzlinkd.sb */, + FDBC26FE1741B19000CA4B2B /* tzlinkd.c */, + ); + path = tzlinkd; + sourceTree = ""; + }; + FDBC270C1741B66500CA4B2B /* xcconfigs */ = { + isa = PBXGroup; + children = ( + FDBC270D1741B66500CA4B2B /* tzlinkd.xcconfig */, + ); + path = xcconfigs; + sourceTree = ""; + }; +/* 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"; + }; + 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 */, + FDBC26E41741B09300CA4B2B /* osx */, + BA79F9C413BB718B006A292D /* util */, + FDBC26EF1741B13400CA4B2B /* tzlinkd */, + ); + }; +/* 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; + }; + FDBC26EC1741B13400CA4B2B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDBC27061741B1CF00CA4B2B /* tzlinkd.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 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 */ + 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; + 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; + INSTALL_PATH_ACTUAL = /usr/lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = "-Wall"; + }; + name = Debug; + }; + BA79F9C913BB718B006A292D /* Release */ = { + isa = XCBuildConfiguration; + 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; + INSTALL_PATH_ACTUAL = /usr/lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = "-Wall"; + }; + 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 */ + 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; + }; + 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 */; +} diff --git a/src/libutil/libutil.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/src/libutil/libutil.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..2b3223281 --- /dev/null +++ b/src/libutil/libutil.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/src/libutil/mntopts.h b/src/libutil/mntopts.h new file mode 100644 index 000000000..7fc549da1 --- /dev/null +++ b/src/libutil/mntopts.h @@ -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_ */ diff --git a/src/libutil/pidfile.3 b/src/libutil/pidfile.3 new file mode 100644 index 000000000..070ddab56 --- /dev/null +++ b/src/libutil/pidfile.3 @@ -0,0 +1,249 @@ +.\" Copyright (c) 2005 Pawel Jakub Dawidek +.\" 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 . diff --git a/src/libutil/pidfile.c b/src/libutil/pidfile.c new file mode 100644 index 000000000..88b300ebf --- /dev/null +++ b/src/libutil/pidfile.c @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2005 Pawel Jakub Dawidek + * 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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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)); +} diff --git a/src/libutil/realhostname.3 b/src/libutil/realhostname.3 new file mode 100644 index 000000000..3148e272f --- /dev/null +++ b/src/libutil/realhostname.3 @@ -0,0 +1,105 @@ +.\" Copyright (c) 1999 Brian Somers +.\" 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 diff --git a/src/libutil/realhostname.c b/src/libutil/realhostname.c new file mode 100644 index 000000000..fad7838c4 --- /dev/null +++ b/src/libutil/realhostname.c @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 1999 Brian Somers + * 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 + +#include +#include + +#include +#include +#include + +#include +#include + +#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; +} + + diff --git a/src/libutil/realhostname_sa.3 b/src/libutil/realhostname_sa.3 new file mode 100644 index 000000000..d1bf06333 --- /dev/null +++ b/src/libutil/realhostname_sa.3 @@ -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 +.\" 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 diff --git a/src/libutil/reexec_to_match_kernel.3 b/src/libutil/reexec_to_match_kernel.3 new file mode 100644 index 000000000..fb20c5012 --- /dev/null +++ b/src/libutil/reexec_to_match_kernel.3 @@ -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. diff --git a/src/libutil/reexec_to_match_kernel.c b/src/libutil/reexec_to_match_kernel.c new file mode 100644 index 000000000..d510fbcd8 --- /dev/null +++ b/src/libutil/reexec_to_match_kernel.c @@ -0,0 +1,215 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + + kernarch = current_kernel_arch(); + progarch = current_program_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; +} diff --git a/src/libutil/trimdomain.3 b/src/libutil/trimdomain.3 new file mode 100644 index 000000000..c3708124d --- /dev/null +++ b/src/libutil/trimdomain.3 @@ -0,0 +1,85 @@ +.\" Copyright (c) 1999 Brian Somers +.\" 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 diff --git a/src/libutil/trimdomain.c b/src/libutil/trimdomain.c new file mode 100644 index 000000000..3c4c20ae0 --- /dev/null +++ b/src/libutil/trimdomain.c @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 2001 Brian Somers + * Based on original work by Atsushi Murai + * 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 + +#include + +#include +#include +#include + +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); +} diff --git a/src/libutil/tzlink.c b/src/libutil/tzlink.c new file mode 100644 index 000000000..634fa3f8d --- /dev/null +++ b/src/libutil/tzlink.c @@ -0,0 +1,70 @@ +// Modified by Lubos Dolezel for Darling build +/* + * 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 +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +# include +#endif +#include + +#include "tzlink.h" +#include "tzlink_internal.h" + +errno_t +tzlink(const char *tz) +{ +#if TARGET_OS_IPHONE && !TARGET_IPHONE_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 */ +} diff --git a/src/libutil/tzlink.h b/src/libutil/tzlink.h new file mode 100644 index 000000000..4553c5c90 --- /dev/null +++ b/src/libutil/tzlink.h @@ -0,0 +1,56 @@ +/* + * 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_ + +/*! + * @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 ). 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_ */ diff --git a/src/libutil/tzlink_internal.h b/src/libutil/tzlink_internal.h new file mode 100644 index 000000000..248a67c8d --- /dev/null +++ b/src/libutil/tzlink_internal.h @@ -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 diff --git a/src/libutil/tzlinkd/com.apple.tzlinkd.plist b/src/libutil/tzlinkd/com.apple.tzlinkd.plist new file mode 100644 index 000000000..b82a5dc08 --- /dev/null +++ b/src/libutil/tzlinkd/com.apple.tzlinkd.plist @@ -0,0 +1,26 @@ + + + + + EnableTransactions + + JetsamProperties + + JetsamMemoryLimit + 300 + JetsamPriority + -49 + + Label + com.apple.tzlinkd + MachServices + + com.apple.tzlink + + + POSIXSpawnType + Adaptive + Program + /usr/libexec/tzlinkd + + diff --git a/src/libutil/tzlinkd/com.apple.tzlinkd.sb b/src/libutil/tzlinkd/com.apple.tzlinkd.sb new file mode 100644 index 000000000..313636ae3 --- /dev/null +++ b/src/libutil/tzlinkd/com.apple.tzlinkd.sb @@ -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")) diff --git a/src/libutil/tzlinkd/entitlements.plist b/src/libutil/tzlinkd/entitlements.plist new file mode 100644 index 000000000..eb41eb094 --- /dev/null +++ b/src/libutil/tzlinkd/entitlements.plist @@ -0,0 +1,10 @@ + + + + + seatbelt-profiles + + com.apple.tzlinkd + + + diff --git a/src/libutil/tzlinkd/tzlinkd.c b/src/libutil/tzlinkd/tzlinkd.c new file mode 100644 index 000000000..5445dde03 --- /dev/null +++ b/src/libutil/tzlinkd/tzlinkd.c @@ -0,0 +1,194 @@ +/* + * 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 +#include +#include +#include + +#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; + + xpc_track_activity(); + + 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)) { + return ENOENT; + } + + /* ... owned by root:wheel */ + if (sb.st_uid != 0 || sb.st_gid != 0) { + return ENOENT; + } + + /* ... 0644 perms */ + if ((sb.st_mode & ACCESSPERMS) != 0644) { + return ENOENT; + } + + /* ... is a real tzfile (starts with TZif) */ + // TODO: Validate contents of file. + + return 0; +} diff --git a/src/libutil/wipefs.3 b/src/libutil/wipefs.3 new file mode 100644 index 000000000..21cee1c4e --- /dev/null +++ b/src/libutil/wipefs.3 @@ -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). diff --git a/src/libutil/wipefs.cpp b/src/libutil/wipefs.cpp new file mode 100644 index 000000000..5f166f072 --- /dev/null +++ b/src/libutil/wipefs.cpp @@ -0,0 +1,317 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "ExtentManager.h" +#include "wipefs.h" + +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) + +struct __wipefs_ctx { + int fd; + class ExtentManager extMan; +}; + +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); +} + +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 }; + + *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; + 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; + 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); + } + catch (bad_alloc &e) { + err = ENOMEM; + } + catch (...) { // currently only ENOMEM is possible + err = ENOMEM; + } + + labelExit: + if (err != 0) { + 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; + + 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 = 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: + if (bufZero != NULL) + delete[] bufZero; + return err; +} // wipefs_wipe + +extern "C" void +wipefs_free(wipefs_ctx *handle) +{ + if (*handle != NULL) { + delete *handle; + *handle = NULL; + } +} diff --git a/src/libutil/wipefs.h b/src/libutil/wipefs.h new file mode 100644 index 000000000..0a9321b5d --- /dev/null +++ b/src/libutil/wipefs.h @@ -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 + diff --git a/src/libutil/xcconfigs/base.xcconfig b/src/libutil/xcconfigs/base.xcconfig new file mode 100644 index 000000000..c51588b92 --- /dev/null +++ b/src/libutil/xcconfigs/base.xcconfig @@ -0,0 +1,11 @@ +#include "/Makefiles/CoreOS/Xcode/BSD.xcconfig" +#include "/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig" + +// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable +INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL) + +// Use $(INSTALL_PATH_PREFIX) instead of $(SDKROOT) as a prefix for other +// variables as appropriate +PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/include +PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include + diff --git a/src/libutil/xcconfigs/tzlinkd.xcconfig b/src/libutil/xcconfigs/tzlinkd.xcconfig new file mode 100644 index 000000000..8c330db45 --- /dev/null +++ b/src/libutil/xcconfigs/tzlinkd.xcconfig @@ -0,0 +1,33 @@ +#include "/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig" + +// Set INSTALL_PATH_ACTUAL to whatever INSTALL_PATH would normally be +INSTALL_PATH_ACTUAL = /usr/sbin + +INSTALL_PATH_ACTUAL = /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 diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index b50ad237f..3dc787171 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -16,6 +16,6 @@ set(util-SRCS leb.cpp ) -add_library(util ${util-SRCS}) -set_target_properties(util PROPERTIES COMPILE_FLAGS "-fPIC") +add_library(darling-util ${util-SRCS}) +set_target_properties(darling-util PROPERTIES COMPILE_FLAGS "-fPIC")