SHELL := /bin/sh
-SDKROOT ?= /
VERSION = 1.0
CC = xcrun cc
CPP = xcrun c++
CPPFLAGS = -I$(SRCROOT)
-CFLAGS = -Os -g3 -no-cpp-precomp -Wall $(RC_CFLAGS) -isysroot $(SDKROOT)
+
+ifneq ($(SDKROOT),)
+CFLAGS_SDK = -isysroot $(SDKROOT)
+LDFLAGS_SDK = -Wl,-syslibroot,$(SDKROOT)
+endif
+
+CFLAGS = -Os -g3 -no-cpp-precomp -Wall $(RC_CFLAGS) $(CFLAGS_SDK)
LDFLAGS = $(RC_CFLAGS) -install_name /usr/lib/libutil.dylib -compatibility_version $(VERSION) \
- -current_version $(VERSION) -lstdc++ -exported_symbols_list libutil.exports -isysroot $(SDKROOT)
+ -current_version $(VERSION) -lstdc++ -exported_symbols_list libutil.exports $(LDFLAGS_SDK)
INSTALL = install -c
LN = ln
MKDIR = mkdir -p
property.3 realhostname.3 realhostname_sa.3 trimdomain.3 \
uucplock.3 wipefs.3 reexec_to_match_kernel.3
+ifeq ($(RC_ProjectName),libutil_Sim)
+ INSTALL_PREFIX = $(SDKROOT)
+else
+ INSTALL_PREFIX =
+endif
+
+
.SUFFIXES :
.SUFFIXES : .c .cpp .h .o
done
installhdrs :
- $(INSTALL) -d $(DSTROOT)/usr/local/include
- $(INSTALL) -m 0644 $(HDRS) $(DSTROOT)/usr/local/include
+ $(INSTALL) -d $(DSTROOT)$(INSTALL_PREFIX)/usr/local/include
+ $(INSTALL) -m 0644 $(HDRS) $(DSTROOT)$(INSTALL_PREFIX)/usr/local/include
+ifeq ($(RC_ProjectName),libutil_Sim)
+install : installhdrs installlib strip install-plist
+else
install : installhdrs installlib strip installman install-plist
+endif
clean :
rm -f $(patsubst %.cpp,$(OBJROOT)/%.o,$(patsubst %.c,$(OBJROOT)/%.o,$(SRCS)))
rm -f $(SYMROOT)/$(LIB)
strip:
- $(STRIP) -x -S $(DSTROOT)/usr/lib/$(LIB)
+ $(STRIP) -x -S $(DSTROOT)$(INSTALL_PREFIX)/usr/lib/$(LIB)
#
# Internal targets and rules.
#
installlib : $(SYMROOT)/$(LIB)
$(DSYMUTIL) $(SYMROOT)/$(LIB) -o $(SYMROOT)/$(LIB).dSYM
- $(INSTALL) -d $(DSTROOT)/usr/lib
- $(INSTALL) -m 0755 $< $(DSTROOT)/usr/lib
- $(LN) -fs libutil1.0.dylib $(DSTROOT)/usr/lib/libutil.dylib
+ $(INSTALL) -d $(DSTROOT)$(INSTALL_PREFIX)/usr/lib
+ $(INSTALL) -m 0755 $< $(DSTROOT)$(INSTALL_PREFIX)/usr/lib
+ $(LN) -fs libutil1.0.dylib $(DSTROOT)$(INSTALL_PREFIX)/usr/lib/libutil.dylib
installman :
$(INSTALL) -d $(DSTROOT)/usr/local/share/man/man3
$(SYMROOT)/$(LIB) : $(patsubst %.cpp,$(OBJROOT)/%.o,$(patsubst %.c,$(OBJROOT)/%.o,$(SRCS)))
$(CC) -dynamiclib $(LDFLAGS) -o $@ $(patsubst %.cpp,$(OBJROOT)/%.o,$(patsubst %.c,$(OBJROOT)/%.o,$(SRCS)))
-OSV = $(DSTROOT)/usr/local/OpenSourceVersions
-OSL = $(DSTROOT)/usr/local/OpenSourceLicenses
+OSV = $(DSTROOT)$(INSTALL_PREFIX)/usr/local/OpenSourceVersions
+OSL = $(DSTROOT)$(INSTALL_PREFIX)/usr/local/OpenSourceLicenses
install-plist:
$(MKDIR) $(OSV)
- $(INSTALL) $(SRCROOT)/libutil.plist $(OSV)/
+ $(INSTALL) -m 644 $(SRCROOT)/libutil.plist $(OSV)/
$(MKDIR) $(OSL)
- $(INSTALL) $(SRCROOT)/libutil.txt $(OSL)/
+ $(INSTALL) -m 644 $(SRCROOT)/libutil.txt $(OSL)/
#include <string.h>
#include <locale.h>
#include <libutil.h>
+#include <stdint.h>
+#include <limits.h>
int
humanize_number(char *buf, size_t len, int64_t bytes,
{
const char *prefixes, *sep;
int b, i, r, maxscale, s1, s2, sign;
- int64_t divisor, max;
+ 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);
buf[0] = '\0';
if (bytes < 0) {
sign = -1;
- bytes *= -100;
+ scalable *= -100;
baselen = 3; /* sign, digit, prefix */
} else {
sign = 1;
- bytes *= 100;
+ scalable *= 100;
baselen = 2; /* digit, prefix */
}
if (flags & HN_NOSPACE)
for (max = 100, i = len - baselen; i-- > 0;)
max *= 10;
- for (i = 0; bytes >= max && i < maxscale; i++)
- bytes /= divisor;
+ 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++)
- bytes /= divisor;
+ scalable /= divisor;
/* If a value <= 9.9 after rounding and ... */
- if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
+ if (scalable < 995 && i > 0 && flags & HN_DECIMAL) {
/* baselen + \0 + .N */
if (len < baselen + 1 + 2)
return (-1);
- b = ((int)bytes + 5) / 10;
+ b = ((int)scalable + 5) / 10;
s1 = b / 10;
s2 = b % 10;
- r = snprintf(buf, len, "%d%s%d%s%s%s",
- sign * s1, localeconv()->decimal_point, s2,
+ 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, "%lld%s%s%s",
+ r = snprintf(buf, len, "%s%lld%s%s%s",
/* LONGLONG */
- (long long)(sign * ((bytes + 50) / 100)),
+ ((sign == -1) ? "-" : ""),
+ (long long)((scalable + 50) / 100),
sep, SCALE2PREFIX(i), suffix);
return (r);
_realhostname
_realhostname_sa
_reexec_to_match_kernel
+_reexec_to_match_lp64ness
_trimdomain
_uu_lock
_uu_lock_txfr
#define _LIBUTIL_H_
#include <unistd.h>
+#include <stdbool.h>
+
#define PROPERTY_MAX_NAME 64
#define PROPERTY_MAX_VALUE 512
#endif
int reexec_to_match_kernel(void);
+int reexec_to_match_lp64ness(bool isLP64);
__END_DECLS
.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
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
-function returns 0 if re-execution was not required. It returns -1 and
+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
/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
static cpu_type_t current_program_arch(void);
static cpu_type_t current_kernel_arch(void);
-static int reexec(cpu_type_t cputype);
+static int reexec(cpu_type_t cputype, const char *guardenv);
-#define kReExec "REEXEC_TO_MATCH_KERNEL"
+#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(kReExec);
+ alreadyenv = getenv(kReExecToMatchKernel);
if (alreadyenv) {
/* we've done this at least once, assume
another try won't help */
}
/* Now we need to re-exec */
- return reexec(kernarch);
+ 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)
return current_arch;
}
-static int reexec(cpu_type_t cputype)
+static int reexec(cpu_type_t cputype, const char *guardenv)
{
posix_spawnattr_t attr;
int ret, envcount;
char **argv, **oldenvp, **newenvp;
char execpath[MAXPATHLEN+1];
uint32_t execsize;
+ char guardstr[32];
argv = *_NSGetArgv();
oldenvp = *_NSGetEnviron();
for (envcount = 0; oldenvp[envcount]; envcount++) {
newenvp[envcount] = oldenvp[envcount];
}
- newenvp[envcount++] = kReExec"=1";
+
+ snprintf(guardstr, sizeof(guardstr), "%s=1", guardenv);
+ newenvp[envcount++] = guardstr;
newenvp[envcount] = NULL;
execsize = (uint32_t)sizeof(execpath);
return -1;
}
- /*
- fprintf(stderr, "reexec: %s\n", execpath);
+#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;
uint8_t *bufZero = NULL;
ListExtIt curExt;
size_t bufSize;
- dk_discard_t discard;
+ dk_extent_t extent;
+ dk_unmap_t unmap;
- memset(&discard, 0, sizeof(dk_discard_t));
- discard.length = handle->extMan.totalBytes;
+ 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, DKIOCDISCARD, (caddr_t)&discard);
+ ioctl(handle->fd, DKIOCUNMAP, (caddr_t)&unmap);
bufSize = 256 * 1024; // issue large I/O to get better performance