.include <CoreOS/Standard/Variables.mk>
ALLARCHS = arm i386 ppc ppc64 x86_64 # installsrc doesn't set RC_ARCHS
+CODESIGN != xcrun -find codesign
TOP != ${PWD}
.ifdef DSTROOT
DESTDIR = $(DSTROOT)
.else
LIBSYS = $(SDKROOT)/usr/local/lib/system
.endif
+.ifdef ALTUSRLIBSYSTEM
+LSYS = $(ALTUSRLIBSYSTEM)
+.else
+LSYS = $(SDKROOT)/usr/lib/system
+.endif
NJOBS != ${PERL} -e '$$n = `$(SYSCTL) -n hw.ncpu`; printf "%d\n", $$n < 2 ? 2 : ($$n * 1.5)'
.ifdef DEBUG
MYBSDMAKE = $(BSDMAKE) -f Makefile -P
# These are the non B&I defaults
.ifndef RC_ProjectName
+RC_ProjectName = Libc
+
installhdrs: roots installhdrs-real
build: roots build-static build-profile build-debug build-dynamic
install: roots installhdrs install-all
.else # RC_ProjectName
+RC_ProjectNameBase := $(RC_ProjectName:%_Sim=%)
+.if $(RC_ProjectName) == $(RC_ProjectNameBase)
+INSTALL_PREFIX =
+.else
+INSTALL_PREFIX = $(SDKROOT)
+.endif
+
# And these are to deal with B&I building libc differently
# based on RC_ProjectName.
-.if $(RC_ProjectName) == Libc
+.if $(RC_ProjectNameBase) == Libc
installhdrs:
build: roots build-dynamic
install: roots BI-install-dynamic
.endif
-.if $(RC_ProjectName) == Libc_headers
+.if $(RC_ProjectNameBase) == Libc_headers
installhdrs: roots installhdrs-real
build:
install: roots installhdrs-real
.endif
-.if $(RC_ProjectName) == Libc_man
+.if $(RC_ProjectNameBase) == Libc_man
installhdrs:
build:
install: roots install-man
.endif
-.if $(RC_ProjectName) == Libc_static
+.if $(RC_ProjectNameBase) == Libc_static
installhdrs:
build: roots build-static
install: roots BI-install-static
.endif
-.if $(RC_ProjectName) == Libc_debug
+.if $(RC_ProjectNameBase) == Libc_debug
installhdrs:
build: roots build-debug
install: roots BI-install-debug
.endif
-.if $(RC_ProjectName) == Libc_profile
+.if $(RC_ProjectNameBase) == Libc_profile
installhdrs:
build: roots build-profile
install: roots BI-install-profile
${LN} -fs $(VERSIONSB)/PrivateHeaders $(FRAMEWORKS)/$(SYSTEMFRAMEWORK)/PrivateHeaders
AUTOPATCHED = $(SRCROOT)/.autopatched
-PARTIAL = -partial
+PARTIAL =
.for F in $(FORMS) # {
.if $(dynamic) == $(F) # {
SUFFIX-$(F) =
touch $(AUTOPATCHED)
copysrc:
- ${PAX} -rw -p p . "$(SRCROOT)"
+ ${TAR} -cp --exclude .git --exclude .svn --exclude CVS . | ${TAR} -pox -C "$(SRCROOT)"
installsrc: copysrc $(AUTOPATCHED)
installhdrs-real:
- MAKEOBJDIR="$(OBJROOT)" DESTDIR="$(DSTROOT)" MAKEFLAGS="" \
- DSTROOT=$(DSTROOT) OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) \
+ MAKEOBJDIR="$(OBJROOT)" DESTDIR="$(DSTROOT)$(INSTALL_PREFIX)" MAKEFLAGS="" \
+ DSTROOT="$(DSTROOT)$(INSTALL_PREFIX)" OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) \
$(MYBSDMAKEJ) installhdrs
.for A in $(RC_ARCHS) # {
${MKDIR} "$(OBJROOT)/obj.$(A)" && \
.for F in $(FORMS) # {
BI-install-$(F): build-$(F)
+ $(CC) -dynamiclib -o $(SYMROOT)/libsystem_c$(SUFFIX-$(F)).dylib $(RC_ARCHS:C/^/-arch /g) \
+ -compatibility_version 1 -current_version $(RC_ProjectSourceVersion) \
+ -install_name /usr/lib/system/libsystem_c$(SUFFIX-$(F)).dylib -nostdlib -Wl,-umbrella,System \
+ -all_load $(SYMROOT)/libc$(PSUFFIX-$(F)).a -Wl,-interposable_list,$(SRCROOT)/interposable.list \
+ -L$(LSYS) -L$(SDKROOT)/usr/lib -lSystem -lgcc
${MKDIR} $(DSTROOT)/usr/local/lib/system
- if [ -f "$(SYMROOT)/libc$(PSUFFIX-$(F)).a" ]; then \
- ${ECHO} "Installing libc$(PSUFFIX-$(F)).a" && \
- ${INSTALL} -m 444 "$(SYMROOT)/libc$(PSUFFIX-$(F)).a" \
- $(DSTROOT)/usr/local/lib/system && \
- ${RANLIB} "$(DSTROOT)/usr/local/lib/system/libc$(PSUFFIX-$(F)).a" || exit 1; \
- fi
+ ${MKDIR} $(DSTROOT)/usr/lib/system
+ ${INSTALL} $(SYMROOT)/libsystem_c$(SUFFIX-$(F)).dylib $(DSTROOT)/usr/lib/system
+ ${STRIP} -S $(DSTROOT)/usr/lib/system/libsystem_c$(SUFFIX-$(F)).dylib
+ -${CODESIGN} -s - $(DSTROOT)/usr/lib/system/libsystem_c$(SUFFIX-$(F)).dylib
.if $(dynamic) == $(F) # {
if [ -f "$(SYMROOT)/libc-dyld.a" ]; then \
${ECHO} "Installing libc-dyld.a" && \
+ ${MKDIR} $(DSTROOT)/usr/local/lib/dyld && \
${INSTALL} -m 444 "$(SYMROOT)/libc-dyld.a" \
- $(DSTROOT)/usr/local/lib/system && \
- ${RANLIB} "$(DSTROOT)/usr/local/lib/system/libc-dyld.a" || exit 1; \
+ $(DSTROOT)/usr/local/lib/dyld/libc.a && \
+ ${LN} -sf "../dyld/libc.a" "$(DSTROOT)/usr/local/lib/system/libc-dyld.a" && \
+ ${RANLIB} "$(DSTROOT)/usr/local/lib/dyld/libc.a" || exit 1; \
fi
.for A in $(RC_ARCHS) # {
MAKEOBJDIR="$(OBJROOT)/obj.$(A)" MACHINE_ARCH=$(MACHINE_ARCH-$(A)) CCARCH=$(A) \
${MKDIR} $(DSTROOT)/usr/share/man/man4
${MKDIR} $(DSTROOT)/usr/share/man/man5
${MKDIR} $(DSTROOT)/usr/share/man/man7
- MAKEOBJDIR="$(OBJROOT)" DESTDIR="$(DSTROOT)" \
- DSTROOT='$(DSTROOT)' OBJROOT='$(OBJROOT)' SYMROOT='$(SYMROOT)' \
+ MAKEOBJDIR="$(OBJROOT)" DESTDIR="$(DSTROOT)$(INSTALL_PREFIX)" \
+ DSTROOT='$(DSTROOT)$(INSTALL_PREFIX)' OBJROOT='$(OBJROOT)' SYMROOT='$(SYMROOT)' \
MACHINE_ARCH="$(MACHINE_ARCH-$(FIRST_ARCH))" CCARCH=$(FIRST_ARCH) MAKEFLAGS="" \
RC_NONARCH_CFLAGS="$(RC_NONARCH_CFLAGS)" \
$(MYBSDMAKE) all-man maninstall $(MANARGS)
RC_TARGET_CONFIG = MacOSX
.endif
+.ifndef RC_ProjectName
+RC_ProjectName = Libc
+.endif
+
# Use default compiler, so comment out OTHERCC
#OTHERCC = gcc-4.0
# HOSTCC is the compiler on the local host, so we need to unset any SDKROOT
CFLAGS = -g -arch ${CCARCH} ${RC_NONARCH_CFLAGS} -std=gnu99 -fno-common -fno-builtin -Wmost
CFLAGS += -D__LIBC__ -D__DARWIN_UNIX03=1 -D__DARWIN_64_BIT_INO_T=1 -D__DARWIN_NON_CANCELABLE=1 -D__DARWIN_VERS_1050=1 -D_FORTIFY_SOURCE=0
CFLAGS += -DNOID -DLIBC_MAJOR=${SHLIB_MAJOR}
-CFLAGS += -I${.OBJDIR} -I${SYMROOTINC} -I${.CURDIR}/include
+CFLAGS += -I${.OBJDIR} ${VARIANTINC} -I${SYMROOTINC} -I${.CURDIR}/include
AINC = -g -arch ${CCARCH} ${RC_NONARCH_CFLAGS}
AINC += -I${.CURDIR}/${MACHINE_ARCH} ${PRIVINC}
.if $(MACHINE_ARCH) != arm
AINC += -isysroot '${SDKROOT}'
.endif # SDKROOT
-.if ${GCC_42} != YES
-CFLAGS += -no-cpp-precomp
-AINC += -no-cpp-precomp
-.endif
CLEANFILES+=tags
INSTALL_PIC_ARCHIVE= yes
PRECIOUSLIB= yes
.endif
DESTDIR ?= ${DSTROOT}
MAKEOBJDIR ?= ${OBJROOT}
+PLATROOT != xcodebuild -version -sdk $(SDKROOT) PlatformPath | tr -d '\n'
# add version string
SRCS += libc_version.c
libc_version.c:
- ${SDKROOT}/Developer/Makefiles/bin/version.pl Libc > $@
+ ${PLATROOT}/Developer/Makefiles/bin/version.pl Libc > $@
.include "Makefile.features"
.include "${.CURDIR}/Makefile.inc"
FEATURE_BLOCKS = YES
.endif # _BLOCKS
.endif # CCARCH
+_LIBCRASHREPORTERCLIENT_A = ${SDKROOT}/usr/local/lib/libCrashReporterClient.a
+_LIBCRASHREPORTERCLIENT != test -f ${_LIBCRASHREPORTERCLIENT_A} || echo NO
+.if ${_LIBCRASHREPORTERCLIENT} == NO
+FEATURE_NO_LIBCRASHREPORTERCLIENT = YES
+.endif # !_LIBCRASHREPORTERCLIENT
${SYMROOTINC}/${MACHINE_ARCH}/libc-features.h:
${MKDIR} ${.TARGET:H}
@echo '#define _LIBC_FEATURES_H_' >> ${.TARGET}
@echo >> ${.TARGET}
.ifdef FEATURE_LEGACY_RUNE_APIS
- @echo '#define LEGACY_RUNE_APIS 1' >> ${.TARGET}
+ @echo '#define UNIFDEF_LEGACY_RUNE_APIS 1' >> ${.TARGET}
.else
- @echo '/* #undef LEGACY_RUNE_APIS */' >> ${.TARGET}
+ @echo '/* #undef UNIFDEF_LEGACY_RUNE_APIS */' >> ${.TARGET}
+.endif
+.ifdef FEATURE_LEGACY_CRT1_ENVIRON
+ @echo '#define LEGACY_CRT1_ENVIRON 1' >> ${.TARGET}
+.else
+ @echo '/* #undef LEGACY_CRT1_ENVIRON */' >> ${.TARGET}
.endif
.ifdef FEATURE_LEGACY_UTMP_APIS
- @echo '#define LEGACY_UTMP_APIS 1' >> ${.TARGET}
+ @echo '#define UNIFDEF_LEGACY_UTMP_APIS 1' >> ${.TARGET}
.else
- @echo '/* #undef LEGACY_UTMP_APIS */' >> ${.TARGET}
+ @echo '/* #undef UNIFDEF_LEGACY_UTMP_APIS */' >> ${.TARGET}
.endif
.ifdef FEATURE_MOVE_LOCALTIME
@echo '#define UNIFDEF_MOVE_LOCALTIME 1' >> ${.TARGET}
@echo '# error Feature mismatch: __DARWIN_ONLY_64_BIT_INO_T == 1' >> ${.TARGET}
@echo '#endif /* __DARWIN_ONLY_64_BIT_INO_T */' >> ${.TARGET}
.endif
-.ifdef FEATURE_PATCH_3375657
- @echo '#define __APPLE_PR3375657_HACK__ 1' >> ${.TARGET}
-.else
- @echo '/* #undef __APPLE_PR3375657_HACK__ */' >> ${.TARGET}
-.endif
.ifdef FEATURE_PATCH_3417676
@echo '#define __APPLE_PR3417676_HACK__ 1' >> ${.TARGET}
.else
@echo '#define NOTIFY_TZ 1' >> ${.TARGET}
.else
@echo '/* #undef NOTIFY_TZ */' >> ${.TARGET}
+.endif
+.ifdef FEATURE_NO_LIBCRASHREPORTERCLIENT
+ @echo '#define LIBC_NO_LIBCRASHREPORTERCLIENT 1' >> ${.TARGET}
+.else
+ @echo '/* #undef LIBC_NO_LIBCRASHREPORTERCLIENT */' >> ${.TARGET}
.endif
@echo >> ${.TARGET}
@echo '#endif /* _LIBC_FEATURES_H_ */' >> ${.TARGET}
CFLAGS_CANCELABLE= -DVARIANT_CANCELABLE
CFLAGS_DARWINEXTSN= -DVARIANT_DARWINEXTSN
-CFLAGS_DYLD= -DVARIANT_DYLD
+CFLAGS_DYLD= -DVARIANT_DYLD -DVARIANT_CANCELABLE -DVARIANT_DARWINEXTSN -U__DARWIN_NON_CANCELABLE -D__DARWIN_NON_CANCELABLE=0
CFLAGS_INODE32= -U__DARWIN_64_BIT_INO_T -D__DARWIN_64_BIT_INO_T=0 -DVARIANT_INODE32
CFLAGS_LDBL= -mlong-double-64 -DLDBL_COMPAT
CFLAGS_LEGACY= -U__DARWIN_UNIX03 -D__DARWIN_UNIX03=0 -U__DARWIN_64_BIT_INO_T -D__DARWIN_64_BIT_INO_T=0 -DVARIANT_LEGACY
${_v:H:S,/,,}:
.ifdef ${_v:H:S,/,,}SRCS
${MKDIR} ${MAKEOBJDIR}/${_v:H:S,/,,}; \
- MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="-DBUILDING_VARIANT ${_v:T:S/@/ /g}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}
+ MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="-DBUILDING_VARIANT ${_v:T:S/@/ /g}" VARIANTINC="-I${MAKEOBJDIR}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}
.endif
${_v:H:S,/,,}_D:
.ifdef ${_v:H:S,/,,}SRCS
${MKDIR} ${MAKEOBJDIR}/${_v:H:S,/,,}; \
- MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="-DBUILDING_VARIANT ${_v:T:S/@/ /g}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}_D
+ MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="-DBUILDING_VARIANT ${_v:T:S/@/ /g}" VARIANTINC="-I${MAKEOBJDIR}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}_D
.endif
${_v:H:S,/,,}_P:
.ifdef ${_v:H:S,/,,}SRCS
${MKDIR} ${MAKEOBJDIR}/${_v:H:S,/,,}; \
- MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="-DBUILDING_VARIANT ${_v:T:S/@/ /g}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}_P
+ MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="-DBUILDING_VARIANT ${_v:T:S/@/ /g}" VARIANTINC="-I${MAKEOBJDIR}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}_P
.endif
${_v:H:S,/,,}_S:
.ifdef ${_v:H:S,/,,}SRCS
${MKDIR} ${MAKEOBJDIR}/${_v:H:S,/,,}; \
- MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="${${_v:H:S,/,,}_BUILDING_VARIANT} ${_v:T:S/@/ /g}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}_S
+ MAKEOBJDIR="${MAKEOBJDIR}/${_v:H:S,/,,}" VARIANTCFLAGS="${${_v:H:S,/,,}_BUILDING_VARIANT} ${_v:T:S/@/ /g}" VARIANTINC="-I${MAKEOBJDIR}" ${MYBSDMAKE} -C "${.CURDIR}" build_${_v:H:S,/,,}_S
.endif
.endfor
${MYCC} -static -x assembler-with-cpp \
${PRECFLAGS:M-[BIDFU]*} ${PRECFLAGS-${.IMPSRC:T}:M-[BIDFU]*} \
${CFLAGS:M-[BIDFU]*} ${CFLAGS-${.IMPSRC:T}:M-[BIDFU]*} ${AINC} \
- -Os ${OPTIMIZE-${.IMPSRC:T}} -c ${.IMPSRC} -o ${.TARGET}
+ ${VARIANTCFLAGS:M-[BIDFU]*} -Os ${OPTIMIZE-${.IMPSRC:T}} \
+ -c ${.IMPSRC} -o ${.TARGET}
.s.po .S.po:
${MYCC} -pg -x assembler-with-cpp -DPROFILE \
${PRECFLAGS:M-[BIDFU]*} ${PRECFLAGS-${.IMPSRC:T}:M-[BIDFU]*} \
${CFLAGS:M-[BIDFU]*} ${CFLAGS-${.IMPSRC:T}:M-[BIDFU]*} ${AINC} \
- -Os ${OPTIMIZE-${.IMPSRC:T}} -c ${.IMPSRC} -o ${.TARGET}
+ ${VARIANTCFLAGS:M-[BIDFU]*} -Os ${OPTIMIZE-${.IMPSRC:T}} \
+ -c ${.IMPSRC} -o ${.TARGET}
.s.So .S.So:
${MYCC} -x assembler-with-cpp \
${PRECFLAGS:M-[BIDFU]*} ${PRECFLAGS-${.IMPSRC:T}:M-[BIDFU]*} \
${CFLAGS:M-[BIDFU]*} ${CFLAGS-${.IMPSRC:T}:M-[BIDFU]*} ${AINC} \
- -Os ${OPTIMIZE-${.IMPSRC:T}} -c ${.IMPSRC} -o ${.TARGET}
+ ${VARIANTCFLAGS:M-[BIDFU]*} -Os ${OPTIMIZE-${.IMPSRC:T}} \
+ -c ${.IMPSRC} -o ${.TARGET}
.s.do .S.do:
${MYCC} -x assembler-with-cpp -DDEBUG \
${PRECFLAGS:M-[BIDFU]*} ${PRECFLAGS-${.IMPSRC:T}:M-[BIDFU]*} \
${CFLAGS:M-[BIDFU]*} ${CFLAGS-${.IMPSRC:T}:M-[BIDFU]*} ${AINC} \
- -c ${.IMPSRC} -o ${.TARGET}
+ ${VARIANTCFLAGS:M-[BIDFU]*} -c ${.IMPSRC} -o ${.TARGET}
#### mig Rules ########################################################
.defs.h .defsUser.c .defsServer.c:
gen_mig_defs: ${SRVMIGHDRS} ${MIGHDRS}
gen_md_mig_defs: ${MD_MIGHDRS}
+#### CrashReporterClient Rules ########################################
+.ifdef FEATURE_NO_LIBCRASHREPORTERCLIENT
+CRASHREPORTERCLIENTOBJ =
+.else # !FEATURE_NO_LIBCRASHREPORTERCLIENT
+CRASHREPORTERCLIENT = CrashReporterClient
+CRASHREPORTERCLIENTOBJ = ${CRASHREPORTERCLIENT}.${OBJSUFFIX}
+LIBCRASHREPORTERCLIENT = lib${CRASHREPORTERCLIENT}.a
+${CRASHREPORTERCLIENTOBJ}: ${SDKROOT}/usr/local/lib/${LIBCRASHREPORTERCLIENT}
+ ditto -arch ${MACHINE_ARCH} $> ${LIBCRASHREPORTERCLIENT}
+ ar x ${LIBCRASHREPORTERCLIENT}
+ mv ${CRASHREPORTERCLIENT}.o $@
+.endif # !FEATURE_NO_LIBCRASHREPORTERCLIENT
+
#### Library Rules ####################################################
${VARIANTCOMBOS:N*DYLD*} ${OBJS} ${STATICOBJS}: ${SYMROOTINC}/${MACHINE_ARCH}/libc-features.h
-lib${LIB}_static.a:: ${VARIANTCOMBOS:N*DYLD*} ${OBJS} ${STATICOBJS}
+lib${LIB}_static.a:: ${BUILDFIRST} ${VARIANTCOMBOS:N*DYLD*} ${OBJS} ${STATICOBJS} ${CRASHREPORTERCLIENTOBJ}
@${ECHO} building static ${LIB} library
@${RM} lib${LIB}_static.a
- @${AR} cq lib${LIB}_static.a `${LORDER} ${OBJS} ${STATICOBJS} ${VARIANTOBJS} | ${TSORT} -q`
+ @${AR} cq lib${LIB}_static.a `${LORDER} ${OBJS} ${STATICOBJS} ${VARIANTOBJS} ${CRASHREPORTERCLIENTOBJ} | ${TSORT} -q`
${RANLIB} lib${LIB}_static.a
${VARIANTCOMBOS:N*DYLD*:S/$/_P/g} ${POBJS}: ${SYMROOTINC}/${MACHINE_ARCH}/libc-features.h
-lib${LIB}_profile.a:: ${VARIANTCOMBOS:N*DYLD*:S/$/_P/g} ${POBJS}
+lib${LIB}_profile.a:: ${BUILDFIRST} ${VARIANTCOMBOS:N*DYLD*:S/$/_P/g} ${POBJS} ${CRASHREPORTERCLIENTOBJ}
@${ECHO} building profiled ${LIB} library
@${RM} lib${LIB}_profile.a
- @${AR} cq lib${LIB}_profile.a `${LORDER} ${POBJS} ${VARIANTPOBJS} | ${TSORT} -q`
+ @${AR} cq lib${LIB}_profile.a `${LORDER} ${POBJS} ${VARIANTPOBJS} ${CRASHREPORTERCLIENTOBJ} | ${TSORT} -q`
${RANLIB} lib${LIB}_profile.a
${VARIANTCOMBOS:N*DYLD*:S/$/_D/g} ${DOBJS}: ${SYMROOTINC}/${MACHINE_ARCH}/libc-features.h
-lib${LIB}_debug.a:: ${VARIANTCOMBOS:N*DYLD*:S/$/_D/g} ${DOBJS}
+lib${LIB}_debug.a:: ${BUILDFIRST} ${VARIANTCOMBOS:N*DYLD*:S/$/_D/g} ${DOBJS} ${CRASHREPORTERCLIENTOBJ}
@${ECHO} building debug ${LIB} library
@${RM} lib${LIB}_debug.a
- @${AR} cq lib${LIB}_debug.a `${LORDER} ${DOBJS} ${VARIANTDOBJS} | ${TSORT} -q`
+ @${AR} cq lib${LIB}_debug.a `${LORDER} ${DOBJS} ${VARIANTDOBJS} ${CRASHREPORTERCLIENTOBJ} | ${TSORT} -q`
${RANLIB} lib${LIB}_debug.a
${VARIANTCOMBOS:S/$/_S/g} ${SOBJS}: ${SYMROOTINC}/${MACHINE_ARCH}/libc-features.h
-lib${LIB}.a:: ${VARIANTCOMBOS:S/$/_S/g} ${SOBJS}
+lib${LIB}.a:: ${BUILDFIRST} ${VARIANTCOMBOS:S/$/_S/g} ${SOBJS} ${CRASHREPORTERCLIENTOBJ}
@${ECHO} building standard ${LIB} library
@${RM} lib${LIB}.a
- @${AR} cq lib${LIB}.a `${LORDER} ${SOBJS} ${VARIANTSOBJS} | ${TSORT} -q`
+ @${AR} cq lib${LIB}.a `${LORDER} ${SOBJS} ${VARIANTSOBJS} ${CRASHREPORTERCLIENTOBJ} | ${TSORT} -q`
${RANLIB} lib${LIB}.a
@${ECHO} building custom ${LIB} library for dyld
@${RM} lib${LIB}-dyld.a
+++ /dev/null
-#
-# Selectable features for iPhone
-#
-
-# Legacy *64 APIs
-#FEATURE_LEGACY_64_APIS = 1
-
-# Legacy NX international APIs
-FEATURE_LEGACY_NX_INTERNAT_APIS = 1
-
-# Legacy NXZone APIs
-FEATURE_LEGACY_NXZONE_APIS = 1
-
-# Legacy rune APIs
-#FEATURE_LEGACY_RUNE_APIS = 1
-
-# Legacy utmp APIs
-#FEATURE_LEGACY_UTMP_APIS = 1
-
-# New OSMemoryNotification and OSThermalNotification APIs
-FEATURE_MEM_THERM_NOTIFICATION_APIS = 1
-
-# Move localtime to /var/db/timezone
-FEATURE_MOVE_LOCALTIME = 1
-
-# Long doubles are doubles (should match sys/cdefs.h)
-.if (${MACHINE_ARCH} == arm)
-FEATURE_ONLY_LONG_DOUBLE_IS_DOUBLE = 1
-.endif
-
-# No pre-1050 variants (should match sys/cdefs.h)
-FEATURE_ONLY_1050_VARIANTS = 1
-
-# No legacy variants (should match sys/cdefs.h)
-FEATURE_ONLY_UNIX_CONFORMANCE = 1
-
-# Only 64-bit ino_t (should match sys/cdefs.h)
-FEATURE_ONLY_64_BIT_INO_T = 1
-
-# Patch 3333969
-#FEATURE_PATCH_3333969 = 1
-
-# Patch 3375657
-#FEATURE_PATCH_3375657 = 1
-
-# Patch 3417676
-#FEATURE_PATCH_3417676 = 1
-
-# Patch 5243343
-FEATURE_PATCH_5243343 = 1
-
-# plockstat dtrace support
-#FEATURE_PLOCKSTAT = 1
-
-# Timezone change notification
-#FEATURE_TIMEZONE_CHANGE_NOTIFICATION = 1
+++ /dev/null
-_accept$NOCANCEL ___accept_nocancel
-_aio_suspend$NOCANCEL ___aio_suspend_nocancel
-_close$NOCANCEL ___close_nocancel
-_connect$NOCANCEL ___connect_nocancel
-_fcntl$NOCANCEL ___fcntl_nocancel
-_fstat ___fstat64
-_fstat64
-_fstatfs ___fstatfs64
-_fstatfs64
-_fstatx_np ___fstatx64_np
-_fstatx64_np
-_fsync$NOCANCEL ___fsync_nocancel
-_getfsstat ___getfsstat64
-_getfsstat64
-_getmntinfo ___getmntinfo64
-_getmntinfo64
-_lstat ___lstat64
-_lstat64
-_lstatx_np ___lstatx64_np
-_lstatx64_np
-_msgrcv$NOCANCEL ___msgrcv_nocancel
-_msgsnd$NOCANCEL ___msgsnd_nocancel
-_msync$NOCANCEL ___msync_nocancel
-_open$NOCANCEL ___open_nocancel
-_poll$NOCANCEL ___poll_nocancel
-_pread$NOCANCEL ___pread_nocancel
-_pwrite$NOCANCEL ___pwrite_nocancel
-_read$NOCANCEL ___read_nocancel
-_readv$NOCANCEL ___readv_nocancel
-_recvfrom$NOCANCEL ___recvfrom_nocancel
-_recvmsg$NOCANCEL ___recvmsg_nocancel
-_select$DARWIN_EXTSN ___select
-_select$DARWIN_EXTSN$NOCANCEL ___select_nocancel
-_sem_wait$NOCANCEL ___sem_wait_nocancel
-_sendmsg$NOCANCEL ___sendmsg_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_stat ___stat64
-_stat64
-_statfs ___statfs64
-_statfs64
-_statx_np ___statx64_np
-_statx64_np
-_waitid$NOCANCEL ___waitid_nocancel
-_write$NOCANCEL ___write_nocancel
-_writev$NOCANCEL ___writev_nocancel
# Legacy *64 APIs
FEATURE_LEGACY_64_APIS = 1
+# Legacy crt1.o environ support
+FEATURE_LEGACY_CRT1_ENVIRON = 1
+
# Legacy NX international APIs
FEATURE_LEGACY_NX_INTERNAT_APIS = 1
# Patch 3333969
FEATURE_PATCH_3333969 = 1
-# Patch 3375657
-#FEATURE_PATCH_3375657 = 1
-
# Patch 3417676
FEATURE_PATCH_3417676 = 1
+++ /dev/null
-_accept$NOCANCEL$UNIX2003 ___accept_nocancel
-_accept$UNIX2003 ___accept
-_accept$UNIX2003 ___accept
-_aio_suspend ___aio_suspend_nocancel
-_aio_suspend$NOCANCEL$UNIX2003 ___aio_suspend_nocancel
-_aio_suspend$UNIX2003 ___aio_suspend
-_bind$UNIX2003 ___bind
-_close ___close_nocancel
-_close$NOCANCEL$UNIX2003 ___close_nocancel
-_close$UNIX2003 ___close
-_connect$NOCANCEL$UNIX2003 ___connect_nocancel
-_connect$UNIX2003 ___connect
-_connect$UNIX2003 ___connect
-_fcntl ___fcntl_nocancel
-_fcntl$NOCANCEL$UNIX2003 ___fcntl_nocancel
-_fcntl$UNIX2003 ___fcntl
-_fstat$INODE64 ___fstat64
-_fstatfs$INODE64 ___fstatfs64
-_fsync ___fsync_nocancel
-_fsync$NOCANCEL$UNIX2003 ___fsync_nocancel
-_fsync$UNIX2003 ___fsync
-_getattrlist$UNIX2003 ___getattrlist
-_getfsstat$INODE64 ___getfsstat64
-_getpeername$UNIX2003 ___getpeername
-_getsockname$UNIX2003 ___getsockname
-_lchown$UNIX2003 ___lchown
-_listen$UNIX2003 ___listen
-_lstat$INODE64 ___lstat64
-_mprotect$UNIX2003 ___mprotect
-_msgctl$UNIX2003 ___msgctl
-_msgrcv ___msgrcv_nocancel
-_msgrcv$NOCANCEL$UNIX2003 ___msgrcv_nocancel
-_msgrcv$UNIX2003 ___msgrcv
-_msgsnd ___msgsnd_nocancel
-_msgsnd$NOCANCEL$UNIX2003 ___msgsnd_nocancel
-_msgsnd$UNIX2003 ___msgsnd
-_msync$NOCANCEL$UNIX2003 ___msync_nocancel
-_msync$UNIX2003 ___msync
-_munmap$UNIX2003 ___munmap
-_open$NOCANCEL$UNIX2003 ___open_nocancel
-_open$UNIX2003 ___open
-_poll ___poll_nocancel
-_poll$NOCANCEL$UNIX2003 ___poll_nocancel
-_poll$UNIX2003 ___poll
-_pread ___pread_nocancel
-_pread$NOCANCEL$UNIX2003 ___pread_nocancel
-_pread$UNIX2003 ___pread
-_pwrite ___pwrite_nocancel
-_pwrite$NOCANCEL$UNIX2003 ___pwrite_nocancel
-_pwrite$UNIX2003 ___pwrite
-_read ___read_nocancel
-_read$NOCANCEL$UNIX2003 ___read_nocancel
-_read$UNIX2003 ___read
-_readv ___readv_nocancel
-_readv$NOCANCEL$UNIX2003 ___readv_nocancel
-_readv$UNIX2003 ___readv
-_recvfrom$NOCANCEL$UNIX2003 ___recvfrom_nocancel
-_recvfrom$UNIX2003 ___recvfrom
-_recvmsg$NOCANCEL$UNIX2003 ___recvmsg_nocancel
-_recvmsg$UNIX2003 ___recvmsg
-_select$DARWIN_EXTSN ___select
-_select$DARWIN_EXTSN$NOCANCEL ___select_nocancel
-_sem_wait ___sem_wait_nocancel
-_sem_wait$NOCANCEL$UNIX2003 ___sem_wait_nocancel
-_sem_wait$UNIX2003 ___sem_wait
-_semctl$UNIX2003 ___semctl
-_sendmsg$NOCANCEL$UNIX2003 ___sendmsg_nocancel
-_sendmsg$UNIX2003 ___sendmsg
-_sendto$NOCANCEL$UNIX2003 ___sendto_nocancel
-_sendto$NOCANCEL$UNIX2003 ___sendto_nocancel
-_sendto$UNIX2003 ___sendto
-_sendto$UNIX2003 ___sendto
-_setattrlist$UNIX2003 ___setattrlist
-_setpgrp ___setpgid
-_setregid$UNIX2003 ___setregid
-_setreuid$UNIX2003 ___setreuid
-_shmctl$UNIX2003 ___shmctl
-_socketpair$UNIX2003 ___socketpair
-_stat$INODE64 ___stat64
-_statfs$INODE64 ___statfs64
-_waitid ___waitid_nocancel
-_waitid$NOCANCEL$UNIX2003 ___waitid_nocancel
-_waitid$UNIX2003 ___waitid
-_write ___write_nocancel
-_write$NOCANCEL$UNIX2003 ___write_nocancel
-_write$UNIX2003 ___write
-_writev ___writev_nocancel
-_writev$NOCANCEL$UNIX2003 ___writev_nocancel
-_writev$UNIX2003 ___writev
+++ /dev/null
-_accept$NOCANCEL$UNIX2003 ___accept_nocancel
-_accept$UNIX2003 ___accept
-_accept$UNIX2003 ___accept
-_aio_suspend ___aio_suspend_nocancel
-_aio_suspend$NOCANCEL$UNIX2003 ___aio_suspend_nocancel
-_aio_suspend$UNIX2003 ___aio_suspend
-_bind$UNIX2003 ___bind
-_close ___close_nocancel
-_close$NOCANCEL$UNIX2003 ___close_nocancel
-_close$UNIX2003 ___close
-_connect$NOCANCEL$UNIX2003 ___connect_nocancel
-_connect$UNIX2003 ___connect
-_connect$UNIX2003 ___connect
-_fcntl ___fcntl_nocancel
-_fcntl$NOCANCEL$UNIX2003 ___fcntl_nocancel
-_fcntl$UNIX2003 ___fcntl
-_fstat$INODE64 ___fstat64
-_fstatfs$INODE64 ___fstatfs64
-_fsync ___fsync_nocancel
-_fsync$NOCANCEL$UNIX2003 ___fsync_nocancel
-_fsync$UNIX2003 ___fsync
-_getattrlist$UNIX2003 ___getattrlist
-_getfsstat$INODE64 ___getfsstat64
-_getpeername$UNIX2003 ___getpeername
-_getsockname$UNIX2003 ___getsockname
-_lchown$UNIX2003 ___lchown
-_listen$UNIX2003 ___listen
-_lstat$INODE64 ___lstat64
-_mprotect$UNIX2003 ___mprotect
-_msgctl$UNIX2003 ___msgctl
-_msgrcv ___msgrcv_nocancel
-_msgrcv$NOCANCEL$UNIX2003 ___msgrcv_nocancel
-_msgrcv$UNIX2003 ___msgrcv
-_msgsnd ___msgsnd_nocancel
-_msgsnd$NOCANCEL$UNIX2003 ___msgsnd_nocancel
-_msgsnd$UNIX2003 ___msgsnd
-_msync$NOCANCEL$UNIX2003 ___msync_nocancel
-_msync$UNIX2003 ___msync
-_munmap$UNIX2003 ___munmap
-_open$NOCANCEL$UNIX2003 ___open_nocancel
-_open$UNIX2003 ___open
-_poll ___poll_nocancel
-_poll$NOCANCEL$UNIX2003 ___poll_nocancel
-_poll$UNIX2003 ___poll
-_pread ___pread_nocancel
-_pread$NOCANCEL$UNIX2003 ___pread_nocancel
-_pread$UNIX2003 ___pread
-_pwrite ___pwrite_nocancel
-_pwrite$NOCANCEL$UNIX2003 ___pwrite_nocancel
-_pwrite$UNIX2003 ___pwrite
-_read ___read_nocancel
-_read$NOCANCEL$UNIX2003 ___read_nocancel
-_read$UNIX2003 ___read
-_readv ___readv_nocancel
-_readv$NOCANCEL$UNIX2003 ___readv_nocancel
-_readv$UNIX2003 ___readv
-_recvfrom$NOCANCEL$UNIX2003 ___recvfrom_nocancel
-_recvfrom$UNIX2003 ___recvfrom
-_recvmsg$NOCANCEL$UNIX2003 ___recvmsg_nocancel
-_recvmsg$UNIX2003 ___recvmsg
-_select$DARWIN_EXTSN ___select
-_select$DARWIN_EXTSN$NOCANCEL ___select_nocancel
-_sem_wait ___sem_wait_nocancel
-_sem_wait$NOCANCEL$UNIX2003 ___sem_wait_nocancel
-_sem_wait$UNIX2003 ___sem_wait
-_semctl$UNIX2003 ___semctl
-_sendmsg$NOCANCEL$UNIX2003 ___sendmsg_nocancel
-_sendmsg$UNIX2003 ___sendmsg
-_sendto$NOCANCEL$UNIX2003 ___sendto_nocancel
-_sendto$NOCANCEL$UNIX2003 ___sendto_nocancel
-_sendto$UNIX2003 ___sendto
-_sendto$UNIX2003 ___sendto
-_setattrlist$UNIX2003 ___setattrlist
-_setpgrp ___setpgid
-_setregid$UNIX2003 ___setregid
-_setreuid$UNIX2003 ___setreuid
-_shmctl$UNIX2003 ___shmctl
-_socketpair$UNIX2003 ___socketpair
-_stat$INODE64 ___stat64
-_statfs$INODE64 ___statfs64
-_waitid ___waitid_nocancel
-_waitid$NOCANCEL$UNIX2003 ___waitid_nocancel
-_waitid$UNIX2003 ___waitid
-_write ___write_nocancel
-_write$NOCANCEL$UNIX2003 ___write_nocancel
-_write$UNIX2003 ___write
-_writev ___writev_nocancel
-_writev$NOCANCEL$UNIX2003 ___writev_nocancel
-_writev$UNIX2003 ___writev
+++ /dev/null
-_accept$NOCANCEL$UNIX2003 ___accept_nocancel
-_accept$UNIX2003 ___accept
-_accept$UNIX2003 ___accept
-_aio_suspend ___aio_suspend_nocancel
-_aio_suspend$NOCANCEL$UNIX2003 ___aio_suspend_nocancel
-_aio_suspend$UNIX2003 ___aio_suspend
-_bind$UNIX2003 ___bind
-_close ___close_nocancel
-_close$NOCANCEL$UNIX2003 ___close_nocancel
-_close$UNIX2003 ___close
-_connect$NOCANCEL$UNIX2003 ___connect_nocancel
-_connect$UNIX2003 ___connect
-_connect$UNIX2003 ___connect
-_fcntl ___fcntl_nocancel
-_fcntl$NOCANCEL$UNIX2003 ___fcntl_nocancel
-_fcntl$UNIX2003 ___fcntl
-_fstat$INODE64 ___fstat64
-_fstatfs$INODE64 ___fstatfs64
-_fsync ___fsync_nocancel
-_fsync$NOCANCEL$UNIX2003 ___fsync_nocancel
-_fsync$UNIX2003 ___fsync
-_getattrlist$UNIX2003 ___getattrlist
-_getfsstat$INODE64 ___getfsstat64
-_getpeername$UNIX2003 ___getpeername
-_getsockname$UNIX2003 ___getsockname
-_lchown$UNIX2003 ___lchown
-_listen$UNIX2003 ___listen
-_lstat$INODE64 ___lstat64
-_mprotect$UNIX2003 ___mprotect
-_msgctl$UNIX2003 ___msgctl
-_msgrcv ___msgrcv_nocancel
-_msgrcv$NOCANCEL$UNIX2003 ___msgrcv_nocancel
-_msgrcv$UNIX2003 ___msgrcv
-_msgsnd ___msgsnd_nocancel
-_msgsnd$NOCANCEL$UNIX2003 ___msgsnd_nocancel
-_msgsnd$UNIX2003 ___msgsnd
-_msync$NOCANCEL$UNIX2003 ___msync_nocancel
-_msync$UNIX2003 ___msync
-_munmap$UNIX2003 ___munmap
-_open$NOCANCEL$UNIX2003 ___open_nocancel
-_open$UNIX2003 ___open
-_poll ___poll_nocancel
-_poll$NOCANCEL$UNIX2003 ___poll_nocancel
-_poll$UNIX2003 ___poll
-_pread ___pread_nocancel
-_pread$NOCANCEL$UNIX2003 ___pread_nocancel
-_pread$UNIX2003 ___pread
-_pwrite ___pwrite_nocancel
-_pwrite$NOCANCEL$UNIX2003 ___pwrite_nocancel
-_pwrite$UNIX2003 ___pwrite
-_read ___read_nocancel
-_read$NOCANCEL$UNIX2003 ___read_nocancel
-_read$UNIX2003 ___read
-_readv ___readv_nocancel
-_readv$NOCANCEL$UNIX2003 ___readv_nocancel
-_readv$UNIX2003 ___readv
-_recvfrom$NOCANCEL$UNIX2003 ___recvfrom_nocancel
-_recvfrom$UNIX2003 ___recvfrom
-_recvmsg$NOCANCEL$UNIX2003 ___recvmsg_nocancel
-_recvmsg$UNIX2003 ___recvmsg
-_select$DARWIN_EXTSN ___select
-_select$DARWIN_EXTSN$NOCANCEL ___select_nocancel
-_sem_wait ___sem_wait_nocancel
-_sem_wait$NOCANCEL$UNIX2003 ___sem_wait_nocancel
-_sem_wait$UNIX2003 ___sem_wait
-_semctl$UNIX2003 ___semctl
-_sendmsg$NOCANCEL$UNIX2003 ___sendmsg_nocancel
-_sendmsg$UNIX2003 ___sendmsg
-_sendto$NOCANCEL$UNIX2003 ___sendto_nocancel
-_sendto$NOCANCEL$UNIX2003 ___sendto_nocancel
-_sendto$UNIX2003 ___sendto
-_sendto$UNIX2003 ___sendto
-_setattrlist$UNIX2003 ___setattrlist
-_setpgrp ___setpgid
-_setregid$UNIX2003 ___setregid
-_setreuid$UNIX2003 ___setreuid
-_shmctl$UNIX2003 ___shmctl
-_socketpair$UNIX2003 ___socketpair
-_stat$INODE64 ___stat64
-_statfs$INODE64 ___statfs64
-_waitid ___waitid_nocancel
-_waitid$NOCANCEL$UNIX2003 ___waitid_nocancel
-_waitid$UNIX2003 ___waitid
-_write ___write_nocancel
-_write$NOCANCEL$UNIX2003 ___write_nocancel
-_write$UNIX2003 ___write
-_writev ___writev_nocancel
-_writev$NOCANCEL$UNIX2003 ___writev_nocancel
-_writev$UNIX2003 ___writev
+++ /dev/null
-_accept$NOCANCEL ___accept_nocancel
-_aio_suspend$NOCANCEL ___aio_suspend_nocancel
-_close$NOCANCEL ___close_nocancel
-_connect$NOCANCEL ___connect_nocancel
-_fstat$INODE64 ___fstat64
-_fstatfs$INODE64 ___fstatfs64
-_fsync$NOCANCEL ___fsync_nocancel
-_getfsstat$INODE64 ___getfsstat64
-_lstat$INODE64 ___lstat64
-_msgrcv$NOCANCEL ___msgrcv_nocancel
-_msgsnd$NOCANCEL ___msgsnd_nocancel
-_msync$NOCANCEL ___msync_nocancel
-_open$NOCANCEL ___open_nocancel
-_poll$NOCANCEL ___poll_nocancel
-_pread$NOCANCEL ___pread_nocancel
-_pwrite$NOCANCEL ___pwrite_nocancel
-_read$NOCANCEL ___read_nocancel
-_readv$NOCANCEL ___readv_nocancel
-_recvfrom$NOCANCEL ___recvfrom_nocancel
-_recvmsg$NOCANCEL ___recvmsg_nocancel
-_select$DARWIN_EXTSN ___select
-_select$DARWIN_EXTSN$NOCANCEL ___select_nocancel
-_sem_wait$NOCANCEL ___sem_wait_nocancel
-_sendmsg$NOCANCEL ___sendmsg_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_stat$INODE64 ___stat64
-_statfs$INODE64 ___statfs64
-_waitid$NOCANCEL ___waitid_nocancel
-_write$NOCANCEL ___write_nocancel
-_writev$NOCANCEL ___writev_nocancel
+++ /dev/null
-_accept$NOCANCEL ___accept_nocancel
-_aio_suspend$NOCANCEL ___aio_suspend_nocancel
-_close$NOCANCEL ___close_nocancel
-_connect$NOCANCEL ___connect_nocancel
-_fstat$INODE64 ___fstat64
-_fstatfs$INODE64 ___fstatfs64
-_fsync$NOCANCEL ___fsync_nocancel
-_getfsstat$INODE64 ___getfsstat64
-_lstat$INODE64 ___lstat64
-_msgrcv$NOCANCEL ___msgrcv_nocancel
-_msgsnd$NOCANCEL ___msgsnd_nocancel
-_msync$NOCANCEL ___msync_nocancel
-_open$NOCANCEL ___open_nocancel
-_poll$NOCANCEL ___poll_nocancel
-_pread$NOCANCEL ___pread_nocancel
-_pwrite$NOCANCEL ___pwrite_nocancel
-_read$NOCANCEL ___read_nocancel
-_readv$NOCANCEL ___readv_nocancel
-_recvfrom$NOCANCEL ___recvfrom_nocancel
-_recvmsg$NOCANCEL ___recvmsg_nocancel
-_select$DARWIN_EXTSN ___select
-_select$DARWIN_EXTSN$NOCANCEL ___select_nocancel
-_sem_wait$NOCANCEL ___sem_wait_nocancel
-_sendmsg$NOCANCEL ___sendmsg_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_stat$INODE64 ___stat64
-_statfs$INODE64 ___statfs64
-_waitid$NOCANCEL ___waitid_nocancel
-_write$NOCANCEL ___write_nocancel
-_writev$NOCANCEL ___writev_nocancel
# Legacy *64 APIs
#FEATURE_LEGACY_64_APIS = 1
+# Legacy crt1.o environ support
+#FEATURE_LEGACY_CRT1_ENVIRON = 1
+
# Legacy NX international APIs
FEATURE_LEGACY_NX_INTERNAT_APIS = 1
FEATURE_MEM_THERM_NOTIFICATION_APIS = 1
# Move localtime to /var/db/timezone
+.if $(RC_ProjectName) == $(RC_ProjectName:%_Sim=%)
FEATURE_MOVE_LOCALTIME = 1
+.endif
# Long doubles are doubles (should match sys/cdefs.h)
.if (${MACHINE_ARCH} == arm)
# Patch 3333969
#FEATURE_PATCH_3333969 = 1
-# Patch 3375657
-#FEATURE_PATCH_3375657 = 1
-
# Patch 3417676
#FEATURE_PATCH_3417676 = 1
#FEATURE_PLOCKSTAT = 1
# Timezone change notification
-#FEATURE_TIMEZONE_CHANGE_NOTIFICATION = 1
+FEATURE_TIMEZONE_CHANGE_NOTIFICATION = 1
+++ /dev/null
-_accept$NOCANCEL ___accept_nocancel
-_aio_suspend$NOCANCEL ___aio_suspend_nocancel
-_close$NOCANCEL ___close_nocancel
-_connect$NOCANCEL ___connect_nocancel
-_fstat ___fstat64
-_fstat64
-_fstatfs ___fstatfs64
-_fstatfs64
-_fstatx_np ___fstatx64_np
-_fstatx64_np
-_fsync$NOCANCEL ___fsync_nocancel
-_getfsstat ___getfsstat64
-_getfsstat64
-_getmntinfo ___getmntinfo64
-_getmntinfo64
-_lstat ___lstat64
-_lstat64
-_lstatx_np ___lstatx64_np
-_lstatx64_np
-_msgrcv$NOCANCEL ___msgrcv_nocancel
-_msgsnd$NOCANCEL ___msgsnd_nocancel
-_msync$NOCANCEL ___msync_nocancel
-_open$NOCANCEL ___open_nocancel
-_poll$NOCANCEL ___poll_nocancel
-_pread$NOCANCEL ___pread_nocancel
-_pwrite$NOCANCEL ___pwrite_nocancel
-_read$NOCANCEL ___read_nocancel
-_readv$NOCANCEL ___readv_nocancel
-_recvfrom$NOCANCEL ___recvfrom_nocancel
-_recvmsg$NOCANCEL ___recvmsg_nocancel
-_select$DARWIN_EXTSN ___select
-_select$DARWIN_EXTSN$NOCANCEL ___select_nocancel
-_sem_wait$NOCANCEL ___sem_wait_nocancel
-_sendmsg$NOCANCEL ___sendmsg_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_sendto$NOCANCEL ___sendto_nocancel
-_stat ___stat64
-_stat64
-_statfs ___statfs64
-_statfs64
-_statx_np ___statx64_np
-_statx64_np
-_waitid$NOCANCEL ___waitid_nocancel
-_write$NOCANCEL ___write_nocancel
-_writev$NOCANCEL ___writev_nocancel
.PATH: ${.CURDIR}/arm/gen
-MDSRCS+= icacheinval.s
+MDSRCS += \
+ cpu_number.s \
+ icacheinval.s
+
+DYLDSRCS += icacheinval.s
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <arm/arch.h>
+
+#define __APPLE_API_PRIVATE
+#include <machine/cpu_capabilities.h>
+#undef __APPLE_API_PRIVATE
+
+ .text
+ .align 2
+ .globl _cpu_number
+_cpu_number:
+#ifdef _ARM_ARCH_7
+ mrc p15, 0, r0, c13, c0, 3
+ and r0, r0, #3
+#else
+ mov r0, #0
+#endif
+ bx lr
start_wqthread.s \
thread_start.s
+DYLDSRCS += \
+ pthread_getspecific.s \
+ pthread_self.s \
+ pthread_set_self.s
_pthread_getspecific:
#ifdef _ARM_ARCH_6
mrc p15, 0, r1, c13, c0, 3
+ bic r1, r1, #3
add r0, r1, r0, lsl #2
#else
add r0, r9, r0, lsl #2
#endif
- ldr r0, [r0, #_PTHREAD_TSD_OFFSET]
+ ldr r0, [r0, #0]
bx lr
_pthread_self:
#ifdef _ARM_ARCH_6
mrc p15, 0, r0, c13, c0, 3
+ bic r0, r0, #3
#else
mov r0, r9
#endif
+ ldr r0, [r0, #0]
bx lr
#
.PATH: ${.CURDIR}/arm/string
-MDSRCS += \
- bcopy.s \
- bzero.s \
- ffs.s \
- memcmp.s \
- memset_pattern.s \
+MDSRCS += \
+ bcopy_Generic.s \
+ bcopy_CortexA8.s \
+ bcopy_CortexA9.s \
+ bzero_Generic.s \
+ bzero_CortexA8.s \
+ bzero_CortexA9.s \
+ dyld_resolvers.c \
+ ffs.s \
+ memcmp.s \
+ strcmp.s \
+ strncmp.s \
+ strlen.s \
+ strchr.s \
+ strstr.s \
+ strcpy.s \
+ strlcpy.s \
+ strncpy.s \
+ strnlen.s
+
+DYLDSRCS += \
+ bcopy_Generic.s \
+ bzero_Generic.s \
+ ffs.s \
strcmp.s \
strlen.s
-SUPPRESSSRCS += bcmp.c memcpy.c memmove.c memset.c strlen.c
+.if defined(FEATURE_ARM_ARCH_6)
+MDSRCS += memset_pattern.s
+.endif
+
+SUPPRESSSRCS += \
+ bcmp.c \
+ memcpy.c \
+ memmove.c \
+ memset.c \
+ strncmp.c \
+ strlen.c \
+ strchr.c \
+ strstr.c \
+ strcpy.c \
+ strlcpy.c \
+ strncpy.c \
+ strnlen.c
+
+++ /dev/null
-/*
- * Copyright (c) 2009 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@
- */
-
-/*****************************************************************************
- * Cortex-A8 implementation *
- *****************************************************************************/
-
-// Cortex-A8 implementations of memcpy( ), memmove( ) and bcopy( ).
-//
-// Our tests have shown that NEON is always a performance win for memcpy( ).
-// However, for the specific case of copies from a warm source to a cold
-// destination when the buffer size is between 1k and 32k, it is not enough
-// of a performance win to offset the increased power footprint, resulting
-// in an energy usage regression. Thus, we detect that particular case, and
-// pass those copies through the ARM core registers. All other copies larger
-// than 8 bytes are handled on NEON.
-//
-// Stephen Canon, August 2009
-
-.text
-.code 16
-.syntax unified
-
-// void bcopy(const void * source,
-// void * destination,
-// size_t length);
-//
-// void *memmove(void * destination,
-// const void * source,
-// size_t n);
-//
-// void *memcpy(void * restrict destination,
-// const void * restrict source,
-// size_t n);
-//
-// all copy n successive bytes from source to destination. memmove and memcpy
-// returns destination, whereas bcopy has no return value. copying takes place
-// as if it were through a temporary buffer -- after return destination contains
-// exactly the bytes from source, even if the buffers overlap.
-
-.thumb_func _bcopy
-.globl _bcopy
-.thumb_func _memmove
-.globl _memmove
-.thumb_func _memcpy
-.globl _memcpy
-
-.align 2
-_bcopy:
- mov r3, r0 // swap the first and second arguments
- mov r0, r1 // and fall through into memmove
- mov r1, r3 //
-
-.align 2
-_memmove:
-_memcpy:
- subs r3, r0, r1 // offset = destination addr - source addr
- it eq
- bxeq lr // if source == destination, early out
-
-// Our preference is for using a (faster) front-to-back copy. However, if
-// 0 < offset < length, it is necessary to copy back-to-front for correctness.
-// We have already ruled out offset == 0, so we can use an unsigned compare
-// with length -- if offset is higher, offset is either greater than length
-// or negative.
-
- cmp r3, r2
- bhs L_copyFrontToBack
-
-/*****************************************************************************
- * back to front copy *
- *****************************************************************************/
-
- mov ip, r0 // copy destination pointer.
- add r1, r2 // move source pointer to end of source array
- add ip, r2 // move destination pointer to end of dest array
-
- subs r2, $8 // if length - 8 is negative (i.e. length
- blt L_scalarReverseCopy // is less than 8), jump to cleanup path.
- tst ip, $7 // if (destination + length) is doubleword
- beq L_vectorReverseCopy // aligned, jump to fast path.
-
-0: ldrb r3, [r1, $-1]! // load byte
- sub r2, $1 // decrement length
- strb r3, [ip, $-1]! // store byte
- tst ip, $7 // test alignment
- bne 0b
-
- cmp r2, $0 // if length - 8 is negative,
- blt L_scalarReverseCopy // jump to the cleanup code
-
-/*****************************************************************************
- * destination is doubleword aligned *
- *****************************************************************************/
-
-L_vectorReverseCopy:
- ands r3, r1, $3 // Extract the alignment of the source
- bic r1, $3
- tbh [pc, r3, lsl $1] // Dispatch table on source alignment
-0:
-.short (L_reverseAligned0-0b)/2 // The NEON alignment hardware does not work
-.short (L_reverseAligned1-0b)/2 // properly with sub 4-byte alignment and
-.short (L_reverseAligned2-0b)/2 // buffers that are uncacheable, so we need
-.short (L_reverseAligned3-0b)/2 // to have a software workaround.
-
-/*****************************************************************************
- * source is also at least word aligned *
- *****************************************************************************/
-
-L_reverseAligned0:
- subs r2, $0x38 // if length - 64 is negative, jump to
- blt L_reverseVectorCleanup// the cleanup path.
- tst ip, $0x38 // if (destination + length) is cacheline
- beq L_reverseCachelineAligned // aligned, jump to the fast path.
-
-0: sub r1, $8 // copy eight bytes at a time until the
- vld1.32 {d0}, [r1] // destination is 8 byte aligned.
- sub ip, $8 //
- sub r2, $8 //
- tst ip, $0x38 //
- vst1.64 {d0}, [ip, :64] //
- bne 0b //
-
- cmp r2, $0 // if length - 64 is negative,
- blt L_reverseVectorCleanup// jump to the cleanup code
-
-L_reverseCachelineAligned:
- sub r3, r2, $0x3c0 // If 1024 < length < 32768, use core
- cmp r3, $0x7c00 // register copies instead of NEON to
- blo L_useSTMDB // control energy usage.
-
- sub r1, $32 // decrement source
- sub ip, $32 // decrement destination
- mov r3, $-32 // load address increment
- tst r1, $0x1f // if source shares 32 byte alignment
- beq L_reverseSourceAligned// jump to loop with more alignment hints
-
- vld1.32 {q2,q3}, [r1], r3 // This loop handles 4-byte aligned copies
- vld1.32 {q0,q1}, [r1], r3 // as generally as possible.
- subs r2, $64 //
- vst1.64 {q2,q3}, [ip,:256], r3 // The Cortex-A8 NEON unit does not always
- blt 1f // properly handle misalignment in vld1
-.align 3 // with an element size of 8 or 16, so
-0: vld1.32 {q2,q3}, [r1], r3 // this is the best we can do without
- vst1.64 {q0,q1}, [ip,:256], r3 // handling alignment in software.
- vld1.32 {q0,q1}, [r1], r3 //
- subs r2, $64 //
- vst1.64 {q2,q3}, [ip,:256], r3 //
- bge 0b //
- b 1f //
-
-L_reverseSourceAligned:
- vld1.64 {q2,q3}, [r1,:256], r3 // Identical to loop above except for
- vld1.64 {q0,q1}, [r1,:256], r3 // additional alignment information; this
- subs r2, $64 // gets an additional .5 bytes per cycle
- vst1.64 {q2,q3}, [ip,:256], r3 // on Cortex-A8.
- blt 1f //
-.align 3 //
-0: vld1.64 {q2,q3}, [r1,:256], r3 //
- vst1.64 {q0,q1}, [ip,:256], r3 //
- vld1.64 {q0,q1}, [r1,:256], r3 //
- subs r2, $64 //
- vst1.64 {q2,q3}, [ip,:256], r3 //
- bge 0b //
-1: vst1.64 {q0,q1}, [ip,:256], r3 // loop cleanup: final 32 byte store
- add r1, $32 // point source at last element stored
- add ip, $32 // point destination at last element stored
-
-L_reverseVectorCleanup:
- adds r2, $0x38 // If (length - 8) < 0, goto scalar cleanup
- blt L_scalarReverseCopy //
-
-0: sub r1, $8 // copy eight bytes at a time until
- vld1.32 {d0}, [r1] // (length - 8) < 0.
- sub ip, $8 //
- subs r2, $8 //
- vst1.64 {d0}, [ip, :64] //
- bge 0b //
-
-/*****************************************************************************
- * sub-doubleword cleanup copies *
- *****************************************************************************/
-
-L_scalarReverseCopy:
- adds r2, #0x8 // restore length
- it eq // if this is zero
- bxeq lr // early out
-
-0: ldrb r3, [r1, #-1]! // load a byte from source
- strb r3, [ip, #-1]! // store to destination
- subs r2, #0x1 // subtract one from length
- bne 0b // if non-zero, repeat
- bx lr // return
-
-/*****************************************************************************
- * STMDB loop for 1k-32k buffers *
- *****************************************************************************/
-
-L_useSTMDB:
- push {r4-r8,r10,r11}
-.align 3
-0: ldmdb r1!, {r3-r8,r10,r11}
- subs r2, #0x40
- stmdb ip!, {r3-r8,r10,r11}
- ldmdb r1!, {r3-r8,r10,r11}
- pld [r1, #-0x40]
- stmdb ip!, {r3-r8,r10,r11}
- bge 0b
- pop {r4-r8,r10,r11}
- b L_reverseVectorCleanup
-
-/*****************************************************************************
- * Misaligned vld1 loop *
- *****************************************************************************/
-
-// Software alignment fixup to handle source and dest that are relatively
-// misaligned mod 4 bytes. Load two 4-byte aligned double words from source,
-// use vext.8 to extract a double word to store, and perform an 8-byte aligned
-// store to destination.
-
-#define RCOPY_UNALIGNED(offset) \
- subs r2, $8 ;\
- blt 2f ;\
- sub r1, $8 ;\
- sub ip, $8 ;\
- mov r3, $-8 ;\
- vld1.32 {d2,d3}, [r1], r3 ;\
- subs r2, $8 ;\
- blt 1f ;\
-0: vext.8 d0, d2, d3, $(offset);\
- vmov d3, d2 ;\
- vld1.32 {d2}, [r1], r3 ;\
- subs r2, $8 ;\
- vst1.64 {d0}, [ip, :64], r3 ;\
- bge 0b ;\
-1: vext.8 d0, d2, d3, $(offset);\
- add r1, $8 ;\
- vst1.64 {d0}, [ip, :64] ;\
-2: add r2, $8 ;\
- add r1, $(offset);\
- b L_scalarReverseCopy
-
-L_reverseAligned1:
- RCOPY_UNALIGNED(1)
-L_reverseAligned2:
- RCOPY_UNALIGNED(2)
-L_reverseAligned3:
- RCOPY_UNALIGNED(3)
-
-/*****************************************************************************
- * front to back copy *
- *****************************************************************************/
-
-L_copyFrontToBack:
- mov ip, r0 // copy destination pointer.
- subs r2, $8 // if length - 8 is negative (i.e. length
- blt L_scalarCopy // is less than 8), jump to cleanup path.
- tst ip, $7 // if the destination is doubleword
- beq L_vectorCopy // aligned, jump to fast path.
-
-0: ldrb r3, [r1], $1 // load byte
- sub r2, $1 // decrement length
- strb r3, [ip], $1 // store byte
- tst ip, $7 // test alignment
- bne 0b
-
- cmp r2, $0 // if length - 8 is negative,
- blt L_scalarCopy // jump to the cleanup code
-
-/*****************************************************************************
- * destination is doubleword aligned *
- *****************************************************************************/
-
-L_vectorCopy:
- ands r3, r1, $3 // Extract the alignment of the source
- bic r1, $3
- tbh [pc, r3, lsl $1] // Dispatch table on source alignment
-0:
-.short (L_sourceAligned0-0b)/2 // The NEON alignment hardware does not work
-.short (L_sourceAligned1-0b)/2 // properly with sub 4-byte alignment and
-.short (L_sourceAligned2-0b)/2 // buffers that are uncacheable, so we need
-.short (L_sourceAligned3-0b)/2 // to have a software workaround.
-
-/*****************************************************************************
- * source is also at least word aligned *
- *****************************************************************************/
-
-L_sourceAligned0:
- subs r2, $0x38 // If (length - 64) < 0
- blt L_vectorCleanup // jump to cleanup code
- tst ip, $0x38 // If destination is 64 byte aligned
- beq L_cachelineAligned // jump to main loop
-
-0: vld1.32 {d0}, [r1]! // Copy one double word at a time until
- sub r2, $8 // the destination is 64-byte aligned.
- vst1.64 {d0}, [ip, :64]! //
- tst ip, $0x38 //
- bne 0b //
-
- cmp r2, $0 // If (length - 64) < 0, goto cleanup
- blt L_vectorCleanup //
-
-L_cachelineAligned:
- sub r3, r2, $0x3c0 // If 1024 < length < 32768, use core
- cmp r3, $0x7c00 // register copies instead of NEON to
- blo L_useSTMIA // control energy usage.
- tst r1, $0x1f // If source has 32-byte alignment, use
- beq L_sourceAligned32 // an optimized loop.
-
- vld1.32 {q2,q3}, [r1]! // This is the most common path for small
- vld1.32 {q0,q1}, [r1]! // copies, which are alarmingly frequent.
- subs r2, #0x40 // It requires 4-byte alignment on the
- vst1.64 {q2,q3}, [ip, :256]! // source. For ordinary malloc'd buffers,
- blt 1f // this path could handle only single-byte
-.align 3 // alignment at speed by using vld1.8
-0: vld1.32 {q2,q3}, [r1]! // instead of vld1.32; however, the NEON
- vst1.64 {q0,q1}, [ip, :256]! // alignment handler misbehaves for some
- vld1.32 {q0,q1}, [r1]! // special copies if the element size is
- subs r2, #0x40 // 8 or 16, so we need to work around
- vst1.64 {q2,q3}, [ip, :256]! // sub 4-byte alignment in software, in
- bge 0b // another code path.
- b 1f
-
-L_sourceAligned32:
- vld1.64 {q2,q3}, [r1, :256]! // When the source shares 32-byte alignment
- vld1.64 {q0,q1}, [r1, :256]! // with the destination, we use this loop
- subs r2, #0x40 // instead, which specifies the maximum
- vst1.64 {q2,q3}, [ip, :256]! // :256 alignment on all loads and stores.
- blt 1f //
-.align 3 // This gets an additional .5 bytes per
-0: vld1.64 {q2,q3}, [r1, :256]! // cycle for in-cache copies, which is not
- vst1.64 {q0,q1}, [ip, :256]! // insignificant for this (rather common)
- vld1.64 {q0,q1}, [r1, :256]! // case.
- subs r2, #0x40 //
- vst1.64 {q2,q3}, [ip, :256]! // This is identical to the above loop,
- bge 0b // except for the additional alignment.
-1: vst1.64 {q0,q1}, [ip, :256]! //
-
-L_vectorCleanup:
- adds r2, $0x38 // If (length - 8) < 0, goto scalar cleanup
- blt L_scalarCopy //
-
-0: vld1.32 {d0}, [r1]! // Copy one doubleword at a time until
- subs r2, $8 // (length - 8) < 0.
- vst1.64 {d0}, [ip, :64]! //
- bge 0b //
-
-/*****************************************************************************
- * sub-doubleword cleanup copies *
- *****************************************************************************/
-
-L_scalarCopy:
- adds r2, #0x8 // restore length
- it eq // if this is zero
- bxeq lr // early out
-
-0: ldrb r3, [r1], #1 // load a byte from source
- strb r3, [ip], #1 // store to destination
- subs r2, #1 // subtract one from length
- bne 0b // if non-zero, repeat
- bx lr // return
-
-/*****************************************************************************
- * STMIA loop for 1k-32k buffers *
- *****************************************************************************/
-
-L_useSTMIA:
- push {r4-r8,r10,r11}
-.align 3
-0: ldmia r1!, {r3-r8,r10,r11}
- subs r2, r2, #64
- stmia ip!, {r3-r8,r10,r11}
- ldmia r1!, {r3-r8,r10,r11}
- pld [r1, #64]
- stmia ip!, {r3-r8,r10,r11}
- bge 0b
- pop {r4-r8,r10,r11}
- b L_vectorCleanup
-
-/*****************************************************************************
- * Misaligned reverse vld1 loop *
- *****************************************************************************/
-
-// Software alignment fixup to handle source and dest that are relatively
-// misaligned mod 4 bytes. Load two 4-byte aligned double words from source,
-// use vext.8 to extract a double word to store, and perform an 8-byte aligned
-// store to destination.
-
-#define COPY_UNALIGNED(offset) \
- subs r2, $8 ;\
- blt 2f ;\
- vld1.32 {d2,d3}, [r1]! ;\
- subs r2, $8 ;\
- blt 1f ;\
-0: vext.8 d0, d2, d3, $(offset);\
- vmov d2, d3 ;\
- vld1.32 {d3}, [r1]! ;\
- subs r2, $8 ;\
- vst1.64 {d0}, [ip, :64]! ;\
- bge 0b ;\
-1: vext.8 d0, d2, d3, $(offset);\
- sub r1, $8 ;\
- vst1.64 {d0}, [ip, :64]! ;\
-2: add r1, $(offset);\
- add r2, $8 ;\
- b L_scalarCopy
-
-L_sourceAligned1:
- COPY_UNALIGNED(1)
-L_sourceAligned2:
- COPY_UNALIGNED(2)
-L_sourceAligned3:
- COPY_UNALIGNED(3)
+++ /dev/null
-/*
- * Copyright (c) 2009 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@
- */
-
-/**********************************************************************
- * Cortex-A8 implementation *
- **********************************************************************/
-
-// Cortex-A8 implementations of memset( ) and bzero( ). Main loop is 64-byte
-// NEON stores, unless the buffer length is > 1k. Beyond that point, there is
-// little to no speed advantage with NEON (and a slight regression in some
-// measured cases), so we switch to the GPRs.
-//
-// The crossover point should be reevaluated for future architectures.
-//
-// -- Stephen Canon, August 2009
-
-.text
-.syntax unified
-.code 16
-
-// void bzero(void * destination,
-// size_t length);
-//
-// zeros out a buffer length bytes long, beginning at the address destination.
-.thumb_func ___bzero
-.globl ___bzero
-.thumb_func _bzero
-.globl _bzero
-.align 2
-___bzero:
-_bzero:
- mov r2, r1 // match the API to memset(dest, 0, length)
- eor r1, r1 // and fall through into memset
-
-// void *memset(void * destination,
-// int value, size_t n);
-//
-// writes value converted to an unsigned char to n successive bytes, beginning
-// at destination.
-
-// Notes on register usage:
-//
-// Throughout this function, registers have nearly constant usage; the pattern
-// is:
-//
-// r0 holds the original destination pointer, unmodified. This value
-// must be returned by the routine, so it is easiest to just leave it
-// in place.
-// r1 holds the value that is being copied into the buffer, in some stage
-// of splattedness. The low byte is guaranteed to always have the value
-// but the higher bytes may or may not contain copies of it.
-// r2 holds the length minus some offset, where the offset is always the
-// number of bytes that the current loop stores per iteration.
-// r3-r6,r8,r10,r11 are used with stmia, and will only ever contain splatted
-// copies of the value to be stored.
-// ip holds a pointer to the lowest byte in the array that has not yet been
-// set to hold value.
-// q0 and q1 hold splatted copies of the value in the vector path, and are
-// otherwise unused.
-
-.thumb_func _memset
-.globl _memset
-.align 2
-_memset:
- mov ip, r0 // copy destination pointer.
- subs r2, #0x8 // if length - 8 is negative (i.e. length
- and r1, #0xff // is less than 8), jump to cleanup path.
- blt L_scalarCleanup //
-
- tst ip, #0x7 // if the destination is doubleword
- beq L_vectorCopy // aligned, jump to fast path.
-
-0: strb r1, [ip], #1 // store one byte at a time until
- sub r2, #1 // destination pointer is 8 byte aligned.
- tst ip, #7 //
- bne 0b //
-
- cmp r2, #0x0 // if length - 8 is negative,
- blt L_scalarCleanup // jump to the cleanup code
-
-L_vectorCopy:
- vdup.8 q0, r1 // splat the byte to be stored across
- subs r2, #0x38 // q0 and q1, and check if length - 64
- vmov q1, q0 // is negative; if so, jump to the
- blt L_vectorCleanup // cleanup code.
-
- tst ip, #0x38 // if the destination is cacheline
- beq L_cachelineAligned // aligned, jump to the fast path.
-
-0: vst1.64 {d0}, [ip, :64]! // store one double word at a time until
- sub r2, #8 // the destination is 64-byte aligned
- tst ip, #0x38 //
- bne 0b
-
- cmp r2, #0x0 // if length - 64 is negative,
- blt L_vectorCleanup // jump to the cleanup code
-
-L_cachelineAligned:
- cmp r2, #0x3c0 // if length > 1024
- bge L_useSTMIA // we use stmia instead
-
-.align 4 // main loop
-0: vst1.64 {q0,q1}, [ip, :256]! // store 32 bytes
- subs r2, #0x40 // decrement length by 64
- vst1.64 {q0,q1}, [ip, :256]! // store 32 bytes
- bge 0b // if length - 64 >= 0, continue
-
-L_vectorCleanup:
- adds r2, #0x38 // if (length - 8) < 0, goto scalar cleanup
- blt L_scalarCleanup //
-
-0: subs r2, #8 // store one double word at a time until
- vst1.64 {d0}, [ip, :64]! // (length - 8) < 0.
- bge 0b
-
-L_scalarCleanup:
- adds r2, #8 // restore length
- beq 1f // early out if zero.
-
-0: strb r1, [ip], #1 // store one byte at a time until length
- subs r2, #1 // is zero.
- bne 0b //
-1: bx lr // return.
-
-// STMIA loop for large buffers
-//
-// For stores larger than 1024 bytes, we use STMIA because we can't get enough
-// of a speedup from NEON to offset the higher power draw of the NEON unit.
-//
-// This crossover should be reevaluated on future architectures.
-//
-// We avoid using r7 and r9 even though it's not strictly necessary.
-
-L_useSTMIA:
- push {r4,r5,r6,r8,r10,r11}
- orr r1, r1, r1, lsl #8
- orr r1, r1, r1, lsl #16
- mov r3, r1
- mov r4, r1
- mov r5, r1
- mov r6, r1
- mov r8, r1
- mov r10, r1
- mov r11, r1
-.align 4
-0: stmia ip!, {r1,r3,r4,r5,r6,r8,r10,r11}
- subs r2, #0x40
- stmia ip!, {r1,r3,r4,r5,r6,r8,r10,r11}
- bge 0b
- pop {r4,r5,r6,r8,r10,r11}
- b L_vectorCleanup
+++ /dev/null
-/*
- * Copyright (c) 2006, 2009 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@
- */
-
-#if defined __thumb2__ && defined __ARM_NEON__
-
-// Use our tuned NEON implementation when it is available. Otherwise fall back
-// on more generic ARM code.
-
-#include "NEON/bcopy.s"
-
-#else // defined __thumb2__ && defined __ARM_NEON__
-
-/*****************************************************************************
- * ARMv5 and ARMv6 implementation *
- *****************************************************************************/
-
-#include <arm/arch.h>
-
-.text
-.align 2
-
- .globl _memcpy
- .globl _bcopy
- .globl _memmove
-
-_bcopy: /* void bcopy(const void *src, void *dest, size_t len); */
- mov r3, r0
- mov r0, r1
- mov r1, r3
-
-_memcpy: /* void *memcpy(void *dest, const void *src, size_t len); */
-_memmove: /* void *memmove(void *dest, const void *src, size_t len); */
- /* check for zero len or if the pointers are the same */
- cmp r2, #0
- cmpne r0, r1
- bxeq lr
-
- /* save r0 (return value), r4 (scratch), and r5 (scratch) */
- stmfd sp!, { r0, r4, r5, r7, lr }
- add r7, sp, #12
-
- /* check for overlap. r3 <- distance between src & dest */
- subhs r3, r0, r1
- sublo r3, r1, r0
- cmp r3, r2 /* if distance(src, dest) < len, we have overlap */
- blo Loverlap
-
-Lnormalforwardcopy:
- /* are src and dest dissimilarly word aligned? */
- mov r12, r0, lsl #30
- cmp r12, r1, lsl #30
- bne Lnonwordaligned_forward
-
- /* if len < 64, do a quick forward copy */
- cmp r2, #64
- blt Lsmallforwardcopy
-
- /* check for 16 byte src/dest unalignment */
- tst r0, #0xf
- bne Lsimilarlyunaligned
-
- /* check for 32 byte dest unalignment */
- tst r0, #(1<<4)
- bne Lunaligned_32
-
-Lmorethan64_aligned:
- /* save some more registers to use in the copy */
- stmfd sp!, { r6, r8, r10, r11 }
-
- /* pre-subtract 64 from the len counter to avoid an extra compare in the loop */
- sub r2, r2, #64
-
-L64loop:
- /* copy 64 bytes at a time */
- ldmia r1!, { r3, r4, r5, r6, r8, r10, r11, r12 }
-#ifdef _ARM_ARCH_6
- pld [r1, #32]
-#endif
- stmia r0!, { r3, r4, r5, r6, r8, r10, r11, r12 }
- ldmia r1!, { r3, r4, r5, r6, r8, r10, r11, r12 }
- subs r2, r2, #64
-#ifdef _ARM_ARCH_6
- pld [r1, #32]
-#endif
- stmia r0!, { r3, r4, r5, r6, r8, r10, r11, r12 }
- bge L64loop
-
- /* restore the scratch registers we just saved */
- ldmfd sp!, { r6, r8, r10, r11 }
-
- /* fix up the len counter (previously subtracted an extra 64 from it) and test for completion */
- adds r2, r2, #64
- beq Lexit
-
-Llessthan64_aligned:
- /* copy 16 bytes at a time until we have < 16 bytes */
- cmp r2, #16
- ldmgeia r1!, { r3, r4, r5, r12 }
- stmgeia r0!, { r3, r4, r5, r12 }
- subges r2, r2, #16
- bgt Llessthan64_aligned
- beq Lexit
-
-Llessthan16_aligned:
- mov r2, r2, lsl #28
- msr cpsr_f, r2
-
- ldmmiia r1!, { r2, r3 }
- ldreq r4, [r1], #4
- ldrcsh r5, [r1], #2
- ldrvsb r12, [r1], #1
-
- stmmiia r0!, { r2, r3 }
- streq r4, [r0], #4
- strcsh r5, [r0], #2
- strvsb r12, [r0], #1
- b Lexit
-
-Lsimilarlyunaligned:
- /* both src and dest are unaligned in similar ways, align to dest on 32 byte boundary */
- mov r12, r0, lsl #28
- rsb r12, r12, #0
- msr cpsr_f, r12
-
- ldrvsb r3, [r1], #1
- ldrcsh r4, [r1], #2
- ldreq r5, [r1], #4
-
- strvsb r3, [r0], #1
- strcsh r4, [r0], #2
- streq r5, [r0], #4
-
- ldmmiia r1!, { r3, r4 }
- stmmiia r0!, { r3, r4 }
-
- subs r2, r2, r12, lsr #28
- beq Lexit
-
-Lunaligned_32:
- /* bring up to dest 32 byte alignment */
- tst r0, #(1 << 4)
- ldmneia r1!, { r3, r4, r5, r12 }
- stmneia r0!, { r3, r4, r5, r12 }
- subne r2, r2, #16
-
- /* we should now be aligned, see what copy method we should use */
- cmp r2, #64
- bge Lmorethan64_aligned
- b Llessthan64_aligned
-
-Lbytewise2:
- /* copy 2 bytes at a time */
- subs r2, r2, #2
-
- ldrb r3, [r1], #1
- ldrplb r4, [r1], #1
-
- strb r3, [r0], #1
- strplb r4, [r0], #1
-
- bhi Lbytewise2
- b Lexit
-
-Lbytewise:
- /* simple bytewise forward copy */
- ldrb r3, [r1], #1
- subs r2, r2, #1
- strb r3, [r0], #1
- bne Lbytewise
- b Lexit
-
-Lsmallforwardcopy:
- /* src and dest are word aligned similarly, less than 64 bytes to copy */
- cmp r2, #4
- blt Lbytewise2
-
- /* bytewise copy until word aligned */
- tst r1, #3
-Lwordalignloop:
- ldrneb r3, [r1], #1
- strneb r3, [r0], #1
- subne r2, r2, #1
- tstne r1, #3
- bne Lwordalignloop
-
- cmp r2, #16
- bge Llessthan64_aligned
- blt Llessthan16_aligned
-
-Loverlap:
- /* src and dest overlap in some way, len > 0 */
- cmp r0, r1 /* if dest > src */
- bhi Loverlap_srclower
-
-Loverlap_destlower:
- /* dest < src, see if we can still do a fast forward copy or fallback to slow forward copy */
- cmp r3, #64
- bge Lnormalforwardcopy /* overlap is greater than one stride of the copy, use normal copy */
-
- cmp r3, #2
- bge Lbytewise2
- b Lbytewise
-
- /* the following routines deal with having to copy in the reverse direction */
-Loverlap_srclower:
- /* src < dest, with overlap */
-
- /* src += len; dest += len; */
- add r0, r0, r2
- add r1, r1, r2
-
- /* we have to copy in reverse no matter what, test if we can we use a large block reverse copy */
- cmp r2, #64 /* less than 64 bytes to copy? */
- cmpgt r3, #64 /* less than 64 bytes of nonoverlap? */
- blt Lbytewise_reverse
-
- /* test of src and dest are nonword aligned differently */
- mov r3, r0, lsl #30
- cmp r3, r1, lsl #30
- bne Lbytewise_reverse
-
- /* test if src and dest are non word aligned or dest is non 16 byte aligned */
- tst r0, #0xf
- bne Lunaligned_reverse_similarly
-
- /* test for dest 32 byte alignment */
- tst r0, #(1<<4)
- bne Lunaligned_32_reverse_similarly
-
- /* 64 byte reverse block copy, src and dest aligned */
-Lmorethan64_aligned_reverse:
- /* save some more registers to use in the copy */
- stmfd sp!, { r6, r8, r10, r11 }
-
- /* pre-subtract 64 from the len counter to avoid an extra compare in the loop */
- sub r2, r2, #64
-
-L64loop_reverse:
- /* copy 64 bytes at a time */
- ldmdb r1!, { r3, r4, r5, r6, r8, r10, r11, r12 }
-#ifdef _ARM_ARCH_6
- pld [r1, #-32]
-#endif
- stmdb r0!, { r3, r4, r5, r6, r8, r10, r11, r12 }
- ldmdb r1!, { r3, r4, r5, r6, r8, r10, r11, r12 }
- subs r2, r2, #64
-#ifdef _ARM_ARCH_6
- pld [r1, #-32]
-#endif
- stmdb r0!, { r3, r4, r5, r6, r8, r10, r11, r12 }
- bge L64loop_reverse
-
- /* restore the scratch registers we just saved */
- ldmfd sp!, { r6, r8, r10, r11 }
-
- /* fix up the len counter (previously subtracted an extra 64 from it) and test for completion */
- adds r2, r2, #64
- beq Lexit
-
-Lbytewise_reverse:
- ldrb r3, [r1, #-1]!
- strb r3, [r0, #-1]!
- subs r2, r2, #1
- bne Lbytewise_reverse
- b Lexit
-
-Lunaligned_reverse_similarly:
- /* both src and dest are unaligned in similar ways, align to dest on 32 byte boundary */
- mov r12, r0, lsl #28
- msr cpsr_f, r12
-
- ldrvsb r3, [r1, #-1]!
- ldrcsh r4, [r1, #-2]!
- ldreq r5, [r1, #-4]!
-
- strvsb r3, [r0, #-1]!
- strcsh r4, [r0, #-2]!
- streq r5, [r0, #-4]!
-
- ldmmidb r1!, { r3, r4 }
- stmmidb r0!, { r3, r4 }
-
- subs r2, r2, r12, lsr #28
- beq Lexit
-
-Lunaligned_32_reverse_similarly:
- /* bring up to dest 32 byte alignment */
- tst r0, #(1 << 4)
- ldmnedb r1!, { r3, r4, r5, r12 }
- stmnedb r0!, { r3, r4, r5, r12 }
- subne r2, r2, #16
-
- /* we should now be aligned, see what copy method we should use */
- cmp r2, #64
- bge Lmorethan64_aligned_reverse
- b Lbytewise_reverse
-
- /* the following routines deal with non word aligned copies */
-Lnonwordaligned_forward:
- cmp r2, #8
- blt Lbytewise2 /* not worth the effort with less than 24 bytes total */
-
- /* bytewise copy until src word aligned */
- tst r1, #3
-Lwordalignloop2:
- ldrneb r3, [r1], #1
- strneb r3, [r0], #1
- subne r2, r2, #1
- tstne r1, #3
- bne Lwordalignloop2
-
- /* figure out how the src and dest are unaligned */
- and r3, r0, #3
- cmp r3, #2
- blt Lalign1_forward
- beq Lalign2_forward
- bgt Lalign3_forward
-
-Lalign1_forward:
- /* the dest pointer is 1 byte off from src */
- mov r12, r2, lsr #2 /* number of words we should copy */
- sub r0, r0, #1
-
- /* prime the copy */
- ldrb r4, [r0] /* load D[7:0] */
-
-Lalign1_forward_loop:
- ldr r3, [r1], #4 /* load S */
- orr r4, r4, r3, lsl #8 /* D[31:8] = S[24:0] */
- str r4, [r0], #4 /* save D */
- mov r4, r3, lsr #24 /* D[7:0] = S[31:25] */
- subs r12, r12, #1
- bne Lalign1_forward_loop
-
- /* finish the copy off */
- strb r4, [r0], #1 /* save D[7:0] */
-
- ands r2, r2, #3
- beq Lexit
- b Lbytewise2
-
-Lalign2_forward:
- /* the dest pointer is 2 bytes off from src */
- mov r12, r2, lsr #2 /* number of words we should copy */
- sub r0, r0, #2
-
- /* prime the copy */
- ldrh r4, [r0] /* load D[15:0] */
-
-Lalign2_forward_loop:
- ldr r3, [r1], #4 /* load S */
- orr r4, r4, r3, lsl #16 /* D[31:16] = S[15:0] */
- str r4, [r0], #4 /* save D */
- mov r4, r3, lsr #16 /* D[15:0] = S[31:15] */
- subs r12, r12, #1
- bne Lalign2_forward_loop
-
- /* finish the copy off */
- strh r4, [r0], #2 /* save D[15:0] */
-
- ands r2, r2, #3
- beq Lexit
- b Lbytewise2
-
-Lalign3_forward:
- /* the dest pointer is 3 bytes off from src */
- mov r12, r2, lsr #2 /* number of words we should copy */
- sub r0, r0, #3
-
- /* prime the copy */
- ldr r4, [r0]
- and r4, r4, #0x00ffffff /* load D[24:0] */
-
-Lalign3_forward_loop:
- ldr r3, [r1], #4 /* load S */
- orr r4, r4, r3, lsl #24 /* D[31:25] = S[7:0] */
- str r4, [r0], #4 /* save D */
- mov r4, r3, lsr #8 /* D[24:0] = S[31:8] */
- subs r12, r12, #1
- bne Lalign3_forward_loop
-
- /* finish the copy off */
- strh r4, [r0], #2 /* save D[15:0] */
- mov r4, r4, lsr #16
- strb r4, [r0], #1 /* save D[23:16] */
-
- ands r2, r2, #3
- beq Lexit
- b Lbytewise2
-
-Lexit:
- ldmfd sp!, {r0, r4, r5, r7, pc}
-
-#endif // defined __thumb2__ && defined __ARM_NEON__
-
+++ /dev/null
-/*
- * Copyright (c) 2006, 2009 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@
- */
-
-#if defined __thumb2__ && defined __ARM_NEON__
-
-// Use our tuned NEON implementation when it is available. Otherwise fall back
-// on more generic ARM code.
-
-#include "NEON/bzero.s"
-
-#else // defined __thumb2__ && defined __ARM_NEON__
-
-#include <mach/machine/asm.h>
-#include <architecture/arm/asm_help.h>
-
-/*
- * A reasonably well-optimized bzero/memset. Should work equally well on arm11 and arm9 based
- * cores.
- *
- * The algorithm is to align the destination pointer on a 32 byte boundary and then
- * blast data 64 bytes at a time, in two stores of 32 bytes per loop.
- */
- .text
- .align 2
-
- .globl _memset
-/* void *memset(void *ptr, int c, size_t len); */
-_memset:
- /* move len into r1, unpack c into r2 */
- mov r3, r2
- and r1, r1, #0xff
- orr r1, r1, r1, lsl #8
- orr r2, r1, r1, lsl #16
- mov r1, r3
- b Lbzeroengine
-
- .globl _bzero
-/* void bzero(void *ptr, size_t len); */
-_bzero:
- /* zero out r2 so we can be just like memset(0) */
- mov r2, #0
-
-Lbzeroengine:
- /* move the base pointer into r12 and leave r0 alone so that we return the original pointer */
- mov r12, r0
-
- /* copy r2 into r3 for 64-bit stores */
- mov r3, r2
-
- /* check for zero len */
- cmp r1, #0
- bxeq lr
-
- /* fall back to a bytewise store for less than 32 bytes */
- cmp r1, #32
- blt L_bytewise
-
- /* check for 32 byte unaligned ptr */
- tst r12, #0x1f
- bne L_unaligned
-
- /* make sure we have more than 64 bytes to zero */
- cmp r1, #64
- blt L_lessthan64aligned
-
- /* >= 64 bytes of len, 32 byte aligned */
-L_64ormorealigned:
-
- /* we need some registers, avoid r7 (frame pointer) and r9 (thread register) */
- stmfd sp!, { r4-r6, r8, r10-r11 }
- mov r4, r2
- mov r5, r2
- mov r6, r2
- mov r8, r2
- mov r10, r2
- mov r11, r2
-
- /* pre-subtract 64 from the len to avoid an extra compare in the loop */
- sub r1, r1, #64
-
-L_64loop:
- stmia r12!, { r2-r6, r8, r10-r11 }
- subs r1, r1, #64
- stmia r12!, { r2-r6, r8, r10-r11 }
- bge L_64loop
-
- /* restore the saved regs */
- ldmfd sp!, { r4-r6, r8, r10-r11 }
-
- /* check for completion (had previously subtracted an extra 64 from len) */
- adds r1, r1, #64
- bxeq lr
-
-L_lessthan64aligned:
- /* do we have 16 or more bytes left */
- cmp r1, #16
- stmgeia r12!, { r2-r3 }
- stmgeia r12!, { r2-r3 }
- subges r1, r1, #16
- bgt L_lessthan64aligned
- bxeq lr
-
-L_lessthan16aligned:
- /* store 0 to 15 bytes */
- mov r1, r1, lsl #28 /* move the remaining len bits [3:0] to the flags area of cpsr */
- msr cpsr_f, r1
-
- stmmiia r12!, { r2-r3 } /* n is set, store 8 bytes */
- streq r2, [r12], #4 /* z is set, store 4 bytes */
- strcsh r2, [r12], #2 /* c is set, store 2 bytes */
- strvsb r2, [r12], #1 /* v is set, store 1 byte */
- bx lr
-
-L_bytewise:
- /* bytewise copy, 2 bytes at a time, alignment not guaranteed */
- subs r1, r1, #2
- strb r2, [r12], #1
- strplb r2, [r12], #1
- bhi L_bytewise
- bx lr
-
-L_unaligned:
- /* unaligned on 32 byte boundary, store 1-15 bytes until we're 16 byte aligned */
- mov r3, r12, lsl #28
- rsb r3, r3, #0x00000000
- msr cpsr_f, r3
-
- strvsb r2, [r12], #1 /* v is set, unaligned in the 1s column */
- strcsh r2, [r12], #2 /* c is set, unaligned in the 2s column */
- streq r2, [r12], #4 /* z is set, unaligned in the 4s column */
- strmi r2, [r12], #4 /* n is set, unaligned in the 8s column */
- strmi r2, [r12], #4
-
- subs r1, r1, r3, lsr #28
- bxeq lr
-
- /* we had previously trashed r3, restore it */
- mov r3, r2
-
- /* now make sure we're 32 byte aligned */
- tst r12, #(1 << 4)
- stmneia r12!, { r2-r3 }
- stmneia r12!, { r2-r3 }
- subnes r1, r1, #16
-
- /* we're now aligned, check for >= 64 bytes left */
- cmp r1, #64
- bge L_64ormorealigned
- b L_lessthan64aligned
-
-X_LEAF(___bzero, _bzero)
-
-#endif // defined __thumb2__ && defined __ARM_NEON__
--- /dev/null
+// This file implements resolvers to assist dyld in choosing the correct
+// implementation of <string.h> routines on ARMv7 processors. The
+// micro-architectural differences between Cortex-A8 and Cortex-A9 are such
+// that optimal write loops are quite different on the two processors.
+//
+// The MakeResolver_a8_a9(name) macro creates a function that dyld calls to
+// pick an implementation of the name function. It does a check to determine
+// if it is running on a8 or a9 hardware, and returns a pointer to either
+//
+// name$VARIANT$CortexA8
+// or
+// name$VARIANT$CortexA9
+//
+// This resolution only occurs once per process; once a symbol is bound to an
+// implementation in dyld, no further calls to the resolver occur.
+//
+// On unknown implementations of the ARMv7 architecture, the Cortex-A9 variant
+// is returned by these resolvers.
+
+#include <arm/arch.h>
+#if defined _ARM_ARCH_7 && !defined VARIANT_DYLD
+
+#include <stdlib.h>
+#include <machine/cpu_capabilities.h>
+#include <mach/machine.h>
+
+#define MakeResolver_a8_a9(name) \
+ void * name ## Resolver(void) __asm__("_" #name);\
+ void * name ## Resolver(void) {\
+ __asm__(".symbol_resolver _" #name);\
+ if (*(int *)_COMM_PAGE_CPUFAMILY == CPUFAMILY_ARM_13)\
+ return name ## $VARIANT$CortexA8;\
+ else\
+ return name ## $VARIANT$CortexA9;\
+ }
+
+void bcopy$VARIANT$CortexA8(const void *, void *, size_t);
+void bcopy$VARIANT$CortexA9(const void *, void *, size_t);
+MakeResolver_a8_a9(bcopy)
+
+void *memmove$VARIANT$CortexA8(void *, const void *, size_t);
+void *memmove$VARIANT$CortexA9(void *, const void *, size_t);
+MakeResolver_a8_a9(memmove)
+
+void *memcpy$VARIANT$CortexA8(void *, const void *, size_t);
+void *memcpy$VARIANT$CortexA9(void *, const void *, size_t);
+MakeResolver_a8_a9(memcpy)
+
+void bzero$VARIANT$CortexA8(void *, size_t);
+void bzero$VARIANT$CortexA9(void *, size_t);
+MakeResolver_a8_a9(bzero)
+
+void __bzero$VARIANT$CortexA8(void *, size_t);
+void __bzero$VARIANT$CortexA9(void *, size_t);
+MakeResolver_a8_a9(__bzero)
+
+void *memset$VARIANT$CortexA8(void *, int, size_t);
+void *memset$VARIANT$CortexA9(void *, int, size_t);
+MakeResolver_a8_a9(memset)
+
+#else // defined _ARM_ARCH_7 && !defined VARIANT_DYLD
+
+typedef int emptyFilesArentCFiles;
+
+#endif // defined _ARM_ARCH_7 && !defined VARIANT_DYLD
-/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <arm/arch.h>
-
-#ifdef _ARM_ARCH_5
- .text
-
- .align 2
- .globl _ffs
-_ffs:
- .globl _ffsl
-_ffsl:
- rsb r3, r0, #0
- and r0, r0, r3
- clz r0, r0
- rsb r0, r0, #32
- bx lr
-
- .align 2
- .globl _fls
-_fls:
- .globl _flsl
-_flsl:
- clz r0, r0
- rsb r0, r0, #32
- bx lr
-#else
-#error need to define ffs for this architecture
-#endif
-/*
- * Copyright (c) 2009 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@
- */
-
-// ARM Assembly implementation of memcmp( ) from <string.h>
-// Uses Thumb2 if it is available, otherwise generates ARM code.
-//
-// -- Stephen Canon, August 2009
-//
-// The basic idea is to use word compares instead of byte compares as long as
-// at least four bytes remain to be compared. However, because memcmp( )
-// compares the buffers as though they were big-endian unsigned integers, we
-// need to byte-reverse each word before comparing them.
-//
-// If the buffers are not word aligned, or they are shorter than four bytes,
-// we just use a simple byte comparison loop instead.
-//
-// int bcmp(void *src1, void *src2, size_t length);
-// int memcmp(void *src1, void *src2, size_t length);
-
-#include <arm/arch.h>
-
- .text
- .syntax unified
-#if defined __thumb2__
- .code 16
- .thumb_func _bcmp
- .thumb_func _memcmp
-#else
- .code 32
-#endif
- .globl _bcmp
- .globl _memcmp
- .align 3
-_bcmp:
-_memcmp:
-
-#ifdef _ARM_ARCH_6
- subs ip, r2, #4 // if length < 4
- bmi L_useByteCompares // jump to the byte comparison loop
-
- orr r3, r0, r1 // if the buffers are
- tst r3, #3 // not word aligned
- bne L_useByteCompares // jump to the byte comparison loop
-
-.align 3
-L_wordCompare: // Here we know that both buffers are word
- ldr r2, [r0], #4 // aligned, and (length - 4) > 0, so at least
- ldr r3, [r1], #4 // four bytes remain to be compared. We load
- subs ip, #4 // a word from each buffer, and byte reverse
- bmi L_lastWord // the loaded words. We also decrement the
- rev r2, r2 // length by four and jump out of this loop if
- rev r3, r3 // the result is negative. Then we compare the
- cmp r2, r3 // reversed words, and continue the loop only
- beq L_wordCompare // if they are equal.
-L_wordsUnequal:
- ite hi // If the words compared unequal, return +/- 1
- movhi r0, #1 // according to the result of the comparison.
- movls r0, #-1 //
- bx lr //
-L_lastWord:
- rev r2, r2 // If we just loaded the last complete words
- rev r3, r3 // from the buffers, byte-reverse them and
- cmp r2, r3 // compare. If they are unequal, jump to the
- bne L_wordsUnequal // return path.
- add r2, ip, #4 // Otherwise, fall into the cleanup code.
-#endif // _ARM_ARCH_6
-
-L_useByteCompares:
- tst r2, r2 // If the length is exactly zero
- beq L_returnZero // avoid doing any loads and return zero.
- mov r3, r0
-.align 3
-L_byteCompareLoop:
- ldrb r0, [r3], #1 // Load a byte from each buffer, and decrement
- ldrb ip, [r1], #1 // the length by one. If the decremented
- subs r2, #1 // length is zero, exit the loop. Otherwise
- beq L_lastByte // subtract the loaded bytes; if their
- subs r0, ip // difference is zero, continue the comparison
- beq L_byteCompareLoop // loop. Otherwise, return their difference.
- bx lr
-L_returnZero:
- mov r0, ip
-L_lastByte:
- sub r0, ip // Return the difference of the final bytes
- bx lr
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <arm/arch.h>
-#include <mach/machine/asm.h>
-
-/*
- * This file contains the following functions:
- *
- * void memset_pattern4(void *b, const void *c4, size_t len)
- * void memset_pattern8(void *b, const void *c8, size_t len)
- * void memset_pattern16(void *b, const void *c16, size_t len)
- *
- * The memset() is implemented in the bzero.s file.
- *
- * This is a reasonably well optimized version of memset_pattern* routines
- * implemented for ARM processors using the ARMv4 and later instruction sets.
- * These routines use the ARM's core registers.
- *
- * The algorithm is to align the destination pointer on a 16 byte boundary
- * and then blast data 64 bytes at a time, in two stores of 32 bytes per loop.
- *
- */
- .text
- .align 2
- .syntax unified
-
-/*----------------------------------------------------------------------------*/
-/* void memset_pattern4(void *ptr, const void *pattern4, size_t len); */
-/* */
-/* r0 << destination pointer */
-/* r1 << pointer to 4-byte pattern */
-/* r2 << 'len' (length of destination buffer in bytes) */
-/*----------------------------------------------------------------------------*/
- .globl _memset_pattern4
-_memset_pattern4:
- cmp r2, #0 /* check if len is zero */
- bxeq lr /* return if length is zero */
-
- /* We need some registers, so save volatiles on stack */
- /* Avoid r7 (frame pointer) and r9 (thread register) */
- stmfd sp!, {r4-r7, lr}
- add r7, sp, #12 /* establish frame */
- stmfd sp!, {r8, r10-r11}
-
- /* copy destination base pointer r0 to r12 and leave r0 alone */
- /* so that we return original pointer back to the caller */
- mov r12, r0
-
- /* Check if 'len' is long enough to bother alignment of destination */
- /* pointer */
- cmp r2, #32 /* long enough to bother aligning? */
- movlt r3, #4 /* move pattern length into r3 */
- movlt r10, #4 /* pattern index */
- movlt r11, r1 /* move pattern pointer into r11 */
- blt L_Short /* no */
-
- /* move 'len' into r1, get 4-byte pattern in r2 */
- mov r6, r2 /* temporarily move 'len' in to r6 */
- bl L_GetPatternWord /* get unaligned pattern word in r5 */
- mov r2, r5 /* move pattern word into r2 */
- mov r0, r12 /* r0 was clobbered - restore it */
- mov r1, r6 /* move 'len' from r6 to r1 */
-
- mov r3, r2 /* copy 4-byte pattern into r3, r4 and r5 registers */
- mov r4, r2
- mov r5, r2
-
-L_NotShort:
-
- /* Check for 16 or 32 byte aligned destination pointer */
- tst r12, #0x1F /* check for 32 byte aligned */
- beq L_Aligned
- tst r12, #0xF /* check for 16 byte aligned */
- beq L_16ByteAligned
- b L_Unaligned /* yes */
-
-L_Bytewise:
- ldrb r4, [r11], #1
- strb r4, [r12], #1
- subs r10, #1
- moveq r10, r3
- moveq r11, r1
- sub r2, #1
-
-L_Short:
- cmp r2, #0 /* more bytes left? */
- bne L_Bytewise
- ldm sp!, {r8, r10-r11} /* restores registers from stack */
- ldm sp!, {r4-r7, lr} /* restore & return from subroutine */
- bx lr
-
-/* 'len' is long enough to justify aligning the destination pointer */
-/* */
-/* By the time we reach here, data is stored in registers as follows: */
-/* r1 << 'len' (length of destination buffer in bytes) */
-/* r2-r5 << pattern; either 4x4byte OR 2x8byte OR 1x16-byte */
-/* r12 << destination pointer copy (scratch register) */
-/* r0 << destination pointer original */
-/* */
-/* Use r11 as scratch register to store the #bytes offset to 16-byte align */
-/* */
-/* Unaligned on 32-byte boundary, store 1-15 bytes until 16-byte aligned */
-/* As we store these bytes, we rotate the pattern stored in r2-r5 to reflect */
-/* the alignment. */
-
-L_Unaligned:
- mov r11, r12, lsl #28
- rsb r11, r11, #0
- msr cpsr_f, r11 /* Bits[31:28] of cpsr now contain #bytes to align*/
-
-L_Store15BytesAndRotatePattern:
- strbvs r2, [r12], #1 /* v is set, unaligned in the 1s column */
- andvs r6, r2, #0xFF /* Rotate pattern right in r2-r5 by 1-byte */
- andvs r8, r3, #0xFF /* Consider register r2-r5 and a contiguous */
- andvs r10, r4, #0xFF /* 16-byte register with r2 containing LSB */
- andvs r11, r5, #0xFF /* and r5 containing MSB */
- lsrvs r2, r2, #8
- lsrvs r3, r3, #8
- lsrvs r4, r4, #8
- lsrvs r5, r5, #8
- orrvs r2, r2, r8, lsl #24
- orrvs r3, r3, r10, lsl #24
- orrvs r4, r4, r11, lsl #24
- orrvs r5, r5, r6, lsl #24
-
- strhcs r2, [r12], #2 /* c is set, unaligned in the 2s column */
- movcs r6, r2, lsl #16 /* Rotate pattern right in r2-r5 by 2-bytes */
- movcs r8, r3, lsl #16
- movcs r10, r4, lsl #16
- movcs r11, r5, lsl #16
- lsrcs r2, r2, #16
- lsrcs r3, r3, #16
- lsrcs r4, r4, #16
- lsrcs r5, r5, #16
- orrcs r2, r2, r8
- orrcs r3, r3, r10
- orrcs r4, r4, r11
- orrcs r5, r5, r6
-
- streq r2, [r12], #4 /* z is set, unaligned in the 4s column */
- moveq r6, r2 /* Rotate pattern right in r2-r5 by 4-bytes */
- moveq r2, r3
- moveq r3, r4
- moveq r4, r5
- moveq r5, r6
-
- stmmi r12!, {r2-r3} /* n is set, unaligned in the 8s column */
- movmi r6, r2 /* Rotate pattern right in r2-r5 by 4-bytes */
- movmi r8, r3
- movmi r2, r4
- movmi r3, r5
- movmi r4, r6
- movmi r5, r8
-
- mrs r11, cpsr /*copy cpsr in to r11 */
- subs r1, r1, r11, lsr #28
- ldmeq sp!, {r8, r10-r11} /* restores registers from stack */
- ldmeq sp!, {r4-r7, lr} /* restore & return from subroutine */
- bxeq lr
-
-/* By the time we reach here, we are 16-byte aligned and r2-r5 contains */
-/* rotated pattern. Now lets make sure we are 32-byte aligned. */
-L_16ByteAligned:
- tst r12, #(1 << 4)
- stmne r12!, {r2-r5}
- subsne r1, r1, #16
-
-/* By the time we reach here, data is stored in registers as follows: */
-/* r1 << 'len' (remaining length of destination buffer in bytes) */
-/* r2-r5 << rotated pattern; either 4x4byte OR 2x8byte OR 1x16-byte */
-/* r12 << aligned destination pointer copy (scratch register) */
-L_Aligned:
- cmp r1, #64
- blt L_AlignedLessThan64
-
-/* Copy pattern in four more registers so that we can do 64 byte transfers */
- mov r6, r2
- mov r8, r3
- mov r10, r4
- mov r11, r5
-
-/* At this point, we are 16-byte aligned and 'len' is greater than 64 bytes */
-/* Lets transfer 64 bytes at a time until len becomes less than 64 bytes */
- sub r1, r1, #64 /* pre-subtract to avoid extra compare in loop */
-L_Loop64:
- stm r12!, {r2-r6, r8, r10-r11}
- subs r1, r1, #64
- stm r12!, {r2-r6, r8, r10-r11}
- bge L_Loop64
-
- /* return if 'len' is zero */
- adds r1, r1, #64 /* readjust length; previously subtracted extra 64*/
- ldmeq sp!, {r8, r10-r11} /* restores registers from stack */
- ldmeq sp!, {r4-r7, lr} /* restore & return from subroutine */
- bxeq lr
-
-L_AlignedLessThan64:
- /* do we have 16 or more bytes left */
- cmp r1, #16
- stmge r12!, {r2-r5}
- subsge r1, r1, #16
- bgt L_AlignedLessThan64
- ldmeq sp!, {r8, r10-r11} /* restores registers from stack */
- ldmeq sp!, {r4-r7, lr} /* restore & return from subroutine */
- bxeq lr
-
-L_AlignedLessThan16:
- /* store last up-to 15 bytes */
- /* move the remaining len bits [3:0] to the flags area of cpsr */
- mov r1, r1, lsl #28
- msr cpsr_f, r1
-
- stmmi r12!, {r2-r3} /* n is set, store 8 bytes */
- movmi r2, r4 /* shift vector down 8 bytes */
- movmi r3, r5
-
- streq r2, [r12], #4 /* z is set, store 4 bytes */
- moveq r2, r3 /* shift vector down 4 bytes */
-
- strhcs r2, [r12], #2 /* c is set, store 2 bytes */
- lsrcs r2, #16 /* shift register right 2 bytes */
-
- strbvs r2, [r12], #1 /* v is set, store 1 byte */
- ldm sp!, {r8, r10-r11} /* restores registers from stack */
- ldm sp!, {r4-r7, lr} /* restore & return from subroutine */
- bx lr
-
-/*----------------------------------------------------------------------------*/
-/* void memset_pattern8(void *ptr, const void *pattern8, size_t len); */
-/* */
-/* r0 << destination pointer */
-/* r1 << pointer to 8-byte pattern */
-/* r2 << 'len' (length of destination buffer in bytes) */
-/*----------------------------------------------------------------------------*/
- .globl _memset_pattern8
-_memset_pattern8:
- cmp r2, #0 /* check if len is zero */
- bxeq lr /* return if length is zero */
-
- /* We need some registers, so save volatiles on stack */
- /* Avoid r7 (frame pointer) and r9 (thread register) */
- stmfd sp!, {r4-r7, lr}
- add r7, sp, #12 /* establish frame */
- stmfd sp!, {r8, r10-r11}
-
- /* copy destination base pointer r0 to r12 and leave r0 alone */
- /* so that we return original pointer back to the caller */
- mov r12, r0
-
- /* Check if 'len' is long enough to bother alignment of destination */
- /* pointer */
- cmp r2, #32 /* long enough to bother aligning? */
- movlt r3, #8 /* move pattern length into r3 */
- movlt r10, #8 /* pattern index */
- movlt r11, r1 /* move pattern pointer into r11 */
- blt L_Short /* no */
-
- /* move 'len' into r1, get 8-byte pattern in r2-r3 */
- mov r6, r2 /* temporarily move 'len' in to r6 */
- bl L_GetPatternWord /* get unaligned pattern word in r5 */
- mov r2, r5 /* move pattern word into r2 */
- bl L_GetPatternWord
- mov r3, r5
- mov r0, r12 /* r0 was clobbered - restore it */
- mov r1, r6 /* move 'len' from r6 to r1 */
-
- mov r4, r2 /* copy 8-byte pattern into r4-r5 registers */
- mov r5, r3
- b L_NotShort /* yes */
-
-
-/*----------------------------------------------------------------------------*/
-/* void memset_pattern16(void *ptr, const void *pattern16, size_t len); */
-/* */
-/* r0 << destination pointer */
-/* r1 << pointer to 16-byte pattern */
-/* r2 << 'len' (length of destination buffer in bytes) */
-/*----------------------------------------------------------------------------*/
- .globl _memset_pattern16
-_memset_pattern16:
- cmp r2, #0 /* check if len is zero */
- bxeq lr /* return if length is zero */
-
- /* We need some registers, so save volatiles on stack */
- /* Avoid r7 (frame pointer) and r9 (thread register) */
- stmfd sp!, {r4-r7, lr}
- add r7, sp, #12 /* establish frame */
- stmfd sp!, {r8, r10-r11}
-
- /* copy destination base pointer r0 to r12 and leave r0 alone */
- /* so that we return original pointer back to the caller */
- mov r12, r0
-
- /* Check if 'len' is long enough to bother alignment of destination */
- /* pointer */
- cmp r2, #32 /* long enough to bother aligning? */
- movlt r3, #16 /* move pattern length into r3 */
- movlt r10, #16 /* pattern index */
- movlt r11, r1 /* move pattern pointer into r11 */
- blt L_Short /* no */
-
- /* move 'len' into r1, get 16-byte pattern in r2-r5 */
- mov r6, r2 /* temporarily move 'len' in to r6 */
- bl L_GetPatternWord /* get unaligned pattern word in r5 */
- mov r2, r5 /* move pattern word into r2 */
- bl L_GetPatternWord
- mov r3, r5
- bl L_GetPatternWord
- mov r4, r5
- bl L_GetPatternWord
- mov r0, r12 /* r0 was clobbered - restore it */
- mov r1, r6 /* move 'len' from r6 to r1 */
-
- b L_NotShort /* yes */
-
-
-/*----------------------------------------------------------------------------*/
-/* Get an unaligned word at r1, returning it in r5. */
-/* Increments r1 by 4, clobbers r0. */
-/* This is tailored to fit the register usage by the call sites. */
-/*----------------------------------------------------------------------------*/
-L_GetPatternWord:
- ldrb r5, [r1], #1 /* get the 1st byte at r1 */
- ldrb r0, [r1], #1 /* get the 2nd byte at r1 */
- orr r5, r5, r0, lsl #8 /* move into bits 15:8 */
- ldrb r0, [r1], #1 /* get the 3rd byte */
- orr r5, r5, r0, lsl #16 /* bits 23:16 */
- ldrb r0, [r1], #1 /* get the 4th byte */
- orr r5, r5, r0, lsl #24 /* bits 31:24 */
- bx lr
-/* $NetBSD: strcmp.S,v 1.3 2003/04/05 23:08:52 bjh21 Exp $ */
-/* $FreeBSD: src/lib/libc/arm/string/strcmp.S,v 1.2 2004/11/09 16:49:14 cognet Exp $ */
-
-/*
- * Copyright (c) 2002 ARM Ltd
- * 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. The name of the company may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
- */
-
- .text
- .align 2
- .globl _strcmp
-
-_strcmp:
-1:
- ldrb r2, [r0], #1
- ldrb r3, [r1], #1
- cmp r2, #1
- cmpcs r2, r3
- beq 1b
- sub r0, r2, r3
- bx lr
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-.text
- .align 2
-
- .globl _strlen
-/* size_t strlen(const char *s); */
-_strlen:
- /* save the original pointer */
- mov r12, r0
-
- /* see if the string is aligned */
- ands r3, r0, #3
-
- /* load the first word, address rounded down */
- bic r0, r0, #3
- ldr r2, [r0], #4
-
- /* skip the next part if the string is already aligned */
- beq Laligned
-
-Lunaligned:
- /* unaligned pointer, mask out the bytes that we've read that we should be ignoring */
- cmp r3, #2
- orr r2, r2, #0x000000ff
- orrge r2, r2, #0x0000ff00
- orrgt r2, r2, #0x00ff0000
-
-Laligned:
- /* load 0x01010101 into r1 */
- mov r1, #0x01
- orr r1, r1, r1, lsl #8
- orr r1, r1, r1, lsl #16
-
-Laligned_loop:
- /* ((x - 0x01010101) & ~x & 0x80808080) == hasnull(word) */
- sub r3, r2, r1 /* x - 0x01010101 */
- bic r3, r3, r2 /* above & ~x */
- tst r3, r1, lsl #7 /* above & 0x80808080 */
- ldreq r2, [r0], #4 /* load next word */
- beq Laligned_loop
-
- /* we found a nullbyte */
- /* r0 (ptr) has overshot by up to 4 bytes, so subtract off until we find a nullbyte */
- sub r0, r0, #1
- tst r2, #0x000000ff
- subeq r0, r0, #1
- tstne r2, #0x0000ff00
- subeq r0, r0, #1
- tstne r2, #0x00ff0000
- subeq r0, r0, #1
-
-Lexit:
- /* len = ptr - original pointer */
- sub r0, r0, r12
- bx lr
-
MDSRCS+= \
OSAtomic.s \
+ OSAtomic_resolvers.c \
gcc_atomic.c \
_longjmp.s \
_setjmp.s \
arm_commpage_gettimeofday.c \
longjmp.s \
- setjmp.s
+ setjmp.s \
+ mach_absolute_time.s
+
+DYLDSRCS += OSAtomic.s arm_commpage_gettimeofday.c mach_absolute_time.s
.if !defined(FEATURE_ARM_ARCH_6)
MDSRCS+= OSAtomic-v4.c
+DYLDSRCS+= OSAtomic-v4.c
.endif
-
-MDCOPYFILES+= ${.CURDIR}/Platforms/${RC_TARGET_CONFIG}/arm/libc.syscall.arm
return result;
}
+void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset )
+{
+ OSSpinLockLock(&_atomic_lock);
+ *((void **)((char *)__new + __offset)) = __list->opaque1;
+ __list->opaque1 = __new;
+ OSSpinLockUnlock(&_atomic_lock);
+}
+
+void* OSAtomicDequeue( OSQueueHead *__list, size_t __offset )
+{
+ void *head;
+
+ OSSpinLockLock(&_atomic_lock);
+ head = __list->opaque1;
+ if (head != NULL) {
+ void **next = (void **)((char *)head + __offset);
+ __list->opaque1 = *next;
+ }
+ OSSpinLockUnlock(&_atomic_lock);
+
+ return head;
+}
+
#endif /* !defined(_ARM_ARCH_6) */
.text
+/* Number of times we spin in a spinlock before going to kernel */
+#define MP_SPIN_TRIES 1000
+#define MP_SPIN_TRIES_WFE 10
+
+#if defined(VARIANT_DYLD)
+ #if defined(_ARM_ARCH_7)
+ /* This makes sure we pick up MP variants for dyld on armv7 */
+ #define ENTRY_POINT_RESOLVER(symbol, variant) \
+ ENTRY_POINT(symbol##$VARIANT$##variant) ;\
+ .private_extern symbol##$VARIANT$##variant
+
+ #define ENTRY_POINT_DEFAULT(symbol, variant) \
+ ENTRY_POINT(symbol##$VARIANT$##variant) ;\
+ .private_extern symbol##$VARIANT$##variant
+
+ #define makeResolver_up_mp(name) \
+ ENTRY_POINT(_##name) \
+ ldr ip, L##name##$commpage ; \
+ ldr ip, [ip] ; \
+ tst ip, $(kUP) ; \
+ beq _##name##$VARIANT$mp ; \
+ b _##name##$VARIANT$up ; \
+ L##name##$commpage: .long _COMM_PAGE_CPU_CAPABILITIES ;
+
+ #define makeResolver_up_mp_wfe(name) \
+ makeResolver_up_mp(name)
+ #else
+ #define ENTRY_POINT_RESOLVER(symbol, variant) \
+ ENTRY_POINT(symbol##$VARIANT$##variant) ;\
+ .private_extern symbol##$VARIANT$##variant
+
+ #define ENTRY_POINT_DEFAULT(symbol, variant) ENTRY_POINT(symbol)
+ #endif
+#else
+ #if defined(_ARM_ARCH_7)
+ #define ENTRY_POINT_RESOLVER(symbol, variant) \
+ ENTRY_POINT(symbol##$VARIANT$##variant) ;\
+ .private_extern symbol##$VARIANT$##variant
+ #define ENTRY_POINT_DEFAULT(symbol, variant) \
+ ENTRY_POINT(symbol##$VARIANT$##variant) ;\
+ .private_extern symbol##$VARIANT$##variant
+ #else // !_ARM_ARCH_7
+ /* _RESOLVER shouldn't be used on armv5/6, so intentionally plants bad text. */
+ #define ENTRY_POINT_RESOLVER(symbol, variant) .error
+ #define ENTRY_POINT_DEFAULT(symbol, variant) ENTRY_POINT(symbol)
+ #endif
+#endif // VARIANT_DYLD
+
+#if defined(VARIANT_DYLD) && defined(_ARM_ARCH_7)
/*
- * Use LDREX/STREX to perform atomic operations.
- * Memory barriers are not needed on a UP system
+ * In dyld's build only, we include the list of resolvers needed and
+ * this generates entry points for dyld which are run on every execution
+ * in order to pick the correct variant.
*/
+#include "OSAtomic_resolvers.h"
+#endif
#if defined(_ARM_ARCH_6)
/* Implement a generic atomic arithmetic operation:
* operand is in R0, pointer is in R1. Return new
- * value into R0
+ * value into R0 (or old valule in _ORIG cases).
+ *
+ * Return instructions are separate to the
+ * _ATOMIC_ARITHMETIC macro.
*/
-#define ATOMIC_ARITHMETIC(op) \
-1: ldrex r2, [r1] /* load existing value and tag memory */ ;\
+#define _ATOMIC_ARITHMETIC(op) \
+ ldrex r2, [r1] /* load existing value and tag memory */ ;\
op r3, r2, r0 /* compute new value */ ;\
strex ip, r3, [r1] /* store new value if memory is still tagged */ ;\
cmp ip, #0 /* check if the store succeeded */ ;\
- bne 1b /* if not, try again */ ;\
+ bne 1b /* if not, try again */
+
+#if defined(_ARM_ARCH_7)
+/*
+ * ARMv7 barrier operations:
+ * - Full Barrier (FB); store barrier before store exclusive, full barrier after op.
+ */
+
+#define ATOMIC_ARITHMETIC_FB(op) \
+ dmb ishst /* store barrier before store exclusive */ ;\
+1: _ATOMIC_ARITHMETIC(op) ;\
+ dmb ish /* issue data memory barrier */ ;\
+ mov r0, r3 /* return new value */
+
+#define ATOMIC_ARITHMETIC_ORIG_FB(op) \
+ dmb ishst /* store barrier before store exclusive */ ;\
+1: _ATOMIC_ARITHMETIC(op) ;\
+ dmb ish /* issue data memory barrier */ ;\
+ mov r0, r2 /* return orig value */
+
+#endif
+
+/*
+ * For the non-MP ARMv7 cases, and ARMv5/6, these provide atomic arithmetic
+ * without any barriers at all.
+ */
+#define ATOMIC_ARITHMETIC(op) \
+1: _ATOMIC_ARITHMETIC(op) ;\
mov r0, r3 /* return new value */
#define ATOMIC_ARITHMETIC_ORIG(op) \
-1: ldrex r2, [r1] /* load existing value and tag memory */ ;\
- op r3, r2, r0 /* compute new value */ ;\
- strex ip, r3, [r1] /* store new value if memory is still tagged */ ;\
- cmp ip, #0 /* check if the store succeeded */ ;\
- bne 1b /* if not, try again */ ;\
+ 1: _ATOMIC_ARITHMETIC(op) ;\
mov r0, r2 /* return orig value */
-ENTRY_POINT(_OSAtomicAdd32Barrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicAdd32Barrier, mp)
+ ATOMIC_ARITHMETIC_FB(add)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicAdd32Barrier, up)
ENTRY_POINT(_OSAtomicAdd32)
ATOMIC_ARITHMETIC(add)
bx lr
-ENTRY_POINT(_OSAtomicOr32Barrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicOr32Barrier, mp)
+ ATOMIC_ARITHMETIC_FB(orr)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicOr32Barrier, up)
ENTRY_POINT(_OSAtomicOr32)
ATOMIC_ARITHMETIC(orr)
bx lr
-ENTRY_POINT(_OSAtomicOr32OrigBarrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicOr32OrigBarrier, mp)
+ ATOMIC_ARITHMETIC_ORIG_FB(orr)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicOr32OrigBarrier, up)
ENTRY_POINT(_OSAtomicOr32Orig)
ATOMIC_ARITHMETIC_ORIG(orr)
bx lr
-ENTRY_POINT(_OSAtomicAnd32Barrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicAnd32Barrier, mp)
+ ATOMIC_ARITHMETIC_FB(and)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicAnd32Barrier, up)
ENTRY_POINT(_OSAtomicAnd32)
ATOMIC_ARITHMETIC(and)
bx lr
-ENTRY_POINT(_OSAtomicAnd32OrigBarrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicAnd32OrigBarrier, mp)
+ ATOMIC_ARITHMETIC_ORIG_FB(and)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicAnd32OrigBarrier, up)
ENTRY_POINT(_OSAtomicAnd32Orig)
ATOMIC_ARITHMETIC_ORIG(and)
bx lr
-ENTRY_POINT(_OSAtomicXor32Barrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicXor32Barrier, mp)
+ ATOMIC_ARITHMETIC_FB(eor)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicXor32Barrier, up)
ENTRY_POINT(_OSAtomicXor32)
ATOMIC_ARITHMETIC(eor)
bx lr
-ENTRY_POINT(_OSAtomicXor32OrigBarrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicXor32OrigBarrier, mp)
+ ATOMIC_ARITHMETIC_ORIG_FB(eor)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicXor32OrigBarrier, up)
ENTRY_POINT(_OSAtomicXor32Orig)
ATOMIC_ARITHMETIC_ORIG(eor)
bx lr
-ENTRY_POINT(_OSAtomicCompareAndSwap32Barrier)
+
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicCompareAndSwap32Barrier, mp)
+ENTRY_POINT_RESOLVER(_OSAtomicCompareAndSwapIntBarrier, mp)
+ENTRY_POINT_RESOLVER(_OSAtomicCompareAndSwapLongBarrier, mp)
+ENTRY_POINT_RESOLVER(_OSAtomicCompareAndSwapPtrBarrier, mp)
+ ldrex r3, [r2] // load existing value and tag memory
+ teq r3, r0 // is it the same as oldValue?
+ movne r0, #0 // if not, return 0 immediately
+ bxne lr
+ dmb ishst // store barrier before store exclusive
+ strex r3, r1, [r2] // otherwise, try to store new value
+ cmp r3, #0 // check if the store succeeded
+ bne 2f // if not, try again
+1: dmb ish // memory barrier
+ mov r0, #1 // return true
+ bx lr
+2: ldrex r3, [r2] // load existing value and tag memory
+ teq r3, r0 // is it the same as oldValue?
+ movne r0, #0 // if not, return 0 immediately
+ bxne lr
+ strex r3, r1, [r2] // otherwise, try to store new value
+ cmp r3, #0 // check if the store succeeded
+ bne 2b // if not, try again
+ b 1b // return
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicCompareAndSwap32Barrier, up)
+ENTRY_POINT_DEFAULT(_OSAtomicCompareAndSwapIntBarrier, up)
+ENTRY_POINT_DEFAULT(_OSAtomicCompareAndSwapLongBarrier, up)
+ENTRY_POINT_DEFAULT(_OSAtomicCompareAndSwapPtrBarrier, up)
ENTRY_POINT(_OSAtomicCompareAndSwap32)
-ENTRY_POINT(_OSAtomicCompareAndSwapIntBarrier)
ENTRY_POINT(_OSAtomicCompareAndSwapInt)
-ENTRY_POINT(_OSAtomicCompareAndSwapLongBarrier)
ENTRY_POINT(_OSAtomicCompareAndSwapLong)
-ENTRY_POINT(_OSAtomicCompareAndSwapPtrBarrier)
ENTRY_POINT(_OSAtomicCompareAndSwapPtr)
1: ldrex r3, [r2] // load existing value and tag memory
teq r3, r0 // is it the same as oldValue?
* bit to set is in R0, base address is in R1. Return
* previous value (0 or 1) of the bit in R0.
*/
-#define ATOMIC_BITOP(op) \
+#define _BITOP(op) \
/* Adjust pointer to point at the correct word ;\
* R1 = R1 + 4 * (R0 / 32) ;\
*/ ;\
- mov r3, r0, lsr #5 ;\
- add r1, r1, r3, asl #2 ;\
+ mov r3, r0, lsr #5 ;\
+ add r1, r1, r3, asl #2 ;\
/* Generate a bit mask for the bit we want to test ;\
* R0 = (0x80 >> (R0 & 7)) << (R0 & ~7 & 31) ;\
*/ ;\
- and r2, r0, #7 ;\
- mov r3, #0x80 ;\
- mov r3, r3, asr r2 ;\
- and r0, r0, #0x18 ;\
- mov r0, r3, asl r0 ;\
+ and r2, r0, #7 ;\
+ mov r3, #0x80 ;\
+ mov r3, r3, asr r2 ;\
+ and r0, r0, #0x18 ;\
+ mov r0, r3, asl r0 ;\
+
+#define ATOMIC_BITOP(op) \
+ _BITOP(op) ;\
1: ;\
ldrex r2, [r1] /* load existing value and tag memory */ ;\
op r3, r2, r0 /* compute new value */ ;\
strex ip, r3, [r1] /* attempt to store new value */ ;\
cmp ip, #0 /* check if the store succeeded */ ;\
- bne 1b /* if so, try again */ ;\
+ bne 1b /* if not, try again */ ;\
ands r0, r2, r0 /* mask off the bit from the old value */ ;\
movne r0, #1 /* if non-zero, return exactly 1 */
-ENTRY_POINT(_OSAtomicTestAndSetBarrier)
+#if defined(_ARM_ARCH_7)
+#define ATOMIC_BITOP_FB(op) \
+ _BITOP(op) ;\
+ dmb ishst /* store barrier before store exclusive */ ;\
+1: ldrex r2, [r1] /* load existing value and tag memory */ ;\
+ op r3, r2, r0 /* compute new value */ ;\
+ strex ip, r3, [r1] /* attempt to store new value */ ;\
+ cmp ip, #0 /* check if the store succeeded */ ;\
+ bne 1b /* if not, try again */ ;\
+ dmb ish /* memory barrier */ ;\
+ ands r0, r2, r0 /* mask off the bit from the old value */ ;\
+ movne r0, #1 /* if non-zero, return exactly 1 */
+#endif
+
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicTestAndSetBarrier, mp)
+ ATOMIC_BITOP_FB(orr)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicTestAndSetBarrier, up)
ENTRY_POINT(_OSAtomicTestAndSet)
ATOMIC_BITOP(orr)
bx lr
-ENTRY_POINT(_OSAtomicTestAndClearBarrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicTestAndClearBarrier, mp)
+ ATOMIC_BITOP_FB(bic)
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicTestAndClearBarrier, up)
ENTRY_POINT(_OSAtomicTestAndClear)
ATOMIC_BITOP(bic)
bx lr
-ENTRY_POINT(_OSMemoryBarrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSMemoryBarrier, mp)
+ dmb ish
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSMemoryBarrier, up)
bx lr
+/* void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset); */
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicEnqueue, mp)
+ dmb ishst
+1: ldrex r3, [r0] // get link to 1st on list
+ str r3, [r1, r2] // hang list off new node
+ strex r3, r1, [r0] // make new 1st on list
+ cmp r3, #0
+ bne 1b
+ dmb ish
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicEnqueue, up)
+1: ldrex r3, [r0] // get link to 1st on list
+ str r3, [r1, r2] // hang list off new node
+ strex r3, r1, [r0] // make new 1st on list
+ cmp r3, #0
+ bne 1b
+ bx lr
+
+/* void* OSAtomicDequeue( OSQueueHead *list, size_t offset); */
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicDequeue, mp)
+ mov r2, r0
+ dmb ishst
+1: ldrex r0, [r2] // get 1st in list
+ cmp r0, #0 // null?
+ bxeq lr // yes, list empty
+ ldr r3, [r0, r1] // get 2nd
+ strex ip, r3, [r2] // make 2nd first
+ cmp ip, #0
+ bne 1b
+ dmb ish
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicDequeue, up)
+ mov r2, r0
+1: ldrex r0, [r2] // get 1st in list
+ cmp r0, #0 // null?
+ bxeq lr // yes, list empty
+ ldr r3, [r0, r1] // get 2nd
+ strex ip, r3, [r2] // make 2nd first
+ cmp ip, #0
+ bne 1b
+ bx lr
#if defined(_ARM_ARCH_6K)
/* If we can use LDREXD/STREXD, then we can implement 64-bit atomic operations */
-ENTRY_POINT(_OSAtomicAdd64Barrier)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicAdd64Barrier, mp)
+ // R0,R1 contain the amount to add
+ // R2 contains the pointer
+ stmfd sp!, {r4, r5, r8, r9, lr}
+ dmb ishst // store memory barrier before store exclusive
+1: ldrexd r4, r5, [r2] // load existing value to R4/R5 and tag memory
+ adds r8, r4, r0 // add lower half of new value into R8 and set carry bit
+ adc r9, r5, r1 // add upper half of new value into R9 with carry
+ strexd r3, r8, r9, [r2] // store new value if memory is still tagged
+ cmp r3, #0 // check if store succeeded
+ bne 1b // if not, try again
+ dmb ish // memory barrier
+ mov r0, r8 // return new value
+ mov r1, r9
+ ldmfd sp!, {r4, r5, r8, r9, pc}
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicAdd64Barrier, up)
ENTRY_POINT(_OSAtomicAdd64)
// R0,R1 contain the amount to add
// R2 contains the pointer
stmfd sp!, {r4, r5, r8, r9, lr}
-1:
- ldrexd r4, r5, [r2] // load existing value to R4/R5 and tag memory
- adds r8, r4, r0 // add lower half of new value into R6 and set carry bit
- adc r9, r5, r1 // add upper half of new value into R8 with carry
+1: ldrexd r4, r5, [r2] // load existing value to R4/R5 and tag memory
+ adds r8, r4, r0 // add lower half of new value into R8 and set carry bit
+ adc r9, r5, r1 // add upper half of new value into R9 with carry
strexd r3, r8, r9, [r2] // store new value if memory is still tagged
cmp r3, #0 // check if store succeeded
- bne 1b // if so, try again
+ bne 1b // if not, try again
mov r0, r8 // return new value
mov r1, r9
ldmfd sp!, {r4, r5, r8, r9, pc}
-ENTRY_POINT(_OSAtomicCompareAndSwap64Barrier)
-ENTRY_POINT(_OSAtomicCompareAndSwap64)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_OSAtomicCompareAndSwap64Barrier, mp)
// R0,R1 contains the old value
// R2,R3 contains the new value
// the pointer is pushed onto the stack
ldr ip, [sp, #0] // load pointer into IP
stmfd sp!, {r4, r5, lr}
-1:
ldrexd r4, [ip] // load existing value into R4/R5 and tag memory
teq r0, r4 // check low word
teqeq r1, r5 // if low words match, check high word
movne r0, #0 // if either match fails, return 0
bne 2f
+ dmb ishst // store barrier before store exclusive
strexd r4, r2, [ip] // otherwise, try to store new values
- cmp r3, #0 // check if store succeeded
- bne 1b // if so, try again
+ cmp r4, #0 // check if store succeeded
+ bne 3f // if not, try again
+1: dmb ish // memory barrier
mov r0, #1 // return true
-2:
- ldmfd sp!, {r4, r5, pc}
+2: ldmfd sp!, {r4, r5, pc}
+3: ldrexd r4, [ip] // load existing value into R4/R5 and tag memory
+ teq r0, r4 // check low word
+ teqeq r1, r5 // if low words match, check high word
+ movne r0, #0 // if either match fails, return 0
+ bne 2b
+ strexd r4, r2, [ip] // otherwise, try to store new values
+ cmp r4, #0 // check if store succeeded
+ bne 3f // if not, try again
+ b 1b // return
+#endif
+
+ENTRY_POINT_DEFAULT(_OSAtomicCompareAndSwap64Barrier, up)
+ENTRY_POINT(_OSAtomicCompareAndSwap64)
+ // R0,R1 contains the old value
+ // R2,R3 contains the new value
+ // the pointer is pushed onto the stack
+ ldr ip, [sp, #0] // load pointer into IP
+ stmfd sp!, {r4, r5, lr}
+1: ldrexd r4, [ip] // load existing value into R4/R5 and tag memory
+ teq r0, r4 // check low word
+ teqeq r1, r5 // if low words match, check high word
+ movne r0, #0 // if either match fails, return 0
+ bne 2f
+ strexd r4, r2, [ip] // otherwise, try to store new values
+ cmp r4, #0 // check if store succeeded
+ bne 1b // if not, try again
+ mov r0, #1 // return true
+2: ldmfd sp!, {r4, r5, pc}
#endif /* defined(_ARM_ARCH_6K) */
* Lock the lock pointed to by p. Spin (possibly forever) until the next
* lock is available.
*/
-ENTRY_POINT(_spin_lock)
-ENTRY_POINT(__spin_lock)
-ENTRY_POINT(_OSSpinLockLock)
-L_spin_lock_loop:
+
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_spin_lock, mp)
+ENTRY_POINT_RESOLVER(__spin_lock, mp)
+ENTRY_POINT_RESOLVER(_OSSpinLockLock, mp)
mov r1, #1
+1: ldrex r2, [r0] // load the value of [r0] into r2
+ cmp r2, #0 // compare the lock value to zero
+ bne 2f // jump to the spin if we don't own the lock
+ strex r3, r1, [r0] // try to store the one
+ cmp r3, #0 // test to see if we stored our value
+ bne 2f // if not, jump to the spin too
+ dmb ish // memory barrier if we acquired the lock
+ bx lr // and return
+2: mov r3, $(MP_SPIN_TRIES) // load up r3 with spin counter
+3: ldr r2, [r0] // load the lock
+ cmp r2, #0 // if unlocked
+ beq 1b // then go back to the top
+ subs r3, r3, #1 // counter--
+ bne 3b // if nonzero, back to 3:
+
+ mov r3, r0 // r0 is clobbered by the syscall return value
+ mov r0, #0 // THREAD_NULL
+ // SWITCH_OPTION_DEPRESS (r1==1 already)
+ mov r2, #1 // timeout (ms)
+ mov r12, #-61 // SYSCALL_THREAD_SWITCH
+ swi 0x80
+ mov r0, r3 // restore state of r0
+ b 1b
+
+#if !defined(VARIANT_DYLD)
+/*
+ This sucks from a code sharing PoV. The only difference in this version is
+ the presence of a WFE instruction in the spin loop. This is only used on
+ CPU's which get woken up regularly out of WFE waits.
+
+ Additionally, completely compiled out of the dyld variant so we can easily
+ use macros to pick the normal MP version for dyld on armv7 platforms.
+ */
+ENTRY_POINT_RESOLVER(_spin_lock, wfe)
+ENTRY_POINT_RESOLVER(__spin_lock, wfe)
+ENTRY_POINT_RESOLVER(_OSSpinLockLock, wfe)
+ mov r1, #1
+1: ldrex r2, [r0] // load the value of [r0] into r2
+ cmp r2, #0 // compare the lock value to zero
+ bne 2f // jump to the spin if we don't own the lock
+ strex r3, r1, [r0] // try to store the one
+ cmp r3, #0 // test to see if we stored our value
+ bne 2f // if not, jump to the spin too
+ dmb ish // memory barrier if we acquired the lock
+ bx lr // and return
+2: mov r3, $(MP_SPIN_TRIES_WFE) // load up r3 with spin counter
+3: wfe // sleepy time
+ ldr r2, [r0] // load the lock
+ cmp r2, #0 // if unlocked
+ beq 1b // then go back to the top
+ subs r3, r3, #1 // counter--
+ bne 3b // if nonzero, back to 3:
+
+ mov r3, r0 // r0 is clobbered by the syscall return value
+ mov r0, #0 // THREAD_NULL
+ // SWITCH_OPTION_DEPRESS (r1==1 already)
+ mov r2, #1 // timeout (ms)
+ mov r12, #-61 // SYSCALL_THREAD_SWITCH
+ swi 0x80
+ mov r0, r3 // restore state of r0
+ b 1b
+#endif // VARIANT_DYLD
+#endif // _ARM_ARCH_7
+
+ENTRY_POINT_DEFAULT(_spin_lock, up)
+ENTRY_POINT_DEFAULT(__spin_lock, up)
+ENTRY_POINT_DEFAULT(_OSSpinLockLock, up)
+ mov r1, #1
+1:
+#if !defined(_ARM_ARCH_7)
swp r2, r1, [r0]
cmp r2, #0
- bxeq lr
- mov ip, sp
- stmfd sp!, {r0, r8}
- mov r0, #0 // THREAD_NULL
- mov r1, #1 // SWITCH_OPTION_DEPRESS
- mov r2, #1 // timeout (ms)
- mov r12, #-61 // SYSCALL_THREAD_SWITCH
+#else
+ ldrex r2, [r0] // load the value of [r0] into r2
+ cmp r2, #0 // compare the lock value to zero
+ bne 2f // jump to the spin if we don't own the lock
+ strex r3, r1, [r0] // try to store the one
+ cmp r3, #0 // test to see if we stored our value
+#endif // !_ARM_ARCH_6
+ bxeq lr // if so, return
+2: mov r3, r0 // r0 is clobbered by the syscall return value
+ mov r0, #0 // THREAD_NULL
+ // SWITCH_OPTION_DEPRESS (r1==1 already)
+ mov r2, #1 // timeout (ms)
+ mov r12, #-61 // SYSCALL_THREAD_SWITCH
swi 0x80
- ldmfd sp!, {r0, r8}
- b L_spin_lock_loop
+ mov r0, r3 // restore state of r0
+ b 1b
-ENTRY_POINT(_spin_lock_try)
-ENTRY_POINT(__spin_lock_try)
-ENTRY_POINT(_OSSpinLockTry)
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_spin_lock_try, mp)
+ENTRY_POINT_RESOLVER(__spin_lock_try, mp)
+ENTRY_POINT_RESOLVER(_OSSpinLockTry, mp)
mov r1, #1
+1: ldrex r2, [r0]
+ strex r3, r1, [r0]
+ cmp r3, #0
+ bne 1b
+ dmb ish
+ bic r0, r1, r2
+ bx lr
+#endif
+
+ENTRY_POINT_DEFAULT(_spin_lock_try, up)
+ENTRY_POINT_DEFAULT(__spin_lock_try, up)
+ENTRY_POINT_DEFAULT(_OSSpinLockTry, up)
+ mov r1, #1
+#if !defined(_ARM_ARCH_7)
swp r2, r1, [r0]
+#else
+1: ldrex r2, [r0]
+ strex r3, r1, [r0]
+ cmp r3, #0
+ bne 1b
+#endif // !_ARM_ARCH_6
bic r0, r1, r2
bx lr
*
* Unlock the lock pointed to by p.
*/
-ENTRY_POINT(_spin_unlock)
-ENTRY_POINT(__spin_unlock)
-ENTRY_POINT(_OSSpinLockUnlock)
+
+#if defined(_ARM_ARCH_7)
+ENTRY_POINT_RESOLVER(_spin_unlock, mp)
+ENTRY_POINT_RESOLVER(__spin_unlock, mp)
+ENTRY_POINT_RESOLVER(_OSSpinLockUnlock, mp)
mov r1, #0
- str r1, [r0]
+ dmb ish // barrier so that previous accesses are observed before unlock
+1: ldrex r2, [r0] // load the lock to get exclusive access
+ strex r3, r1, [r0] // strex is instantly visible to (at least) {st,ld}rex
+ cmp r3, #0 // did the unlock succeed?
+ bne 1b // if not, try try again.
bx lr
+#endif
+ENTRY_POINT_DEFAULT(_spin_unlock, up)
+ENTRY_POINT_DEFAULT(__spin_unlock, up)
+ENTRY_POINT_DEFAULT(_OSSpinLockUnlock, up)
+ mov r1, #0
+#if !defined(_ARM_ARCH_7)
+ str r1, [r0]
+#else
+1: ldrex r2, [r0] // load the lock to get exclusive access
+ strex r3, r1, [r0] // store zero to the lock
+ cmp r3, #0 // did the unlock succeed?
+ bne 1b // if not, try try again.
+#endif // !_ARM_ARCH_6
+ bx lr
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * This holds the C versions of OSAtomic.s resolver functions, used by
+ * everyone except dyld.
+ */
+
+#include <arm/arch.h>
+#if defined(_ARM_ARCH_7) && !defined(VARIANT_DYLD)
+
+#include <stdlib.h>
+#include <machine/cpu_capabilities.h>
+#include <mach/machine.h>
+
+#define makeResolver_up_mp(name) \
+ void name ## $VARIANT$up(void); \
+ void name ## $VARIANT$mp(void); \
+ void* name ## Resolver(void) __asm__( "_" #name ) ; \
+ void* name ## Resolver(void) { \
+ __asm__(".symbol_resolver _" #name); \
+ /* return MP variant functions on kNumCPUs > 1 */ \
+ if ((_get_cpu_capabilities() & kUP) == 0) { \
+ return name ## $VARIANT$mp; \
+ } \
+ return name ## $VARIANT$up; \
+ }
+
+#define makeResolver_up_mp_wfe(name) \
+ void name ## $VARIANT$up(void); \
+ void name ## $VARIANT$mp(void); \
+ void name ## $VARIANT$wfe(void); \
+ void* name ## Resolver(void) __asm__( "_" #name ) ; \
+ void* name ## Resolver(void) { \
+ __asm__(".symbol_resolver _" #name); \
+ int caps = _get_cpu_capabilities(); \
+ /* return WFE variant if we will get woken up */ \
+ if ((caps & (kHasEvent | kUP)) == kHasEvent) { \
+ return name ## $VARIANT$wfe; \
+ } \
+ /* return MP variant functions on kNumCPUs > 1 */ \
+ else if ((caps & kUP) == 0) { \
+ return name ## $VARIANT$mp; \
+ } \
+ return name ## $VARIANT$up; \
+ }
+
+#include "OSAtomic_resolvers.h"
+
+#else // defined _ARM_ARCH_7 && !defined VARIANT_DYLD
+
+typedef int emptyFilesArentCFiles;
+
+#endif // defined _ARM_ARCH_7 && !defined VARIANT_DYLD
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * This header file gets included by OSAtomic_resolvers.c and OSAtomic.s
+ * in order to create the appropriate resolvers for both libsystem_c.dylib
+ * and dyld's libc.a
+ */
+
+makeResolver_up_mp(OSAtomicAdd32Barrier)
+makeResolver_up_mp(OSAtomicOr32Barrier)
+makeResolver_up_mp(OSAtomicOr32OrigBarrier)
+makeResolver_up_mp(OSAtomicAnd32Barrier)
+makeResolver_up_mp(OSAtomicAnd32OrigBarrier)
+makeResolver_up_mp(OSAtomicXor32Barrier)
+makeResolver_up_mp(OSAtomicXor32OrigBarrier)
+makeResolver_up_mp(OSAtomicCompareAndSwap32Barrier)
+makeResolver_up_mp(OSAtomicCompareAndSwapIntBarrier)
+makeResolver_up_mp(OSAtomicCompareAndSwapLongBarrier)
+makeResolver_up_mp(OSAtomicCompareAndSwapPtrBarrier)
+makeResolver_up_mp(OSAtomicTestAndSetBarrier)
+makeResolver_up_mp(OSAtomicTestAndClearBarrier)
+makeResolver_up_mp(OSMemoryBarrier)
+makeResolver_up_mp(OSAtomicEnqueue)
+makeResolver_up_mp(OSAtomicDequeue)
+makeResolver_up_mp(OSAtomicAdd64Barrier)
+makeResolver_up_mp(OSAtomicCompareAndSwap64Barrier)
+
+makeResolver_up_mp_wfe(spin_lock)
+makeResolver_up_mp_wfe(_spin_lock)
+makeResolver_up_mp_wfe(OSSpinLockLock)
+
+makeResolver_up_mp(spin_lock_try)
+makeResolver_up_mp(_spin_lock_try)
+makeResolver_up_mp(OSSpinLockTry)
+
+makeResolver_up_mp(spin_unlock)
+makeResolver_up_mp(_spin_unlock)
+makeResolver_up_mp(OSSpinLockUnlock)
*
* @APPLE_LICENSE_HEADER_END@
*/
+
+#ifndef __clang__
+
#include <stdint.h>
#include <libkern/OSAtomic.h>
#include <arm/arch.h>
int32_t __sync_fetch_and_add_4 (int32_t *ptr, int32_t value)
{
- return OSAtomicAdd32(value, ptr) - value;
+ return OSAtomicAdd32Barrier(value, ptr) - value;
}
int32_t __sync_fetch_and_sub_4 (int32_t *ptr, int32_t value)
{
- return OSAtomicAdd32(-value, ptr) + value;
+ return OSAtomicAdd32Barrier(-value, ptr) + value;
}
uint32_t __sync_fetch_and_or_4(uint32_t *ptr, uint32_t value)
{
- return OSAtomicOr32Orig(value, ptr);
+ return OSAtomicOr32OrigBarrier(value, ptr);
}
uint32_t __sync_fetch_and_and_4(uint32_t *ptr, uint32_t value)
{
- return OSAtomicAnd32Orig(value, ptr);
+ return OSAtomicAnd32OrigBarrier(value, ptr);
}
uint32_t __sync_fetch_and_xor_4(uint32_t *ptr, uint32_t value)
{
- OSAtomicXor32Orig(value, ptr);
+ return OSAtomicXor32OrigBarrier(value, ptr);
}
int32_t __sync_add_and_fetch_4 (int32_t *ptr, int32_t value)
{
- return OSAtomicAdd32(value, ptr);
+ return OSAtomicAdd32Barrier(value, ptr);
}
int32_t __sync_sub_and_fetch_4 (int32_t *ptr, int32_t value)
{
- return OSAtomicAdd32(-value, ptr);
+ return OSAtomicAdd32Barrier(-value, ptr);
}
uint32_t __sync_or_and_fetch_4 (uint32_t *ptr, int32_t value)
{
- return OSAtomicOr32(value, ptr);
+ return OSAtomicOr32Barrier(value, ptr);
}
uint32_t __sync_and_and_fetch_4 (uint32_t *ptr, int32_t value)
{
- return OSAtomicAnd32(value, ptr);
+ return OSAtomicAnd32Barrier(value, ptr);
}
uint32_t __sync_xor_and_fetch_4 (uint32_t *ptr, int32_t value)
{
- return OSAtomicXor32(value, ptr);
+ return OSAtomicXor32Barrier(value, ptr);
}
bool __sync_bool_compare_and_swap_4(int32_t *ptr, int32_t oldval, int32_t newval)
{
- return OSAtomicCompareAndSwap32(oldval, newval, ptr);
+ return OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
}
int32_t __sync_val_compare_and_swap_4(int32_t *ptr, int32_t oldval, int32_t newval)
{
int32_t old = *ptr;
- OSAtomicCompareAndSwap32(oldval, newval, ptr);
+ OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
return old;
}
do {
old = *ptr;
- } while (!OSAtomicCompareAndSwap32(old, value, ptr));
+ } while (!OSAtomicCompareAndSwap32Barrier(old, value, ptr));
return old;
}
{
*ptr = 0;
}
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+
+#if __arm__
+ .text
+ .align 2
+ .globl _mach_absolute_time
+_mach_absolute_time:
+ mov r12, #-3
+ swi 0x80
+ bx lr
+#endif
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)creat.2 8.1 (Berkeley) 6/2/93
-.\" $FreeBSD: src/lib/libc/compat-43/creat.2,v 1.10 2002/12/18 12:45:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/compat-43/creat.2,v 1.11 2007/01/09 00:27:49 imp Exp $
.\"
.Dd June 2, 1993
.Dt CREAT 2
* 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.
static char sccsid[] = "@(#)creat.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/creat.c,v 1.7 2002/03/22 21:51:56 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/creat.c,v 1.8 2007/01/09 00:27:49 imp Exp $");
#include "namespace.h"
#include <fcntl.h>
---- creat.c.orig 2006-09-16 19:12:44.000000000 -0700
-+++ creat.c 2006-09-17 00:17:18.000000000 -0700
-@@ -37,14 +37,26 @@
+--- creat.c.orig 2009-11-06 10:36:38.000000000 -0800
++++ creat.c 2009-11-06 10:39:44.000000000 -0800
+@@ -33,14 +33,26 @@ static char sccsid[] = "@(#)creat.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/compat-43/creat.c,v 1.7 2002/03/22 21:51:56 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/compat-43/creat.c,v 1.8 2007/01/09 00:27:49 imp Exp $");
+
#include "namespace.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)gethostid.3 8.1 (Berkeley) 6/2/93
-.\" $FreeBSD: src/lib/libc/compat-43/gethostid.3,v 1.12 2004/07/02 23:52:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/compat-43/gethostid.3,v 1.14 2007/01/09 00:27:49 imp Exp $
.\"
.Dd June 2, 1993
.Dt GETHOSTID 3
.Xr gethostname 3 ,
.Xr sysctl 3 ,
.Xr sysctl 8
-.Sh BUGS
-32 bits for the identifier is too small.
.Sh HISTORY
The
.Fn gethostid
.Bx 4.2
and were dropped in
.Bx 4.4 .
+.Sh BUGS
+32 bits for the identifier is too small.
---- _SB/Libc/compat-43/FreeBSD/gethostid.3 2004-11-25 11:37:56.000000000 -0800
-+++ _SB/Libc/compat-43/FreeBSD/gethostid.3.edit 2006-06-28 16:55:50.000000000 -0700
-@@ -51,11 +51,9 @@
+--- gethostid.3.orig 2009-11-06 10:36:38.000000000 -0800
++++ gethostid.3 2009-11-06 10:41:15.000000000 -0800
+@@ -47,11 +47,9 @@
The
.Fn sethostid
function
* 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.
static char sccsid[] = "@(#)gethostid.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/gethostid.c,v 1.3 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/gethostid.c,v 1.5 2007/01/09 00:27:49 imp Exp $");
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <unistd.h>
+
long
gethostid(void)
{
--- /dev/null
+--- gethostid.c.orig 2011-02-15 16:30:07.000000000 -0800
++++ gethostid.c 2011-02-18 12:19:33.000000000 -0800
+@@ -43,7 +43,7 @@ gethostid(void)
+ {
+ int mib[2];
+ size_t size;
+- long value;
++ int value;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTID;
* 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.
static char sccsid[] = "@(#)getwd.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/getwd.c,v 1.3 2002/03/22 21:51:56 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/getwd.c,v 1.6 2007/01/09 00:27:49 imp Exp $");
#include <sys/param.h>
#include <unistd.h>
#include <string.h>
char *
-getwd(buf)
- char *buf;
+getwd(char *buf)
{
char *p;
if ( (p = getcwd(buf, MAXPATHLEN)) )
return(p);
- (void)strcpy(buf, strerror(errno));
+ (void)strerror_r(errno, buf, MAXPATHLEN);
return((char *)NULL);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)killpg.2 8.1 (Berkeley) 6/2/93
-.\" $FreeBSD: src/lib/libc/compat-43/killpg.2,v 1.12 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/compat-43/killpg.2,v 1.14 2007/01/09 00:27:49 imp Exp $
.\"
-.Dd June 2, 1993
+.Dd October 10, 2006
.Dt KILLPG 2
.Os
.Sh NAME
have the same effective user ID, or
the sender must be the super-user.
As a single special case the continue signal SIGCONT may be sent
-to any process that is a descendant of the current process.
+to any process with the same session ID as the caller.
.Sh RETURN VALUES
.Rv -std killpg
.Sh ERRORS
---- killpg.2 2003-05-20 15:20:40.000000000 -0700
-+++ killpg.2.edit 2006-07-12 10:52:21.000000000 -0700
-@@ -41,7 +41,6 @@
+--- killpg.2.orig 2009-11-06 10:36:38.000000000 -0800
++++ killpg.2 2009-11-06 10:41:32.000000000 -0800
+@@ -37,7 +37,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In signal.h
.Ft int
.Fn killpg "pid_t pgrp" "int sig"
-@@ -80,21 +79,29 @@
+@@ -76,21 +75,29 @@ The
.Fa sig
argument
is not a valid signal number.
* 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.
static char sccsid[] = "@(#)killpg.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/killpg.c,v 1.4 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/killpg.c,v 1.5 2007/01/09 00:27:49 imp Exp $");
#include <sys/types.h>
#include <signal.h>
---- killpg.c.orig 2005-01-26 12:24:56.000000000 -0800
-+++ killpg.c 2005-01-26 12:23:37.000000000 -0800
-@@ -41,6 +41,16 @@
+--- killpg.c.orig 2009-11-06 10:36:38.000000000 -0800
++++ killpg.c 2009-11-06 10:41:47.000000000 -0800
+@@ -37,6 +37,16 @@ __FBSDID("$FreeBSD: src/lib/libc/compat-
#include <signal.h>
#include <errno.h>
/*
* Backwards-compatible killpg().
*/
-@@ -48,8 +58,8 @@
+@@ -44,8 +54,8 @@ int
killpg(pid_t pgid, int sig)
{
if (pgid == 1) {
* 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.
static char sccsid[] = "@(#)sethostid.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/sethostid.c,v 1.3 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/sethostid.c,v 1.5 2007/01/09 00:27:49 imp Exp $");
#include <sys/param.h>
#include <sys/sysctl.h>
-long
+#include <unistd.h>
+
+void
sethostid(long hostid)
{
int mib[2];
mib[0] = CTL_KERN;
mib[1] = KERN_HOSTID;
- if (sysctl(mib, 2, NULL, NULL, &hostid, sizeof hostid) == -1)
- return (-1);
- return (0);
+ sysctl(mib, 2, NULL, NULL, &hostid, sizeof hostid);
}
* 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.
static char sccsid[] = "@(#)setpgrp.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/setpgrp.c,v 1.4 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/setpgrp.c,v 1.5 2007/01/09 00:27:49 imp Exp $");
#include <sys/types.h>
#include <unistd.h>
---- setpgrp.c.orig 2006-09-17 12:11:20.000000000 -0700
-+++ setpgrp.c 2006-09-24 16:13:25.000000000 -0700
-@@ -40,8 +40,13 @@
+--- setpgrp.c.orig 2009-11-06 10:36:38.000000000 -0800
++++ setpgrp.c 2009-11-06 10:42:14.000000000 -0800
+@@ -36,8 +36,13 @@ __FBSDID("$FreeBSD: src/lib/libc/compat-
#include <sys/types.h>
#include <unistd.h>
* 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.
static char sccsid[] = "@(#)setrgid.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/setrgid.c,v 1.3 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/setrgid.c,v 1.4 2007/01/09 00:27:49 imp Exp $");
#include <unistd.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)setruid.3 8.1 (Berkeley) 6/2/93
-.\" $FreeBSD: src/lib/libc/compat-43/setruid.3,v 1.10 2001/10/01 16:08:50 ru Exp $
+.\" $FreeBSD: src/lib/libc/compat-43/setruid.3,v 1.12 2007/01/09 00:27:49 imp Exp $
.\"
.Dd June 2, 1993
.Dt SETRUID 3
current process.
.Sh RETURN VALUES
.Rv -std
+.Sh COMPATIBILITY
+The use of these calls is not portable.
+Their use is discouraged; they will be removed in the future.
.Sh ERRORS
The functions fail if:
.Bl -tag -width Er
The user is not the super user and the ID
specified is not the real or effective ID.
.El
-.Sh COMPATIBILITY
-The use of these calls is not portable.
-Their use is discouraged; they will be removed in the future.
.Sh SEE ALSO
.Xr getgid 2 ,
.Xr getuid 2 ,
* 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.
static char sccsid[] = "@(#)setruid.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/setruid.c,v 1.3 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/setruid.c,v 1.4 2007/01/09 00:27:49 imp Exp $");
#include <unistd.h>
* 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.
static char sccsid[] = "@(#)creat.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/creat.c,v 1.7 2002/03/22 21:51:56 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/creat.c,v 1.8 2007/01/09 00:27:49 imp Exp $");
#include "namespace.h"
+++ /dev/null
-./gethostid.c
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostid.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/gethostid.c,v 1.5 2007/01/09 00:27:49 imp Exp $");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <unistd.h>
+
+long
+gethostid(void)
+{
+ int mib[2];
+ size_t size;
+ int value;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTID;
+ size = sizeof value;
+ if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
+ return (-1);
+ return (value);
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)gethostid.3 8.1 (Berkeley) 6/2/93
-.\" $FreeBSD: src/lib/libc/compat-43/gethostid.3,v 1.12 2004/07/02 23:52:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/compat-43/gethostid.3,v 1.14 2007/01/09 00:27:49 imp Exp $
.\"
.Dd June 2, 1993
.Dt GETHOSTID 3
.Xr gethostname 3 ,
.Xr sysctl 3 ,
.Xr sysctl 8
-.Sh BUGS
-32 bits for the identifier is too small.
.Sh HISTORY
The
.Fn gethostid
.Bx 4.2
and were dropped in
.Bx 4.4 .
+.Sh BUGS
+32 bits for the identifier is too small.
* 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.
static char sccsid[] = "@(#)killpg.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/killpg.c,v 1.4 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/killpg.c,v 1.5 2007/01/09 00:27:49 imp Exp $");
#include <sys/types.h>
#include <signal.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)killpg.2 8.1 (Berkeley) 6/2/93
-.\" $FreeBSD: src/lib/libc/compat-43/killpg.2,v 1.12 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/compat-43/killpg.2,v 1.14 2007/01/09 00:27:49 imp Exp $
.\"
-.Dd June 2, 1993
+.Dd October 10, 2006
.Dt KILLPG 2
.Os
.Sh NAME
have the same effective user ID, or
the sender must be the super-user.
As a single special case the continue signal SIGCONT may be sent
-to any process that is a descendant of the current process.
+to any process with the same session ID as the caller.
.Sh RETURN VALUES
.Rv -std killpg
.Sh ERRORS
* 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.
static char sccsid[] = "@(#)setpgrp.c 8.1 (Berkeley) 6/2/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/compat-43/setpgrp.c,v 1.4 2002/05/28 16:56:57 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/compat-43/setpgrp.c,v 1.5 2007/01/09 00:27:49 imp Exp $");
#include <sys/types.h>
#include <unistd.h>
LOCALHDRS += ${.CURDIR}/darwin/dirhelper.defs \
${.CURDIR}/darwin/dirhelper_priv.h \
- ${.CURDIR}/darwin/libproc.h
+ ${.CURDIR}/darwin/libproc.h \
+ ${.CURDIR}/darwin/libproc_internal.h
MISRCS += ${DARWINMIGSRCS} _dirhelper.c libproc.c proc_listpidspath.c
.ifndef LP64
/*
- * Copyright (c) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <string.h>
#include <libkern/OSByteOrder.h>
#include <TargetConditionals.h>
+#include <xpc/xpc.h>
+#include <xpc/private.h>
#include "dirhelper.h"
#include "dirhelper_priv.h"
#define MUTEX_LOCK(x) if(__is_threaded) pthread_mutex_lock(x)
#define MUTEX_UNLOCK(x) if(__is_threaded) pthread_mutex_unlock(x)
-#define ENCODEBITS 6
+// Use 5 bits per character, to avoid uppercase and shell magic characters
+#define ENCODEBITS 5
#define ENCODEDSIZE ((8 * UUID_UID_SIZE + ENCODEBITS - 1) / ENCODEBITS)
+#define MASK(x) ((1 << (x)) - 1)
#define UUID_UID_SIZE (sizeof(uuid_t) + sizeof(uid_t))
extern int __is_threaded;
static const mode_t modes[] = {
- 0, /* unused */
+ 0755, /* user */
0700, /* temp */
0700, /* cache */
};
DIRHELPER_CACHE_STR,
};
-static const char encode[] = "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static pthread_once_t userdir_control = PTHREAD_ONCE_INIT;
+static char *userdir = NULL;
+
+// lower case letter (minus vowels), plus numbers and _, making
+// 32 characters.
+static const char encode[] = "0123456789_bcdfghjklmnpqrstvwxyz";
static void
-encode_uuid_uid(uuid_t uuid, uid_t uid, char *str)
+encode_uuid_uid(const uuid_t uuid, uid_t uid, char *str)
{
unsigned char buf[UUID_UID_SIZE + 1];
unsigned char *bp = buf;
- int i = 0;
+ int i;
unsigned int n;
memcpy(bp, uuid, sizeof(uuid_t));
uid = OSSwapHostToBigInt32(uid);
memcpy(bp + sizeof(uuid_t), &uid, sizeof(uid_t));
bp[UUID_UID_SIZE] = 0; // this ensures the last encoded byte will have trailing zeros
- while(i < ENCODEDSIZE) {
- switch(i % 4) {
+ for(i = 0; i < ENCODEDSIZE; i++) {
+ // 5 bits has 8 states
+ switch(i % 8) {
case 0:
n = *bp++;
- *str++ = encode[n >> 2];
+ *str++ = encode[n >> 3];
break;
case 1:
- n = ((n & 0x3) << 8) | *bp++;
- *str++ = encode[n >> 4];
+ n = ((n & MASK(3)) << 8) | *bp++;
+ *str++ = encode[n >> 6];
break;
case 2:
- n = ((n & 0xf) << 8) | *bp++;
- *str++ = encode[n >> 6];
+ n &= MASK(6);
+ *str++ = encode[n >> 1];
break;
case 3:
- *str++ = encode[n & 0x3f];
+ n = ((n & MASK(1)) << 8) | *bp++;
+ *str++ = encode[n >> 4];
+ break;
+ case 4:
+ n = ((n & MASK(4)) << 8) | *bp++;
+ *str++ = encode[n >> 7];
+ break;
+ case 5:
+ n &= MASK(7);
+ *str++ = encode[n >> 2];
+ break;
+ case 6:
+ n = ((n & MASK(2)) << 8) | *bp++;
+ *str++ = encode[n >> 5];
+ break;
+ case 7:
+ *str++ = encode[n & MASK(5)];
break;
}
- i++;
}
*str = 0;
}
}
#if TARGET_OS_EMBEDDED
- tmpdir = getenv("TMPDIR");
- if(!tmpdir) {
+ /* We only support DIRHELPER_USER_LOCAL_TEMP on embedded.
+ * This interface really doesn't map from OSX to embedded,
+ * and clients of this interface will need to adapt when
+ * porting their applications to embedded.
+ * See: <rdar://problem/7515613>
+ */
+ if(which == DIRHELPER_USER_LOCAL_TEMP) {
+ tmpdir = getenv("TMPDIR");
+ if(!tmpdir) {
+ errno = EINVAL;
+ return NULL;
+ }
+ res = snprintf(path, pathlen, "%s", tmpdir);
+ } else {
errno = EINVAL;
return NULL;
}
-
- res = snprintf(path, pathlen, "%s/%s", tmpdir, subdirs[which]);
#else
res = mbr_uid_to_uuid(uid, uuid);
if(res != 0) {
//
// We partition the namespace so that we don't end up with too
- // many users in a single directory. With 4096 buckets, we
+ // many users in a single directory. With 1024 buckets, we
// could scale to 1,000,000 users while keeping the average
- // number of files in a single directory below 250
+ // number of files in a single directory around 1000
//
encode_uuid_uid(uuid, uid, str);
res = snprintf(path, pathlen,
"%s%.*s/%s/%s",
- VAR_FOLDERS_PATH, BUCKETLEN, str, str, subdirs[which]);
+ VAR_FOLDERS_PATH, BUCKETLEN, str, str + BUCKETLEN, subdirs[which]);
#endif
if(res >= pathlen) {
errno = EINVAL;
return path;
}
+static void userdir_allocate(void)
+{
+ userdir = calloc(PATH_MAX, sizeof(char));
+}
+
+/*
+ * 9407258: Invalidate the dirhelper cache (userdir) of the child after fork.
+ * There is a rare case when launchd will have userdir set, and child process
+ * will sometimes inherit this cached value.
+ */
+__private_extern__ void
+_dirhelper_fork_child(void)
+{
+ if(userdir) *userdir = 0;
+}
+
__private_extern__ char *
_dirhelper(dirhelper_which_t which, char *path, size_t pathlen)
{
- static char userdir[PATH_MAX];
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
- int res;
struct stat sb;
if(which < 0 || which > DIRHELPER_USER_LOCAL_LAST) {
return NULL;
}
+ if (pthread_once(&userdir_control, userdir_allocate)
+ || !userdir) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
if(!*userdir) {
MUTEX_LOCK(&lock);
if (!*userdir) {
- if(__user_local_dirname(geteuid(), DIRHELPER_USER_LOCAL, userdir, sizeof(userdir)) == NULL) {
+ if(__user_local_dirname(geteuid(), DIRHELPER_USER_LOCAL, userdir, PATH_MAX) == NULL) {
MUTEX_UNLOCK(&lock);
return NULL;
}
+ /*
+ * All dirhelper directories are now at the same level, so
+ * we need to remove the DIRHELPER_TOP_STR suffix to get the
+ * parent directory.
+ */
+ userdir[strlen(userdir) - (sizeof(DIRHELPER_TOP_STR) - 1)] = 0;
/*
* check if userdir exists, and if not, either do the work
* ourself if we are root, or call
/*
* now for subdirectories, create it with the appropriate permissions
- * if it doesn't already exist.
+ * if it doesn't already exist. On OS X, if we're under App Sandbox, we
+ * rely on xpchelper having created the subdir for us.
*/
- if(which != DIRHELPER_USER_LOCAL) {
- res = mkdir(path, modes[which]);
- if(res != 0 && errno != EEXIST)
- return NULL;
+#if !TARGET_OS_EMBEDDED
+ if (!_xpc_runtime_is_app_sandboxed())
+#endif
+ if(mkdir(path, modes[which]) != 0 && errno != EEXIST)
+ return NULL;
+
+#if !TARGET_OS_EMBEDDED
+ if (_xpc_runtime_is_app_sandboxed()) {
+ /*
+ * if xpchelper didn't make the subdir for us, bail since we don't have
+ * permission to create it ourselves.
+ */
+ if(stat(path, &sb) < 0) {
+ errno = EPERM;
+ return NULL;
+ }
+
+ /*
+ * sandboxed applications get per-application directories named
+ * after the container
+ */
+ char *container_id = getenv(XPC_ENV_SANDBOX_CONTAINER_ID);
+ if(!container_id) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /*
+ * container ID doesn't end in a slash, so +2 is for slash and \0
+ */
+ if (pathlen < strlen(path) + strlen(container_id) + 2) {
+ errno = EINVAL;
+ return NULL; /* buffer too small */
+ }
+
+ strcat(path, container_id);
+ strcat(path, "/");
+
+ /*
+ * create per-app subdirectory with the appropriate permissions
+ * if it doesn't already exist.
+ */
+ if(mkdir(path, modes[which]) != 0 && errno != EEXIST)
+ return NULL;
}
+#endif
return path;
}
/*
- * Copyright (c) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define VAR_FOLDERS_PATH "/var/folders/"
#define DIRHELPER_BOOTSTRAP_NAME "com.apple.bsd.dirhelper"
-#define DIRHELPER_CACHE_STR "-Caches-/"
-#define DIRHELPER_TEMP_STR "-Tmp-/"
-#define DIRHELPER_TOP_STR ""
+#define DIRHELPER_CACHE_STR "C/"
+#define DIRHELPER_TEMP_STR "T/"
+#define DIRHELPER_TOP_STR "0/"
typedef enum {
DIRHELPER_USER_LOCAL = 0,
/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2006, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <strings.h>
#include <sys/errno.h>
#include <sys/msgbuf.h>
+#define CONFIG_EMBEDDED 1
+#include <sys/process_policy.h>
-#include "libproc.h"
+#include "libproc_internal.h"
int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
+__private_extern__ int proc_setthreadname(void * buffer, int buffersize);
+int __process_policy(int scope, int action, int policy, int policy_subtype, proc_policy_attribute_t * attrp, pid_t target_pid, uint64_t target_threadid);
{
int retval;
- if ((type == PROC_ALL_PIDS) || (type == PROC_PGRP_ONLY) || (type == PROC_TTY_ONLY) || (type == PROC_UID_ONLY) || (type == PROC_RUID_ONLY)) {
+ if ((type >= PROC_ALL_PIDS) || (type <= PROC_PPID_ONLY)) {
if ((retval = __proc_info(1, type, typeinfo,(uint64_t)0, buffer, buffersize)) == -1)
return(0);
} else {
}
+int
+proc_listallpids(void * buffer, int buffersize)
+{
+ int numpids;
+ numpids = proc_listpids(PROC_ALL_PIDS, (uint32_t)0, buffer, buffersize);
+
+ if (numpids == -1)
+ return(-1);
+ else
+ return(numpids/sizeof(int));
+}
+
+int
+proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize)
+{
+ int numpids;
+ numpids = proc_listpids(PROC_PGRP_ONLY, (uint32_t)pgrpid, buffer, buffersize);
+ if (numpids == -1)
+ return(-1);
+ else
+ return(numpids/sizeof(int));
+}
+
+int
+proc_listchildpids(pid_t ppid, void * buffer, int buffersize)
+{
+ int numpids;
+ numpids = proc_listpids(PROC_PPID_ONLY, (uint32_t)ppid, buffer, buffersize);
+ if (numpids == -1)
+ return(-1);
+ else
+ return(numpids/sizeof(int));
+}
+
+
int
proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize)
{
}
+int
+proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize)
+{
+ int retval;
+
+ if ((retval = __proc_info(6, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1)
+ return (0);
+ return (retval);
+}
+
int
proc_name(int pid, void * buffer, uint32_t buffersize)
if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE)
return(EINVAL);
- if ((retval = __proc_info(5, getpid(), PROC_SELFSET_PCONTROL,(uint64_t)control, NULL, 0)) == -1)
+ if ((retval = __proc_info(5, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1)
return(errno);
return(0);
}
+__private_extern__ int
+proc_setthreadname(void * buffer, int buffersize)
+{
+ int retval;
+
+ retval = __proc_info(5, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize);
+
+ if (retval == -1)
+ return(errno);
+ else
+ return(0);
+}
+
+#if TARGET_OS_EMBEDDED
+
+int
+proc_setcpu_percentage(pid_t pid, int action, int percentage)
+{
+ proc_policy_cpuusage_attr_t attr;
+
+ bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
+ attr.ppattr_cpu_attr = action;
+ attr.ppattr_cpu_percentage = percentage;
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+}
+
+int
+proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline)
+{
+ proc_policy_cpuusage_attr_t attr;
+
+ bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
+ attr.ppattr_cpu_attr = action;
+ attr.ppattr_cpu_attr_deadline = deadline;
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+
+}
+
+
+int
+proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline)
+{
+ proc_policy_cpuusage_attr_t attr;
+
+ bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
+ attr.ppattr_cpu_attr = action;
+ attr.ppattr_cpu_percentage = percentage;
+ attr.ppattr_cpu_attr_deadline = deadline;
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+}
+
+int
+proc_clear_cpulimits(pid_t pid)
+{
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+
+
+}
+
+int
+proc_appstate(int pid, int * appstatep)
+{
+ int state;
+
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (int *)&state, pid, (uint64_t)0) != -1) {
+ if (appstatep != NULL)
+ *appstatep = state;
+ return(0);
+ } else
+ return(errno);
+
+}
+
+
+int
+proc_setappstate(int pid, int appstate)
+{
+ int state = appstate;
+
+ switch (state) {
+ case PROC_APPSTATE_NONE:
+ case PROC_APPSTATE_ACTIVE:
+ case PROC_APPSTATE_INACTIVE:
+ case PROC_APPSTATE_BACKGROUND:
+ case PROC_APPSTATE_NONUI:
+ break;
+ default:
+ return(EINVAL);
+ }
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (int *)&state, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+}
+
+int
+proc_devstatusnotify(int devicestatus)
+{
+ int state = devicestatus;
+
+ switch (devicestatus) {
+ case PROC_DEVSTATUS_SHORTTERM:
+ case PROC_DEVSTATUS_LONGTERM:
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_DEVSTATUS, (int *)&state, getpid(), (uint64_t)0) != -1) {
+ return(0);
+ } else
+ return(errno);
+
+}
+
+int
+proc_pidbind(int pid, uint64_t threadid, int bind)
+{
+ int state = bind;
+ pid_t passpid = pid;
+
+ switch (bind) {
+ case PROC_PIDBIND_CLEAR:
+ passpid = getpid(); /* ignore pid on clear */
+ break;
+ case PROC_PIDBIND_SET:
+ break;
+ default:
+ return(EINVAL);
+ }
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_PIDBIND, (int *)&state, passpid, threadid) != -1)
+ return(0);
+ else
+ return(errno);
+}
+
+#else /* TARGET_OS_EMBEDDED */
+
+int
+proc_clear_vmpressure(pid_t pid)
+{
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_STARVATION, PROC_POLICY_RS_VIRTUALMEM, NULL, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+}
+
+/* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */
+int
+proc_set_owner_vmpressure(void)
+{
+ int retval;
+
+ if ((retval = __proc_info(5, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1)
+ return(errno);
+
+ return(0);
+}
+
+/* disable the launch time backgroudn policy and restore the process to default group */
+int
+proc_disable_apptype(pid_t pid, int apptype)
+{
+ switch (apptype) {
+ case PROC_POLICY_OSX_APPTYPE_TAL:
+ case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
+ break;
+ default:
+ return(EINVAL);
+
+ }
+
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+
+}
+
+/* re-enable the launch time background policy if it had been disabled. */
+int
+proc_enable_apptype(pid_t pid, int apptype)
+{
+ switch (apptype) {
+ case PROC_POLICY_OSX_APPTYPE_TAL:
+ case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
+ break;
+ default:
+ return(EINVAL);
+
+ }
+
+ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
+ return(0);
+ else
+ return(errno);
+
+}
+
+#endif /* TARGET_OS_EMBEDDED */
+
/*
- * Copyright (c) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/proc_info.h>
+#include <Availability.h>
+
/*
* This header file contains private interfaces to obtain process information.
* These interfaces are subject to change in future releases.
__BEGIN_DECLS
-int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize);
/*!
@function proc_listpidspath
const char *path,
uint32_t pathflags,
void *buffer,
- int buffersize);
+ int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize);
-int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize);
-int proc_name(int pid, void * buffer, uint32_t buffersize);
-int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize);
-int proc_kmsgbuf(void * buffer, uint32_t buffersize);
-int proc_pidpath(int pid, void * buffer, uint32_t buffersize);
-int proc_libversion(int *major, int * minor);
+int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
+int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
+int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
+int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int proc_libversion(int *major, int * minor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
/*
* A process can use the following api to set its own process control
* state on resoure starvation. The argument can have one of the PROC_SETPC_XX values
#define PROC_SETPC_SUSPEND 2
#define PROC_SETPC_TERMINATE 3
+int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
int proc_setpcontrol(const int control);
+
__END_DECLS
#endif /*_LIBPROC_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _LIBPROC_INTERNALH_
+#define _LIBPROC_INTERNALH_
+
+#include <TargetConditionals.h>
+
+#include <sys/cdefs.h>
+#include <libproc.h>
+#include <sys/process_policy.h>
+
+__BEGIN_DECLS
+
+#if TARGET_OS_EMBEDDED
+
+#define PROC_SETCPU_ACTION_NONE 0
+#define PROC_SETCPU_ACTION_THROTTLE 1
+#define PROC_SETCPU_ACTION_SUSPEND 2
+#define PROC_SETCPU_ACTION_TERMINATE 3
+#define PROC_SETCPU_ACTION_NOTIFY 4
+
+int proc_setcpu_percentage(pid_t pid, int action, int percentage) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_5_0);
+int proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_5_0);
+int proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_5_0);
+int proc_clear_cpulimits(pid_t pid) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_5_0);
+
+#define PROC_APPSTATE_NONE 0
+#define PROC_APPSTATE_ACTIVE 1
+#define PROC_APPSTATE_BACKGROUND 2
+#define PROC_APPSTATE_NONUI 3
+#define PROC_APPSTATE_INACTIVE 4
+
+int proc_setappstate(int pid, int appstate);
+int proc_appstate(int pid, int * appstatep);
+
+#define PROC_DEVSTATUS_SHORTTERM 1
+#define PROC_DEVSTATUS_LONGTERM 2
+
+int proc_devstatusnotify(int devicestatus);
+
+#define PROC_PIDBIND_CLEAR 0
+#define PROC_PIDBIND_SET 1
+int proc_pidbind(int pid, uint64_t threadid, int bind);
+
+
+#else /* TARGET_OS_EMBEDDED */
+
+/* resume the process suspend due to low VM resource */
+int proc_clear_vmpressure(pid_t pid);
+/* set self as the one who is going to resume suspended processes due to low VM. Need to be root */
+int proc_set_owner_vmpressure(void);
+
+/*
+ * Resumes the backgrounded TAL or dashboard client. Only priv users can disable TAL apps.
+ * Valid apptype are PROC_POLICY_OSX_APPTYPE_DASHCLIENT and PROC_POLICY_OSX_APPTYPE_TAL.
+ * Returns 0 on success otherwise appropriate error code.
+ */
+int proc_disable_apptype(pid_t pid, int apptype);
+int proc_enable_apptype(pid_t pid, int apptype);
+
+#endif /* TARGET_OS_EMBEDDED */
+
+__END_DECLS
+
+#endif /* _LIBPROC_INTERNALH_ */
+
* 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.
static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_close.c,v 1.8 2002/03/22 21:52:00 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_close.c,v 1.10 2009/03/02 23:47:18 delphij Exp $");
#include "namespace.h"
#include <sys/param.h>
* RET_ERROR, RET_SUCCESS
*/
int
-__bt_close(dbp)
- DB *dbp;
+__bt_close(DB *dbp)
{
BTREE *t;
int fd;
* RET_SUCCESS, RET_ERROR.
*/
int
-__bt_sync(dbp, flags)
- const DB *dbp;
- u_int flags;
+__bt_sync(const DB *dbp, u_int flags)
{
BTREE *t;
int status;
* RET_ERROR, RET_SUCCESS
*/
static int
-bt_meta(t)
- BTREE *t;
+bt_meta(BTREE *t)
{
BTMETA m;
void *p;
* 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.
static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_conv.c,v 1.2 2002/03/21 22:46:25 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_conv.c,v 1.4 2009/03/02 23:47:18 delphij Exp $");
#include <sys/param.h>
* h: page to convert
*/
void
-__bt_pgin(t, pg, pp)
- void *t;
- pgno_t pg;
- void *pp;
+__bt_pgin(void *t, pgno_t pg, void *pp)
{
PAGE *h;
indx_t i, top;
}
void
-__bt_pgout(t, pg, pp)
- void *t;
- pgno_t pg;
- void *pp;
+__bt_pgout(void *t, pgno_t pg, void *pp)
{
PAGE *h;
indx_t i, top;
* p: page to convert
*/
static void
-mswap(pg)
- PAGE *pg;
+mswap(PAGE *pg)
{
char *p;
* 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.
static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_debug.c,v 1.3 2004/09/10 05:41:41 kuriyama Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_debug.c,v 1.6 2009/03/23 23:22:09 delphij Exp $");
#include <sys/param.h>
* dbp: pointer to the DB
*/
void
-__bt_dump(dbp)
- DB *dbp;
+__bt_dump(DB *dbp)
{
BTREE *t;
PAGE *h;
char *sep;
t = dbp->internal;
- (void)fprintf(stderr, "%s: pgsz %d",
+ (void)fprintf(stderr, "%s: pgsz %u",
F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
if (F_ISSET(t, R_RECNO))
(void)fprintf(stderr, " keys %u", t->bt_nrecs);
* h: pointer to the PAGE
*/
void
-__bt_dmpage(h)
- PAGE *h;
+__bt_dmpage(PAGE *h)
{
BTMETA *m;
char *sep;
* n: page number to dump.
*/
void
-__bt_dnpage(dbp, pgno)
- DB *dbp;
- pgno_t pgno;
+__bt_dnpage(DB *dbp, pgno_t pgno)
{
BTREE *t;
PAGE *h;
* h: pointer to the PAGE
*/
void
-__bt_dpage(h)
- PAGE *h;
+__bt_dpage(PAGE *h)
{
BINTERNAL *bi;
BLEAF *bl;
indx_t cur, top;
char *sep;
- (void)fprintf(stderr, " page %d: (", h->pgno);
+ (void)fprintf(stderr, " page %u: (", h->pgno);
#undef X
#define X(flag, name) \
if (h->flags & flag) { \
(void)fprintf(stderr, ")\n");
#undef X
- (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg);
+ (void)fprintf(stderr, "\tprev %2u next %2u", h->prevpg, h->nextpg);
if (h->flags & P_OVERFLOW)
return;
* dbp: pointer to the DB
*/
void
-__bt_stat(dbp)
- DB *dbp;
+__bt_stat(DB *dbp)
{
extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit;
extern u_long bt_sortsplit, bt_split;
(void)mpool_put(t->bt_mp, h, 0);
}
- (void)fprintf(stderr, "%d level%s with %ld keys",
+ (void)fprintf(stderr, "%d level%s with %lu keys",
levels, levels == 1 ? "" : "s", nkeys);
if (F_ISSET(t, R_RECNO))
- (void)fprintf(stderr, " (%d header count)", t->bt_nrecs);
+ (void)fprintf(stderr, " (%u header count)", t->bt_nrecs);
(void)fprintf(stderr,
- "\n%u pages (leaf %d, internal %d, overflow %d)\n",
+ "\n%u pages (leaf %u, internal %u, overflow %u)\n",
pinternal + pleaf + pcont, pleaf, pinternal, pcont);
- (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n",
+ (void)fprintf(stderr, "%lu cache hits, %lu cache misses\n",
bt_cache_hit, bt_cache_miss);
(void)fprintf(stderr, "%lu splits (%lu root splits, %lu sort splits)\n",
bt_split, bt_rootsplit, bt_sortsplit);
pleaf *= t->bt_psize - BTDATAOFF;
if (pleaf)
(void)fprintf(stderr,
- "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n",
+ "%.0f%% leaf fill (%lu bytes used, %lu bytes free)\n",
((double)(pleaf - lfree) / pleaf) * 100,
pleaf - lfree, lfree);
pinternal *= t->bt_psize - BTDATAOFF;
if (pinternal)
(void)fprintf(stderr,
- "%.0f%% internal fill (%ld bytes used, %ld bytes free\n",
+ "%.0f%% internal fill (%lu bytes used, %lu bytes free\n",
((double)(pinternal - ifree) / pinternal) * 100,
pinternal - ifree, ifree);
if (bt_pfxsaved)
* 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.
static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_delete.c,v 1.2 2002/03/21 22:46:25 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_delete.c,v 1.6 2009/03/04 00:58:04 delphij Exp $");
#include <sys/types.h>
* Return RET_SPECIAL if the key is not found.
*/
int
-__bt_delete(dbp, key, flags)
- const DB *dbp;
- const DBT *key;
- u_int flags;
+__bt_delete(const DB *dbp, const DBT *key, u_int flags)
{
BTREE *t;
CURSOR *c;
* 0 on success, 1 on failure
*/
static int
-__bt_stkacq(t, hp, c)
- BTREE *t;
- PAGE **hp;
- CURSOR *c;
+__bt_stkacq(BTREE *t, PAGE **hp, CURSOR *c)
{
BINTERNAL *bi;
EPG *e;
EPGNO *parent;
PAGE *h;
- indx_t index;
+ indx_t idx;
pgno_t pgno;
recno_t nextpg, prevpg;
int exact, level;
-
+
/*
* Find the first occurrence of the key in the tree. Toss the
* currently locked page so we don't hit an already-locked page.
/* Move to the next index. */
if (parent->index != NEXTINDEX(h) - 1) {
- index = parent->index + 1;
- BT_PUSH(t, h->pgno, index);
+ idx = parent->index + 1;
+ BT_PUSH(t, h->pgno, idx);
break;
}
mpool_put(t->bt_mp, h, 0);
/* Restore the stack. */
while (level--) {
/* Push the next level down onto the stack. */
- bi = GETBINTERNAL(h, index);
+ bi = GETBINTERNAL(h, idx);
pgno = bi->pgno;
BT_PUSH(t, pgno, 0);
/* Get the next level down. */
if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
return (1);
- index = 0;
+ idx = 0;
}
mpool_put(t->bt_mp, h, 0);
if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
/* Move to the next index. */
if (parent->index != 0) {
- index = parent->index - 1;
- BT_PUSH(t, h->pgno, index);
+ idx = parent->index - 1;
+ BT_PUSH(t, h->pgno, idx);
break;
}
mpool_put(t->bt_mp, h, 0);
/* Restore the stack. */
while (level--) {
/* Push the next level down onto the stack. */
- bi = GETBINTERNAL(h, index);
+ bi = GETBINTERNAL(h, idx);
pgno = bi->pgno;
/* Lose the currently pinned page. */
if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
return (1);
- index = NEXTINDEX(h) - 1;
- BT_PUSH(t, pgno, index);
+ idx = NEXTINDEX(h) - 1;
+ BT_PUSH(t, pgno, idx);
}
mpool_put(t->bt_mp, h, 0);
if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
return (1);
}
-
+
ret: mpool_put(t->bt_mp, h, 0);
return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
*/
static int
-__bt_bdelete(t, key)
- BTREE *t;
- const DBT *key;
+__bt_bdelete(BTREE *t, const DBT *key)
{
EPG *e;
PAGE *h;
* mpool_put's the page
*/
static int
-__bt_pdelete(t, h)
- BTREE *t;
- PAGE *h;
+__bt_pdelete(BTREE *t, PAGE *h)
{
BINTERNAL *bi;
PAGE *pg;
EPGNO *parent;
- indx_t cnt, index, *ip, offset;
+ indx_t cnt, idx, *ip, offset;
u_int32_t nksize;
char *from;
/* Get the parent page. */
if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
return (RET_ERROR);
-
- index = parent->index;
- bi = GETBINTERNAL(pg, index);
+
+ idx = parent->index;
+ bi = GETBINTERNAL(pg, idx);
/* Free any overflow pages. */
if (bi->flags & P_BIGKEY &&
* root page. If it's the rootpage, turn it back into an empty
* leaf page.
*/
- if (NEXTINDEX(pg) == 1)
+ if (NEXTINDEX(pg) == 1) {
if (pg->pgno == P_ROOT) {
pg->lower = BTDATAOFF;
pg->upper = t->bt_psize;
return (RET_ERROR);
continue;
}
- else {
+ } else {
/* Pack remaining key items at the end of the page. */
nksize = NBINTERNAL(bi->ksize);
from = (char *)pg + pg->upper;
pg->upper += nksize;
/* Adjust indices' offsets, shift the indices down. */
- offset = pg->linp[index];
- for (cnt = index, ip = &pg->linp[0]; cnt--; ++ip)
+ offset = pg->linp[idx];
+ for (cnt = idx, ip = &pg->linp[0]; cnt--; ++ip)
if (ip[0] < offset)
ip[0] += nksize;
- for (cnt = NEXTINDEX(pg) - index; --cnt; ++ip)
+ for (cnt = NEXTINDEX(pg) - idx; --cnt; ++ip)
ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
pg->lower -= sizeof(indx_t);
}
* t: tree
* key: referenced key
* h: page
- * index: index on page to delete
+ * idx: index on page to delete
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*/
int
-__bt_dleaf(t, key, h, index)
- BTREE *t;
- const DBT *key;
- PAGE *h;
- u_int index;
+__bt_dleaf(BTREE *t, const DBT *key, PAGE *h, u_int idx)
{
BLEAF *bl;
indx_t cnt, *ip, offset;
/* If this record is referenced by the cursor, delete the cursor. */
if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
!F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
- t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == index &&
- __bt_curdel(t, key, h, index))
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == idx &&
+ __bt_curdel(t, key, h, idx))
return (RET_ERROR);
/* If the entry uses overflow pages, make them available for reuse. */
- to = bl = GETBLEAF(h, index);
+ to = bl = GETBLEAF(h, idx);
if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
return (RET_ERROR);
if (bl->flags & P_BIGDATA &&
h->upper += nbytes;
/* Adjust the indices' offsets, shift the indices down. */
- offset = h->linp[index];
- for (cnt = index, ip = &h->linp[0]; cnt--; ++ip)
+ offset = h->linp[idx];
+ for (cnt = idx, ip = &h->linp[0]; cnt--; ++ip)
if (ip[0] < offset)
ip[0] += nbytes;
- for (cnt = NEXTINDEX(h) - index; --cnt; ++ip)
+ for (cnt = NEXTINDEX(h) - idx; --cnt; ++ip)
ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
h->lower -= sizeof(indx_t);
/* If the cursor is on this page, adjust it as necessary. */
if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
!F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
- t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > index)
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > idx)
--t->bt_cursor.pg.index;
return (RET_SUCCESS);
* t: tree
* key: referenced key (or NULL)
* h: page
- * index: index on page to delete
+ * idx: index on page to delete
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*/
static int
-__bt_curdel(t, key, h, index)
- BTREE *t;
- const DBT *key;
- PAGE *h;
- u_int index;
+__bt_curdel(BTREE *t, const DBT *key, PAGE *h, u_int idx)
{
CURSOR *c;
EPG e;
*/
if (key == NULL) {
e.page = h;
- e.index = index;
+ e.index = idx;
if ((status = __bt_ret(t, &e,
&c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
return (status);
key = &c->key;
}
/* Check previous key, if not at the beginning of the page. */
- if (index > 0) {
+ if (idx > 0) {
e.page = h;
- e.index = index - 1;
+ e.index = idx - 1;
if (__bt_cmp(t, key, &e) == 0) {
F_SET(c, CURS_BEFORE);
goto dup2;
}
}
/* Check next key, if not at the end of the page. */
- if (index < NEXTINDEX(h) - 1) {
+ if (idx < NEXTINDEX(h) - 1) {
e.page = h;
- e.index = index + 1;
+ e.index = idx + 1;
if (__bt_cmp(t, key, &e) == 0) {
F_SET(c, CURS_AFTER);
goto dup2;
}
}
/* Check previous key if at the beginning of the page. */
- if (index == 0 && h->prevpg != P_INVALID) {
+ if (idx == 0 && h->prevpg != P_INVALID) {
if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
return (RET_ERROR);
e.page = pg;
mpool_put(t->bt_mp, pg, 0);
}
/* Check next key if at the end of the page. */
- if (index == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
+ if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
return (RET_ERROR);
e.page = pg;
}
}
e.page = h;
- e.index = index;
+ e.index = idx;
if (curcopy || (status =
__bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
F_SET(c, CURS_ACQUIRE);
* h: page to be deleted
*/
static int
-__bt_relink(t, h)
- BTREE *t;
- PAGE *h;
+__bt_relink(BTREE *t, PAGE *h)
{
PAGE *pg;
* 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.
static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_get.c,v 1.2 2002/03/22 21:52:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_get.c,v 1.4 2009/03/02 23:47:18 delphij Exp $");
#include <sys/types.h>
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
*/
int
-__bt_get(dbp, key, data, flags)
- const DB *dbp;
- const DBT *key;
- DBT *data;
- u_int flags;
+__bt_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)
{
BTREE *t;
EPG *e;
* 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.
static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_open.c,v 1.11 2002/03/22 21:52:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_open.c,v 1.17 2009/03/28 05:57:27 delphij Exp $");
/*
* Implementation of btree access method for 4.4BSD.
*
*/
DB *
-__bt_open(fname, flags, mode, openinfo, dflags)
- const char *fname;
- int flags, mode, dflags;
- const BTREEINFO *openinfo;
+__bt_open(const char *fname, int flags, int mode, const BTREEINFO *openinfo, int dflags)
{
struct stat sb;
BTMETA m;
DB *dbp;
pgno_t ncache;
ssize_t nr;
- int machine_lorder;
+ int machine_lorder, saved_errno;
t = NULL;
goto einval;
/* Allocate and initialize DB and BTREE structures. */
- if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL)
+ if ((t = (BTREE *)calloc(1, sizeof(BTREE))) == NULL)
goto err;
- memset(t, 0, sizeof(BTREE));
t->bt_fd = -1; /* Don't close unopened fd on error. */
t->bt_lorder = b.lorder;
t->bt_order = NOT;
t->bt_pfx = b.prefix;
t->bt_rfd = -1;
- if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL)
+ if ((t->bt_dbp = dbp = (DB *)calloc(1, sizeof(DB))) == NULL)
goto err;
- memset(t->bt_dbp, 0, sizeof(DB));
if (t->bt_lorder != machine_lorder)
F_SET(t, B_NEEDSWAP);
default:
goto einval;
}
-
+
if ((t->bt_fd = _open(fname, flags, mode)) < 0)
goto err;
eftype: errno = EFTYPE;
goto err;
-err: if (t) {
+err: saved_errno = errno;
+ if (t) {
if (t->bt_dbp)
free(t->bt_dbp);
if (t->bt_fd != -1)
(void)_close(t->bt_fd);
free(t);
}
+ errno = saved_errno;
return (NULL);
}
* RET_ERROR, RET_SUCCESS
*/
static int
-nroot(t)
- BTREE *t;
+nroot(BTREE *t)
{
PAGE *meta, *root;
pgno_t npg;
}
static int
-tmp()
+tmp(void)
{
sigset_t set, oset;
- int fd;
+ int fd, len;
char *envtmp = NULL;
char path[MAXPATHLEN];
if (issetugid() == 0)
envtmp = getenv("TMPDIR");
- (void)snprintf(path,
+ len = snprintf(path,
sizeof(path), "%s/bt.XXXXXXXXXX", envtmp ? envtmp : "/tmp");
+ if (len < 0 || len >= (int)sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return(-1);
+ }
(void)sigfillset(&set);
(void)_sigprocmask(SIG_BLOCK, &set, &oset);
}
static int
-byteorder()
+byteorder(void)
{
u_int32_t x;
u_char *p;
}
int
-__bt_fd(dbp)
- const DB *dbp;
+__bt_fd(const DB *dbp)
{
BTREE *t;
* 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.
static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_overflow.c,v 1.3 2002/03/22 21:52:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_overflow.c,v 1.6 2009/03/05 00:57:01 delphij Exp $");
#include <sys/param.h>
* RET_ERROR, RET_SUCCESS
*/
int
-__ovfl_get(t, p, ssz, buf, bufsz)
- BTREE *t;
- void *p;
- size_t *ssz;
- void **buf;
- size_t *bufsz;
+__ovfl_get(BTREE *t, void *p, size_t *ssz, void **buf, size_t *bufsz)
{
PAGE *h;
pgno_t pg;
#endif
/* Make the buffer bigger as necessary. */
if (*bufsz < sz) {
- *buf = (char *)(*buf == NULL ? malloc(sz) : reallocf(*buf, sz));
+ *buf = reallocf(*buf, sz);
if (*buf == NULL)
return (RET_ERROR);
*bufsz = sz;
* RET_ERROR, RET_SUCCESS
*/
int
-__ovfl_put(t, dbt, pg)
- BTREE *t;
- const DBT *dbt;
- pgno_t *pg;
+__ovfl_put(BTREE *t, const DBT *dbt, pgno_t *pg)
{
PAGE *h, *last;
void *p;
* RET_ERROR, RET_SUCCESS
*/
int
-__ovfl_delete(t, p)
- BTREE *t;
- void *p;
+__ovfl_delete(BTREE *t, void *p)
{
PAGE *h;
pgno_t pg;
---- bt_overflow.c.orig 2008-09-07 11:37:54.000000000 -0700
-+++ bt_overflow.c 2008-09-07 12:00:45.000000000 -0700
-@@ -97,7 +97,7 @@ __ovfl_get(t, p, ssz, buf, bufsz)
+--- bt_overflow.c.orig 2009-11-06 12:39:34.000000000 -0800
++++ bt_overflow.c 2009-11-06 12:40:06.000000000 -0800
+@@ -88,7 +88,7 @@ __ovfl_get(BTREE *t, void *p, size_t *ss
#ifdef DEBUG
if (pg == P_INVALID || sz == 0)
#endif
/* Make the buffer bigger as necessary. */
if (*bufsz < sz) {
-@@ -206,7 +206,7 @@ __ovfl_delete(t, p)
+@@ -192,7 +192,7 @@ __ovfl_delete(BTREE *t, void *p)
#ifdef DEBUG
if (pg == P_INVALID || sz == 0)
* 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.
static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_page.c,v 1.3 2002/03/22 21:52:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_page.c,v 1.5 2009/03/02 23:47:18 delphij Exp $");
#include <sys/types.h>
* mpool_put's the page.
*/
int
-__bt_free(t, h)
- BTREE *t;
- PAGE *h;
+__bt_free(BTREE *t, PAGE *h)
{
/* Insert the page at the head of the free list. */
h->prevpg = P_INVALID;
* Pointer to a page, NULL on error.
*/
PAGE *
-__bt_new(t, npg)
- BTREE *t;
- pgno_t *npg;
+__bt_new(BTREE *t, pgno_t *npg)
{
PAGE *h;
* 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.
static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_put.c,v 1.4 2003/05/30 11:05:08 tmm Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_put.c,v 1.9 2009/03/28 05:45:29 delphij Exp $");
#include <sys/types.h>
* tree and R_NOOVERWRITE specified.
*/
int
-__bt_put(dbp, key, data, flags)
- const DB *dbp;
- DBT *key;
- const DBT *data;
- u_int flags;
+__bt_put(const DB *dbp, DBT *key, const DBT *data, u_int flags)
{
BTREE *t;
DBT tkey, tdata;
EPG *e;
PAGE *h;
- indx_t index, nxtindex;
+ indx_t idx, nxtindex;
pgno_t pg;
u_int32_t nbytes, tmp;
int dflags, exact, status;
*/
if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
!F_ISSET(&t->bt_cursor,
- CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+ CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
break;
/* FALLTHROUGH */
default:
if (flags == R_CURSOR) {
if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
return (RET_ERROR);
- index = t->bt_cursor.pg.index;
+ idx = t->bt_cursor.pg.index;
goto delete;
}
if ((e = __bt_search(t, key, &exact)) == NULL)
return (RET_ERROR);
h = e->page;
- index = e->index;
+ idx = e->index;
/*
* Add the key/data pair to the tree. If an identical key is already
* Note, the delete may empty the page, so we need to put a
* new entry into the page immediately.
*/
-delete: if (__bt_dleaf(t, key, h, index) == RET_ERROR) {
+delete: if (__bt_dleaf(t, key, h, idx) == RET_ERROR) {
mpool_put(t->bt_mp, h, 0);
return (RET_ERROR);
}
* into the offset array, shift the pointers up.
*/
nbytes = NBLEAFDBT(key->size, data->size);
- if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
if ((status = __bt_split(t, h, key,
- data, dflags, nbytes, index)) != RET_SUCCESS)
+ data, dflags, nbytes, idx)) != RET_SUCCESS)
return (status);
goto success;
}
- if (index < (nxtindex = NEXTINDEX(h)))
- memmove(h->linp + index + 1, h->linp + index,
- (nxtindex - index) * sizeof(indx_t));
+ if (idx < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + idx + 1, h->linp + idx,
+ (nxtindex - idx) * sizeof(indx_t));
h->lower += sizeof(indx_t);
- h->linp[index] = h->upper -= nbytes;
+ h->linp[idx] = h->upper -= nbytes;
dest = (char *)h + h->upper;
WR_BLEAF(dest, key, data, dflags);
/* If the cursor is on this page, adjust it as necessary. */
if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
!F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
- t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= index)
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= idx)
++t->bt_cursor.pg.index;
if (t->bt_order == NOT) {
if (h->nextpg == P_INVALID) {
- if (index == NEXTINDEX(h) - 1) {
+ if (idx == NEXTINDEX(h) - 1) {
t->bt_order = FORWARD;
- t->bt_last.index = index;
+ t->bt_last.index = idx;
t->bt_last.pgno = h->pgno;
}
} else if (h->prevpg == P_INVALID) {
- if (index == 0) {
+ if (idx == 0) {
t->bt_order = BACK;
t->bt_last.index = 0;
t->bt_last.pgno = h->pgno;
* key: key to insert
*
* Returns:
- * EPG for new record or NULL if not found.
+ * EPG for new record or NULL if not found.
*/
static EPG *
-bt_fast(t, key, data, exactp)
- BTREE *t;
- const DBT *key, *data;
- int *exactp;
+bt_fast(BTREE *t, const DBT *key, const DBT *data, int *exactp)
{
PAGE *h;
u_int32_t nbytes;
* have to search to get split stack.
*/
nbytes = NBLEAFDBT(key->size, data->size);
- if (h->upper - h->lower < nbytes + sizeof(indx_t))
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t))
goto miss;
if (t->bt_order == FORWARD) {
* 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.
static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_search.c,v 1.2 2002/03/21 22:46:25 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_search.c,v 1.5 2009/03/03 02:16:12 delphij Exp $");
#include <sys/types.h>
* the bt_cur field of the tree. A pointer to the field is returned.
*/
EPG *
-__bt_search(t, key, exactp)
- BTREE *t;
- const DBT *key;
- int *exactp;
+__bt_search(BTREE *t, const DBT *key, int *exactp)
{
PAGE *h;
- indx_t base, index, lim;
+ indx_t base, idx, lim;
pgno_t pg;
int cmp;
/* Do a binary search on the current page. */
t->bt_cur.page = h;
for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
- t->bt_cur.index = index = base + (lim >> 1);
+ t->bt_cur.index = idx = base + (lim >> 1);
if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
if (h->flags & P_BLEAF) {
*exactp = 1;
goto next;
}
if (cmp > 0) {
- base = index + 1;
+ base = idx + 1;
--lim;
}
}
* be a parent page for the key. If a split later occurs, the
* inserted page will be to the right of the saved page.
*/
- index = base ? base - 1 : base;
+ idx = base ? base - 1 : base;
-next: BT_PUSH(t, h->pgno, index);
- pg = GETBINTERNAL(h, index)->pgno;
+next: BT_PUSH(t, h->pgno, idx);
+ pg = GETBINTERNAL(h, idx)->pgno;
mpool_put(t->bt_mp, h, 0);
}
}
* If an exact match found.
*/
static int
-__bt_snext(t, h, key, exactp)
- BTREE *t;
- PAGE *h;
- const DBT *key;
- int *exactp;
+__bt_snext(BTREE *t, PAGE *h, const DBT *key, int *exactp)
{
EPG e;
* If an exact match found.
*/
static int
-__bt_sprev(t, h, key, exactp)
- BTREE *t;
- PAGE *h;
- const DBT *key;
- int *exactp;
+__bt_sprev(BTREE *t, PAGE *h, const DBT *key, int *exactp)
{
EPG e;
* 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.
static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_seq.c,v 1.3 2002/03/21 22:46:25 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_seq.c,v 1.7 2009/03/04 00:58:04 delphij Exp $");
#include <sys/types.h>
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
int
-__bt_seq(dbp, key, data, flags)
- const DB *dbp;
- DBT *key, *data;
- u_int flags;
+__bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
{
BTREE *t;
EPG e;
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
static int
-__bt_seqset(t, ep, key, flags)
- BTREE *t;
- EPG *ep;
- DBT *key;
- int flags;
+__bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags)
{
PAGE *h;
pgno_t pg;
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
static int
-__bt_seqadv(t, ep, flags)
- BTREE *t;
- EPG *ep;
- int flags;
+__bt_seqadv(BTREE *t, EPG *ep, int flags)
{
CURSOR *c;
PAGE *h;
- indx_t index;
+ indx_t idx;
pgno_t pg;
int exact;
return (RET_ERROR);
/*
- * Find the next/previous record in the tree and point the cursor at
+ * Find the next/previous record in the tree and point the cursor at
* it. The cursor may not be moved until a new key has been found.
*/
switch (flags) {
*/
if (F_ISSET(c, CURS_AFTER))
goto usecurrent;
- index = c->pg.index;
- if (++index == NEXTINDEX(h)) {
+ idx = c->pg.index;
+ if (++idx == NEXTINDEX(h)) {
pg = h->nextpg;
mpool_put(t->bt_mp, h, 0);
if (pg == P_INVALID)
return (RET_SPECIAL);
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
return (RET_ERROR);
- index = 0;
+ idx = 0;
}
break;
case R_PREV: /* Previous record. */
ep->index = c->pg.index;
return (RET_SUCCESS);
}
- index = c->pg.index;
- if (index == 0) {
+ idx = c->pg.index;
+ if (idx == 0) {
pg = h->prevpg;
mpool_put(t->bt_mp, h, 0);
if (pg == P_INVALID)
return (RET_SPECIAL);
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
return (RET_ERROR);
- index = NEXTINDEX(h) - 1;
+ idx = NEXTINDEX(h) - 1;
} else
- --index;
+ --idx;
break;
}
ep->page = h;
- ep->index = index;
+ ep->index = idx;
return (RET_SUCCESS);
}
* or RET_SPECIAL if no such key exists.
*/
static int
-__bt_first(t, key, erval, exactp)
- BTREE *t;
- const DBT *key;
- EPG *erval;
- int *exactp;
+__bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp)
{
PAGE *h;
EPG *ep, save;
*erval = *ep;
return (RET_SUCCESS);
}
-
+
/*
* Walk backwards, as long as the entry matches and there are
* keys left in the tree. Save a copy of each match in case
* Parameters:
* t: the tree
* pgno: page number
- * index: page index
+ * idx: page index
*/
void
-__bt_setcur(t, pgno, index)
- BTREE *t;
- pgno_t pgno;
- u_int index;
+__bt_setcur(BTREE *t, pgno_t pgno, u_int idx)
{
/* Lose any already deleted key. */
if (t->bt_cursor.key.data != NULL) {
/* Update the cursor. */
t->bt_cursor.pg.pgno = pgno;
- t->bt_cursor.pg.index = index;
+ t->bt_cursor.pg.index = idx;
F_SET(&t->bt_cursor, CURS_INIT);
}
---- bt_seq.c.orig 2008-10-09 11:40:48.000000000 -0700
-+++ bt_seq.c 2008-10-09 11:43:28.000000000 -0700
-@@ -387,18 +387,19 @@ __bt_first(t, key, erval, exactp)
+--- bt_seq.c.orig 2009-11-06 12:39:34.000000000 -0800
++++ bt_seq.c 2009-11-06 12:40:06.000000000 -0800
+@@ -369,18 +369,19 @@ __bt_first(BTREE *t, const DBT *key, EPG
* occurs.
*/
if (ep->index == 0) {
* 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.
static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_split.c,v 1.7 2004/09/13 22:07:24 kuriyama Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_split.c,v 1.12 2009/03/28 05:45:29 delphij Exp $");
#include <sys/types.h>
#include "btree.h"
static int bt_broot(BTREE *, PAGE *, PAGE *, PAGE *);
-static PAGE *bt_page (BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static PAGE *bt_page(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
static int bt_preserve(BTREE *, pgno_t);
-static PAGE *bt_psplit (BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
-static PAGE *bt_root (BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static PAGE *bt_psplit(BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
+static PAGE *bt_root(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
static int bt_rroot(BTREE *, PAGE *, PAGE *, PAGE *);
static recno_t rec_total(PAGE *);
* RET_ERROR, RET_SUCCESS
*/
int
-__bt_split(t, sp, key, data, flags, ilen, argskip)
- BTREE *t;
- PAGE *sp;
- const DBT *key, *data;
- int flags;
- size_t ilen;
- u_int32_t argskip;
+__bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, int flags,
+ size_t ilen, u_int32_t argskip)
{
BINTERNAL *bi;
BLEAF *bl, *tbl;
if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
goto err2;
- /*
+ /*
* The new key goes ONE AFTER the index, because the split
* was to the right.
*/
}
/* Split the parent page if necessary or shift the indices. */
- if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
sp = h;
h = h->pgno == P_ROOT ?
bt_root(t, h, &l, &r, &skip, nbytes) :
* Pointer to page in which to insert or NULL on error.
*/
static PAGE *
-bt_page(t, h, lp, rp, skip, ilen)
- BTREE *t;
- PAGE *h, **lp, **rp;
- indx_t *skip;
- size_t ilen;
+bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
{
PAGE *l, *r, *tp;
pgno_t npg;
}
/* Put the new left page for the split into place. */
- if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) {
+ if ((l = (PAGE *)calloc(1, t->bt_psize)) == NULL) {
mpool_put(t->bt_mp, r, 0);
return (NULL);
}
-#ifdef PURIFY
- memset(l, 0xff, t->bt_psize);
-#endif
l->pgno = h->pgno;
l->nextpg = r->pgno;
l->prevpg = h->prevpg;
* Pointer to page in which to insert or NULL on error.
*/
static PAGE *
-bt_root(t, h, lp, rp, skip, ilen)
- BTREE *t;
- PAGE *h, **lp, **rp;
- indx_t *skip;
- size_t ilen;
+bt_root(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
{
PAGE *l, *r, *tp;
pgno_t lnpg, rnpg;
* RET_ERROR, RET_SUCCESS
*/
static int
-bt_rroot(t, h, l, r)
- BTREE *t;
- PAGE *h, *l, *r;
+bt_rroot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
{
char *dest;
* RET_ERROR, RET_SUCCESS
*/
static int
-bt_broot(t, h, l, r)
- BTREE *t;
- PAGE *h, *l, *r;
+bt_broot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
{
BINTERNAL *bi;
BLEAF *bl;
* Pointer to page in which to insert.
*/
static PAGE *
-bt_psplit(t, h, l, r, pskip, ilen)
- BTREE *t;
- PAGE *h, *l, *r;
- indx_t *pskip;
- size_t ilen;
+bt_psplit(BTREE *t, PAGE *h, PAGE *l, PAGE *r, indx_t *pskip, size_t ilen)
{
BINTERNAL *bi;
BLEAF *bl;
* RET_SUCCESS, RET_ERROR.
*/
static int
-bt_preserve(t, pg)
- BTREE *t;
- pgno_t pg;
+bt_preserve(BTREE *t, pgno_t pg)
{
PAGE *h;
* all the way back to bt_split/bt_rroot and it's not very clean.
*/
static recno_t
-rec_total(h)
- PAGE *h;
+rec_total(PAGE *h)
{
recno_t recs;
indx_t nxt, top;
---- bt_split.c.orig 2008-09-07 11:37:54.000000000 -0700
-+++ bt_split.c 2008-09-07 12:29:24.000000000 -0700
-@@ -210,7 +210,7 @@ __bt_split(t, sp, key, data, flags, ilen
+--- bt_split.c.orig 2009-11-06 12:39:34.000000000 -0800
++++ bt_split.c 2009-11-06 12:40:06.000000000 -0800
+@@ -201,7 +201,7 @@ __bt_split(BTREE *t, PAGE *sp, const DBT
nbytes = NRINTERNAL;
break;
default:
}
/* Split the parent page if necessary or shift the indices. */
-@@ -285,7 +285,7 @@ __bt_split(t, sp, key, data, flags, ilen
+@@ -276,7 +276,7 @@ __bt_split(BTREE *t, PAGE *sp, const DBT
((RINTERNAL *)dest)->pgno = rchild->pgno;
break;
default:
}
/* Unpin the held pages. */
-@@ -580,7 +580,7 @@ bt_broot(t, h, l, r)
+@@ -556,7 +556,7 @@ bt_broot(BTREE *t, PAGE *h, PAGE *l, PAG
((BINTERNAL *)dest)->pgno = r->pgno;
break;
default:
}
/* There are two keys on the page. */
-@@ -663,7 +663,7 @@ bt_psplit(t, h, l, r, pskip, ilen)
+@@ -635,7 +635,7 @@ bt_psplit(BTREE *t, PAGE *h, PAGE *l, PA
isbigkey = 0;
break;
default:
}
/*
-@@ -756,7 +756,7 @@ bt_psplit(t, h, l, r, pskip, ilen)
+@@ -728,7 +728,7 @@ bt_psplit(BTREE *t, PAGE *h, PAGE *l, PA
nbytes = NRLEAF(rl);
break;
default:
* 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.
static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_utils.c,v 1.3 2003/01/01 18:48:42 schweikh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_utils.c,v 1.7 2009/03/05 00:57:01 delphij Exp $");
#include <sys/param.h>
* RET_SUCCESS, RET_ERROR.
*/
int
-__bt_ret(t, e, key, rkey, data, rdata, copy)
- BTREE *t;
- EPG *e;
- DBT *key, *rkey, *data, *rdata;
- int copy;
+__bt_ret(BTREE *t, EPG *e, DBT *key, DBT *rkey, DBT *data, DBT *rdata, int copy)
{
BLEAF *bl;
void *p;
key->data = rkey->data;
} else if (copy || F_ISSET(t, B_DB_LOCK)) {
if (bl->ksize > rkey->size) {
- p = (void *)(rkey->data == NULL ?
- malloc(bl->ksize) : realloc(rkey->data, bl->ksize));
+ p = realloc(rkey->data, bl->ksize);
if (p == NULL)
return (RET_ERROR);
rkey->data = p;
} else if (copy || F_ISSET(t, B_DB_LOCK)) {
/* Use +1 in case the first record retrieved is 0 length. */
if (bl->dsize + 1 > rdata->size) {
- p = (void *)(rdata->data == NULL ?
- malloc(bl->dsize + 1) :
- realloc(rdata->data, bl->dsize + 1));
+ p = realloc(rdata->data, bl->dsize + 1);
if (p == NULL)
return (RET_ERROR);
rdata->data = p;
* > 0 if k1 is > record
*/
int
-__bt_cmp(t, k1, e)
- BTREE *t;
- const DBT *k1;
- EPG *e;
+__bt_cmp(BTREE *t, const DBT *k1, EPG *e)
{
BINTERNAL *bi;
BLEAF *bl;
*
* Parameters:
* a: DBT #1
- * b: DBT #2
+ * b: DBT #2
*
* Returns:
* < 0 if a is < b
* > 0 if a is > b
*/
int
-__bt_defcmp(a, b)
- const DBT *a, *b;
+__bt_defcmp(const DBT *a, const DBT *b)
{
size_t len;
u_char *p1, *p2;
*
* Parameters:
* a: DBT #1
- * b: DBT #2
+ * b: DBT #2
*
* Returns:
* Number of bytes needed to distinguish b from a.
*/
size_t
-__bt_defpfx(a, b)
- const DBT *a, *b;
+__bt_defpfx(const DBT *a, const DBT *b)
{
u_char *p1, *p2;
size_t cnt, len;
* 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.
* SUCH DAMAGE.
*
* @(#)btree.h 8.11 (Berkeley) 8/17/94
- * $FreeBSD: src/lib/libc/db/btree/btree.h,v 1.3 2002/03/22 23:41:40 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/btree/btree.h,v 1.5 2009/03/04 00:58:04 delphij Exp $
*/
/* Macros to set/clear/test flags. */
CURSOR bt_cursor; /* cursor */
#define BT_PUSH(t, p, i) { \
- t->bt_sp->pgno = p; \
- t->bt_sp->index = i; \
+ t->bt_sp->pgno = p; \
+ t->bt_sp->index = i; \
++t->bt_sp; \
}
#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
---- btree.h.orig Fri Mar 22 15:41:40 2002
-+++ btree.h Sat Oct 18 18:14:05 2003
-@@ -381,4 +381,4 @@
+--- btree.h.orig 2009-11-06 12:39:34.000000000 -0800
++++ btree.h 2009-11-06 12:40:06.000000000 -0800
+@@ -377,4 +377,4 @@ typedef struct _btree {
u_int32_t flags;
} BTREE;
* 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.
* SUCH DAMAGE.
*
* @(#)extern.h 8.10 (Berkeley) 7/20/94
- * $FreeBSD: src/lib/libc/db/btree/extern.h,v 1.3 2002/03/22 09:18:22 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/btree/extern.h,v 1.4 2007/01/09 00:27:50 imp Exp $
*/
int __bt_close(DB *);
* 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.
static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_overflow.c,v 1.3 2002/03/22 21:52:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_overflow.c,v 1.6 2009/03/05 00:57:01 delphij Exp $");
#include <sys/param.h>
* RET_ERROR, RET_SUCCESS
*/
int
-__ovfl_get(t, p, ssz, buf, bufsz)
- BTREE *t;
- void *p;
- size_t *ssz;
- void **buf;
- size_t *bufsz;
+__ovfl_get(BTREE *t, void *p, size_t *ssz, void **buf, size_t *bufsz)
{
PAGE *h;
pgno_t pg;
#endif
/* Make the buffer bigger as necessary. */
if (*bufsz < sz) {
- *buf = (char *)(*buf == NULL ? malloc(sz) : reallocf(*buf, sz));
+ *buf = reallocf(*buf, sz);
if (*buf == NULL)
return (RET_ERROR);
*bufsz = sz;
* RET_ERROR, RET_SUCCESS
*/
int
-__ovfl_put(t, dbt, pg)
- BTREE *t;
- const DBT *dbt;
- pgno_t *pg;
+__ovfl_put(BTREE *t, const DBT *dbt, pgno_t *pg)
{
PAGE *h, *last;
void *p;
* RET_ERROR, RET_SUCCESS
*/
int
-__ovfl_delete(t, p)
- BTREE *t;
- void *p;
+__ovfl_delete(BTREE *t, void *p)
{
PAGE *h;
pgno_t pg;
* 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.
static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_seq.c,v 1.3 2002/03/21 22:46:25 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_seq.c,v 1.7 2009/03/04 00:58:04 delphij Exp $");
#include <sys/types.h>
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
int
-__bt_seq(dbp, key, data, flags)
- const DB *dbp;
- DBT *key, *data;
- u_int flags;
+__bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
{
BTREE *t;
EPG e;
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
static int
-__bt_seqset(t, ep, key, flags)
- BTREE *t;
- EPG *ep;
- DBT *key;
- int flags;
+__bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags)
{
PAGE *h;
pgno_t pg;
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
static int
-__bt_seqadv(t, ep, flags)
- BTREE *t;
- EPG *ep;
- int flags;
+__bt_seqadv(BTREE *t, EPG *ep, int flags)
{
CURSOR *c;
PAGE *h;
- indx_t index;
+ indx_t idx;
pgno_t pg;
int exact;
return (RET_ERROR);
/*
- * Find the next/previous record in the tree and point the cursor at
+ * Find the next/previous record in the tree and point the cursor at
* it. The cursor may not be moved until a new key has been found.
*/
switch (flags) {
*/
if (F_ISSET(c, CURS_AFTER))
goto usecurrent;
- index = c->pg.index;
- if (++index == NEXTINDEX(h)) {
+ idx = c->pg.index;
+ if (++idx == NEXTINDEX(h)) {
pg = h->nextpg;
mpool_put(t->bt_mp, h, 0);
if (pg == P_INVALID)
return (RET_SPECIAL);
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
return (RET_ERROR);
- index = 0;
+ idx = 0;
}
break;
case R_PREV: /* Previous record. */
ep->index = c->pg.index;
return (RET_SUCCESS);
}
- index = c->pg.index;
- if (index == 0) {
+ idx = c->pg.index;
+ if (idx == 0) {
pg = h->prevpg;
mpool_put(t->bt_mp, h, 0);
if (pg == P_INVALID)
return (RET_SPECIAL);
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
return (RET_ERROR);
- index = NEXTINDEX(h) - 1;
+ idx = NEXTINDEX(h) - 1;
} else
- --index;
+ --idx;
break;
}
ep->page = h;
- ep->index = index;
+ ep->index = idx;
return (RET_SUCCESS);
}
* or RET_SPECIAL if no such key exists.
*/
static int
-__bt_first(t, key, erval, exactp)
- BTREE *t;
- const DBT *key;
- EPG *erval;
- int *exactp;
+__bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp)
{
PAGE *h;
EPG *ep, save;
*erval = *ep;
return (RET_SUCCESS);
}
-
+
/*
* Walk backwards, as long as the entry matches and there are
* keys left in the tree. Save a copy of each match in case
* Parameters:
* t: the tree
* pgno: page number
- * index: page index
+ * idx: page index
*/
void
-__bt_setcur(t, pgno, index)
- BTREE *t;
- pgno_t pgno;
- u_int index;
+__bt_setcur(BTREE *t, pgno_t pgno, u_int idx)
{
/* Lose any already deleted key. */
if (t->bt_cursor.key.data != NULL) {
/* Update the cursor. */
t->bt_cursor.pg.pgno = pgno;
- t->bt_cursor.pg.index = index;
+ t->bt_cursor.pg.index = idx;
F_SET(&t->bt_cursor, CURS_INIT);
}
* 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.
static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_split.c,v 1.7 2004/09/13 22:07:24 kuriyama Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/btree/bt_split.c,v 1.12 2009/03/28 05:45:29 delphij Exp $");
#include <sys/types.h>
#include "btree.h"
static int bt_broot(BTREE *, PAGE *, PAGE *, PAGE *);
-static PAGE *bt_page (BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static PAGE *bt_page(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
static int bt_preserve(BTREE *, pgno_t);
-static PAGE *bt_psplit (BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
-static PAGE *bt_root (BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static PAGE *bt_psplit(BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
+static PAGE *bt_root(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
static int bt_rroot(BTREE *, PAGE *, PAGE *, PAGE *);
static recno_t rec_total(PAGE *);
* RET_ERROR, RET_SUCCESS
*/
int
-__bt_split(t, sp, key, data, flags, ilen, argskip)
- BTREE *t;
- PAGE *sp;
- const DBT *key, *data;
- int flags;
- size_t ilen;
- u_int32_t argskip;
+__bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, int flags,
+ size_t ilen, u_int32_t argskip)
{
BINTERNAL *bi;
BLEAF *bl, *tbl;
if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
goto err2;
- /*
+ /*
* The new key goes ONE AFTER the index, because the split
* was to the right.
*/
}
/* Split the parent page if necessary or shift the indices. */
- if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
sp = h;
h = h->pgno == P_ROOT ?
bt_root(t, h, &l, &r, &skip, nbytes) :
* Pointer to page in which to insert or NULL on error.
*/
static PAGE *
-bt_page(t, h, lp, rp, skip, ilen)
- BTREE *t;
- PAGE *h, **lp, **rp;
- indx_t *skip;
- size_t ilen;
+bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
{
PAGE *l, *r, *tp;
pgno_t npg;
}
/* Put the new left page for the split into place. */
- if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) {
+ if ((l = (PAGE *)calloc(1, t->bt_psize)) == NULL) {
mpool_put(t->bt_mp, r, 0);
return (NULL);
}
-#ifdef PURIFY
- memset(l, 0xff, t->bt_psize);
-#endif
l->pgno = h->pgno;
l->nextpg = r->pgno;
l->prevpg = h->prevpg;
* Pointer to page in which to insert or NULL on error.
*/
static PAGE *
-bt_root(t, h, lp, rp, skip, ilen)
- BTREE *t;
- PAGE *h, **lp, **rp;
- indx_t *skip;
- size_t ilen;
+bt_root(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
{
PAGE *l, *r, *tp;
pgno_t lnpg, rnpg;
* RET_ERROR, RET_SUCCESS
*/
static int
-bt_rroot(t, h, l, r)
- BTREE *t;
- PAGE *h, *l, *r;
+bt_rroot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
{
char *dest;
* RET_ERROR, RET_SUCCESS
*/
static int
-bt_broot(t, h, l, r)
- BTREE *t;
- PAGE *h, *l, *r;
+bt_broot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
{
BINTERNAL *bi;
BLEAF *bl;
* Pointer to page in which to insert.
*/
static PAGE *
-bt_psplit(t, h, l, r, pskip, ilen)
- BTREE *t;
- PAGE *h, *l, *r;
- indx_t *pskip;
- size_t ilen;
+bt_psplit(BTREE *t, PAGE *h, PAGE *l, PAGE *r, indx_t *pskip, size_t ilen)
{
BINTERNAL *bi;
BLEAF *bl;
* RET_SUCCESS, RET_ERROR.
*/
static int
-bt_preserve(t, pg)
- BTREE *t;
- pgno_t pg;
+bt_preserve(BTREE *t, pgno_t pg)
{
PAGE *h;
* all the way back to bt_split/bt_rroot and it's not very clean.
*/
static recno_t
-rec_total(h)
- PAGE *h;
+rec_total(PAGE *h)
{
recno_t recs;
indx_t nxt, top;
* 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.
* SUCH DAMAGE.
*
* @(#)btree.h 8.11 (Berkeley) 8/17/94
- * $FreeBSD: src/lib/libc/db/btree/btree.h,v 1.3 2002/03/22 23:41:40 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/btree/btree.h,v 1.5 2009/03/04 00:58:04 delphij Exp $
*/
/* Macros to set/clear/test flags. */
CURSOR bt_cursor; /* cursor */
#define BT_PUSH(t, p, i) { \
- t->bt_sp->pgno = p; \
- t->bt_sp->index = i; \
+ t->bt_sp->pgno = p; \
+ t->bt_sp->index = i; \
++t->bt_sp; \
}
#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
* 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.
* SUCH DAMAGE.
*
* @(#)extern.h 8.4 (Berkeley) 6/16/94
- * $FreeBSD: src/lib/libc/db/hash/extern.h,v 1.3 2002/03/22 09:18:22 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/hash/extern.h,v 1.4 2007/01/09 00:27:50 imp Exp $
*/
BUFHEAD *__add_ovflpage(HTAB *, BUFHEAD *);
* 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.
static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash.c,v 1.12 2004/09/10 05:41:41 kuriyama Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash.c,v 1.21 2009/03/28 07:20:39 delphij Exp $");
#include "namespace.h"
#include <sys/param.h>
static int hash_seq(const DB *, DBT *, DBT *, u_int32_t);
static int hash_sync(const DB *, u_int32_t);
static int hdestroy(HTAB *);
-static HTAB *init_hash(HTAB *, const char *, HASHINFO *);
+static HTAB *init_hash(HTAB *, const char *, const HASHINFO *);
static int init_htab(HTAB *, int);
#if BYTE_ORDER == LITTLE_ENDIAN
static void swap_header(HTAB *);
/************************** INTERFACE ROUTINES ***************************/
/* OPEN/CLOSE */
-extern DB *
-__hash_open(file, flags, mode, info, dflags)
- const char *file;
- int flags, mode, dflags;
- const HASHINFO *info; /* Special directives for create */
+/* ARGSUSED */
+DB *
+__hash_open(const char *file, int flags, int mode,
+ const HASHINFO *info, /* Special directives for create */
+ int dflags)
{
HTAB *hashp;
struct stat statbuf;
*/
hashp->flags = flags;
- new_table = 0;
- if (!file || (flags & O_TRUNC) ||
- (stat(file, &statbuf) && (errno == ENOENT))) {
- if (errno == ENOENT)
- errno = 0; /* Just in case someone looks at errno */
- new_table = 1;
- }
if (file) {
if ((hashp->fp = _open(file, flags, mode)) == -1)
RETURN_ERROR(errno, error0);
-
- /* if the .db file is empty, and we had permission to create
- a new .db file, then reinitialize the database */
- if ((flags & O_CREAT) &&
- _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0)
- new_table = 1;
-
(void)_fcntl(hashp->fp, F_SETFD, 1);
- }
+ new_table = _fstat(hashp->fp, &statbuf) == 0 &&
+ statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY;
+ } else
+ new_table = 1;
+
if (new_table) {
- if (!(hashp = init_hash(hashp, file, (HASHINFO *)info)))
+ if (!(hashp = init_hash(hashp, file, info)))
RETURN_ERROR(errno, error1);
} else {
/* Table already exists */
if (hashp->VERSION != HASHVERSION &&
hashp->VERSION != OLDHASHVERSION)
RETURN_ERROR(EFTYPE, error1);
- if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
+ if ((int32_t)hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
RETURN_ERROR(EFTYPE, error1);
/*
* Figure out how many segments we need. Max_Bucket is the
*/
nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
hashp->SGSIZE;
- hashp->nsegs = 0;
if (alloc_segs(hashp, nsegs))
/*
* If alloc_segs fails, table will have been destroyed
}
static int
-hash_close(dbp)
- DB *dbp;
+hash_close(DB *dbp)
{
HTAB *hashp;
int retval;
}
static int
-hash_fd(dbp)
- const DB *dbp;
+hash_fd(const DB *dbp)
{
HTAB *hashp;
/************************** LOCAL CREATION ROUTINES **********************/
static HTAB *
-init_hash(hashp, file, info)
- HTAB *hashp;
- const char *file;
- HASHINFO *info;
+init_hash(HTAB *hashp, const char *file, const HASHINFO *info)
{
struct stat statbuf;
int nelem;
* Returns 0 on No Error
*/
static int
-init_htab(hashp, nelem)
- HTAB *hashp;
- int nelem;
+init_htab(HTAB *hashp, int nelem)
{
- int nbuckets, nsegs;
- int l2;
+ int nbuckets, nsegs, l2;
/*
* Divide number of elements by the fill factor and determine a
* structure, freeing all allocated space.
*/
static int
-hdestroy(hashp)
- HTAB *hashp;
+hdestroy(HTAB *hashp)
{
int i, save_errno;
for (i = 0; i < hashp->nmaps; i++)
if (hashp->mapp[i])
free(hashp->mapp[i]);
+ if (hashp->tmp_key)
+ free(hashp->tmp_key);
+ if (hashp->tmp_buf)
+ free(hashp->tmp_buf);
if (hashp->fp != -1)
(void)_close(hashp->fp);
* -1 ERROR
*/
static int
-hash_sync(dbp, flags)
- const DB *dbp;
- u_int32_t flags;
+hash_sync(const DB *dbp, u_int32_t flags)
{
HTAB *hashp;
* -1 indicates that errno should be set
*/
static int
-flush_meta(hashp)
- HTAB *hashp;
+flush_meta(HTAB *hashp)
{
HASHHDR *whdrp;
#if BYTE_ORDER == LITTLE_ENDIAN
whdrp = &whdr;
swap_header_copy(&hashp->hdr, whdrp);
#endif
- if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
- ((wsize = _write(fp, whdrp, sizeof(HASHHDR))) == -1))
+ if ((wsize = pwrite(fp, whdrp, sizeof(HASHHDR), (off_t)0)) == -1)
return (-1);
else
if (wsize != sizeof(HASHHDR)) {
* -1 to indicate an internal ERROR (i.e. out of memory, etc)
*/
static int
-hash_get(dbp, key, data, flag)
- const DB *dbp;
- const DBT *key;
- DBT *data;
- u_int32_t flag;
+hash_get(const DB *dbp, const DBT *key, DBT *data, u_int32_t flag)
{
HTAB *hashp;
}
static int
-hash_put(dbp, key, data, flag)
- const DB *dbp;
- DBT *key;
- const DBT *data;
- u_int32_t flag;
+hash_put(const DB *dbp, DBT *key, const DBT *data, u_int32_t flag)
{
HTAB *hashp;
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_NOOVERWRITE) {
- hashp->error = EINVAL;
- errno = EINVAL;
+ hashp->error = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
}
static int
-hash_delete(dbp, key, flag)
- const DB *dbp;
- const DBT *key;
- u_int32_t flag; /* Ignored */
+hash_delete(const DB *dbp, const DBT *key,
+ u_int32_t flag) /* Ignored */
{
HTAB *hashp;
* Assume that hashp has been set in wrapper routine.
*/
static int
-hash_access(hashp, action, key, val)
- HTAB *hashp;
- ACTION action;
- DBT *key, *val;
+hash_access(HTAB *hashp, ACTION action, DBT *key, DBT *val)
{
BUFHEAD *rbufp;
BUFHEAD *bufp, *save_bufp;
}
static int
-hash_seq(dbp, key, data, flag)
- const DB *dbp;
- DBT *key, *data;
- u_int32_t flag;
+hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
{
u_int32_t bucket;
BUFHEAD *bufp;
hashp->cndx = 1;
hashp->cpage = NULL;
}
-
+ next_bucket:
for (bp = NULL; !bp || !bp[0]; ) {
if (!(bufp = hashp->cpage)) {
for (bucket = hashp->cbucket;
break;
}
hashp->cbucket = bucket;
- if (hashp->cbucket > hashp->MAX_BUCKET) {
+ if ((u_int32_t)hashp->cbucket > hashp->MAX_BUCKET) {
hashp->cbucket = -1;
return (ABNORMAL);
}
- } else
+ } else {
bp = (u_int16_t *)hashp->cpage->page;
+ if (flag == R_NEXT) {
+ hashp->cndx += 2;
+ if (hashp->cndx > bp[0]) {
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ hashp->cndx = 1;
+ goto next_bucket;
+ }
+ }
+ }
#ifdef DEBUG
assert(bp);
if (__big_keydata(hashp, bufp, key, data, 1))
return (ERROR);
} else {
+ if (hashp->cpage == 0)
+ return (ERROR);
key->data = (u_char *)hashp->cpage->page + bp[ndx];
key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
data->size = bp[ndx] - bp[ndx + 1];
- ndx += 2;
- if (ndx > bp[0]) {
- hashp->cpage = NULL;
- hashp->cbucket++;
- hashp->cndx = 1;
- } else
- hashp->cndx = ndx;
}
return (SUCCESS);
}
* 0 ==> OK
* -1 ==> Error
*/
-extern int
-__expand_table(hashp)
- HTAB *hashp;
+int
+__expand_table(HTAB *hashp)
{
u_int32_t old_bucket, new_bucket;
int dirsize, new_segnum, spare_ndx;
* fails, then this routine can go away.
*/
static void *
-hash_realloc(p_ptr, oldsize, newsize)
- SEGMENT **p_ptr;
- int oldsize, newsize;
+hash_realloc(SEGMENT **p_ptr, int oldsize, int newsize)
{
void *p;
return (p);
}
-extern u_int32_t
-__call_hash(hashp, k, len)
- HTAB *hashp;
- char *k;
- int len;
+u_int32_t
+__call_hash(HTAB *hashp, char *k, int len)
{
- int n, bucket;
+ unsigned int n, bucket;
n = hashp->hash(k, len);
bucket = n & hashp->HIGH_MASK;
* Returns 0 on success
*/
static int
-alloc_segs(hashp, nsegs)
- HTAB *hashp;
- int nsegs;
+alloc_segs(HTAB *hashp, int nsegs)
{
int i;
SEGMENT store;
errno = save_errno;
return (-1);
}
+ hashp->nsegs = nsegs;
+ if (nsegs == 0)
+ return (0);
/* Allocate segments */
- if ((store =
- (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
+ if ((store = (SEGMENT)calloc(nsegs << hashp->SSHIFT,
+ sizeof(SEGMENT))) == NULL) {
save_errno = errno;
(void)hdestroy(hashp);
errno = save_errno;
return (-1);
}
- for (i = 0; i < nsegs; i++, hashp->nsegs++)
+ for (i = 0; i < nsegs; i++)
hashp->dir[i] = &store[i << hashp->SSHIFT];
return (0);
}
* Hashp->hdr needs to be byteswapped.
*/
static void
-swap_header_copy(srcp, destp)
- HASHHDR *srcp, *destp;
+swap_header_copy(HASHHDR *srcp, HASHHDR *destp)
{
int i;
}
static void
-swap_header(hashp)
- HTAB *hashp;
+swap_header(HTAB *hashp)
{
HASHHDR *hdrp;
int i;
---- hash.c.orig 2008-09-07 11:37:54.000000000 -0700
-+++ hash.c 2008-09-07 12:42:15.000000000 -0700
-@@ -58,7 +58,7 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
+--- hash.c.orig 2009-11-06 12:41:16.000000000 -0800
++++ hash.c 2009-11-06 12:41:27.000000000 -0800
+@@ -54,7 +54,7 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
#include <db.h>
#include "hash.h"
#include "page.h"
static int alloc_segs(HTAB *, int);
static int flush_meta(HTAB *);
-@@ -108,8 +108,7 @@ __hash_open(file, flags, mode, info, dfl
+@@ -104,8 +104,7 @@ __hash_open(const char *file, int flags,
int bpages, hdrsize, new_table, nsegs, save_errno;
if ((flags & O_ACCMODE) == O_WRONLY) {
}
if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
-@@ -722,7 +721,7 @@ found:
+@@ -684,7 +683,7 @@ found:
return (ERROR);
break;
default:
* 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.
* SUCH DAMAGE.
*
* @(#)hash.h 8.3 (Berkeley) 5/31/94
- * $FreeBSD: src/lib/libc/db/hash/hash.h,v 1.6 2002/03/21 22:46:26 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/hash/hash.h,v 1.9 2009/03/28 05:45:29 delphij Exp $
*/
/* Operations */
/* Hash Table Information */
typedef struct hashhdr { /* Disk resident portion */
- int magic; /* Magic NO for hash tables */
- int version; /* Version ID */
+ int32_t magic; /* Magic NO for hash tables */
+ int32_t version; /* Version ID */
u_int32_t lorder; /* Byte Order */
- int bsize; /* Bucket/Page Size */
- int bshift; /* Bucket shift */
- int dsize; /* Directory Size */
- int ssize; /* Segment Size */
- int sshift; /* Segment shift */
- int ovfl_point; /* Where overflow pages are being
+ int32_t bsize; /* Bucket/Page Size */
+ int32_t bshift; /* Bucket shift */
+ int32_t dsize; /* Directory Size */
+ int32_t ssize; /* Segment Size */
+ int32_t sshift; /* Segment shift */
+ int32_t ovfl_point; /* Where overflow pages are being
* allocated */
- int last_freed; /* Last overflow page freed */
- int max_bucket; /* ID of Maximum bucket in use */
- int high_mask; /* Mask to modulo into entire table */
- int low_mask; /* Mask to modulo into lower half of
+ int32_t last_freed; /* Last overflow page freed */
+ u_int32_t max_bucket; /* ID of Maximum bucket in use */
+ u_int32_t high_mask; /* Mask to modulo into entire table */
+ u_int32_t low_mask; /* Mask to modulo into lower half of
* table */
- int ffactor; /* Fill factor */
- int nkeys; /* Number of keys in hash table */
- int hdrpages; /* Size of table header */
- int h_charkey; /* value of hash(CHARKEY) */
+ u_int32_t ffactor; /* Fill factor */
+ int32_t nkeys; /* Number of keys in hash table */
+ int32_t hdrpages; /* Size of table header */
+ int32_t h_charkey; /* value of hash(CHARKEY) */
#define NCACHED 32 /* number of bit maps and spare
* points */
- int spares[NCACHED];/* spare pages for overflow */
+ int32_t spares[NCACHED];/* spare pages for overflow */
u_int16_t bitmaps[NCACHED]; /* address of overflow page
* bitmaps */
} HASHHDR;
---- hash.h.orig 2003-10-22 19:07:01.000000000 -0700
-+++ hash.h 2004-10-23 22:52:09.000000000 -0700
-@@ -117,6 +117,8 @@
+--- hash.h.orig 2009-11-06 12:41:16.000000000 -0800
++++ hash.h 2009-11-06 12:41:27.000000000 -0800
+@@ -113,6 +113,8 @@ typedef struct htab { /* Memory reside
* allocate */
BUFHEAD bufhead; /* Header of buffer lru list */
SEGMENT *dir; /* Hash Bucket directory */
* 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.
static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_bigkey.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_bigkey.c,v 1.10 2009/03/28 06:47:05 delphij Exp $");
/*
* PACKAGE: hash
* 0 ==> OK
*-1 ==> ERROR
*/
-extern int
-__big_insert(hashp, bufp, key, val)
- HTAB *hashp;
- BUFHEAD *bufp;
- const DBT *key, *val;
+int
+__big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
u_int16_t *p;
- int key_size, n, val_size;
+ int key_size, n;
+ unsigned int val_size;
u_int16_t space, move_bytes, off;
char *cp, *key_data, *val_data;
return (-1);
n = p[0];
if (!key_size) {
- if (FREESPACE(p)) {
- move_bytes = MIN(FREESPACE(p), val_size);
+ space = FREESPACE(p);
+ if (space) {
+ move_bytes = MIN(space, val_size);
+ /*
+ * If the data would fit exactly in the
+ * remaining space, we must overflow it to the
+ * next page; otherwise the invariant that the
+ * data must end on a page with FREESPACE
+ * non-zero would fail.
+ */
+ if (space == val_size && val_size == val->size)
+ goto toolarge;
off = OFFSET(p) - move_bytes;
- p[n] = off;
memmove(cp + off, val_data, move_bytes);
val_data += move_bytes;
val_size -= move_bytes;
+ p[n] = off;
p[n - 2] = FULL_KEY_DATA;
FREESPACE(p) = FREESPACE(p) - move_bytes;
OFFSET(p) = off;
- } else
+ } else {
+ toolarge:
p[n - 2] = FULL_KEY;
+ }
}
p = (u_int16_t *)bufp->page;
cp = bufp->page;
* 0 => OK
*-1 => ERROR
*/
-extern int
-__big_delete(hashp, bufp)
- HTAB *hashp;
- BUFHEAD *bufp;
+int
+__big_delete(HTAB *hashp, BUFHEAD *bufp)
{
BUFHEAD *last_bfp, *rbufp;
u_int16_t *bp, pageno;
n -= 2;
bp[0] = n;
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
- OFFSET(bp) = hashp->BSIZE - 1;
+ OFFSET(bp) = hashp->BSIZE;
bufp->flags |= BUF_MOD;
if (rbufp)
__free_ovflpage(hashp, rbufp);
- if (last_bfp != rbufp)
+ if (last_bfp && last_bfp != rbufp)
__free_ovflpage(hashp, last_bfp);
hashp->NKEYS--;
* -2 means key not found and this is big key/data
* -3 error
*/
-extern int
-__find_bigpair(hashp, bufp, ndx, key, size)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- char *key;
- int size;
+int
+__find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size)
{
u_int16_t *bp;
char *p;
* of the pair; 0 if there isn't any (i.e. big pair is the last key in the
* bucket)
*/
-extern u_int16_t
-__find_last_page(hashp, bpp)
- HTAB *hashp;
- BUFHEAD **bpp;
+u_int16_t
+__find_last_page(HTAB *hashp, BUFHEAD **bpp)
{
BUFHEAD *bufp;
u_int16_t *bp, pageno;
* Return the data for the key/data pair that begins on this page at this
* index (index should always be 1).
*/
-extern int
-__big_return(hashp, bufp, ndx, val, set_current)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- DBT *val;
- int set_current;
+int
+__big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current)
{
BUFHEAD *save_p;
u_int16_t *bp, len, off, save_addr;
return (0);
}
- val->size = collect_data(hashp, bufp, (int)len, set_current);
- if (val->size == -1)
+ val->size = (size_t)collect_data(hashp, bufp, (int)len, set_current);
+ if (val->size == (size_t)-1)
return (-1);
if (save_p->addr != save_addr) {
/* We are pretty short on buffers. */
* allocate a buffer and copy the data as you recurse up.
*/
static int
-collect_data(hashp, bufp, len, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len, set;
+collect_data(HTAB *hashp, BUFHEAD *bufp, int len, int set)
{
u_int16_t *bp;
char *p;
/*
* Fill in the key and data for this big pair.
*/
-extern int
-__big_keydata(hashp, bufp, key, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- DBT *key, *val;
- int set;
+int
+__big_keydata(HTAB *hashp, BUFHEAD *bufp, DBT *key, DBT *val, int set)
{
- key->size = collect_key(hashp, bufp, 0, val, set);
- if (key->size == -1)
+ key->size = (size_t)collect_key(hashp, bufp, 0, val, set);
+ if (key->size == (size_t)-1)
return (-1);
key->data = (u_char *)hashp->tmp_key;
return (0);
* collect the data, allocate a buffer and copy the key as you recurse up.
*/
static int
-collect_key(hashp, bufp, len, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len;
- DBT *val;
- int set;
+collect_key(HTAB *hashp, BUFHEAD *bufp, int len, DBT *val, int set)
{
BUFHEAD *xbp;
char *p;
* 0 => OK
* -1 => error
*/
-extern int
-__big_split(hashp, op, np, big_keyp, addr, obucket, ret)
- HTAB *hashp;
- BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */
- BUFHEAD *np; /* Pointer to new bucket page */
- /* Pointer to first page containing the big key/data */
- BUFHEAD *big_keyp;
- int addr; /* Address of big_keyp */
- u_int32_t obucket;/* Old Bucket */
- SPLIT_RETURN *ret;
+int
+__big_split(HTAB *hashp,
+ BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */
+ BUFHEAD *np, /* Pointer to new bucket page */
+ BUFHEAD *big_keyp, /* Pointer to first page containing the big key/data */
+ int addr, /* Address of big_keyp */
+ u_int32_t obucket, /* Old Bucket */
+ SPLIT_RETURN *ret)
{
- BUFHEAD *tmpp;
- u_int16_t *tp;
- BUFHEAD *bp;
+ BUFHEAD *bp, *tmpp;
DBT key, val;
u_int32_t change;
- u_int16_t free_space, n, off;
+ u_int16_t free_space, n, off, *tp;
bp = big_keyp;
if ( (ret->next_addr = __find_last_page(hashp, &big_keyp)) ) {
if (!(ret->nextp =
__get_buf(hashp, ret->next_addr, big_keyp, 0)))
- return (-1);;
+ return (-1);
} else
ret->nextp = NULL;
---- hash_bigkey.c.orig Sun Feb 16 09:29:09 2003
-+++ hash_bigkey.c Sat Oct 18 18:30:43 2003
-@@ -72,7 +72,7 @@
+--- hash_bigkey.c.orig 2009-11-06 12:41:16.000000000 -0800
++++ hash_bigkey.c 2009-11-06 12:41:27.000000000 -0800
+@@ -68,7 +68,7 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
#include <db.h>
#include "hash.h"
#include "page.h"
* 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.
static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_buf.c,v 1.7 2002/03/21 22:46:26 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_buf.c,v 1.12 2009/03/28 06:40:48 delphij Exp $");
/*
* PACKAGE: hash
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#ifdef DEBUG
#include <assert.h>
* be valid. Therefore, you must always verify that its address matches the
* address you are seeking.
*/
-extern BUFHEAD *
-__get_buf(hashp, addr, prev_bp, newpage)
- HTAB *hashp;
- u_int32_t addr;
- BUFHEAD *prev_bp;
- int newpage; /* If prev_bp set, indicates a new overflow page. */
+BUFHEAD *
+__get_buf(HTAB *hashp, u_int32_t addr,
+ BUFHEAD *prev_bp, /* If prev_bp set, indicates a new overflow page. */
+ int newpage)
{
BUFHEAD *bp;
u_int32_t is_disk_mask;
* If newbuf finds an error (returning NULL), it also sets errno.
*/
static BUFHEAD *
-newbuf(hashp, addr, prev_bp)
- HTAB *hashp;
- u_int32_t addr;
- BUFHEAD *prev_bp;
+newbuf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp)
{
BUFHEAD *bp; /* The buffer we're going to use */
BUFHEAD *xbp; /* Temp pointer */
oaddr = 0;
bp = LRU;
+
+ /* It is bad to overwrite the page under the cursor. */
+ if (bp == hashp->cpage) {
+ BUF_REMOVE(bp);
+ MRU_INSERT(bp);
+ bp = LRU;
+ }
+
+ /* If prev_bp is part of bp overflow, create a new buffer. */
+ if (hashp->nbufs == 0 && prev_bp && bp->ovfl) {
+ BUFHEAD *ovfl;
+
+ for (ovfl = bp->ovfl; ovfl ; ovfl = ovfl->ovfl) {
+ if (ovfl == prev_bp) {
+ hashp->nbufs++;
+ break;
+ }
+ }
+ }
+
/*
* If LRU buffer is pinned, the buffer pool is too small. We need to
* allocate more buffers.
*/
- if (hashp->nbufs || (bp->flags & BUF_PIN)) {
+ if (hashp->nbufs || (bp->flags & BUF_PIN) || bp == hashp->cpage) {
/* Allocate a new one */
- if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
+ if ((bp = (BUFHEAD *)calloc(1, sizeof(BUFHEAD))) == NULL)
return (NULL);
-#ifdef PURIFY
- memset(bp, 0xff, sizeof(BUFHEAD));
-#endif
- if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) {
+ if ((bp->page = (char *)calloc(1, hashp->BSIZE)) == NULL) {
free(bp);
return (NULL);
}
-#ifdef PURIFY
- memset(bp->page, 0xff, hashp->BSIZE);
-#endif
if (hashp->nbufs)
hashp->nbufs--;
} else {
*/
#ifdef DEBUG1
(void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
- prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
+ prev_bp->addr, (prev_bp->ovfl ? prev_bp->ovfl->addr : 0),
(bp ? bp->addr : 0));
#endif
prev_bp->ovfl = bp;
return (bp);
}
-extern void
-__buf_init(hashp, nbytes)
- HTAB *hashp;
- int nbytes;
+void
+__buf_init(HTAB *hashp, int nbytes)
{
BUFHEAD *bfp;
int npages;
*/
}
-extern int
-__buf_free(hashp, do_free, to_disk)
- HTAB *hashp;
- int do_free, to_disk;
+int
+__buf_free(HTAB *hashp, int do_free, int to_disk)
{
BUFHEAD *bp;
}
/* Check if we are freeing stuff */
if (do_free) {
- if (bp->page)
+ if (bp->page) {
+ (void)memset(bp->page, 0, hashp->BSIZE);
free(bp->page);
+ }
BUF_REMOVE(bp);
free(bp);
bp = LRU;
return (0);
}
-extern void
-__reclaim_buf(hashp, bp)
- HTAB *hashp;
- BUFHEAD *bp;
+void
+__reclaim_buf(HTAB *hashp, BUFHEAD *bp)
{
bp->ovfl = 0;
bp->addr = 0;
---- hash_buf.c.orig Thu Mar 21 14:46:26 2002
-+++ hash_buf.c Sat Oct 18 18:30:49 2003
-@@ -69,7 +69,7 @@
+--- hash_buf.c (revision 61187)
++++ hash_buf.c (working copy)
+@@ -66,7 +66,7 @@
#include <db.h>
#include "hash.h"
#include "page.h"
static BUFHEAD *newbuf(HTAB *, u_int32_t, BUFHEAD *);
+@@ -293,7 +293,7 @@
+ return (bp);
+ }
+
+-void
++__private_extern__ void
+ __buf_init(HTAB *hashp, int nbytes)
+ {
+ BUFHEAD *bfp;
* 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.
static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_func.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_func.c,v 1.6 2007/01/09 00:27:50 imp Exp $");
#include <sys/types.h>
---- hash_func.c.orig Sun Feb 16 09:29:09 2003
-+++ hash_func.c Sat Oct 18 18:30:57 2003
-@@ -45,7 +45,7 @@
+--- hash_func.c.orig 2009-11-06 12:41:16.000000000 -0800
++++ hash_func.c 2009-11-06 12:41:27.000000000 -0800
+@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
#include <db.h>
#include "hash.h"
#include "page.h"
* 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.
static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_log2.c,v 1.2 2002/03/21 18:47:38 obrien Exp $");
-
-#include <sys/types.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_log2.c,v 1.5 2009/03/28 05:45:29 delphij Exp $");
#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
u_int32_t
-__log2(num)
- u_int32_t num;
+__log2(u_int32_t num)
{
u_int32_t i, limit;
--- /dev/null
+--- hash_log2.c.orig 2009-11-06 14:27:02.000000000 -0800
++++ hash_log2.c 2009-11-06 14:27:42.000000000 -0800
+@@ -39,7 +39,7 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
+ #include <db.h>
+ #include "hash.h"
+ #include "page.h"
+-#include "extern.h"
++#include "hash_extern.h"
+
+ u_int32_t
+ __log2(u_int32_t num)
* 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.
static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_page.c,v 1.8 2002/03/21 22:46:26 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_page.c,v 1.16 2009/03/28 06:30:43 delphij Exp $");
/*
* PACKAGE: hashing
*/
#include "namespace.h"
-#include <sys/types.h>
+#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include "page.h"
#include "extern.h"
-static u_int32_t *fetch_bitmap(HTAB *, int);
-static u_int32_t first_free(u_int32_t);
-static int open_temp(HTAB *);
-static u_int16_t overflow_page(HTAB *);
-static void putpair(char *, const DBT *, const DBT *);
-static void squeeze_key(u_int16_t *, const DBT *, const DBT *);
-static int ugly_split
-(HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int);
+static u_int32_t *fetch_bitmap(HTAB *, int);
+static u_int32_t first_free(u_int32_t);
+static int open_temp(HTAB *);
+static u_int16_t overflow_page(HTAB *);
+static void putpair(char *, const DBT *, const DBT *);
+static void squeeze_key(u_int16_t *, const DBT *, const DBT *);
+static int ugly_split(HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int);
#define PAGE_INIT(P) { \
((u_int16_t *)(P))[0] = 0; \
* stuff on.
*/
static void
-putpair(p, key, val)
- char *p;
- const DBT *key, *val;
+putpair(char *p, const DBT *key, const DBT *val)
{
u_int16_t *bp, n, off;
* 0 OK
* -1 error
*/
-extern int
-__delpair(hashp, bufp, ndx)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
+int
+__delpair(HTAB *hashp, BUFHEAD *bufp, int ndx)
{
- u_int16_t *bp, newoff;
+ u_int16_t *bp, newoff, pairlen;
int n;
- u_int16_t pairlen;
bp = (u_int16_t *)bufp->page;
n = bp[0];
bp[i - 1] = bp[i + 1] + pairlen;
}
}
+ if (ndx == hashp->cndx) {
+ /*
+ * We just removed pair we were "pointing" to.
+ * By moving back the cndx we ensure subsequent
+ * hash_seq() calls won't skip over any entries.
+ */
+ hashp->cndx -= 2;
+ }
}
/* Finally adjust the page data */
bp[n] = OFFSET(bp) + pairlen;
* 0 ==> OK
* -1 ==> Error
*/
-extern int
-__split_page(hashp, obucket, nbucket)
- HTAB *hashp;
- u_int32_t obucket, nbucket;
+int
+__split_page(HTAB *hashp, u_int32_t obucket, u_int32_t nbucket)
{
BUFHEAD *new_bufp, *old_bufp;
u_int16_t *ino;
* -1 ==> failure
*/
static int
-ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
- HTAB *hashp;
- u_int32_t obucket; /* Same as __split_page. */
- BUFHEAD *old_bufp, *new_bufp;
- int copyto; /* First byte on page which contains key/data values. */
- int moved; /* Number of pairs moved to new page. */
+ugly_split(HTAB *hashp,
+ u_int32_t obucket, /* Same as __split_page. */
+ BUFHEAD *old_bufp,
+ BUFHEAD *new_bufp,
+ int copyto, /* First byte on page which contains key/data values. */
+ int moved) /* Number of pairs moved to new page. */
{
- BUFHEAD *bufp; /* Buffer header for ino */
- u_int16_t *ino; /* Page keys come off of */
- u_int16_t *np; /* New page */
- u_int16_t *op; /* Page keys go on to if they aren't moving */
+ BUFHEAD *bufp; /* Buffer header for ino */
+ u_int16_t *ino; /* Page keys come off of */
+ u_int16_t *np; /* New page */
+ u_int16_t *op; /* Page keys go on to if they aren't moving */
BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */
DBT key, val;
* 0 ==> OK
* 1 ==> failure
*/
-extern int
-__addel(hashp, bufp, key, val)
- HTAB *hashp;
- BUFHEAD *bufp;
- const DBT *key, *val;
+int
+__addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
u_int16_t *bp, *sop;
int do_expand;
if (!bufp)
return (-1);
bp = (u_int16_t *)bufp->page;
- } else
+ } else if (bp[bp[0]] != OVFLPAGE) {
+ /* Short key/data pairs, no more pages */
+ break;
+ } else {
/* Try to squeeze key on this page */
- if (FREESPACE(bp) > PAIRSIZE(key, val)) {
+ if (bp[2] >= REAL_KEY &&
+ FREESPACE(bp) >= PAIRSIZE(key, val)) {
squeeze_key(bp, key, val);
- return (0);
+ goto stats;
} else {
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!bufp)
return (-1);
bp = (u_int16_t *)bufp->page;
}
+ }
if (PAIRFITS(bp, key, val))
putpair(bufp->page, key, val);
if (__big_insert(hashp, bufp, key, val))
return (-1);
}
+stats:
bufp->flags |= BUF_MOD;
/*
* If the average number of keys per bucket exceeds the fill factor,
* pointer on success
* NULL on error
*/
-extern BUFHEAD *
-__add_ovflpage(hashp, bufp)
- HTAB *hashp;
- BUFHEAD *bufp;
+BUFHEAD *
+__add_ovflpage(HTAB *hashp, BUFHEAD *bufp)
{
- u_int16_t *sp;
- u_int16_t ndx, ovfl_num;
+ u_int16_t *sp, ndx, ovfl_num;
#ifdef DEBUG1
int tmp1, tmp2;
#endif
* 0 indicates SUCCESS
* -1 indicates FAILURE
*/
-extern int
-__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
- HTAB *hashp;
- char *p;
- u_int32_t bucket;
- int is_bucket, is_disk, is_bitmap;
+int
+__get_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_disk,
+ int is_bitmap)
{
- int fd, page, size;
- int rsize;
+ int fd, page, size, rsize;
u_int16_t *bp;
fd = hashp->fp;
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((rsize = _read(fd, p, size)) == -1))
+ if ((rsize = pread(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
return (-1);
bp = (u_int16_t *)p;
if (!rsize)
* 0 ==> OK
* -1 ==>failure
*/
-extern int
-__put_page(hashp, p, bucket, is_bucket, is_bitmap)
- HTAB *hashp;
- char *p;
- u_int32_t bucket;
- int is_bucket, is_bitmap;
+int
+__put_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_bitmap)
{
- int fd, page, size;
- int wsize;
+ int fd, page, size, wsize;
size = hashp->BSIZE;
if ((hashp->fp == -1) && open_temp(hashp))
fd = hashp->fp;
if (hashp->LORDER != BYTE_ORDER) {
- int i;
- int max;
+ int i, max;
if (is_bitmap) {
max = hashp->BSIZE >> 2; /* divide by 4 */
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((wsize = _write(fd, p, size)) == -1))
+ if ((wsize = pwrite(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
/* Errno is set */
return (-1);
if (wsize != size) {
* Initialize a new bitmap page. Bitmap pages are left in memory
* once they are read in.
*/
-extern int
-__ibitmap(hashp, pnum, nbits, ndx)
- HTAB *hashp;
- int pnum, nbits, ndx;
+int
+__ibitmap(HTAB *hashp, int pnum, int nbits, int ndx)
{
u_int32_t *ip;
int clearbytes, clearints;
}
static u_int32_t
-first_free(map)
- u_int32_t map;
+first_free(u_int32_t map)
{
u_int32_t i, mask;
}
static u_int16_t
-overflow_page(hashp)
- HTAB *hashp;
+overflow_page(HTAB *hashp)
{
u_int32_t *freep;
int max_free, offset, splitnum;
if (offset > SPLITMASK) {
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
free_page++;
if (free_page >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
/*
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG,
sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
/* Calculate the split number for this page */
for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
offset = (i ? bit - hashp->SPARES[i - 1] : bit);
- if (offset >= SPLITMASK)
+ if (offset >= SPLITMASK) {
+ (void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0); /* Out of overflow pages */
+ }
addr = OADDR_OF(i, offset);
#ifdef DEBUG2
(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
/*
* Mark this overflow page as free.
*/
-extern void
-__free_ovflpage(hashp, obufp)
- HTAB *hashp;
- BUFHEAD *obufp;
+void
+__free_ovflpage(HTAB *hashp, BUFHEAD *obufp)
{
u_int16_t addr;
u_int32_t *freep;
* -1 failure
*/
static int
-open_temp(hashp)
- HTAB *hashp;
+open_temp(HTAB *hashp)
{
sigset_t set, oset;
- static char namestr[] = "_hashXXXXXX";
+ int len;
+ char *envtmp = NULL;
+ char path[MAXPATHLEN];
+
+ if (issetugid() == 0)
+ envtmp = getenv("TMPDIR");
+ len = snprintf(path,
+ sizeof(path), "%s/_hash.XXXXXX", envtmp ? envtmp : "/tmp");
+ if (len < 0 || len >= sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
/* Block signals; make sure file goes away at process exit. */
(void)sigfillset(&set);
(void)_sigprocmask(SIG_BLOCK, &set, &oset);
- if ((hashp->fp = mkstemp(namestr)) != -1) {
- (void)unlink(namestr);
+ if ((hashp->fp = mkstemp(path)) != -1) {
+ (void)unlink(path);
(void)_fcntl(hashp->fp, F_SETFD, 1);
}
(void)_sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
* an overflow pair, so we need to shift things.
*/
static void
-squeeze_key(sp, key, val)
- u_int16_t *sp;
- const DBT *key, *val;
+squeeze_key(u_int16_t *sp, const DBT *key, const DBT *val)
{
char *p;
u_int16_t free_space, n, off, pageno;
}
static u_int32_t *
-fetch_bitmap(hashp, ndx)
- HTAB *hashp;
- int ndx;
+fetch_bitmap(HTAB *hashp, int ndx)
{
if (ndx >= hashp->nmaps)
return (NULL);
#ifdef DEBUG4
int
-print_chain(addr)
- int addr;
+print_chain(int addr)
{
BUFHEAD *bufp;
short *bp, oaddr;
---- hash_page.c.orig 2006-04-22 23:04:55.000000000 -0700
-+++ hash_page.c 2006-04-23 00:23:46.000000000 -0700
-@@ -74,7 +74,7 @@
+--- hash_page.c.orig 2009-11-06 12:41:16.000000000 -0800
++++ hash_page.c 2009-11-06 12:43:23.000000000 -0800
+@@ -70,7 +70,7 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
#include <db.h>
#include "hash.h"
#include "page.h"
-#include "extern.h"
+#include "hash_extern.h"
- static u_int32_t *fetch_bitmap(HTAB *, int);
- static u_int32_t first_free(u_int32_t);
-@@ -586,7 +586,7 @@
- int is_bucket, is_bitmap;
+ static u_int32_t *fetch_bitmap(HTAB *, int);
+ static u_int32_t first_free(u_int32_t);
+@@ -571,7 +571,7 @@ __get_page(HTAB *hashp, char *p, u_int32
+ int
+ __put_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_bitmap)
{
- int fd, page, size;
-- int wsize;
-+ int wsize, max;
+- int fd, page, size, wsize;
++ int fd, page, size, wsize, max;
size = hashp->BSIZE;
if ((hashp->fp == -1) && open_temp(hashp))
-@@ -595,7 +595,6 @@
+@@ -579,7 +579,7 @@ __put_page(HTAB *hashp, char *p, u_int32
+ fd = hashp->fp;
if (hashp->LORDER != BYTE_ORDER) {
- int i;
-- int max;
+- int i, max;
++ int i;
if (is_bitmap) {
max = hashp->BSIZE >> 2; /* divide by 4 */
-@@ -619,6 +618,18 @@
+@@ -602,6 +602,18 @@ __put_page(HTAB *hashp, char *p, u_int32
errno = EFTYPE;
return (-1);
}
* 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.
static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/ndbm.c,v 1.6 2002/03/22 21:52:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/ndbm.c,v 1.7 2007/01/09 00:27:51 imp Exp $");
/*
* This package provides a dbm compatible interface to the new hashing
---- ndbm.c.org 2006-09-08 18:47:42.000000000 -0700
-+++ ndbm.c 2006-09-08 18:48:03.000000000 -0700
-@@ -51,6 +51,9 @@
+--- ndbm.c.orig 2009-11-06 12:41:16.000000000 -0800
++++ ndbm.c 2009-11-06 12:41:27.000000000 -0800
+@@ -47,6 +47,9 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
#include <string.h>
#include <errno.h>
#include <ndbm.h>
#include "hash.h"
-@@ -62,7 +65,8 @@
+@@ -58,7 +61,8 @@ __FBSDID("$FreeBSD: src/lib/libc/db/hash
extern DBM *
dbm_open(file, flags, mode)
const char *file;
{
HASHINFO info;
char path[MAXPATHLEN];
-@@ -128,10 +132,14 @@
+@@ -124,10 +128,14 @@ dbm_firstkey(db)
int status;
datum retkey;
DBT dbtretkey, dbtretdata;
retkey.dptr = dbtretkey.data;
retkey.dsize = dbtretkey.size;
return (retkey);
-@@ -146,13 +154,20 @@
+@@ -142,13 +150,20 @@ extern datum
dbm_nextkey(db)
DBM *db;
{
* 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.
* SUCH DAMAGE.
*
* @(#)page.h 8.2 (Berkeley) 5/31/94
- * $FreeBSD: src/lib/libc/db/hash/page.h,v 1.2 2002/03/22 23:41:40 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/hash/page.h,v 1.4 2009/03/04 00:58:04 delphij Exp $
*/
/*
* +--------+---------------------+
* | F R E E A R E A |
* +--------------+---------------+
- * | <---- - - - | data |
+ * | <---- - - - | data |
* +--------+-----+----+----------+
* | key | data | key |
* +--------+----------+----------+
* 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.
static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash.c,v 1.12 2004/09/10 05:41:41 kuriyama Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash.c,v 1.21 2009/03/28 07:20:39 delphij Exp $");
#include "namespace.h"
#include <sys/param.h>
static int hash_seq(const DB *, DBT *, DBT *, u_int32_t);
static int hash_sync(const DB *, u_int32_t);
static int hdestroy(HTAB *);
-static HTAB *init_hash(HTAB *, const char *, HASHINFO *);
+static HTAB *init_hash(HTAB *, const char *, const HASHINFO *);
static int init_htab(HTAB *, int);
#if BYTE_ORDER == LITTLE_ENDIAN
static void swap_header(HTAB *);
/************************** INTERFACE ROUTINES ***************************/
/* OPEN/CLOSE */
-extern DB *
-__hash_open(file, flags, mode, info, dflags)
- const char *file;
- int flags, mode, dflags;
- const HASHINFO *info; /* Special directives for create */
+/* ARGSUSED */
+DB *
+__hash_open(const char *file, int flags, int mode,
+ const HASHINFO *info, /* Special directives for create */
+ int dflags)
{
HTAB *hashp;
struct stat statbuf;
*/
hashp->flags = flags;
- new_table = 0;
- if (!file || (flags & O_TRUNC) ||
- (stat(file, &statbuf) && (errno == ENOENT))) {
- if (errno == ENOENT)
- errno = 0; /* Just in case someone looks at errno */
- new_table = 1;
- }
if (file) {
if ((hashp->fp = _open(file, flags, mode)) == -1)
RETURN_ERROR(errno, error0);
-
- /* if the .db file is empty, and we had permission to create
- a new .db file, then reinitialize the database */
- if ((flags & O_CREAT) &&
- _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0)
- new_table = 1;
-
(void)_fcntl(hashp->fp, F_SETFD, 1);
- }
+ new_table = _fstat(hashp->fp, &statbuf) == 0 &&
+ statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY;
+ } else
+ new_table = 1;
+
if (new_table) {
- if (!(hashp = init_hash(hashp, file, (HASHINFO *)info)))
+ if (!(hashp = init_hash(hashp, file, info)))
RETURN_ERROR(errno, error1);
} else {
/* Table already exists */
if (hashp->VERSION != HASHVERSION &&
hashp->VERSION != OLDHASHVERSION)
RETURN_ERROR(EFTYPE, error1);
- if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
+ if ((int32_t)hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
RETURN_ERROR(EFTYPE, error1);
/*
* Figure out how many segments we need. Max_Bucket is the
*/
nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
hashp->SGSIZE;
- hashp->nsegs = 0;
if (alloc_segs(hashp, nsegs))
/*
* If alloc_segs fails, table will have been destroyed
}
static int
-hash_close(dbp)
- DB *dbp;
+hash_close(DB *dbp)
{
HTAB *hashp;
int retval;
}
static int
-hash_fd(dbp)
- const DB *dbp;
+hash_fd(const DB *dbp)
{
HTAB *hashp;
/************************** LOCAL CREATION ROUTINES **********************/
static HTAB *
-init_hash(hashp, file, info)
- HTAB *hashp;
- const char *file;
- HASHINFO *info;
+init_hash(HTAB *hashp, const char *file, const HASHINFO *info)
{
struct stat statbuf;
int nelem;
* Returns 0 on No Error
*/
static int
-init_htab(hashp, nelem)
- HTAB *hashp;
- int nelem;
+init_htab(HTAB *hashp, int nelem)
{
- int nbuckets, nsegs;
- int l2;
+ int nbuckets, nsegs, l2;
/*
* Divide number of elements by the fill factor and determine a
* structure, freeing all allocated space.
*/
static int
-hdestroy(hashp)
- HTAB *hashp;
+hdestroy(HTAB *hashp)
{
int i, save_errno;
for (i = 0; i < hashp->nmaps; i++)
if (hashp->mapp[i])
free(hashp->mapp[i]);
+ if (hashp->tmp_key)
+ free(hashp->tmp_key);
+ if (hashp->tmp_buf)
+ free(hashp->tmp_buf);
if (hashp->fp != -1)
(void)_close(hashp->fp);
* -1 ERROR
*/
static int
-hash_sync(dbp, flags)
- const DB *dbp;
- u_int32_t flags;
+hash_sync(const DB *dbp, u_int32_t flags)
{
HTAB *hashp;
* -1 indicates that errno should be set
*/
static int
-flush_meta(hashp)
- HTAB *hashp;
+flush_meta(HTAB *hashp)
{
HASHHDR *whdrp;
#if BYTE_ORDER == LITTLE_ENDIAN
whdrp = &whdr;
swap_header_copy(&hashp->hdr, whdrp);
#endif
- if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
- ((wsize = _write(fp, whdrp, sizeof(HASHHDR))) == -1))
+ if ((wsize = pwrite(fp, whdrp, sizeof(HASHHDR), (off_t)0)) == -1)
return (-1);
else
if (wsize != sizeof(HASHHDR)) {
* -1 to indicate an internal ERROR (i.e. out of memory, etc)
*/
static int
-hash_get(dbp, key, data, flag)
- const DB *dbp;
- const DBT *key;
- DBT *data;
- u_int32_t flag;
+hash_get(const DB *dbp, const DBT *key, DBT *data, u_int32_t flag)
{
HTAB *hashp;
}
static int
-hash_put(dbp, key, data, flag)
- const DB *dbp;
- DBT *key;
- const DBT *data;
- u_int32_t flag;
+hash_put(const DB *dbp, DBT *key, const DBT *data, u_int32_t flag)
{
HTAB *hashp;
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_NOOVERWRITE) {
- hashp->error = EINVAL;
- errno = EINVAL;
+ hashp->error = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
}
static int
-hash_delete(dbp, key, flag)
- const DB *dbp;
- const DBT *key;
- u_int32_t flag; /* Ignored */
+hash_delete(const DB *dbp, const DBT *key,
+ u_int32_t flag) /* Ignored */
{
HTAB *hashp;
* Assume that hashp has been set in wrapper routine.
*/
static int
-hash_access(hashp, action, key, val)
- HTAB *hashp;
- ACTION action;
- DBT *key, *val;
+hash_access(HTAB *hashp, ACTION action, DBT *key, DBT *val)
{
BUFHEAD *rbufp;
BUFHEAD *bufp, *save_bufp;
}
static int
-hash_seq(dbp, key, data, flag)
- const DB *dbp;
- DBT *key, *data;
- u_int32_t flag;
+hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
{
u_int32_t bucket;
BUFHEAD *bufp;
hashp->cndx = 1;
hashp->cpage = NULL;
}
-
+ next_bucket:
for (bp = NULL; !bp || !bp[0]; ) {
if (!(bufp = hashp->cpage)) {
for (bucket = hashp->cbucket;
break;
}
hashp->cbucket = bucket;
- if (hashp->cbucket > hashp->MAX_BUCKET) {
+ if ((u_int32_t)hashp->cbucket > hashp->MAX_BUCKET) {
hashp->cbucket = -1;
return (ABNORMAL);
}
- } else
+ } else {
bp = (u_int16_t *)hashp->cpage->page;
+ if (flag == R_NEXT) {
+ hashp->cndx += 2;
+ if (hashp->cndx > bp[0]) {
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ hashp->cndx = 1;
+ goto next_bucket;
+ }
+ }
+ }
#ifdef DEBUG
assert(bp);
if (__big_keydata(hashp, bufp, key, data, 1))
return (ERROR);
} else {
+ if (hashp->cpage == 0)
+ return (ERROR);
key->data = (u_char *)hashp->cpage->page + bp[ndx];
key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
data->size = bp[ndx] - bp[ndx + 1];
- ndx += 2;
- if (ndx > bp[0]) {
- hashp->cpage = NULL;
- hashp->cbucket++;
- hashp->cndx = 1;
- } else
- hashp->cndx = ndx;
}
return (SUCCESS);
}
* 0 ==> OK
* -1 ==> Error
*/
-extern int
-__expand_table(hashp)
- HTAB *hashp;
+int
+__expand_table(HTAB *hashp)
{
u_int32_t old_bucket, new_bucket;
int dirsize, new_segnum, spare_ndx;
* fails, then this routine can go away.
*/
static void *
-hash_realloc(p_ptr, oldsize, newsize)
- SEGMENT **p_ptr;
- int oldsize, newsize;
+hash_realloc(SEGMENT **p_ptr, int oldsize, int newsize)
{
void *p;
return (p);
}
-extern u_int32_t
-__call_hash(hashp, k, len)
- HTAB *hashp;
- char *k;
- int len;
+u_int32_t
+__call_hash(HTAB *hashp, char *k, int len)
{
- int n, bucket;
+ unsigned int n, bucket;
n = hashp->hash(k, len);
bucket = n & hashp->HIGH_MASK;
* Returns 0 on success
*/
static int
-alloc_segs(hashp, nsegs)
- HTAB *hashp;
- int nsegs;
+alloc_segs(HTAB *hashp, int nsegs)
{
int i;
SEGMENT store;
errno = save_errno;
return (-1);
}
+ hashp->nsegs = nsegs;
+ if (nsegs == 0)
+ return (0);
/* Allocate segments */
- if ((store =
- (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
+ if ((store = (SEGMENT)calloc(nsegs << hashp->SSHIFT,
+ sizeof(SEGMENT))) == NULL) {
save_errno = errno;
(void)hdestroy(hashp);
errno = save_errno;
return (-1);
}
- for (i = 0; i < nsegs; i++, hashp->nsegs++)
+ for (i = 0; i < nsegs; i++)
hashp->dir[i] = &store[i << hashp->SSHIFT];
return (0);
}
* Hashp->hdr needs to be byteswapped.
*/
static void
-swap_header_copy(srcp, destp)
- HASHHDR *srcp, *destp;
+swap_header_copy(HASHHDR *srcp, HASHHDR *destp)
{
int i;
}
static void
-swap_header(hashp)
- HTAB *hashp;
+swap_header(HTAB *hashp)
{
HASHHDR *hdrp;
int i;
* 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.
* SUCH DAMAGE.
*
* @(#)hash.h 8.3 (Berkeley) 5/31/94
- * $FreeBSD: src/lib/libc/db/hash/hash.h,v 1.6 2002/03/21 22:46:26 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/hash/hash.h,v 1.9 2009/03/28 05:45:29 delphij Exp $
*/
/* Operations */
/* Hash Table Information */
typedef struct hashhdr { /* Disk resident portion */
- int magic; /* Magic NO for hash tables */
- int version; /* Version ID */
+ int32_t magic; /* Magic NO for hash tables */
+ int32_t version; /* Version ID */
u_int32_t lorder; /* Byte Order */
- int bsize; /* Bucket/Page Size */
- int bshift; /* Bucket shift */
- int dsize; /* Directory Size */
- int ssize; /* Segment Size */
- int sshift; /* Segment shift */
- int ovfl_point; /* Where overflow pages are being
+ int32_t bsize; /* Bucket/Page Size */
+ int32_t bshift; /* Bucket shift */
+ int32_t dsize; /* Directory Size */
+ int32_t ssize; /* Segment Size */
+ int32_t sshift; /* Segment shift */
+ int32_t ovfl_point; /* Where overflow pages are being
* allocated */
- int last_freed; /* Last overflow page freed */
- int max_bucket; /* ID of Maximum bucket in use */
- int high_mask; /* Mask to modulo into entire table */
- int low_mask; /* Mask to modulo into lower half of
+ int32_t last_freed; /* Last overflow page freed */
+ u_int32_t max_bucket; /* ID of Maximum bucket in use */
+ u_int32_t high_mask; /* Mask to modulo into entire table */
+ u_int32_t low_mask; /* Mask to modulo into lower half of
* table */
- int ffactor; /* Fill factor */
- int nkeys; /* Number of keys in hash table */
- int hdrpages; /* Size of table header */
- int h_charkey; /* value of hash(CHARKEY) */
+ u_int32_t ffactor; /* Fill factor */
+ int32_t nkeys; /* Number of keys in hash table */
+ int32_t hdrpages; /* Size of table header */
+ int32_t h_charkey; /* value of hash(CHARKEY) */
#define NCACHED 32 /* number of bit maps and spare
* points */
- int spares[NCACHED];/* spare pages for overflow */
+ int32_t spares[NCACHED];/* spare pages for overflow */
u_int16_t bitmaps[NCACHED]; /* address of overflow page
* bitmaps */
} HASHHDR;
* 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.
static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_bigkey.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_bigkey.c,v 1.10 2009/03/28 06:47:05 delphij Exp $");
/*
* PACKAGE: hash
* 0 ==> OK
*-1 ==> ERROR
*/
-extern int
-__big_insert(hashp, bufp, key, val)
- HTAB *hashp;
- BUFHEAD *bufp;
- const DBT *key, *val;
+int
+__big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
u_int16_t *p;
- int key_size, n, val_size;
+ int key_size, n;
+ unsigned int val_size;
u_int16_t space, move_bytes, off;
char *cp, *key_data, *val_data;
return (-1);
n = p[0];
if (!key_size) {
- if (FREESPACE(p)) {
- move_bytes = MIN(FREESPACE(p), val_size);
+ space = FREESPACE(p);
+ if (space) {
+ move_bytes = MIN(space, val_size);
+ /*
+ * If the data would fit exactly in the
+ * remaining space, we must overflow it to the
+ * next page; otherwise the invariant that the
+ * data must end on a page with FREESPACE
+ * non-zero would fail.
+ */
+ if (space == val_size && val_size == val->size)
+ goto toolarge;
off = OFFSET(p) - move_bytes;
- p[n] = off;
memmove(cp + off, val_data, move_bytes);
val_data += move_bytes;
val_size -= move_bytes;
+ p[n] = off;
p[n - 2] = FULL_KEY_DATA;
FREESPACE(p) = FREESPACE(p) - move_bytes;
OFFSET(p) = off;
- } else
+ } else {
+ toolarge:
p[n - 2] = FULL_KEY;
+ }
}
p = (u_int16_t *)bufp->page;
cp = bufp->page;
* 0 => OK
*-1 => ERROR
*/
-extern int
-__big_delete(hashp, bufp)
- HTAB *hashp;
- BUFHEAD *bufp;
+int
+__big_delete(HTAB *hashp, BUFHEAD *bufp)
{
BUFHEAD *last_bfp, *rbufp;
u_int16_t *bp, pageno;
n -= 2;
bp[0] = n;
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
- OFFSET(bp) = hashp->BSIZE - 1;
+ OFFSET(bp) = hashp->BSIZE;
bufp->flags |= BUF_MOD;
if (rbufp)
__free_ovflpage(hashp, rbufp);
- if (last_bfp != rbufp)
+ if (last_bfp && last_bfp != rbufp)
__free_ovflpage(hashp, last_bfp);
hashp->NKEYS--;
* -2 means key not found and this is big key/data
* -3 error
*/
-extern int
-__find_bigpair(hashp, bufp, ndx, key, size)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- char *key;
- int size;
+int
+__find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size)
{
u_int16_t *bp;
char *p;
* of the pair; 0 if there isn't any (i.e. big pair is the last key in the
* bucket)
*/
-extern u_int16_t
-__find_last_page(hashp, bpp)
- HTAB *hashp;
- BUFHEAD **bpp;
+u_int16_t
+__find_last_page(HTAB *hashp, BUFHEAD **bpp)
{
BUFHEAD *bufp;
u_int16_t *bp, pageno;
* Return the data for the key/data pair that begins on this page at this
* index (index should always be 1).
*/
-extern int
-__big_return(hashp, bufp, ndx, val, set_current)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- DBT *val;
- int set_current;
+int
+__big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current)
{
BUFHEAD *save_p;
u_int16_t *bp, len, off, save_addr;
return (0);
}
- val->size = collect_data(hashp, bufp, (int)len, set_current);
- if (val->size == -1)
+ val->size = (size_t)collect_data(hashp, bufp, (int)len, set_current);
+ if (val->size == (size_t)-1)
return (-1);
if (save_p->addr != save_addr) {
/* We are pretty short on buffers. */
* allocate a buffer and copy the data as you recurse up.
*/
static int
-collect_data(hashp, bufp, len, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len, set;
+collect_data(HTAB *hashp, BUFHEAD *bufp, int len, int set)
{
u_int16_t *bp;
char *p;
/*
* Fill in the key and data for this big pair.
*/
-extern int
-__big_keydata(hashp, bufp, key, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- DBT *key, *val;
- int set;
+int
+__big_keydata(HTAB *hashp, BUFHEAD *bufp, DBT *key, DBT *val, int set)
{
- key->size = collect_key(hashp, bufp, 0, val, set);
- if (key->size == -1)
+ key->size = (size_t)collect_key(hashp, bufp, 0, val, set);
+ if (key->size == (size_t)-1)
return (-1);
key->data = (u_char *)hashp->tmp_key;
return (0);
* collect the data, allocate a buffer and copy the key as you recurse up.
*/
static int
-collect_key(hashp, bufp, len, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len;
- DBT *val;
- int set;
+collect_key(HTAB *hashp, BUFHEAD *bufp, int len, DBT *val, int set)
{
BUFHEAD *xbp;
char *p;
* 0 => OK
* -1 => error
*/
-extern int
-__big_split(hashp, op, np, big_keyp, addr, obucket, ret)
- HTAB *hashp;
- BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */
- BUFHEAD *np; /* Pointer to new bucket page */
- /* Pointer to first page containing the big key/data */
- BUFHEAD *big_keyp;
- int addr; /* Address of big_keyp */
- u_int32_t obucket;/* Old Bucket */
- SPLIT_RETURN *ret;
+int
+__big_split(HTAB *hashp,
+ BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */
+ BUFHEAD *np, /* Pointer to new bucket page */
+ BUFHEAD *big_keyp, /* Pointer to first page containing the big key/data */
+ int addr, /* Address of big_keyp */
+ u_int32_t obucket, /* Old Bucket */
+ SPLIT_RETURN *ret)
{
- BUFHEAD *tmpp;
- u_int16_t *tp;
- BUFHEAD *bp;
+ BUFHEAD *bp, *tmpp;
DBT key, val;
u_int32_t change;
- u_int16_t free_space, n, off;
+ u_int16_t free_space, n, off, *tp;
bp = big_keyp;
if ( (ret->next_addr = __find_last_page(hashp, &big_keyp)) ) {
if (!(ret->nextp =
__get_buf(hashp, ret->next_addr, big_keyp, 0)))
- return (-1);;
+ return (-1);
} else
ret->nextp = NULL;
* 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.
static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_buf.c,v 1.7 2002/03/21 22:46:26 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_buf.c,v 1.12 2009/03/28 06:40:48 delphij Exp $");
/*
* PACKAGE: hash
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#ifdef DEBUG
#include <assert.h>
* be valid. Therefore, you must always verify that its address matches the
* address you are seeking.
*/
-extern BUFHEAD *
-__get_buf(hashp, addr, prev_bp, newpage)
- HTAB *hashp;
- u_int32_t addr;
- BUFHEAD *prev_bp;
- int newpage; /* If prev_bp set, indicates a new overflow page. */
+BUFHEAD *
+__get_buf(HTAB *hashp, u_int32_t addr,
+ BUFHEAD *prev_bp, /* If prev_bp set, indicates a new overflow page. */
+ int newpage)
{
BUFHEAD *bp;
u_int32_t is_disk_mask;
* If newbuf finds an error (returning NULL), it also sets errno.
*/
static BUFHEAD *
-newbuf(hashp, addr, prev_bp)
- HTAB *hashp;
- u_int32_t addr;
- BUFHEAD *prev_bp;
+newbuf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp)
{
BUFHEAD *bp; /* The buffer we're going to use */
BUFHEAD *xbp; /* Temp pointer */
oaddr = 0;
bp = LRU;
+
+ /* It is bad to overwrite the page under the cursor. */
+ if (bp == hashp->cpage) {
+ BUF_REMOVE(bp);
+ MRU_INSERT(bp);
+ bp = LRU;
+ }
+
+ /* If prev_bp is part of bp overflow, create a new buffer. */
+ if (hashp->nbufs == 0 && prev_bp && bp->ovfl) {
+ BUFHEAD *ovfl;
+
+ for (ovfl = bp->ovfl; ovfl ; ovfl = ovfl->ovfl) {
+ if (ovfl == prev_bp) {
+ hashp->nbufs++;
+ break;
+ }
+ }
+ }
+
/*
* If LRU buffer is pinned, the buffer pool is too small. We need to
* allocate more buffers.
*/
- if (hashp->nbufs || (bp->flags & BUF_PIN)) {
+ if (hashp->nbufs || (bp->flags & BUF_PIN) || bp == hashp->cpage) {
/* Allocate a new one */
- if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
+ if ((bp = (BUFHEAD *)calloc(1, sizeof(BUFHEAD))) == NULL)
return (NULL);
-#ifdef PURIFY
- memset(bp, 0xff, sizeof(BUFHEAD));
-#endif
- if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) {
+ if ((bp->page = (char *)calloc(1, hashp->BSIZE)) == NULL) {
free(bp);
return (NULL);
}
-#ifdef PURIFY
- memset(bp->page, 0xff, hashp->BSIZE);
-#endif
if (hashp->nbufs)
hashp->nbufs--;
} else {
*/
#ifdef DEBUG1
(void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
- prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
+ prev_bp->addr, (prev_bp->ovfl ? prev_bp->ovfl->addr : 0),
(bp ? bp->addr : 0));
#endif
prev_bp->ovfl = bp;
return (bp);
}
-extern void
-__buf_init(hashp, nbytes)
- HTAB *hashp;
- int nbytes;
+__private_extern__ void
+__buf_init(HTAB *hashp, int nbytes)
{
BUFHEAD *bfp;
int npages;
*/
}
-extern int
-__buf_free(hashp, do_free, to_disk)
- HTAB *hashp;
- int do_free, to_disk;
+int
+__buf_free(HTAB *hashp, int do_free, int to_disk)
{
BUFHEAD *bp;
}
/* Check if we are freeing stuff */
if (do_free) {
- if (bp->page)
+ if (bp->page) {
+ (void)memset(bp->page, 0, hashp->BSIZE);
free(bp->page);
+ }
BUF_REMOVE(bp);
free(bp);
bp = LRU;
return (0);
}
-extern void
-__reclaim_buf(hashp, bp)
- HTAB *hashp;
- BUFHEAD *bp;
+void
+__reclaim_buf(HTAB *hashp, BUFHEAD *bp)
{
bp->ovfl = 0;
bp->addr = 0;
* 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.
static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_func.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_func.c,v 1.6 2007/01/09 00:27:50 imp Exp $");
#include <sys/types.h>
+++ /dev/null
-./hash_log2.c
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_log2.c,v 1.5 2009/03/28 05:45:29 delphij Exp $");
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "hash_extern.h"
+
+u_int32_t
+__log2(u_int32_t num)
+{
+ u_int32_t i, limit;
+
+ limit = 1;
+ for (i = 0; limit < num; limit = limit << 1, i++);
+ return (i);
+}
* 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.
static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_page.c,v 1.8 2002/03/21 22:46:26 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_page.c,v 1.16 2009/03/28 06:30:43 delphij Exp $");
/*
* PACKAGE: hashing
*/
#include "namespace.h"
-#include <sys/types.h>
+#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include "page.h"
#include "hash_extern.h"
-static u_int32_t *fetch_bitmap(HTAB *, int);
-static u_int32_t first_free(u_int32_t);
-static int open_temp(HTAB *);
-static u_int16_t overflow_page(HTAB *);
-static void putpair(char *, const DBT *, const DBT *);
-static void squeeze_key(u_int16_t *, const DBT *, const DBT *);
-static int ugly_split
-(HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int);
+static u_int32_t *fetch_bitmap(HTAB *, int);
+static u_int32_t first_free(u_int32_t);
+static int open_temp(HTAB *);
+static u_int16_t overflow_page(HTAB *);
+static void putpair(char *, const DBT *, const DBT *);
+static void squeeze_key(u_int16_t *, const DBT *, const DBT *);
+static int ugly_split(HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int);
#define PAGE_INIT(P) { \
((u_int16_t *)(P))[0] = 0; \
* stuff on.
*/
static void
-putpair(p, key, val)
- char *p;
- const DBT *key, *val;
+putpair(char *p, const DBT *key, const DBT *val)
{
u_int16_t *bp, n, off;
* 0 OK
* -1 error
*/
-extern int
-__delpair(hashp, bufp, ndx)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
+int
+__delpair(HTAB *hashp, BUFHEAD *bufp, int ndx)
{
- u_int16_t *bp, newoff;
+ u_int16_t *bp, newoff, pairlen;
int n;
- u_int16_t pairlen;
bp = (u_int16_t *)bufp->page;
n = bp[0];
bp[i - 1] = bp[i + 1] + pairlen;
}
}
+ if (ndx == hashp->cndx) {
+ /*
+ * We just removed pair we were "pointing" to.
+ * By moving back the cndx we ensure subsequent
+ * hash_seq() calls won't skip over any entries.
+ */
+ hashp->cndx -= 2;
+ }
}
/* Finally adjust the page data */
bp[n] = OFFSET(bp) + pairlen;
* 0 ==> OK
* -1 ==> Error
*/
-extern int
-__split_page(hashp, obucket, nbucket)
- HTAB *hashp;
- u_int32_t obucket, nbucket;
+int
+__split_page(HTAB *hashp, u_int32_t obucket, u_int32_t nbucket)
{
BUFHEAD *new_bufp, *old_bufp;
u_int16_t *ino;
* -1 ==> failure
*/
static int
-ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
- HTAB *hashp;
- u_int32_t obucket; /* Same as __split_page. */
- BUFHEAD *old_bufp, *new_bufp;
- int copyto; /* First byte on page which contains key/data values. */
- int moved; /* Number of pairs moved to new page. */
+ugly_split(HTAB *hashp,
+ u_int32_t obucket, /* Same as __split_page. */
+ BUFHEAD *old_bufp,
+ BUFHEAD *new_bufp,
+ int copyto, /* First byte on page which contains key/data values. */
+ int moved) /* Number of pairs moved to new page. */
{
- BUFHEAD *bufp; /* Buffer header for ino */
- u_int16_t *ino; /* Page keys come off of */
- u_int16_t *np; /* New page */
- u_int16_t *op; /* Page keys go on to if they aren't moving */
+ BUFHEAD *bufp; /* Buffer header for ino */
+ u_int16_t *ino; /* Page keys come off of */
+ u_int16_t *np; /* New page */
+ u_int16_t *op; /* Page keys go on to if they aren't moving */
BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */
DBT key, val;
* 0 ==> OK
* 1 ==> failure
*/
-extern int
-__addel(hashp, bufp, key, val)
- HTAB *hashp;
- BUFHEAD *bufp;
- const DBT *key, *val;
+int
+__addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
u_int16_t *bp, *sop;
int do_expand;
if (!bufp)
return (-1);
bp = (u_int16_t *)bufp->page;
- } else
+ } else if (bp[bp[0]] != OVFLPAGE) {
+ /* Short key/data pairs, no more pages */
+ break;
+ } else {
/* Try to squeeze key on this page */
- if (FREESPACE(bp) > PAIRSIZE(key, val)) {
+ if (bp[2] >= REAL_KEY &&
+ FREESPACE(bp) >= PAIRSIZE(key, val)) {
squeeze_key(bp, key, val);
- return (0);
+ goto stats;
} else {
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!bufp)
return (-1);
bp = (u_int16_t *)bufp->page;
}
+ }
if (PAIRFITS(bp, key, val))
putpair(bufp->page, key, val);
if (__big_insert(hashp, bufp, key, val))
return (-1);
}
+stats:
bufp->flags |= BUF_MOD;
/*
* If the average number of keys per bucket exceeds the fill factor,
* pointer on success
* NULL on error
*/
-extern BUFHEAD *
-__add_ovflpage(hashp, bufp)
- HTAB *hashp;
- BUFHEAD *bufp;
+BUFHEAD *
+__add_ovflpage(HTAB *hashp, BUFHEAD *bufp)
{
- u_int16_t *sp;
- u_int16_t ndx, ovfl_num;
+ u_int16_t *sp, ndx, ovfl_num;
#ifdef DEBUG1
int tmp1, tmp2;
#endif
* 0 indicates SUCCESS
* -1 indicates FAILURE
*/
-extern int
-__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
- HTAB *hashp;
- char *p;
- u_int32_t bucket;
- int is_bucket, is_disk, is_bitmap;
+int
+__get_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_disk,
+ int is_bitmap)
{
- int fd, page, size;
- int rsize;
+ int fd, page, size, rsize;
u_int16_t *bp;
fd = hashp->fp;
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((rsize = _read(fd, p, size)) == -1))
+ if ((rsize = pread(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
return (-1);
bp = (u_int16_t *)p;
if (!rsize)
* 0 ==> OK
* -1 ==>failure
*/
-extern int
-__put_page(hashp, p, bucket, is_bucket, is_bitmap)
- HTAB *hashp;
- char *p;
- u_int32_t bucket;
- int is_bucket, is_bitmap;
+int
+__put_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_bitmap)
{
- int fd, page, size;
- int wsize, max;
+ int fd, page, size, wsize, max;
size = hashp->BSIZE;
if ((hashp->fp == -1) && open_temp(hashp))
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((wsize = _write(fd, p, size)) == -1))
+ if ((wsize = pwrite(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
/* Errno is set */
return (-1);
if (wsize != size) {
* Initialize a new bitmap page. Bitmap pages are left in memory
* once they are read in.
*/
-extern int
-__ibitmap(hashp, pnum, nbits, ndx)
- HTAB *hashp;
- int pnum, nbits, ndx;
+int
+__ibitmap(HTAB *hashp, int pnum, int nbits, int ndx)
{
u_int32_t *ip;
int clearbytes, clearints;
}
static u_int32_t
-first_free(map)
- u_int32_t map;
+first_free(u_int32_t map)
{
u_int32_t i, mask;
}
static u_int16_t
-overflow_page(hashp)
- HTAB *hashp;
+overflow_page(HTAB *hashp)
{
u_int32_t *freep;
int max_free, offset, splitnum;
if (offset > SPLITMASK) {
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
free_page++;
if (free_page >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
/*
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG,
sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
/* Calculate the split number for this page */
for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
offset = (i ? bit - hashp->SPARES[i - 1] : bit);
- if (offset >= SPLITMASK)
+ if (offset >= SPLITMASK) {
+ (void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0); /* Out of overflow pages */
+ }
addr = OADDR_OF(i, offset);
#ifdef DEBUG2
(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
/*
* Mark this overflow page as free.
*/
-extern void
-__free_ovflpage(hashp, obufp)
- HTAB *hashp;
- BUFHEAD *obufp;
+void
+__free_ovflpage(HTAB *hashp, BUFHEAD *obufp)
{
u_int16_t addr;
u_int32_t *freep;
* -1 failure
*/
static int
-open_temp(hashp)
- HTAB *hashp;
+open_temp(HTAB *hashp)
{
sigset_t set, oset;
- static char namestr[] = "_hashXXXXXX";
+ int len;
+ char *envtmp = NULL;
+ char path[MAXPATHLEN];
+
+ if (issetugid() == 0)
+ envtmp = getenv("TMPDIR");
+ len = snprintf(path,
+ sizeof(path), "%s/_hash.XXXXXX", envtmp ? envtmp : "/tmp");
+ if (len < 0 || len >= sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
/* Block signals; make sure file goes away at process exit. */
(void)sigfillset(&set);
(void)_sigprocmask(SIG_BLOCK, &set, &oset);
- if ((hashp->fp = mkstemp(namestr)) != -1) {
- (void)unlink(namestr);
+ if ((hashp->fp = mkstemp(path)) != -1) {
+ (void)unlink(path);
(void)_fcntl(hashp->fp, F_SETFD, 1);
}
(void)_sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
* an overflow pair, so we need to shift things.
*/
static void
-squeeze_key(sp, key, val)
- u_int16_t *sp;
- const DBT *key, *val;
+squeeze_key(u_int16_t *sp, const DBT *key, const DBT *val)
{
char *p;
u_int16_t free_space, n, off, pageno;
}
static u_int32_t *
-fetch_bitmap(hashp, ndx)
- HTAB *hashp;
- int ndx;
+fetch_bitmap(HTAB *hashp, int ndx)
{
if (ndx >= hashp->nmaps)
return (NULL);
#ifdef DEBUG4
int
-print_chain(addr)
- int addr;
+print_chain(int addr)
{
BUFHEAD *bufp;
short *bp, oaddr;
* 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.
static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/ndbm.c,v 1.6 2002/03/22 21:52:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/ndbm.c,v 1.7 2007/01/09 00:27:51 imp Exp $");
/*
* This package provides a dbm compatible interface to the new hashing
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)btree.3 8.4 (Berkeley) 8/18/94
-.\" $FreeBSD: src/lib/libc/db/man/btree.3,v 1.8 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/db/man/btree.3,v 1.9 2007/01/09 00:27:51 imp Exp $
.\"
.Dd August 18, 1994
.Dt BTREE 3
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/db/man/dbm.3,v 1.8 2003/09/08 19:57:13 ru Exp $
+.\" $FreeBSD: src/lib/libc/db/man/dbm.3,v 1.10 2009/01/30 15:28:35 gabor Exp $
.\"
-.\" Note: The date here should be updated whenever a non-trivial
-.\" change is made to the manual page.
-.Dd July 7, 1999
+.Dd April 16, 2006
.Dt DBM 3
.Os
.Sh NAME
is a typical value for
.Fa mode .
.Dv O_WRONLY
-is treated as O_RDWR in
+is not allowed in
.Fa flags .
The pointer returned by
.Fn dbm_open
.Fn dbm_close db
function
closes the database.
-The
-.Fn dbm_close
-function
-normally returns zero.
.Pp
The
.Fn dbm_store db key data flags
---- dbm.3 2005-07-28 16:23:28.000000000 -0700
-+++ dbm.3.edit 2006-07-12 11:16:35.000000000 -0700
-@@ -33,28 +33,54 @@
+--- dbm.3.orig 2009-11-06 12:44:50.000000000 -0800
++++ dbm.3 2009-11-06 12:49:59.000000000 -0800
+@@ -31,28 +31,54 @@
.Nm dbm_store
.Nd database access functions
.Sh SYNOPSIS
.Sh DESCRIPTION
Database access functions.
These functions are implemented using
-@@ -74,38 +100,38 @@
+@@ -72,38 +98,38 @@ typedef struct {
.Ed
.Pp
The
-.Fa mode .
+.Fa file_mode .
.Dv O_WRONLY
- is treated as O_RDWR in
+ is not allowed in
-.Fa flags .
+.Fa open_flags .
The pointer returned by
.Fn dbm_open
identifies the database and is the
-@@ -130,18 +156,18 @@
- normally returns zero.
+@@ -124,18 +150,18 @@ function
+ closes the database.
.Pp
The
-.Fn dbm_store db key data flags
is
.Dv DBM_INSERT
and the database already contains an entry for
-@@ -153,7 +179,7 @@
+@@ -147,7 +173,7 @@ The
function
normally returns zero but returns 1 if the entry could not be
inserted (because
is
.Dv DBM_INSERT ,
and an entry with
-@@ -168,7 +194,7 @@
+@@ -162,7 +188,7 @@ function
returns
.Dv NULL
or the
corresponding to
.Fa key .
.Pp
-@@ -223,10 +249,30 @@
+@@ -217,10 +243,30 @@ The
.Fn dbm_dirfno db
function
returns the file descriptor to the database.
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)dbopen.3 8.5 (Berkeley) 1/2/94
-.\" $FreeBSD: src/lib/libc/db/man/dbopen.3,v 1.10 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/db/man/dbopen.3,v 1.13 2007/01/09 00:27:51 imp Exp $
.\"
.Dd January 2, 1994
.Dt DBOPEN 3
.\".Bl -tag -width indent
.\".It Dv DB_LOCK
.\"Do the necessary locking in the database to support concurrent access.
-.\"If concurrent access isn't needed or the database is read-only this
+.\"If concurrent access is not needed or the database is read-only this
.\"flag should not be set, as it tends to have an associated performance
.\"penalty.
.\".It Dv DB_SHMEM
.Bd -literal
typedef struct {
DBTYPE type;
- int (*close)(const DB *db);
+ int (*close)(DB *db);
int (*del)(const DB *db, const DBT *key, u_int flags);
int (*fd)(const DB *db);
- int (*get)(const DB *db, DBT *key, DBT *data, u_int flags);
+ int (*get)(const DB *db, const DBT *key, DBT *data, u_int flags);
int (*put)(const DB *db, DBT *key, const DBT *data,
u_int flags);
int (*sync)(const DB *db, u_int flags);
is a mnemonic for
.Dq "data base thang" ,
and was used
-because noone could think of a reasonable name that wasn't already used.
+because noone could think of a reasonable name that was not already used.
.Pp
The file descriptor interface is a kluge and will be deleted in a
future version of the interface.
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)hash.3 8.6 (Berkeley) 8/18/94
-.\" $FreeBSD: src/lib/libc/db/man/hash.3,v 1.8 2003/09/08 19:57:13 ru Exp $
+.\" $FreeBSD: src/lib/libc/db/man/hash.3,v 1.9 2007/01/09 00:27:51 imp Exp $
.\"
.Dd August 18, 1994
.Dt HASH 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)mpool.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/db/man/mpool.3,v 1.13 2004/08/27 14:51:21 roam Exp $
+.\" $FreeBSD: src/lib/libc/db/man/mpool.3,v 1.15 2007/01/09 00:27:51 imp Exp $
.\"
.Dd June 4, 1993
.Dt MPOOL 3
for the following:
.Bl -tag -width Er
.It Bq Er EINVAL
-The requested record doesn't exist.
+The requested record does not exist.
.El
.Pp
The
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)recno.3 8.5 (Berkeley) 8/18/94
-.\" $FreeBSD: src/lib/libc/db/man/recno.3,v 1.8 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/db/man/recno.3,v 1.9 2007/01/09 00:27:51 imp Exp $
.\"
.Dd August 18, 1994
.Dt RECNO 3
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/db/man/dbm.3,v 1.8 2003/09/08 19:57:13 ru Exp $
+.\" $FreeBSD: src/lib/libc/db/man/dbm.3,v 1.10 2009/01/30 15:28:35 gabor Exp $
.\"
-.\" Note: The date here should be updated whenever a non-trivial
-.\" change is made to the manual page.
-.Dd July 7, 1999
+.Dd April 16, 2006
.Dt DBM 3
.Os
.Sh NAME
is a typical value for
.Fa file_mode .
.Dv O_WRONLY
-is treated as O_RDWR in
+is not allowed in
.Fa open_flags .
The pointer returned by
.Fn dbm_open
.Fn dbm_close db
function
closes the database.
-The
-.Fn dbm_close
-function
-normally returns zero.
.Pp
The
.Fn dbm_store db key content store_mode
* 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.
static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/mpool/mpool.c,v 1.12 2004/09/10 05:41:41 kuriyama Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/mpool/mpool.c,v 1.16 2009/03/28 04:00:46 delphij Exp $");
#include "namespace.h"
#include <sys/param.h>
* mpool_open --
* Initialize a memory pool.
*/
+/* ARGSUSED */
MPOOL *
-mpool_open(key, fd, pagesize, maxcache)
- void *key;
- int fd;
- pgno_t pagesize, maxcache;
+mpool_open(void *key, int fd, pgno_t pagesize, pgno_t maxcache)
{
struct stat sb;
MPOOL *mp;
* Initialize input/output filters.
*/
void
-mpool_filter(mp, pgin, pgout, pgcookie)
- MPOOL *mp;
- void (*pgin)(void *, pgno_t, void *);
- void (*pgout)(void *, pgno_t, void *);
- void *pgcookie;
+mpool_filter(MPOOL *mp, void (*pgin) (void *, pgno_t, void *),
+ void (*pgout) (void *, pgno_t, void *), void *pgcookie)
{
mp->pgin = pgin;
mp->pgout = pgout;
* mpool_get
* Get a page.
*/
+/* ARGSUSED */
void *
-mpool_get(mp, pgno, flags)
- MPOOL *mp;
- pgno_t pgno;
- u_int flags; /* XXX not used? */
+mpool_get(MPOOL *mp, pgno_t pgno,
+ u_int flags) /* XXX not used? */
{
struct _hqh *head;
BKT *bp;
* mpool_put
* Return a page.
*/
+/* ARGSUSED */
int
-mpool_put(mp, page, flags)
- MPOOL *mp;
- void *page;
- u_int flags;
+mpool_put(MPOOL *mp, void *page, u_int flags)
{
BKT *bp;
* Close the buffer pool.
*/
int
-mpool_close(mp)
- MPOOL *mp;
+mpool_close(MPOOL *mp)
{
BKT *bp;
* Sync the pool to disk.
*/
int
-mpool_sync(mp)
- MPOOL *mp;
+mpool_sync(MPOOL *mp)
{
BKT *bp;
* Get a page from the cache (or create one).
*/
static BKT *
-mpool_bkt(mp)
- MPOOL *mp;
+mpool_bkt(MPOOL *mp)
{
struct _hqh *head;
BKT *bp;
return (bp);
}
-new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
+new: if ((bp = (BKT *)calloc(1, sizeof(BKT) + mp->pagesize)) == NULL)
return (NULL);
#ifdef STATISTICS
++mp->pagealloc;
-#endif
-#if defined(DEBUG) || defined(PURIFY)
- memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
#endif
bp->page = (char *)bp + sizeof(BKT);
++mp->curcache;
* Write a page to disk.
*/
static int
-mpool_write(mp, bp)
- MPOOL *mp;
- BKT *bp;
+mpool_write(MPOOL *mp, BKT *bp)
{
off_t off;
* Lookup a page in the cache.
*/
static BKT *
-mpool_look(mp, pgno)
- MPOOL *mp;
- pgno_t pgno;
+mpool_look(MPOOL *mp, pgno_t pgno)
{
struct _hqh *head;
BKT *bp;
* Print out cache statistics.
*/
void
-mpool_stat(mp)
- MPOOL *mp;
+mpool_stat(MPOOL *mp)
{
BKT *bp;
int cnt;
char *sep;
- (void)fprintf(stderr, "%u pages in the file\n", mp->npages);
+ (void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
(void)fprintf(stderr,
- "page size %lu, cacheing %u pages of %u page max cache\n",
+ "page size %lu, cacheing %lu pages of %lu page max cache\n",
mp->pagesize, mp->curcache, mp->maxcache);
(void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
mp->pageput, mp->pageget, mp->pagenew);
---- mpool.c.orig 2008-09-07 11:37:54.000000000 -0700
-+++ mpool.c 2008-09-07 12:46:41.000000000 -0700
-@@ -128,7 +128,7 @@ mpool_new(mp, pgnoaddr)
+--- mpool.c.orig 2009-11-06 12:36:03.000000000 -0800
++++ mpool.c 2009-11-06 12:36:15.000000000 -0800
+@@ -119,7 +119,7 @@ mpool_new(mp, pgnoaddr)
if (mp->npages == MAX_PAGE_NUMBER) {
(void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
}
#ifdef STATISTICS
++mp->pagenew;
-@@ -180,7 +180,7 @@ mpool_get(mp, pgno, flags)
+@@ -170,7 +170,7 @@ mpool_get(MPOOL *mp, pgno_t pgno,
if (bp->flags & MPOOL_PINNED) {
(void)fprintf(stderr,
"mpool_get: page %d already pinned\n", bp->pgno);
}
#endif
/*
-@@ -253,7 +253,7 @@ mpool_put(mp, page, flags)
+@@ -241,7 +241,7 @@ mpool_put(MPOOL *mp, void *page, u_int f
if (!(bp->flags & MPOOL_PINNED)) {
(void)fprintf(stderr,
"mpool_put: page %d not pinned\n", bp->pgno);
}
#endif
bp->flags &= ~MPOOL_PINNED;
-@@ -294,10 +294,16 @@ mpool_sync(mp)
+@@ -280,10 +280,16 @@ mpool_sync(MPOOL *mp)
BKT *bp;
/* Walk the lru chain, flushing any dirty pages to disk. */
* 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.
static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/mpool/mpool.c,v 1.12 2004/09/10 05:41:41 kuriyama Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/mpool/mpool.c,v 1.16 2009/03/28 04:00:46 delphij Exp $");
#include "namespace.h"
#include <sys/param.h>
* mpool_open --
* Initialize a memory pool.
*/
+/* ARGSUSED */
MPOOL *
-mpool_open(key, fd, pagesize, maxcache)
- void *key;
- int fd;
- pgno_t pagesize, maxcache;
+mpool_open(void *key, int fd, pgno_t pagesize, pgno_t maxcache)
{
struct stat sb;
MPOOL *mp;
* Initialize input/output filters.
*/
void
-mpool_filter(mp, pgin, pgout, pgcookie)
- MPOOL *mp;
- void (*pgin)(void *, pgno_t, void *);
- void (*pgout)(void *, pgno_t, void *);
- void *pgcookie;
+mpool_filter(MPOOL *mp, void (*pgin) (void *, pgno_t, void *),
+ void (*pgout) (void *, pgno_t, void *), void *pgcookie)
{
mp->pgin = pgin;
mp->pgout = pgout;
* mpool_get
* Get a page.
*/
+/* ARGSUSED */
void *
-mpool_get(mp, pgno, flags)
- MPOOL *mp;
- pgno_t pgno;
- u_int flags; /* XXX not used? */
+mpool_get(MPOOL *mp, pgno_t pgno,
+ u_int flags) /* XXX not used? */
{
struct _hqh *head;
BKT *bp;
* mpool_put
* Return a page.
*/
+/* ARGSUSED */
int
-mpool_put(mp, page, flags)
- MPOOL *mp;
- void *page;
- u_int flags;
+mpool_put(MPOOL *mp, void *page, u_int flags)
{
BKT *bp;
* Close the buffer pool.
*/
int
-mpool_close(mp)
- MPOOL *mp;
+mpool_close(MPOOL *mp)
{
BKT *bp;
* Sync the pool to disk.
*/
int
-mpool_sync(mp)
- MPOOL *mp;
+mpool_sync(MPOOL *mp)
{
BKT *bp;
* Get a page from the cache (or create one).
*/
static BKT *
-mpool_bkt(mp)
- MPOOL *mp;
+mpool_bkt(MPOOL *mp)
{
struct _hqh *head;
BKT *bp;
return (bp);
}
-new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
+new: if ((bp = (BKT *)calloc(1, sizeof(BKT) + mp->pagesize)) == NULL)
return (NULL);
#ifdef STATISTICS
++mp->pagealloc;
-#endif
-#if defined(DEBUG) || defined(PURIFY)
- memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
#endif
bp->page = (char *)bp + sizeof(BKT);
++mp->curcache;
* Write a page to disk.
*/
static int
-mpool_write(mp, bp)
- MPOOL *mp;
- BKT *bp;
+mpool_write(MPOOL *mp, BKT *bp)
{
off_t off;
* Lookup a page in the cache.
*/
static BKT *
-mpool_look(mp, pgno)
- MPOOL *mp;
- pgno_t pgno;
+mpool_look(MPOOL *mp, pgno_t pgno)
{
struct _hqh *head;
BKT *bp;
* Print out cache statistics.
*/
void
-mpool_stat(mp)
- MPOOL *mp;
+mpool_stat(MPOOL *mp)
{
BKT *bp;
int cnt;
char *sep;
- (void)fprintf(stderr, "%u pages in the file\n", mp->npages);
+ (void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
(void)fprintf(stderr,
- "page size %lu, cacheing %u pages of %u page max cache\n",
+ "page size %lu, cacheing %lu pages of %lu page max cache\n",
mp->pagesize, mp->curcache, mp->maxcache);
(void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
mp->pageput, mp->pageget, mp->pagenew);
* 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.
* SUCH DAMAGE.
*
* @(#)extern.h 8.3 (Berkeley) 6/4/94
- * $FreeBSD: src/lib/libc/db/recno/extern.h,v 1.2 2002/03/21 22:46:28 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/recno/extern.h,v 1.3 2007/01/09 00:27:51 imp Exp $
*/
#include "../btree/extern.h"
---- extern.h.orig Thu Mar 21 14:46:28 2002
-+++ extern.h Sat Oct 18 19:49:46 2003
-@@ -34,7 +34,7 @@
- * $FreeBSD: src/lib/libc/db/recno/extern.h,v 1.2 2002/03/21 22:46:28 obrien Exp $
+--- extern.h.orig 2009-11-06 12:44:16.000000000 -0800
++++ extern.h 2009-11-06 12:44:28.000000000 -0800
+@@ -30,7 +30,7 @@
+ * $FreeBSD: src/lib/libc/db/recno/extern.h,v 1.3 2007/01/09 00:27:51 imp Exp $
*/
-#include "../btree/extern.h"
* 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.
static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_close.c,v 1.7 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_close.c,v 1.11 2009/03/28 05:45:29 delphij Exp $");
#include "namespace.h"
#include <sys/types.h>
* RET_ERROR, RET_SUCCESS
*/
int
-__rec_close(dbp)
- DB *dbp;
+__rec_close(DB *dbp)
{
BTREE *t;
int status;
if (F_ISSET(t, R_CLOSEFP)) {
if (fclose(t->bt_rfp))
status = RET_ERROR;
- } else
+ } else {
if (_close(t->bt_rfd))
status = RET_ERROR;
+ }
}
if (__bt_close(dbp) == RET_ERROR)
* RET_SUCCESS, RET_ERROR.
*/
int
-__rec_sync(dbp, flags)
- const DB *dbp;
- u_int flags;
+__rec_sync(const DB *dbp, u_int flags)
{
struct iovec iov[2];
BTREE *t;
status = (dbp->seq)(dbp, &key, &data, R_FIRST);
while (status == RET_SUCCESS) {
if (_write(t->bt_rfd, data.data, data.size) !=
- data.size)
+ (ssize_t)data.size)
return (RET_ERROR);
status = (dbp->seq)(dbp, &key, &data, R_NEXT);
}
} else {
- iov[1].iov_base = (char *)&t->bt_bval;
+ iov[1].iov_base = &t->bt_bval;
iov[1].iov_len = 1;
status = (dbp->seq)(dbp, &key, &data, R_FIRST);
while (status == RET_SUCCESS) {
iov[0].iov_base = data.data;
iov[0].iov_len = data.size;
- if (_writev(t->bt_rfd, iov, 2) != data.size + 1)
+ if (_writev(t->bt_rfd, iov, 2) != (ssize_t)(data.size + 1))
return (RET_ERROR);
status = (dbp->seq)(dbp, &key, &data, R_NEXT);
}
* 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.
static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_delete.c,v 1.2 2002/03/21 22:46:28 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_delete.c,v 1.5 2009/03/03 02:16:12 delphij Exp $");
#include <sys/types.h>
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
*/
int
-__rec_delete(dbp, key, flags)
- const DB *dbp;
- const DBT *key;
- u_int flags;
+__rec_delete(const DB *dbp, const DBT *key, u_int flags)
{
BTREE *t;
recno_t nrec;
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
*/
static int
-rec_rdelete(t, nrec)
- BTREE *t;
- recno_t nrec;
+rec_rdelete(BTREE *t, recno_t nrec)
{
EPG *e;
PAGE *h;
*
* Parameters:
* t: tree
- * index: index on current page to delete
+ * idx: index on current page to delete
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*/
int
-__rec_dleaf(t, h, index)
- BTREE *t;
- PAGE *h;
- u_int32_t index;
+__rec_dleaf(BTREE *t, PAGE *h, u_int32_t idx)
{
RLEAF *rl;
indx_t *ip, cnt, offset;
* down, overwriting the deleted record and its index. If the record
* uses overflow pages, make them available for reuse.
*/
- to = rl = GETRLEAF(h, index);
+ to = rl = GETRLEAF(h, idx);
if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
return (RET_ERROR);
nbytes = NRLEAF(rl);
memmove(from + nbytes, from, (char *)to - from);
h->upper += nbytes;
- offset = h->linp[index];
- for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip)
+ offset = h->linp[idx];
+ for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip)
if (ip[0] < offset)
ip[0] += nbytes;
for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
* 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.
static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_get.c,v 1.5 2002/03/22 21:52:02 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_get.c,v 1.8 2009/03/05 00:57:01 delphij Exp $");
#include <sys/types.h>
* RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
*/
int
-__rec_get(dbp, key, data, flags)
- const DB *dbp;
- const DBT *key;
- DBT *data;
- u_int flags;
+__rec_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)
{
BTREE *t;
EPG *e;
* RET_ERROR, RET_SUCCESS
*/
int
-__rec_fpipe(t, top)
- BTREE *t;
- recno_t top;
+__rec_fpipe(BTREE *t, recno_t top)
{
DBT data;
recno_t nrec;
u_char *p;
if (t->bt_rdata.size < t->bt_reclen) {
- t->bt_rdata.data = t->bt_rdata.data == NULL ?
- malloc(t->bt_reclen) :
- reallocf(t->bt_rdata.data, t->bt_reclen);
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);
if (t->bt_rdata.data == NULL)
return (RET_ERROR);
t->bt_rdata.size = t->bt_reclen;
* RET_ERROR, RET_SUCCESS
*/
int
-__rec_vpipe(t, top)
- BTREE *t;
- recno_t top;
+__rec_vpipe(BTREE *t, recno_t top)
{
DBT data;
recno_t nrec;
if (sz == 0) {
len = p - (u_char *)t->bt_rdata.data;
t->bt_rdata.size += (sz = 256);
- t->bt_rdata.data = t->bt_rdata.data == NULL ?
- malloc(t->bt_rdata.size) :
- reallocf(t->bt_rdata.data, t->bt_rdata.size);
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_rdata.size);
if (t->bt_rdata.data == NULL)
return (RET_ERROR);
p = (u_char *)t->bt_rdata.data + len;
* RET_ERROR, RET_SUCCESS
*/
int
-__rec_fmap(t, top)
- BTREE *t;
- recno_t top;
+__rec_fmap(BTREE *t, recno_t top)
{
DBT data;
recno_t nrec;
size_t len;
if (t->bt_rdata.size < t->bt_reclen) {
- t->bt_rdata.data = t->bt_rdata.data == NULL ?
- malloc(t->bt_reclen) :
- reallocf(t->bt_rdata.data, t->bt_reclen);
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);
if (t->bt_rdata.data == NULL)
return (RET_ERROR);
t->bt_rdata.size = t->bt_reclen;
* RET_ERROR, RET_SUCCESS
*/
int
-__rec_vmap(t, top)
- BTREE *t;
- recno_t top;
+__rec_vmap(BTREE *t, recno_t top)
{
DBT data;
u_char *sp, *ep;
* 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.
static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_open.c,v 1.6 2002/03/22 21:52:02 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_open.c,v 1.9 2009/03/04 00:58:04 delphij Exp $");
#include "namespace.h"
#include <sys/types.h>
#include "recno.h"
DB *
-__rec_open(fname, flags, mode, openinfo, dflags)
- const char *fname;
- int flags, mode, dflags;
- const RECNOINFO *openinfo;
+__rec_open(const char *fname, int flags, int mode, const RECNOINFO *openinfo,
+ int dflags)
{
BTREE *t;
BTREEINFO btopeninfo;
if (openinfo && openinfo->flags & R_SNAPSHOT &&
!F_ISSET(t, R_EOF | R_INMEM) &&
t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
- goto err;
+ goto err;
return (dbp);
einval: errno = EINVAL;
}
int
-__rec_fd(dbp)
- const DB *dbp;
+__rec_fd(const DB *dbp)
{
BTREE *t;
* 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.
static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_put.c,v 1.6 2002/03/22 21:52:02 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_put.c,v 1.11 2009/03/28 05:45:29 delphij Exp $");
#include <sys/types.h>
* already in the tree and R_NOOVERWRITE specified.
*/
int
-__rec_put(dbp, key, data, flags)
- const DB *dbp;
- DBT *key;
- const DBT *data;
- u_int flags;
+__rec_put(const DB *dbp, DBT *key, const DBT *data, u_int flags)
{
BTREE *t;
DBT fdata, tdata;
t->bt_cursor.rcursor = nrec;
break;
}
-
+
F_SET(t, R_MODIFIED);
return (__rec_ret(t, NULL, nrec, key, NULL));
}
* RET_ERROR, RET_SUCCESS
*/
int
-__rec_iput(t, nrec, data, flags)
- BTREE *t;
- recno_t nrec;
- const DBT *data;
- u_int flags;
+__rec_iput(BTREE *t, recno_t nrec, const DBT *data, u_int flags)
{
DBT tdata;
EPG *e;
PAGE *h;
- indx_t index, nxtindex;
+ indx_t idx, nxtindex;
pgno_t pg;
u_int32_t nbytes;
int dflags, status;
return (RET_ERROR);
h = e->page;
- index = e->index;
+ idx = e->index;
/*
* Add the specified key/data pair to the tree. The R_IAFTER and
*/
switch (flags) {
case R_IAFTER:
- ++index;
+ ++idx;
break;
case R_IBEFORE:
break;
default:
if (nrec < t->bt_nrecs &&
- __rec_dleaf(t, h, index) == RET_ERROR) {
+ __rec_dleaf(t, h, idx) == RET_ERROR) {
mpool_put(t->bt_mp, h, 0);
return (RET_ERROR);
}
* the offset array, shift the pointers up.
*/
nbytes = NRLEAFDBT(data->size);
- if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
- status = __bt_split(t, h, NULL, data, dflags, nbytes, index);
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
+ status = __bt_split(t, h, NULL, data, dflags, nbytes, idx);
if (status == RET_SUCCESS)
++t->bt_nrecs;
return (status);
}
- if (index < (nxtindex = NEXTINDEX(h)))
- memmove(h->linp + index + 1, h->linp + index,
- (nxtindex - index) * sizeof(indx_t));
+ if (idx < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + idx + 1, h->linp + idx,
+ (nxtindex - idx) * sizeof(indx_t));
h->lower += sizeof(indx_t);
- h->linp[index] = h->upper -= nbytes;
+ h->linp[idx] = h->upper -= nbytes;
dest = (char *)h + h->upper;
WR_RLEAF(dest, data, dflags);
* 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.
static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_search.c,v 1.4 2002/03/21 18:47:38 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_search.c,v 1.8 2009/03/04 00:58:04 delphij Exp $");
#include <sys/types.h>
* Parameters:
* t: tree to search
* recno: key to find
- * op: search operation
+ * op: search operation
*
* Returns:
* EPG for matching record, if any, or the EPG for the location of the
* the bt_cur field of the tree. A pointer to the field is returned.
*/
EPG *
-__rec_search(t, recno, op)
- BTREE *t;
- recno_t recno;
- enum SRCHOP op;
+__rec_search(BTREE *t, recno_t recno, enum SRCHOP op)
{
- indx_t index;
+ indx_t idx;
PAGE *h;
EPGNO *parent;
RINTERNAL *r;
t->bt_cur.index = recno - total;
return (&t->bt_cur);
}
- for (index = 0, top = NEXTINDEX(h);;) {
- r = GETRINTERNAL(h, index);
- if (++index == top || total + r->nrecs > recno)
+ for (idx = 0, top = NEXTINDEX(h);;) {
+ r = GETRINTERNAL(h, idx);
+ if (++idx == top || total + r->nrecs > recno)
break;
total += r->nrecs;
}
- BT_PUSH(t, pg, index - 1);
-
+ BT_PUSH(t, pg, idx - 1);
+
pg = r->pgno;
switch (op) {
case SDELETE:
- --GETRINTERNAL(h, (index - 1))->nrecs;
+ --GETRINTERNAL(h, (idx - 1))->nrecs;
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
break;
case SINSERT:
- ++GETRINTERNAL(h, (index - 1))->nrecs;
+ ++GETRINTERNAL(h, (idx - 1))->nrecs;
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
break;
case SEARCH:
--GETRINTERNAL(h, parent->index)->nrecs;
else
++GETRINTERNAL(h, parent->index)->nrecs;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- }
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ }
errno = sverrno;
return (NULL);
}
* 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.
/* XXX use __SCCSID */
static char sccsid[] __unused = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94";
#endif /* not lint */
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_seq.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_seq.c,v 1.8 2009/03/04 00:58:04 delphij Exp $");
#include <sys/types.h>
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
int
-__rec_seq(dbp, key, data, flags)
- const DB *dbp;
- DBT *key, *data;
- u_int flags;
+__rec_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
{
BTREE *t;
EPG *e;
einval: errno = EINVAL;
return (RET_ERROR);
}
-
+
if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
if (!F_ISSET(t, R_EOF | R_INMEM) &&
(status = t->bt_irec(t, nrec)) != RET_SUCCESS)
* 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.
static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_utils.c,v 1.2 2002/03/22 21:52:02 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/recno/rec_utils.c,v 1.6 2009/03/05 00:57:01 delphij Exp $");
#include <sys/param.h>
* e: key/data pair to be returned
* nrec: record number
* key: user's key structure
- * data: user's data structure
+ * data: user's data structure
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*/
int
-__rec_ret(t, e, nrec, key, data)
- BTREE *t;
- EPG *e;
- recno_t nrec;
- DBT *key, *data;
+__rec_ret(BTREE *t, EPG *e, recno_t nrec, DBT *key, DBT *data)
{
RLEAF *rl;
void *p;
/* We have to copy the key, it's not on the page. */
if (sizeof(recno_t) > t->bt_rkey.size) {
- p = (void *)(t->bt_rkey.data == NULL ?
- malloc(sizeof(recno_t)) :
- realloc(t->bt_rkey.data, sizeof(recno_t)));
+ p = realloc(t->bt_rkey.data, sizeof(recno_t));
if (p == NULL)
return (RET_ERROR);
t->bt_rkey.data = p;
} else if (F_ISSET(t, B_DB_LOCK)) {
/* Use +1 in case the first record retrieved is 0 length. */
if (rl->dsize + 1 > t->bt_rdata.size) {
- p = (void *)(t->bt_rdata.data == NULL ?
- malloc(rl->dsize + 1) :
- realloc(t->bt_rdata.data, rl->dsize + 1));
+ p = realloc(t->bt_rdata.data, rl->dsize + 1);
if (p == NULL)
return (RET_ERROR);
t->bt_rdata.data = p;
* 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.
* SUCH DAMAGE.
*
* @(#)recno.h 8.1 (Berkeley) 6/4/93
- * $FreeBSD: src/lib/libc/db/recno/recno.h,v 1.2 2002/03/22 23:41:40 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/recno/recno.h,v 1.3 2007/01/09 00:27:52 imp Exp $
*/
enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */
---- recno/FreeBSD/recno.h.orig 2007-03-13 10:38:09.000000000 -0700
-+++ recno/FreeBSD/recno.h 2007-03-14 22:20:30.000000000 -0700
-@@ -37,4 +37,4 @@
+--- recno.h.orig 2009-11-06 12:44:16.000000000 -0800
++++ recno.h 2009-11-06 12:44:28.000000000 -0800
+@@ -33,4 +33,4 @@
enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */
#include "../btree/btree.h"
* 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.
* SUCH DAMAGE.
*
* @(#)extern.h 8.3 (Berkeley) 6/4/94
- * $FreeBSD: src/lib/libc/db/recno/extern.h,v 1.2 2002/03/21 22:46:28 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/recno/extern.h,v 1.3 2007/01/09 00:27:51 imp Exp $
*/
#include "../btree/bt_extern.h"
* 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.
* SUCH DAMAGE.
*
* @(#)recno.h 8.1 (Berkeley) 6/4/93
- * $FreeBSD: src/lib/libc/db/recno/recno.h,v 1.2 2002/03/22 23:41:40 obrien Exp $
+ * $FreeBSD: src/lib/libc/db/recno/recno.h,v 1.3 2007/01/09 00:27:52 imp Exp $
*/
enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */
.PATH: ${.CURDIR}/emulated
MISRCS+=bsd_signal.c \
+ brk.c \
lchflags.c \
lchmod.c \
lutimes.c \
tcgetsid.c
.if ${LIB} == "c"
+MAN2+= brk.2
+
+MLINKS+=brk.2 sbrk.2
+
MAN3+= bsd_signal.3 lchflags.3 lchmod.3 lutimes.3 statvfs.3 tcgetsid.3
MLINKS+=statvfs.3 fstatvfs.3
--- /dev/null
+.\" $NetBSD: brk.2,v 1.7 1995/02/27 12:31:57 cgd Exp $
+.\"
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)brk.2 8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt BRK 2
+.Os BSD 4
+.Sh NAME
+.Nm brk ,
+.Nm sbrk
+.Nd change data segment size
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft void *
+.Fn brk "const void *addr"
+.Ft void *
+.Fn sbrk "int incr"
+.Sh DESCRIPTION
+.Bf -symbolic
+The brk and sbrk functions are historical curiosities
+left over from earlier days before the advent of virtual memory management.
+.Ef
+The
+.Fn brk
+function
+sets the break or lowest address
+of a process's data segment (uninitialized data) to
+.Fa addr
+(immediately above bss).
+Data addressing is restricted between
+.Fa addr
+and the lowest stack pointer to the stack segment.
+Memory is allocated by
+.Fa brk
+in page size pieces;
+if
+.Fa addr
+is not evenly divisible by the system page size, it is
+increased to the next page boundary.
+.Pp
+.\" The
+.\" .Nm sbrk
+.\" function
+.\" allocates chunks of
+.\" .Fa incr
+.\" bytes
+.\" to the process's data space
+.\" and returns an address pointer.
+.\" The
+.\" .Xr malloc 3
+.\" function utilizes
+.\" .Nm sbrk .
+.\" .Pp
+The current value of the program break is reliably returned by
+.Dq Li sbrk(0)
+(see also
+.Xr end 3 ) .
+The
+.Xr getrlimit 2
+system call may be used to determine
+the maximum permissible size of the
+.Em data
+segment;
+it will not be possible to set the break
+beyond the
+.Em rlim_max
+value returned from a call to
+.Xr getrlimit ,
+e.g.
+.Dq qetext + rlp\(->rlim_max.
+(see
+.Xr end 3
+for the definition of
+.Em etext ) .
+.Sh RETURN VALUES
+.Nm Brk
+returns a pointer to the new end of memory if successful;
+otherwise -1 with
+.Va errno
+set to indicate why the allocation failed.
+The
+.Nm sbrk
+function returns a pointer to the base of the new storage if successful;
+otherwise -1 with
+.Va errno
+set to indicate why the allocation failed.
+.Sh ERRORS
+.Xr Sbrk
+will fail and no additional memory will be allocated if
+one of the following are true:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+The limit, as set by
+.Xr setrlimit 2 ,
+was exceeded.
+.It Bq Er ENOMEM
+The maximum possible size of a data segment (compiled into the
+system) was exceeded.
+.It Bq Er ENOMEM
+Insufficient space existed in the swap area
+to support the expansion.
+.El
+.Sh SEE ALSO
+.Xr execve 2 ,
+.Xr getrlimit 2 ,
+.Xr malloc 3 ,
+.Xr mmap 2 ,
+.Xr end 3
+.Sh BUGS
+Setting the break may fail due to a temporary lack of
+swap space. It is not possible to distinguish this
+from a failure caused by exceeding the maximum size of
+the data segment without consulting
+.Xr getrlimit .
+.Sh HISTORY
+A
+.Fn brk
+function call appeared in
+.At v7 .
--- /dev/null
+/*
+ * Copyright (c) 1999-2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * File: brk.c
+ *
+ * Unix compatibility for sbrk system call.
+ *
+ * HISTORY
+ * 09-Mar-90 Gregg Kellogg (gk) at NeXT.
+ * include <kern/mach_interface.h> instead of <kern/mach.h>
+ *
+ * 14-Feb-89 Avadis Tevanian (avie) at NeXT.
+ * Total rewrite using a fixed area of VM from break region.
+ */
+
+#include <mach/mach.h> /* for vm_allocate, vm_offset_t */
+#include <mach/vm_statistics.h>
+#include <errno.h>
+
+static int sbrk_needs_init = TRUE;
+static vm_size_t sbrk_region_size = 4*1024*1024; /* Well, what should it be? */
+static vm_address_t sbrk_curbrk;
+
+void *sbrk(int size)
+{
+ kern_return_t ret;
+
+ if (sbrk_needs_init) {
+ sbrk_needs_init = FALSE;
+ /*
+ * Allocate a big region to simulate break region.
+ */
+ ret = vm_allocate(mach_task_self(), &sbrk_curbrk, sbrk_region_size,
+ VM_MAKE_TAG(VM_MEMORY_SBRK)|TRUE);
+ if (ret != KERN_SUCCESS) {
+ errno = ENOMEM;
+ return((void *)-1);
+ }
+ }
+
+ if (size <= 0)
+ return((void *)sbrk_curbrk);
+ else if (size > sbrk_region_size) {
+ errno = ENOMEM;
+ return((void *)-1);
+ }
+ sbrk_curbrk += size;
+ sbrk_region_size -= size;
+ return((void *)(sbrk_curbrk - size));
+}
+
+void *brk(void *x)
+{
+ errno = ENOMEM;
+ return((void *)-1);
+}
#define _socketpair socketpair
#define _system system
#define _tcdrain tcdrain
+#define _usleep usleep
#define _wait wait
#define _wait4 wait4
#define _waitpid waitpid
#define __swapcontext swapcontext
#define __system system
#define __tcdrain tcdrain
+#define __usleep usleep
#define __vfscanf vfscanf
#define __wait wait
#define __waitpid waitpid
--- /dev/null
+/*-
+ * Copyright (c) 1997,98 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * 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.
+ *
+ * $FreeBSD: src/lib/libc/include/reentrant.h,v 1.3 2004/02/25 21:03:45 green Exp $
+ */
+
+/*
+ * Requirements:
+ *
+ * 1. The thread safe mechanism should be lightweight so the library can
+ * be used by non-threaded applications without unreasonable overhead.
+ *
+ * 2. There should be no dependency on a thread engine for non-threaded
+ * applications.
+ *
+ * 3. There should be no dependency on any particular thread engine.
+ *
+ * 4. The library should be able to be compiled without support for thread
+ * safety.
+ *
+ *
+ * Rationale:
+ *
+ * One approach for thread safety is to provide discrete versions of the
+ * library: one thread safe, the other not. The disadvantage of this is
+ * that libc is rather large, and two copies of a library which are 99%+
+ * identical is not an efficent use of resources.
+ *
+ * Another approach is to provide a single thread safe library. However,
+ * it should not add significant run time or code size overhead to non-
+ * threaded applications.
+ *
+ * Since the NetBSD C library is used in other projects, it should be
+ * easy to replace the mutual exclusion primitives with ones provided by
+ * another system. Similarly, it should also be easy to remove all
+ * support for thread safety completely if the target environment does
+ * not support threads.
+ *
+ *
+ * Implementation Details:
+ *
+ * The mutex primitives used by the library (mutex_t, mutex_lock, etc.)
+ * are macros which expand to the cooresponding primitives provided by
+ * the thread engine or to nothing. The latter is used so that code is
+ * not unreasonably cluttered with #ifdefs when all thread safe support
+ * is removed.
+ *
+ * The mutex macros can be directly mapped to the mutex primitives from
+ * pthreads, however it should be reasonably easy to wrap another mutex
+ * implementation so it presents a similar interface.
+ *
+ * Stub implementations of the mutex functions are provided with *weak*
+ * linkage. These functions simply return success. When linked with a
+ * thread library (i.e. -lpthread), the functions will override the
+ * stubs.
+ */
+
+#include <pthread.h>
+#include "libc_private.h"
+
+#define mutex_t pthread_mutex_t
+#define cond_t pthread_cond_t
+#define rwlock_t pthread_rwlock_t
+#define once_t pthread_once_t
+
+#define thread_key_t pthread_key_t
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
+#define ONCE_INITIALIZER PTHREAD_ONCE_INIT
+
+#define mutex_init(m, a) _pthread_mutex_init(m, a)
+#define mutex_lock(m) if (__isthreaded) \
+ _pthread_mutex_lock(m)
+#define mutex_unlock(m) if (__isthreaded) \
+ _pthread_mutex_unlock(m)
+#define mutex_trylock(m) (__isthreaded ? 0 : _pthread_mutex_trylock(m))
+
+#define cond_init(c, a, p) _pthread_cond_init(c, a)
+#define cond_signal(m) if (__isthreaded) \
+ _pthread_cond_signal(m)
+#define cond_broadcast(m) if (__isthreaded) \
+ _pthread_cond_broadcast(m)
+#define cond_wait(c, m) if (__isthreaded) \
+ _pthread_cond_wait(c, m)
+
+#define rwlock_init(l, a) _pthread_rwlock_init(l, a)
+#define rwlock_rdlock(l) if (__isthreaded) \
+ _pthread_rwlock_rdlock(l)
+#define rwlock_wrlock(l) if (__isthreaded) \
+ _pthread_rwlock_wrlock(l)
+#define rwlock_unlock(l) if (__isthreaded) \
+ _pthread_rwlock_unlock(l)
+
+#define thr_keycreate(k, d) _pthread_key_create(k, d)
+#define thr_setspecific(k, p) _pthread_setspecific(k, p)
+#define thr_getspecific(k) _pthread_getspecific(k)
+#define thr_sigsetmask(f, n, o) _pthread_sigmask(f, n, o)
+
+#define thr_once(o, i) _pthread_once(o, i)
+#define thr_self() _pthread_self()
+#define thr_exit(x) _pthread_exit(x)
+#define thr_main() _pthread_main_np()
char *
dtoa
#ifdef KR_headers
- (d, mode, ndigits, decpt, sign, rve)
- double d; int mode, ndigits, *decpt, *sign; char **rve;
+ (d0, mode, ndigits, decpt, sign, rve)
+ double d0; int mode, ndigits, *decpt, *sign; char **rve;
#else
- (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+ (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
#endif
{
/* Arguments ndigits, decpt, sign are similar to those
ULong x;
#endif
Bigint *b, *b1, *delta, *mlo, *mhi, *S;
- double d2, ds, eps;
+ U d, d2, eps;
+ double ds;
char *s, *s0;
#ifdef SET_INEXACT
int inexact, oldinexact;
dtoa_result = 0;
}
#endif
-
- if (word0(d) & Sign_bit) {
+ d.d = d0;
+ if (word0(&d) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
*sign = 1;
- word0(d) &= ~Sign_bit; /* clear sign bit */
+ word0(&d) &= ~Sign_bit; /* clear sign bit */
}
else
*sign = 0;
#if defined(IEEE_Arith) + defined(VAX)
#ifdef IEEE_Arith
- if ((word0(d) & Exp_mask) == Exp_mask)
+ if ((word0(&d) & Exp_mask) == Exp_mask)
#else
- if (word0(d) == 0x8000)
+ if (word0(&d) == 0x8000)
#endif
{
/* Infinity or NaN */
*decpt = 9999;
#ifdef IEEE_Arith
- if (!word1(d) && !(word0(d) & 0xfffff))
+ if (!word1(&d) && !(word0(&d) & 0xfffff))
return nrv_alloc("Infinity", rve, 8);
#endif
return nrv_alloc("NaN", rve, 3);
}
#endif
#ifdef IBM
- dval(d) += 0; /* normalize */
+ dval(&d) += 0; /* normalize */
#endif
- if (!dval(d)) {
+ if (!dval(&d)) {
*decpt = 1;
return nrv_alloc("0", rve, 1);
}
}
#endif
- b = d2b(dval(d), &be, &bbits);
+ b = d2b(dval(&d), &be, &bbits);
#ifdef Sudden_Underflow
- i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+ i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
- if (( i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
+ if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) {
#endif
- dval(d2) = dval(d);
- word0(d2) &= Frac_mask1;
- word0(d2) |= Exp_11;
+ dval(&d2) = dval(&d);
+ word0(&d2) &= Frac_mask1;
+ word0(&d2) |= Exp_11;
#ifdef IBM
- if (( j = 11 - hi0bits(word0(d2) & Frac_mask) )!=0)
- dval(d2) /= 1 << j;
+ if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0)
+ dval(&d2) /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / log(10)
* ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
- * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2)
*
- * This suggests computing an approximation k to log10(d) by
+ * This suggests computing an approximation k to log10(&d) by
*
* k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
/* d is denormalized */
i = bbits + be + (Bias + (P-1) - 1);
- x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
- : word1(d) << 32 - i;
- dval(d2) = x;
- word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+ x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32)
+ : word1(&d) << (32 - i);
+ dval(&d2) = x;
+ word0(&d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1;
denorm = 1;
}
#endif
- ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
k = (int)ds;
if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */
k_check = 1;
if (k >= 0 && k <= Ten_pmax) {
- if (dval(d) < tens[k])
+ if (dval(&d) < tens[k])
k--;
k_check = 0;
}
try_quick = 0;
}
leftright = 1;
+ ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
+ /* silence erroneous "gcc -Wall" warning. */
switch(mode) {
case 0:
case 1:
- ilim = ilim1 = -1;
i = 18;
ndigits = 0;
break;
/* Try to get by with floating-point arithmetic. */
i = 0;
- dval(d2) = dval(d);
+ dval(&d2) = dval(&d);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens-1];
+ dval(&d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
ieps++;
ds *= bigtens[i];
}
- dval(d) /= ds;
+ dval(&d) /= ds;
}
else if (( j1 = -k )!=0) {
- dval(d) *= tens[j1 & 0xf];
+ dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
ieps++;
- dval(d) *= bigtens[i];
+ dval(&d) *= bigtens[i];
}
}
- if (k_check && dval(d) < 1. && ilim > 0) {
+ if (k_check && dval(&d) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
- dval(d) *= 10.;
+ dval(&d) *= 10.;
ieps++;
}
- dval(eps) = ieps*dval(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
+ dval(&eps) = ieps*dval(&d) + 7.;
+ word0(&eps) -= (P-1)*Exp_msk1;
if (ilim == 0) {
S = mhi = 0;
- dval(d) -= 5.;
- if (dval(d) > dval(eps))
+ dval(&d) -= 5.;
+ if (dval(&d) > dval(&eps))
goto one_digit;
- if (dval(d) < -dval(eps))
+ if (dval(&d) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
/* Use Steele & White method of only
* generating digits needed.
*/
- dval(eps) = 0.5/tens[ilim-1] - dval(eps);
+ dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) {
- L = dval(d);
- dval(d) -= L;
+ L = dval(&d);
+ dval(&d) -= L;
*s++ = '0' + (int)L;
- if (dval(d) < dval(eps))
+ if (dval(&d) < dval(&eps))
goto ret1;
- if (1. - dval(d) < dval(eps))
+ if (1. - dval(&d) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
+ dval(&eps) *= 10.;
+ dval(&d) *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
- dval(eps) *= tens[ilim-1];
- for(i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d));
- if (!(dval(d) -= L))
+ dval(&eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = (Long)(dval(&d));
+ if (!(dval(&d) -= L))
ilim = i;
*s++ = '0' + (int)L;
if (i == ilim) {
- if (dval(d) > 0.5 + dval(eps))
+ if (dval(&d) > 0.5 + dval(&eps))
goto bump_up;
- else if (dval(d) < 0.5 - dval(eps)) {
+ else if (dval(&d) < 0.5 - dval(&eps)) {
while(*--s == '0');
s++;
goto ret1;
#endif
fast_failed:
s = s0;
- dval(d) = dval(d2);
+ dval(&d) = dval(&d2);
k = k0;
ilim = ilim0;
}
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5*ds)
+ if (ilim < 0 || dval(&d) <= 5*ds)
goto no_digits;
goto one_digit;
}
- for(i = 1;; i++, dval(d) *= 10.) {
- L = (Long)(dval(d) / ds);
- dval(d) -= L*ds;
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = (Long)(dval(&d) / ds);
+ dval(&d) -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (dval(d) < 0) {
+ if (dval(&d) < 0) {
L--;
- dval(d) += ds;
+ dval(&d) += ds;
}
#endif
*s++ = '0' + (int)L;
- if (!dval(d)) {
+ if (!dval(&d)) {
#ifdef SET_INEXACT
inexact = 0;
#endif
case 2: goto bump_up;
}
#endif
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
+ dval(&d) += dval(&d);
+ if (dval(&d) > ds || (dval(&d) == ds && L & 1)) {
bump_up:
while(*--s == '9')
if (s == s0) {
&& Rounding == 1
#endif
) {
- if (!word1(d) && !(word0(d) & Bndry_mask)
+ if (!word1(&d) && !(word0(&d) & Bndry_mask)
#ifndef Sudden_Underflow
- && word0(d) & (Exp_mask & ~Exp_msk1)
+ && word0(&d) & (Exp_mask & ~Exp_msk1)
#endif
) {
/* The special case */
j1 = delta->sign ? 1 : cmp(b, delta);
Bfree(delta);
#ifndef ROUND_BIASED
- if (j1 == 0 && mode != 1 && !(word1(d) & 1)
+ if (j1 == 0 && mode != 1 && !(word1(&d) & 1)
#ifdef Honor_FLT_ROUNDS
&& Rounding >= 1
#endif
goto ret;
}
#endif
- if (j < 0 || j == 0 && mode != 1
+ if (j < 0 || (j == 0 && mode != 1
#ifndef ROUND_BIASED
- && !(word1(d) & 1)
+ && !(word1(&d) & 1)
#endif
- ) {
+ )) {
if (!b->x[0] && b->wds <= 1) {
#ifdef SET_INEXACT
inexact = 0;
if (j1 > 0) {
b = lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1)
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
&& dig++ == '9')
goto round_9_up;
}
#endif
b = lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+ if (j > 0 || (j == 0 && dig & 1)) {
roundoff:
while(*--s == '9')
if (s == s0) {
++*s++;
}
else {
+#ifdef Honor_FLT_ROUNDS
trimzeros:
+#endif
while(*--s == '0');
s++;
}
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
- word0(d) = Exp_1 + (70 << Exp_shift);
- word1(d) = 0;
- dval(d) += 1.;
+ word0(&d) = Exp_1 + (70 << Exp_shift);
+ word1(&d) = 0;
+ dval(&d) += 1.;
}
}
else if (!oldinexact)
int rdir, s2, s5, spec_case, try_quick;
Long L;
Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S;
- double d, d2, ds, eps;
+ double d2, ds;
char *s, *s0;
+ U d, eps;
#ifndef MULTIPLE_THREADS
if (dtoa_result) {
return nrv_alloc("0", rve, 1);
}
- dval(d) = b2d(b, &i);
+ dval(&d) = b2d(b, &i);
i = be + bbits - 1;
- word0(d) &= Frac_mask1;
- word0(d) |= Exp_11;
+ word0(&d) &= Frac_mask1;
+ word0(&d) |= Exp_11;
#ifdef IBM
- if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
- dval(d) /= 1 << j;
+ if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
+ dval(&d) /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
* log10(x) = log(x) / log(10)
* ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
- * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2)
*
- * This suggests computing an approximation k to log10(d) by
+ * This suggests computing an approximation k to log10(&d) by
*
* k = (i - Bias)*0.301029995663981
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
i <<= 2;
i += j;
#endif
- ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
/* correct assumption about exponent range */
if ((j = i) < 0)
#ifdef IBM
j = be + bbits - 1;
if ( (j1 = j & 3) !=0)
- dval(d) *= 1 << j1;
- word0(d) += j << Exp_shift - 2 & Exp_mask;
+ dval(&d) *= 1 << j1;
+ word0(&d) += j << Exp_shift - 2 & Exp_mask;
#else
- word0(d) += (be + bbits - 1) << Exp_shift;
+ word0(&d) += (be + bbits - 1) << Exp_shift;
#endif
if (k >= 0 && k <= Ten_pmax) {
- if (dval(d) < tens[k])
+ if (dval(&d) < tens[k])
k--;
k_check = 0;
}
try_quick = 0;
}
leftright = 1;
+ ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */
+ /* silence erroneous "gcc -Wall" warning. */
switch(mode) {
case 0:
case 1:
- ilim = ilim1 = -1;
i = (int)(nbits * .30103) + 3;
ndigits = 0;
break;
/* Try to get by with floating-point arithmetic. */
i = 0;
- d2 = dval(d);
+ d2 = dval(&d);
#ifdef IBM
- if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0)
- dval(d) /= 1 << j;
+ if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0)
+ dval(&d) /= 1 << j;
#endif
k0 = k;
ilim0 = ilim;
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
- dval(d) /= bigtens[n_bigtens-1];
+ dval(&d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
else {
ds = 1.;
if ( (j1 = -k) !=0) {
- dval(d) *= tens[j1 & 0xf];
+ dval(&d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
ieps++;
- dval(d) *= bigtens[i];
+ dval(&d) *= bigtens[i];
}
}
}
- if (k_check && dval(d) < 1. && ilim > 0) {
+ if (k_check && dval(&d) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
- dval(d) *= 10.;
+ dval(&d) *= 10.;
ieps++;
}
- dval(eps) = ieps*dval(d) + 7.;
- word0(eps) -= (P-1)*Exp_msk1;
+ dval(&eps) = ieps*dval(&d) + 7.;
+ word0(&eps) -= (P-1)*Exp_msk1;
if (ilim == 0) {
S = mhi = 0;
- dval(d) -= 5.;
- if (dval(d) > dval(eps))
+ dval(&d) -= 5.;
+ if (dval(&d) > dval(&eps))
goto one_digit;
- if (dval(d) < -dval(eps))
+ if (dval(&d) < -dval(&eps))
goto no_digits;
goto fast_failed;
}
/* Use Steele & White method of only
* generating digits needed.
*/
- dval(eps) = ds*0.5/tens[ilim-1] - dval(eps);
+ dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps);
for(i = 0;;) {
- L = (Long)(dval(d)/ds);
- dval(d) -= L*ds;
+ L = (Long)(dval(&d)/ds);
+ dval(&d) -= L*ds;
*s++ = '0' + (int)L;
- if (dval(d) < dval(eps)) {
- if (dval(d))
+ if (dval(&d) < dval(&eps)) {
+ if (dval(&d))
inex = STRTOG_Inexlo;
goto ret1;
}
- if (ds - dval(d) < dval(eps))
+ if (ds - dval(&d) < dval(&eps))
goto bump_up;
if (++i >= ilim)
break;
- dval(eps) *= 10.;
- dval(d) *= 10.;
+ dval(&eps) *= 10.;
+ dval(&d) *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
- dval(eps) *= tens[ilim-1];
- for(i = 1;; i++, dval(d) *= 10.) {
- if ( (L = (Long)(dval(d)/ds)) !=0)
- dval(d) -= L*ds;
+ dval(&eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ if ( (L = (Long)(dval(&d)/ds)) !=0)
+ dval(&d) -= L*ds;
*s++ = '0' + (int)L;
if (i == ilim) {
ds *= 0.5;
- if (dval(d) > ds + dval(eps))
+ if (dval(&d) > ds + dval(&eps))
goto bump_up;
- else if (dval(d) < ds - dval(eps)) {
- if (dval(d))
+ else if (dval(&d) < ds - dval(&eps)) {
+ if (dval(&d))
inex = STRTOG_Inexlo;
goto clear_trailing0;
}
#endif
fast_failed:
s = s0;
- dval(d) = d2;
+ dval(&d) = d2;
k = k0;
ilim = ilim0;
}
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
- if (ilim < 0 || dval(d) <= 5*ds)
+ if (ilim < 0 || dval(&d) <= 5*ds)
goto no_digits;
goto one_digit;
}
- for(i = 1;; i++, dval(d) *= 10.) {
- L = dval(d) / ds;
- dval(d) -= L*ds;
+ for(i = 1;; i++, dval(&d) *= 10.) {
+ L = dval(&d) / ds;
+ dval(&d) -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (dval(d) < 0) {
+ if (dval(&d) < 0) {
L--;
- dval(d) += ds;
+ dval(&d) += ds;
}
#endif
*s++ = '0' + (int)L;
- if (dval(d) == 0.)
+ if (dval(&d) == 0.)
break;
if (i == ilim) {
if (rdir) {
inex = STRTOG_Inexlo;
goto ret1;
}
- dval(d) += dval(d);
- if (dval(d) > ds || dval(d) == ds && L & 1) {
+ dval(&d) += dval(&d);
+ if (dval(&d) > ds || (dval(&d) == ds && L & 1)) {
bump_up:
inex = STRTOG_Inexhi;
while(*--s == '9')
* and for all and pass them and a shift to quorem, so it
* can do shifts and ors to compute the numerator for q.
*/
-#ifdef Pack_32
- if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) !=0)
- i = 32 - i;
-#else
- if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) !=0)
- i = 16 - i;
-#endif
- if (i > 4) {
- i -= 4;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- else if (i < 4) {
- i += 28;
- b2 += i;
- m2 += i;
- s2 += i;
- }
- if (b2 > 0)
+ i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask;
+ m2 += i;
+ if ((b2 += i) > 0)
b = lshift(b, b2);
- if (s2 > 0)
+ if ((s2 += i) > 0)
S = lshift(S, s2);
if (k_check) {
if (cmp(b,S) < 0) {
goto ret;
}
#endif
- if (j < 0 || j == 0 && !mode
+ if (j < 0 || (j == 0 && !mode
#ifndef ROUND_BIASED
&& !(bits[0] & 1)
#endif
- ) {
+ )) {
if (rdir && (b->wds > 1 || b->x[0])) {
if (rdir == 2) {
inex = STRTOG_Inexlo;
if (j1 > 0) {
b = lshift(b, 1);
j1 = cmp(b, S);
- if ((j1 > 0 || j1 == 0 && dig & 1)
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
&& dig++ == '9')
goto round_9_up;
inex = STRTOG_Inexhi;
/* Round off last digit */
if (rdir) {
- if (rdir == 2 || b->wds <= 1 && !b->x[0])
+ if (rdir == 2 || (b->wds <= 1 && !b->x[0]))
goto chopzeros;
goto roundoff;
}
b = lshift(b, 1);
j = cmp(b, S);
- if (j > 0 || j == 0 && dig & 1) {
+ if (j > 0 || (j == 0 && dig & 1)) {
roundoff:
inex = STRTOG_Inexhi;
while(*--s == '9')
static unsigned char *decimalpoint_cache;
if (!(s0 = decimalpoint_cache)) {
s0 = (unsigned char*)localeconv()->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
return STRTOG_Normal | STRTOG_Inexlo;
}
n = s1 - s0 - 1;
- for(k = 0; n > 7; n >>= 1)
+ for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
k++;
b = Balloc(k);
x = b->x;
if (*--s1 == '.')
continue;
#endif
- if (n == 32) {
+ if (n == ULbits) {
*x++ = L;
L = 0;
n = 0;
}
*x++ = L;
b->wds = n = x - b->x;
- n = 32*n - hi0bits(L);
+ n = ULbits*n - hi0bits(L);
nbits = fpi->nbits;
lostbits = 0;
x = b->x;
break;
case FPI_Round_near:
if (lostbits & 2
- && (lostbits & 1) | x[0] & 1)
+ && (lostbits | x[0]) & 1)
up = 1;
break;
case FPI_Round_up:
irv = STRTOG_Normal;
}
else if (b->wds > k
- || (n = nbits & kmask) !=0
- && hi0bits(x[k-1]) < 32-n) {
+ || ((n = nbits & kmask) !=0
+ && hi0bits(x[k-1]) < 32-n)) {
rshift(b,1);
if (++e > fpi->emax)
goto ovfl;
---- gdtoa-gethex.c.orig 2008-10-28 11:14:40.000000000 -0700
-+++ gdtoa-gethex.c 2008-10-28 11:20:32.000000000 -0700
-@@ -29,6 +29,8 @@ THIS SOFTWARE.
+--- gdtoa-gethex.c.orig 2010-02-24 20:50:10.000000000 -0800
++++ gdtoa-gethex.c 2010-02-24 21:26:32.000000000 -0800
+@@ -29,34 +29,40 @@ THIS SOFTWARE.
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
+
#include "gdtoaimp.h"
++#include <sys/types.h>
++
#ifdef USE_LOCALE
-@@ -37,10 +39,10 @@ THIS SOFTWARE.
+ #include "locale.h"
+ #endif
int
#ifdef KR_headers
#endif
{
Bigint *b;
-@@ -50,13 +52,14 @@ gethex( CONST char **sp, FPI *fpi, Long
+ CONST unsigned char *decpt, *s0, *s, *s1;
++ unsigned char *strunc;
+ int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
+ ULong L, lostbits, *x;
Long e, e1;
#ifdef USE_LOCALE
int i;
if (!(s0 = decimalpoint_cache)) {
- s0 = (unsigned char*)localeconv()->decimal_point;
+ s0 = (unsigned char*)localeconv_l(loc)->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
+@@ -198,6 +204,57 @@ gethex( CONST char **sp, FPI *fpi, Long
+ *exp = fpi->emin;
+ return STRTOG_Normal | STRTOG_Inexlo;
+ }
++ /*
++ * Truncate the hex string if it is longer than the precision needed,
++ * to avoid denial-of-service issues with very large strings. Use
++ * additional digits to insure precision. Scan to-be-truncated digits
++ * and replace with either '1' or '0' to ensure proper rounding.
++ */
++ {
++ int maxdigits = ((fpi->nbits + 3) >> 2) + 2;
++ size_t nd = s1 - s0;
++#ifdef USE_LOCALE
++ int dplen = strlen((const char *)decimalpoint);
++#else
++ int dplen = 1;
++#endif
++
++ if (decpt && s0 < decpt)
++ nd -= dplen;
++ if (nd > maxdigits && (strunc = alloca(maxdigits + dplen + 2)) != NULL) {
++ ssize_t nd0 = decpt ? decpt - s0 - dplen : nd;
++ unsigned char *tp = strunc + maxdigits;
++ int found = 0;
++ if ((nd0 -= maxdigits) >= 0 || s0 >= decpt)
++ memcpy(strunc, s0, maxdigits);
++ else {
++ memcpy(strunc, s0, maxdigits + dplen);
++ tp += dplen;
++ }
++ s0 += maxdigits;
++ e += (nd - (maxdigits + 1)) << 2;
++ if (nd0 > 0) {
++ while(nd0-- > 0)
++ if (*s0++ != '0') {
++ found++;
++ break;
++ }
++ s0 += dplen;
++ }
++ if (!found && decpt) {
++ while(s0 < s1)
++ if(*s0++ != '0') {
++ found++;
++ break;
++ }
++ }
++ *tp++ = found ? '1' : '0';
++ *tp = 0;
++ s0 = strunc;
++ s1 = tp;
++ }
++ }
++
+ n = s1 - s0 - 1;
+ for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
+ k++;
if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
&& *(CONST unsigned char*)(s+3) > ' ')
s += 2;
- while(c = *(CONST unsigned char*)++s) {
+ while((c = *(CONST unsigned char*)++s)) {
if (!(h = hexdig[c])) {
if (c <= ' ') {
if (hd0 < havedig) {
*sp = s + 1;
break;
}
- } while(c = *++s);
+ } while((c = *++s));
#endif
return STRTOG_NaN;
}
i = 1;
*--x = 0;
}
- *x = (*x << 4) | h & 0xf;
+ *x = (*x << 4) | (h & 0xf);
}
if (!havedig)
return STRTOG_NaN;
---- gdtoa-hexnan.c.orig 2008-03-15 10:08:33.000000000 -0700
-+++ gdtoa-hexnan.c 2008-08-30 17:55:23.000000000 -0700
-@@ -30,6 +30,7 @@ THIS SOFTWARE.
+--- gdtoa-hexnan.c.orig 2010-01-29 16:36:11.000000000 -0800
++++ gdtoa-hexnan.c 2010-01-29 16:40:59.000000000 -0800
+@@ -30,7 +30,9 @@ THIS SOFTWARE.
* with " at " changed at "@" and " dot " changed to "."). */
#include "gdtoaimp.h"
+#include <fpmath.h>
++#ifndef __APPLE__
static void
#ifdef KR_headers
-@@ -57,94 +58,53 @@ hexnan(sp, fpi, x0)
+ L_shift(x, x1, i) ULong *x; ULong *x1; int i;
+@@ -48,6 +50,7 @@ L_shift(ULong *x, ULong *x1, int i)
+ x[1] >>= i;
+ } while(++x < x1);
+ }
++#endif /* !__APPLE__ */
+
+ int
+ #ifdef KR_headers
+@@ -57,10 +60,21 @@ hexnan(sp, fpi, x0)
hexnan( CONST char **sp, FPI *fpi, ULong *x0)
#endif
{
-- ULong c, h, *x, *x1, *xe;
++#ifdef __APPLE__
+ int nbits, len;
+ char *cp;
++#else /* !__APPLE__ */
+ ULong c, h, *x, *x1, *xe;
++#endif /* __APPLE__ */
CONST char *s;
-- int havedig, hd0, i, nbits;
++#ifndef __APPLE__
+ int havedig, hd0, i, nbits;
++#endif /* !__APPLE__ */
-- if (!hexdig['0'])
-- hexdig_init_D2A();
-- nbits = fpi->nbits;
-- x = x0 + (nbits >> kshift);
-- if (nbits & kmask)
-- x++;
-- *--x = 0;
-- x1 = xe = x;
-- havedig = hd0 = i = 0;
++#ifdef __APPLE__
+ if (sp == NULL || *sp == NULL || **sp != '(')
+ return STRTOG_NaN;
++#else /* !__APPLE__ */
+ if (!hexdig['0'])
+ hexdig_init_D2A();
+ nbits = fpi->nbits;
+@@ -70,7 +84,17 @@ hexnan( CONST char **sp, FPI *fpi, ULong
+ *--x = 0;
+ x1 = xe = x;
+ havedig = hd0 = i = 0;
++#endif /* __APPLE__ */
s = *sp;
-- /* allow optional initial 0x or 0X */
-- while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
-- ++s;
-- if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
-- && *(CONST unsigned char*)(s+3) > ' ')
-- s += 2;
-- while(c = *(CONST unsigned char*)++s) {
-- if (!(h = hexdig[c])) {
-- if (c <= ' ') {
-- if (hd0 < havedig) {
-- if (x < x1 && i < 8)
-- L_shift(x, x1, i);
-- if (x <= x0) {
-- i = 8;
-- continue;
-- }
-- hd0 = havedig;
-- *--x = 0;
-- x1 = x;
-- i = 0;
-- }
-- while(*(CONST unsigned char*)(s+1) <= ' ')
-- ++s;
-- if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
-- && *(CONST unsigned char*)(s+3) > ' ')
-- s += 2;
-- continue;
-- }
-- if (/*(*/ c == ')' && havedig) {
-- *sp = s + 1;
-- break;
-- }
--#ifndef GDTOA_NON_PEDANTIC_NANCHECK
-- do {
-- if (/*(*/ c == ')') {
-- *sp = s + 1;
-- break;
-- }
-- } while(c = *++s);
--#endif
++#ifdef __APPLE__
+ if ((cp = strchr(s + 1, ')')) == NULL) {
-+ *sp += strlen(s);
-+ cp = s + 1;
++ return STRTOG_NaN;
+ }
+ else {
+ len = cp - (s + 1);
+ cp = alloca(len + 1);
+ if (!cp)
++#else /* !__APPLE__ */
+ /* allow optional initial 0x or 0X */
+ while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
+ ++s;
+@@ -111,7 +135,12 @@ hexnan( CONST char **sp, FPI *fpi, ULong
+ }
+ } while((c = *++s));
+ #endif
++#endif /* __APPLE__ */
return STRTOG_NaN;
-- }
-- havedig++;
-- if (++i > 8) {
-- if (x <= x0)
-- continue;
-- i = 1;
-- *--x = 0;
-- }
-- *x = (*x << 4) | h & 0xf;
++#ifdef __APPLE__
+ strlcpy(cp, s + 1, len + 1);
+ *sp += len + 2;
++#else /* !__APPLE__ */
+ }
+ havedig++;
+ if (++i > 8) {
+@@ -121,7 +150,17 @@ hexnan( CONST char **sp, FPI *fpi, ULong
+ *--x = 0;
+ }
+ *x = (*x << 4) | (h & 0xf);
++#endif /* __APPLE__ */
}
-- if (!havedig)
-- return STRTOG_NaN;
-- if (x < x1 && i < 8)
-- L_shift(x, x1, i);
-- if (x > x0) {
-- x1 = x0;
-- do *x1++ = *x++;
-- while(x <= xe);
-- do *x1++ = 0;
-- while(x1 <= xe);
++#ifdef __APPLE__
+ nbits = fpi->nbits;
+ /* a hack */
+ if (nbits == 52) { /* double */
+ u.d = nan(cp);
+ x0[1] = u.bits.manh;
+ x0[0] = u.bits.manl;
++#else /* !__APPLE__ */
+ if (!havedig)
+ return STRTOG_NaN;
+ if (x < x1 && i < 8)
+@@ -132,12 +171,36 @@ hexnan( CONST char **sp, FPI *fpi, ULong
+ while(x <= xe);
+ do *x1++ = 0;
+ while(x1 <= xe);
++#endif /* __APPLE__ */
}
-- else {
-- /* truncate high-order word if necessary */
-- if ( (i = nbits & (ULbits-1)) !=0)
-- *xe &= ((ULong)0xffffffff) >> (ULbits - i);
++#ifdef __APPLE__
+ else if (nbits < 52) { /* float */
+ union IEEEf2bits u;
+ u.f = nanf(cp);
+ x0[0] = u.bits.man;
++#else /* !__APPLE__ */
+ else {
+ /* truncate high-order word if necessary */
+ if ( (i = nbits & (ULbits-1)) !=0)
+ *xe &= ((ULong)0xffffffff) >> (ULbits - i);
++#endif /* __APPLE__ */
}
-- for(x1 = xe;; --x1) {
-- if (*x1 != 0)
-- break;
-- if (x1 == x0) {
-- *x1 = 1;
-- break;
-- }
++#ifdef __APPLE__
+ else { /* long double */
+ union IEEEl2bits u;
+ u.e = nanl(cp);
+#else
+#error unsupported architecture
+#endif
++#else /* !__APPLE__ */
+ for(x1 = xe;; --x1) {
+ if (*x1 != 0)
+ break;
+@@ -145,6 +208,7 @@ hexnan( CONST char **sp, FPI *fpi, ULong
+ *x1 = 1;
+ break;
+ }
++#endif /* __APPLE__ */
}
-+
return STRTOG_NaNbits;
}
#endif
ACQUIRE_DTOA_LOCK(0);
- if ( (rv = freelist[k]) !=0) {
+ /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
+ /* but this case seems very unlikely. */
+ if (k <= Kmax && (rv = freelist[k]) !=0) {
freelist[k] = rv->next;
}
else {
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
- if (pmem_next - private_mem + len <= PRIVATE_mem) {
+ if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
rv = (Bigint*)pmem_next;
pmem_next += len;
}
#endif
{
if (v) {
- ACQUIRE_DTOA_LOCK(0);
- v->next = freelist[v->k];
- freelist[v->k] = v;
- FREE_DTOA_LOCK(0);
+ if (v->k > Kmax)
+#ifdef FREE
+ FREE((void*)v);
+#else
+ free((void*)v);
+#endif
+ else {
+ ACQUIRE_DTOA_LOCK(0);
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+ FREE_DTOA_LOCK(0);
+ }
}
}
(ULong *y)
#endif
{
- register int k;
- register ULong x = *y;
+ int k;
+ ULong x = *y;
if (x & 7) {
if (x & 1)
int
hi0bits_D2A
#ifdef KR_headers
- (x) register ULong x;
+ (x) ULong x;
#else
- (register ULong x)
+ (ULong x)
#endif
{
- register int k = 0;
+ int k = 0;
if (!(x & 0xffff0000)) {
k = 16;
{
ULong *xa, *xa0, w, y, z;
int k;
- double d;
+ U d;
#ifdef VAX
ULong d0, d1;
#else
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
#endif
xa0 = a->x;
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
+ d0 = Exp_1 | y >> (Ebits - k);
w = xa > xa0 ? *--xa : 0;
- d1 = y << (32-Ebits) + k | w >> Ebits - k;
+ d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
+ d0 = Exp_1 | y << k | z >> (32 - k);
y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
+ d1 = z << k | y >> (32 - k);
}
else {
d0 = Exp_1 | y;
#endif
ret_d:
#ifdef VAX
- word0(d) = d0 >> 16 | d0 << 16;
- word1(d) = d1 >> 16 | d1 << 16;
+ word0(&d) = d0 >> 16 | d0 << 16;
+ word1(&d) = d1 >> 16 | d1 << 16;
#endif
- return dval(d);
+ return dval(&d);
}
#undef d0
#undef d1
Bigint *
d2b
#ifdef KR_headers
- (d, e, bits) double d; int *e, *bits;
+ (dd, e, bits) double dd; int *e, *bits;
#else
- (double d, int *e, int *bits)
+ (double dd, int *e, int *bits)
#endif
{
Bigint *b;
+ U d;
#ifndef Sudden_Underflow
int i;
#endif
ULong *x, y, z;
#ifdef VAX
ULong d0, d1;
- d0 = word0(d) >> 16 | word0(d) << 16;
- d1 = word1(d) >> 16 | word1(d) << 16;
#else
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
+#endif
+ d.d = dd;
+#ifdef VAX
+ d0 = word0(&d) >> 16 | word0(&d) << 16;
+ d1 = word1(&d) >> 16 | word1(&d) << 16;
#endif
#ifdef Pack_32
#ifdef Pack_32
if ( (y = d1) !=0) {
if ( (k = lo0bits(&y)) !=0) {
- x[0] = y | z << 32 - k;
+ x[0] = y | z << (32 - k);
z >>= k;
}
else
b->wds = (x[1] = z) !=0 ? 2 : 1;
}
else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
k = lo0bits(&z);
x[0] = z;
#ifndef Sudden_Underflow
#endif
#ifdef IBM
*e = (de - Bias - (P-1) << 2) + k;
- *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
+ *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
#else
*e = de - Bias - (P-1) + k;
*bits = P - k;
strcp_D2A(char *a, CONST char *b)
#endif
{
- while(*a = *b++)
+ while((*a = *b++))
a++;
return a;
}
memcpy_D2A(void *a1, void *b1, size_t len)
#endif
{
- register char *a = (char*)a1, *ae = a + len;
- register char *b = (char*)b1, *a0 = a;
+ char *a = (char*)a1, *ae = a + len;
+ char *b = (char*)b1, *a0 = a;
while(a < ae)
*a++ = *b++;
return a0;
---- gdtoa-misc.c.orig 2010-01-07 22:03:21.000000000 -0800
-+++ gdtoa-misc.c 2010-01-07 22:25:33.000000000 -0800
+--- gdtoa-misc.c.orig 2010-01-12 10:59:42.000000000 -0800
++++ gdtoa-misc.c 2010-01-12 12:08:17.000000000 -0800
@@ -29,9 +29,20 @@ THIS SOFTWARE.
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
Bigint *
Balloc
#ifdef KR_headers
-@@ -53,9 +84,26 @@ Balloc
+@@ -53,8 +84,25 @@ Balloc
#ifndef Omit_Private_Memory
unsigned int len;
#endif
+ }
+#else /* !GDTOA_TSD */
ACQUIRE_DTOA_LOCK(0);
-- if ( (rv = freelist[k]) !=0) {
+#endif /* GDTOA_TSD */
-+ if (k <= Kmax && (rv = freelist[k]) !=0) {
- freelist[k] = rv->next;
- }
- else {
-@@ -65,7 +113,7 @@ Balloc
- #else
- len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
- /sizeof(double);
-- if (pmem_next - private_mem + len <= PRIVATE_mem) {
-+ if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
- rv = (Bigint*)pmem_next;
- pmem_next += len;
- }
-@@ -75,7 +123,9 @@ Balloc
+ /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
+ /* but this case seems very unlikely. */
+ if (k <= Kmax && (rv = freelist[k]) !=0) {
+@@ -77,7 +125,9 @@ Balloc
rv->k = k;
rv->maxwds = x;
}
rv->sign = rv->wds = 0;
return rv;
}
-@@ -89,10 +139,20 @@ Bfree
+@@ -98,10 +148,16 @@ Bfree
+ free((void*)v);
#endif
- {
- if (v) {
-- ACQUIRE_DTOA_LOCK(0);
-- v->next = freelist[v->k];
-- freelist[v->k] = v;
-- FREE_DTOA_LOCK(0);
-+ if (v->k > Kmax)
-+ free((void*)v);
-+ else {
+ else {
+#ifdef GDTOA_TSD
+ Bigint **freelist = (Bigint **)pthread_getspecific(gdtoa_tsd_key);
+#else /* !GDTOA_TSD */
-+ ACQUIRE_DTOA_LOCK(0);
-+#endif /* GDTOA_TSD */
-+ v->next = freelist[v->k];
-+ freelist[v->k] = v;
+ ACQUIRE_DTOA_LOCK(0);
++#endif /* !GDTOA_TSD */
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+#ifndef GDTOA_TSD
-+ FREE_DTOA_LOCK(0);
-+#endif /* GDTOA_TSD */
-+ }
+ FREE_DTOA_LOCK(0);
++#endif /* !GDTOA_TSD */
+ }
}
}
-
Bigint *
s2b
#ifdef KR_headers
- (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
+ (s, nd0, nd, y9, dplen) CONST char *s; int dplen, nd0, nd; ULong y9;
#else
- (CONST char *s, int nd0, int nd, ULong y9)
+ (CONST char *s, int nd0, int nd, ULong y9, int dplen)
#endif
{
Bigint *b;
s += 9;
do b = multadd(b, 10, *s++ - '0');
while(++i < nd0);
- s++;
+ s += dplen;
}
else
- s += 10;
+ s += dplen + 9;
for(; i < nd; i++)
b = multadd(b, 10, *s++ - '0');
return b;
(Bigint *a, Bigint *b)
#endif
{
- double da, db;
+ U da, db;
int k, ka, kb;
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
+ dval(&da) = b2d(a, &ka);
+ dval(&db) = b2d(b, &kb);
k = ka - kb + ULbits*(a->wds - b->wds);
#ifdef IBM
if (k > 0) {
- word0(da) += (k >> 2)*Exp_msk1;
+ word0(&da) += (k >> 2)*Exp_msk1;
if (k &= 3)
- dval(da) *= 1 << k;
+ dval(&da) *= 1 << k;
}
else {
k = -k;
- word0(db) += (k >> 2)*Exp_msk1;
+ word0(&db) += (k >> 2)*Exp_msk1;
if (k &= 3)
- dval(db) *= 1 << k;
+ dval(&db) *= 1 << k;
}
#else
if (k > 0)
- word0(da) += k*Exp_msk1;
+ word0(&da) += k*Exp_msk1;
else {
k = -k;
- word0(db) += k*Exp_msk1;
+ word0(&db) += k*Exp_msk1;
}
#endif
- return dval(da) / dval(db);
+ return dval(&da) / dval(&db);
}
#ifdef INFNAN_CHECK
+++ /dev/null
---- gdtoa-smisc.c.orig 2005-01-20 20:12:36.000000000 -0800
-+++ gdtoa-smisc.c 2005-03-24 17:33:43.000000000 -0800
-@@ -34,9 +34,9 @@
- Bigint *
- s2b
- #ifdef KR_headers
-- (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
-+ (s, nd0, nd, y9, decpt) CONST char *s; int nd0, nd; ULong y9; int decpt;
- #else
-- (CONST char *s, int nd0, int nd, ULong y9)
-+ (CONST char *s, int nd0, int nd, ULong y9, int decpt)
- #endif
- {
- Bigint *b;
-@@ -60,10 +60,10 @@
- s += 9;
- do b = multadd(b, 10, *s++ - '0');
- while(++i < nd0);
-- s++;
-+ s += decpt;
- }
- else
-- s += 10;
-+ s += 9 + decpt;
- for(; i < nd; i++)
- b = multadd(b, 10, *s++ - '0');
- return b;
goto swapcheck;
}
if (b1->wds > nw
- || nb1 && b1->x[nw1] & 1L << nb1) {
+ || (nb1 && b1->x[nw1] & 1L << nb1)) {
if (++e1 > fpi->emax)
rv1 = STRTOG_Infinite | STRTOG_Inexhi;
rshift(b1, 1);
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
CONST char *s, *s0, *s1;
- double aadj, aadj1, adj, rv, rv0;
+ double aadj;
Long L;
+ U adj, aadj1, rv, rv0;
ULong y, z;
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
-#ifdef USE_LOCALE
+#ifdef USE_LOCALE /*{{*/
#ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv()->decimal_point;
+ int dplen = strlen(decimalpoint);
#else
char *decimalpoint;
static char *decimalpoint_cache;
+ static int dplen;
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv()->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
+ dplen = strlen(s0);
}
decimalpoint = (char*)s0;
-#endif
-#endif
+#endif /*NO_LOCALE_CACHE*/
+#else /*USE_LOCALE}{*/
+#define dplen 1
+#endif /*USE_LOCALE}}*/
+
#ifdef Honor_FLT_ROUNDS /*{*/
int Rounding;
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
#endif /*}*/
sign = nz0 = nz = decpt = 0;
- dval(rv) = 0.;
+ dval(&rv) = 0.;
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
case 'x':
case 'X':
{
-#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD) /*{{*/
+#ifdef Honor_FLT_ROUNDS
FPI fpi1 = fpi;
-#ifdef Honor_FLT_ROUNDS /*{{*/
fpi1.rounding = Rounding;
-#else /*}{*/
- switch(fegetround()) {
- case FE_TOWARDZERO: fpi1.rounding = 0; break;
- case FE_UPWARD: fpi1.rounding = 2; break;
- case FE_DOWNWARD: fpi1.rounding = 3;
- }
-#endif /*}}*/
-#else /*}{*/
+#else
#define fpi1 fpi
-#endif /*}}*/
+#endif
switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
--s;
if (!match(&s,"inity"))
++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
+ word0(&rv) = 0x7ff00000;
+ word1(&rv) = 0;
goto ret;
}
break;
if (*s == '(' /*)*/
&& hexnan(&s, &fpinan, bits)
== STRTOG_NaNbits) {
- word0(rv) = 0x7ff00000 | bits[1];
- word1(rv) = bits[0];
+ word0(&rv) = 0x7ff00000 | bits[1];
+ word1(&rv) = bits[0];
}
else {
#endif
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
+ word0(&rv) = NAN_WORD0;
+ word1(&rv) = NAN_WORD1;
#ifndef No_Hex_NaN
}
#endif
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ dval(&rv) = y;
if (k > 9) {
#ifdef SET_INEXACT
if (k > DBL_DIG)
oldinexact = get_inexact();
#endif
- dval(rv) = tens[k - 9] * dval(rv) + z;
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
}
bd0 = 0;
if (nd <= DBL_DIG
sign = 0;
}
#endif
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
goto ret;
#endif
}
}
#endif
e -= i;
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
- word0(rv) -= P*Exp_msk1;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if ((word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if ((word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto ovfl;
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
#else
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
#endif
goto ret;
}
sign = 0;
}
#endif
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
goto ret;
}
#endif
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
switch(Rounding) {
case 0: /* toward 0 */
case 3: /* toward -infinity */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
break;
default:
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
}
#else /*Honor_FLT_ROUNDS*/
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
#endif /*Honor_FLT_ROUNDS*/
#ifdef SET_INEXACT
/* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e300;
+ dval(&rv0) *= dval(&rv0);
#endif
#else /*IEEE_Arith*/
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
#endif /*IEEE_Arith*/
if (bd0)
goto retfree;
e1 >>= 4;
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= bigtens[j];
+ dval(&rv) *= bigtens[j];
/* The last multiplication could overflow. */
- word0(rv) -= P*Exp_msk1;
- dval(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ dval(&rv) *= bigtens[j];
+ if ((z = word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
goto ovfl;
if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
/* set to largest number */
/* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 >>= 4) {
if (e1 >= 1 << n_bigtens)
goto undfl;
scale = 2*P;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
- if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+ dval(&rv) *= tinytens[j];
+ if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
>> Exp_shift)) > 0) {
/* scaled rv is denormal; zap j low bits */
if (j >= 32) {
- word1(rv) = 0;
+ word1(&rv) = 0;
if (j >= 53)
- word0(rv) = (P+2)*Exp_msk1;
+ word0(&rv) = (P+2)*Exp_msk1;
else
- word0(rv) &= 0xffffffff << j-32;
+ word0(&rv) &= 0xffffffff << (j-32);
}
else
- word1(rv) &= 0xffffffff << j;
+ word1(&rv) &= 0xffffffff << j;
}
#else
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ dval(&rv) *= tinytens[j];
/* The last multiplication could underflow. */
- dval(rv0) = dval(rv);
- dval(rv) *= tinytens[j];
- if (!dval(rv)) {
- dval(rv) = 2.*dval(rv0);
- dval(rv) *= tinytens[j];
+ dval(&rv0) = dval(&rv);
+ dval(&rv) *= tinytens[j];
+ if (!dval(&rv)) {
+ dval(&rv) = 2.*dval(&rv0);
+ dval(&rv) *= tinytens[j];
#endif
- if (!dval(rv)) {
+ if (!dval(&rv)) {
undfl:
- dval(rv) = 0.;
+ dval(&rv) = 0.;
#ifndef NO_ERRNO
errno = ERANGE;
#endif
goto ret;
}
#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
/* The refinement below will clean
* this approximation up.
*/
/* Put digits into bd: true value = bd * 10^e */
- bd0 = s2b(s0, nd0, nd, y);
+ bd0 = s2b(s0, nd0, nd, y, dplen);
for(;;) {
bd = Balloc(bd0->k);
Bcopy(bd, bd0);
- bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
bs = i2b(1);
if (e >= 0) {
#endif
#ifdef Avoid_Underflow
j = bbe - scale;
- i = j + bbbits - 1; /* logb(rv) */
+ i = j + bbbits - 1; /* logb(&rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
#endif
#else /*Sudden_Underflow*/
j = bbe;
- i = j + bbbits - 1; /* logb(rv) */
+ i = j + bbbits - 1; /* logb(&rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
}
if (Rounding) {
if (dsign) {
- adj = 1.;
+ dval(&adj) = 1.;
goto apply_adj;
}
}
else if (!dsign) {
- adj = -1.;
- if (!word1(rv)
- && !(word0(rv) & Frac_mask)) {
- y = word0(rv) & Exp_mask;
+ dval(&adj) = -1.;
+ if (!word1(&rv)
+ && !(word0(&rv) & Frac_mask)) {
+ y = word0(&rv) & Exp_mask;
#ifdef Avoid_Underflow
if (!scale || y > 2*P*Exp_msk1)
#else
{
delta = lshift(delta,Log2P);
if (cmp(delta, bs) <= 0)
- adj = -0.5;
+ dval(&adj) = -0.5;
}
}
apply_adj:
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask)
+ if (scale && (y = word0(&rv) & Exp_mask)
<= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <=
+ if ((word0(&rv) & Exp_mask) <=
P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- dval(rv) += adj*ulp(dval(rv));
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
+ dval(&rv) += adj*ulp(&rv);
+ word0(&rv) -= P*Exp_msk1;
}
else
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- dval(rv) += adj*ulp(dval(rv));
+ dval(&rv) += adj*ulp(&rv);
}
break;
}
- adj = ratio(delta, bs);
+ dval(&adj) = ratio(delta, bs);
if (adj < 1.)
- adj = 1.;
+ dval(&adj) = 1.;
if (adj <= 0x7ffffffe) {
- /* adj = Rounding ? ceil(adj) : floor(adj); */
+ /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
y = adj;
if (y != adj) {
if (!((Rounding>>1) ^ dsign))
y++;
- adj = y;
+ dval(&adj) = y;
}
}
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- adj *= ulp(dval(rv));
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) *= ulp(&rv);
if (dsign)
- dval(rv) += adj;
+ dval(&rv) += adj;
else
- dval(rv) -= adj;
- word0(rv) -= P*Exp_msk1;
+ dval(&rv) -= adj;
+ word0(&rv) -= P*Exp_msk1;
goto cont;
}
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- adj *= ulp(dval(rv));
+ dval(&adj) *= ulp(&rv);
if (dsign) {
- if (word0(rv) == Big0 && word1(rv) == Big1)
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
goto ovfl;
- dval(rv) += adj;
+ dval(&rv) += adj;
}
else
- dval(rv) -= adj;
+ dval(&rv) -= adj;
goto cont;
}
#endif /*Honor_FLT_ROUNDS*/
/* Error is less than half an ulp -- check for
* special case of mantissa a power of two.
*/
- if (dsign || word1(rv) || word0(rv) & Bndry_mask
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
#ifdef IEEE_Arith
#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+ || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
+ || (word0(&rv) & Exp_mask) <= Exp_msk1
#endif
#endif
) {
if (i == 0) {
/* exactly half-way between */
if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == (
+ if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
+ && word1(&rv) == (
#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
#endif
0xffffffff)) {
/*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask)
+ word0(&rv) = (word0(&rv) & Exp_mask)
+ Exp_msk1
#ifdef IBM
| Exp_msk1 >> 4
#endif
;
- word1(rv) = 0;
+ word1(&rv) = 0;
#ifdef Avoid_Underflow
dsign = 0;
#endif
break;
}
}
- else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
drop_down:
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
#ifdef IBM
if (L < Exp_msk1)
#else
#else /*Sudden_Underflow}{*/
#ifdef Avoid_Underflow
if (scale) {
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
if (L <= (2*P+1)*Exp_msk1) {
if (L > (P+2)*Exp_msk1)
/* round even ==> */
}
}
#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
+ L = (word0(&rv) & Exp_mask) - Exp_msk1;
#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
+ word0(&rv) = L | Bndry_mask1;
+ word1(&rv) = 0xffffffff;
#ifdef IBM
goto cont;
#else
#endif
}
#ifndef ROUND_BIASED
- if (!(word1(rv) & LSB))
+ if (!(word1(&rv) & LSB))
break;
#endif
if (dsign)
- dval(rv) += ulp(dval(rv));
+ dval(&rv) += ulp(&rv);
#ifndef ROUND_BIASED
else {
- dval(rv) -= ulp(dval(rv));
+ dval(&rv) -= ulp(&rv);
#ifndef Sudden_Underflow
- if (!dval(rv))
+ if (!dval(&rv))
goto undfl;
#endif
}
}
if ((aadj = ratio(delta, bs)) <= 2.) {
if (dsign)
- aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
+ aadj = dval(&aadj1) = 1.;
+ else if (word1(&rv) || word0(&rv) & Bndry_mask) {
#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
+ if (word1(&rv) == Tiny1 && !word0(&rv))
goto undfl;
#endif
aadj = 1.;
- aadj1 = -1.;
+ dval(&aadj1) = -1.;
}
else {
/* special case -- power of FLT_RADIX to be */
aadj = 1./FLT_RADIX;
else
aadj *= 0.5;
- aadj1 = -aadj;
+ dval(&aadj1) = -aadj;
}
}
else {
aadj *= 0.5;
- aadj1 = dsign ? aadj : -aadj;
+ dval(&aadj1) = dsign ? aadj : -aadj;
#ifdef Check_FLT_ROUNDS
switch(Rounding) {
case 2: /* towards +infinity */
- aadj1 -= 0.5;
+ dval(&aadj1) -= 0.5;
break;
case 0: /* towards 0 */
case 3: /* towards -infinity */
- aadj1 += 0.5;
+ dval(&aadj1) += 0.5;
}
#else
if (Flt_Rounds == 0)
- aadj1 += 0.5;
+ dval(&aadj1) += 0.5;
#endif /*Check_FLT_ROUNDS*/
}
- y = word0(rv) & Exp_mask;
+ y = word0(&rv) & Exp_mask;
/* Check for overflow */
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- dval(rv0) = dval(rv);
- word0(rv) -= P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) >=
+ dval(&rv0) = dval(&rv);
+ word0(&rv) -= P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
+ if ((word0(&rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
goto cont;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
else {
#ifdef Avoid_Underflow
if ((z = aadj) <= 0)
z = 1;
aadj = z;
- aadj1 = dsign ? aadj : -aadj;
+ dval(&aadj1) = dsign ? aadj : -aadj;
}
- word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+ word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- dval(rv0) = dval(rv);
- word0(rv) += P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(&rv0) = dval(&rv);
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
#ifdef IBM
- if ((word0(rv) & Exp_mask) < P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) < P*Exp_msk1)
#else
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
#endif
{
- if (word0(rv0) == Tiny0
- && word1(rv0) == Tiny1)
+ if (word0(&rv0) == Tiny0
+ && word1(&rv0) == Tiny1)
goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
goto cont;
}
else
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) -= P*Exp_msk1;
}
else {
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
}
#else /*Sudden_Underflow*/
- /* Compute adj so that the IEEE rounding rules will
- * correctly round rv + adj in some half-way cases.
- * If rv * ulp(rv) is denormalized (i.e.,
+ /* Compute dval(&adj) so that the IEEE rounding rules will
+ * correctly round rv + dval(&adj) in some half-way cases.
+ * If rv * ulp(&rv) is denormalized (i.e.,
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
* trouble from bits lost to denormalization;
* example: 1.2e-307 .
*/
if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
- aadj1 = (double)(int)(aadj + 0.5);
+ dval(&aadj1) = (double)(int)(aadj + 0.5);
if (!dsign)
- aadj1 = -aadj1;
+ dval(&aadj1) = -dval(&aadj1);
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
}
- z = word0(rv) & Exp_mask;
+ z = word0(&rv) & Exp_mask;
#ifndef SET_INEXACT
#ifdef Avoid_Underflow
if (!scale)
L = (Long)aadj;
aadj -= L;
/* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
if (aadj < .4999999 || aadj > .5000001)
break;
}
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
- word0(rv0) = Exp_1 + (70 << Exp_shift);
- word1(rv0) = 0;
- dval(rv0) += 1.;
+ word0(&rv0) = Exp_1 + (70 << Exp_shift);
+ word1(&rv0) = 0;
+ dval(&rv0) += 1.;
}
}
else if (!oldinexact)
#endif
#ifdef Avoid_Underflow
if (scale) {
- word0(rv0) = Exp_1 - 2*P*Exp_msk1;
- word1(rv0) = 0;
- dval(rv) *= dval(rv0);
+ word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(&rv0) = 0;
+ dval(&rv) *= dval(&rv0);
#ifndef NO_ERRNO
/* try to avoid the bug of testing an 8087 register value */
#ifdef IEEE_Arith
- if (!(word0(rv) & Exp_mask))
+ if (!(word0(&rv) & Exp_mask))
#else
- if (word0(rv) == 0 && word1(rv) == 0)
+ if (word0(&rv) == 0 && word1(&rv) == 0)
#endif
errno = ERANGE;
#endif
}
#endif /* Avoid_Underflow */
#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
+ if (inexact && !(word0(&rv) & Exp_mask)) {
/* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e-300;
+ dval(&rv0) *= dval(&rv0);
}
#endif
retfree:
ret:
if (se)
*se = (char *)s;
- return sign ? -dval(rv) : dval(rv);
+ return sign ? -dval(&rv) : dval(&rv);
}
---- gdtoa-strtod.c.orig 2008-10-28 12:07:31.000000000 -0700
-+++ gdtoa-strtod.c 2008-10-28 12:22:37.000000000 -0700
+--- gdtoa-strtod.c.orig 2010-01-29 16:43:20.000000000 -0800
++++ gdtoa-strtod.c 2010-01-29 18:05:44.000000000 -0800
@@ -29,6 +29,8 @@ THIS SOFTWARE.
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
#endif
{
#ifdef Avoid_Underflow
-@@ -79,13 +81,14 @@ strtod
+@@ -71,6 +73,7 @@ strtod
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
+ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ CONST char *s, *s0, *s1;
++ char *strunc = NULL;
+ double aadj;
+ Long L;
+ U adj, aadj1, rv, rv0;
+@@ -80,15 +83,16 @@ strtod
int inexact, oldinexact;
#endif
- #ifdef USE_LOCALE
+ #ifdef USE_LOCALE /*{{*/
+ NORMALIZE_LOCALE(loc);
#ifdef NO_LOCALE_CACHE
- char *decimalpoint = localeconv()->decimal_point;
+ char *decimalpoint = localeconv_l(loc)->decimal_point;
+ int dplen = strlen(decimalpoint);
#else
char *decimalpoint;
static char *decimalpoint_cache;
+ static int dplen;
if (!(s0 = decimalpoint_cache)) {
- s0 = localeconv()->decimal_point;
+ s0 = localeconv_l(loc)->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
-@@ -155,7 +158,7 @@ strtod
- #else /*}{*/
+@@ -154,7 +158,7 @@ strtod
+ #else
#define fpi1 fpi
- #endif /*}}*/
+ #endif
- switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
+ switch((i = gethex(&s, &fpi1, &exp, &bb, sign, loc)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
sign = 0;
-@@ -545,7 +548,11 @@ strtod
-
- /* Put digits into bd: true value = bd * 10^e */
-
-- bd0 = s2b(s0, nd0, nd, y);
-+#ifdef USE_LOCALE
-+ bd0 = s2b(s0, nd0, nd, y, strlen(decimalpoint));
-+#else
-+ bd0 = s2b(s0, nd0, nd, y, 1);
-+#endif
+@@ -310,6 +314,9 @@ strtod
+ }
+ goto ret;
+ }
++#define FPIEMIN (1-1023-53+1) // fpi.emin
++#define FPINBITS 52 // fpi.nbits
++ TRUNCATE_DIGITS(s0, strunc, nd, nd0, nf, FPINBITS, FPIEMIN, dplen);
+ e1 = e -= nf;
- for(;;) {
- bd = Balloc(bd0->k);
-@@ -992,7 +999,7 @@ strtod
- dval(rv) *= dval(rv0);
+ /* Now we have nd0 digits, starting at s0, followed by a
+@@ -346,7 +353,7 @@ strtod
+ #ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+- rv = -rv;
++ dval(&rv) = -dval(&rv);
+ sign = 0;
+ }
+ #endif
+@@ -362,7 +369,7 @@ strtod
+ #ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+- rv = -rv;
++ dval(&rv) = -dval(&rv);
+ sign = 0;
+ }
+ #endif
+@@ -390,7 +397,7 @@ strtod
+ #ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+- rv = -rv;
++ dval(&rv) = -dval(&rv);
+ sign = 0;
+ }
+ #endif
+@@ -672,17 +679,17 @@ strtod
+ else
+ #endif /*Sudden_Underflow*/
+ #endif /*Avoid_Underflow*/
+- dval(&rv) += adj*ulp(&rv);
++ dval(&rv) += dval(&adj)*ulp(&rv);
+ }
+ break;
+ }
+ dval(&adj) = ratio(delta, bs);
+- if (adj < 1.)
++ if (dval(&adj) < 1.)
+ dval(&adj) = 1.;
+- if (adj <= 0x7ffffffe) {
++ if (dval(&adj) <= 0x7ffffffe) {
+ /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
+- y = adj;
+- if (y != adj) {
++ y = dval(&adj);
++ if (y != dval(&adj)) {
+ if (!((Rounding>>1) ^ dsign))
+ y++;
+ dval(&adj) = y;
+@@ -709,10 +716,10 @@ strtod
+ if (dsign) {
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
+ goto ovfl;
+- dval(&rv) += adj;
++ dval(&rv) += dval(&adj);
+ }
+ else
+- dval(&rv) -= adj;
++ dval(&rv) -= dval(&adj);
+ goto cont;
+ }
+ #endif /*Honor_FLT_ROUNDS*/
+@@ -991,7 +998,7 @@ strtod
+ dval(&rv) *= dval(&rv0);
#ifndef NO_ERRNO
/* try to avoid the bug of testing an 8087 register value */
-#ifdef IEEE_Arith
+#if defined(IEEE_Arith) && __DARWIN_UNIX03
- if (!(word0(rv) & Exp_mask))
+ if (!(word0(&rv) & Exp_mask))
#else
- if (word0(rv) == 0 && word1(rv) == 0)
-@@ -1020,3 +1027,13 @@ strtod
- return sign ? -dval(rv) : dval(rv);
+ if (word0(&rv) == 0 && word1(&rv) == 0)
+@@ -1016,6 +1023,22 @@ strtod
+ ret:
+ if (se)
+ *se = (char *)s;
++ if (strunc)
++#ifdef FREE
++ FREE(strunc);
++#else
++ free(strunc);
++#endif
+ return sign ? -dval(&rv) : dval(&rv);
}
+ double
rvOK
#ifdef KR_headers
(d, fpi, exp, bits, exact, rd, irv)
- double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
+ U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
#else
- (double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
+ (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
#endif
{
Bigint *b;
int bdif, e, j, k, k1, nb, rv;
carry = rv = 0;
- b = d2b(d, &e, &bdif);
+ b = d2b(dval(d), &e, &bdif);
bdif -= nb = fpi->nbits;
e += bdif;
if (bdif <= 0) {
static int
#ifdef KR_headers
-mantbits(d) double d;
+mantbits(d) U *d;
#else
-mantbits(double d)
+mantbits(U *d)
#endif
{
ULong L;
int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
int sudden_underflow;
CONST char *s, *s0, *s1;
- double adj, adj0, rv, tol;
+ double adj0, tol;
Long L;
+ U adj, rv;
ULong *b, *be, y, z;
Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
-#ifdef USE_LOCALE
+#ifdef USE_LOCALE /*{{*/
#ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv()->decimal_point;
+ int dplen = strlen(decimalpoint);
#else
char *decimalpoint;
static char *decimalpoint_cache;
+ static int dplen;
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv()->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
+ dplen = strlen(s0);
}
decimalpoint = (char*)s0;
-#endif
-#endif
+#endif /*NO_LOCALE_CACHE*/
+#else /*USE_LOCALE}{*/
+#define dplen 1
+#endif /*USE_LOCALE}}*/
irv = STRTOG_Zero;
denorm = sign = nz0 = nz = 0;
- dval(rv) = 0.;
+ dval(&rv) = 0.;
rvb = 0;
nbits = fpi->nbits;
for(s = s00;;s++) switch(*s) {
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ dval(&rv) = y;
if (k > 9)
- dval(rv) = tens[k - 9] * dval(rv) + z;
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
bd0 = 0;
if (nbits <= P && nd <= DBL_DIG) {
if (!e) {
- if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv))
+ if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
goto ret;
}
else if (e > 0) {
#ifdef VAX
goto vax_ovfl_check;
#else
- i = fivesbits[e] + mantbits(dval(rv)) <= P;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
+ i = fivesbits[e] + mantbits(&rv) <= P;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
goto ret;
e1 -= e;
goto rv_notOK;
*/
e2 = e - i;
e1 -= i;
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
- dval(adj) = dval(rv);
- word0(adj) -= P*Exp_msk1;
- /* adj = */ rounded_product(dval(adj), tens[e2]);
- if ((word0(adj) & Exp_mask)
+ dval(&adj) = dval(&rv);
+ word0(&adj) -= P*Exp_msk1;
+ /* adj = */ rounded_product(dval(&adj), tens[e2]);
+ if ((word0(&adj) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto rv_notOK;
- word0(adj) += P*Exp_msk1;
- dval(rv) = dval(adj);
+ word0(&adj) += P*Exp_msk1;
+ dval(&rv) = dval(&adj);
#else
- /* rv = */ rounded_product(dval(rv), tens[e2]);
+ /* rv = */ rounded_product(dval(&rv), tens[e2]);
#endif
- if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e2;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
- if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e;
}
e2 = 0;
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
- while(e1 >= (1 << n_bigtens-1)) {
- e2 += ((word0(rv) & Exp_mask)
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
- dval(rv) *= bigtens[n_bigtens-1];
- e1 -= 1 << n_bigtens-1;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= bigtens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
}
- e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= bigtens[j];
+ dval(&rv) *= bigtens[j];
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
- while(e1 >= (1 << n_bigtens-1)) {
- e2 += ((word0(rv) & Exp_mask)
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
- dval(rv) *= tinytens[n_bigtens-1];
- e1 -= 1 << n_bigtens-1;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= tinytens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
}
- e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ dval(&rv) *= tinytens[j];
}
}
#ifdef IBM
*/
e2 <<= 2;
#endif
- rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */
+ rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
rve += e2;
if ((j = rvbits - nbits) > 0) {
rshift(rvb, j);
/* Put digits into bd: true value = bd * 10^e */
- bd0 = s2b(s0, nd0, nd, y);
+ bd0 = s2b(s0, nd0, nd, y, dplen);
for(;;) {
bd = Balloc(bd0->k);
}
else
irv = STRTOG_Normal | STRTOG_Inexhi;
- if (bbbits < nbits && !denorm || !(rvb->x[0] & 1))
+ if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
break;
if (dsign) {
rvb = increment(rvb);
}
break;
}
- if ((dval(adj) = ratio(delta, bs)) <= 2.) {
+ if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
adj1:
inex = STRTOG_Inexlo;
if (dsign) {
irv = STRTOG_Underflow | STRTOG_Inexlo;
break;
}
- adj0 = dval(adj) = 1.;
+ adj0 = dval(&adj) = 1.;
}
else {
- adj0 = dval(adj) *= 0.5;
+ adj0 = dval(&adj) *= 0.5;
if (dsign) {
asub = 0;
inex = STRTOG_Inexlo;
}
- if (dval(adj) < 2147483647.) {
+ if (dval(&adj) < 2147483647.) {
L = adj0;
adj0 -= L;
switch(rd) {
inex = STRTOG_Inexact - inex;
}
}
- dval(adj) = L;
+ dval(&adj) = L;
}
}
y = rve + rvbits;
- /* adj *= ulp(dval(rv)); */
+ /* adj *= ulp(dval(&rv)); */
/* if (asub) rv -= adj; else rv += adj; */
if (!denorm && rvbits < nbits) {
rve -= j;
rvbits = nbits;
}
- ab = d2b(dval(adj), &abe, &abits);
+ ab = d2b(dval(&adj), &abe, &abits);
if (abe < 0)
rshift(ab, -abe);
else if (abe > 0)
z = rve + rvbits;
if (y == z && L) {
/* Can we stop now? */
- tol = dval(adj) * 5e-16; /* > max rel error */
- dval(adj) = adj0 - .5;
- if (dval(adj) < -tol) {
+ tol = dval(&adj) * 5e-16; /* > max rel error */
+ dval(&adj) = adj0 - .5;
+ if (dval(&adj) < -tol) {
if (adj0 > tol) {
irv |= inex;
break;
}
}
- else if (dval(adj) > tol && adj0 < 1. - tol) {
+ else if (dval(&adj) > tol && adj0 < 1. - tol) {
irv |= inex;
break;
}
---- gdtoa-strtodg.c.orig 2008-10-28 12:23:36.000000000 -0700
-+++ gdtoa-strtodg.c 2008-10-28 12:34:18.000000000 -0700
+--- gdtoa-strtodg.c.orig 2010-01-29 16:43:20.000000000 -0800
++++ gdtoa-strtodg.c 2010-01-29 18:13:37.000000000 -0800
@@ -29,13 +29,29 @@ THIS SOFTWARE.
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
+extern CONST int fivesbits[];
+int all_on(Bigint *b, int n);
+Bigint *set_ones(Bigint *b, int n);
-+int rvOK(double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv);
-+int mantbits(double d);
++int rvOK(U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv);
++int mantbits(U *d);
+#else /* !BUILDING_VARIANT */
+
+ __private_extern__ CONST int
- static int
+ __private_extern__ int
#ifdef KR_headers
- mantbits(d) double d;
+ mantbits(d) U *d;
#else
-@@ -312,13 +328,15 @@ mantbits(double d)
+@@ -312,13 +328,15 @@ mantbits(U *d)
return P - 32 - lo0bits(&L);
}
#endif
{
int abe, abits, asub;
-@@ -332,13 +350,14 @@ strtodg
+@@ -327,21 +345,23 @@ strtodg
+ int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
+ int sudden_underflow;
+ CONST char *s, *s0, *s1;
++ char *strunc = NULL;
+ double adj0, tol;
+ Long L;
+ U adj, rv;
ULong *b, *be, y, z;
Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
- #ifdef USE_LOCALE
-+ NORMALIZE_LOCALE(loc)
+ #ifdef USE_LOCALE /*{{*/
++ NORMALIZE_LOCALE(loc);
#ifdef NO_LOCALE_CACHE
- char *decimalpoint = localeconv()->decimal_point;
+ char *decimalpoint = localeconv_l(loc)->decimal_point;
+ int dplen = strlen(decimalpoint);
#else
char *decimalpoint;
static char *decimalpoint_cache;
+ static int dplen;
if (!(s0 = decimalpoint_cache)) {
- s0 = localeconv()->decimal_point;
+ s0 = localeconv_l(loc)->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
-@@ -382,7 +401,7 @@ strtodg
+@@ -388,7 +408,7 @@ strtodg
switch(s[1]) {
case 'x':
case 'X':
if (irv == STRTOG_NoNumber) {
s = s00;
sign = 0;
-@@ -687,6 +706,10 @@ strtodg
+@@ -525,6 +545,7 @@ strtodg
+ }
+ goto ret;
+ }
++ TRUNCATE_DIGITS(s0, strunc, nd, nd0, nf, fpi->nbits, fpi->emin, dplen);
+
+ irv = STRTOG_Normal;
+ e1 = e -= nf;
+@@ -693,6 +714,10 @@ strtodg
rvb->x[0] = 0;
*exp = emin;
irv = STRTOG_Underflow | STRTOG_Inexlo;
goto ret;
}
rvb->x[0] = rvb->wds = rvbits = 1;
-@@ -703,7 +726,11 @@ strtodg
-
- /* Put digits into bd: true value = bd * 10^e */
-
-- bd0 = s2b(s0, nd0, nd, y);
-+#ifdef USE_LOCALE
-+ bd0 = s2b(s0, nd0, nd, y, strlen(decimalpoint));
-+#else
-+ bd0 = s2b(s0, nd0, nd, y, 1);
-+#endif
-
- for(;;) {
- bd = Balloc(bd0->k);
-@@ -1032,7 +1059,7 @@ strtodg
+@@ -1038,7 +1063,7 @@ strtodg
if (sudden_underflow) {
rvb->wds = 0;
irv = STRTOG_Underflow | STRTOG_Inexlo;
errno = ERANGE;
#endif
}
-@@ -1041,7 +1068,7 @@ strtodg
+@@ -1047,7 +1072,7 @@ strtodg
(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
if (irv & STRTOG_Inexact) {
irv |= STRTOG_Underflow;
errno = ERANGE;
#endif
}
+@@ -1061,5 +1086,11 @@ strtodg
+ copybits(bits, nbits, rvb);
+ Bfree(rvb);
+ }
++ if (strunc)
++#ifdef FREE
++ FREE(strunc);
++#else
++ free(strunc);
++#endif
+ return irv;
+ }
case STRTOG_Normal:
case STRTOG_NaNbits:
- u.L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+ u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
break;
case STRTOG_Denormal:
case STRTOG_Normal:
u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
- u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
- | exp + 0x3ff + 105 << 20;
+ u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff)
+ | ((exp + 0x3ff + 105) << 20);
exp += 0x3ff + 52;
if (bits[1] &= 0x1fffff) {
i = hi0bits(bits[1]) - 11;
else
exp -= i;
if (i > 0) {
- bits[1] = bits[1] << i | bits[0] >> 32-i;
+ bits[1] = bits[1] << i | bits[0] >> (32-i);
bits[0] = bits[0] << i & 0xffffffffL;
}
}
else
exp -= i;
if (i < 32) {
- bits[1] = bits[0] >> 32 - i;
+ bits[1] = bits[0] >> (32 - i);
bits[0] = bits[0] << i & 0xffffffffL;
}
else {
- bits[1] = bits[0] << i - 32;
+ bits[1] = bits[0] << (i - 32);
bits[0] = 0;
}
}
break;
}
u->L[2+_1] = bits[0];
- u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
+ u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
break;
case STRTOG_Denormal:
nearly_normal:
i = hi0bits(bits[3]) - 11; /* i >= 12 */
j = 32 - i;
- u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
- | 65 - i << 20;
+ u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
+ | ((65 - i) << 20);
u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
break;
if (i < 0) {
j = -i;
i += 32;
- u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
- u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[_0] = (bits[2] >> j & 0xfffff) | (33 + j) << 20;
+ u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
break;
}
if (i == 0) {
- u->L[_0] = bits[2] & 0xfffff | 33 << 20;
+ u->L[_0] = (bits[2] & 0xfffff) | (33 << 20);
u->L[_1] = bits[1];
u->L[2+_0] = 0;
u->L[2+_1] = bits[0];
break;
}
j = 32 - i;
- u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
- | j + 1 << 20;
+ u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
+ | ((j + 1) << 20);
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
break;
hardly_normal:
j = 11 - hi0bits(bits[1]);
i = 32 - j;
- u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
+ u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
break;
case STRTOG_Infinite:
---- gdtoa-strtopdd.c.orig 2008-10-28 12:43:22.000000000 -0700
-+++ gdtoa-strtopdd.c 2008-10-28 12:51:49.000000000 -0700
+--- gdtoa-strtopdd.c.orig 2010-01-12 10:59:42.000000000 -0800
++++ gdtoa-strtopdd.c 2010-01-12 11:09:40.000000000 -0800
@@ -29,13 +29,25 @@ THIS SOFTWARE.
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
@@ -106,6 +124,9 @@ strtopdd(CONST char *s, char **sp, doubl
}
u->L[2+_1] = bits[0];
- u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
+ u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
+#ifdef __APPLE__
+ fixLDBL(u->ld);
+#endif /* __APPLE__ */
case STRTOG_Denormal:
@@ -129,6 +150,9 @@ strtopdd(CONST char *s, char **sp, doubl
u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
+#ifdef __APPLE__
+ fixLDBL(u->ld);
partly_normal:
@@ -140,6 +164,9 @@ strtopdd(CONST char *s, char **sp, doubl
- u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
+#ifdef __APPLE__
+ fixLDBL(u->ld);
@@ -155,6 +185,9 @@ strtopdd(CONST char *s, char **sp, doubl
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
+#ifdef __APPLE__
+ fixLDBL(u->ld);
+#endif /* __APPLE__ */
@@ -164,20 +197,45 @@ strtopdd(CONST char *s, char **sp, doubl
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
+#ifdef __APPLE__
+ fixLDBL(u->ld);
+#endif /* __APPLE__ */
case STRTOG_Infinite:
L[_0] = 0x7fff;
- L[_1] = L[_2] = L[_3] = L[_4] = 0;
+ L[_1] = 0x8000;
+ L[_2] = L[_3] = L[_4] = 0;
break;
case STRTOG_NaN:
---- gdtoa-strtopx.c.orig 2008-10-28 12:54:18.000000000 -0700
-+++ gdtoa-strtopx.c 2008-10-28 12:57:26.000000000 -0700
+--- gdtoa-strtopx.c.orig 2010-01-12 10:59:42.000000000 -0800
++++ gdtoa-strtopx.c 2010-01-12 12:11:48.000000000 -0800
@@ -29,6 +29,8 @@ THIS SOFTWARE.
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
case STRTOG_Zero:
L[0] = L[1] = L[2] = L[3] = L[4] = 0;
break;
-@@ -92,7 +97,8 @@ strtopx(CONST char *s, char **sp, void *
-
- case STRTOG_Infinite:
- L[_0] = 0x7fff;
-- L[_1] = L[_2] = L[_3] = L[_4] = 0;
-+ L[_1] = 0x8000; /* 4306392: to match gcc */
-+ L[_2] = L[_3] = L[_4] = 0;
- break;
-
- case STRTOG_NaN:
double
ulp
#ifdef KR_headers
- (x) double x;
+ (x) U *x;
#else
- (double x)
+ (U *x)
#endif
{
Long L;
- double a;
+ U a;
L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
#ifndef Sudden_Underflow
#ifdef IBM
L |= Exp_msk1 >> 4;
#endif
- word0(a) = L;
- word1(a) = 0;
+ word0(&a) = L;
+ word1(&a) = 0;
#ifndef Sudden_Underflow
}
else {
L = -L >> Exp_shift;
if (L < Exp_shift) {
- word0(a) = 0x80000 >> L;
- word1(a) = 0;
+ word0(&a) = 0x80000 >> L;
+ word1(&a) = 0;
}
else {
- word0(a) = 0;
+ word0(&a) = 0;
L -= Exp_shift;
- word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ word1(&a) = L >= 31 ? 1 : 1 << (31 - L);
}
}
#endif
- return a;
+ return dval(&a);
}
* #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
* if memory is available and otherwise does something you deem
* appropriate. If MALLOC is undefined, malloc will be invoked
- * directly -- and assumed always to succeed.
+ * directly -- and assumed always to succeed. Similarly, if you
+ * want something other than the system's free() to be called to
+ * recycle memory acquired from MALLOC, #define FREE to be the
+ * name of the alternate routine. (FREE or free is only called in
+ * pathological cases, e.g., in a gdtoa call after a gdtoa return in
+ * mode 3 with thousands of digits requested.)
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
* memory allocations from a private pool of memory when possible.
* When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
* conversions of IEEE doubles in single-threaded executions with
* 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
* 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- * Infinity and NaN (case insensitively).
+ * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
+ * #defined automatically on IEEE systems. On such systems,
+ * when INFNAN_CHECK is #defined, strtod checks
+ * for Infinity and NaN (case insensitively).
* When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
* strtodg also accepts (case insensitively) strings of the form
* NaN(x), where x is a string of hexadecimal digits (optionally
* #define NO_STRING_H to use private versions of memcpy.
* On some K&R systems, it may also be necessary to
* #define DECLARE_SIZE_T in this case.
- * #define YES_ALIAS to permit aliasing certain double values with
- * arrays of ULongs. This leads to slightly better code with
- * some compilers and was always used prior to 19990916, but it
- * is not strictly legal and can cause trouble with aggressively
- * optimizing compilers (e.g., gcc 2.95.1 under -O2).
* #define USE_LOCALE to use the current locale's decimal_point value.
*/
typedef union { double d; ULong L[2]; } U;
-#ifdef YES_ALIAS
-#define dval(x) x
#ifdef IEEE_8087
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
#else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
#endif
-#else /* !YES_ALIAS */
-#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
-#endif
-#define dval(x) ((U*)&x)->d
-#endif /* YES_ALIAS */
+#define dval(x) (x)->d
/* The following definition of Storeinc is appropriate for MIPS processors.
* An alternative that might be better on some machines is
#define FREE_DTOA_LOCK(n) /*nothing*/
#endif
-#define Kmax 15
+#define Kmax 9
struct
Bigint {
extern double ratio ANSI((Bigint*, Bigint*));
extern void rshift ANSI((Bigint*, int));
extern char *rv_alloc ANSI((int));
- extern Bigint *s2b ANSI((CONST char*, int, int, ULong));
+ extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int));
extern Bigint *set_ones ANSI((Bigint*, int));
extern char *strcp ANSI((char*, const char*));
extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
extern double strtod ANSI((const char *s00, char **se));
extern Bigint *sum ANSI((Bigint*, Bigint*));
extern int trailz ANSI((Bigint*));
- extern double ulp ANSI((double));
+ extern double ulp ANSI((U*));
#ifdef __cplusplus
}
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
*/
#ifdef IEEE_Arith
+#ifndef NO_INFNAN_CHECK
+#undef INFNAN_CHECK
+#define INFNAN_CHECK
+#endif
#ifdef IEEE_MC68k
#define _0 0
#define _1 1
---- gdtoaimp.h.orig 2008-10-28 11:36:44.000000000 -0700
-+++ gdtoaimp.h 2008-10-28 12:01:07.000000000 -0700
-@@ -170,6 +170,91 @@
+--- gdtoaimp.h.orig 2010-01-29 16:43:20.000000000 -0800
++++ gdtoaimp.h 2010-02-01 10:58:41.000000000 -0800
+@@ -172,6 +172,91 @@
#ifndef GDTOAIMP_H_INCLUDED
#define GDTOAIMP_H_INCLUDED
#include "gdtoa.h"
#include "gd_qnan.h"
#ifdef Honor_FLT_ROUNDS
-@@ -181,8 +266,11 @@
+@@ -183,8 +268,11 @@
#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
#endif
#ifdef KR_headers
#define Char char
-@@ -196,6 +284,10 @@
+@@ -198,6 +286,10 @@
#define MALLOC malloc
#endif
#undef IEEE_Arith
#undef Avoid_Underflow
#ifdef IEEE_MC68k
-@@ -455,10 +547,14 @@
+@@ -446,10 +538,14 @@
#define ALL_ON 0xffff
#endif
+ if (__isthreaded) _SPINUNLOCK(&__gdtoa_locks[n]); \
+} while(0)
- #define Kmax 15
+ #define Kmax 9
-@@ -481,52 +577,6 @@
+@@ -472,52 +568,6 @@
#define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
#endif /* NO_STRING_H */
extern char *dtoa_result;
extern CONST double bigtens[], tens[], tinytens[];
extern unsigned char hexdig[];
-@@ -549,7 +599,7 @@
+@@ -540,7 +590,7 @@
extern char *dtoa ANSI((double d, int mode, int ndigits,
int *decpt, int *sign, char **rve));
extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
extern void hexdig_init_D2A(Void);
extern int hexnan ANSI((CONST char**, FPI*, ULong*));
extern int hi0bits_D2A ANSI((ULong));
-@@ -566,11 +616,12 @@
- extern double ratio ANSI((Bigint*, Bigint*));
- extern void rshift ANSI((Bigint*, int));
- extern char *rv_alloc ANSI((int));
-- extern Bigint *s2b ANSI((CONST char*, int, int, ULong));
-+ extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int));
- extern Bigint *set_ones ANSI((Bigint*, int));
+@@ -562,6 +612,7 @@
extern char *strcp ANSI((char*, const char*));
extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
extern double strtod ANSI((const char *s00, char **se));
+ extern double strtod_l ANSI((const char *s00, char **se, locale_t));
extern Bigint *sum ANSI((Bigint*, Bigint*));
extern int trailz ANSI((Bigint*));
- extern double ulp ANSI((double));
+ extern double ulp ANSI((U*));
+@@ -613,4 +664,78 @@
+ #define SI 0
+ #endif
+
++/*
++ * For very large strings, strtod and family might exhaust memory in tight
++ * memory conditions (especially in 32-bits). Such large strings could also
++ * tie up a CPU for minutes at a time. Either can be considered a denial-of-
++ * service vunerability.
++ *
++ * To fix, we limit the string size to the maximum we need to calculate the
++ * rounding point correctly. The longest string corresponding to the exact
++ * value of a floating point number occuring at 1.f...f p^-n, where n is
++ * the (absolute value of the) smallest exponent for a normalize number.
++ *
++ * To calculate this number of decimal digits, we use the formula:
++ *
++ * (n + m) - int(n * log10(2)) + 3
++ *
++ * where m is the number of bits in the f...f fraction. This is the number
++ * of decimal digits for the least significant bit minus the number of leading
++ * zeros for the most significant bit (the '1'), plus a few to compensate for
++ * an extra digits due to the full 1.f...f value, an extra digit for the
++ * mid-way point for rounding and an extra guard digit.
++ *
++ * Using the approximation log10(2) ~ 1233 / (2^12), converting to the fpi.emin
++ * and fpi.nbits values, we get:
++ *
++ * -fpi.emin -((1233 * (-fpi.nbits - fpi.emin)) >> 12) + 3
++ *
++ * Finally, we add an extra digit, either '1' or '0', to represent whether
++ * to-be-truncated digits contain a non-zero digit, or are all zeros,
++ * respectively.
++ *
++ * The truncated string is allocated on the heap, so code using
++ * TRUNCATE_DIGITS() will need to free that space when no longer needed.
++ * Pass a char * as the second argument, initialized to NULL; if its value
++ * becomes non-NULL, memory was allocated.
++ */
++#define LOG2NUM 1233
++#define LOG2DENOMSHIFT 12
++#define TRUNCATEDIGITS(_nbits, _emin) (-(_emin) - ((LOG2NUM * (-(_nbits) - (_emin))) >> LOG2DENOMSHIFT) + 3)
++
++#define TRUNCATE_DIGITS(_s0, _temp, _nd, _nd0, _nf, _nbits, _emin, _dplen) \
++{ \
++ int _maxdigits = TRUNCATEDIGITS((_nbits), (_emin)); \
++ if ((_nd) > _maxdigits && \
++ ((_temp) = MALLOC(_maxdigits + (_dplen) + 2)) != NULL) { \
++ char *_tp = (_temp) + _maxdigits; \
++ if ((_nd0) >= _maxdigits) { \
++ memcpy((_temp), (_s0), _maxdigits); \
++ if ((_nd) > (_nd0)) *_tp++ = '1'; \
++ else { \
++ const char *_q = (_s0) + _maxdigits; \
++ int _n = (_nd0) - _maxdigits; \
++ for(; _n > 0 && *_q == '0'; _n--, _q++) {} \
++ *_tp++ = _n > 0 ? '1' : '0'; \
++ } \
++ (_nf) = -((_nd0) - (_maxdigits + 1)); \
++ (_nd0) = _maxdigits + 1; \
++ } \
++ else if ((_nd0) == 0) { \
++ memcpy((_temp), (_s0), _maxdigits); \
++ *_tp++ = '1'; \
++ (_nf) -= ((_nd) - (_maxdigits + 1)); \
++ } \
++ else { \
++ memcpy((_temp), (_s0), _maxdigits + (_dplen)); \
++ _tp += (_dplen); \
++ *_tp++ = '1'; \
++ (_nf) = (_maxdigits + 1) - (_nd0); \
++ } \
++ *_tp = 0; \
++ (_nd) = _maxdigits + 1; \
++ (_s0) = (_temp); \
++ } \
++ }
++
+ #endif /* GDTOAIMP_H_INCLUDED */
#include "gdtoaimp.h"
+#include <sys/types.h>
+
#ifdef USE_LOCALE
#include "locale.h"
#endif
{
Bigint *b;
CONST unsigned char *decpt, *s0, *s, *s1;
+ unsigned char *strunc;
int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
ULong L, lostbits, *x;
Long e, e1;
static unsigned char *decimalpoint_cache;
if (!(s0 = decimalpoint_cache)) {
s0 = (unsigned char*)localeconv_l(loc)->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
*exp = fpi->emin;
return STRTOG_Normal | STRTOG_Inexlo;
}
+ /*
+ * Truncate the hex string if it is longer than the precision needed,
+ * to avoid denial-of-service issues with very large strings. Use
+ * additional digits to insure precision. Scan to-be-truncated digits
+ * and replace with either '1' or '0' to ensure proper rounding.
+ */
+ {
+ int maxdigits = ((fpi->nbits + 3) >> 2) + 2;
+ size_t nd = s1 - s0;
+#ifdef USE_LOCALE
+ int dplen = strlen((const char *)decimalpoint);
+#else
+ int dplen = 1;
+#endif
+
+ if (decpt && s0 < decpt)
+ nd -= dplen;
+ if (nd > maxdigits && (strunc = alloca(maxdigits + dplen + 2)) != NULL) {
+ ssize_t nd0 = decpt ? decpt - s0 - dplen : nd;
+ unsigned char *tp = strunc + maxdigits;
+ int found = 0;
+ if ((nd0 -= maxdigits) >= 0 || s0 >= decpt)
+ memcpy(strunc, s0, maxdigits);
+ else {
+ memcpy(strunc, s0, maxdigits + dplen);
+ tp += dplen;
+ }
+ s0 += maxdigits;
+ e += (nd - (maxdigits + 1)) << 2;
+ if (nd0 > 0) {
+ while(nd0-- > 0)
+ if (*s0++ != '0') {
+ found++;
+ break;
+ }
+ s0 += dplen;
+ }
+ if (!found && decpt) {
+ while(s0 < s1)
+ if(*s0++ != '0') {
+ found++;
+ break;
+ }
+ }
+ *tp++ = found ? '1' : '0';
+ *tp = 0;
+ s0 = strunc;
+ s1 = tp;
+ }
+ }
+
n = s1 - s0 - 1;
- for(k = 0; n > 7; n >>= 1)
+ for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
k++;
b = Balloc(k);
x = b->x;
if (*--s1 == '.')
continue;
#endif
- if (n == 32) {
+ if (n == ULbits) {
*x++ = L;
L = 0;
n = 0;
}
*x++ = L;
b->wds = n = x - b->x;
- n = 32*n - hi0bits(L);
+ n = ULbits*n - hi0bits(L);
nbits = fpi->nbits;
lostbits = 0;
x = b->x;
break;
case FPI_Round_near:
if (lostbits & 2
- && (lostbits & 1) | x[0] & 1)
+ && (lostbits | x[0]) & 1)
up = 1;
break;
case FPI_Round_up:
irv = STRTOG_Normal;
}
else if (b->wds > k
- || (n = nbits & kmask) !=0
- && hi0bits(x[k-1]) < 32-n) {
+ || ((n = nbits & kmask) !=0
+ && hi0bits(x[k-1]) < 32-n)) {
rshift(b,1);
if (++e > fpi->emax)
goto ovfl;
#include "gdtoaimp.h"
#include <fpmath.h>
+#ifndef __APPLE__
static void
#ifdef KR_headers
L_shift(x, x1, i) ULong *x; ULong *x1; int i;
x[1] >>= i;
} while(++x < x1);
}
+#endif /* !__APPLE__ */
int
#ifdef KR_headers
hexnan( CONST char **sp, FPI *fpi, ULong *x0)
#endif
{
+#ifdef __APPLE__
int nbits, len;
char *cp;
+#else /* !__APPLE__ */
+ ULong c, h, *x, *x1, *xe;
+#endif /* __APPLE__ */
CONST char *s;
+#ifndef __APPLE__
+ int havedig, hd0, i, nbits;
+#endif /* !__APPLE__ */
+#ifdef __APPLE__
if (sp == NULL || *sp == NULL || **sp != '(')
return STRTOG_NaN;
+#else /* !__APPLE__ */
+ if (!hexdig['0'])
+ hexdig_init_D2A();
+ nbits = fpi->nbits;
+ x = x0 + (nbits >> kshift);
+ if (nbits & kmask)
+ x++;
+ *--x = 0;
+ x1 = xe = x;
+ havedig = hd0 = i = 0;
+#endif /* __APPLE__ */
s = *sp;
+#ifdef __APPLE__
if ((cp = strchr(s + 1, ')')) == NULL) {
- *sp += strlen(s);
- cp = s + 1;
+ return STRTOG_NaN;
}
else {
len = cp - (s + 1);
cp = alloca(len + 1);
if (!cp)
+#else /* !__APPLE__ */
+ /* allow optional initial 0x or 0X */
+ while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
+ ++s;
+ if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
+ && *(CONST unsigned char*)(s+3) > ' ')
+ s += 2;
+ while((c = *(CONST unsigned char*)++s)) {
+ if (!(h = hexdig[c])) {
+ if (c <= ' ') {
+ if (hd0 < havedig) {
+ if (x < x1 && i < 8)
+ L_shift(x, x1, i);
+ if (x <= x0) {
+ i = 8;
+ continue;
+ }
+ hd0 = havedig;
+ *--x = 0;
+ x1 = x;
+ i = 0;
+ }
+ while(*(CONST unsigned char*)(s+1) <= ' ')
+ ++s;
+ if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
+ && *(CONST unsigned char*)(s+3) > ' ')
+ s += 2;
+ continue;
+ }
+ if (/*(*/ c == ')' && havedig) {
+ *sp = s + 1;
+ break;
+ }
+#ifndef GDTOA_NON_PEDANTIC_NANCHECK
+ do {
+ if (/*(*/ c == ')') {
+ *sp = s + 1;
+ break;
+ }
+ } while((c = *++s));
+#endif
+#endif /* __APPLE__ */
return STRTOG_NaN;
+#ifdef __APPLE__
strlcpy(cp, s + 1, len + 1);
*sp += len + 2;
+#else /* !__APPLE__ */
+ }
+ havedig++;
+ if (++i > 8) {
+ if (x <= x0)
+ continue;
+ i = 1;
+ *--x = 0;
+ }
+ *x = (*x << 4) | (h & 0xf);
+#endif /* __APPLE__ */
}
+#ifdef __APPLE__
nbits = fpi->nbits;
/* a hack */
if (nbits == 52) { /* double */
u.d = nan(cp);
x0[1] = u.bits.manh;
x0[0] = u.bits.manl;
+#else /* !__APPLE__ */
+ if (!havedig)
+ return STRTOG_NaN;
+ if (x < x1 && i < 8)
+ L_shift(x, x1, i);
+ if (x > x0) {
+ x1 = x0;
+ do *x1++ = *x++;
+ while(x <= xe);
+ do *x1++ = 0;
+ while(x1 <= xe);
+#endif /* __APPLE__ */
}
+#ifdef __APPLE__
else if (nbits < 52) { /* float */
union IEEEf2bits u;
u.f = nanf(cp);
x0[0] = u.bits.man;
+#else /* !__APPLE__ */
+ else {
+ /* truncate high-order word if necessary */
+ if ( (i = nbits & (ULbits-1)) !=0)
+ *xe &= ((ULong)0xffffffff) >> (ULbits - i);
+#endif /* __APPLE__ */
}
+#ifdef __APPLE__
else { /* long double */
union IEEEl2bits u;
u.e = nanl(cp);
#else
#error unsupported architecture
#endif
+#else /* !__APPLE__ */
+ for(x1 = xe;; --x1) {
+ if (*x1 != 0)
+ break;
+ if (x1 == x0) {
+ *x1 = 1;
+ break;
+ }
+#endif /* __APPLE__ */
}
-
return STRTOG_NaNbits;
}
#else /* !GDTOA_TSD */
ACQUIRE_DTOA_LOCK(0);
#endif /* GDTOA_TSD */
+ /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
+ /* but this case seems very unlikely. */
if (k <= Kmax && (rv = freelist[k]) !=0) {
freelist[k] = rv->next;
}
{
if (v) {
if (v->k > Kmax)
+#ifdef FREE
+ FREE((void*)v);
+#else
free((void*)v);
+#endif
else {
#ifdef GDTOA_TSD
Bigint **freelist = (Bigint **)pthread_getspecific(gdtoa_tsd_key);
#else /* !GDTOA_TSD */
ACQUIRE_DTOA_LOCK(0);
-#endif /* GDTOA_TSD */
+#endif /* !GDTOA_TSD */
v->next = freelist[v->k];
freelist[v->k] = v;
#ifndef GDTOA_TSD
FREE_DTOA_LOCK(0);
-#endif /* GDTOA_TSD */
+#endif /* !GDTOA_TSD */
}
}
}
(ULong *y)
#endif
{
- register int k;
- register ULong x = *y;
+ int k;
+ ULong x = *y;
if (x & 7) {
if (x & 1)
int
hi0bits_D2A
#ifdef KR_headers
- (x) register ULong x;
+ (x) ULong x;
#else
- (register ULong x)
+ (ULong x)
#endif
{
- register int k = 0;
+ int k = 0;
if (!(x & 0xffff0000)) {
k = 16;
{
ULong *xa, *xa0, w, y, z;
int k;
- double d;
+ U d;
#ifdef VAX
ULong d0, d1;
#else
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
#endif
xa0 = a->x;
*e = 32 - k;
#ifdef Pack_32
if (k < Ebits) {
- d0 = Exp_1 | y >> Ebits - k;
+ d0 = Exp_1 | y >> (Ebits - k);
w = xa > xa0 ? *--xa : 0;
- d1 = y << (32-Ebits) + k | w >> Ebits - k;
+ d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
goto ret_d;
}
z = xa > xa0 ? *--xa : 0;
if (k -= Ebits) {
- d0 = Exp_1 | y << k | z >> 32 - k;
+ d0 = Exp_1 | y << k | z >> (32 - k);
y = xa > xa0 ? *--xa : 0;
- d1 = z << k | y >> 32 - k;
+ d1 = z << k | y >> (32 - k);
}
else {
d0 = Exp_1 | y;
#endif
ret_d:
#ifdef VAX
- word0(d) = d0 >> 16 | d0 << 16;
- word1(d) = d1 >> 16 | d1 << 16;
+ word0(&d) = d0 >> 16 | d0 << 16;
+ word1(&d) = d1 >> 16 | d1 << 16;
#endif
- return dval(d);
+ return dval(&d);
}
#undef d0
#undef d1
Bigint *
d2b
#ifdef KR_headers
- (d, e, bits) double d; int *e, *bits;
+ (dd, e, bits) double dd; int *e, *bits;
#else
- (double d, int *e, int *bits)
+ (double dd, int *e, int *bits)
#endif
{
Bigint *b;
+ U d;
#ifndef Sudden_Underflow
int i;
#endif
ULong *x, y, z;
#ifdef VAX
ULong d0, d1;
- d0 = word0(d) >> 16 | word0(d) << 16;
- d1 = word1(d) >> 16 | word1(d) << 16;
#else
-#define d0 word0(d)
-#define d1 word1(d)
+#define d0 word0(&d)
+#define d1 word1(&d)
+#endif
+ d.d = dd;
+#ifdef VAX
+ d0 = word0(&d) >> 16 | word0(&d) << 16;
+ d1 = word1(&d) >> 16 | word1(&d) << 16;
#endif
#ifdef Pack_32
#ifdef Pack_32
if ( (y = d1) !=0) {
if ( (k = lo0bits(&y)) !=0) {
- x[0] = y | z << 32 - k;
+ x[0] = y | z << (32 - k);
z >>= k;
}
else
b->wds = (x[1] = z) !=0 ? 2 : 1;
}
else {
-#ifdef DEBUG
- if (!z)
- Bug("Zero passed to d2b");
-#endif
k = lo0bits(&z);
x[0] = z;
#ifndef Sudden_Underflow
#endif
#ifdef IBM
*e = (de - Bias - (P-1) << 2) + k;
- *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
+ *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
#else
*e = de - Bias - (P-1) + k;
*bits = P - k;
strcp_D2A(char *a, CONST char *b)
#endif
{
- while(*a = *b++)
+ while((*a = *b++))
a++;
return a;
}
memcpy_D2A(void *a1, void *b1, size_t len)
#endif
{
- register char *a = (char*)a1, *ae = a + len;
- register char *b = (char*)b1, *a0 = a;
+ char *a = (char*)a1, *ae = a + len;
+ char *b = (char*)b1, *a0 = a;
while(a < ae)
*a++ = *b++;
return a0;
+++ /dev/null
-/****************************************************************
-
-The author of this software is David M. Gay.
-
-Copyright (C) 1998, 1999 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
-****************************************************************/
-
-/* Please send bug reports to David M. Gay (dmg at acm dot org,
- * with " at " changed at "@" and " dot " changed to "."). */
-
-#include "gdtoaimp.h"
-
- Bigint *
-s2b
-#ifdef KR_headers
- (s, nd0, nd, y9, decpt) CONST char *s; int nd0, nd; ULong y9; int decpt;
-#else
- (CONST char *s, int nd0, int nd, ULong y9, int decpt)
-#endif
-{
- Bigint *b;
- int i, k;
- Long x, y;
-
- x = (nd + 8) / 9;
- for(k = 0, y = 1; x > y; y <<= 1, k++) ;
-#ifdef Pack_32
- b = Balloc(k);
- b->x[0] = y9;
- b->wds = 1;
-#else
- b = Balloc(k+1);
- b->x[0] = y9 & 0xffff;
- b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
- i = 9;
- if (9 < nd0) {
- s += 9;
- do b = multadd(b, 10, *s++ - '0');
- while(++i < nd0);
- s += decpt;
- }
- else
- s += 9 + decpt;
- for(; i < nd; i++)
- b = multadd(b, 10, *s++ - '0');
- return b;
- }
-
- double
-ratio
-#ifdef KR_headers
- (a, b) Bigint *a, *b;
-#else
- (Bigint *a, Bigint *b)
-#endif
-{
- double da, db;
- int k, ka, kb;
-
- dval(da) = b2d(a, &ka);
- dval(db) = b2d(b, &kb);
- k = ka - kb + ULbits*(a->wds - b->wds);
-#ifdef IBM
- if (k > 0) {
- word0(da) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- dval(da) *= 1 << k;
- }
- else {
- k = -k;
- word0(db) += (k >> 2)*Exp_msk1;
- if (k &= 3)
- dval(db) *= 1 << k;
- }
-#else
- if (k > 0)
- word0(da) += k*Exp_msk1;
- else {
- k = -k;
- word0(db) += k*Exp_msk1;
- }
-#endif
- return dval(da) / dval(db);
- }
-
-#ifdef INFNAN_CHECK
-
- int
-match
-#ifdef KR_headers
- (sp, t) char **sp, *t;
-#else
- (CONST char **sp, char *t)
-#endif
-{
- int c, d;
- CONST char *s = *sp;
-
- while( (d = *t++) !=0) {
- if ((c = *++s) >= 'A' && c <= 'Z')
- c += 'a' - 'A';
- if (c != d)
- return 0;
- }
- *sp = s + 1;
- return 1;
- }
-#endif /* INFNAN_CHECK */
-
- void
-#ifdef KR_headers
-copybits(c, n, b) ULong *c; int n; Bigint *b;
-#else
-copybits(ULong *c, int n, Bigint *b)
-#endif
-{
- ULong *ce, *x, *xe;
-#ifdef Pack_16
- int nw, nw1;
-#endif
-
- ce = c + ((n-1) >> kshift) + 1;
- x = b->x;
-#ifdef Pack_32
- xe = x + b->wds;
- while(x < xe)
- *c++ = *x++;
-#else
- nw = b->wds;
- nw1 = nw & 1;
- for(xe = x + (nw - nw1); x < xe; x += 2)
- Storeinc(c, x[1], x[0]);
- if (nw1)
- *c++ = *x;
-#endif
- while(c < ce)
- *c++ = 0;
- }
-
- ULong
-#ifdef KR_headers
-any_on(b, k) Bigint *b; int k;
-#else
-any_on(Bigint *b, int k)
-#endif
-{
- int n, nwds;
- ULong *x, *x0, x1, x2;
-
- x = b->x;
- nwds = b->wds;
- n = k >> kshift;
- if (n > nwds)
- n = nwds;
- else if (n < nwds && (k &= kmask)) {
- x1 = x2 = x[n];
- x1 >>= k;
- x1 <<= k;
- if (x1 != x2)
- return 1;
- }
- x0 = x;
- x += n;
- while(x > x0)
- if (*--x)
- return 1;
- return 0;
- }
--- /dev/null
+./gdtoa-smisc.c
\ No newline at end of file
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
CONST char *s, *s0, *s1;
- double aadj, aadj1, adj, rv, rv0;
+ char *strunc = NULL;
+ double aadj;
Long L;
+ U adj, aadj1, rv, rv0;
ULong y, z;
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
-#ifdef USE_LOCALE
+#ifdef USE_LOCALE /*{{*/
NORMALIZE_LOCALE(loc);
#ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv_l(loc)->decimal_point;
+ int dplen = strlen(decimalpoint);
#else
char *decimalpoint;
static char *decimalpoint_cache;
+ static int dplen;
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv_l(loc)->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
+ dplen = strlen(s0);
}
decimalpoint = (char*)s0;
-#endif
-#endif
+#endif /*NO_LOCALE_CACHE*/
+#else /*USE_LOCALE}{*/
+#define dplen 1
+#endif /*USE_LOCALE}}*/
+
#ifdef Honor_FLT_ROUNDS /*{*/
int Rounding;
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
#endif /*}*/
sign = nz0 = nz = decpt = 0;
- dval(rv) = 0.;
+ dval(&rv) = 0.;
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
case 'x':
case 'X':
{
-#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD) /*{{*/
+#ifdef Honor_FLT_ROUNDS
FPI fpi1 = fpi;
-#ifdef Honor_FLT_ROUNDS /*{{*/
fpi1.rounding = Rounding;
-#else /*}{*/
- switch(fegetround()) {
- case FE_TOWARDZERO: fpi1.rounding = 0; break;
- case FE_UPWARD: fpi1.rounding = 2; break;
- case FE_DOWNWARD: fpi1.rounding = 3;
- }
-#endif /*}}*/
-#else /*}{*/
+#else
#define fpi1 fpi
-#endif /*}}*/
+#endif
switch((i = gethex(&s, &fpi1, &exp, &bb, sign, loc)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
--s;
if (!match(&s,"inity"))
++s;
- word0(rv) = 0x7ff00000;
- word1(rv) = 0;
+ word0(&rv) = 0x7ff00000;
+ word1(&rv) = 0;
goto ret;
}
break;
if (*s == '(' /*)*/
&& hexnan(&s, &fpinan, bits)
== STRTOG_NaNbits) {
- word0(rv) = 0x7ff00000 | bits[1];
- word1(rv) = bits[0];
+ word0(&rv) = 0x7ff00000 | bits[1];
+ word1(&rv) = bits[0];
}
else {
#endif
- word0(rv) = NAN_WORD0;
- word1(rv) = NAN_WORD1;
+ word0(&rv) = NAN_WORD0;
+ word1(&rv) = NAN_WORD1;
#ifndef No_Hex_NaN
}
#endif
}
goto ret;
}
+#define FPIEMIN (1-1023-53+1) // fpi.emin
+#define FPINBITS 52 // fpi.nbits
+ TRUNCATE_DIGITS(s0, strunc, nd, nd0, nf, FPINBITS, FPIEMIN, dplen);
e1 = e -= nf;
/* Now we have nd0 digits, starting at s0, followed by a
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ dval(&rv) = y;
if (k > 9) {
#ifdef SET_INEXACT
if (k > DBL_DIG)
oldinexact = get_inexact();
#endif
- dval(rv) = tens[k - 9] * dval(rv) + z;
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
}
bd0 = 0;
if (nd <= DBL_DIG
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ dval(&rv) = -dval(&rv);
sign = 0;
}
#endif
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
goto ret;
#endif
}
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ dval(&rv) = -dval(&rv);
sign = 0;
}
#endif
e -= i;
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
- word0(rv) -= P*Exp_msk1;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if ((word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if ((word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto ovfl;
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
#else
- /* rv = */ rounded_product(dval(rv), tens[e]);
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
#endif
goto ret;
}
#ifdef Honor_FLT_ROUNDS
/* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) {
- rv = -rv;
+ dval(&rv) = -dval(&rv);
sign = 0;
}
#endif
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
goto ret;
}
#endif
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
switch(Rounding) {
case 0: /* toward 0 */
case 3: /* toward -infinity */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
break;
default:
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
}
#else /*Honor_FLT_ROUNDS*/
- word0(rv) = Exp_mask;
- word1(rv) = 0;
+ word0(&rv) = Exp_mask;
+ word1(&rv) = 0;
#endif /*Honor_FLT_ROUNDS*/
#ifdef SET_INEXACT
/* set overflow bit */
- dval(rv0) = 1e300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e300;
+ dval(&rv0) *= dval(&rv0);
#endif
#else /*IEEE_Arith*/
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
#endif /*IEEE_Arith*/
if (bd0)
goto retfree;
e1 >>= 4;
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= bigtens[j];
+ dval(&rv) *= bigtens[j];
/* The last multiplication could overflow. */
- word0(rv) -= P*Exp_msk1;
- dval(rv) *= bigtens[j];
- if ((z = word0(rv) & Exp_mask)
+ word0(&rv) -= P*Exp_msk1;
+ dval(&rv) *= bigtens[j];
+ if ((z = word0(&rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
goto ovfl;
if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
/* set to largest number */
/* (Can't trust DBL_MAX) */
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 >>= 4) {
if (e1 >= 1 << n_bigtens)
goto undfl;
scale = 2*P;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
- if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+ dval(&rv) *= tinytens[j];
+ if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)
>> Exp_shift)) > 0) {
/* scaled rv is denormal; zap j low bits */
if (j >= 32) {
- word1(rv) = 0;
+ word1(&rv) = 0;
if (j >= 53)
- word0(rv) = (P+2)*Exp_msk1;
+ word0(&rv) = (P+2)*Exp_msk1;
else
- word0(rv) &= 0xffffffff << j-32;
+ word0(&rv) &= 0xffffffff << (j-32);
}
else
- word1(rv) &= 0xffffffff << j;
+ word1(&rv) &= 0xffffffff << j;
}
#else
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ dval(&rv) *= tinytens[j];
/* The last multiplication could underflow. */
- dval(rv0) = dval(rv);
- dval(rv) *= tinytens[j];
- if (!dval(rv)) {
- dval(rv) = 2.*dval(rv0);
- dval(rv) *= tinytens[j];
+ dval(&rv0) = dval(&rv);
+ dval(&rv) *= tinytens[j];
+ if (!dval(&rv)) {
+ dval(&rv) = 2.*dval(&rv0);
+ dval(&rv) *= tinytens[j];
#endif
- if (!dval(rv)) {
+ if (!dval(&rv)) {
undfl:
- dval(rv) = 0.;
+ dval(&rv) = 0.;
#ifndef NO_ERRNO
errno = ERANGE;
#endif
goto ret;
}
#ifndef Avoid_Underflow
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
/* The refinement below will clean
* this approximation up.
*/
/* Put digits into bd: true value = bd * 10^e */
-#ifdef USE_LOCALE
- bd0 = s2b(s0, nd0, nd, y, strlen(decimalpoint));
-#else
- bd0 = s2b(s0, nd0, nd, y, 1);
-#endif
+ bd0 = s2b(s0, nd0, nd, y, dplen);
for(;;) {
bd = Balloc(bd0->k);
Bcopy(bd, bd0);
- bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
bs = i2b(1);
if (e >= 0) {
#endif
#ifdef Avoid_Underflow
j = bbe - scale;
- i = j + bbbits - 1; /* logb(rv) */
+ i = j + bbbits - 1; /* logb(&rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
#endif
#else /*Sudden_Underflow*/
j = bbe;
- i = j + bbbits - 1; /* logb(rv) */
+ i = j + bbbits - 1; /* logb(&rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
}
if (Rounding) {
if (dsign) {
- adj = 1.;
+ dval(&adj) = 1.;
goto apply_adj;
}
}
else if (!dsign) {
- adj = -1.;
- if (!word1(rv)
- && !(word0(rv) & Frac_mask)) {
- y = word0(rv) & Exp_mask;
+ dval(&adj) = -1.;
+ if (!word1(&rv)
+ && !(word0(&rv) & Frac_mask)) {
+ y = word0(&rv) & Exp_mask;
#ifdef Avoid_Underflow
if (!scale || y > 2*P*Exp_msk1)
#else
{
delta = lshift(delta,Log2P);
if (cmp(delta, bs) <= 0)
- adj = -0.5;
+ dval(&adj) = -0.5;
}
}
apply_adj:
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask)
+ if (scale && (y = word0(&rv) & Exp_mask)
<= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <=
+ if ((word0(&rv) & Exp_mask) <=
P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- dval(rv) += adj*ulp(dval(rv));
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
+ dval(&rv) += adj*ulp(&rv);
+ word0(&rv) -= P*Exp_msk1;
}
else
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- dval(rv) += adj*ulp(dval(rv));
+ dval(&rv) += dval(&adj)*ulp(&rv);
}
break;
}
- adj = ratio(delta, bs);
- if (adj < 1.)
- adj = 1.;
- if (adj <= 0x7ffffffe) {
- /* adj = Rounding ? ceil(adj) : floor(adj); */
- y = adj;
- if (y != adj) {
+ dval(&adj) = ratio(delta, bs);
+ if (dval(&adj) < 1.)
+ dval(&adj) = 1.;
+ if (dval(&adj) <= 0x7ffffffe) {
+ /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
+ y = dval(&adj);
+ if (y != dval(&adj)) {
if (!((Rounding>>1) ^ dsign))
y++;
- adj = y;
+ dval(&adj) = y;
}
}
#ifdef Avoid_Underflow
- if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
- word0(adj) += (2*P+1)*Exp_msk1 - y;
+ if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(&adj) += (2*P+1)*Exp_msk1 - y;
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- word0(rv) += P*Exp_msk1;
- adj *= ulp(dval(rv));
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) *= ulp(&rv);
if (dsign)
- dval(rv) += adj;
+ dval(&rv) += adj;
else
- dval(rv) -= adj;
- word0(rv) -= P*Exp_msk1;
+ dval(&rv) -= adj;
+ word0(&rv) -= P*Exp_msk1;
goto cont;
}
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
- adj *= ulp(dval(rv));
+ dval(&adj) *= ulp(&rv);
if (dsign) {
- if (word0(rv) == Big0 && word1(rv) == Big1)
+ if (word0(&rv) == Big0 && word1(&rv) == Big1)
goto ovfl;
- dval(rv) += adj;
+ dval(&rv) += dval(&adj);
}
else
- dval(rv) -= adj;
+ dval(&rv) -= dval(&adj);
goto cont;
}
#endif /*Honor_FLT_ROUNDS*/
/* Error is less than half an ulp -- check for
* special case of mantissa a power of two.
*/
- if (dsign || word1(rv) || word0(rv) & Bndry_mask
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
#ifdef IEEE_Arith
#ifdef Avoid_Underflow
- || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+ || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1
#else
- || (word0(rv) & Exp_mask) <= Exp_msk1
+ || (word0(&rv) & Exp_mask) <= Exp_msk1
#endif
#endif
) {
if (i == 0) {
/* exactly half-way between */
if (dsign) {
- if ((word0(rv) & Bndry_mask1) == Bndry_mask1
- && word1(rv) == (
+ if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
+ && word1(&rv) == (
#ifdef Avoid_Underflow
- (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1)
? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
#endif
0xffffffff)) {
/*boundary case -- increment exponent*/
- word0(rv) = (word0(rv) & Exp_mask)
+ word0(&rv) = (word0(&rv) & Exp_mask)
+ Exp_msk1
#ifdef IBM
| Exp_msk1 >> 4
#endif
;
- word1(rv) = 0;
+ word1(&rv) = 0;
#ifdef Avoid_Underflow
dsign = 0;
#endif
break;
}
}
- else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
drop_down:
/* boundary case -- decrement exponent */
#ifdef Sudden_Underflow /*{{*/
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
#ifdef IBM
if (L < Exp_msk1)
#else
#else /*Sudden_Underflow}{*/
#ifdef Avoid_Underflow
if (scale) {
- L = word0(rv) & Exp_mask;
+ L = word0(&rv) & Exp_mask;
if (L <= (2*P+1)*Exp_msk1) {
if (L > (P+2)*Exp_msk1)
/* round even ==> */
}
}
#endif /*Avoid_Underflow*/
- L = (word0(rv) & Exp_mask) - Exp_msk1;
+ L = (word0(&rv) & Exp_mask) - Exp_msk1;
#endif /*Sudden_Underflow}}*/
- word0(rv) = L | Bndry_mask1;
- word1(rv) = 0xffffffff;
+ word0(&rv) = L | Bndry_mask1;
+ word1(&rv) = 0xffffffff;
#ifdef IBM
goto cont;
#else
#endif
}
#ifndef ROUND_BIASED
- if (!(word1(rv) & LSB))
+ if (!(word1(&rv) & LSB))
break;
#endif
if (dsign)
- dval(rv) += ulp(dval(rv));
+ dval(&rv) += ulp(&rv);
#ifndef ROUND_BIASED
else {
- dval(rv) -= ulp(dval(rv));
+ dval(&rv) -= ulp(&rv);
#ifndef Sudden_Underflow
- if (!dval(rv))
+ if (!dval(&rv))
goto undfl;
#endif
}
}
if ((aadj = ratio(delta, bs)) <= 2.) {
if (dsign)
- aadj = aadj1 = 1.;
- else if (word1(rv) || word0(rv) & Bndry_mask) {
+ aadj = dval(&aadj1) = 1.;
+ else if (word1(&rv) || word0(&rv) & Bndry_mask) {
#ifndef Sudden_Underflow
- if (word1(rv) == Tiny1 && !word0(rv))
+ if (word1(&rv) == Tiny1 && !word0(&rv))
goto undfl;
#endif
aadj = 1.;
- aadj1 = -1.;
+ dval(&aadj1) = -1.;
}
else {
/* special case -- power of FLT_RADIX to be */
aadj = 1./FLT_RADIX;
else
aadj *= 0.5;
- aadj1 = -aadj;
+ dval(&aadj1) = -aadj;
}
}
else {
aadj *= 0.5;
- aadj1 = dsign ? aadj : -aadj;
+ dval(&aadj1) = dsign ? aadj : -aadj;
#ifdef Check_FLT_ROUNDS
switch(Rounding) {
case 2: /* towards +infinity */
- aadj1 -= 0.5;
+ dval(&aadj1) -= 0.5;
break;
case 0: /* towards 0 */
case 3: /* towards -infinity */
- aadj1 += 0.5;
+ dval(&aadj1) += 0.5;
}
#else
if (Flt_Rounds == 0)
- aadj1 += 0.5;
+ dval(&aadj1) += 0.5;
#endif /*Check_FLT_ROUNDS*/
}
- y = word0(rv) & Exp_mask;
+ y = word0(&rv) & Exp_mask;
/* Check for overflow */
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- dval(rv0) = dval(rv);
- word0(rv) -= P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
- if ((word0(rv) & Exp_mask) >=
+ dval(&rv0) = dval(&rv);
+ word0(&rv) -= P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
+ if ((word0(&rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
- if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
goto ovfl;
- word0(rv) = Big0;
- word1(rv) = Big1;
+ word0(&rv) = Big0;
+ word1(&rv) = Big1;
goto cont;
}
else
- word0(rv) += P*Exp_msk1;
+ word0(&rv) += P*Exp_msk1;
}
else {
#ifdef Avoid_Underflow
if ((z = aadj) <= 0)
z = 1;
aadj = z;
- aadj1 = dsign ? aadj : -aadj;
+ dval(&aadj1) = dsign ? aadj : -aadj;
}
- word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+ word0(&aadj1) += (2*P+1)*Exp_msk1 - y;
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += dval(&adj);
#else
#ifdef Sudden_Underflow
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- dval(rv0) = dval(rv);
- word0(rv) += P*Exp_msk1;
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(&rv0) = dval(&rv);
+ word0(&rv) += P*Exp_msk1;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
#ifdef IBM
- if ((word0(rv) & Exp_mask) < P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) < P*Exp_msk1)
#else
- if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+ if ((word0(&rv) & Exp_mask) <= P*Exp_msk1)
#endif
{
- if (word0(rv0) == Tiny0
- && word1(rv0) == Tiny1)
+ if (word0(&rv0) == Tiny0
+ && word1(&rv0) == Tiny1)
goto undfl;
- word0(rv) = Tiny0;
- word1(rv) = Tiny1;
+ word0(&rv) = Tiny0;
+ word1(&rv) = Tiny1;
goto cont;
}
else
- word0(rv) -= P*Exp_msk1;
+ word0(&rv) -= P*Exp_msk1;
}
else {
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
}
#else /*Sudden_Underflow*/
- /* Compute adj so that the IEEE rounding rules will
- * correctly round rv + adj in some half-way cases.
- * If rv * ulp(rv) is denormalized (i.e.,
+ /* Compute dval(&adj) so that the IEEE rounding rules will
+ * correctly round rv + dval(&adj) in some half-way cases.
+ * If rv * ulp(&rv) is denormalized (i.e.,
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
* trouble from bits lost to denormalization;
* example: 1.2e-307 .
*/
if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
- aadj1 = (double)(int)(aadj + 0.5);
+ dval(&aadj1) = (double)(int)(aadj + 0.5);
if (!dsign)
- aadj1 = -aadj1;
+ dval(&aadj1) = -dval(&aadj1);
}
- adj = aadj1 * ulp(dval(rv));
- dval(rv) += adj;
+ dval(&adj) = dval(&aadj1) * ulp(&rv);
+ dval(&rv) += adj;
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
}
- z = word0(rv) & Exp_mask;
+ z = word0(&rv) & Exp_mask;
#ifndef SET_INEXACT
#ifdef Avoid_Underflow
if (!scale)
L = (Long)aadj;
aadj -= L;
/* The tolerances below are conservative. */
- if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
if (aadj < .4999999 || aadj > .5000001)
break;
}
#ifdef SET_INEXACT
if (inexact) {
if (!oldinexact) {
- word0(rv0) = Exp_1 + (70 << Exp_shift);
- word1(rv0) = 0;
- dval(rv0) += 1.;
+ word0(&rv0) = Exp_1 + (70 << Exp_shift);
+ word1(&rv0) = 0;
+ dval(&rv0) += 1.;
}
}
else if (!oldinexact)
#endif
#ifdef Avoid_Underflow
if (scale) {
- word0(rv0) = Exp_1 - 2*P*Exp_msk1;
- word1(rv0) = 0;
- dval(rv) *= dval(rv0);
+ word0(&rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(&rv0) = 0;
+ dval(&rv) *= dval(&rv0);
#ifndef NO_ERRNO
/* try to avoid the bug of testing an 8087 register value */
#if defined(IEEE_Arith) && __DARWIN_UNIX03
- if (!(word0(rv) & Exp_mask))
+ if (!(word0(&rv) & Exp_mask))
#else
- if (word0(rv) == 0 && word1(rv) == 0)
+ if (word0(&rv) == 0 && word1(&rv) == 0)
#endif
errno = ERANGE;
#endif
}
#endif /* Avoid_Underflow */
#ifdef SET_INEXACT
- if (inexact && !(word0(rv) & Exp_mask)) {
+ if (inexact && !(word0(&rv) & Exp_mask)) {
/* set underflow bit */
- dval(rv0) = 1e-300;
- dval(rv0) *= dval(rv0);
+ dval(&rv0) = 1e-300;
+ dval(&rv0) *= dval(&rv0);
}
#endif
retfree:
ret:
if (se)
*se = (char *)s;
- return sign ? -dval(rv) : dval(rv);
+ if (strunc)
+#ifdef FREE
+ FREE(strunc);
+#else
+ free(strunc);
+#endif
+ return sign ? -dval(&rv) : dval(&rv);
}
double
extern CONST int fivesbits[];
int all_on(Bigint *b, int n);
Bigint *set_ones(Bigint *b, int n);
-int rvOK(double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv);
-int mantbits(double d);
+int rvOK(U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv);
+int mantbits(U *d);
#else /* !BUILDING_VARIANT */
__private_extern__ CONST int
rvOK
#ifdef KR_headers
(d, fpi, exp, bits, exact, rd, irv)
- double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
+ U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
#else
- (double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
+ (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
#endif
{
Bigint *b;
int bdif, e, j, k, k1, nb, rv;
carry = rv = 0;
- b = d2b(d, &e, &bdif);
+ b = d2b(dval(d), &e, &bdif);
bdif -= nb = fpi->nbits;
e += bdif;
if (bdif <= 0) {
__private_extern__ int
#ifdef KR_headers
-mantbits(d) double d;
+mantbits(d) U *d;
#else
-mantbits(double d)
+mantbits(U *d)
#endif
{
ULong L;
int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
int sudden_underflow;
CONST char *s, *s0, *s1;
- double adj, adj0, rv, tol;
+ char *strunc = NULL;
+ double adj0, tol;
Long L;
+ U adj, rv;
ULong *b, *be, y, z;
Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
-#ifdef USE_LOCALE
- NORMALIZE_LOCALE(loc)
+#ifdef USE_LOCALE /*{{*/
+ NORMALIZE_LOCALE(loc);
#ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv_l(loc)->decimal_point;
+ int dplen = strlen(decimalpoint);
#else
char *decimalpoint;
static char *decimalpoint_cache;
+ static int dplen;
if (!(s0 = decimalpoint_cache)) {
s0 = localeconv_l(loc)->decimal_point;
- if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
}
+ dplen = strlen(s0);
}
decimalpoint = (char*)s0;
-#endif
-#endif
+#endif /*NO_LOCALE_CACHE*/
+#else /*USE_LOCALE}{*/
+#define dplen 1
+#endif /*USE_LOCALE}}*/
irv = STRTOG_Zero;
denorm = sign = nz0 = nz = 0;
- dval(rv) = 0.;
+ dval(&rv) = 0.;
rvb = 0;
nbits = fpi->nbits;
for(s = s00;;s++) switch(*s) {
}
goto ret;
}
+ TRUNCATE_DIGITS(s0, strunc, nd, nd0, nf, fpi->nbits, fpi->emin, dplen);
irv = STRTOG_Normal;
e1 = e -= nf;
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- dval(rv) = y;
+ dval(&rv) = y;
if (k > 9)
- dval(rv) = tens[k - 9] * dval(rv) + z;
+ dval(&rv) = tens[k - 9] * dval(&rv) + z;
bd0 = 0;
if (nbits <= P && nd <= DBL_DIG) {
if (!e) {
- if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv))
+ if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv))
goto ret;
}
else if (e > 0) {
#ifdef VAX
goto vax_ovfl_check;
#else
- i = fivesbits[e] + mantbits(dval(rv)) <= P;
- /* rv = */ rounded_product(dval(rv), tens[e]);
- if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
+ i = fivesbits[e] + mantbits(&rv) <= P;
+ /* rv = */ rounded_product(dval(&rv), tens[e]);
+ if (rvOK(&rv, fpi, exp, bits, i, rd, &irv))
goto ret;
e1 -= e;
goto rv_notOK;
*/
e2 = e - i;
e1 -= i;
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
- dval(adj) = dval(rv);
- word0(adj) -= P*Exp_msk1;
- /* adj = */ rounded_product(dval(adj), tens[e2]);
- if ((word0(adj) & Exp_mask)
+ dval(&adj) = dval(&rv);
+ word0(&adj) -= P*Exp_msk1;
+ /* adj = */ rounded_product(dval(&adj), tens[e2]);
+ if ((word0(&adj) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto rv_notOK;
- word0(adj) += P*Exp_msk1;
- dval(rv) = dval(adj);
+ word0(&adj) += P*Exp_msk1;
+ dval(&rv) = dval(&adj);
#else
- /* rv = */ rounded_product(dval(rv), tens[e2]);
+ /* rv = */ rounded_product(dval(&rv), tens[e2]);
#endif
- if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e2;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
- /* rv = */ rounded_quotient(dval(rv), tens[-e]);
- if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
+ /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
+ if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv))
goto ret;
e1 -= e;
}
e2 = 0;
if (e1 > 0) {
if ( (i = e1 & 15) !=0)
- dval(rv) *= tens[i];
+ dval(&rv) *= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
- while(e1 >= (1 << n_bigtens-1)) {
- e2 += ((word0(rv) & Exp_mask)
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
- dval(rv) *= bigtens[n_bigtens-1];
- e1 -= 1 << n_bigtens-1;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= bigtens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
}
- e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= bigtens[j];
+ dval(&rv) *= bigtens[j];
}
}
else if (e1 < 0) {
e1 = -e1;
if ( (i = e1 & 15) !=0)
- dval(rv) /= tens[i];
+ dval(&rv) /= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
- while(e1 >= (1 << n_bigtens-1)) {
- e2 += ((word0(rv) & Exp_mask)
+ while(e1 >= (1 << (n_bigtens-1))) {
+ e2 += ((word0(&rv) & Exp_mask)
>> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
- dval(rv) *= tinytens[n_bigtens-1];
- e1 -= 1 << n_bigtens-1;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
+ dval(&rv) *= tinytens[n_bigtens-1];
+ e1 -= 1 << (n_bigtens-1);
}
- e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
- word0(rv) &= ~Exp_mask;
- word0(rv) |= Bias << Exp_shift1;
+ e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias;
+ word0(&rv) &= ~Exp_mask;
+ word0(&rv) |= Bias << Exp_shift1;
for(j = 0; e1 > 0; j++, e1 >>= 1)
if (e1 & 1)
- dval(rv) *= tinytens[j];
+ dval(&rv) *= tinytens[j];
}
}
#ifdef IBM
*/
e2 <<= 2;
#endif
- rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */
+ rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */
rve += e2;
if ((j = rvbits - nbits) > 0) {
rshift(rvb, j);
/* Put digits into bd: true value = bd * 10^e */
-#ifdef USE_LOCALE
- bd0 = s2b(s0, nd0, nd, y, strlen(decimalpoint));
-#else
- bd0 = s2b(s0, nd0, nd, y, 1);
-#endif
+ bd0 = s2b(s0, nd0, nd, y, dplen);
for(;;) {
bd = Balloc(bd0->k);
}
else
irv = STRTOG_Normal | STRTOG_Inexhi;
- if (bbbits < nbits && !denorm || !(rvb->x[0] & 1))
+ if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1))
break;
if (dsign) {
rvb = increment(rvb);
}
break;
}
- if ((dval(adj) = ratio(delta, bs)) <= 2.) {
+ if ((dval(&adj) = ratio(delta, bs)) <= 2.) {
adj1:
inex = STRTOG_Inexlo;
if (dsign) {
irv = STRTOG_Underflow | STRTOG_Inexlo;
break;
}
- adj0 = dval(adj) = 1.;
+ adj0 = dval(&adj) = 1.;
}
else {
- adj0 = dval(adj) *= 0.5;
+ adj0 = dval(&adj) *= 0.5;
if (dsign) {
asub = 0;
inex = STRTOG_Inexlo;
}
- if (dval(adj) < 2147483647.) {
+ if (dval(&adj) < 2147483647.) {
L = adj0;
adj0 -= L;
switch(rd) {
inex = STRTOG_Inexact - inex;
}
}
- dval(adj) = L;
+ dval(&adj) = L;
}
}
y = rve + rvbits;
- /* adj *= ulp(dval(rv)); */
+ /* adj *= ulp(dval(&rv)); */
/* if (asub) rv -= adj; else rv += adj; */
if (!denorm && rvbits < nbits) {
rve -= j;
rvbits = nbits;
}
- ab = d2b(dval(adj), &abe, &abits);
+ ab = d2b(dval(&adj), &abe, &abits);
if (abe < 0)
rshift(ab, -abe);
else if (abe > 0)
z = rve + rvbits;
if (y == z && L) {
/* Can we stop now? */
- tol = dval(adj) * 5e-16; /* > max rel error */
- dval(adj) = adj0 - .5;
- if (dval(adj) < -tol) {
+ tol = dval(&adj) * 5e-16; /* > max rel error */
+ dval(&adj) = adj0 - .5;
+ if (dval(&adj) < -tol) {
if (adj0 > tol) {
irv |= inex;
break;
}
}
- else if (dval(adj) > tol && adj0 < 1. - tol) {
+ else if (dval(&adj) > tol && adj0 < 1. - tol) {
irv |= inex;
break;
}
copybits(bits, nbits, rvb);
Bfree(rvb);
}
+ if (strunc)
+#ifdef FREE
+ FREE(strunc);
+#else
+ free(strunc);
+#endif
return irv;
}
case STRTOG_Normal:
case STRTOG_NaNbits:
- u.L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23;
+ u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23);
break;
case STRTOG_Denormal:
case STRTOG_Normal:
u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL;
- u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff
- | exp + 0x3ff + 105 << 20;
+ u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff)
+ | ((exp + 0x3ff + 105) << 20);
exp += 0x3ff + 52;
if (bits[1] &= 0x1fffff) {
i = hi0bits(bits[1]) - 11;
else
exp -= i;
if (i > 0) {
- bits[1] = bits[1] << i | bits[0] >> 32-i;
+ bits[1] = bits[1] << i | bits[0] >> (32-i);
bits[0] = bits[0] << i & 0xffffffffL;
}
}
else
exp -= i;
if (i < 32) {
- bits[1] = bits[0] >> 32 - i;
+ bits[1] = bits[0] >> (32 - i);
bits[0] = bits[0] << i & 0xffffffffL;
}
else {
- bits[1] = bits[0] << i - 32;
+ bits[1] = bits[0] << (i - 32);
bits[0] = 0;
}
}
break;
}
u->L[2+_1] = bits[0];
- u->L[2+_0] = bits[1] & 0xfffff | exp << 20;
+ u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20);
#ifdef __APPLE__
fixLDBL(u->ld);
#endif /* __APPLE__ */
nearly_normal:
i = hi0bits(bits[3]) - 11; /* i >= 12 */
j = 32 - i;
- u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff
- | 65 - i << 20;
+ u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff)
+ | ((65 - i) << 20);
u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
#ifdef __APPLE__
fixLDBL(u->ld);
if (i < 0) {
j = -i;
i += 32;
- u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20;
- u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL;
- u->L[2+_0] = bits[1] & (1L << j) - 1;
+ u->L[_0] = (bits[2] >> j & 0xfffff) | (33 + j) << 20;
+ u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL;
+ u->L[2+_0] = bits[1] & ((1L << j) - 1);
u->L[2+_1] = bits[0];
#ifdef __APPLE__
fixLDBL(u->ld);
break;
}
if (i == 0) {
- u->L[_0] = bits[2] & 0xfffff | 33 << 20;
+ u->L[_0] = (bits[2] & 0xfffff) | (33 << 20);
u->L[_1] = bits[1];
u->L[2+_0] = 0;
u->L[2+_1] = bits[0];
break;
}
j = 32 - i;
- u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff
- | j + 1 << 20;
+ u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff)
+ | ((j + 1) << 20);
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
#ifdef __APPLE__
fixLDBL(u->ld);
#endif /* __APPLE__ */
hardly_normal:
j = 11 - hi0bits(bits[1]);
i = 32 - j;
- u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20;
+ u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20);
u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL;
u->L[2+_0] = 0;
- u->L[2+_1] = bits[0] & (1L << j) - 1;
+ u->L[2+_1] = bits[0] & ((1L << j) - 1);
#ifdef __APPLE__
fixLDBL(u->ld);
#endif /* __APPLE__ */
case STRTOG_Infinite:
L[_0] = 0x7fff;
- L[_1] = 0x8000; /* 4306392: to match gcc */
+ L[_1] = 0x8000;
L[_2] = L[_3] = L[_4] = 0;
break;
* #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
* if memory is available and otherwise does something you deem
* appropriate. If MALLOC is undefined, malloc will be invoked
- * directly -- and assumed always to succeed.
+ * directly -- and assumed always to succeed. Similarly, if you
+ * want something other than the system's free() to be called to
+ * recycle memory acquired from MALLOC, #define FREE to be the
+ * name of the alternate routine. (FREE or free is only called in
+ * pathological cases, e.g., in a gdtoa call after a gdtoa return in
+ * mode 3 with thousands of digits requested.)
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
* memory allocations from a private pool of memory when possible.
* When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
* conversions of IEEE doubles in single-threaded executions with
* 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with
* 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- * Infinity and NaN (case insensitively).
+ * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
+ * #defined automatically on IEEE systems. On such systems,
+ * when INFNAN_CHECK is #defined, strtod checks
+ * for Infinity and NaN (case insensitively).
* When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
* strtodg also accepts (case insensitively) strings of the form
* NaN(x), where x is a string of hexadecimal digits (optionally
* #define NO_STRING_H to use private versions of memcpy.
* On some K&R systems, it may also be necessary to
* #define DECLARE_SIZE_T in this case.
- * #define YES_ALIAS to permit aliasing certain double values with
- * arrays of ULongs. This leads to slightly better code with
- * some compilers and was always used prior to 19990916, but it
- * is not strictly legal and can cause trouble with aggressively
- * optimizing compilers (e.g., gcc 2.95.1 under -O2).
* #define USE_LOCALE to use the current locale's decimal_point value.
*/
typedef union { double d; ULong L[2]; } U;
-#ifdef YES_ALIAS
-#define dval(x) x
#ifdef IEEE_8087
-#define word0(x) ((ULong *)&x)[1]
-#define word1(x) ((ULong *)&x)[0]
+#define word0(x) (x)->L[1]
+#define word1(x) (x)->L[0]
#else
-#define word0(x) ((ULong *)&x)[0]
-#define word1(x) ((ULong *)&x)[1]
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
#endif
-#else /* !YES_ALIAS */
-#ifdef IEEE_8087
-#define word0(x) ((U*)&x)->L[1]
-#define word1(x) ((U*)&x)->L[0]
-#else
-#define word0(x) ((U*)&x)->L[0]
-#define word1(x) ((U*)&x)->L[1]
-#endif
-#define dval(x) ((U*)&x)->d
-#endif /* YES_ALIAS */
+#define dval(x) (x)->d
/* The following definition of Storeinc is appropriate for MIPS processors.
* An alternative that might be better on some machines is
if (__isthreaded) _SPINUNLOCK(&__gdtoa_locks[n]); \
} while(0)
-#define Kmax 15
+#define Kmax 9
struct
Bigint {
extern double strtod_l ANSI((const char *s00, char **se, locale_t));
extern Bigint *sum ANSI((Bigint*, Bigint*));
extern int trailz ANSI((Bigint*));
- extern double ulp ANSI((double));
+ extern double ulp ANSI((U*));
#ifdef __cplusplus
}
* (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
*/
#ifdef IEEE_Arith
+#ifndef NO_INFNAN_CHECK
+#undef INFNAN_CHECK
+#define INFNAN_CHECK
+#endif
#ifdef IEEE_MC68k
#define _0 0
#define _1 1
#define SI 0
#endif
+/*
+ * For very large strings, strtod and family might exhaust memory in tight
+ * memory conditions (especially in 32-bits). Such large strings could also
+ * tie up a CPU for minutes at a time. Either can be considered a denial-of-
+ * service vunerability.
+ *
+ * To fix, we limit the string size to the maximum we need to calculate the
+ * rounding point correctly. The longest string corresponding to the exact
+ * value of a floating point number occuring at 1.f...f p^-n, where n is
+ * the (absolute value of the) smallest exponent for a normalize number.
+ *
+ * To calculate this number of decimal digits, we use the formula:
+ *
+ * (n + m) - int(n * log10(2)) + 3
+ *
+ * where m is the number of bits in the f...f fraction. This is the number
+ * of decimal digits for the least significant bit minus the number of leading
+ * zeros for the most significant bit (the '1'), plus a few to compensate for
+ * an extra digits due to the full 1.f...f value, an extra digit for the
+ * mid-way point for rounding and an extra guard digit.
+ *
+ * Using the approximation log10(2) ~ 1233 / (2^12), converting to the fpi.emin
+ * and fpi.nbits values, we get:
+ *
+ * -fpi.emin -((1233 * (-fpi.nbits - fpi.emin)) >> 12) + 3
+ *
+ * Finally, we add an extra digit, either '1' or '0', to represent whether
+ * to-be-truncated digits contain a non-zero digit, or are all zeros,
+ * respectively.
+ *
+ * The truncated string is allocated on the heap, so code using
+ * TRUNCATE_DIGITS() will need to free that space when no longer needed.
+ * Pass a char * as the second argument, initialized to NULL; if its value
+ * becomes non-NULL, memory was allocated.
+ */
+#define LOG2NUM 1233
+#define LOG2DENOMSHIFT 12
+#define TRUNCATEDIGITS(_nbits, _emin) (-(_emin) - ((LOG2NUM * (-(_nbits) - (_emin))) >> LOG2DENOMSHIFT) + 3)
+
+#define TRUNCATE_DIGITS(_s0, _temp, _nd, _nd0, _nf, _nbits, _emin, _dplen) \
+{ \
+ int _maxdigits = TRUNCATEDIGITS((_nbits), (_emin)); \
+ if ((_nd) > _maxdigits && \
+ ((_temp) = MALLOC(_maxdigits + (_dplen) + 2)) != NULL) { \
+ char *_tp = (_temp) + _maxdigits; \
+ if ((_nd0) >= _maxdigits) { \
+ memcpy((_temp), (_s0), _maxdigits); \
+ if ((_nd) > (_nd0)) *_tp++ = '1'; \
+ else { \
+ const char *_q = (_s0) + _maxdigits; \
+ int _n = (_nd0) - _maxdigits; \
+ for(; _n > 0 && *_q == '0'; _n--, _q++) {} \
+ *_tp++ = _n > 0 ? '1' : '0'; \
+ } \
+ (_nf) = -((_nd0) - (_maxdigits + 1)); \
+ (_nd0) = _maxdigits + 1; \
+ } \
+ else if ((_nd0) == 0) { \
+ memcpy((_temp), (_s0), _maxdigits); \
+ *_tp++ = '1'; \
+ (_nf) -= ((_nd) - (_maxdigits + 1)); \
+ } \
+ else { \
+ memcpy((_temp), (_s0), _maxdigits + (_dplen)); \
+ _tp += (_dplen); \
+ *_tp++ = '1'; \
+ (_nf) = (_maxdigits + 1) - (_nd0); \
+ } \
+ *_tp = 0; \
+ (_nd) = _maxdigits + 1; \
+ (_s0) = (_temp); \
+ } \
+ }
+
#endif /* GDTOAIMP_H_INCLUDED */
---- _rand48.c.orig 2003-05-20 15:21:01.000000000 -0700
-+++ _rand48.c 2005-11-03 13:52:27.000000000 -0800
-@@ -16,34 +16,6 @@
+--- _rand48.c.orig 2009-11-07 14:51:37.000000000 -0800
++++ _rand48.c 2009-11-07 14:51:38.000000000 -0800
+@@ -16,34 +16,6 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/_ra
#include "rand48.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)alarm.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/alarm.3,v 1.16 2002/12/18 13:33:02 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/alarm.3,v 1.17 2007/01/09 00:27:52 imp Exp $
.\"
.Dd April 19, 1994
.Dt ALARM 3
---- _SB/Libc/gen/FreeBSD/alarm.3 2003-05-20 15:21:01.000000000 -0700
-+++ _SB/Libc/gen/FreeBSD/alarm.3.edit 2006-06-28 16:55:50.000000000 -0700
-@@ -42,8 +42,8 @@
+--- alarm.3.orig 2009-11-07 14:51:37.000000000 -0800
++++ alarm.3 2009-11-07 14:51:40.000000000 -0800
+@@ -38,8 +38,8 @@
.Lb libc
.Sh SYNOPSIS
.In unistd.h
* 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.
static char sccsid[] = "@(#)alarm.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/alarm.c,v 1.2 2002/02/01 01:08:47 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/alarm.c,v 1.3 2007/01/09 00:27:53 imp Exp $");
/*
* Backwards compatible alarm.
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" Manual page, using -mandoc macros
-.\" $FreeBSD: src/lib/libc/gen/arc4random.3,v 1.16 2003/07/31 06:18:24 das Exp $
+.\" $FreeBSD: src/lib/libc/gen/arc4random.3,v 1.18 2008/07/22 11:33:49 ache Exp $
.\"
.Dd April 15, 1997
.Dt ARC4RANDOM 3
.Os
.Sh NAME
.Nm arc4random ,
+.Nm arc4random_buf ,
+.Nm arc4random_uniform ,
.Nm arc4random_stir ,
.Nm arc4random_addrandom
.Nd arc4 random number generator
.Ft u_int32_t
.Fn arc4random "void"
.Ft void
+.Fn arc4random_buf "void *buf" "size_t nbytes"
+.Ft u_int32_t
+.Fn arc4random_uniform "u_int32_t upper_bound"
+.Ft void
.Fn arc4random_stir "void"
.Ft void
.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
and
.Xr random 3 .
.Pp
+.Fn arc4random_buf
+function fills the region
+.Fa buf
+of length
+.Fa nbytes
+with ARC4-derived random data.
+.Pp
+.Fn arc4random_uniform
+will return a uniformly distributed random number less than
+.Fa upper_bound .
+.Fn arc4random_uniform
+is recommended over constructions like
+.Dq Li arc4random() % upper_bound
+as it avoids "modulo bias" when the upper bound is not a power of two.
+.Pp
The
.Fn arc4random_stir
function reads data from
There is no need to call
.Fn arc4random_stir
before using
-.Fn arc4random ,
-since
.Fn arc4random
-automatically initializes itself.
+functions family, since
+they automatically initialize themselves.
.Sh EXAMPLES
The following produces a drop-in replacement for the traditional
.Fn rand
/*
- * Arc4 random number generator for OpenBSD.
- * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * Modification and redistribution in source and binary forms is
- * permitted provided that due credit is given to the author and the
- * OpenBSD project (for instance by leaving this copyright notice
- * intact).
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
+ * Arc4 random number generator for OpenBSD.
+ *
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/arc4random.c,v 1.10 2004/03/24 14:44:57 green Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/arc4random.c,v 1.25 2008/09/09 09:46:36 ache Exp $");
#include "namespace.h"
#include <sys/types.h>
u_int8_t s[256];
};
-static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+static int lock = 0;
+extern void spin_lock(int*);
+extern void spin_unlock(int*);
-#define RANDOMDEV "/dev/urandom"
+#define RANDOMDEV "/dev/random"
+#define KEYSIZE 128
#define THREAD_LOCK() \
do { \
if (__isthreaded) \
- _pthread_mutex_lock(&arc4random_mtx); \
+ spin_lock(&lock); \
} while (0)
#define THREAD_UNLOCK() \
do { \
if (__isthreaded) \
- _pthread_mutex_unlock(&arc4random_mtx); \
+ spin_unlock(&lock); \
} while (0)
-static struct arc4_stream rs;
+static struct arc4_stream rs = {
+ .i = 0,
+ .j = 0,
+ .s = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+ }
+};
static int rs_initialized;
static int rs_stired;
+static int arc4_count;
-static inline u_int8_t arc4_getbyte(struct arc4_stream *);
-static void arc4_stir(struct arc4_stream *);
+static inline u_int8_t arc4_getbyte(void);
+static void arc4_stir(void);
-static inline void
-arc4_init(as)
- struct arc4_stream *as;
-{
- int n;
-
- for (n = 0; n < 256; n++)
- as->s[n] = n;
- as->i = 0;
- as->j = 0;
-}
+static struct {
+ struct timeval tv;
+ pid_t pid;
+ u_int8_t rnd[KEYSIZE];
+} rdat;
+static volatile int rs_data_available = 0;
static inline void
-arc4_addrandom(as, dat, datlen)
- struct arc4_stream *as;
- u_char *dat;
- int datlen;
+arc4_addrandom(u_char *dat, int datlen)
{
int n;
u_int8_t si;
- as->i--;
+ rs.i--;
for (n = 0; n < 256; n++) {
- as->i = (as->i + 1);
- si = as->s[as->i];
- as->j = (as->j + si + dat[n % datlen]);
- as->s[as->i] = as->s[as->j];
- as->s[as->j] = si;
+ rs.i = (rs.i + 1);
+ si = rs.s[rs.i];
+ rs.j = (rs.j + si + dat[n % datlen]);
+ rs.s[rs.i] = rs.s[rs.j];
+ rs.s[rs.j] = si;
}
+ rs.j = rs.i;
}
static void
-arc4_stir(as)
- struct arc4_stream *as;
+arc4_fetch(void)
{
- int fd, n;
- struct {
- struct timeval tv;
- pid_t pid;
- u_int8_t rnd[128 - sizeof(struct timeval) - sizeof(pid_t)];
- } rdat;
-
- gettimeofday(&rdat.tv, NULL);
- rdat.pid = getpid();
+ int done, fd;
fd = _open(RANDOMDEV, O_RDONLY, 0);
+ done = 0;
if (fd >= 0) {
- (void) _read(fd, rdat.rnd, sizeof(rdat.rnd));
- _close(fd);
+ if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
+ done = 1;
+ (void)_close(fd);
}
- /* fd < 0? Ah, what the heck. We'll just take whatever was on the
- * stack... */
+ if (!done) {
+ (void)gettimeofday(&rdat.tv, NULL);
+ rdat.pid = getpid();
+ /* We'll just take whatever was on the stack too... */
+ }
+}
- arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
+static void
+arc4_stir(void)
+{
+ int n;
+ /*
+ * If we don't have data, we need some now before we can integrate
+ * it into the static buffers
+ */
+ if (!rs_data_available)
+ {
+ arc4_fetch();
+ }
+ rs_data_available = 0;
+ __sync_synchronize();
+
+ arc4_addrandom((u_char *)&rdat, KEYSIZE);
/*
* Throw away the first N bytes of output, as suggested in the
* by Ilya Mironov.
*/
for (n = 0; n < 1024; n++)
- arc4_getbyte(as);
+ (void) arc4_getbyte();
+ arc4_count = 1600000;
+ rs_stired = 1;
}
static inline u_int8_t
-arc4_getbyte(as)
- struct arc4_stream *as;
+arc4_getbyte(void)
{
u_int8_t si, sj;
- as->i = (as->i + 1);
- si = as->s[as->i];
- as->j = (as->j + si);
- sj = as->s[as->j];
- as->s[as->i] = sj;
- as->s[as->j] = si;
+ rs.i = (rs.i + 1);
+ si = rs.s[rs.i];
+ rs.j = (rs.j + si);
+ sj = rs.s[rs.j];
+ rs.s[rs.i] = sj;
+ rs.s[rs.j] = si;
- return (as->s[(si + sj) & 0xff]);
+ return (rs.s[(si + sj) & 0xff]);
}
static inline u_int32_t
-arc4_getword(as)
- struct arc4_stream *as;
+arc4_getword(void)
{
u_int32_t val;
- val = arc4_getbyte(as) << 24;
- val |= arc4_getbyte(as) << 16;
- val |= arc4_getbyte(as) << 8;
- val |= arc4_getbyte(as);
+ val = arc4_getbyte() << 24;
+ val |= arc4_getbyte() << 16;
+ val |= arc4_getbyte() << 8;
+ val |= arc4_getbyte();
return (val);
}
-static void
-arc4_check_init(void)
+/* 7944700: force restir in child */
+__private_extern__ void
+_arc4_fork_child(void)
{
- if (!rs_initialized) {
- arc4_init(&rs);
- rs_initialized = 1;
- }
+ rs_stired = 0;
+ rs_data_available = 0;
}
-static void
+static inline int
arc4_check_stir(void)
{
- if (!rs_stired) {
- arc4_stir(&rs);
- rs_stired = 1;
+ if (!rs_stired || arc4_count <= 0) {
+ arc4_stir();
+ return 1;
}
+ return 0;
}
void
-arc4random_stir()
+arc4random_stir(void)
{
THREAD_LOCK();
- arc4_check_init();
- arc4_stir(&rs);
+ arc4_stir();
THREAD_UNLOCK();
}
void
-arc4random_addrandom(dat, datlen)
- u_char *dat;
- int datlen;
+arc4random_addrandom(u_char *dat, int datlen)
{
THREAD_LOCK();
- arc4_check_init();
arc4_check_stir();
- arc4_addrandom(&rs, dat, datlen);
+ arc4_addrandom(dat, datlen);
THREAD_UNLOCK();
}
u_int32_t
-arc4random()
+arc4random(void)
{
u_int32_t rnd;
THREAD_LOCK();
- arc4_check_init();
- arc4_check_stir();
- rnd = arc4_getword(&rs);
+
+ int did_stir = arc4_check_stir();
+ rnd = arc4_getword();
+ arc4_count -= 4;
+
THREAD_UNLOCK();
+ if (did_stir)
+ {
+ /* stirring used up our data pool, we need to read in new data outside of the lock */
+ arc4_fetch();
+ rs_data_available = 1;
+ __sync_synchronize();
+ }
return (rnd);
}
+void
+arc4random_buf(void *_buf, size_t n)
+{
+ u_char *buf = (u_char *)_buf;
+ int did_stir = 0;
+
+ THREAD_LOCK();
+
+ while (n--) {
+ if (arc4_check_stir())
+ {
+ did_stir = 1;
+ }
+ buf[n] = arc4_getbyte();
+ arc4_count--;
+ }
+
+ THREAD_UNLOCK();
+ if (did_stir)
+ {
+ /* stirring used up our data pool, we need to read in new data outside of the lock */
+ arc4_fetch();
+ rs_data_available = 1;
+ __sync_synchronize();
+ }
+}
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound). This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+u_int32_t
+arc4random_uniform(u_int32_t upper_bound)
+{
+ u_int32_t r, min;
+
+ if (upper_bound < 2)
+ return (0);
+
+#if (ULONG_MAX > 0xffffffffUL)
+ min = 0x100000000UL % upper_bound;
+#else
+ /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
+ if (upper_bound > 0x80000000)
+ min = 1 + ~upper_bound; /* 2**32 - upper_bound */
+ else {
+ /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
+ min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
+ }
+#endif
+
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = arc4random();
+ if (r >= min)
+ break;
+ }
+
+ return (r % upper_bound);
+}
+
#if 0
/*-------- Test code for i386 --------*/
#include <stdio.h>
---- arc4random.c.orig 2006-02-19 03:33:43.000000000 -0800
-+++ arc4random.c 2006-02-19 15:35:04.000000000 -0800
-@@ -117,7 +117,7 @@
- /* fd < 0? Ah, what the heck. We'll just take whatever was on the
- * stack... */
-
-- arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
-+ arc4_addrandom(as, (u_char *) &rdat, sizeof(rdat));
-
- /*
- * Throw away the first N bytes of output, as suggested in the
* 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.
static char sccsid[] = "@(#)assert.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/assert.c,v 1.7 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/assert.c,v 1.8 2007/01/09 00:27:53 imp Exp $");
#include <assert.h>
#include <stdio.h>
---- assert.c.orig 2008-09-06 16:27:37.000000000 -0700
-+++ assert.c 2008-09-07 01:35:02.000000000 -0700
-@@ -41,20 +41,39 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/ass
- #include <stdio.h>
+--- assert.c.orig 2010-09-24 10:27:46.000000000 -0700
++++ assert.c 2010-09-24 10:37:33.000000000 -0700
+@@ -34,23 +34,60 @@ static char sccsid[] = "@(#)assert.c 8.1
+ __FBSDID("$FreeBSD: src/lib/libc/gen/assert.c,v 1.8 2007/01/09 00:27:53 imp Exp $");
+
+ #include <assert.h>
+-#include <stdio.h>
#include <stdlib.h>
++#include <unistd.h>
++#include "CrashReporterClient.h"
++#include "_simple.h"
-+extern const char *__crashreporter_info__;
-+static const char badasprintf[] =
-+ "Assertion failed and asprintf also failed to create full error string";
-+
void
-__assert(func, file, line, failedexpr)
+__assert_rtn(func, file, line, failedexpr)
const char *failedexpr;
{
- if (func == NULL)
-+ char *str = NULL;
-+
-+ if (func == NULL) {
- (void)fprintf(stderr,
+- (void)fprintf(stderr,
++ if (func == (const char *)-1L) {
++ /* 8462256: special case to replace __eprintf */
++ _simple_dprintf(STDERR_FILENO,
++ "%s:%u: failed assertion `%s'\n", file, line, failedexpr);
++ if (!CRGetCrashLogMessage()) {
++ _SIMPLE_STRING s = _simple_salloc();
++ if (s) {
++ _simple_sprintf(s,
++ "%s:%u: failed assertion `%s'\n",
++ file, line, failedexpr);
++ CRSetCrashLogMessage(_simple_string(s));
++ } else
++ CRSetCrashLogMessage(failedexpr);
++ }
++ } else if (func == NULL) {
++ _simple_dprintf(STDERR_FILENO,
"Assertion failed: (%s), file %s, line %d.\n", failedexpr,
file, line);
- else
-+ if (!__crashreporter_info__) {
-+ asprintf(&str,
-+ "Assertion failed: (%s), file %s, line %d.\n",
-+ failedexpr, file, line);
-+ __crashreporter_info__ = str ? str : badasprintf;
+- (void)fprintf(stderr,
++ if (!CRGetCrashLogMessage()) {
++ _SIMPLE_STRING s = _simple_salloc();
++ if (s) {
++ _simple_sprintf(s,
++ "Assertion failed: (%s), file %s, line %d.\n",
++ failedexpr, file, line);
++ CRSetCrashLogMessage(_simple_string(s));
++ } else
++ CRSetCrashLogMessage(failedexpr);
+ }
+ } else {
- (void)fprintf(stderr,
++ _simple_dprintf(STDERR_FILENO,
"Assertion failed: (%s), function %s, file %s, line %d.\n",
failedexpr, func, file, line);
-+ if (!__crashreporter_info__) {
-+ asprintf(&str,
-+ "Assertion failed: (%s), function %s, file %s, line %d.\n",
-+ failedexpr, func, file, line);
-+ __crashreporter_info__ = str ? str : badasprintf;
++ if (!CRGetCrashLogMessage()) {
++ _SIMPLE_STRING s = _simple_salloc();
++ if (s) {
++ _simple_sprintf(s,
++ "Assertion failed: (%s), function %s, file %s, line %d.\n",
++ failedexpr, func, file, line);
++ CRSetCrashLogMessage(_simple_string(s));
++ } else
++ CRSetCrashLogMessage(failedexpr);
+ }
+ }
abort();
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)clock.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/clock.3,v 1.11 2001/11/20 13:43:58 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/clock.3,v 1.12 2007/01/09 00:27:53 imp Exp $
.\"
.Dd June 4, 1993
.Dt CLOCK 3
The
.Fn clock
function conforms to
-.St -isoC .
-However,
-.St -susv2
-requires
+.St -isoC
+and
+.St -susv3
+which requires
.Dv CLOCKS_PER_SEC
to be defined as one million.
-.Fx
-does not conform to this requirement;
-changing the value would introduce binary incompatibility
-and one million is still inadequate on modern processors.
* 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.
static char sccsid[] = "@(#)clock.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/clock.c,v 1.3 2002/03/22 21:52:05 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/clock.c,v 1.4 2007/01/09 00:27:53 imp Exp $");
#include <sys/param.h>
#include <sys/time.h>
* 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.
static char sccsid[] = "@(#)closedir.c 8.1 (Berkeley) 6/10/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/closedir.c,v 1.10 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/closedir.c,v 1.13 2007/12/03 14:33:50 des Exp $");
#include "namespace.h"
#include <sys/types.h>
int fd;
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
_seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */
fd = dirp->dd_fd;
dirp->dd_fd = -1;
free((void *)dirp->dd_buf);
_reclaim_telldir(dirp);
if (__isthreaded) {
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
- _pthread_mutex_destroy((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ _pthread_mutex_destroy(&dirp->dd_lock);
}
free((void *)dirp);
return(_close(fd));
---- closedir.c.orig 2007-01-24 14:10:41.000000000 -0800
-+++ closedir.c 2007-01-25 00:17:23.000000000 -0800
-@@ -59,7 +59,9 @@
+--- closedir.c.orig 2009-11-07 15:27:55.000000000 -0800
++++ closedir.c 2009-11-07 15:28:09.000000000 -0800
+@@ -55,7 +55,9 @@ closedir(dirp)
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
+#if !__DARWIN_UNIX03
_seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */
+#endif /* __DARWIN_UNIX03 */
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ctermid.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/ctermid.3,v 1.11 2003/09/08 19:57:14 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/ctermid.3,v 1.12 2007/01/09 00:27:53 imp Exp $
.\"
.Dd June 4, 1993
.Dt CTERMID 3
---- _SB/Libc/gen/FreeBSD/ctermid.3 2004-11-25 11:38:00.000000000 -0800
-+++ _SB/Libc/gen/FreeBSD/ctermid.3.edit 2006-06-28 16:55:50.000000000 -0700
-@@ -36,31 +36,32 @@
+--- ctermid.3.orig 2009-11-07 14:51:37.000000000 -0800
++++ ctermid.3 2009-11-07 14:51:40.000000000 -0800
+@@ -32,31 +32,32 @@
.Dt CTERMID 3
.Os
.Sh NAME
is assumed to be at least
.Dv L_ctermid
(as defined in the include
-@@ -72,9 +73,9 @@
+@@ -68,9 +69,9 @@ The
.Fn ctermid_r
function
provides the same functionality as
* 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.
static char sccsid[] = "@(#)ctermid.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/ctermid.c,v 1.3 2002/03/22 21:52:05 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/ctermid.c,v 1.4 2007/01/09 00:27:53 imp Exp $");
#include <stdio.h>
#include <paths.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)daemon.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/gen/daemon.3,v 1.14 2003/11/10 22:04:51 ghelmer Exp $
+.\" $FreeBSD: src/lib/libc/gen/daemon.3,v 1.15 2007/01/09 00:27:53 imp Exp $
.\"
.Dd June 9, 1993
.Dt DAEMON 3
---- daemon.3.orig 2007-09-11 10:52:31.000000000 -0700
-+++ daemon.3 2007-09-11 10:49:51.000000000 -0700
-@@ -49,6 +49,8 @@
+--- daemon.3.orig 2009-11-07 14:51:37.000000000 -0800
++++ daemon.3 2009-11-07 14:51:40.000000000 -0800
+@@ -45,6 +45,8 @@ The
.Fn daemon
function is for programs wishing to detach themselves from the
controlling terminal and run in the background as system daemons.
* 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.
static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/daemon.c,v 1.6 2003/11/10 22:01:42 ghelmer Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/daemon.c,v 1.8 2007/01/09 00:27:53 imp Exp $");
#include "namespace.h"
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
+#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include "un-namespace.h"
---- daemon.c.orig 2007-09-29 23:58:54.000000000 -0700
-+++ daemon.c 2007-09-30 00:46:19.000000000 -0700
-@@ -37,6 +37,10 @@
+--- daemon.c.orig 2009-11-07 15:29:09.000000000 -0800
++++ daemon.c 2009-11-07 15:30:24.000000000 -0800
+@@ -33,6 +33,10 @@ static char sccsid[] = "@(#)daemon.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/daemon.c,v 1.6 2003/11/10 22:01:42 ghelmer Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/daemon.c,v 1.8 2007/01/09 00:27:53 imp Exp $");
+#ifndef VARIANT_PRE1050
+#include <mach/mach.h>
#include "namespace.h"
#include <errno.h>
#include <fcntl.h>
-@@ -45,6 +49,33 @@
+@@ -42,6 +46,33 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/dae
#include <unistd.h>
#include "un-namespace.h"
int
daemon(nochdir, noclose)
int nochdir, noclose;
-@@ -60,7 +91,9 @@
+@@ -57,7 +88,9 @@ daemon(nochdir, noclose)
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
osa_ok = _sigaction(SIGHUP, &sa, &osa);
+.\" $OpenBSD: dirname.3,v 1.17 2007/05/31 19:19:28 jmc Exp $
.\"
.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
-.\" 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. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
.\"
-.\" THIS SOFTWARE IS PROVIDED ``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.
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $OpenBSD: dirname.3,v 1.9 2000/04/18 03:01:25 aaron Exp $
-.\" $FreeBSD: src/lib/libc/gen/dirname.3,v 1.8 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/dirname.3,v 1.10 2008/11/03 05:19:45 delphij Exp $
.\"
-.Dd August 17, 1997
+.Dd October 12, 2006
.Dt DIRNAME 3
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn dirname
-function
-is the converse of
+function is the converse of
.Xr basename 3 ;
it returns a pointer to the parent directory of the pathname pointed to by
.Fa path .
returns a pointer to the string
.Qq \&. ,
signifying the current directory.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn dirname
+function
+returns a pointer to internal storage space allocated on the first call
+that will be overwritten
+by subsequent calls.
+.Pp
+Other vendor implementations of
+.Fn dirname
+may modify the contents of the string passed to
+.Fn dirname ;
+this should be taken into account when writing code which calls this function
+if portability is desired.
.Sh RETURN VALUES
On successful completion,
.Fn dirname
The path component to be returned was larger than
.Dv MAXPATHLEN .
.El
-.Sh WARNINGS
-The
-.Fn dirname
-function
-returns a pointer to internal static storage space that will be overwritten
-by subsequent calls (each function has its own separate storage).
-.Pp
-Other vendor implementations of
-.Fn dirname
-may modify the contents of the string passed to
-.Fn dirname ;
-this should be taken into account when writing code which calls this function
-if portability is desired.
.Sh SEE ALSO
.Xr basename 1 ,
.Xr dirname 1 ,
and
.Fx 4.2 .
.Sh AUTHORS
-.An "Todd C. Miller" Aq Todd.Miller@courtesan.com
+.An "Todd C. Miller"
---- dirname.3 2004-11-25 11:38:00.000000000 -0800
-+++ dirname.3.edit 2006-07-12 11:18:01.000000000 -0700
-@@ -36,7 +36,9 @@
+--- dirname.3.orig 2009-11-07 15:32:33.000000000 -0800
++++ dirname.3 2009-11-07 15:35:29.000000000 -0800
+@@ -25,7 +25,9 @@
.Sh SYNOPSIS
.In libgen.h
.Ft char *
.Sh DESCRIPTION
The
.Fn dirname
-@@ -88,12 +90,25 @@
+@@ -58,8 +60,20 @@ Other vendor implementations of
.Fn dirname
may modify the contents of the string passed to
.Fn dirname ;
+In legacy mode,
+.Fa path
+will not be changed.
+ .Sh RETURN VALUES
+ On successful completion,
+ .Fn dirname
+@@ -82,7 +96,8 @@ The path component to be returned was la
.Sh SEE ALSO
.Xr basename 1 ,
.Xr dirname 1 ,
+/* $OpenBSD: dirname.c,v 1.13 2005/08/08 08:05:33 espie Exp $ */
+
/*
- * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
+ * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED ``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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if 0
-#ifndef lint
-static char rcsid[] = "$OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $";
-#endif /* not lint */
-#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/dirname.c,v 1.7 2002/12/30 01:41:14 marcel Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/dirname.c,v 1.8 2008/11/03 05:19:45 delphij Exp $");
#include <errno.h>
#include <libgen.h>
#include <sys/param.h>
char *
-dirname(path)
- const char *path;
+dirname(const char *path)
{
- static char *bname = NULL;
+ static char *dname = NULL;
+ size_t len;
const char *endp;
- if (bname == NULL) {
- bname = (char *)malloc(MAXPATHLEN);
- if (bname == NULL)
+ if (dname == NULL) {
+ dname = (char *)malloc(MAXPATHLEN);
+ if (dname == NULL)
return(NULL);
}
/* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') {
- (void)strcpy(bname, ".");
- return(bname);
+ dname[0] = '.';
+ dname[1] = '\0';
+ return (dname);
}
- /* Strip trailing slashes */
+ /* Strip any trailing slashes */
endp = path + strlen(path) - 1;
while (endp > path && *endp == '/')
endp--;
/* Either the dir is "/" or there are no slashes */
if (endp == path) {
- (void)strcpy(bname, *endp == '/' ? "/" : ".");
- return(bname);
+ dname[0] = *endp == '/' ? '/' : '.';
+ dname[1] = '\0';
+ return (dname);
} else {
+ /* Move forward past the separating slashes */
do {
endp--;
} while (endp > path && *endp == '/');
}
- if (endp - path + 2 > MAXPATHLEN) {
+ len = endp - path + 1;
+ if (len >= MAXPATHLEN) {
errno = ENAMETOOLONG;
- return(NULL);
+ return (NULL);
}
- (void)strncpy(bname, path, endp - path + 1);
- bname[endp - path + 1] = '\0';
- return(bname);
+ memcpy(dname, path, len);
+ dname[len] = '\0';
+ return (dname);
}
-Index: dirname.c
-===================================================================
-RCS file: /cvs/root/Libc/gen/FreeBSD/dirname.c,v
-retrieving revision 1.2
-diff -u -d -b -w -p -u -r1.2 dirname.c
---- dirname.c 2003/05/20 22:21:01 1.2
-+++ dirname.c 2004/12/10 18:48:49
-@@ -39,6 +39,10 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/dir
+--- dirname.c.orig 2009-11-07 14:51:37.000000000 -0800
++++ dirname.c 2009-11-07 14:51:40.000000000 -0800
+@@ -25,6 +25,10 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/dir
#include <string.h>
#include <sys/param.h>
+#endif
+
char *
- dirname(path)
- const char *path;
+ dirname(const char *path)
+ {
---- drand48.c.orig 2003-05-20 15:21:01.000000000 -0700
-+++ drand48.c 2005-11-03 13:20:19.000000000 -0800
-@@ -16,10 +16,10 @@
+--- drand48.c.orig 2009-11-07 14:51:37.000000000 -0800
++++ drand48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -16,10 +16,10 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/dra
#include "rand48.h"
---- erand48.c.orig 2003-05-20 15:21:01.000000000 -0700
-+++ erand48.c 2005-11-03 12:30:30.000000000 -0800
-@@ -19,8 +19,8 @@
+--- erand48.c.orig 2009-11-07 14:51:37.000000000 -0800
++++ erand48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -19,8 +19,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/era
double
erand48(unsigned short xseed[3])
{
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)err.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/gen/err.3,v 1.20 2004/10/04 14:04:37 jkoshy Exp $
+.\" $FreeBSD: src/lib/libc/gen/err.3,v 1.24 2008/10/31 15:14:40 rwatson Exp $
.\"
.Dd March 6, 1999
.Dt ERR 3
If the
.Fa fmt
argument is not NULL, the
-.Xr printf 3
+.Xr printf 3 Ns
-like formatted error message is output.
The output is terminated by a newline character.
.Pp
.Fn vwarnc
functions append an error message obtained from
.Xr strerror 3
-based on a code or the global variable
+based on a supplied error code value or the global variable
.Va errno ,
preceded by another colon and space unless the
.Fa fmt
Display the current errno information string and exit:
.Bd -literal -offset indent
if ((p = malloc(size)) == NULL)
- err(1, NULL);
+ err(EX_OSERR, NULL);
if ((fd = open(file_name, O_RDONLY, 0)) == -1)
- err(1, "%s", file_name);
+ err(EX_NOINPUT, "%s", file_name);
.Ed
.Pp
Display an error message and exit:
.Bd -literal -offset indent
if (tm.tm_hour < START_TIME)
- errx(1, "too early, wait until %s", start_time_string);
+ errx(EX_DATAERR, "too early, wait until %s",
+ start_time_string);
.Ed
.Pp
Warn of an error:
warnx("%s: %s: trying the block device",
raw_device, strerror(errno));
if ((fd = open(block_device, O_RDONLY, 0)) == -1)
- err(1, "%s", block_device);
+ err(EX_OSFILE, "%s", block_device);
.Ed
.Pp
Warn of an error without using the global variable
---- err.3.orig 2009-05-12 11:21:55.000000000 -0700
-+++ err.3 2009-05-20 16:48:17.000000000 -0700
-@@ -32,7 +32,7 @@
+--- err.3.orig 2009-11-07 14:51:37.000000000 -0800
++++ err.3 2009-11-07 14:51:40.000000000 -0800
+@@ -28,7 +28,7 @@
.\" From: @(#)err.3 8.1 (Berkeley) 6/9/93
- .\" $FreeBSD: src/lib/libc/gen/err.3,v 1.20 2004/10/04 14:04:37 jkoshy Exp $
+ .\" $FreeBSD: src/lib/libc/gen/err.3,v 1.24 2008/10/31 15:14:40 rwatson Exp $
.\"
-.Dd March 6, 1999
+.Dd May 20, 2008
.Dt ERR 3
.Os
.Sh NAME
-@@ -49,6 +49,9 @@
+@@ -45,6 +45,9 @@
.Nm warnx ,
.Nm vwarnx ,
.Nm err_set_exit ,
.Nm err_set_file
.Nd formatted error messages
.Sh LIBRARY
-@@ -59,6 +62,10 @@
+@@ -55,6 +58,10 @@
.Fn err "int eval" "const char *fmt" "..."
.Ft void
.Fn err_set_exit "void (*exitf)(int)"
.Ft void
.Fn err_set_file "void *vfp"
.Ft void
-@@ -169,6 +176,24 @@
+@@ -165,6 +172,24 @@ function can be used to specify a functi
to perform any necessary cleanup; passing a null function pointer for
.Va exitf
resets the hook to do nothing.
The
.Fn err_set_file
function sets the output stream used by the other functions.
-@@ -234,3 +259,8 @@
+@@ -231,3 +256,8 @@ and
.Fn warnc
functions first appeared in
.Fx 3.0 .
* 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.
static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.13 2002/03/29 22:43:41 markm Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.15 2008/04/03 20:36:44 imp Exp $");
#include "namespace.h"
#include <err.h>
}
void
-verrc(eval, code, fmt, ap)
- int eval;
- int code;
- const char *fmt;
- va_list ap;
+verrc(int eval, int code, const char *fmt, va_list ap)
{
if (err_file == 0)
err_set_file((FILE *)0);
}
void
-verrx(eval, fmt, ap)
- int eval;
- const char *fmt;
- va_list ap;
+verrx(int eval, const char *fmt, va_list ap)
{
if (err_file == 0)
err_set_file((FILE *)0);
}
void
-vwarn(fmt, ap)
- const char *fmt;
- va_list ap;
+vwarn(const char *fmt, va_list ap)
{
vwarnc(errno, fmt, ap);
}
}
void
-vwarnc(code, fmt, ap)
- int code;
- const char *fmt;
- va_list ap;
+vwarnc(int code, const char *fmt, va_list ap)
{
if (err_file == 0)
err_set_file((FILE *)0);
}
void
-vwarnx(fmt, ap)
- const char *fmt;
- va_list ap;
+vwarnx(const char *fmt, va_list ap)
{
if (err_file == 0)
err_set_file((FILE *)0);
---- err.c.orig 2009-05-12 11:21:55.000000000 -0700
-+++ err.c 2009-05-23 13:27:52.000000000 -0700
-@@ -44,12 +44,105 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/err
+--- err.c.orig 2011-02-15 16:29:48.000000000 -0800
++++ err.c 2011-02-15 18:01:51.000000000 -0800
+@@ -40,12 +40,107 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/err
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+ * (NUL isn't used)
+ */
+static unsigned char escape[256] = {
-+ /* NUL SOH STX ETX EOT ENQ ACK BEL */
-+ 0 , 255, 255, 255, 255, 255, 255, 'a',
++ /* NUL */
++ 0, /* Unused: strings can't contain nulls */
++ /* SOH STX ETX EOT ENQ ACK BEL */
++ 255, 255, 255, 255, 255, 255, 'a',
+ /* BS HT NL VT NP CR SO SI */
-+ 'b', 't', 'n', 'v', 'f', 'r', 255, 255,
++ 'b', 0, 0, 'v', 'f', 'r', 255, 255,
+ /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+ /* CAN EM SUB ESC FS GS RS US */
+ *tp++ = *fp;
+ break;
+ case 255:
-+ sprintf(tp, "\\%03o", *fp);
++ sprintf((char *)tp, "\\%03o", *fp);
+ tp += 4;
+ break;
+ default:
/*
* This is declared to take a `void *' so that the caller is not required
-@@ -60,16 +153,27 @@ void
+@@ -56,16 +151,27 @@ void
err_set_file(void *fp)
{
if (fp)
__weak_reference(_err, err);
-@@ -107,16 +211,21 @@ verrc(eval, code, fmt, ap)
- const char *fmt;
- va_list ap;
+@@ -99,16 +205,21 @@ errc(int eval, int code, const char *fmt
+ void
+ verrc(int eval, int code, const char *fmt, va_list ap)
{
- if (err_file == 0)
+ if (_e_err_file == 0)
exit(eval);
}
-@@ -135,14 +244,19 @@ verrx(eval, fmt, ap)
- const char *fmt;
- va_list ap;
+@@ -124,14 +235,19 @@ errx(int eval, const char *fmt, ...)
+ void
+ verrx(int eval, const char *fmt, va_list ap)
{
- if (err_file == 0)
+ if (_e_err_file == 0)
exit(eval);
}
-@@ -180,14 +294,14 @@ vwarnc(code, fmt, ap)
- const char *fmt;
- va_list ap;
+@@ -164,14 +280,14 @@ warnc(int code, const char *fmt, ...)
+ void
+ vwarnc(int code, const char *fmt, va_list ap)
{
- if (err_file == 0)
+ if (_e_err_file == 0)
}
void
-@@ -204,10 +318,10 @@ vwarnx(fmt, ap)
- const char *fmt;
- va_list ap;
+@@ -186,10 +302,10 @@ warnx(const char *fmt, ...)
+ void
+ vwarnx(const char *fmt, va_list ap)
{
- if (err_file == 0)
+ if (_e_err_file == 0)
+++ /dev/null
-/*-
- * Copyright (c) 2002 Peter Wemm <peter@freebsd.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/errno.c,v 1.1 2002/10/09 08:04:24 peter Exp $");
-
-int errno;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)exec.3 8.3 (Berkeley) 1/24/94
-.\" $FreeBSD: src/lib/libc/gen/exec.3,v 1.23 2003/09/10 19:24:32 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/exec.3,v 1.28 2008/06/23 05:22:06 ed Exp $
.\"
.Dd January 24, 1994
.Dt EXEC 3
search path is the path specified in the environment by
.Dq Ev PATH
variable.
-If this variable isn't specified,
+If this variable is not specified,
the default path is set according to the
.Dv _PATH_DEFPATH
definition in
according to whether at least one file with suitable execute permissions
was found.
.Pp
-If the header of a file isn't recognized (the attempted
+If the header of a file is not recognized (the attempted
.Fn execve
returned
.Er ENOEXEC ) ,
.It Pa /bin/sh
The shell.
.El
-.Sh ERRORS
-The
-.Fn execl ,
-.Fn execle ,
-.Fn execlp ,
-.Fn execvp
-and
-.Fn execvP
-functions
-may fail and set
-.Va errno
-for any of the errors specified for the library functions
-.Xr execve 2
-and
-.Xr malloc 3 .
-.Pp
-The
-.Fn exect
-and
-.Fn execv
-functions
-may fail and set
-.Va errno
-for any of the errors specified for the library function
-.Xr execve 2 .
-.Sh SEE ALSO
-.Xr sh 1 ,
-.Xr execve 2 ,
-.Xr fork 2 ,
-.Xr ktrace 2 ,
-.Xr ptrace 2 ,
-.Xr environ 7
.Sh COMPATIBILITY
Historically, the default path for the
.Fn execlp
.Er EIO .
The behaviour was changed to match the behaviour of
.Xr sh 1 .
+.Sh ERRORS
+The
+.Fn execl ,
+.Fn execle ,
+.Fn execlp ,
+.Fn execvp
+and
+.Fn execvP
+functions
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr execve 2
+and
+.Xr malloc 3 .
+.Pp
+The
+.Fn exect
+and
+.Fn execv
+functions
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr execve 2 .
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr execve 2 ,
+.Xr fork 2 ,
+.Xr ktrace 2 ,
+.Xr ptrace 2 ,
+.Xr environ 7
.Sh STANDARDS
The
.Fn execl ,
---- exec.3.orig 2006-09-18 18:04:52.000000000 -0700
-+++ exec.3 2006-09-18 18:05:37.000000000 -0700
-@@ -37,9 +37,8 @@
+--- exec.3.orig 2009-12-15 13:07:38.000000000 -0800
++++ exec.3 2009-12-15 13:09:07.000000000 -0800
+@@ -33,9 +33,8 @@
.Os
.Sh NAME
.Nm execl ,
.Nm execv ,
.Nm execvp ,
.Nm execvP
-@@ -50,25 +49,43 @@
+@@ -46,25 +45,43 @@
.In unistd.h
.Vt extern char **environ ;
.Ft int
.Sh DESCRIPTION
The
.Nm exec
-@@ -84,7 +101,7 @@
+@@ -80,7 +97,7 @@ The initial argument for these functions
is to be executed.
.Pp
The
and subsequent ellipses in the
.Fn execl ,
.Fn execlp ,
-@@ -106,7 +123,6 @@
+@@ -102,7 +119,6 @@ be terminated by a
pointer.
.Pp
The
.Fn execv ,
.Fn execvp ,
and
-@@ -123,10 +139,8 @@
+@@ -119,10 +135,8 @@ pointer.
.Pp
The
.Fn execle
.Dv NULL
pointer that terminates the list of arguments in the argument list
or the pointer to the argv array with an additional argument.
-@@ -203,11 +217,6 @@
+@@ -199,11 +213,6 @@ returned
these functions will execute the shell with the path of
the file as its first argument.
(If this attempt fails, no further searching is done.)
.Sh RETURN VALUES
If any of the
.Fn exec
-@@ -225,7 +234,7 @@
+@@ -277,7 +286,7 @@ The
.Fn execl ,
.Fn execle ,
.Fn execlp ,
and
.Fn execvP
functions
-@@ -237,11 +246,8 @@
+@@ -289,11 +298,8 @@ and
.Xr malloc 3 .
.Pp
The
.Va errno
for any of the errors specified for the library function
.Xr execve 2 .
-@@ -249,7 +255,6 @@
+@@ -301,7 +307,6 @@ for any of the errors specified for the
.Xr sh 1 ,
.Xr execve 2 ,
.Xr fork 2 ,
-.Xr ktrace 2 ,
.Xr ptrace 2 ,
.Xr environ 7
- .Sh COMPATIBILITY
-@@ -272,11 +277,11 @@
- .Tn POSIX
- standard.
- .Pp
--Traditionally, the functions
-+Traditionally, the
- .Fn execlp
- and
- .Fn execvp
--ignored all errors except for the ones described above and
-+functions ignored all errors except for the ones described above and
- .Er ETXTBSY ,
- upon which they retried after sleeping for several seconds, and
- .Er ENOMEM
-@@ -313,7 +318,7 @@
+ .Sh STANDARDS
+@@ -309,7 +314,7 @@ The
.Fn execl ,
.Fn execv ,
.Fn execle ,
* 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.
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/exec.c,v 1.22 2003/07/01 12:30:03 bde Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/exec.c,v 1.27 2009/12/05 18:55:16 ed Exp $");
#include "namespace.h"
#include <sys/param.h>
#include <stdarg.h>
#include "un-namespace.h"
+#include "libc_private.h"
extern char **environ;
execl(const char *name, const char *arg, ...)
{
va_list ap;
- char **argv;
+ const char **argv;
int n;
va_start(ap, arg);
}
va_start(ap, arg);
n = 1;
- argv[0] = (char *)arg;
+ argv[0] = arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
va_end(ap);
- return (_execve(name, argv, environ));
+ return (_execve(name, __DECONST(char **, argv), environ));
}
int
execle(const char *name, const char *arg, ...)
{
va_list ap;
- char **argv, **envp;
+ const char **argv;
+ char **envp;
int n;
va_start(ap, arg);
}
va_start(ap, arg);
n = 1;
- argv[0] = (char *)arg;
+ argv[0] = arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
envp = va_arg(ap, char **);
va_end(ap);
- return (_execve(name, argv, envp));
+ return (_execve(name, __DECONST(char **, argv), envp));
}
int
execlp(const char *name, const char *arg, ...)
{
va_list ap;
- char **argv;
+ const char **argv;
int n;
va_start(ap, arg);
}
va_start(ap, arg);
n = 1;
- argv[0] = (char *)arg;
+ argv[0] = arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
va_end(ap);
- return (execvp(name, argv));
+ return (execvp(name, __DECONST(char **, argv)));
}
int
int
execvp(const char *name, char * const *argv)
{
- const char *path;
-
- /* Get the path we're searching. */
- if ((path = getenv("PATH")) == NULL)
- path = _PATH_DEFPATH;
-
- return (execvP(name, path, argv));
+ return (_execvpe(name, argv, environ));
}
-int
-execvP(name, path, argv)
- const char *name;
- const char *path;
- char * const *argv;
+static int
+execvPe(const char *name, const char *path, char * const *argv,
+ char * const *envp)
{
- char **memp;
- int cnt, lp, ln;
- char *p;
+ const char **memp;
+ size_t cnt, lp, ln;
int eacces, save_errno;
- char *bp, *cur, buf[MAXPATHLEN];
+ char *cur, buf[MAXPATHLEN];
+ const char *p, *bp;
struct stat sb;
eacces = 0;
/* If it's an absolute or relative path name, it's easy. */
if (index(name, '/')) {
- bp = (char *)name;
+ bp = name;
cur = NULL;
goto retry;
}
bcopy(name, buf + lp + 1, ln);
buf[lp + ln + 1] = '\0';
-retry: (void)_execve(bp, argv, environ);
+retry: (void)_execve(bp, argv, envp);
switch (errno) {
case E2BIG:
goto done;
memp[0] = "sh";
memp[1] = bp;
bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
- (void)_execve(_PATH_BSHELL, memp, environ);
+ (void)_execve(_PATH_BSHELL,
+ __DECONST(char **, memp), envp);
goto done;
case ENOMEM:
goto done;
done:
return (-1);
}
+
+int
+execvP(const char *name, const char *path, char * const argv[])
+{
+ return execvPe(name, path, argv, environ);
+}
+
+int
+_execvpe(const char *name, char * const argv[], char * const envp[])
+{
+ const char *path;
+
+ /* Get the path we're searching. */
+ if ((path = getenv("PATH")) == NULL)
+ path = _PATH_DEFPATH;
+
+ return (execvPe(name, path, argv, envp));
+}
---- exec.c.orig 2004-11-24 00:12:00.000000000 -0800
-+++ exec.c 2004-11-24 15:46:54.000000000 -0800
-@@ -51,7 +51,8 @@
- #include <stdarg.h>
+--- exec.c.orig 2010-07-06 16:02:22.000000000 -0700
++++ exec.c 2010-07-06 16:31:46.000000000 -0700
+@@ -48,7 +48,11 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/exe
#include "un-namespace.h"
+ #include "libc_private.h"
-extern char **environ;
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
++
++int
++_execvpe(const char *name, char * const argv[], char * const envp[]);
int
execl(const char *name, const char *arg, ...)
-@@ -268,8 +269,9 @@
+@@ -259,8 +263,9 @@ retry: (void)_execve(bp, argv, envp);
}
if (eacces)
errno = EACCES;
done:
return (-1);
}
+@@ -271,7 +276,7 @@ execvP(const char *name, const char *pat
+ return execvPe(name, path, argv, environ);
+ }
+
+-int
++__private_extern__ int
+ _execvpe(const char *name, char * const argv[], char * const envp[])
+ {
+ const char *path;
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/gen/fmtcheck.3,v 1.9 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/fmtcheck.3,v 1.10 2008/08/02 06:02:42 das Exp $
.Dd October 16, 2002
.Os
.Dt FMTCHECK 3
.Sh BUGS
The
.Fn fmtcheck
-function does not understand all of the conversions that
-.Xr printf 3
-does.
+function does not recognize positional parameters.
+/* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */
+
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
* 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
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* $NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/fmtcheck.c,v 1.7 2004/05/02 10:55:05 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/fmtcheck.c,v 1.10 2009/06/23 23:52:12 delphij Exp $");
#include <stdio.h>
#include <string.h>
FMTCHECK_START,
FMTCHECK_SHORT,
FMTCHECK_INT,
+ FMTCHECK_WINTT,
FMTCHECK_LONG,
FMTCHECK_QUAD,
+ FMTCHECK_INTMAXT,
FMTCHECK_PTRDIFFT,
FMTCHECK_SIZET,
+ FMTCHECK_CHARPOINTER,
FMTCHECK_SHORTPOINTER,
FMTCHECK_INTPOINTER,
FMTCHECK_LONGPOINTER,
FMTCHECK_QUADPOINTER,
+ FMTCHECK_INTMAXTPOINTER,
FMTCHECK_PTRDIFFTPOINTER,
FMTCHECK_SIZETPOINTER,
#ifndef NO_FLOATING_POINT
FMTCHECK_LONGDOUBLE,
#endif
FMTCHECK_STRING,
+ FMTCHECK_WSTRING,
FMTCHECK_WIDTH,
FMTCHECK_PRECISION,
FMTCHECK_DONE,
};
typedef enum __e_fmtcheck_types EFT;
+enum e_modifier {
+ MOD_NONE,
+ MOD_CHAR,
+ MOD_SHORT,
+ MOD_LONG,
+ MOD_QUAD,
+ MOD_INTMAXT,
+ MOD_LONGDOUBLE,
+ MOD_PTRDIFFT,
+ MOD_SIZET,
+};
+
#define RETURN(pf,f,r) do { \
*(pf) = (f); \
return r; \
static EFT
get_next_format_from_precision(const char **pf)
{
- int sh, lg, quad, longdouble, ptrdifft, sizet;
+ enum e_modifier modifier;
const char *f;
- sh = lg = quad = longdouble = ptrdifft = sizet = 0;
-
f = *pf;
switch (*f) {
case 'h':
f++;
- sh = 1;
+ if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
+ if (*f == 'h') {
+ f++;
+ modifier = MOD_CHAR;
+ } else {
+ modifier = MOD_SHORT;
+ }
+ break;
+ case 'j':
+ f++;
+ modifier = MOD_INTMAXT;
break;
case 'l':
f++;
if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
if (*f == 'l') {
f++;
- quad = 1;
+ modifier = MOD_QUAD;
} else {
- lg = 1;
+ modifier = MOD_LONG;
}
break;
case 'q':
f++;
- quad = 1;
+ modifier = MOD_QUAD;
break;
case 't':
f++;
- ptrdifft = 1;
+ modifier = MOD_PTRDIFFT;
break;
case 'z':
f++;
- sizet = 1;
+ modifier = MOD_SIZET;
break;
case 'L':
f++;
- longdouble = 1;
+ modifier = MOD_LONGDOUBLE;
break;
default:
+ modifier = MOD_NONE;
break;
}
if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
if (strchr("diouxX", *f)) {
- if (longdouble)
- RETURN(pf,f,FMTCHECK_UNKNOWN);
- if (lg)
+ switch (modifier) {
+ case MOD_LONG:
RETURN(pf,f,FMTCHECK_LONG);
- if (quad)
+ case MOD_QUAD:
RETURN(pf,f,FMTCHECK_QUAD);
- if (ptrdifft)
+ case MOD_INTMAXT:
+ RETURN(pf,f,FMTCHECK_INTMAXT);
+ case MOD_PTRDIFFT:
RETURN(pf,f,FMTCHECK_PTRDIFFT);
- if (sizet)
+ case MOD_SIZET:
RETURN(pf,f,FMTCHECK_SIZET);
- RETURN(pf,f,FMTCHECK_INT);
+ case MOD_CHAR:
+ case MOD_SHORT:
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_INT);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
}
if (*f == 'n') {
- if (longdouble)
- RETURN(pf,f,FMTCHECK_UNKNOWN);
- if (sh)
+ switch (modifier) {
+ case MOD_CHAR:
+ RETURN(pf,f,FMTCHECK_CHARPOINTER);
+ case MOD_SHORT:
RETURN(pf,f,FMTCHECK_SHORTPOINTER);
- if (lg)
+ case MOD_LONG:
RETURN(pf,f,FMTCHECK_LONGPOINTER);
- if (quad)
+ case MOD_QUAD:
RETURN(pf,f,FMTCHECK_QUADPOINTER);
- if (ptrdifft)
+ case MOD_INTMAXT:
+ RETURN(pf,f,FMTCHECK_INTMAXTPOINTER);
+ case MOD_PTRDIFFT:
RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
- if (sizet)
+ case MOD_SIZET:
RETURN(pf,f,FMTCHECK_SIZETPOINTER);
- RETURN(pf,f,FMTCHECK_INTPOINTER);
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_INTPOINTER);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
}
if (strchr("DOU", *f)) {
- if (sh + lg + quad + longdouble + ptrdifft + sizet)
+ if (modifier != MOD_NONE)
RETURN(pf,f,FMTCHECK_UNKNOWN);
RETURN(pf,f,FMTCHECK_LONG);
}
#ifndef NO_FLOATING_POINT
if (strchr("aAeEfFgG", *f)) {
- if (longdouble)
+ switch (modifier) {
+ case MOD_LONGDOUBLE:
RETURN(pf,f,FMTCHECK_LONGDOUBLE);
- if (sh + lg + quad + ptrdifft + sizet)
+ case MOD_LONG:
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_DOUBLE);
+ default:
RETURN(pf,f,FMTCHECK_UNKNOWN);
- RETURN(pf,f,FMTCHECK_DOUBLE);
+ }
}
#endif
if (*f == 'c') {
- if (sh + lg + quad + longdouble + ptrdifft + sizet)
+ switch (modifier) {
+ case MOD_LONG:
+ RETURN(pf,f,FMTCHECK_WINTT);
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_INT);
+ default:
RETURN(pf,f,FMTCHECK_UNKNOWN);
- RETURN(pf,f,FMTCHECK_INT);
+ }
+ }
+ if (*f == 'C') {
+ if (modifier != MOD_NONE)
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ RETURN(pf,f,FMTCHECK_WINTT);
}
if (*f == 's') {
- if (sh + lg + quad + longdouble + ptrdifft + sizet)
+ switch (modifier) {
+ case MOD_LONG:
+ RETURN(pf,f,FMTCHECK_WSTRING);
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_STRING);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+ }
+ if (*f == 'S') {
+ if (modifier != MOD_NONE)
RETURN(pf,f,FMTCHECK_UNKNOWN);
- RETURN(pf,f,FMTCHECK_STRING);
+ RETURN(pf,f,FMTCHECK_WSTRING);
}
if (*f == 'p') {
- if (sh + lg + quad + longdouble + ptrdifft + sizet)
+ if (modifier != MOD_NONE)
RETURN(pf,f,FMTCHECK_UNKNOWN);
RETURN(pf,f,FMTCHECK_LONG);
}
}
/* Eat any of the flags */
- while (*f && (strchr("#0- +", *f)))
+ while (*f && (strchr("#'0- +", *f)))
f++;
if (*f == '*') {
/*NOTREACHED*/
}
-__const char *
+const char *
__fmtcheck(const char *f1, const char *f2)
{
const char *f1p, *f2p;
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/fmtmsg.c,v 1.5 2003/05/01 19:03:13 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/fmtmsg.c,v 1.6 2009/11/08 14:02:54 brueffer Exp $");
#include <fmtmsg.h>
#include <stdio.h>
size += strlen(sevname);
if (text != MM_NULLTXT)
size += strlen(text);
- if (text != MM_NULLACT)
+ if (act != MM_NULLACT)
size += strlen(act);
if (tag != MM_NULLTAG)
size += strlen(tag);
---- fmtmsg.c 2004-04-15 15:49:49.000000000 -0700
-+++ ../../../test/fmtmsg.c 2005-03-02 10:53:07.000000000 -0800
-@@ -31,6 +31,8 @@
+--- fmtmsg.c.orig 2009-11-07 14:51:37.000000000 -0800
++++ fmtmsg.c 2009-11-07 14:51:39.000000000 -0800
+@@ -31,6 +31,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/fmt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Default value for MSGVERB. */
#define DFLT_MSGVERB "label:severity:text:action:tag"
-@@ -55,6 +57,9 @@
+@@ -55,6 +57,9 @@ fmtmsg(long class, const char *label, in
{
FILE *fp;
char *env, *msgverb, *output;
if (class & MM_PRINT) {
if ((env = getenv("MSGVERB")) != NULL && *env != '\0' &&
-@@ -76,8 +81,12 @@
+@@ -76,8 +81,12 @@ def:
free(msgverb);
return (MM_NOTOK);
}
free(msgverb);
free(output);
}
-@@ -87,16 +96,58 @@
+@@ -87,16 +96,58 @@ def:
if (output == NULL)
return (MM_NOCON);
if (*output != '\0') {
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fnmatch.3 8.3 (Berkeley) 4/28/95
-.\" $FreeBSD: src/lib/libc/gen/fnmatch.3,v 1.18 2004/07/18 06:56:40 tjr Exp $
+.\" $FreeBSD: src/lib/libc/gen/fnmatch.3,v 1.19 2007/01/09 00:27:53 imp Exp $
.\"
.Dd July 18, 2004
.Dt FNMATCH 3
---- _SB/Libc/gen/FreeBSD/fnmatch.3 2004-11-25 11:38:00.000000000 -0800
-+++ _SB/Libc/gen/FreeBSD/fnmatch.3.edit 2006-06-28 16:55:50.000000000 -0700
-@@ -126,7 +126,7 @@
+--- fnmatch.3.orig 2011-02-17 17:09:58.000000000 -0800
++++ fnmatch.3 2011-02-18 12:10:47.000000000 -0800
+@@ -122,7 +122,18 @@
function returns zero if
.Fa string
matches the pattern specified by
-.Fa pattern ,
++.Fa pattern .
++It returns the value
++.Dv FNM_NOMATCH
++if no match is found.
++Otherwise, another non-zero value is returned on error.
++.Sh LEGACY RETURN VALUES
++The
++.Fn fnmatch
++function returns zero if
++.Fa string
++matches the pattern specified by
+.Fa pattern ;
otherwise, it returns the value
.Dv FNM_NOMATCH .
* 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.
static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.16 2004/07/29 03:13:10 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.19 2010/04/16 22:29:24 jilles Exp $");
/*
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
#define RANGE_ERROR (-1)
static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
-static int fnmatch1(const char *, const char *, int, mbstate_t, mbstate_t);
+static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
+ mbstate_t);
int
fnmatch(pattern, string, flags)
{
static const mbstate_t initial;
- return (fnmatch1(pattern, string, flags, initial, initial));
+ return (fnmatch1(pattern, string, string, flags, initial, initial));
}
static int
-fnmatch1(pattern, string, flags, patmbs, strmbs)
- const char *pattern, *string;
+fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
+ const char *pattern, *string, *stringstart;
int flags;
mbstate_t patmbs, strmbs;
{
- const char *stringstart;
char *newp;
char c;
wchar_t pc, sc;
size_t pclen, sclen;
- for (stringstart = string;;) {
+ for (;;) {
pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
if (pclen == (size_t)-1 || pclen == (size_t)-2)
return (FNM_NOMATCH);
/* General case, use recursion. */
while (sc != EOS) {
- if (!fnmatch1(pattern, string,
- flags & ~FNM_PERIOD, patmbs, strmbs))
+ if (!fnmatch1(pattern, string, stringstart,
+ flags, patmbs, strmbs))
return (0);
sclen = mbrtowc(&sc, string, MB_LEN_MAX,
&strmbs);
} else if (*pattern == '\0') {
return (RANGE_ERROR);
} else if (*pattern == '/' && (flags & FNM_PATHNAME)) {
- pattern++;
return (RANGE_NOMATCH);
} else if (*pattern == '\\' && !(flags & FNM_NOESCAPE))
pattern++;
---- fnmatch.c.orig 2004-11-25 11:38:00.000000000 -0800
-+++ fnmatch.c 2005-03-30 14:33:09.000000000 -0800
-@@ -40,6 +40,8 @@
+--- fnmatch.c.orig 2011-02-17 17:11:04.000000000 -0800
++++ fnmatch.c 2011-02-18 12:00:31.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)fnmatch.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.16 2004/07/29 03:13:10 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.19 2010/04/16 22:29:24 jilles Exp $");
+#include "xlocale_private.h"
+
/*
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
* Compares a filename or pathname to a pattern.
-@@ -66,12 +68,15 @@
+@@ -62,13 +64,16 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/fnm
#define EOS '\0'
-+#if __DARWIN_UNIX03
+#define RETURN_ERROR 2 /* neither 0 or FNM_NOMATCH */
-+#endif /* __DARWIN_UNIX03 */
#define RANGE_MATCH 1
#define RANGE_NOMATCH 0
#define RANGE_ERROR (-1)
-static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
--static int fnmatch1(const char *, const char *, int, mbstate_t, mbstate_t);
++#define RECURSION_MAX 64
++
+__private_extern__ int rangematch(const char *, wchar_t, const char *, int, char **, char **, mbstate_t *, mbstate_t *, locale_t);
-+static int fnmatch1(const char *, const char *, int, mbstate_t, mbstate_t, locale_t);
+ static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
+- mbstate_t);
++ mbstate_t, locale_t, int);
int
fnmatch(pattern, string, flags)
-@@ -80,27 +85,32 @@
+@@ -76,27 +81,38 @@ fnmatch(pattern, string, flags)
+ int flags;
{
static const mbstate_t initial;
-
-- return (fnmatch1(pattern, string, flags, initial, initial));
-+ return (fnmatch1(pattern, string, flags, initial, initial, __current_locale()));
+-
+- return (fnmatch1(pattern, string, string, flags, initial, initial));
++#if __DARWIN_UNIX03
++ return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX));
++#else /* !__DARWIN_UNIX03 */
++ return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX) != 0 ? FNM_NOMATCH : 0);
++#endif /* __DARWIN_UNIX03 */
}
static int
--fnmatch1(pattern, string, flags, patmbs, strmbs)
-+fnmatch1(pattern, string, flags, patmbs, strmbs, loc)
- const char *pattern, *string;
+-fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
++fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs, loc, recursion)
+ const char *pattern, *string, *stringstart;
int flags;
mbstate_t patmbs, strmbs;
+ locale_t loc;
++ int recursion;
{
- const char *stringstart;
- char *newp;
+ char *newp, *news;
char c;
wchar_t pc, sc;
size_t pclen, sclen;
- for (stringstart = string;;) {
++ if (recursion-- <= 0)
++ return RETURN_ERROR;
+ for (;;) {
- pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
+ pclen = mbrtowc_l(&pc, pattern, MB_LEN_MAX, &patmbs, loc);
if (pclen == (size_t)-1 || pclen == (size_t)-2)
if (sclen == (size_t)-1 || sclen == (size_t)-2) {
sc = (unsigned char)*string;
sclen = 1;
-@@ -150,10 +160,10 @@
+@@ -144,12 +160,13 @@ fnmatch1(pattern, string, stringstart, f
+ }
+
/* General case, use recursion. */
++ int ret;
while (sc != EOS) {
- if (!fnmatch1(pattern, string,
-- flags & ~FNM_PERIOD, patmbs, strmbs))
-+ flags & ~FNM_PERIOD, patmbs, strmbs, loc))
- return (0);
+- if (!fnmatch1(pattern, string, stringstart,
+- flags, patmbs, strmbs))
+- return (0);
- sclen = mbrtowc(&sc, string, MB_LEN_MAX,
- &strmbs);
++ if ((ret = fnmatch1(pattern, string, stringstart,
++ flags, patmbs, strmbs, loc, recursion)) != FNM_NOMATCH)
++ return (ret);
+ sclen = mbrtowc_l(&sc, string, MB_LEN_MAX,
+ &strmbs, loc);
if (sclen == (size_t)-1 ||
sclen == (size_t)-2) {
sc = (unsigned char)*string;
-@@ -175,35 +185,45 @@
+@@ -171,35 +188,45 @@ fnmatch1(pattern, string, stringstart, f
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
;
else
return (FNM_NOMATCH);
-@@ -214,18 +234,22 @@
+@@ -210,18 +237,22 @@ fnmatch1(pattern, string, stringstart, f
/* NOTREACHED */
}
/*
* A bracket expression starting with an unquoted circumflex
-@@ -238,7 +262,7 @@
+@@ -234,7 +265,7 @@ rangematch(pattern, test, flags, newp, p
++pattern;
if (flags & FNM_CASEFOLD)
/*
* A right bracket shall lose its special meaning and represent
-@@ -248,8 +272,8 @@
+@@ -244,8 +275,8 @@ rangematch(pattern, test, flags, newp, p
ok = 0;
origpat = pattern;
for (;;) {
break;
} else if (*pattern == '\0') {
return (RANGE_ERROR);
-@@ -258,39 +282,188 @@
+@@ -253,39 +284,188 @@ rangematch(pattern, test, flags, newp, p
return (RANGE_NOMATCH);
} else if (*pattern == '\\' && !(flags & FNM_NOESCAPE))
pattern++;
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/gen/ftok.3,v 1.16 2004/07/02 23:52:10 ru Exp $
-.Dd June 24, 1994
+.\" $FreeBSD: src/lib/libc/gen/ftok.3,v 1.17 2009/07/13 12:53:43 trasz Exp $
+.Dd July 9, 2009
.Os
.Dt FTOK 3
.Sh NAME
The
.Fn ftok
function attempts to create a unique key suitable for use with the
-.Xr msgget 3 ,
+.Xr msgget 2 ,
.Xr semget 2
and
.Xr shmget 2
.Sh SEE ALSO
.Xr semget 2 ,
.Xr shmget 2 ,
-.Xr msgget 3
+.Xr msgget 2
.Sh HISTORY
The
.Fn ftok
---- ftok.3 2004-11-25 11:38:00.000000000 -0800
-+++ ftok.3.edit 2006-07-12 11:19:51.000000000 -0700
+--- ftok.3.bsdnew 2009-11-08 14:20:21.000000000 -0800
++++ ftok.3 2009-11-08 14:23:16.000000000 -0800
@@ -33,7 +33,6 @@
.Sh LIBRARY
.Lb libc
.In sys/ipc.h
.Ft key_t
.Fn ftok "const char *path" "int id"
-@@ -42,10 +41,10 @@
+@@ -41,11 +40,10 @@
+ The
.Fn ftok
function attempts to create a unique key suitable for use with the
- .Xr msgget 3 ,
+-.Xr msgget 2 ,
-.Xr semget 2
+.Xr semget 2 ,
and
.Fa path
of an existing file and a user-selectable
.Fa id .
-@@ -63,10 +62,18 @@
+@@ -63,10 +61,17 @@ The
function will return -1 if
.Fa path
does not exist or if it cannot be accessed by the calling process.
.Sh SEE ALSO
.Xr semget 2 ,
.Xr shmget 2 ,
--.Xr msgget 3
-+.Xr msgget 3 ,
+-.Xr msgget 2
+.Xr compat 5
.Sh HISTORY
The
.Fn ftok
-@@ -75,9 +82,9 @@
+@@ -75,9 +80,9 @@ that use the System V IPC routines.
.Sh AUTHORS
.An Thorsten Lockert Aq tholo@sigmasoft.com
.Sh BUGS
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getbsize.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/getbsize.3,v 1.10 2002/12/30 11:12:16 obrien Exp $
+.\" $FreeBSD: src/lib/libc/gen/getbsize.3,v 1.11 2007/01/09 00:27:53 imp Exp $
.\"
.Dd June 4, 1993
.Dt GETBSIZE 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getcap.3 8.4 (Berkeley) 5/13/94
-.\" $FreeBSD: src/lib/libc/gen/getcap.3,v 1.25 2004/07/03 22:30:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/getcap.3,v 1.30 2007/02/11 18:14:49 maxim Exp $
.\"
-.Dd May 13, 1994
+.Dd March 22, 2002
.Dt GETCAP 3
.Os
.Sh NAME
.Sh SYNOPSIS
.In stdlib.h
.Ft int
-.Fn cgetent "char **buf" "char **db_array" "char *name"
+.Fn cgetent "char **buf" "char **db_array" "const char *name"
.Ft int
-.Fn cgetset "char *ent"
+.Fn cgetset "const char *ent"
.Ft int
-.Fn cgetmatch "char *buf" "char *name"
+.Fn cgetmatch "const char *buf" "const char *name"
.Ft char *
-.Fn cgetcap "char *buf" "char *cap" "int type"
+.Fn cgetcap "char *buf" "const char *cap" "int type"
.Ft int
-.Fn cgetnum "char *buf" "char *cap" "long *num"
+.Fn cgetnum "char *buf" "const char *cap" "long *num"
.Ft int
-.Fn cgetstr "char *buf" "char *cap" "char **str"
+.Fn cgetstr "char *buf" "const char *cap" "char **str"
.Ft int
-.Fn cgetustr "char *buf" "char *cap" "char **str"
+.Fn cgetustr "char *buf" "const char *cap" "char **str"
.Ft int
.Fn cgetfirst "char **buf" "char **db_array"
.Ft int
record contains an unresolved
.Ic tc
expansion,
-\-1 if the requested record couldn't be found,
-\-2 if a system error was encountered (couldn't open/read a file, etc.) also
+\-1 if the requested record could not be found,
+\-2 if a system error was encountered (could not open/read a file, etc.) also
setting
.Va errno ,
and \-3 if a potential reference loop is detected (see
.Fa buf
is returned on success,
.Dv NULL
-if the requested capability couldn't be
+if the requested capability could not be
found.
The end of the capability value is signaled by a `:' or
.Tn ASCII
.Ft long
pointed to by
.Fa num .
-0 is returned on success, \-1 if the requested numeric capability couldn't
+0 is returned on success, \-1 if the requested numeric capability could not
be found.
.Pp
The
.Fa str .
The number of characters in the decoded string not including the trailing
.Dv NUL
-is returned on success, \-1 if the requested string capability couldn't
+is returned on success, \-1 if the requested string capability could not
be found, \-2 if a system error was encountered (storage allocation
failure).
.Pp
.Ic tc=
comments below).
Upon completion of the database 0 is returned, 1 is returned upon successful
-return of record with possibly more remaining (we haven't reached the end of
+return of record with possibly more remaining (we have not reached the end of
the database yet), 2 is returned if the record contains an unresolved
.Ic tc
expansion, \-1 is returned if a system error occurred, and \-2
.Pp
Names consist of one or more characters.
Names may contain any character
-except `:', but it's usually best to restrict them to the printable
+except `:', but it is usually best to restrict them to the printable
characters and avoid use of graphics like `#', `=', `%', `@', etc.
Types
are single characters used to separate capability names from their
The
.Fn cgetent ,
and
-.Fn cgetseq
+.Fn cgetset
functions may fail and set
.Va errno
for any of the errors specified for the library functions:
.Xr cap_mkdb 1 ,
.Xr malloc 3
.Sh BUGS
-Colons (`:') can't be used in names, types, or values.
+Colons (`:') cannot be used in names, types, or values.
.Pp
There are no checks for
.Ic tc Ns = Ns Ic name
* 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.
static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getcap.c,v 1.19 2003/01/02 10:19:43 thomas Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getcap.c,v 1.23 2009/11/25 04:45:45 wollman Exp $");
#include "namespace.h"
#include <sys/types.h>
{
DB *capdbp;
char *r_end, *rp, **db_p;
- int myfd, eof, foundit, retval, clen;
+ int myfd, eof, foundit, retval;
char *record, *cbuf;
int tc_not_resolved;
char pbuf[_POSIX_PATH_MAX];
return (retval);
}
/* save the data; close frees it */
- clen = strlen(record);
- cbuf = malloc(clen + 1);
- memcpy(cbuf, record, clen + 1);
+ cbuf = strdup(record);
if (capdbp->close(capdbp) < 0) {
free(cbuf);
return (-2);
}
- *len = clen;
+ if (cbuf == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ *len = strlen(cbuf);
*cap = cbuf;
return (retval);
} else {
cgetnext(char **bp, char **db_array)
{
size_t len;
- int done, hadreaderr, i, savederrno, status;
+ int done, hadreaderr, savederrno, status;
char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
u_int dummy;
(void)cgetclose();
return (-1);
}
- for(;;) {
+ for (;;) {
if (toprec && !gottoprec) {
gottoprec = 1;
line = toprec;
/*
* Line points to a name line.
*/
- i = 0;
done = 0;
np = nbuf;
for (;;) {
---- getcap.c.orig 2003-05-20 15:21:01.000000000 -0700
-+++ getcap.c 2005-02-27 15:52:46.000000000 -0800
-@@ -40,6 +40,8 @@
+--- getcap.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ getcap.c 2009-11-07 14:51:40.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)getcap.c 8.3
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/getcap.c,v 1.19 2003/01/02 10:19:43 thomas Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/getcap.c,v 1.22 2009/05/14 23:09:33 delphij Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <sys/types.h>
-@@ -70,7 +72,7 @@
+@@ -66,7 +68,7 @@ static char *toprec; /* Additional recor
static int gottoprec; /* Flag indicating retrieval of toprecord */
static int cdbget(DB *, char **, const char *);
static int nfcmp(char *, char *);
/*
-@@ -166,7 +168,7 @@
+@@ -162,7 +164,7 @@ cgetent(char **buf, char **db_array, con
{
u_int dummy;
}
/*
-@@ -189,7 +191,7 @@
+@@ -185,7 +187,7 @@ cgetent(char **buf, char **db_array, con
*/
static int
getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
{
DB *capdbp;
char *r_end, *rp, **db_p;
-@@ -428,7 +430,7 @@
+@@ -426,7 +428,7 @@ tc_exp: {
tcend = s;
iret = getent(&icap, &ilen, db_p, fd, tc, depth+1,
newicap = icap; /* Put into a register. */
newilen = ilen;
if (iret != 0) {
-@@ -652,6 +654,7 @@
+@@ -650,6 +652,7 @@ cgetnext(char **bp, char **db_array)
int done, hadreaderr, i, savederrno, status;
char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
u_int dummy;
if (dbp == NULL)
dbp = db_array;
-@@ -693,7 +696,7 @@
+@@ -691,7 +694,7 @@ cgetnext(char **bp, char **db_array)
slash = 0;
continue;
}
*line == ':' || *line == '#' || slash) {
if (line[len - 2] == '\\')
slash = 1;
-@@ -765,7 +768,7 @@
+@@ -763,7 +766,7 @@ cgetnext(char **bp, char **db_array)
* rather than the duplicate entry record. This is a
* matter of semantics that should be resolved.
*/
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getcwd.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/gen/getcwd.3,v 1.16 2003/09/08 19:57:14 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/getcwd.3,v 1.17 2007/01/09 00:27:53 imp Exp $
.\"
.Dd November 24, 1997
.Dt GETCWD 3
* 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.
static char sccsid[] = "@(#)getcwd.c 8.5 (Berkeley) 2/7/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getcwd.c,v 1.25 2003/10/29 10:45:01 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getcwd.c,v 1.29 2007/01/09 00:27:53 imp Exp $");
#include "namespace.h"
#include <sys/param.h>
}
ept = pt + size;
} else {
- if ((pt = malloc(ptsize = 1024 - 4)) == NULL)
+ if ((pt = malloc(ptsize = PATH_MAX)) == NULL)
return (NULL);
ept = pt + ptsize;
}
*bpt = '\0';
/*
- * Allocate bytes (1024 - malloc space) for the string of "../"'s.
- * Should always be enough (it's 340 levels). If it's not, allocate
+ * Allocate 1024 bytes for the string of "../"'s.
+ * Should always be enough. If it's not, allocate
* as necessary. Special case the first stat, it's ".", not "..".
*/
- if ((up = malloc(upsize = 1024 - 4)) == NULL)
+ if ((up = malloc(upsize = 1024)) == NULL)
goto err;
- eup = up + MAXPATHLEN;
+ eup = up + upsize;
bup = up;
up[0] = '.';
up[1] = '\0';
* as necessary. Max length is 3 for "../", the largest
* possible component name, plus a trailing NUL.
*/
- if (bup + 3 + MAXNAMLEN + 1 >= eup) {
+ while (bup + 3 + MAXNAMLEN + 1 >= eup) {
if ((up = reallocf(up, upsize *= 2)) == NULL)
goto err;
bup = up;
* Check for length of the current name, preceding slash,
* leading slash.
*/
- if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
+ while (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
size_t len, off;
if (!ptsize) {
---- getcwd.c.orig 2006-06-07 17:42:52.000000000 -0700
-+++ getcwd.c 2006-06-07 17:44:47.000000000 -0700
-@@ -54,12 +54,87 @@
+--- getcwd.c.bsdnew 2009-11-08 15:25:00.000000000 -0800
++++ getcwd.c 2009-11-08 15:30:17.000000000 -0800
+@@ -50,12 +50,87 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/get
(dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
{
struct dirent *dp;
DIR *dir = NULL;
-@@ -91,31 +166,25 @@
+@@ -87,33 +162,27 @@ getcwd(pt, size)
}
ept = pt + size;
} else {
-- if ((pt = malloc(ptsize = 1024 - 4)) == NULL)
+- if ((pt = malloc(ptsize = PATH_MAX)) == NULL)
+ if ((pt = malloc(ptsize = MAXPATHLEN)) == NULL)
return (NULL);
ept = pt + ptsize;
*bpt = '\0';
/*
-- * Allocate bytes (1024 - malloc space) for the string of "../"'s.
-+ * Allocate bytes MAXPATHLEN) for the string of "../"'s.
- * Should always be enough (it's 340 levels). If it's not, allocate
+- * Allocate 1024 bytes for the string of "../"'s.
++ * Allocate MAXPATHLEN bytes for the string of "../"'s.
+ * Should always be enough. If it's not, allocate
* as necessary. Special case the first stat, it's ".", not "..".
*/
-- if ((up = malloc(upsize = 1024 - 4)) == NULL)
+- if ((up = malloc(upsize = 1024)) == NULL)
+ if ((up = malloc(upsize = MAXPATHLEN)) == NULL)
goto err;
- eup = up + MAXPATHLEN;
+- eup = up + upsize;
++ eup = up + MAXPATHLEN;
bup = up;
-@@ -259,3 +328,11 @@
+ up[0] = '.';
+ up[1] = '\0';
+@@ -255,3 +324,11 @@ err:
errno = save_errno;
return (NULL);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)gethostname.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/gethostname.3,v 1.16 2004/07/03 22:30:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/gethostname.3,v 1.17 2007/01/09 00:27:54 imp Exp $
.\"
.Dd August 18, 2003
.Dt GETHOSTNAME 3
---- _SB/Libc/gen/FreeBSD/gethostname.3 2004-11-25 11:38:01.000000000 -0800
-+++ _SB/Libc/gen/FreeBSD/gethostname.3.edit 2006-06-28 16:55:50.000000000 -0700
-@@ -60,7 +60,7 @@
+--- gethostname.3.orig 2010-04-28 23:38:49.000000000 -0700
++++ gethostname.3 2010-04-28 23:47:57.000000000 -0700
+@@ -56,7 +56,7 @@ argument
specifies the size of the
.Fa name
array.
.Pp
The
.Fn sethostname
+@@ -68,8 +68,8 @@ which has length
+ This call is restricted to the super-user and
+ is normally used only when the system is bootstrapped.
+ .Pp
+-Host names are limited to
+-.Brq Dv HOST_NAME_MAX
++Host names are limited in length to
++.Brq Dv sysconf(_SC_HOST_NAME_MAX)
+ characters, not including the trailing null, currently 255.
+ .Sh RETURN VALUES
+ .Rv -std
+@@ -101,7 +101,7 @@ The
+ function conforms to
+ .St -p1003.1-2001 .
+ Callers should be aware that
+-.Brq Dv HOST_NAME_MAX
++.Brq Dv sysconf(_SC_HOST_NAME_MAX)
+ may be variable or infinite, but is guaranteed to be no less than
+ .Brq Dv _POSIX_HOST_NAME_MAX .
+ On older systems, this limit was defined in the non-standard header
* 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.
static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/gethostname.c,v 1.5 2003/08/19 23:01:46 wollman Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/gethostname.c,v 1.8 2007/01/09 00:27:54 imp Exp $");
#include <sys/param.h>
#include <sys/sysctl.h>
#include <errno.h>
+#include <unistd.h>
int
gethostname(name, namelen)
{
int mib[2];
- /* Kluge to avoid ABI breakage. */
- namelen = (int)namelen;
-
mib[0] = CTL_KERN;
mib[1] = KERN_HOSTNAME;
if (sysctl(mib, 2, name, &namelen, NULL, 0) == -1) {
---- gethostname.c.orig 2008-04-05 00:47:41.000000000 -0700
-+++ gethostname.c 2008-04-05 01:04:59.000000000 -0700
-@@ -37,8 +37,10 @@ static char sccsid[] = "@(#)gethostname.
+--- gethostname.c.orig 2009-11-07 15:38:57.000000000 -0800
++++ gethostname.c 2009-11-07 15:44:48.000000000 -0800
+@@ -33,8 +33,10 @@ static char sccsid[] = "@(#)gethostname.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/gethostname.c,v 1.5 2003/08/19 23:01:46 wollman Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/gethostname.c,v 1.8 2007/01/09 00:27:54 imp Exp $");
+#include <string.h>
#include <sys/param.h>
+#include <limits.h>
#include <errno.h>
-
-@@ -54,10 +56,22 @@ gethostname(name, namelen)
+ #include <unistd.h>
+@@ -48,10 +50,22 @@ gethostname(name, namelen)
mib[0] = CTL_KERN;
mib[1] = KERN_HOSTNAME;
* 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.
static char sccsid[] = "@(#)getlogin.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getlogin.c,v 1.9 2003/10/29 10:45:01 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getlogin.c,v 1.11 2009/12/05 19:04:21 ed Exp $");
#include <sys/param.h>
#include <errno.h>
#include <pwd.h>
-#include <utmp.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
---- getlogin.c.orig 2007-08-19 17:24:10.000000000 -0700
-+++ getlogin.c 2007-08-19 20:51:27.000000000 -0700
-@@ -40,7 +40,6 @@
- #include <sys/param.h>
- #include <errno.h>
- #include <pwd.h>
--#include <utmp.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
-@@ -53,7 +52,7 @@
+--- getlogin.c.bsdnew 2009-12-08 00:37:57.000000000 -0800
++++ getlogin.c 2009-12-08 00:44:06.000000000 -0800
+@@ -48,7 +48,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/get
#define THREAD_LOCK() if (__isthreaded) _pthread_mutex_lock(&logname_mutex)
#define THREAD_UNLOCK() if (__isthreaded) _pthread_mutex_unlock(&logname_mutex)
int _logname_valid; /* known to setlogin() */
static pthread_mutex_t logname_mutex = PTHREAD_MUTEX_INITIALIZER;
-@@ -64,7 +63,7 @@
+@@ -59,7 +59,7 @@ getlogin_basic(int *status)
static char logname[MAXLOGNAME];
if (_logname_valid == 0) {
*status = errno;
return (NULL);
}
-@@ -87,7 +86,7 @@
+@@ -82,7 +82,7 @@ getlogin(void)
}
int
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getmntinfo.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/gen/getmntinfo.3,v 1.12 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/getmntinfo.3,v 1.13 2007/01/09 00:27:54 imp Exp $
.\"
.Dd June 9, 1993
.Dt GETMNTINFO 3
---- getmntinfo.3.orig 2008-05-13 13:37:51.000000000 -0700
-+++ getmntinfo.3 2008-05-15 19:58:50.000000000 -0700
-@@ -32,26 +32,30 @@
+--- getmntinfo.3.orig 2010-06-17 09:25:28.000000000 -0700
++++ getmntinfo.3 2010-06-17 09:26:43.000000000 -0700
+@@ -28,28 +28,37 @@
.\" @(#)getmntinfo.3 8.1 (Berkeley) 6/9/93
- .\" $FreeBSD: src/lib/libc/gen/getmntinfo.3,v 1.12 2002/12/19 09:40:21 ru Exp $
+ .\" $FreeBSD: src/lib/libc/gen/getmntinfo.3,v 1.13 2007/01/09 00:27:54 imp Exp $
.\"
-.Dd June 9, 1993
-+.Dd May 15, 2008
++.Dd May 4, 2010
.Dt GETMNTINFO 3
.Os
.Sh NAME
.Nm getmntinfo
++.Nm getmntinfo64
.Nd get information about mounted file systems
-.Sh LIBRARY
-.Lb libc
.In sys/mount.h
.Ft int
.Fn getmntinfo "struct statfs **mntbufp" "int flags"
-+#ifdef UNIFDEF_LEGACY_64_APIS
+.Sh TRANSITIIONAL SYNOPSIS (NOW DEPRECATED)
+.Ft int
+.br
+.Fn getmntinfo64 "struct statfs64 **mntbufp" "int flags" ;
-+#endif /* UNIFDEF_LEGACY_64_APIS */
.Sh DESCRIPTION
The
.Fn getmntinfo
+.Ft statfs
structures describing each currently mounted file system (see
.Xr statfs 2 ) .
++As
++.Xr statfs 2
++indicates, the structure is defined differently depending on
++whether the macro _DARWIN_FEATURE_64_BIT_INODE is defined (see
++.Xr stat 2
++for more information on this macro).
.Pp
-@@ -62,6 +66,33 @@
- .Fa flags
- argument transparently to
- .Xr getfsstat 2 .
-+#ifdef UNIFDEF_LEGACY_64_APIS
-+.Pp
-+Like
-+.Xr getfsstat 2 ,
-+when the macro
-+.Dv _DARWIN_FEATURE_64_BIT_INODE
-+is defined, the
-+.Ft ino_t
-+type will be 64-bits (force 64-bit inode mode by defining the
-+.Dv _DARWIN_USE_64_BIT_INODE
-+macro before including header files).
-+This will cause the symbol variant of
-+.Fn getmntinfo ,
-+with the
-+.Fa $INODE64
-+suffixes, to be automatically linked in.
-+In addition, the
-+.Ft statfs
-+structure will be the 64-bit inode version.
-+If
-+.Dv _DARWIN_USE_64_BIT_INODE
-+is not defined, both
-+.Fn getmntinfo
-+and the
-+.Ft statfs
-+structure will refer to the 32-bit inode versions.
-+#endif /* UNIFDEF_LEGACY_64_APIS */
- .Sh RETURN VALUES
- On successful completion,
+ The
.Fn getmntinfo
-@@ -86,6 +117,24 @@
+@@ -82,9 +91,26 @@ routines
.Xr getfsstat 2
or
.Xr malloc 3 .
-+#ifdef UNIFDEF_LEGACY_64_APIS
+.Sh TRANSITIONAL DESCRIPTION (NOW DEPRECATED)
+The
+.Fn getmntinfo64
+structure used by this deprecated routine is the same as the
+.Ft statfs
+structure when 64-bit inodes are in effect.
-+#endif /* UNIFDEF_LEGACY_64_APIS */
.Sh SEE ALSO
.Xr getfsstat 2 ,
.Xr mount 2 ,
-@@ -99,15 +148,29 @@
- .Sh BUGS
- The
- .Fn getmntinfo
-+#ifdef UNIFDEF_LEGACY_64_APIS
-+and
-+.Fn getmntinfo64
-+functions write the array of structures to an internal static object
-+#else /* !UNIFDEF_LEGACY_64_APIS */
- function writes the array of structures to an internal static object
-+#endif /* UNIFDEF_LEGACY_64_APIS */
- and returns
- a pointer to that object.
- Subsequent calls to
- .Fn getmntinfo
-+#ifdef UNIFDEF_LEGACY_64_APIS
-+and
-+.Fn getmntinfo64
-+#endif /* UNIFDEF_LEGACY_64_APIS */
- will modify the same object.
- .Pp
- The memory allocated by
- .Fn getmntinfo
-+#ifdef UNIFDEF_LEGACY_64_APIS
-+and
-+.Fn getmntinfo64
-+#endif /* UNIFDEF_LEGACY_64_APIS */
- cannot be
- .Xr free 3 Ns 'd
- by the application.
++.Xr stat 2 ,
+ .Xr statfs 2 ,
+ .Xr mount 8
+ .Sh HISTORY
* 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.
static char sccsid[] = "@(#)getmntinfo.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getmntinfo.c,v 1.4 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getmntinfo.c,v 1.5 2007/01/09 00:27:54 imp Exp $");
#include <sys/param.h>
#include <sys/ucred.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getpagesize.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/getpagesize.3,v 1.11 2002/12/27 12:15:28 schweikh Exp $
+.\" $FreeBSD: src/lib/libc/gen/getpagesize.3,v 1.12 2007/01/09 00:27:54 imp Exp $
.\"
.Dd June 4, 1993
.Dt GETPAGESIZE 3
* 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.
static char sccsid[] = "@(#)getpagesize.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getpagesize.c,v 1.4 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getpagesize.c,v 1.6 2007/01/09 00:27:54 imp Exp $");
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <unistd.h>
+
/*
* This is unlikely to change over the running time of any
* program, so we cache the result to save some syscalls.
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getpass.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/getpass.3,v 1.11 2001/11/22 09:48:54 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/getpass.3,v 1.12 2007/01/09 00:27:54 imp Exp $
.\"
.Dd June 4, 1993
.Dt GETPASS 3
---- getprogname.3.orig Fri May 28 17:17:08 2004
-+++ getprogname.3 Fri May 28 17:17:39 2004
-@@ -85,8 +85,7 @@
+--- getprogname.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ getprogname.3 2009-11-07 14:51:39.000000000 -0800
+@@ -85,8 +85,7 @@ Calling
allows the aforementioned library to learn the program name without
modifications to the start-up code.
.Sh SEE ALSO
---- getprogname.c.orig Mon Apr 28 15:05:02 2003
-+++ getprogname.c Sat May 3 14:04:57 2003
-@@ -3,6 +3,8 @@
+--- getprogname.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ getprogname.c 2009-11-07 14:51:39.000000000 -0800
+@@ -3,6 +3,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/get
#include "namespace.h"
#include <stdlib.h>
* 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.
static char sccsid[] = "@(#)isatty.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/isatty.c,v 1.5 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/isatty.c,v 1.6 2007/01/09 00:27:54 imp Exp $");
#include <termios.h>
#include <unistd.h>
---- isatty.c.orig 2008-04-05 00:47:41.000000000 -0700
-+++ isatty.c 2008-04-05 01:05:40.000000000 -0700
-@@ -39,14 +39,22 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/isa
+--- isatty.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ isatty.c 2009-11-07 14:51:40.000000000 -0800
+@@ -35,14 +35,22 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/isa
#include <termios.h>
#include <unistd.h>
---- jrand48.c.orig 2003-05-20 15:21:02.000000000 -0700
-+++ jrand48.c 2005-11-03 13:31:28.000000000 -0800
-@@ -19,6 +19,7 @@
+--- jrand48.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ jrand48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -19,6 +19,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/jra
long
jrand48(unsigned short xseed[3])
{
---- lcong48.c.orig 2003-05-20 15:21:02.000000000 -0700
-+++ lcong48.c 2005-11-03 13:36:03.000000000 -0800
-@@ -16,18 +16,10 @@
+--- lcong48.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ lcong48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -16,18 +16,10 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/lco
#include "rand48.h"
-.\" $NetBSD: lockf.3,v 1.2 1998/02/05 18:47:28 perry Exp $
+.\" $NetBSD: lockf.3,v 1.10 2008/04/30 13:10:50 martin Exp $
.\"
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/gen/lockf.3,v 1.13 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/lockf.3,v 1.14 2009/03/04 01:01:26 delphij Exp $
.\"
.Dd December 19, 1997
.Dt LOCKF 3
---- lockf.3 2004-11-25 11:38:01.000000000 -0800
-+++ lockf.3.edit 2006-07-15 14:04:01.000000000 -0700
-@@ -47,7 +47,7 @@
+--- lockf.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ lockf.3 2009-11-07 14:51:40.000000000 -0800
+@@ -40,7 +40,7 @@
.Sh SYNOPSIS
.In unistd.h
.Ft int
.Sh DESCRIPTION
The
.Fn lockf
-@@ -56,10 +56,10 @@
+@@ -49,10 +49,10 @@ Calls to
.Fn lockf
from other processes which attempt to lock the locked file section will
either return an error value or block until the section becomes unlocked.
is an open file descriptor.
The file descriptor must have been opened either for write-only
.Dv ( O_WRONLY )
-@@ -214,7 +214,7 @@
+@@ -207,7 +207,7 @@ or
and the section is already locked by another process.
.It Bq Er EBADF
The argument
is not a valid open file descriptor.
.Pp
The argument
-@@ -224,7 +224,7 @@
+@@ -217,7 +217,7 @@ is
or
.Dv F_TLOCK ,
and
is not a valid file descriptor open for writing.
.It Bq Er EDEADLK
The argument
-@@ -243,25 +243,29 @@
+@@ -236,25 +236,29 @@ was interrupted by the delivery of a sig
The argument
.Fa function
is not one of
+/* $NetBSD: lockf.c,v 1.3 2008/04/28 20:22:59 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
* 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
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* $NetBSD: lockf.c,v 1.1 1997/12/20 20:23:18 kleink Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/lockf.c,v 1.8 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/lockf.c,v 1.10 2009/03/04 01:01:26 delphij Exp $");
#include "namespace.h"
#include <errno.h>
#include "un-namespace.h"
int
-lockf(filedes, function, size)
- int filedes;
- int function;
- off_t size;
+lockf(int filedes, int function, off_t size)
{
struct flock fl;
int cmd;
fl.l_type = F_WRLCK;
if (_fcntl(filedes, F_GETLK, &fl) == -1)
return (-1);
- if (fl.l_type == F_UNLCK || fl.l_pid == getpid())
+ if (fl.l_type == F_UNLCK || (fl.l_sysid == 0 && fl.l_pid == getpid()))
return (0);
errno = EAGAIN;
return (-1);
---- lockf.c.orig 2006-09-16 19:12:39.000000000 -0700
-+++ lockf.c 2006-09-16 20:35:36.000000000 -0700
-@@ -38,6 +38,13 @@
+--- lockf.c.orig 2009-11-07 15:52:44.000000000 -0800
++++ lockf.c 2009-11-07 16:04:57.000000000 -0800
+@@ -31,6 +31,13 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/lockf.c,v 1.8 2002/02/01 00:57:29 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/lockf.c,v 1.10 2009/03/04 01:01:26 delphij Exp $");
+#ifdef VARIANT_CANCELABLE
+int __fcntl(int, int, void *);
#include "namespace.h"
#include <errno.h>
#include <fcntl.h>
-@@ -53,6 +60,7 @@
- struct flock fl;
- int cmd;
-
-+
- fl.l_start = 0;
- fl.l_len = size;
- fl.l_whence = SEEK_CUR;
-@@ -72,8 +80,13 @@
+@@ -62,9 +69,14 @@ lockf(int filedes, int function, off_t s
break;
case F_TEST:
fl.l_type = F_WRLCK;
+#ifdef VARIANT_CANCELABLE
+ if (__fcntl(filedes, F_GETLK, &fl) == -1)
return (-1);
+- if (fl.l_type == F_UNLCK || (fl.l_sysid == 0 && fl.l_pid == getpid()))
+#else /* !VARIANT_CANCELABLE */
+ if (__fcntl_nocancel(filedes, F_GETLK, &fl) == -1)
+ return (-1);
+#endif /* VARIANT_CANCELABLE */
- if (fl.l_type == F_UNLCK || fl.l_pid == getpid())
++ if (fl.l_type == F_UNLCK || fl.l_pid == getpid())
return (0);
errno = EAGAIN;
-@@ -85,5 +98,10 @@
+ return (-1);
+@@ -75,5 +87,10 @@ lockf(int filedes, int function, off_t s
/* NOTREACHED */
}
- return (_fcntl(filedes, cmd, &fl));
+#ifdef VARIANT_CANCELABLE
-+ return (__fcntl(filedes, cmd, &fl));
++ return (__fcntl(filedes, cmd, &fl));
+#else /* !VARIANT_CANCELABLE */
-+ return (__fcntl_nocancel(filedes, cmd, &fl));
++ return (__fcntl_nocancel(filedes, cmd, &fl));
+#endif /* VARIANT_CANCELABLE */
}
+
---- lrand48.c.orig 2003-05-20 15:21:02.000000000 -0700
-+++ lrand48.c 2005-11-03 13:41:09.000000000 -0800
-@@ -16,11 +16,9 @@
+--- lrand48.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ lrand48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -16,11 +16,9 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/lra
#include "rand48.h"
---- makecontext.3.orig 2009-03-13 03:05:02.000000000 -0700
-+++ makecontext.3 2009-03-13 03:12:49.000000000 -0700
+--- makecontext.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ makecontext.3 2009-11-07 14:51:39.000000000 -0800
@@ -48,7 +48,7 @@
.Ft void
.Fo makecontext
.Fa "int argc" ...
.Fc
.Ft int
-@@ -64,7 +64,9 @@
+@@ -64,7 +64,9 @@ which must have previously been initiali
and had a stack allocated for it.
The context is modified so that it will continue execution by invoking
.Fn func
---- mrand48.c.orig 2003-05-20 15:21:02.000000000 -0700
-+++ mrand48.c 2005-11-03 13:42:32.000000000 -0800
-@@ -16,11 +16,9 @@
+--- mrand48.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ mrand48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -16,11 +16,9 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/mra
#include "rand48.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)nice.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/nice.3,v 1.11 2001/10/01 16:08:51 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/nice.3,v 1.12 2007/01/09 00:27:54 imp Exp $
.\"
.Dd June 4, 1993
.Dt NICE 3
* 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.
static char sccsid[] = "@(#)nice.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/nice.c,v 1.3 2002/03/22 21:52:05 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/nice.c,v 1.4 2007/01/09 00:27:54 imp Exp $");
#include <sys/types.h>
#include <sys/time.h>
-Index: nice.c
-===================================================================
-RCS file: /cvs/root/Libc/gen/FreeBSD/nice.c,v
-retrieving revision 1.2
-diff -u -d -b -w -p -r1.2 nice.c
---- nice.c 2003/05/20 22:21:02 1.2
-+++ nice.c 2005/04/06 22:28:10
-@@ -42,7 +42,9 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/nic
+--- nice.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ nice.c 2009-11-07 14:51:40.000000000 -0800
+@@ -38,7 +38,9 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/nic
#include <sys/resource.h>
#include <errno.h>
#include <unistd.h>
/*
* Backwards compatible nice.
*/
-@@ -50,11 +52,18 @@ int
+@@ -46,11 +48,18 @@ int
nice(incr)
int incr;
{
---- nrand48.c.orig 2003-05-20 15:21:02.000000000 -0700
-+++ nrand48.c 2005-11-03 13:43:51.000000000 -0800
-@@ -19,6 +19,7 @@
+--- nrand48.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ nrand48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -19,6 +19,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/nra
long
nrand48(unsigned short xseed[3])
{
-/*
+/*-
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* 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.
static char sccsid[] = "@(#)opendir.c 8.8 (Berkeley) 5/1/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/opendir.c,v 1.22 2004/08/14 17:46:10 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/opendir.c,v 1.24 2008/04/16 18:40:52 delphij Exp $");
#include "namespace.h"
#include <sys/param.h>
* Open a directory.
*/
DIR *
-opendir(name)
- const char *name;
+opendir(const char *name)
{
return (__opendir2(name, DTF_HIDEW|DTF_NODUP));
}
DIR *
-__opendir2(name, flags)
- const char *name;
- int flags;
+__opendir2(const char *name, int flags)
{
DIR *dirp;
int fd;
---- opendir.c.orig 2007-01-24 14:10:41.000000000 -0800
-+++ opendir.c 2007-01-28 01:37:51.000000000 -0800
-@@ -48,6 +48,7 @@
+--- opendir.c.orig 2009-11-08 17:01:43.000000000 -0800
++++ opendir.c 2009-11-08 17:01:51.000000000 -0800
+@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/ope
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "un-namespace.h"
#include "telldir.h"
-@@ -72,27 +73,15 @@
+@@ -65,27 +66,15 @@ __opendir2(const char *name, int flags)
int incr;
int saved_errno;
int unionstack;
if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
(dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL)
goto fail;
-@@ -154,7 +143,11 @@
+@@ -147,7 +136,11 @@ __opendir2(const char *name, int flags)
ddptr = buf + (len - space);
}
if (n > 0) {
ddptr += n;
space -= n;
-@@ -262,14 +255,18 @@
+@@ -255,14 +248,18 @@ __opendir2(const char *name, int flags)
dirp->dd_buf = malloc(dirp->dd_len);
if (dirp->dd_buf == NULL)
goto fail;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)pause.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/pause.3,v 1.8 2001/10/01 16:08:51 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/pause.3,v 1.9 2007/01/09 00:27:54 imp Exp $
.\"
.Dd June 4, 1993
.Dt PAUSE 3
* 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.
static char sccsid[] = "@(#)pause.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/pause.c,v 1.6 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/pause.c,v 1.8 2009/12/05 19:31:38 ed Exp $");
#include <signal.h>
#include <unistd.h>
* Backwards compatible pause.
*/
int
-__pause()
+__pause(void)
{
return sigpause(sigblock(0L));
}
---- pause.c.orig 2006-09-17 12:11:15.000000000 -0700
-+++ pause.c 2006-09-24 16:38:00.000000000 -0700
-@@ -34,6 +34,13 @@
+--- pause.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ pause.c 2009-11-07 14:51:40.000000000 -0800
+@@ -30,6 +30,13 @@
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)pause.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
+#endif /* VARIANT_CANCELABLE */
+
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/pause.c,v 1.6 2002/02/01 00:57:29 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/pause.c,v 1.7 2007/01/09 00:27:54 imp Exp $");
-@@ -46,7 +53,10 @@
+@@ -42,7 +49,10 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pau
int
__pause()
{
* 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.
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/popen.c,v 1.18 2003/01/04 00:15:15 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/popen.c,v 1.21 2009/05/27 19:28:04 ed Exp $");
#include "namespace.h"
#include <sys/param.h>
+#include <sys/queue.h>
#include <sys/wait.h>
#include <signal.h>
extern char **environ;
-static struct pid {
- struct pid *next;
+struct pid {
+ SLIST_ENTRY(pid) next;
FILE *fp;
pid_t pid;
-} *pidlist;
+};
+static SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
static pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
#define THREAD_LOCK() if (__isthreaded) _pthread_mutex_lock(&pidlist_mutex)
}
(void)_close(pdes[1]);
}
- for (p = pidlist; p; p = p->next) {
+ SLIST_FOREACH(p, &pidlist, next)
(void)_close(fileno(p->fp));
- }
_execve(_PATH_BSHELL, argv, environ);
_exit(127);
/* NOTREACHED */
cur->fp = iop;
cur->pid = pid;
THREAD_LOCK();
- cur->next = pidlist;
- pidlist = cur;
+ SLIST_INSERT_HEAD(&pidlist, cur, next);
THREAD_UNLOCK();
return (iop);
pclose(iop)
FILE *iop;
{
- struct pid *cur, *last;
+ struct pid *cur, *last = NULL;
int pstat;
pid_t pid;
* Find the appropriate file pointer and remove it from the list.
*/
THREAD_LOCK();
- for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ SLIST_FOREACH(cur, &pidlist, next) {
if (cur->fp == iop)
break;
+ last = cur;
+ }
if (cur == NULL) {
THREAD_UNLOCK();
return (-1);
}
if (last == NULL)
- pidlist = cur->next;
+ SLIST_REMOVE_HEAD(&pidlist, next);
else
- last->next = cur->next;
+ SLIST_REMOVE_AFTER(last, next);
THREAD_UNLOCK();
(void)fclose(iop);
---- popen.c.orig 2009-03-03 02:04:57.000000000 -0800
-+++ popen.c 2009-03-03 15:28:31.000000000 -0800
-@@ -34,6 +34,10 @@
+--- popen.c.orig 2009-12-02 15:21:37.000000000 -0800
++++ popen.c 2009-12-02 15:36:51.000000000 -0800
+@@ -30,6 +30,10 @@
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
#endif /* LIBC_SCCS and not lint */
-@@ -43,7 +47,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
- #include "namespace.h"
+@@ -40,7 +44,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
#include <sys/param.h>
+ #include <sys/queue.h>
#include <sys/wait.h>
-
+#include <sys/socket.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
-@@ -52,17 +57,29 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
+@@ -49,18 +54,39 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
#include <string.h>
#include <paths.h>
#include <pthread.h>
-extern char **environ;
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
++
++/* Our queue.h doesn't have SLIST_REMOVE_AFTER in it yet
++ * <rdar://problem/7431558> API: Add SLIST_REMOVE_AFTER to sys/queue.h (from FreeBSD)
++ */
++#ifndef SLIST_REMOVE_AFTER
++#define SLIST_REMOVE_AFTER(elm, field) do { \
++ SLIST_NEXT(elm, field) = \
++ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
++} while (0)
++#endif
--static struct pid {
+/* 3516149 - store file descriptor and use that to close to prevent blocking */
-+struct pid {
- struct pid *next;
+ struct pid {
+ SLIST_ENTRY(pid) next;
FILE *fp;
+ int fd;
pid_t pid;
--} *pidlist;
+ };
+-static SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
-static pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
-+};
+#define pidlist __popen_pidlist
+#define pidlist_mutex __popen_pidlist_mutex
+#ifndef BUILDING_VARIANT
-+__private_extern__ struct pid *pidlist = NULL;
++__private_extern__ SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
+__private_extern__ pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
+#else /* BUILDING_VARIANT */
-+extern struct pid *pidlist;
++extern SLIST_HEAD(, pid) pidlist;
+extern pthread_mutex_t pidlist_mutex;
+#endif /* !BUILDING_VARIANT */
#define THREAD_LOCK() if (__isthreaded) _pthread_mutex_lock(&pidlist_mutex)
#define THREAD_UNLOCK() if (__isthreaded) _pthread_mutex_unlock(&pidlist_mutex)
-@@ -73,85 +90,109 @@ popen(command, type)
+@@ -71,84 +97,108 @@ popen(command, type)
{
struct pid *cur;
FILE *iop;
+ }
+ (void)posix_spawn_file_actions_addclose(&file_actions, pdes[1]);
+ }
-+ for (p = pidlist; p; p = p->next) {
++ SLIST_FOREACH(p, &pidlist, next)
+ (void)posix_spawn_file_actions_addclose(&file_actions, p->fd);
-+ }
+
argv[0] = "sh";
argv[1] = "-c";
- }
- (void)_close(pdes[1]);
- }
-- for (p = pidlist; p; p = p->next) {
+- SLIST_FOREACH(p, &pidlist, next)
- (void)_close(fileno(p->fp));
-- }
- _execve(_PATH_BSHELL, argv, environ);
- _exit(127);
- /* NOTREACHED */
(void)_close(pdes[0]);
}
-@@ -162,10 +203,11 @@ popen(command, type)
- cur->next = pidlist;
- pidlist = cur;
+@@ -158,10 +208,11 @@ popen(command, type)
+ THREAD_LOCK();
+ SLIST_INSERT_HEAD(&pidlist, cur, next);
THREAD_UNLOCK();
-
+ fwide(iop, -1); /* byte stream */
/*
* pclose --
* Pclose returns -1 if stream is not associated with a `popened' command,
-@@ -198,6 +240,10 @@ pclose(iop)
+@@ -196,6 +247,10 @@ pclose(iop)
(void)fclose(iop);
do {
pid = _wait4(cur->pid, &pstat, 0, (struct rusage *)0);
} while (pid == -1 && errno == EINTR);
-@@ -206,3 +252,4 @@ pclose(iop)
+@@ -204,3 +259,4 @@ pclose(iop)
return (pid == -1 ? -1 : pstat);
}
---- _SB/Libc/gen/FreeBSD/pselect.3 2003-05-20 15:21:02.000000000 -0700
-+++ _SB/Libc/gen/FreeBSD/pselect.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- pselect.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ pselect.3 2009-11-07 14:51:39.000000000 -0800
@@ -37,15 +37,15 @@
.Sh LIBRARY
.Lb libc
.Fc
.Sh DESCRIPTION
The
-@@ -57,7 +57,7 @@
+@@ -57,7 +57,7 @@ as a slightly stronger version of
The
.Fa nfds , readfds , writefds ,
and
arguments are all identical to the analogous arguments of
.Fn select .
The
-@@ -65,7 +65,7 @@
+@@ -65,7 +65,7 @@ The
argument in
.Fn pselect
points to a
rather than the (modifiable)
.Vt "struct timeval"
used by
-@@ -76,7 +76,7 @@
+@@ -76,7 +76,7 @@ a null pointer may be passed to indicate
.Fn pselect
should wait indefinitely.
Finally,
---- pselect.c.orig 2007-08-19 17:38:56.000000000 -0700
-+++ pselect.c 2007-08-19 19:15:50.000000000 -0700
+--- pselect.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ pselect.c 2009-11-07 14:51:39.000000000 -0800
@@ -27,12 +27,22 @@
* SUCH DAMAGE.
*/
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)psignal.3 8.2 (Berkeley) 2/27/95
-.\" $FreeBSD: src/lib/libc/gen/psignal.3,v 1.16 2002/12/30 21:18:02 schweikh Exp $
+.\" $FreeBSD: src/lib/libc/gen/psignal.3,v 1.17 2007/01/09 00:27:54 imp Exp $
.\"
.Dd February 27, 1995
.Dt PSIGNAL 3
--- /dev/null
+--- psignal.3.orig 2010-05-06 12:14:16.000000000 -0700
++++ psignal.3 2010-05-06 12:21:47.000000000 -0700
+@@ -98,6 +98,19 @@ contains a count of the strings in
+ .Va sys_siglist
+ and
+ .Va sys_signame .
++.Sh RETURN VALUES
++.Fn strsignal
++a pointer to the desired message or a NULL value indicating an error. This
++string is not to be freed by the caller. Beginning with Mac OSX 10.7, this
++string is unique to each thread.
++.Sh ERRORS
++.Fn strsignal
++will fail and no additional memory will be allocated if
++one of the following are true:
++.Bl -tag -width Er
++.It Bq Er ENOMEM
++There was insufficient memory to allocate storage space for the return value in the running thread.
++.El
+ .Sh SEE ALSO
+ .Xr sigaction 2 ,
+ .Xr perror 3 ,
* 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.
static char sccsid[] = "@(#)psignal.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/psignal.c,v 1.7 2002/02/01 01:08:48 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/psignal.c,v 1.8 2007/01/09 00:27:54 imp Exp $");
/*
* Print the name of the signal indicated
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)raise.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/raise.3,v 1.7 2001/10/01 16:08:51 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/raise.3,v 1.8 2007/01/09 00:27:55 imp Exp $
.\"
.Dd June 4, 1993
.Dt RAISE 3
* 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.
static char sccsid[] = "@(#)raise.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/raise.c,v 1.4 2003/07/19 05:22:56 davidxu Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/raise.c,v 1.5 2007/01/09 00:27:55 imp Exp $");
#include <signal.h>
#include <unistd.h>
.\" to anyone/anything when using this software.
.\"
.\" @(#)rand48.3 V1.0 MB 8 Oct 1993
-.\" $FreeBSD: src/lib/libc/gen/rand48.3,v 1.16 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/rand48.3,v 1.17 2005/01/20 09:17:02 ru Exp $
.\"
.Dd October 8, 1993
.Dt RAND48 3
.Pp
For a more powerful random number generator, see
.Xr random 3 .
-.Sh AUTHORS
-.An Martin Birgmeier
.Sh SEE ALSO
.Xr rand 3 ,
.Xr random 3
+.Sh AUTHORS
+.An Martin Birgmeier
---- _SB/Libc/gen/FreeBSD/rand48.3 2004-11-25 11:38:01.000000000 -0800
-+++ _SB/Libc/gen/FreeBSD/rand48.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- rand48.3.orig 2010-02-08 16:26:16.000000000 -0800
++++ rand48.3 2010-02-13 19:48:39.000000000 -0800
@@ -18,51 +18,68 @@
.Sh NAME
.Nm drand48 ,
-for the multiplicand a = 0xfdeece66d = 25214903917 and
-the addend c = 0xb = 11.
+r(n+1) = (a * r(n) + c) mod m.
-+The default value for the multiplicand `a' is 0xfdeece66d (25214903917).
++The default value for the multiplicand `a' is 0x5deece66d (25214903917).
+The default value for the the addend `c' is 0xb (11).
The modulo is always fixed at m = 2 ** 48.
r(n) is called the seed of the random number generator.
computational step is to perform a single iteration of the algorithm.
.Pp
The
-@@ -124,7 +141,7 @@
+@@ -124,7 +141,7 @@ is used to initialize the internal buffe
.Fn drand48 ,
.Fn lrand48 ,
and
such that the 32 bits of the seed value are copied into the upper 32 bits
of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
Additionally, the constant multiplicand and addend of the algorithm are
-@@ -147,7 +164,7 @@
+@@ -147,7 +164,7 @@ The
.Fn seed48
function
returns a pointer to an array of 3 shorts which contains the old seed.
---- rand48.h.orig 2003-05-20 15:21:02.000000000 -0700
-+++ rand48.h 2005-11-03 14:06:17.000000000 -0800
+--- rand48.h.orig 2009-11-07 14:51:38.000000000 -0800
++++ rand48.h 2009-11-07 14:51:39.000000000 -0800
@@ -19,8 +19,6 @@
#include <math.h>
#include <stdlib.h>
#define RAND48_SEED_0 (0x330e)
#define RAND48_SEED_1 (0xabcd)
#define RAND48_SEED_2 (0x1234)
-@@ -29,4 +27,55 @@
+@@ -29,4 +27,55 @@ void _dorand48(unsigned short[3]);
#define RAND48_MULT_2 (0x0005)
#define RAND48_ADD (0x000b)
* 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.
static char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/readdir.c,v 1.11 2002/02/26 21:39:32 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/readdir.c,v 1.15 2008/05/05 14:05:23 kib Exp $");
#include "namespace.h"
#include <sys/param.h>
#include "un-namespace.h"
#include "libc_private.h"
+#include "telldir.h"
/*
* get next entry in a directory.
*/
struct dirent *
-_readdir_unlocked(dirp)
+_readdir_unlocked(dirp, skip)
DIR *dirp;
+ int skip;
{
struct dirent *dp;
dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
return (NULL);
dirp->dd_loc += dp->d_reclen;
- if (dp->d_ino == 0)
+ if (dp->d_ino == 0 && skip)
continue;
if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW))
continue;
struct dirent *dp;
if (__isthreaded) {
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
- dp = _readdir_unlocked(dirp);
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
+ dp = _readdir_unlocked(dirp, 1);
+ _pthread_mutex_unlock(&dirp->dd_lock);
}
else
- dp = _readdir_unlocked(dirp);
+ dp = _readdir_unlocked(dirp, 1);
return (dp);
}
saved_errno = errno;
errno = 0;
if (__isthreaded) {
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
- if ((dp = _readdir_unlocked(dirp)) != NULL)
+ _pthread_mutex_lock(&dirp->dd_lock);
+ if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
}
- else if ((dp = _readdir_unlocked(dirp)) != NULL)
+ else if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
if (errno != 0) {
---- readdir.c.orig 2007-01-24 14:10:41.000000000 -0800
-+++ readdir.c 2007-01-27 02:51:25.000000000 -0800
-@@ -43,8 +43,10 @@
+--- readdir.c.orig 2009-11-08 13:59:03.000000000 -0800
++++ readdir.c 2009-11-08 13:59:22.000000000 -0800
+@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/rea
#include <errno.h>
#include <string.h>
#include <pthread.h>
+#include <unistd.h>
#include "un-namespace.h"
-+#include "telldir.h"
#include "libc_private.h"
-
- /*
-@@ -63,8 +65,13 @@
+@@ -61,8 +62,13 @@ _readdir_unlocked(dirp, skip)
dirp->dd_loc = 0;
}
if (dirp->dd_loc == 0 && !(dirp->dd_flags & __DTF_READALL)) {
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/gen/readpassphrase.3,v 1.6 2002/12/27 12:15:28 schweikh Exp $
+.\" $FreeBSD: src/lib/libc/gen/readpassphrase.3,v 1.7 2005/01/20 09:17:02 ru Exp $
.\"
.Dd December 7, 2001
.Dt READPASSPHRASE 3
a
.Dv NULL
pointer is returned.
-.Sh ERRORS
-.Bl -tag -width Er
-.It Bq Er EINTR
-The
-.Fn readpassphrase
-function was interrupted by a signal.
-.It Bq Er EINVAL
-The
-.Fa bufsiz
-argument was zero.
-.It Bq Er EIO
-The process is a member of a background process attempting to read
-from its controlling terminal, the process is ignoring or blocking
-the
-.Dv SIGTTIN
-signal or the process group is orphaned.
-.It Bq Er EMFILE
-The process has already reached its limit for open file descriptors.
-.It Bq Er ENFILE
-The system file table is full.
-.It Bq Er ENOTTY
-There is no controlling terminal and the
-.Dv RPP_REQUIRE_TTY
-flag was specified.
+.Sh FILES
+.Bl -tag -width ".Pa /dev/tty" -compact
+.It Pa /dev/tty
.El
.Sh EXAMPLES
The following code fragment will read a passphrase from
When the process is resumed after it has been stopped,
.Fn readpassphrase
will reprint the prompt and the user may then enter a passphrase.
-.Sh FILES
-.Bl -tag -width ".Pa /dev/tty" -compact
-.It Pa /dev/tty
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINTR
+The
+.Fn readpassphrase
+function was interrupted by a signal.
+.It Bq Er EINVAL
+The
+.Fa bufsiz
+argument was zero.
+.It Bq Er EIO
+The process is a member of a background process attempting to read
+from its controlling terminal, the process is ignoring or blocking
+the
+.Dv SIGTTIN
+signal or the process group is orphaned.
+.It Bq Er EMFILE
+The process has already reached its limit for open file descriptors.
+.It Bq Er ENFILE
+The system file table is full.
+.It Bq Er ENOTTY
+There is no controlling terminal and the
+.Dv RPP_REQUIRE_TTY
+flag was specified.
.El
.Sh SEE ALSO
.Xr sigaction 2 ,
---- readpassphrase.c.orig 2003-05-20 15:21:02.000000000 -0700
-+++ readpassphrase.c 2005-02-24 17:00:36.000000000 -0800
-@@ -33,6 +33,8 @@
+--- readpassphrase.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ readpassphrase.c 2009-11-07 14:51:39.000000000 -0800
+@@ -33,6 +33,8 @@ static const char rcsid[] = "$OpenBSD: r
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/gen/readpassphrase.c,v 1.6 2002/03/09 03:16:41 green Exp $");
#include "namespace.h"
#include <ctype.h>
#include <errno.h>
-@@ -59,6 +61,7 @@
+@@ -59,6 +61,7 @@ readpassphrase(const char *prompt, char
struct termios term, oterm;
struct sigaction sa, saveint, savehup, savequit, saveterm;
struct sigaction savetstp, savettin, savettou;
/* I suppose we could alloc on demand in this case (XXX). */
if (bufsiz == 0) {
-@@ -115,11 +118,11 @@
+@@ -115,11 +118,11 @@ restart:
if (p < end) {
if ((flags & RPP_SEVENBIT))
ch &= 0x7f;
* 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.
static char sccsid[] = "@(#)rewinddir.c 8.1 (Berkeley) 6/8/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/rewinddir.c,v 1.5 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/rewinddir.c,v 1.6 2007/01/09 00:27:55 imp Exp $");
#include <sys/types.h>
#include <dirent.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)scandir.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/scandir.3,v 1.8 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/scandir.3,v 1.9 2007/01/09 00:27:55 imp Exp $
.\"
.Dd June 4, 1993
.Dt SCANDIR 3
---- scandir.3.orig 2009-05-12 11:21:55.000000000 -0700
-+++ scandir.3 2009-05-20 15:41:07.000000000 -0700
-@@ -32,15 +32,16 @@
+--- scandir.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ scandir.3 2009-11-07 14:51:40.000000000 -0800
+@@ -28,15 +28,16 @@
.\" @(#)scandir.3 8.1 (Berkeley) 6/4/93
- .\" $FreeBSD: src/lib/libc/gen/scandir.3,v 1.8 2002/12/19 09:40:21 ru Exp $
+ .\" $FreeBSD: src/lib/libc/gen/scandir.3,v 1.9 2007/01/09 00:27:55 imp Exp $
.\"
-.Dd June 4, 1993
+.Dd May 20, 2008
.Sh SYNOPSIS
.In sys/types.h
.In dirent.h
-@@ -48,6 +49,10 @@
+@@ -44,6 +45,10 @@
.Fn scandir "const char *dirname" "struct dirent ***namelist" "int \\*(lp*select\\*(rp\\*(lpstruct dirent *\\*(rp" "int \\*(lp*compar\\*(rp\\*(lpconst void *, const void *\\*(rp"
.Ft int
.Fn alphasort "const void *d1" "const void *d2"
.Sh DESCRIPTION
The
.Fn scandir
-@@ -80,6 +85,13 @@
+@@ -76,6 +81,13 @@ argument is a pointer to a user supplied
.Xr qsort 3
to sort the completed array.
If this pointer is null, the array is not sorted.
.Pp
The
.Fn alphasort
-@@ -91,6 +103,18 @@
+@@ -87,6 +99,18 @@ argument to sort the array alphabeticall
The memory allocated for the array can be deallocated with
.Xr free 3 ,
by freeing each pointer in the array and then the array itself.
.Sh DIAGNOSTICS
Returns \-1 if the directory cannot be opened for reading or if
.Xr malloc 3
-@@ -107,3 +131,8 @@
+@@ -103,3 +127,8 @@ and
.Fn alphasort
functions appeared in
.Bx 4.2 .
* 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.
static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.7 2002/02/01 01:32:19 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.9 2008/03/16 19:08:53 das Exp $");
/*
* Scan the directory dirname calling select to make a list of selected
*/
#include "namespace.h"
-#include <sys/types.h>
-#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
{
struct dirent *d, *p, **names = NULL;
size_t nitems = 0;
- struct stat stb;
long arraysz;
DIR *dirp;
if ((dirp = opendir(dirname)) == NULL)
return(-1);
- if (_fstat(dirp->dd_fd, &stb) < 0)
- goto fail;
- /*
- * estimate the array size by taking the size of the directory file
- * and dividing it by a multiple of the minimum size entry.
- */
- arraysz = (stb.st_size / 24);
+ arraysz = 32; /* initial estimate of the array size */
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
if (names == NULL)
goto fail;
* realloc the maximum size.
*/
if (nitems >= arraysz) {
- const int inc = 10; /* increase by this much */
struct dirent **names2;
names2 = (struct dirent **)realloc((char *)names,
- (arraysz + inc) * sizeof(struct dirent *));
+ (arraysz * 2) * sizeof(struct dirent *));
if (names2 == NULL) {
free(p);
goto fail;
}
names = names2;
- arraysz += inc;
+ arraysz *= 2;
}
names[nitems++] = p;
}
---- scandir.c.orig 2008-07-28 02:49:02.000000000 -0700
-+++ scandir.c 2008-07-29 12:02:49.000000000 -0700
-@@ -53,15 +53,11 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/sca
+--- scandir.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ scandir.c 2009-11-07 14:51:40.000000000 -0800
+@@ -47,15 +47,11 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/sca
#include "un-namespace.h"
/*
int
scandir(dirname, namelist, select, dcomp)
-@@ -96,7 +92,7 @@ scandir(dirname, namelist, select, dcomp
+@@ -83,7 +79,7 @@ scandir(dirname, namelist, select, dcomp
/*
* Make a minimum size copy of the data
*/
---- scandir_b.c.orig 2008-07-29 12:03:05.000000000 -0700
-+++ scandir_b.c 2008-07-29 12:03:31.000000000 -0700
-@@ -53,22 +53,18 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/sca
+--- scandir_b.c 2009-11-07 14:51:38.000000000 -0800
++++ scandir_b.c 2009-11-07 18:46:38.000000000 -0800
+@@ -47,22 +47,18 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/sca
#include "un-namespace.h"
/*
{
struct dirent *d, *p, **names = NULL;
size_t nitems = 0;
-@@ -91,12 +87,12 @@ scandir(dirname, namelist, select, dcomp
+@@ -78,12 +74,12 @@ scandir(dirname, namelist, select, dcomp
goto fail;
while ((d = readdir(dirp)) != NULL) {
if (p == NULL)
goto fail;
p->d_fileno = d->d_fileno;
-@@ -125,7 +121,7 @@ scandir(dirname, namelist, select, dcomp
+@@ -111,7 +107,7 @@ scandir(dirname, namelist, select, dcomp
}
closedir(dirp);
if (nitems && dcomp != NULL)
*namelist = names;
return(nitems);
-@@ -136,15 +132,3 @@ fail:
+@@ -122,15 +118,3 @@ fail:
closedir(dirp);
return -1;
}
---- seed48.c.orig 2003-05-20 15:21:02.000000000 -0700
-+++ seed48.c 2005-11-03 13:48:11.000000000 -0800
-@@ -16,24 +16,14 @@
+--- seed48.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ seed48.c 2009-11-07 14:51:39.000000000 -0800
+@@ -16,24 +16,14 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/see
#include "rand48.h"
* 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.
static char sccsid[] = "@(#)seekdir.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/seekdir.c,v 1.5 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/seekdir.c,v 1.7 2007/12/03 14:33:51 des Exp $");
#include "namespace.h"
#include <sys/param.h>
long loc;
{
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
_seekdir(dirp, loc);
if (__isthreaded)
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
}
* 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.
static char sccsid[] = "@(#)sethostname.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/sethostname.c,v 1.4 2002/05/28 16:59:39 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/sethostname.c,v 1.6 2007/01/09 00:27:55 imp Exp $");
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <unistd.h>
+
int
sethostname(const char *name, int namelen)
{
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)setmode.3 8.2 (Berkeley) 4/28/95
-.\" $FreeBSD: src/lib/libc/gen/setmode.3,v 1.11 2001/10/01 16:08:51 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/setmode.3,v 1.12 2007/01/09 00:27:55 imp Exp $
.\"
.Dd April 28, 1995
.Dt SETMODE 3
* 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.
static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/setmode.c,v 1.9 2003/02/23 00:24:03 mikeh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/setmode.c,v 1.11 2007/01/09 00:27:55 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
* bits) followed by a '+' (set bits).
*/
mode_t
-getmode(bbox, omode)
- const void *bbox;
- mode_t omode;
+getmode(const void *bbox, mode_t omode)
{
const BITCMD *set;
mode_t clrval, newmode, value;
#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
void *
-setmode(p)
- const char *p;
+setmode(const char *p)
{
int perm, who;
char op, *ep;
}
static BITCMD *
-addcmd(set, op, who, oparg, mask)
- BITCMD *set;
- int oparg, who;
- int op;
- u_int mask;
+addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
{
switch (op) {
case '=':
#ifdef SETMODE_DEBUG
static void
-dumpmode(set)
- BITCMD *set;
+dumpmode(BITCMD *set)
{
for (; set->cmd; ++set)
(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
* compacted, but it's not worth the effort.
*/
static void
-compress_mode(set)
- BITCMD *set;
+compress_mode(BITCMD *set)
{
BITCMD *nset;
int setbits, clrbits, Xbits, op;
---- setmode.c.orig 2008-02-08 00:45:35.000000000 -0800
-+++ setmode.c 2008-02-17 19:36:02.000000000 -0800
-@@ -70,12 +70,15 @@ typedef struct bitcmd {
+--- setmode.c.orig 2009-11-08 14:13:46.000000000 -0800
++++ setmode.c 2009-11-08 14:13:39.000000000 -0800
+@@ -66,12 +66,15 @@ typedef struct bitcmd {
#define CMD2_OBITS 0x08
#define CMD2_UBITS 0x10
/*
* Given the old mode and an array of bitcmd structures, apply the operations
* described in the bitcmd structures to the old mode, and return the new mode.
-@@ -151,6 +154,7 @@ common: if (set->cmd2 & CMD2_CLR) {
+@@ -145,6 +148,7 @@ common: if (set->cmd2 & CMD2_CLR) {
return (newmode);
}
}
#define ADDCMD(a, b, c, d) \
if (set >= endset) { \
-@@ -169,7 +173,11 @@ common: if (set->cmd2 & CMD2_CLR) {
+@@ -163,7 +167,11 @@ common: if (set->cmd2 & CMD2_CLR) {
} \
set = addcmd(set, (a), (b), (c), (d))
+#endif /* !VARIANT_LEGACY */
void *
- setmode(p)
-@@ -211,12 +219,21 @@ setmode(p)
+ setmode(const char *p)
+@@ -204,12 +212,21 @@ setmode(const char *p)
*/
if (isdigit((unsigned char)*p)) {
perml = strtol(p, &ep, 8);
set->cmd = 0;
return (saveset);
}
-@@ -253,7 +270,9 @@ getop: if ((op = *p++) != '+' && op !=
+@@ -246,7 +263,9 @@ getop: if ((op = *p++) != '+' && op !=
if (op == '=')
equalopdone = 0;
for (perm = 0, permXbits = 0;; ++p) {
switch (*p) {
case 'r':
-@@ -267,7 +286,9 @@ getop: if ((op = *p++) != '+' && op !=
+@@ -260,7 +279,9 @@ getop: if ((op = *p++) != '+' && op !=
case 't':
/* If only "other" bits ignore sticky. */
if (!who || who & ~S_IRWXO) {
perm |= S_ISTXT;
}
break;
-@@ -402,13 +423,14 @@ dumpmode(set)
+@@ -390,13 +411,14 @@ dumpmode(BITCMD *set)
}
#endif
*/
-static void
+__private_extern__ void
- compress_mode(set)
- BITCMD *set;
+ compress_mode(BITCMD *set)
{
-@@ -457,3 +479,4 @@ compress_mode(set)
+ BITCMD *nset;
+@@ -444,3 +466,4 @@ compress_mode(BITCMD *set)
}
}
}
---- setprogname.c.orig 2008-01-31 02:47:06.000000000 -0800
-+++ setprogname.c 2008-01-31 03:07:50.000000000 -0800
-@@ -3,6 +3,10 @@
+--- setprogname.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ setprogname.c 2009-11-07 14:51:39.000000000 -0800
+@@ -3,6 +3,10 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/set
#include <stdlib.h>
#include <string.h>
#include "libc_private.h"
-@@ -10,10 +14,20 @@
+@@ -10,10 +14,20 @@ void
setprogname(const char *progname)
{
const char *p;
p = strrchr(progname, '/');
if (p != NULL)
- __progname = p + 1;
-+ __progname = (char *)(p + 1);
++ __progname = (char *)(p = p + 1);
else
- __progname = progname;
+ __progname = (char *)(p = progname);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)siginterrupt.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/siginterrupt.3,v 1.14 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/siginterrupt.3,v 1.15 2007/01/09 00:27:55 imp Exp $
.\"
.Dd June 4, 1993
.Dt SIGINTERRUPT 3
---- _SB/Libc/gen/FreeBSD/siginterrupt.3 2003-05-20 15:21:02.000000000 -0700
-+++ _SB/Libc/gen/FreeBSD/siginterrupt.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -96,8 +96,8 @@
+--- siginterrupt.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ siginterrupt.3 2009-11-07 14:51:40.000000000 -0800
+@@ -92,8 +92,8 @@ the new action to take place on the next
This library routine uses an extension of the
.Xr sigaction 2
system call that is not available in
* 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.
static char sccsid[] = "@(#)siginterrupt.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/siginterrupt.c,v 1.4 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/siginterrupt.c,v 1.5 2007/01/09 00:27:55 imp Exp $");
#include "namespace.h"
#include <signal.h>
* 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.
static char sccsid[] = "@(#)siglist.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/siglist.c,v 1.4 2002/09/07 08:14:19 jmallett Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/siglist.c,v 1.6 2007/01/20 08:24:01 maxim Exp $");
-#include <sys/cdefs.h>
#include <signal.h>
const char *const sys_signame[NSIG] = {
---- siglist.c.orig Sat Sep 7 01:14:19 2002
-+++ siglist.c Thu May 8 00:46:49 2003
-@@ -109,4 +109,3 @@
+--- siglist.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ siglist.c 2009-11-07 14:51:40.000000000 -0800
+@@ -104,4 +104,3 @@ const char *const sys_siglist[NSIG] = {
"User defined signal 1", /* SIGUSR1 */
"User defined signal 2" /* SIGUSR2 */
};
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)signal.3 8.3 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/signal.3,v 1.38 2004/07/03 22:30:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/signal.3,v 1.43 2008/07/17 21:54:23 simon Exp $
.\"
.Dd June 7, 2004
.Dt SIGNAL 3
.Lb libc
.Sh SYNOPSIS
.In signal.h
-.\" The following is Quite Ugly, but syntactically correct.
-.\" Don't try to
-.\" fix it.
-.Ft void \*(lp*
-.Fn signal "int sig" "void \*(lp*func\*(rp\*(lpint\*(rp\*(rp\*(rp\*(lpint"
+.\" XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
+.\" The prototype for signal(3) cannot be cleanly marked up in -mdoc
+.\" without the following lower-level tweak.
+.nr in-synopsis-section 0
.Pp
+.Ft "void \*(lp*" Ns
+.Fo signal
+.Fa "int sig"
+.Fa "void \*(lp*func\*(rp\*(lpint\*(rp"
+.Fc Ns
+.Ft "\*(rp\*(lpint\*(rp" ;
+.Pp
+.nr in-synopsis-section 1
+.\" XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
or in
-.Fx Ns 's
+.Fx Ap s
equivalent but easier to read typedef'd version:
.Ft typedef "void \*(lp*sig_t\*(rp \*(lpint\*(rp" ;
+.Pp
.Ft sig_t
.Fn signal "int sig" "sig_t func"
.Sh DESCRIPTION
For some system calls, if a signal is caught while the call is
executing and the call is prematurely terminated,
the call is automatically restarted.
-(The handler is installed using the
+Any handler installed with
+.Xr signal 3
+will have the
.Dv SA_RESTART
-flag with
-.Xr sigaction 2 . )
+flag set, meaning that any restartable system call will not return on
+receipt of a signal.
The affected system calls include
.Xr read 2 ,
.Xr write 2 ,
An attempt is made to ignore or supply a handler for
.Dv SIGKILL
or
-.Ev SIGSTOP .
+.Dv SIGSTOP .
.El
.Sh SEE ALSO
.Xr kill 1 ,
.Xr siginterrupt 3 ,
.Xr tty 4
.Sh HISTORY
-This
-.Fn signal
+The
+.Nm
facility appeared in
.Bx 4.0 .
The option to avoid the creation of child zombies through ignoring
---- signal.3.orig 2006-12-15 11:55:30.000000000 -0800
-+++ signal.3 2006-12-15 11:57:08.000000000 -0800
-@@ -48,9 +48,7 @@
- .Ft void \*(lp*
- .Fn signal "int sig" "void \*(lp*func\*(rp\*(lpint\*(rp\*(rp\*(rp\*(lpint"
+--- signal.3.bsdnew 2009-11-08 14:20:21.000000000 -0800
++++ signal.3 2009-11-08 14:26:22.000000000 -0800
+@@ -52,9 +52,7 @@
.Pp
+ .nr in-synopsis-section 1
+ .\" XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
-or in
--.Fx Ns 's
+-.Fx Ap s
-equivalent but easier to read typedef'd version:
+or in the equivalent but easier to read typedef'd version:
.Ft typedef "void \*(lp*sig_t\*(rp \*(lpint\*(rp" ;
+ .Pp
.Ft sig_t
- .Fn signal "int sig" "sig_t func"
-@@ -62,9 +60,9 @@
+@@ -67,9 +65,9 @@ is a simplified interface to the more ge
.Xr sigaction 2
facility.
.Pp
There are two general types of signals:
those that cause termination of a process and those that do not.
Signals which cause termination of a program might result from
-@@ -77,11 +75,10 @@
+@@ -82,11 +80,10 @@ Signals are optionally generated
when a process resumes after being stopped,
when the status of child processes changes,
or when input is ready at the control terminal.
Except for the
.Dv SIGKILL
and
-@@ -135,7 +132,6 @@
+@@ -140,7 +137,6 @@ is possible on a descriptor (see
.It 29 Ta Dv SIGINFO Ta "discard signal" Ta "status request from keyboard"
.It 30 Ta Dv SIGUSR1 Ta "terminate process" Ta "User defined signal 1"
.It 31 Ta Dv SIGUSR2 Ta "terminate process" Ta "User defined signal 2"
.El
.Pp
The
-@@ -151,7 +147,7 @@
+@@ -156,7 +152,7 @@ should be
A
.Dv SIG_DFL
resets the default action.
.Fa func
should be
.Dv SIG_IGN .
-@@ -185,7 +181,7 @@
+@@ -192,7 +188,7 @@ The affected system calls include
.Xr write 2 ,
.Xr sendto 2 ,
.Xr recvfrom 2 ,
* 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.
static char sccsid[] = "@(#)signal.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/signal.c,v 1.3 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/signal.c,v 1.4 2007/01/09 00:27:55 imp Exp $");
/*
* Almost backwards compatible signal.
---- signal.c.orig Thu Jan 31 16:57:29 2002
-+++ signal.c Fri May 16 14:16:12 2003
-@@ -47,10 +47,13 @@
+--- signal.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ signal.c 2009-11-07 14:51:40.000000000 -0800
+@@ -43,10 +43,13 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/sig
sigset_t _sigintr; /* shared with siginterrupt */
{
struct sigaction sa, osa;
-@@ -59,7 +62,34 @@
+@@ -55,7 +58,34 @@ signal(s, a)
sa.sa_flags = 0;
if (!sigismember(&_sigintr, s))
sa.sa_flags |= SA_RESTART;
---- _SB/Libc/gen/FreeBSD/signbit.3 2003-11-12 00:44:46.000000000 -0800
-+++ _SB/Libc/gen/FreeBSD/signbit.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- signbit.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ signbit.3 2009-11-07 14:51:39.000000000 -0800
@@ -40,8 +40,9 @@
The
.Fn signbit
.Sh SEE ALSO
.Xr fpclassify 3 ,
.Xr math 3
-@@ -50,8 +51,3 @@
+@@ -50,8 +51,3 @@ The
.Fn signbit
macro conforms to
.St -isoC-99 .
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)sleep.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/sleep.3,v 1.16 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/sleep.3,v 1.17 2007/01/09 00:27:55 imp Exp $
.\"
.Dd February 13, 1998
.Dt SLEEP 3
---- /Volumes/XDisk/tmp/Libc/gen/FreeBSD/sleep.3.orig 2004-07-02 16:52:10.000000000 -0700
-+++ /Volumes/XDisk/tmp/Libc/gen/FreeBSD/sleep.3 2004-10-24 17:08:28.000000000 -0700
-@@ -37,7 +37,7 @@
+--- sleep.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ sleep.3 2009-11-07 14:51:40.000000000 -0800
+@@ -33,7 +33,7 @@
.Os
.Sh NAME
.Nm sleep
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-@@ -47,11 +47,11 @@
+@@ -43,11 +43,11 @@
.Sh DESCRIPTION
The
.Fn sleep
* 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.
static char sccsid[] = "@(#)sleep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/sleep.c,v 1.31 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/sleep.c,v 1.33 2009/12/05 19:31:38 ed Exp $");
#include "namespace.h"
#include <errno.h>
#include "un-namespace.h"
unsigned int
-__sleep(seconds)
- unsigned int seconds;
+__sleep(unsigned int seconds)
{
struct timespec time_to_sleep;
struct timespec time_remaining;
---- sleep.c.orig 2007-05-23 18:18:17.000000000 -0700
-+++ sleep.c 2007-05-23 22:15:14.000000000 -0700
-@@ -31,6 +31,11 @@
+--- sleep.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ sleep.c 2009-11-07 14:51:40.000000000 -0800
+@@ -27,6 +27,11 @@
* SUCH DAMAGE.
*/
---- srand48.c.orig 2003-05-20 15:21:03.000000000 -0700
-+++ srand48.c 2005-11-03 13:50:51.000000000 -0800
+--- srand48.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ srand48.c 2009-11-07 14:51:39.000000000 -0800
@@ -13,18 +13,10 @@
#include "rand48.h"
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/gen/stringlist.3,v 1.10 2003/02/23 01:47:47 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/stringlist.3,v 1.11 2005/02/13 23:45:46 ru Exp $
.\"
.Dd November 28, 1999
.Os
.Fa item
in
.Fa sl ,
-returning NULL if it's not found.
+returning NULL if it is not found.
.El
.Sh SEE ALSO
.Xr free 3 ,
* 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.
*
static char *rcsid = "$NetBSD: stringlist.c,v 1.2 1997/01/17 07:26:20 lukem Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/stringlist.c,v 1.7 2003/01/19 01:16:01 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/stringlist.c,v 1.8 2007/01/09 00:27:55 imp Exp $");
#include "namespace.h"
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)sysconf.3 8.3 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/sysconf.3,v 1.20 2003/12/23 18:42:55 trhodes Exp $
+.\" $FreeBSD: src/lib/libc/gen/sysconf.3,v 1.25 2007/01/09 00:27:55 imp Exp $
.\"
-.Dd June 18, 2001
+.Dd December 14, 2006
.Dt SYSCONF 3
.Os
.Sh NAME
The number of processors currently online.
.It Li _SC_OPEN_MAX
The maximum number of open files per user id.
+.It Li _SC_PAGESIZE
+The size of a system page in bytes.
.It Li _SC_STREAM_MAX
The minimum maximum number of streams that a process may have open
at any one time.
Return 1 if the system supports the User Portability Utilities Option,
otherwise \-1.
.El
+.Pp
+These values also exist, but may not be standard:
+.Pp
+.Bl -tag -width 6n
+.Pp
+.It Li _SC_PHYS_PAGES
+The number of pages of physical memory.
+Note that it is possible that the product of this value and the value of
+.Li _SC_PAGESIZE
+will overflow a
+.Vt long
+in some configurations on a 32bit machine.
+.El
.Sh RETURN VALUES
If the call to
.Fn sysconf
.Xr pathconf 2 ,
.Xr confstr 3 ,
.Xr sysctl 3
-.Sh BUGS
-The value for _SC_STREAM_MAX is a minimum maximum, and required to be
-the same as ANSI C's FOPEN_MAX, so the returned value is a ridiculously
-small and misleading number.
.Sh STANDARDS
Except for the fact that values returned by
.Fn sysconf
.Fn sysconf
function first appeared in
.Bx 4.4 .
+.Sh BUGS
+The value for _SC_STREAM_MAX is a minimum maximum, and required to be
+the same as ANSI C's FOPEN_MAX, so the returned value is a ridiculously
+small and misleading number.
---- sysctl.3.orig 2008-10-21 16:45:53.000000000 -0700
-+++ sysctl.3 2008-10-22 09:33:13.000000000 -0700
+--- sysctl.3.orig 2010-04-28 23:38:49.000000000 -0700
++++ sysctl.3 2010-04-29 10:13:28.000000000 -0700
@@ -32,7 +32,7 @@
.\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95
.\" $FreeBSD: src/lib/libc/gen/sysctl.3,v 1.63 2004/07/02 23:52:10 ru Exp $
.Dt SYSCTL 3
.Os
.Sh NAME
-@@ -182,13 +182,21 @@
+@@ -182,13 +182,21 @@ for (i = 0; i < 100; i++) {
}
.Ed
.Pp
+-- to print whatever data deemed necessary from the large
+.Vt kinfo_proc
+structure (
-+.In sysctl.h
++.In sys/sysctl.h
+) -- is left as an exercise for the reader.
+.Pp
The top level names are defined with a CTL_ prefix in
.It Sy "Name Next level names Description"
.It "CTL_DEBUG sys/sysctl.h Debugging"
.It "CTL_VFS sys/mount.h File system"
-@@ -197,7 +205,8 @@
+@@ -197,7 +205,8 @@ listed here, and described in separate s
.It "CTL_MACHDEP sys/sysctl.h Machine dependent"
.It "CTL_NET sys/socket.h Networking"
.It "CTL_USER sys/sysctl.h User-level"
.El
.Pp
For example, the following retrieves the maximum number of processes allowed
-@@ -456,16 +465,6 @@
+@@ -279,7 +288,7 @@ privilege may change the value.
+ .It Sy "Second level name Type Changeable"
+ .It "HW_MACHINE string no"
+ .It "HW_MODEL string no"
+-.It "HW_NCPU integer no"
++.It "HW_NCPU integer no (DEPRECATED)"
+ .It "HW_BYTEORDER integer no"
+ .It "HW_PHYSMEM integer no"
+ .It "HW_MEMSIZE integer no"
+@@ -296,8 +305,16 @@ privilege may change the value.
+ The machine class.
+ .It Li HW_MODEL
+ The machine model
+-.It Li HW_NCPU
+-The number of cpus.
++.It Li HW_NCPU (DEPRECATED)
++The number of cpus. It is recommended that you use "hw.physicalcpu" "hw.physicalcpu_max" "hw.logicalcpu" or "hw.logicalcpu_max" instead.
++.It Li "hw.physicalcpu"
++The number of physical processors available in the current power management mode.
++.It Li "hw.physicalcpu_max"
++The maximum number of physical processors that could be available this boot.
++.It Li "hw.logicalcpu"
++The number of logical processors available in the current power management mode.
++.It Li "hw.logicalcpu_max"
++The maximum number of logical processors that could be available this boot.
+ .It Li HW_BYTEORDER
+ The byteorder (4,321, or 1,234).
+ .It Li HW_PHYSMEM
+@@ -346,7 +363,7 @@ information.
+ .It "KERN_OSREV integer no"
+ .It "KERN_OSTYPE string no"
+ .It "KERN_POSIX1 integer no"
+-.It "KERN_PROC struct proc no"
++.It "KERN_PROC struct kinfo_proc no"
+ .It "KERN_PROF node not applicable"
+ .It "KERN_QUANTUM integer yes"
+ .It "KERN_SAVED_IDS integer no"
+@@ -440,10 +457,8 @@ with which the system
+ attempts to comply.
+ .It Li KERN_PROC
+ Return the entire process table, or a subset of it.
+-An array of pairs of
+-.Va struct proc
+-followed by corresponding
+-.Va struct eproc
++An array of
++.Va struct kinfo_proc
+ structures is returned,
+ whose size depends on the current number of such objects in the system.
+ The third and fourth level names are as follows:
+@@ -456,16 +471,6 @@ The third and fourth level names are as
.It "KERN_PROC_UID A user ID"
.It "KERN_PROC_RUID A real user ID"
.El
.It Li KERN_PROF
Return profiling information about the kernel.
If the kernel is not compiled for profiling,
-@@ -731,7 +730,6 @@
+@@ -731,7 +736,6 @@ privilege may change the value.
.Bl -column "Second level nameXXXXXX" "struct loadavgXXX" -offset indent
.It Sy "Second level name Type Changeable"
.It "VM_LOADAVG struct loadavg no"
.It "VM_PAGEOUT_ALGORITHM integer yes"
.It "VM_SWAPPING_ENABLED integer maybe"
.It "VM_V_CACHE_MAX integer yes"
-@@ -748,10 +746,6 @@
+@@ -748,10 +752,6 @@ privilege may change the value.
Return the load average history.
The returned data consists of a
.Va struct loadavg .
.It Li VM_PAGEOUT_ALGORITHM
0 if the statistics-based page management algorithm is in use
or 1 if the near-LRU algorithm is in use.
-@@ -848,7 +842,7 @@
+@@ -848,7 +848,7 @@ identifiers, and user level identifiers
definitions for second level network identifiers
.It In sys/gmon.h
definitions for third level profiling identifiers
* 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.
static char sccsid[] = "@(#)sysctl.c 8.2 (Berkeley) 1/4/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/sysctl.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/sysctl.c,v 1.6 2007/01/09 00:27:55 imp Exp $");
#include <sys/param.h>
#include <sys/sysctl.h>
--- /dev/null
+--- sysctl.c.orig 2010-06-30 01:03:07.000000000 -0700
++++ sysctl.c 2010-07-01 23:10:13.000000000 -0700
+@@ -53,8 +53,34 @@ sysctl(name, namelen, oldp, oldlenp, new
+ void *oldp, *newp;
+ size_t *oldlenp, newlen;
+ {
+- if (name[0] != CTL_USER)
++ if (name[0] != CTL_USER) {
++ if (namelen == 2 && name[0] == CTL_KERN && name[1] == KERN_EXEC) {
++ /*
++ * 7723306: intercept kern.exec and fake a return of
++ * a dummy string ("/" in this case)
++ */
++ if (newp != NULL) {
++ errno = EPERM;
++ return -1;
++ }
++ if (oldp == NULL) {
++ if (oldlenp != NULL) *oldlenp = 2;
++ return 0;
++ }
++ if (oldlenp == NULL) {
++ errno = EFAULT;
++ return -1;
++ }
++ if (*oldlenp < 2) {
++ errno = ENOMEM;
++ return -1;
++ }
++ memmove(oldp, "/", 2);
++ *oldlenp = 2;
++ return 0;
++ }
+ return (__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
++ }
+
+ if (newp != NULL) {
+ errno = EPERM;
* 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.
static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/telldir.c,v 1.8 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/telldir.c,v 1.11 2008/05/05 14:05:23 kib Exp $");
#include "namespace.h"
#include <sys/param.h>
if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
return (-1);
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
lp->loc_index = dirp->dd_td->td_loccnt++;
lp->loc_seek = dirp->dd_seek;
lp->loc_loc = dirp->dd_loc;
LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe);
if (__isthreaded)
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
return (lp->loc_index);
}
dirp->dd_seek = lp->loc_seek;
dirp->dd_loc = 0;
while (dirp->dd_loc < lp->loc_loc) {
- dp = _readdir_unlocked(dirp);
+ dp = _readdir_unlocked(dirp, 0);
if (dp == NULL)
break;
}
---- telldir.c.orig 2007-01-24 14:10:41.000000000 -0800
-+++ telldir.c 2007-01-27 02:51:57.000000000 -0800
-@@ -54,7 +54,9 @@
+--- telldir.c.orig 2009-11-08 14:02:31.000000000 -0800
++++ telldir.c 2009-11-08 14:02:24.000000000 -0800
+@@ -50,7 +50,9 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/tel
* cookie may be used only once before it is freed. This option
* is used to avoid having memory usage grow without bound.
*/
/*
* return a pointer into a directory
-@@ -65,14 +67,41 @@
+@@ -61,14 +63,41 @@ telldir(dirp)
{
struct ddloc *lp;
+#if __DARWIN_UNIX03
+ if (__isthreaded)
-+ _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
++ _pthread_mutex_lock(&dirp->dd_lock);
+ LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) {
+ if (
+#if __DARWIN_64_BIT_INO_T
+ }
+ if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) {
+ if (__isthreaded)
-+ _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
++ _pthread_mutex_unlock(&dirp->dd_lock);
+ return (-1);
+ }
+#else /* !__DARWIN_UNIX03 */
if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
return (-1);
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
+#endif /* __DARWIN_UNIX03 */
lp->loc_index = dirp->dd_td->td_loccnt++;
+#if __DARWIN_64_BIT_INO_T
+found:
+#endif /* __DARWIN_UNIX03 */
if (__isthreaded)
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
return (lp->loc_index);
-@@ -96,23 +125,34 @@
+@@ -92,23 +121,34 @@ _seekdir(dirp, loc)
}
if (lp == NULL)
return;
+#endif /* __DARWIN_64_BIT_INO_T */
dirp->dd_loc = 0;
while (dirp->dd_loc < lp->loc_loc) {
- dp = _readdir_unlocked(dirp);
+ dp = _readdir_unlocked(dirp, 0);
if (dp == NULL)
break;
}
/*
* Reclaim memory for telldir cookies which weren't used.
*/
-@@ -131,3 +171,4 @@
+@@ -127,3 +167,4 @@ _reclaim_telldir(dirp)
}
LIST_INIT(&dirp->dd_td->td_locq);
}
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/lib/libc/gen/telldir.h,v 1.2 2001/01/24 12:59:24 deischen Exp $
+ * $FreeBSD: src/lib/libc/gen/telldir.h,v 1.3 2008/05/05 14:05:23 kib Exp $
*/
#ifndef _TELLDIR_H_
long td_loccnt; /* index of entry for sequential readdir's */
};
-struct dirent *_readdir_unlocked(DIR *);
+struct dirent *_readdir_unlocked(DIR *, int);
void _reclaim_telldir(DIR *);
void _seekdir(DIR *, long);
---- telldir.h.orig 2007-01-24 14:10:41.000000000 -0800
-+++ telldir.h 2007-01-25 01:18:29.000000000 -0800
+--- telldir.h.orig 2009-11-08 13:57:20.000000000 -0800
++++ telldir.h 2009-11-08 13:57:11.000000000 -0800
@@ -46,7 +46,11 @@
struct ddloc {
LIST_ENTRY(ddloc) loc_lqe; /* entry in list */
long loc_loc; /* offset of entry in buffer */
};
-@@ -57,10 +61,17 @@
+@@ -57,10 +61,17 @@ struct ddloc {
struct _telldir {
LIST_HEAD(, ddloc) td_locq; /* list of locations */
long td_loccnt; /* index of entry for sequential readdir's */
+#endif /* __DARWIN_64_BIT_INO_T */
};
--struct dirent *_readdir_unlocked(DIR *);
+-struct dirent *_readdir_unlocked(DIR *, int);
+#if __DARWIN_64_BIT_INO_T
+size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep);
+#endif /* __DARWIN_64_BIT_INO_T */
-+struct dirent *_readdir_unlocked(DIR *) __DARWIN_INODE64(_readdir_unlocked);
++struct dirent *_readdir_unlocked(DIR *, int) __DARWIN_INODE64(_readdir_unlocked);
void _reclaim_telldir(DIR *);
-void _seekdir(DIR *, long);
+void _seekdir(DIR *, long) __DARWIN_ALIAS_I(_seekdir);
* 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.
static char sccsid[] = "@(#)termios.c 8.2 (Berkeley) 2/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/termios.c,v 1.13 2002/05/28 16:59:39 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/termios.c,v 1.16 2009/05/07 13:49:48 ed Exp $");
#include "namespace.h"
#include <sys/types.h>
return ((pid_t)s);
}
+pid_t
+tcgetsid(int fd)
+{
+ int s;
+
+ if (_ioctl(fd, TIOCGSID, &s) < 0)
+ return ((pid_t)-1);
+
+ return ((pid_t)s);
+}
+
+int
+tcsetsid(int fd, pid_t pid)
+{
+
+ if (pid != getsid(0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (_ioctl(fd, TIOCSCTTY, NULL));
+}
+
speed_t
cfgetospeed(t)
const struct termios *t;
---- termios.c.orig 2007-03-16 00:36:09.000000000 -0700
-+++ termios.c 2007-03-16 00:45:15.000000000 -0700
-@@ -37,6 +37,14 @@
+--- termios.c.orig 2009-11-08 16:27:01.000000000 -0800
++++ termios.c 2009-11-08 16:28:15.000000000 -0800
+@@ -33,6 +33,14 @@ static char sccsid[] = "@(#)termios.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/termios.c,v 1.13 2002/05/28 16:59:39 alfred Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/termios.c,v 1.16 2009/05/07 13:49:48 ed Exp $");
+#if __DARWIN_UNIX03
+#ifdef VARIANT_CANCELABLE
#include "namespace.h"
#include <sys/types.h>
#include <sys/fcntl.h>
-@@ -48,6 +56,7 @@
+@@ -44,6 +52,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/ter
#include <unistd.h>
#include "un-namespace.h"
int
tcgetattr(fd, t)
int fd;
-@@ -87,6 +96,9 @@
+@@ -83,6 +92,9 @@ tcsetpgrp(int fd, pid_t pgrp)
{
int s;
s = pgrp;
return (_ioctl(fd, TIOCSPGRP, &s));
}
-@@ -97,6 +109,9 @@
+@@ -93,12 +105,16 @@ tcgetpgrp(fd)
{
int s;
if (_ioctl(fd, TIOCGPGRP, &s) < 0)
return ((pid_t)-1);
-@@ -183,17 +198,24 @@
+ return ((pid_t)s);
+ }
+
++#if 0 // Needs API review first
+ pid_t
+ tcgetsid(int fd)
+ {
+@@ -121,6 +137,7 @@ tcsetsid(int fd, pid_t pid)
+
+ return (_ioctl(fd, TIOCSCTTY, NULL));
+ }
++#endif
+
+ speed_t
+ cfgetospeed(t)
+@@ -202,17 +219,24 @@ tcsendbreak(fd, len)
return (-1);
return (0);
}
int
tcflush(fd, which)
int fd, which;
-@@ -230,16 +252,13 @@
+@@ -249,16 +273,13 @@ tcflow(fd, action)
case TCOON:
return (_ioctl(fd, TIOCSTART, 0));
case TCION:
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)time.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/time.3,v 1.13 2004/07/02 19:07:30 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/time.3,v 1.15 2007/01/09 00:27:55 imp Exp $
.\"
.Dd July 18, 2003
.Dt TIME 3
.Nm
function conforms to
.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Fn time
+function appeared in
+.At v6 .
.Sh BUGS
Neither
.St -isoC-99
did not set
.No \&* Ns Va tloc
in the error case.
-.Sh HISTORY
-A
-.Fn time
-function appeared in
-.At v6 .
---- time.3.orig 2004-07-02 12:07:30.000000000 -0700
-+++ time.3 2004-10-24 17:39:18.000000000 -0700
-@@ -53,7 +53,8 @@
+--- time.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ time.3 2009-11-07 14:51:40.000000000 -0800
+@@ -49,7 +49,8 @@ The
.Fn time
function
returns the value of time in seconds since 0 hours, 0 minutes,
* 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.
static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/time.c,v 1.4 2003/07/19 02:53:46 wollman Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/time.c,v 1.5 2007/01/09 00:27:55 imp Exp $");
#include <sys/types.h>
#include <sys/time.h>
---- time.c.orig 2008-07-30 13:29:30.000000000 -0700
-+++ time.c 2008-07-30 13:36:03.000000000 -0700
-@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/tim
+--- time.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ time.c 2009-11-07 14:51:40.000000000 -0800
+@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/tim
#include <sys/types.h>
#include <sys/time.h>
time_t
time(t)
-@@ -46,12 +47,21 @@ time(t)
+@@ -42,12 +43,21 @@ time(t)
{
struct timeval tt;
time_t retval;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)timezone.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/timezone.3,v 1.9 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/timezone.3,v 1.10 2007/01/09 00:27:55 imp Exp $
.\"
.Dd April 19, 1994
.Dt TIMEZONE 3
* 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.
static char sccsid[] = "@(#)timezone.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/timezone.c,v 1.5 2002/02/01 01:08:48 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/timezone.c,v 1.6 2007/01/09 00:27:55 imp Exp $");
#include <sys/types.h>
#include <sys/time.h>
---- ttyname.c.orig 2008-10-09 21:30:31.000000000 -0700
-+++ ttyname.c 2008-10-09 22:00:10.000000000 -0700
-@@ -48,10 +48,12 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/tty
+--- ttyname.c.orig 2010-05-01 19:18:09.000000000 -0700
++++ ttyname.c 2010-05-03 10:18:47.000000000 -0700
+@@ -48,11 +48,14 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/tty
#include <string.h>
#include <paths.h>
#include <pthread.h>
#include "libc_private.h"
+-static char buf[sizeof(_PATH_DEV) + MAXNAMLEN];
+#ifndef BUILDING_VARIANT
- static char buf[sizeof(_PATH_DEV) + MAXNAMLEN];
++static pthread_once_t ttyname_buf_control = PTHREAD_ONCE_INIT;
++static char *buf = NULL;
static char *ttyname_threaded(int fd);
static char *ttyname_unthreaded(int fd);
-@@ -71,31 +73,63 @@ ttyname(int fd)
+
+@@ -71,31 +74,63 @@ ttyname(int fd)
ret = ttyname_threaded(fd);
return (ret);
}
- devname_r(sb.st_rdev, S_IFCHR,
- buf + strlen(buf), sizeof(buf) - strlen(buf));
- return (buf);
-+ strcpy(thrbuf, _PATH_DEV);
++ strlcpy(thrbuf, _PATH_DEV, len);
+ if (devname_r(sb.st_rdev, S_IFCHR,
+ thrbuf + strlen(thrbuf), len - strlen(thrbuf)) == NULL)
+#if __DARWIN_UNIX03
static char *
ttyname_threaded(int fd)
{
-@@ -104,8 +138,12 @@ ttyname_threaded(int fd)
+@@ -104,8 +139,12 @@ ttyname_threaded(int fd)
if (ttyname_init == 0) {
_pthread_mutex_lock(&ttyname_lock);
if (ttyname_init == 0) {
return (NULL);
}
ttyname_init = 1;
-@@ -117,14 +155,20 @@ ttyname_threaded(int fd)
+@@ -117,14 +156,26 @@ ttyname_threaded(int fd)
if ((buf = _pthread_getspecific(ttyname_key)) == NULL) {
if ((buf = malloc(sizeof(_PATH_DEV) + MAXNAMLEN)) != NULL) {
if (_pthread_setspecific(ttyname_key, buf) != 0) {
+#else /* !__DARWIN_UNIX03 */
return (ttyname_r(fd, buf, sizeof(_PATH_DEV) + MAXNAMLEN));
+#endif /* __DARWIN_UNIX03 */
++}
++
++static void
++ttyname_buf_allocate(void)
++{
++ buf = malloc(sizeof(_PATH_DEV) + MAXNAMLEN);
}
static char *
-@@ -137,11 +181,19 @@ ttyname_unthreaded(int fd)
+@@ -137,11 +188,25 @@ ttyname_unthreaded(int fd)
if (tcgetattr(fd, &ttyb) < 0)
return (NULL);
/* Must be a character device. */
- if (_fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
+ if (_fstat(fd, &sb))
- return (NULL);
++ return (NULL);
+ if (!S_ISCHR(sb.st_mode)) {
+ errno = ENOTTY;
+ return (NULL);
++ }
++
++ if (pthread_once(&ttyname_buf_control, ttyname_buf_allocate)
++ || !buf) {
++ errno = ENOMEM;
+ return (NULL);
+ }
- strcpy(buf, _PATH_DEV);
+- strcpy(buf, _PATH_DEV);
- devname_r(sb.st_rdev, S_IFCHR,
- buf + strlen(buf), sizeof(buf) - strlen(buf));
++ strlcpy(buf, _PATH_DEV, sizeof(_PATH_DEV) + MAXNAMLEN);
+ if (devname_r(sb.st_rdev, S_IFCHR,
-+ buf + strlen(buf), sizeof(buf) - strlen(buf)) == NULL) {
++ buf + strlen(buf), sizeof(_PATH_DEV) + MAXNAMLEN - strlen(buf)) == NULL) {
+ errno = ERANGE;
+ return (NULL);
+ }
* 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.
static char sccsid[] = "@(#)ttyslot.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/ttyslot.c,v 1.4 2002/02/01 01:08:48 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/ttyslot.c,v 1.6 2009/02/12 19:00:13 ed Exp $");
+#include <paths.h>
#include <ttyent.h>
#include <stdio.h>
#include <string.h>
{
struct ttyent *ttyp;
int slot;
- char *p;
int cnt;
char *name;
setttyent();
for (cnt = 0; cnt < 3; ++cnt)
if ( (name = ttyname(cnt)) ) {
- if ( (p = rindex(name, '/')) )
- ++p;
- else
- p = name;
+ if (strncmp(name, _PATH_DEV, sizeof _PATH_DEV - 1) != 0)
+ break;
+ name += sizeof _PATH_DEV - 1;
for (slot = 1; (ttyp = getttyent()); ++slot)
- if (!strcmp(ttyp->ty_name, p)) {
+ if (!strcmp(ttyp->ty_name, name)) {
endttyent();
return(slot);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)ualarm.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/ualarm.3,v 1.19 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/ualarm.3,v 1.20 2007/01/09 00:27:56 imp Exp $
.\"
.Dd April 19, 1994
.Dt UALARM 3
---- _SB/Libc/gen/FreeBSD/ualarm.3 2004-11-25 11:38:02.000000000 -0800
-+++ _SB/Libc/gen/FreeBSD/ualarm.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -43,7 +43,10 @@
+--- ualarm.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ ualarm.3 2009-11-07 14:51:40.000000000 -0800
+@@ -39,7 +39,10 @@
.Sh SYNOPSIS
.In unistd.h
.Ft useconds_t
.Sh DESCRIPTION
.Bf -symbolic
This is a simplified interface to
-@@ -54,7 +57,7 @@
+@@ -50,7 +53,7 @@ The
.Fn ualarm
function
waits a count of
before asserting the terminating signal
.Dv SIGALRM .
System activity or time used in processing the call may cause a slight
-@@ -67,17 +70,17 @@
+@@ -63,17 +66,17 @@ argument is non-zero, the
signal will be sent
to the process every
.Fa interval
* 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.
static char sccsid[] = "@(#)ualarm.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/ualarm.c,v 1.4 2002/12/29 00:59:09 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/ualarm.c,v 1.5 2007/01/09 00:27:56 imp Exp $");
#include <sys/time.h>
#include <unistd.h>
---- _SB/Libc/gen/FreeBSD/ulimit.3 2003-05-20 15:21:03.000000000 -0700
-+++ _SB/Libc/gen/FreeBSD/ulimit.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- ulimit.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ ulimit.3 2009-11-07 14:51:39.000000000 -0800
@@ -34,28 +34,31 @@
.Sh SYNOPSIS
.In ulimit.h
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)unvis.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/gen/unvis.3,v 1.17 2004/07/03 22:30:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/unvis.3,v 1.18 2007/01/09 00:27:56 imp Exp $
.\"
.Dd December 11, 1993
.Dt UNVIS 3
* 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.
static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/unvis.c,v 1.9 2004/08/02 08:46:23 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/unvis.c,v 1.10 2007/01/09 00:27:56 imp Exp $");
#include <sys/types.h>
#include <ctype.h>
---- unvis.c.orig 2004-11-25 11:38:02.000000000 -0800
-+++ unvis.c 2005-02-27 01:14:02.000000000 -0800
-@@ -37,6 +37,8 @@
+--- unvis.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ unvis.c 2009-11-07 14:51:40.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)unvis.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/unvis.c,v 1.9 2004/08/02 08:46:23 stefanf Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/unvis.c,v 1.10 2007/01/09 00:27:56 imp Exp $");
+#include "xlocale_private.h"
+
#include <sys/types.h>
#include <ctype.h>
#include <vis.h>
-@@ -64,6 +66,7 @@
+@@ -60,6 +62,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/unv
int
unvis(char *cp, int c, int *astate, int flag)
{
if (flag & UNVIS_END) {
if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
-@@ -90,8 +93,8 @@
+@@ -86,8 +89,8 @@ unvis(char *cp, int c, int *astate, int
case S_START:
if (*astate & S_HTTP) {
*astate = S_HEX2;
return (0);
}
-@@ -216,8 +219,8 @@
+@@ -212,8 +215,8 @@ unvis(char *cp, int c, int *astate, int
return (UNVIS_VALIDPUSH);
case S_HEX2: /* second mandatory hex digit */
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)usleep.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/usleep.3,v 1.18 2002/12/29 00:59:09 mike Exp $
+.\" $FreeBSD: src/lib/libc/gen/usleep.3,v 1.19 2007/01/09 00:27:56 imp Exp $
.\"
.Dd February 13, 1998
.Dt USLEEP 3
---- _SB/Libc/gen/FreeBSD/usleep.3 2004-11-25 11:38:02.000000000 -0800
-+++ _SB/Libc/gen/FreeBSD/usleep.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -37,30 +37,34 @@
+--- usleep.3.orig 2009-11-07 14:51:38.000000000 -0800
++++ usleep.3 2009-11-07 14:51:40.000000000 -0800
+@@ -33,30 +33,34 @@
.Os
.Sh NAME
.Nm usleep
* 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.
static char sccsid[] = "@(#)usleep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/usleep.c,v 1.28 2002/12/29 00:59:09 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/usleep.c,v 1.31 2009/12/05 19:31:38 ed Exp $");
#include "namespace.h"
#include <time.h>
#include "un-namespace.h"
int
-usleep(useconds)
- useconds_t useconds;
+__usleep(useconds_t useconds)
{
struct timespec time_to_sleep;
time_to_sleep.tv_sec = useconds / 1000000;
return (_nanosleep(&time_to_sleep, NULL));
}
+
+__weak_reference(__usleep, usleep);
+__weak_reference(__usleep, _usleep);
---- usleep.c.orig 2007-05-23 18:18:17.000000000 -0700
-+++ usleep.c 2007-05-23 22:15:42.000000000 -0700
-@@ -31,6 +31,11 @@
+--- usleep.c.bsdnew 2009-12-08 00:38:07.000000000 -0800
++++ usleep.c 2009-12-08 00:41:05.000000000 -0800
+@@ -27,6 +27,11 @@
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)usleep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
+@@ -39,7 +44,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/usl
+ #include "un-namespace.h"
+
+ int
+-__usleep(useconds_t useconds)
++usleep(useconds_t useconds)
+ {
+ struct timespec time_to_sleep;
+
+@@ -47,6 +52,3 @@ __usleep(useconds_t useconds)
+ time_to_sleep.tv_sec = useconds / 1000000;
+ return (_nanosleep(&time_to_sleep, NULL));
+ }
+-
+-__weak_reference(__usleep, usleep);
+-__weak_reference(__usleep, _usleep);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)utime.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/utime.3,v 1.11 2002/08/24 00:39:43 mike Exp $
+.\" $FreeBSD: src/lib/libc/gen/utime.3,v 1.14 2007/01/09 00:27:56 imp Exp $
.\"
.Dd June 4, 1993
.Dt UTIME 3
The
.Fn utime
function sets the access and modification times of the named file from
-the structures in the argument array
+the
+.Va actime
+and
+.Va modtime
+fields of the
+.Vt "struct utimbuf"
+pointed at by
.Fa timep .
.Pp
If the times are specified (the
.Sh SEE ALSO
.Xr stat 2 ,
.Xr utimes 2
-.Sh HISTORY
-A
-.Fn utime
-function appeared in
-.At v7 .
.Sh STANDARDS
The
.Fn utime
function conforms to
.St -p1003.1-88 .
+.Sh HISTORY
+A
+.Fn utime
+function appeared in
+.At v7 .
---- _SB/Libc/gen/FreeBSD/utime.3 2003-05-20 15:21:03.000000000 -0700
-+++ _SB/Libc/gen/FreeBSD/utime.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -43,7 +43,10 @@
+--- utime.3.bsdnew 2009-11-08 14:20:21.000000000 -0800
++++ utime.3 2009-11-08 14:32:59.000000000 -0800
+@@ -39,7 +39,10 @@
.Sh SYNOPSIS
.In utime.h
.Ft int
.Sh DESCRIPTION
.Bf -symbolic
This interface is obsoleted by
-@@ -52,22 +55,22 @@
+@@ -48,28 +51,28 @@ This interface is obsoleted by
.Pp
The
.Fn utime
-function sets the access and modification times of the named file from
--the structures in the argument array
--.Fa timep .
+-the
+function sets the access and modification times of the named file,
-+based on the structures in the argument array
++based on the
+ .Va actime
+ and
+ .Va modtime
+ fields of the
+ .Vt "struct utimbuf"
+ pointed at by
+-.Fa timep .
+.Fa times .
.Pp
If the times are specified (the
* 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.
static char sccsid[] = "@(#)utime.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/utime.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/utime.c,v 1.3 2007/01/09 00:27:56 imp Exp $");
#include <sys/time.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)vis.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/gen/vis.3,v 1.26 2004/07/17 12:27:25 tjr Exp $
+.\" $FreeBSD: src/lib/libc/gen/vis.3,v 1.30 2007/01/09 00:27:56 imp Exp $
.\"
-.Dd March 21, 2004
+.Dd April 9, 2006
.Dt VIS 3
.Os
.Sh NAME
Use C-style backslash sequences to represent standard non-printable
characters.
The following sequences are used to represent the indicated characters:
-.Bd -unfilled -offset indent
-.Li \ea Tn - BEL No (007)
-.Li \eb Tn - BS No (010)
-.Li \ef Tn - NP No (014)
-.Li \en Tn - NL No (012)
-.Li \er Tn - CR No (015)
-.Li \et Tn - HT No (011)
-.Li \ev Tn - VT No (013)
-.Li \e0 Tn - NUL No (000)
-.Ed
+.Pp
+.Bl -tag -width ".Li \e0" -offset indent -compact
+.It Li \ea
+.Dv BEL No (007)
+.It Li \eb
+.Dv BS No (010)
+.It Li \ef
+.Dv NP No (014)
+.It Li \en
+.Dv NL No (012)
+.It Li \er
+.Dv CR No (015)
+.It Li \es
+.Dv SP No (040)
+.It Li \et
+.Dv HT No (011)
+.It Li \ev
+.Dv VT No (013)
+.It Li \e0
+.Dv NUL No (000)
+.El
.Pp
When using this format, the
.Fa nextc
* 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.
static char sccsid[] = "@(#)vis.c 8.1 (Berkeley) 7/19/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/vis.c,v 1.13 2003/10/30 12:41:50 phk Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/vis.c,v 1.14 2007/01/09 00:27:56 imp Exp $");
#include <sys/types.h>
#include <limits.h>
---- vis.c.orig 2004-11-25 11:38:02.000000000 -0800
-+++ vis.c 2005-02-24 16:58:00.000000000 -0800
-@@ -37,6 +37,8 @@
+--- vis.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ vis.c 2009-11-07 14:51:40.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)vis.c 8.1 (B
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/gen/vis.c,v 1.13 2003/10/30 12:41:50 phk Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/gen/vis.c,v 1.14 2007/01/09 00:27:56 imp Exp $");
+#include "xlocale_private.h"
+
#include <sys/types.h>
#include <limits.h>
#include <ctype.h>
-@@ -54,18 +56,20 @@
+@@ -50,18 +52,20 @@ vis(dst, c, flag, nextc)
int c, nextc;
int flag;
{
dst += 2;
goto done;
}
-@@ -74,7 +78,7 @@
+@@ -70,7 +74,7 @@ vis(dst, c, flag, nextc)
if ((flag & VIS_GLOB) &&
(c == '*' || c == '?' || c == '[' || c == '#'))
;
((flag & VIS_SP) == 0 && c == ' ') ||
((flag & VIS_TAB) == 0 && c == '\t') ||
((flag & VIS_NL) == 0 && c == '\n') ||
-@@ -130,7 +134,7 @@
+@@ -126,7 +130,7 @@ vis(dst, c, flag, nextc)
goto done;
}
}
*dst++ = '\\';
*dst++ = ((u_char)c >> 6 & 07) + '0';
*dst++ = ((u_char)c >> 3 & 07) + '0';
-@@ -143,7 +147,7 @@
+@@ -139,7 +143,7 @@ vis(dst, c, flag, nextc)
c &= 0177;
*dst++ = 'M';
}
* 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.
static char sccsid[] = "@(#)wait.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/wait.c,v 1.6 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/wait.c,v 1.7 2007/01/09 00:27:56 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
---- wait.c.orig 2006-09-13 16:57:37.000000000 -0700
-+++ wait.c 2006-09-13 17:00:15.000000000 -0700
-@@ -44,10 +44,20 @@
+--- wait.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ wait.c 2009-11-07 14:51:40.000000000 -0800
+@@ -40,10 +40,20 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/wai
#include <sys/resource.h>
#include "un-namespace.h"
* 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.
static char sccsid[] = "@(#)wait3.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/wait3.c,v 1.3 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/wait3.c,v 1.4 2007/01/09 00:27:56 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
* 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.
static char sccsid[] = "@(#)waitpid.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/waitpid.c,v 1.6 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/waitpid.c,v 1.7 2007/01/09 00:27:56 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
---- waitpid.c.orig 2006-09-16 19:12:38.000000000 -0700
-+++ waitpid.c 2006-09-16 20:38:56.000000000 -0700
-@@ -44,10 +44,31 @@
+--- waitpid.c.orig 2009-11-07 14:51:38.000000000 -0800
++++ waitpid.c 2009-11-07 14:51:40.000000000 -0800
+@@ -40,10 +40,31 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/wai
#include <sys/resource.h>
#include "un-namespace.h"
GENMIGSRCS += ${GENMIGDEFS:.defs=User.c}
MISRCS += ${GENMIGSRCS} NSSystemDirectories.c \
- asl.c asl_core.c asl_file.c asl_legacy1.c asl_store.c asl_util.c \
+ asl.c asl_core.c asl_file.c asl_legacy1.c asl_msg.c asl_store.c asl_util.c \
+ assumes.c \
backtrace.c \
cache.c confstr.c crypt.c devname.c disklabel.c errlst.c \
filesec.c fts.c \
isinf.c isnan.c \
malloc.c nanosleep.c nftw.c magazine_malloc.c setlogin.c \
sigsetops.c _simple.c stack_logging.c stack_logging_disk.c strtofflags.c syslog.c \
- thread_stack_pcs.c uname.c utmpx-darwin.c wordexp.c
+ thread_stack_pcs.c uname.c utmpx-darwin.c wordexp.c \
+ platfunc.c
.ifdef FEATURE_LEGACY_NXZONE_APIS
MISRCS += zone.c
magazine_malloc.${OBJSUFFIX}: ${SYMROOTINC}/magmallocProvider.h
malloc.${OBJSUFFIX}: ${SYMROOTINC}/magmallocProvider.h
-# Force these files to build after the mig stuff
-asl.${OBJSUFFIX}: asl_ipcUser.c
-syslog.${OBJSUFFIX}: asl_ipcUser.c
-utmpx-darwin.${OBJSUFFIX}: asl_ipcUser.c
+# Force the ASL-related mig files to build first
+BUILDFIRST += asl_ipcUser.c
CLEANFILES += ${GENMIGHDRS} ${GENMIGSRCS} ${GENMIGDEFS:.defs=Server.c}
-LOCALHDRS += ${.CURDIR}/gen/asl_core.h ${.CURDIR}/gen/asl_file.h ${.CURDIR}/gen/asl_legacy1.h \
- ${.CURDIR}/gen/asl_private.h ${.CURDIR}/gen/asl_store.h \
- ${.CURDIR}/gen/_simple.h ${.CURDIR}/gen/stack_logging.h
+LOCALHDRS += \
+ ${.CURDIR}/gen/asl_core.h \
+ ${.CURDIR}/gen/asl_file.h \
+ ${.CURDIR}/gen/asl_ipc.defs \
+ ${.CURDIR}/gen/asl_legacy1.h \
+ ${.CURDIR}/gen/asl_msg.h \
+ ${.CURDIR}/gen/asl_private.h \
+ ${.CURDIR}/gen/asl_store.h \
+ ${.CURDIR}/gen/assumes.h \
+ ${.CURDIR}/gen/_simple.h \
+ ${.CURDIR}/gen/stack_logging.h \
+ ${.CURDIR}/gen/utmpx_thread.h
CFLAGS-asl_file.c += -D_DARWIN_UNLIMITED_STREAMS
CFLAGS-asl_legacy1.c += -D_DARWIN_UNLIMITED_STREAMS
+CFLAGS-asl_msg.c += -D_DARWIN_UNLIMITED_STREAMS
CFLAGS-asl_store.c += -D_DARWIN_UNLIMITED_STREAMS
CFLAGS-confstr.c += -I${.CURDIR}/darwin
CFLAGS-fmtmsg-fbsd.c += -D_DARWIN_UNLIMITED_STREAMS
.include "Makefile.fbsd_begin"
FBSDMISRCS = _rand48.c alarm.c arc4random.c assert.c \
basename.c clock.c closedir.c ctermid.c \
- daemon.c dirname.c drand48.c erand48.c err.c errno_.c exec.c \
+ daemon.c dirname.c drand48.c erand48.c err.c exec.c \
fmtcheck.c fmtmsg.c fnmatch.c ftok.c \
getbsize.c getcap.c getcwd.c gethostname.c getpeereid.c \
getlogin.c getmntinfo.c getpagesize.c getprogname.c glob.c isatty.c \
usleep.c wait.c waitpid.c
CANCELABLE-DARWINEXTSNSRCS += pselect.c
DARWINEXTSNSRCS += popen.c pselect.c
-DYLDSRCS += _simple.c
+
+DYLDSRCS += \
+ _simple.c \
+ arc4random.c \
+ closedir.c \
+ getcwd.c \
+ getpagesize.c \
+ nanosleep.c \
+ opendir.c \
+ readdir.c \
+ scandir.c \
+ sysctl.c \
+ sysctlbyname.c \
+ telldir.c \
+ usleep.c
# include __dirent.h to rename DIR structure elements
.for _src in closedir-fbsd.c opendir-fbsd.c readdir-fbsd.c rewinddir-fbsd.c \
.include "Makefile.nbsd_end"
MLINKS+= arc4random.3 arc4random_addrandom.3 \
- arc4random.3 arc4random_stir.3
+ arc4random.3 arc4random_buf.3 \
+ arc4random.3 arc4random_stir.3 \
+ arc4random.3 arc4random_uniform.3
MLINKS+= asl.3 asl_add_log_file.3 \
asl.3 asl_close.3 \
#include <string.h>
#include <sys/param.h>
#include <unistd.h>
+#include <pthread.h>
#define NSUserDomainIndex 0
#define NSLocalDomainIndex 1
},
{ // NSCachesDirectory
1,
- (const void * const * const)prefixAll,
+ (const void * const * const)prefixNoNetwork,
(const void * const)NSCachesDirectoryBase
},
{ // NSApplicationSupportDirectory
},
{ // NSInputMethodsDirectory
1,
- (const void * const * const)prefixAll,
+ (const void * const * const)prefixAllSystem,
(const void * const)NSInputMethodsDirectoryBase
},
{ // NSMoviesDirectory
return (dir << DirShift) + domainMask;
}
+static const char *nextRoot = NULL;
+static pthread_once_t nextRoot_init_once = PTHREAD_ONCE_INIT;
+
+static void
+nextRoot_init(void)
+{
+ if (!issetugid() && (nextRoot = getenv("NEXT_ROOT")) != NULL) {
+ nextRoot = strdup(nextRoot);
+ }
+ if (nextRoot == NULL) {
+ nextRoot = "";
+ }
+}
+
NSSearchPathEnumerationState NSGetNextSearchPathEnumeration(NSSearchPathEnumerationState state, char *path) {
- static const char *nextRoot = NULL;
int dir = (state >> DirShift) & ByteMask;
int domainMask = state & DomainMask;
int domain, i, n;
}
if (addNextRoot(prefix)) {
- if (nextRoot == NULL) { // Get NEXT_ROOT
- if (!issetugid() && (nextRoot = getenv("NEXT_ROOT")) != NULL) {
- nextRoot = strdup(nextRoot);
- }
- if (nextRoot == NULL) {
- nextRoot = "";
- }
- }
+ if (pthread_once(&nextRoot_init_once, nextRoot_init) != 0 || nextRoot == NULL)// Error
+ return 0;
strlcpy(path, nextRoot, PATH_MAX);
} else {
*path = 0;
-.\" $NetBSD: endutxent.3,v 1.4 2004/05/04 02:38:35 atatat Exp $
+.\" $NetBSD: endutxent.3,v 1.5 2008/04/30 13:10:50 martin Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
---- endutxent.3.orig 2007-04-08 18:49:40.000000000 -0700
-+++ endutxent.3 2007-04-08 19:03:43.000000000 -0700
+--- endutxent.3.orig 2009-04-03 22:48:14.000000000 -0700
++++ endutxent.3 2009-04-04 18:16:44.000000000 -0700
@@ -34,7 +34,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
+.El
+.Ss Other extensions to the standards
+The
-+.Fa ut_tv
++.Fa ut_type
+value may also be OR-ed with the following masks:
+.Bl -tag -width XXXX -compact -offset indent
+.It Dv UTMPX_AUTOFILL_MASK
-+Depending on the
++Depending on the main part of
+.Fa ut_type
+value, other fields are automatically filled in (as specified in the
+meaningful fields table above).
-.\" $NetBSD: getlastlogx.3,v 1.1 2003/08/26 17:37:51 wiz Exp $
+.\" $NetBSD: getlastlogx.3,v 1.2 2008/04/30 13:10:50 martin Exp $
.\"
.\" Copyright (c) 2003 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
-.\" $NetBSD: utmpx.5,v 1.2 2003/04/16 13:35:24 wiz Exp $
+.\" $NetBSD: utmpx.5,v 1.7 2008/04/30 13:10:57 martin Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd September 26, 2002
+.Dd January 31, 2007
.Dt UTMPX 5
.Os
.Sh NAME
.Sh SYNOPSIS
.In utmpx.h
.Sh DESCRIPTION
+In contrast to
+.Pa utmp
+and
+.Pa wtmp ,
+the extended databases in
+.Pa utmpx
+and
+.Pa wtmpx
+reserve more space for logging hostnames, and also
+information on a process' ID, termination signal and exit status.
+.Pp
The
.Aq Pa utmpx.h
header defines the structures and functions for logging user.
.Pa /var/log/wtmpx ,
and the last login of each user is noted in
.Pa /var/log/lastlogx .
-The files are not automatically created if they do not exist; they
-must be created manually.
.Pp
The interface to the
.Nm utmpx
file is described in
-.Xr endutxent 3 .
+.Xr getutxent 3 .
.Pp
The
.Nm wtmpx
.Xr who 1 ,
.Xr endutxent 3 ,
.Xr logwtmpx 3 ,
+.Xr utmp 5 ,
.Xr ac 8 ,
.Xr init 8 ,
.Xr newsyslog 8 ,
---- utmpx.5.orig 2004-09-20 17:32:52.000000000 -0700
-+++ utmpx.5 2005-12-26 11:25:30.000000000 -0800
-@@ -34,13 +34,11 @@
- .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- .\" POSSIBILITY OF SUCH DAMAGE.
- .\"
--.Dd September 26, 2002
-+.Dd Dec 26, 2005
+--- utmpx.5.orig 2009-11-06 10:28:19.000000000 -0800
++++ utmpx.5 2009-11-06 10:29:23.000000000 -0800
+@@ -31,9 +31,7 @@
.Dt UTMPX 5
.Os
.Sh NAME
.Nd user accounting database
.Sh SYNOPSIS
.In utmpx.h
-@@ -49,89 +47,51 @@
+@@ -53,88 +51,51 @@ The
.Aq Pa utmpx.h
header defines the structures and functions for logging user.
Currently logged in users are tracked in
-.Pa /var/log/wtmpx ,
-and the last login of each user is noted in
-.Pa /var/log/lastlogx .
--The files are not automatically created if they do not exist; they
--must be created manually.
-.Pp
+.Pa /var/run/utmpx .
The interface to the
.Nm utmpx
file is described in
- .Xr endutxent 3 .
+-.Xr getutxent 3 .
++.Xr endutxent 3 .
+The file is not automatically created if they do not exist; it
+must be created manually.
.Pp
+.Xr asl 3 ,
.Xr endutxent 3 ,
-.Xr logwtmpx 3 ,
+-.Xr utmp 5 ,
-.Xr ac 8 ,
-.Xr init 8 ,
-.Xr newsyslog 8 ,
-/* $NetBSD: utmpx.c,v 1.21 2003/09/06 16:42:10 wiz Exp $ */
+/* $NetBSD: utmpx.c,v 1.25 2008/04/28 20:22:59 martin Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* 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
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: utmpx.c,v 1.21 2003/09/06 16:42:10 wiz Exp $");
+__RCSID("$NetBSD: utmpx.c,v 1.25 2008/04/28 20:22:59 martin Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include <string.h>
#include <unistd.h>
#include <utmp.h>
-/* don't define earlier, has side effects in fcntl.h */
-#define __LIBC12_SOURCE__
#include <utmpx.h>
#include <vis.h>
-__warn_references(getlastlogx,
- "warning: reference to compatibility getlastlogx(); include <utmpx.h> for correct reference")
-__warn_references(lastlogxname,
- "warning: reference to deprecated lastlogxname()")
-
static FILE *fp;
static int readonly = 0;
static struct utmpx ut;
static char utfile[MAXPATHLEN] = _PATH_UTMPX;
-static char llfile[MAXPATHLEN] = _PATH_LASTLOGX;
static struct utmpx *utmp_update(const struct utmpx *);
case 0:
(void)execl(_PATH_UTMP_UPDATE,
strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
- exit(1);
+ _exit(1);
/*NOTREACHED*/
case -1:
return NULL;
ux->ut_exit.e_exit = 0;
}
-int
-lastlogxname(const char *fname)
-{
- size_t len;
-
- _DIAGASSERT(fname != NULL);
-
- len = strlen(fname);
-
- if (len >= sizeof(llfile))
- return 0;
-
- /* must end in x! */
- if (fname[len - 1] != 'x')
- return 0;
-
- (void)strlcpy(llfile, fname, sizeof(llfile));
- return 1;
-}
-
-struct lastlogx *
-getlastlogx(uid_t uid, struct lastlogx *ll)
-{
-
- return __getlastlogx13(_PATH_LASTLOGX, uid, ll);
-}
-
struct lastlogx *
-__getlastlogx13(const char *fname, uid_t uid, struct lastlogx *ll)
+getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
{
DBT key, data;
DB *db;
_DIAGASSERT(fname != NULL);
_DIAGASSERT(ll != NULL);
- db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0, DB_HASH, NULL);
+ db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0644, DB_HASH, NULL);
if (db == NULL)
return -1;
---- utmpx.c.orig 2009-04-01 04:01:12.000000000 -0700
-+++ utmpx.c 2009-04-01 04:09:50.000000000 -0700
-@@ -49,48 +49,57 @@ __RCSID("$NetBSD: utmpx.c,v 1.21 2003/09
+--- utmpx.c.orig 2010-06-24 19:43:32.000000000 -0700
++++ utmpx.c 2010-06-29 11:25:57.000000000 -0700
+@@ -42,111 +42,240 @@ __RCSID("$NetBSD: utmpx.c,v 1.25 2008/04
#include <sys/time.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-+#ifdef LEGACY_UTMP_APIS
++#ifdef UNIFDEF_LEGACY_UTMP_APIS
#include <utmp.h>
--/* don't define earlier, has side effects in fcntl.h */
--#define __LIBC12_SOURCE__
-+#endif /* LEGACY_UTMP_APIS */
++#endif /* UNIFDEF_LEGACY_UTMP_APIS */
#include <utmpx.h>
+#include <utmpx-darwin.h>
+#include <errno.h>
#include <vis.h>
--
--__warn_references(getlastlogx,
-- "warning: reference to compatibility getlastlogx(); include <utmpx.h> for correct reference")
--__warn_references(lastlogxname,
-- "warning: reference to deprecated lastlogxname()")
+#include <notify.h>
- static FILE *fp;
- static int readonly = 0;
- static struct utmpx ut;
- static char utfile[MAXPATHLEN] = _PATH_UTMPX;
--static char llfile[MAXPATHLEN] = _PATH_LASTLOGX;
-+__private_extern__ int utfile_system = 1; /* are we using _PATH_UTMPX? */
-+__private_extern__ pthread_mutex_t utmpx_mutex = PTHREAD_MUTEX_INITIALIZER;
+-static FILE *fp;
+-static int readonly = 0;
+-static struct utmpx ut;
+-static char utfile[MAXPATHLEN] = _PATH_UTMPX;
++/* This is the default struct _utmpx shared by the POSIX APIs */
++__private_extern__
++struct _utmpx __utx__ = {
++ __UTX_MAGIC__, /* magic */
++ {}, /* ut */
++ PTHREAD_MUTEX_INITIALIZER, /* utmpx_mutex */
++ _PATH_UTMPX, /* utfile */
++ NULL, /* fp */
++ 1, /* utfile_system */
++ 0, /* readonly */
++};
++
++static struct utmpx *__getutxid(struct _utmpx *, const struct utmpx *);
-static struct utmpx *utmp_update(const struct utmpx *);
-+static struct utmpx *_getutxid(const struct utmpx *);
-
--static const char vers[] = "utmpx-1.00";
+__private_extern__ const char _utmpx_vers[] = "utmpx-1.00";
--void
--setutxent()
+-static const char vers[] = "utmpx-1.00";
+__private_extern__ void
-+_setutxent()
- {
-
- (void)memset(&ut, 0, sizeof(ut));
- if (fp == NULL)
- return;
++__setutxent(struct _utmpx *U)
++{
++
++ (void)memset(&U->ut, 0, sizeof(U->ut));
++ if (U->fp == NULL)
++ return;
+#ifdef __LP64__
-+ (void)fseeko(fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
++ (void)fseeko(U->fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
+#else /* __LP64__ */
- (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
++ (void)fseeko(U->fp, (off_t)sizeof(U->ut), SEEK_SET);
+#endif /* __LP64__ */
++}
+
+ void
+-setutxent()
++_setutxent(struct _utmpx *U)
+ {
+
+- (void)memset(&ut, 0, sizeof(ut));
+- if (fp == NULL)
+- return;
+- (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
++ TEST_UTMPX_T("_setutxent", U);
++ UTMPX_LOCK(U);
++ __setutxent(U);
++ UTMPX_UNLOCK(U);
}
void
-endutxent()
+setutxent()
-+{
-+ UTMPX_LOCK;
-+ _setutxent();
-+ UTMPX_UNLOCK;
+ {
++ _setutxent(&__utx__);
+}
+
-+
-+__private_extern__ void
-+_endutxent()
- {
- (void)memset(&ut, 0, sizeof(ut));
-@@ -102,9 +111,21 @@ endutxent()
+- (void)memset(&ut, 0, sizeof(ut));
+- if (fp != NULL) {
+- (void)fclose(fp);
+- fp = NULL;
+- readonly = 0;
++__private_extern__ void
++__endutxent(struct _utmpx *U)
++{
++ (void)memset(&U->ut, 0, sizeof(U->ut));
++ if (U->fp != NULL) {
++ int saveerrno = errno;
++ (void)fclose(U->fp);
++ errno = saveerrno;
++ U->fp = NULL;
++ U->readonly = 0;
+ }
}
-struct utmpx *
-getutxent()
+void
-+endutxent()
++_endutxent(struct _utmpx *U)
{
-+ UTMPX_LOCK;
-+ _endutxent();
-+ UTMPX_UNLOCK;
++ TEST_UTMPX_T("_endutxent", U);
++ UTMPX_LOCK(U);
++ __endutxent(U);
++ UTMPX_UNLOCK(U);
++}
+
+- if (fp == NULL) {
++
++void
++endutxent()
++{
++ _endutxent(&__utx__);
+}
+
+
-+static struct utmpx *
-+_getutxent()
++__private_extern__ struct utmpx *
++__getutxent(struct _utmpx *U)
+{
++ int saveerrno;
+#ifdef __LP64__
+ struct utmpx32 ut32;
+#endif /* __LP64__ */
-
- if (fp == NULL) {
++
++ if (U->fp == NULL) {
struct stat st;
-@@ -116,7 +137,8 @@ getutxent()
+
+- if ((fp = fopen(utfile, "r+")) == NULL)
+- if ((fp = fopen(utfile, "w+")) == NULL) {
+- if ((fp = fopen(utfile, "r")) == NULL)
++ if ((U->fp = fopen(U->utfile, "r+")) == NULL)
++ if ((U->fp = fopen(U->utfile, "w+")) == NULL) {
++ if ((U->fp = fopen(U->utfile, "r")) == NULL)
+ goto fail;
else
- readonly = 1;
+- readonly = 1;
++ U->readonly = 1;
}
-
+
-+ fcntl(fileno(fp), F_SETFD, 1); /* set close-on-exec flag */
++ fcntl(fileno(U->fp), F_SETFD, 1); /* set close-on-exec flag */
/* get file size in order to check if new file */
- if (fstat(fileno(fp), &st) == -1)
-@@ -124,27 +146,51 @@ getutxent()
+- if (fstat(fileno(fp), &st) == -1)
++ if (fstat(fileno(U->fp), &st) == -1)
+ goto failclose;
if (st.st_size == 0) {
/* new file, add signature record */
+- (void)memset(&ut, 0, sizeof(ut));
+- ut.ut_type = SIGNATURE;
+- (void)memcpy(ut.ut_user, vers, sizeof(vers));
+- if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
+#ifdef __LP64__
+ (void)memset(&ut32, 0, sizeof(ut32));
+ ut32.ut_type = SIGNATURE;
+ (void)memcpy(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
-+ if (fwrite(&ut32, sizeof(ut32), 1, fp) != 1)
++ if (fwrite(&ut32, sizeof(ut32), 1, U->fp) != 1)
+#else /* __LP64__ */
- (void)memset(&ut, 0, sizeof(ut));
- ut.ut_type = SIGNATURE;
-- (void)memcpy(ut.ut_user, vers, sizeof(vers));
-+ (void)memcpy(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
- if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
++ (void)memset(&U->ut, 0, sizeof(U->ut));
++ U->ut.ut_type = SIGNATURE;
++ (void)memcpy(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
++ if (fwrite(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
+#endif /* __LP64__ */
goto failclose;
} else {
/* old file, read signature record */
+- if (fread(&ut, sizeof(ut), 1, fp) != 1)
+#ifdef __LP64__
-+ if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
++ if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
+#else /* __LP64__ */
- if (fread(&ut, sizeof(ut), 1, fp) != 1)
++ if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
+#endif /* __LP64__ */
goto failclose;
- if (memcmp(ut.ut_user, vers, sizeof(vers)) != 0 ||
+- ut.ut_type != SIGNATURE)
+#ifdef __LP64__
+ if (memcmp(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
+ ut32.ut_type != SIGNATURE)
+#else /* __LP64__ */
-+ if (memcmp(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
- ut.ut_type != SIGNATURE)
++ if (memcmp(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
++ U->ut.ut_type != SIGNATURE)
+#endif /* __LP64__ */
++ {
++ errno = EINVAL;
goto failclose;
++ }
}
}
+- if (fread(&ut, sizeof(ut), 1, fp) != 1)
+#ifdef __LP64__
-+ if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
++ if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
+#else /* __LP64__ */
- if (fread(&ut, sizeof(ut), 1, fp) != 1)
++ if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
+#endif /* __LP64__ */
goto fail;
+- return &ut;
+#ifdef __LP64__
-+ _utmpx32_64(&ut32, &ut);
++ _utmpx32_64(&ut32, &U->ut);
+#endif /* __LP64__ */
- return &ut;
++ return &U->ut;
failclose:
- (void)fclose(fp);
-+ fp = NULL;
+- (void)fclose(fp);
++ saveerrno = errno;
++ (void)fclose(U->fp);
++ errno = saveerrno;
++ U->fp = NULL;
fail:
- (void)memset(&ut, 0, sizeof(ut));
+- (void)memset(&ut, 0, sizeof(ut));
++ (void)memset(&U->ut, 0, sizeof(U->ut));
return NULL;
-@@ -152,14 +198,45 @@ fail:
+ }
struct utmpx *
-+getutxent()
-+{
+-getutxid(const struct utmpx *utx)
++_getutxent(struct _utmpx *U)
+ {
+ struct utmpx *ret;
-+ UTMPX_LOCK;
-+ ret = _getutxent();
-+ UTMPX_UNLOCK;
++
++ TEST_UTMPX_T("_getutxent", U);
++ UTMPX_LOCK(U);
++ ret = __getutxent(U);
++ UTMPX_UNLOCK(U);
+ return ret;
+}
+
++
+struct utmpx *
- getutxid(const struct utmpx *utx)
- {
++getutxent()
++{
++ return _getutxent(&__utx__);
++}
+
+- _DIAGASSERT(utx != NULL);
++
++struct utmpx *
++_getutxid(struct _utmpx *U, const struct utmpx *utx)
++{
+ struct utmpx temp;
+ const struct utmpx *ux;
+ struct utmpx *ret;
- _DIAGASSERT(utx != NULL);
-
if (utx->ut_type == EMPTY)
return NULL;
-+ UTMPX_LOCK;
++ TEST_UTMPX_T("_getutxid", U);
++ UTMPX_LOCK(U);
+ /* make a copy as needed, and auto-fill if requested */
+ ux = _utmpx_working_copy(utx, &temp, 1);
+ if (!ux) {
-+ UTMPX_UNLOCK;
++ UTMPX_UNLOCK(U);
+ return NULL;
+ }
+
-+ ret = _getutxid(ux);
-+ UTMPX_UNLOCK;
++ ret = __getutxid(U, ux);
++ UTMPX_UNLOCK(U);
+ return ret;
+}
+
+
++struct utmpx *
++getutxid(const struct utmpx *utx)
++{
++ return _getutxid(&__utx__, utx);
++}
++
++
+static struct utmpx *
-+_getutxid(const struct utmpx *utx)
++__getutxid(struct _utmpx *U, const struct utmpx *utx)
+{
+
do {
- if (ut.ut_type == EMPTY)
+- if (ut.ut_type == EMPTY)
++ if (U->ut.ut_type == EMPTY)
continue;
-@@ -193,7 +270,7 @@ getutxid(const struct utmpx *utx)
+ switch (utx->ut_type) {
+ case EMPTY:
+@@ -155,21 +284,21 @@ getutxid(const struct utmpx *utx)
+ case BOOT_TIME:
+ case OLD_TIME:
+ case NEW_TIME:
+- if (ut.ut_type == utx->ut_type)
+- return &ut;
++ if (U->ut.ut_type == utx->ut_type)
++ return &U->ut;
+ break;
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case USER_PROCESS:
+ case DEAD_PROCESS:
+- switch (ut.ut_type) {
++ switch (U->ut.ut_type) {
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case USER_PROCESS:
+ case DEAD_PROCESS:
+- if (memcmp(ut.ut_id, utx->ut_id,
+- sizeof(ut.ut_id)) == 0)
+- return &ut;
++ if (memcmp(U->ut.ut_id, utx->ut_id,
++ sizeof(U->ut.ut_id)) == 0)
++ return &U->ut;
+ break;
+ default:
+ break;
+@@ -178,188 +307,253 @@ getutxid(const struct utmpx *utx)
default:
return NULL;
}
- } while (getutxent() != NULL);
-+ } while (_getutxent() != NULL);
++ } while (__getutxent(U) != NULL);
return NULL;
}
-@@ -204,6 +281,7 @@ getutxline(const struct utmpx *utx)
- _DIAGASSERT(utx != NULL);
-
-+ UTMPX_LOCK;
+-struct utmpx *
+-getutxline(const struct utmpx *utx)
++static struct utmpx *
++__getutxline(struct _utmpx *U, const struct utmpx *utx)
+ {
+-
+- _DIAGASSERT(utx != NULL);
+-
do {
- switch (ut.ut_type) {
+- switch (ut.ut_type) {
++ switch (U->ut.ut_type) {
case EMPTY:
-@@ -211,13 +289,16 @@ getutxline(const struct utmpx *utx)
+ break;
case LOGIN_PROCESS:
case USER_PROCESS:
- if (strncmp(ut.ut_line, utx->ut_line,
+- if (strncmp(ut.ut_line, utx->ut_line,
- sizeof(ut.ut_line)) == 0)
-+ sizeof(ut.ut_line)) == 0) {
-+ UTMPX_UNLOCK;
- return &ut;
-+ }
+- return &ut;
++ if (strncmp(U->ut.ut_line, utx->ut_line,
++ sizeof(U->ut.ut_line)) == 0)
++ return &U->ut;
break;
default:
break;
}
- } while (getutxent() != NULL);
-+ } while (_getutxent() != NULL);
-+ UTMPX_UNLOCK;
++ } while (__getutxent(U) != NULL);
return NULL;
}
-@@ -225,156 +306,180 @@ getutxline(const struct utmpx *utx)
+
struct utmpx *
- pututxline(const struct utmpx *utx)
+-pututxline(const struct utmpx *utx)
++_getutxline(struct _utmpx *U, const struct utmpx *utx)
++{
++ struct utmpx *ret;
++
++ TEST_UTMPX_T("_getutxline", U);
++ UTMPX_LOCK(U);
++ ret = __getutxline(U, utx);
++ UTMPX_UNLOCK(U);
++ return ret;
++}
++
++
++struct utmpx *
++getutxline(const struct utmpx *utx)
{
- struct utmpx temp, *u = NULL;
- int gotlock = 0;
-+ struct utmpx *ux;
++ return _getutxline(&__utx__, utx);
++}
- _DIAGASSERT(utx != NULL);
+- _DIAGASSERT(utx != NULL);
- if (utx == NULL)
++struct utmpx *
++_pututxline(struct _utmpx *U, const struct utmpx *utx)
++{
++ struct utmpx *ux;
++
+ if (utx == NULL) {
+ errno = EINVAL;
return NULL;
- if (strcmp(_PATH_UTMPX, utfile) == 0)
- if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0))
- return utmp_update(utx);
--
-+ UTMPX_LOCK;
-+ if ((ux = _pututxline(utx)) != NULL && utfile_system) {
++ TEST_UTMPX_T("_pututxline", U);
++ UTMPX_LOCK(U);
++ if ((ux = __pututxline(&__utx__, utx)) != NULL && __utx__.utfile_system) {
+ _utmpx_asl(ux); /* the equivalent of wtmpx and lastlogx */
+#ifdef UTMP_COMPAT
+ _write_utmp_compat(ux);
+#endif /* UTMP_COMPAT */
+ }
-+ UTMPX_UNLOCK;
++ UTMPX_UNLOCK(U);
+ return ux;
+}
+
- (void)memcpy(&temp, utx, sizeof(temp));
++struct utmpx *
++pututxline(const struct utmpx *utx)
++{
++ return _pututxline(&__utx__, utx);
++}
++
+__private_extern__ struct utmpx *
-+_pututxline(const struct utmpx *utx)
++__pututxline(struct _utmpx *U, const struct utmpx *utx)
+{
+ struct utmpx temp, *u = NULL, *x;
+ const struct utmpx *ux;
+#define gotlock (fl.l_start >= 0)
+
+ fl.l_start = -1; /* also means we haven't locked */
-+ if (utfile_system)
-+ if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0)) {
++ if (U->utfile_system)
++ if ((U->fp != NULL && U->readonly) || (U->fp == NULL && geteuid() != 0)) {
+ errno = EPERM;
+ return NULL;
+ }
- if (fp == NULL) {
+- if (fp == NULL) {
- (void)getutxent();
- if (fp == NULL || readonly)
-+ (void)_getutxent();
-+ if (fp == NULL || readonly) {
++ if (U->fp == NULL) {
++ (void)__getutxent(U);
++ if (U->fp == NULL || U->readonly) {
+ errno = EPERM;
return NULL;
+ }
+ if (!ux)
+ return NULL;
+
-+ if ((x = _getutxid(ux)) == NULL) {
-+ _setutxent();
-+ if ((x = _getutxid(ux)) == NULL) {
++ if ((x = __getutxid(U, ux)) == NULL) {
++ __setutxent(U);
++ if ((x = __getutxid(U, ux)) == NULL) {
+ /*
+ * utx->ut_type has any original mask bits, while
+ * ux->ut_type has those mask bits removed. If we
+ if (ux->ut_type == DEAD_PROCESS &&
+ (utx->ut_type & UTMPX_DEAD_IF_CORRESPONDING_MASK)) {
+ errno = EINVAL;
-+ return NULL;
+ return NULL;
+- gotlock++;
+- if (fseeko(fp, (off_t)0, SEEK_END) == -1)
+ }
+ /*
+ * Replace lockf() with fcntl() and a fixed start
+ * value. We should already be at EOF.
+ */
-+ if ((fl.l_start = lseek(fileno(fp), 0, SEEK_CUR)) < 0)
++ if ((fl.l_start = lseek(fileno(U->fp), 0, SEEK_CUR)) < 0)
+ return NULL;
+ fl.l_len = 0;
+ fl.l_whence = SEEK_SET;
+ fl.l_type = F_WRLCK;
-+ if (fcntl(fileno(fp), F_SETLKW, &fl) == -1)
- return NULL;
-- gotlock++;
- if (fseeko(fp, (off_t)0, SEEK_END) == -1)
++ if (fcntl(fileno(U->fp), F_SETLKW, &fl) == -1)
++ return NULL;
++ if (fseeko(U->fp, (off_t)0, SEEK_END) == -1)
goto fail;
}
}
+ return NULL;
+ }
/* we are not appending */
+- if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
+#ifdef __LP64__
-+ if (fseeko(fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
++ if (fseeko(U->fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
+#else /* __LP64__ */
- if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
++ if (fseeko(U->fp, -(off_t)sizeof(U->ut), SEEK_CUR) == -1)
+#endif /* __LP64__ */
return NULL;
}
- if (fwrite(&temp, sizeof (temp), 1, fp) != 1)
+#ifdef __LP64__
+ _utmpx64_32(ux, &ut32);
-+ if (fwrite(&ut32, sizeof (ut32), 1, fp) != 1)
++ if (fwrite(&ut32, sizeof (ut32), 1, U->fp) != 1)
+#else /* __LP64__ */
-+ if (fwrite(ux, sizeof (*ux), 1, fp) != 1)
++ if (fwrite(ux, sizeof (*ux), 1, U->fp) != 1)
+#endif /* __LP64__ */
goto fail;
- if (fflush(fp) == -1)
+- if (fflush(fp) == -1)
++ if (fflush(U->fp) == -1)
goto fail;
- u = memcpy(&ut, &temp, sizeof(ut));
-+ u = memcpy(&ut, ux, sizeof(ut));
++ u = memcpy(&U->ut, ux, sizeof(U->ut));
+ notify_post(UTMPX_CHANGE_NOTIFICATION);
fail:
if (gotlock) {
- if (lockf(fileno(fp), F_ULOCK, (off_t)0) == -1)
+ int save = errno;
+ fl.l_type = F_UNLCK;
-+ if (fcntl(fileno(fp), F_SETLK, &fl) == -1)
++ if (fcntl(fileno(U->fp), F_SETLK, &fl) == -1)
return NULL;
+ errno = save;
}
- case 0:
- (void)execl(_PATH_UTMP_UPDATE,
- strrchr(_PATH_UTMP_UPDATE, '/') + 1, buf, NULL);
-- exit(1);
+- _exit(1);
- /*NOTREACHED*/
- case -1:
- return NULL;
/*
* The following are extensions and not part of the X/Open spec.
*/
- int
+-int
-updwtmpx(const char *file, const struct utmpx *utx)
-{
- int fd;
-
-
-int
- utmpxname(const char *fname)
+-utmpxname(const char *fname)
++__private_extern__ int
++__utmpxname(struct _utmpx *U, const char *fname)
{
size_t len;
- _DIAGASSERT(fname != NULL);
-+ UTMPX_LOCK;
+ if (fname == NULL) {
-+ strcpy(utfile, _PATH_UTMPX);
-+ utfile_system = 1;
-+ _endutxent();
-+ UTMPX_UNLOCK;
++ if(!U->utfile_system)
++ free(U->utfile);
++ U->utfile = _PATH_UTMPX;
++ U->utfile_system = 1;
++ __endutxent(U);
+ return 1;
+ }
len = strlen(fname);
- if (len >= sizeof(utfile))
-+ if (len >= sizeof(utfile)) {
-+ UTMPX_UNLOCK;
++ if (len >= MAXPATHLEN)
return 0;
-+ }
/* must end in x! */
-- if (fname[len - 1] != 'x')
-+ if (fname[len - 1] != 'x') {
-+ UTMPX_UNLOCK;
+ if (fname[len - 1] != 'x')
return 0;
-+ }
- (void)strlcpy(utfile, fname, sizeof(utfile));
+- (void)strlcpy(utfile, fname, sizeof(utfile));
- endutxent();
-+ _endutxent();
-+ utfile_system = 0;
-+ UTMPX_UNLOCK;
++ if (U->utfile_system)
++ U->utfile = NULL;
++ U->utfile_system = 0;
++ if ((U->utfile = reallocf(U->utfile, len + 1)) == NULL)
++ return 0;
++
++ (void)strcpy(U->utfile, fname);
++ __endutxent(U);
return 1;
}
--
-+#ifdef LEGACY_UTMP_APIS
++int
++_utmpxname(struct _utmpx *U, const char *fname)
++{
++ int ret;
++
++ TEST_UTMPX_T("_utmpxname", U);
++ UTMPX_LOCK(U);
++ ret = __utmpxname(U, fname);
++ UTMPX_UNLOCK(U);
++ return ret;
++}
++
++int
++utmpxname(const char *fname)
++{
++ return _utmpxname(&__utx__, fname);
++}
+
++#ifdef UNIFDEF_LEGACY_UTMP_APIS
void
getutmp(const struct utmpx *ux, struct utmp *u)
{
(void)memcpy(u->ut_line, ux->ut_line, sizeof(u->ut_line));
(void)memcpy(u->ut_host, ux->ut_host, sizeof(u->ut_host));
u->ut_time = ux->ut_tv.tv_sec;
-@@ -384,109 +489,16 @@ void
+@@ -369,82 +563,16 @@ void
getutmpx(const struct utmp *u, struct utmpx *ux)
{
- ux->ut_exit.e_exit = 0;
-}
-
--int
--lastlogxname(const char *fname)
--{
-- size_t len;
--
-- _DIAGASSERT(fname != NULL);
--
-- len = strlen(fname);
--
-- if (len >= sizeof(llfile))
-- return 0;
--
-- /* must end in x! */
-- if (fname[len - 1] != 'x')
-- return 0;
--
-- (void)strlcpy(llfile, fname, sizeof(llfile));
-- return 1;
--}
--
--struct lastlogx *
--getlastlogx(uid_t uid, struct lastlogx *ll)
--{
--
-- return __getlastlogx13(_PATH_LASTLOGX, uid, ll);
--}
--
-struct lastlogx *
--__getlastlogx13(const char *fname, uid_t uid, struct lastlogx *ll)
+-getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
-{
- DBT key, data;
- DB *db;
- _DIAGASSERT(fname != NULL);
- _DIAGASSERT(ll != NULL);
-
-- db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0, DB_HASH, NULL);
+- db = dbopen(fname, O_RDWR|O_CREAT|O_EXLOCK, 0644, DB_HASH, NULL);
-
- if (db == NULL)
- return -1;
- (db->close)(db);
- return error;
}
-+#endif /* LEGACY_UTMP_APIS */
++#endif /* UNIFDEF_LEGACY_UTMP_APIS */
#include <sys/un.h>
#include <pthread.h>
#include <errno.h>
+#include <servers/bootstrap.h>
+#include <asl_ipc.h>
#include "_simple.h"
+#ifndef VM_PAGE_SIZE
#define VM_PAGE_SIZE 4096
+#endif
+
#define SBUF_SIZE(s) (((SBUF *)(s))->b.end - ((SBUF *)(s))->b.buf + 1)
/* we use a small buffer to minimize stack usage constraints */
#define MYBUFSIZE 32
#endif /* !VARIANT_DYLD */
} SBUF;
-static int asl_socket;
-static pthread_once_t asl_socket_once = PTHREAD_ONCE_INIT;
+#define ASL_SERVICE_NAME "com.apple.system.logger"
+
+static mach_port_t asl_port;
+static pthread_once_t asl_init_once = PTHREAD_ONCE_INIT;
/* private extern exports from asl.c */
const char *_asl_escape(unsigned char);
{
vm_size_t s;
+ if(b == NULL) return;
if(((intptr_t)(((SBUF *)b)->b.buf) & (VM_PAGE_SIZE - 1)) == 0) {
vm_deallocate(mach_task_self(), (vm_address_t)((SBUF *)b)->b.buf, SBUF_SIZE(b));
s = VM_PAGE_SIZE;
* Simplified ASL log interface; does not use malloc. Unfortunately, this
* requires knowledge of the format used by ASL.
*/
+
static void
-socket_init(void)
+_simple_asl_init(void)
{
- struct sockaddr_un server;
+ kern_return_t status;
+ char *str;
- server.sun_family = AF_UNIX;
- strncpy(server.sun_path, _PATH_LOG, sizeof(server.sun_path));
- asl_socket = socket(AF_UNIX, SOCK_DGRAM, 0);
- if (asl_socket < 0) return;
-
- fcntl(asl_socket, F_SETFD, 1);
-
- if (connect(asl_socket, (struct sockaddr *)&server, sizeof(server)) == -1)
+ if (asl_port == MACH_PORT_NULL)
{
- close(asl_socket);
- asl_socket = -1;
+ str = getenv("ASL_DISABLE");
+ if ((str != NULL) && (!strcmp(str, "1"))) return;
+
+ status = bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &asl_port);
+ if (status != KERN_SUCCESS) asl_port = MACH_PORT_NULL;
}
}
void
-_simple_asl_log(int level, const char *facility, const char *message)
+_simple_asl_log_prog(int level, const char *facility, const char *message, const char *prog)
{
_SIMPLE_STRING b;
- if(pthread_once(&asl_socket_once, socket_init) != 0)
- return;
- if((b = _simple_salloc()) == NULL)
- return;
- do {
- char *cp, *bp;
- unsigned u;
- struct timeval tv;
+ if (pthread_once(&asl_init_once, _simple_asl_init) != 0) return;
+ if (asl_port == MACH_PORT_NULL) return;
- if(_simple_sprintf(b, "%10u [Time ", 0))
- break;
- gettimeofday(&tv, NULL);
- if(_simple_esprintf(b, _asl_escape, "%lu", tv.tv_sec))
- break;
- if(_simple_sappend(b, "] [Host] [Sender "))
- break;
- if(_simple_esappend(b, _asl_escape, getprogname()))
- break;
- if(_simple_sappend(b, "] [PID "))
- break;
- if(_simple_esprintf(b, _asl_escape, "%u", getpid()))
- break;
- if(_simple_sappend(b, "] [UID "))
- break;
- if(_simple_esprintf(b, _asl_escape, "%d", getuid()))
- break;
- if(_simple_sappend(b, "] [GID "))
- break;
- if(_simple_esprintf(b, _asl_escape, "%d", getgid()))
- break;
- if(_simple_sappend(b, "] [Level "))
- break;
- if(_simple_esprintf(b, _asl_escape, "%d", level))
- break;
- if(_simple_sappend(b, "] [Message "))
- break;
- if(_simple_esappend(b, _asl_escape, message))
- break;
- /* remove trailing (escaped) newlines */
- cp = _simple_string(b);
- cp += strlen(cp);
- for(;;) {
- cp -= 2;
- if(strcmp(cp, "\\n") != 0)
- break;
- *cp = 0;
- }
- _simple_sresize(b);
- if(_simple_sappend(b, "] [Facility "))
- break;
- if(_simple_esappend(b, _asl_escape, facility))
- break;
- if(_simple_sappend(b, "]\n"))
- break;
- cp = _simple_string(b);
- u = strlen(cp) - 10; // includes newline and null
- bp = cp + 10;
- if(u == 0)
- *--bp = '0';
- else
- while(bp > cp && u) {
- *--bp = u % 10 + '0';
- u /= 10;
- }
- write(asl_socket, cp, strlen(cp) + 1);
- } while(0);
- _simple_sfree(b);
+ if ((b = _simple_salloc()) == NULL) return;
+
+ do
+ {
+ kern_return_t kstatus;
+ vm_address_t out;
+ int outlen;
+ char *cp;
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ if (_simple_sprintf(b, " 0 [Time ", 0)) break;
+ if (_simple_esprintf(b, _asl_escape, "%lu", tv.tv_sec)) break;
+ if (_simple_sappend(b, "] [Sender ")) break;
+ if (_simple_esappend(b, _asl_escape, prog)) break;
+ if (_simple_sappend(b, "] [Level ")) break;
+ if (_simple_esprintf(b, _asl_escape, "%d", level)) break;
+ if (_simple_sappend(b, "] [Facility ")) break;
+ if (_simple_esappend(b, _asl_escape, facility)) break;
+ if (_simple_sappend(b, "] [Message ")) break;
+ if (_simple_esappend(b, _asl_escape, message)) break;
+
+ /* remove trailing (escaped) newlines */
+ cp = _simple_string(b);
+ cp += strlen(cp);
+ for (;;)
+ {
+ cp -= 2;
+ if (strcmp(cp, "\\n") != 0) break;
+ *cp = 0;
+ }
+
+ _simple_sresize(b);
+
+ if (_simple_sappend(b, "]\n")) break;
+
+ cp = _simple_string(b);
+
+ /*
+ * The MIG defs for _asl_server_message specifies "dealloc",
+ * so we copy the string into a new vm buffer and send that.
+ */
+ outlen = strlen(cp);
+ kstatus = vm_allocate(mach_task_self(), &out, outlen, TRUE);
+ if (kstatus != KERN_SUCCESS) break;
+
+ memcpy((void *)out, cp, outlen);
+ _asl_server_message(asl_port, (caddr_t)out, outlen);
+ } while (0);
+
+ _simple_sfree(b);
+}
+
+void
+_simple_asl_log(int level, const char *facility, const char *message)
+{
+ _simple_asl_log_prog(level, facility, message, getprogname());
}
/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2006, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* requires knowledge of the format used by ASL.
*/
void _simple_asl_log(int __level, const char *__facility, const char *__message);
+void _simple_asl_log_prog(int level, const char *facility, const char *message, const char *progname);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)alarm.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/alarm.3,v 1.16 2002/12/18 13:33:02 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/alarm.3,v 1.17 2007/01/09 00:27:52 imp Exp $
.\"
.Dd April 19, 1994
.Dt ALARM 3
/*
- * Arc4 random number generator for OpenBSD.
- * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * Modification and redistribution in source and binary forms is
- * permitted provided that due credit is given to the author and the
- * OpenBSD project (for instance by leaving this copyright notice
- * intact).
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
+ * Arc4 random number generator for OpenBSD.
+ *
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/arc4random.c,v 1.10 2004/03/24 14:44:57 green Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/arc4random.c,v 1.25 2008/09/09 09:46:36 ache Exp $");
#include "namespace.h"
#include <sys/types.h>
u_int8_t s[256];
};
-static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+static int lock = 0;
+extern void spin_lock(int*);
+extern void spin_unlock(int*);
-#define RANDOMDEV "/dev/urandom"
+#define RANDOMDEV "/dev/random"
+#define KEYSIZE 128
#define THREAD_LOCK() \
do { \
if (__isthreaded) \
- _pthread_mutex_lock(&arc4random_mtx); \
+ spin_lock(&lock); \
} while (0)
#define THREAD_UNLOCK() \
do { \
if (__isthreaded) \
- _pthread_mutex_unlock(&arc4random_mtx); \
+ spin_unlock(&lock); \
} while (0)
-static struct arc4_stream rs;
+static struct arc4_stream rs = {
+ .i = 0,
+ .j = 0,
+ .s = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+ }
+};
static int rs_initialized;
static int rs_stired;
+static int arc4_count;
-static inline u_int8_t arc4_getbyte(struct arc4_stream *);
-static void arc4_stir(struct arc4_stream *);
+static inline u_int8_t arc4_getbyte(void);
+static void arc4_stir(void);
-static inline void
-arc4_init(as)
- struct arc4_stream *as;
-{
- int n;
-
- for (n = 0; n < 256; n++)
- as->s[n] = n;
- as->i = 0;
- as->j = 0;
-}
+static struct {
+ struct timeval tv;
+ pid_t pid;
+ u_int8_t rnd[KEYSIZE];
+} rdat;
+static volatile int rs_data_available = 0;
static inline void
-arc4_addrandom(as, dat, datlen)
- struct arc4_stream *as;
- u_char *dat;
- int datlen;
+arc4_addrandom(u_char *dat, int datlen)
{
int n;
u_int8_t si;
- as->i--;
+ rs.i--;
for (n = 0; n < 256; n++) {
- as->i = (as->i + 1);
- si = as->s[as->i];
- as->j = (as->j + si + dat[n % datlen]);
- as->s[as->i] = as->s[as->j];
- as->s[as->j] = si;
+ rs.i = (rs.i + 1);
+ si = rs.s[rs.i];
+ rs.j = (rs.j + si + dat[n % datlen]);
+ rs.s[rs.i] = rs.s[rs.j];
+ rs.s[rs.j] = si;
}
+ rs.j = rs.i;
}
static void
-arc4_stir(as)
- struct arc4_stream *as;
+arc4_fetch(void)
{
- int fd, n;
- struct {
- struct timeval tv;
- pid_t pid;
- u_int8_t rnd[128 - sizeof(struct timeval) - sizeof(pid_t)];
- } rdat;
-
- gettimeofday(&rdat.tv, NULL);
- rdat.pid = getpid();
+ int done, fd;
fd = _open(RANDOMDEV, O_RDONLY, 0);
+ done = 0;
if (fd >= 0) {
- (void) _read(fd, rdat.rnd, sizeof(rdat.rnd));
- _close(fd);
+ if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
+ done = 1;
+ (void)_close(fd);
}
- /* fd < 0? Ah, what the heck. We'll just take whatever was on the
- * stack... */
+ if (!done) {
+ (void)gettimeofday(&rdat.tv, NULL);
+ rdat.pid = getpid();
+ /* We'll just take whatever was on the stack too... */
+ }
+}
- arc4_addrandom(as, (u_char *) &rdat, sizeof(rdat));
+static void
+arc4_stir(void)
+{
+ int n;
+ /*
+ * If we don't have data, we need some now before we can integrate
+ * it into the static buffers
+ */
+ if (!rs_data_available)
+ {
+ arc4_fetch();
+ }
+ rs_data_available = 0;
+ __sync_synchronize();
+
+ arc4_addrandom((u_char *)&rdat, KEYSIZE);
/*
* Throw away the first N bytes of output, as suggested in the
* by Ilya Mironov.
*/
for (n = 0; n < 1024; n++)
- arc4_getbyte(as);
+ (void) arc4_getbyte();
+ arc4_count = 1600000;
+ rs_stired = 1;
}
static inline u_int8_t
-arc4_getbyte(as)
- struct arc4_stream *as;
+arc4_getbyte(void)
{
u_int8_t si, sj;
- as->i = (as->i + 1);
- si = as->s[as->i];
- as->j = (as->j + si);
- sj = as->s[as->j];
- as->s[as->i] = sj;
- as->s[as->j] = si;
+ rs.i = (rs.i + 1);
+ si = rs.s[rs.i];
+ rs.j = (rs.j + si);
+ sj = rs.s[rs.j];
+ rs.s[rs.i] = sj;
+ rs.s[rs.j] = si;
- return (as->s[(si + sj) & 0xff]);
+ return (rs.s[(si + sj) & 0xff]);
}
static inline u_int32_t
-arc4_getword(as)
- struct arc4_stream *as;
+arc4_getword(void)
{
u_int32_t val;
- val = arc4_getbyte(as) << 24;
- val |= arc4_getbyte(as) << 16;
- val |= arc4_getbyte(as) << 8;
- val |= arc4_getbyte(as);
+ val = arc4_getbyte() << 24;
+ val |= arc4_getbyte() << 16;
+ val |= arc4_getbyte() << 8;
+ val |= arc4_getbyte();
return (val);
}
-static void
-arc4_check_init(void)
+/* 7944700: force restir in child */
+__private_extern__ void
+_arc4_fork_child(void)
{
- if (!rs_initialized) {
- arc4_init(&rs);
- rs_initialized = 1;
- }
+ rs_stired = 0;
+ rs_data_available = 0;
}
-static void
+static inline int
arc4_check_stir(void)
{
- if (!rs_stired) {
- arc4_stir(&rs);
- rs_stired = 1;
+ if (!rs_stired || arc4_count <= 0) {
+ arc4_stir();
+ return 1;
}
+ return 0;
}
void
-arc4random_stir()
+arc4random_stir(void)
{
THREAD_LOCK();
- arc4_check_init();
- arc4_stir(&rs);
+ arc4_stir();
THREAD_UNLOCK();
}
void
-arc4random_addrandom(dat, datlen)
- u_char *dat;
- int datlen;
+arc4random_addrandom(u_char *dat, int datlen)
{
THREAD_LOCK();
- arc4_check_init();
arc4_check_stir();
- arc4_addrandom(&rs, dat, datlen);
+ arc4_addrandom(dat, datlen);
THREAD_UNLOCK();
}
u_int32_t
-arc4random()
+arc4random(void)
{
u_int32_t rnd;
THREAD_LOCK();
- arc4_check_init();
- arc4_check_stir();
- rnd = arc4_getword(&rs);
+
+ int did_stir = arc4_check_stir();
+ rnd = arc4_getword();
+ arc4_count -= 4;
+
THREAD_UNLOCK();
+ if (did_stir)
+ {
+ /* stirring used up our data pool, we need to read in new data outside of the lock */
+ arc4_fetch();
+ rs_data_available = 1;
+ __sync_synchronize();
+ }
return (rnd);
}
+void
+arc4random_buf(void *_buf, size_t n)
+{
+ u_char *buf = (u_char *)_buf;
+ int did_stir = 0;
+
+ THREAD_LOCK();
+
+ while (n--) {
+ if (arc4_check_stir())
+ {
+ did_stir = 1;
+ }
+ buf[n] = arc4_getbyte();
+ arc4_count--;
+ }
+
+ THREAD_UNLOCK();
+ if (did_stir)
+ {
+ /* stirring used up our data pool, we need to read in new data outside of the lock */
+ arc4_fetch();
+ rs_data_available = 1;
+ __sync_synchronize();
+ }
+}
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound). This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+u_int32_t
+arc4random_uniform(u_int32_t upper_bound)
+{
+ u_int32_t r, min;
+
+ if (upper_bound < 2)
+ return (0);
+
+#if (ULONG_MAX > 0xffffffffUL)
+ min = 0x100000000UL % upper_bound;
+#else
+ /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
+ if (upper_bound > 0x80000000)
+ min = 1 + ~upper_bound; /* 2**32 - upper_bound */
+ else {
+ /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
+ min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
+ }
+#endif
+
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = arc4random();
+ if (r >= min)
+ break;
+ }
+
+ return (r % upper_bound);
+}
+
#if 0
/*-------- Test code for i386 --------*/
#include <stdio.h>
-.\" Copyright (c) 2005-2007 Apple Inc.
+.\" Copyright (c) 2005-2010 Apple Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" SUCH DAMAGE.
.\"
.\"
-.Dd January 11, 2007
+.Dd March 3, 2010
.Dt asl 3
.Os "Mac OS X"
.Sh NAME
.Nm asl_add_log_file ,
.Nm asl_close ,
+.Nm asl_close_auxiliary_file ,
+.Nm asl_create_auxiliary_file ,
.Nm asl_free ,
.Nm asl_get ,
.Nm asl_key ,
.Nm asl_log ,
+.Nm asl_log_auxiliary_location ,
.Nm asl_new ,
.Nm asl_open ,
+.Nm asl_open_from_file ,
.Nm asl_remove_log_file ,
.Nm asl_search ,
.Nm asl_send ,
.Fa "aslclient asl"
.Fc
.Ft void
+.Fo asl_close_auxiliary_file
+.Fa "int fd"
+.Fc
+.Ft void
+.Fo asl_create_auxiliary_file
+.Fa "aslmsg msg"
+.Fa "const char *title"
+.Fa "const char *uti"
+.Fa "int *out_fd"
+.Fc
+.Ft void
.Fo asl_free
.Fa "aslmsg msg"
.Fc
.Fa "const char *format"
.Fa "..."
.Fc
+.Ft void
+.Fo asl_log_auxiliary_location
+.Fa "aslmsg msg"
+.Fa "const char *title"
+.Fa "const char *uti"
+.Fa "const char *url"
+.Fc
.Ft aslmsg
.Fo asl_new
.Fa "uint32_t type"
.Fa "const char *facility"
.Fa "uint32_t opts"
.Fc
+.Ft aslclient
+.Fo asl_open_from_file
+.Fa "int fd"
+.Fa "const char *ident"
+.Fa "const char *facility"
+.Fc
.Ft int
.Fo asl_remove_log_file
.Fa "aslclient asl"
creates and returns a client handle, or NULL if an error occurs in the library.
Messages sent using this handle will default to having the string
.Ar ident
-as the value assocated with the ASL_KEY_SENDER key, and the value
+as the value associated with the ASL_KEY_SENDER key, and the value
.Ar facility
-assocated with the ASL_KEY_FACILITY key.
+associated with the ASL_KEY_FACILITY key.
Several options are available, as described in the
.Sx CLIENT HANDLES
section.
frees the aslresponse structure
.Ar r
and all of its associated resources.
+.Pp
+.Fo asl_create_auxiliary_file
+.Fa msg
+.Fa title
+.Fa uti
+.Fa out_fd
+.Fc
+Creates an auxiliary file that may be used by the client to save arbitrary data.
+When the file is closed using
+.Fo asl_close_auxiliary_file
+.Fc ,
+.Nm syslogd
+will log the specified
+.Fa msg
+along with the
+.Fa title
+and the Uniform Type Identifier provided by
+.Fa uti .
+If a NULL value is supplied for
+.Fa uti
+the type
+.Dq public.data
+will be used.
+The
+.Nm Console
+application will display the message with a link to the file.
+.Pp
+Auxiliary files are saved in the ASL data store.
+They are automatically deleted at the same time that the log message expires.
+Messages expire in 7 days by default.
+A value set for the ASLExpireTime key will override the default.
+Read access for the auxiliary file will be the same as read access for
+.Fa msg .
+By default, messages (and auxiliary files) are world-readable.
+Access may be limited by setting values for the ReadUID and ReadGID keys.
+.Pp
+.Fo asl_close_auxiliary_file
+.Fa fd
+.Fc
+closes the file descriptor
+.Ar fd
+previously returned by a call to
+.Fn asl_create_auxiliary_file .
+.Pp
+.Fo asl_log_auxiliary_location
+.Fa msg
+.Fa title
+.Fa uti
+.Fa url
+.Fc
+will log the specified
+.Fa msg
+along with the
+.Fa title ,
+the Uniform Type Identifier provided by
+.Fa uti ,
+and the Uniform Resource Locator provided by
+.Fa url .
+The
+.Nm Console
+application will display the message with a link to the file.
+This allows a client to save data in an auxiliary file, but unlike
+.Fo asl_create_auxiliary_file
+.Fc ,
+the life-cycle of this file must be managed by some external system.
+The file will not be removed when the corresponding log message expired from the ASL data store.
+.Pp
+.Fo asl_open_from_file
+.Fa fd
+.Fa facility
+.Fa opts
+.Fc
+creates a client handle for an open file descriptor
+.Fa fd .
+This routine may be used in conjunction with
+.Fo asl_create_auxiliary_file
+.Fc
+or
+.Fo asl_log_auxiliary_location
+.Fc
+to save ASL format log messages in an auxiliary file.
+The UTI type
+.Dq com.apple.asl-file
+should be used for ASL format auxiliary files.
+.Pp
+Files with this format may be read from the command line using
+.Nm syslog Fl f Ar file ,
+or from the
+.Nm Console
+utility.
+.Pp
+The file must be open for read and write access.
+The file will be truncated and its existing contents will be lost.
+.Fo asl_close
+.Fc
+must be called to close the client handle when logging to this file is complete.
+The file should be closed using
+.Fo asl_close_auxiliary_file
+.Fc
+if it was returned by
+.Fo asl_create_auxiliary_file
+.Fc ,
+or
+.Fo close
+.Fc
+otherwise.
+.Pp
+The client handle may be used safely by multiple threads.
+The threads will contend for a single internal lock when saving log messages to a file.
+.Pp
+Note that messages with ReadUID or ReadGID values will simply be saved to the file,
+and will not effect read access to either the message or the file itself.
+Similarly, messages with ASLExpireTime values will be saved, but will not effect the
+life-cycle of either the individual messages or the file.
.Ss MESSAGES
At the core of this API is the aslmsg structure.
Although the structure is opaque and may not be directly manipulated,
/*
- * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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 <stdarg.h>
#include <syslog.h>
#include <errno.h>
+#include <limits.h>
#include <time.h>
#include <sys/time.h>
+#include <sys/fcntl.h>
#include <crt_externs.h>
#include <asl.h>
-#include <asl_private.h>
-#include <asl_store.h>
#include <regex.h>
#include <notify.h>
#include <mach/mach.h>
#include <sys/types.h>
#include <servers/bootstrap.h>
#include <pthread.h>
-#include "asl_core.h"
+#include <dispatch/dispatch.h>
#include <asl_ipc.h>
+#include "asl_core.h"
+#include "asl_msg.h"
+#include "asl_store.h"
+#include "asl_private.h"
#define streq(A, B) (strcmp(A, B) == 0)
#define strcaseeq(A, B) (strcasecmp(A, B) == 0)
-#ifndef ASL_QUERY_OP_FALSE
-#define ASL_QUERY_OP_FALSE 0
-#endif
-
#define forever for(;;)
-#define TOKEN_NULL 0
-#define TOKEN_OPEN 1
-#define TOKEN_CLOSE 2
-#define TOKEN_WORD 3
-#define TOKEN_INT 4
-
-#define MFMT_RAW 0
-#define MFMT_STD 1
-#define MFMT_BSD 2
-#define MFMT_XML 3
-#define MFMT_STR 4
-#define MFMT_MSG 5
-
-#define TFMT_SEC 0
-#define TFMT_UTC 1
-#define TFMT_LCL 2
-
-#define XML_TAG_KEY 0
-#define XML_TAG_STRING 1
-#define XML_TAG_DATA 2
-
#define FETCH_BATCH 256
/* forward */
time_t asl_parse_time(const char *);
const char *asl_syslog_faciliy_num_to_name(int n);
+__private_extern__ int _asl_send_message(aslclient ac, asl_msg_t *msg, int slevel, const char *aux_message);
__private_extern__ asl_client_t *_asl_open_default();
-__private_extern__ int _asl_send_level_message(aslclient ac, aslmsg msg, int level, const char *message);
+
+/* private asl_msg SPI */
+__private_extern__ uint32_t _asl_msg_string_length_aux(asl_msg_t *msg, asl_msg_aux_t *aux);
+__private_extern__ uint32_t _asl_msg_to_string_buffer_aux(asl_msg_t *msg, asl_msg_aux_t *aux, char *buf, uint32_t bufsize);
+
+/* private asl_file SPI */
+__private_extern__ uint32_t asl_file_open_write_fd(int fd, asl_file_t **s);
/* notify SPI */
uint32_t notify_register_plain(const char *name, int *out_token);
-/* from asl_util.c */
-int asl_is_utf8(const char *str);
-uint8_t *asl_b64_encode(const uint8_t *buf, size_t len);
-
/* fork handling in syslog.c */
extern void _syslog_fork_child();
-/* character encoding lengths */
-static const uint8_t char_encode_len[128] =
+typedef struct
{
- 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3
-};
-
-static const char *cvis_7_13 = "abtnvfr";
+ int fd;
+ asl_msg_t *msg;
+ dispatch_semaphore_t sem;
+} asl_aux_context_t;
typedef struct
{
int master_token;
uint64_t proc_filter;
uint64_t master_filter;
- int port_count;
+ dispatch_once_t port_lookup_once;
mach_port_t server_port;
char *sender;
pthread_mutex_t lock;
- pthread_mutex_t port_lock;
+ int aux_count;
+ asl_aux_context_t **aux_ctx;
asl_client_t *asl;
} _asl_global_t;
+
#ifndef BUILDING_VARIANT
-__private_extern__ _asl_global_t _asl_global = {0, -1, -1, -1, 0LL, 0LL, 0, MACH_PORT_NULL, NULL, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL};
+__private_extern__ _asl_global_t _asl_global = {0, -1, -1, -1, 0LL, 0LL, 0, MACH_PORT_NULL, NULL, PTHREAD_MUTEX_INITIALIZER, 0, NULL, NULL};
#define ASL_SERVICE_NAME "com.apple.system.logger"
_asl_global.master_token = -1;
_asl_global.notify_token = -1;
- _asl_global.port_count = 0;
+ _asl_global.port_lookup_once = 0;
_asl_global.server_port = MACH_PORT_NULL;
+}
+
+/*
+ * asl_remote_notify_name: returns the notification key for remote-control filter
+ * changes for this process.
+ */
+char *
+asl_remote_notify_name()
+{
+ pid_t pid = getpid();
+ uid_t euid = geteuid();
+ char *str = NULL;
- /* clean up in syslog.c */
- _syslog_fork_child();
+ if (euid == 0) asprintf(&str, "%s.%d", NOTIFY_PREFIX_SYSTEM, pid);
+ else asprintf(&str, "user.uid.%d.syslog.%d", euid, pid);
+
+ return str;
}
static int
{
char *notify_name;
uint32_t status;
- uint32_t euid;
if (do_lock != 0) pthread_mutex_lock(&_asl_global.lock);
if (status != NOTIFY_STATUS_OK) _asl_global.master_token = -1;
}
- euid = geteuid();
- notify_name = NULL;
- if (euid == 0) asprintf(¬ify_name, "%s.%d", NOTIFY_PREFIX_SYSTEM, getpid());
- else asprintf(¬ify_name, "user.uid.%d.syslog.%d", euid, getpid());
-
+ notify_name = asl_remote_notify_name();
if (notify_name != NULL)
{
status = notify_register_plain(notify_name, &_asl_global.notify_token);
return;
}
- if (_asl_global.rc_change_token > 0) notify_cancel(_asl_global.rc_change_token);
+ if (_asl_global.rc_change_token >= 0) notify_cancel(_asl_global.rc_change_token);
_asl_global.rc_change_token = -1;
- if (_asl_global.master_token > 0) notify_cancel(_asl_global.master_token);
+ if (_asl_global.master_token >= 0) notify_cancel(_asl_global.master_token);
_asl_global.master_token = -1;
- if (_asl_global.notify_token > 0) notify_cancel(_asl_global.notify_token);
+ if (_asl_global.notify_token >= 0) notify_cancel(_asl_global.notify_token);
_asl_global.notify_token = -1;
pthread_mutex_unlock(&_asl_global.lock);
}
static void
-_asl_get_global_server_port()
-{
- kern_return_t kstatus;
-
- pthread_mutex_lock(&(_asl_global.port_lock));
-
- if (_asl_global.server_port == MACH_PORT_NULL)
- {
- _asl_global.port_count = 0;
-
- kstatus = bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &_asl_global.server_port);
- if (kstatus == KERN_SUCCESS) _asl_global.port_count = 1;
- else _asl_global.server_port = MACH_PORT_NULL;
- }
- else
- {
- _asl_global.port_count++;
- }
-
- pthread_mutex_unlock(&(_asl_global.port_lock));
-}
-
-static void
-_asl_release_global_server_port()
+_asl_global_init()
{
- pthread_mutex_lock(&(_asl_global.port_lock));
-
- if (_asl_global.port_count > 0) _asl_global.port_count--;
- if (_asl_global.port_count == 0)
- {
- mach_port_deallocate(mach_task_self(), _asl_global.server_port);
- _asl_global.server_port = MACH_PORT_NULL;
- }
-
- pthread_mutex_unlock(&(_asl_global.port_lock));
+ dispatch_once(&_asl_global.port_lookup_once, ^{
+ char *str = getenv("ASL_DISABLE");
+ if ((str == NULL) || strcmp(str, "1"))
+ {
+ bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &_asl_global.server_port);
+ }
+ });
}
aslclient
asl->sock = -1;
- _asl_get_global_server_port();
+ _asl_global_init();
asl->pid = getpid();
asl->uid = getuid();
if (asl->facility == NULL)
{
if (asl->sock >= 0) close(asl->sock);
+ if (asl->name != NULL) free(asl->name);
free(asl);
return NULL;
}
return (aslclient)asl;
}
-void
-asl_close(aslclient ac)
+aslclient
+asl_open_from_file(int fd, const char *ident, const char *facility)
{
+ char *name, *x;
asl_client_t *asl;
- uint32_t i;
-
- asl = (asl_client_t *)ac;
- if (asl == NULL) return;
-
- if (asl->sock >= 0) close(asl->sock);
-
- pthread_mutex_lock(&(_asl_global.port_lock));
-
- if (_asl_global.port_count > 0) _asl_global.port_count--;
- if (_asl_global.port_count == 0)
- {
- mach_port_deallocate(mach_task_self(), _asl_global.server_port);
- _asl_global.server_port = MACH_PORT_NULL;
- }
-
- pthread_mutex_unlock(&(_asl_global.port_lock));
-
- if (asl->name != NULL) free(asl->name);
- if (asl->facility != NULL) free(asl->facility);
- if (!(asl->options & ASL_OPT_NO_REMOTE)) _asl_notify_close();
- if (asl->fd_list != NULL) free(asl->fd_list);
-
- if (asl->fd_mfmt != NULL)
- {
- for (i = 0; i < asl->fd_count; i++) if (asl->fd_mfmt[i] != NULL) free(asl->fd_mfmt[i]);
- free(asl->fd_mfmt);
- }
-
- if (asl->fd_tfmt != NULL)
- {
- for (i = 0; i < asl->fd_count; i++) if (asl->fd_tfmt[i] != NULL) free(asl->fd_tfmt[i]);
- free(asl->fd_tfmt);
- }
-
- if (asl->fd_encoding != NULL) free(asl->fd_encoding);
-
- memset(asl, 0, sizeof(asl_client_t));
- free(asl);
-}
-
-__private_extern__ asl_client_t *
-_asl_open_default()
-{
- if (_asl_global.asl != NULL) return _asl_global.asl;
-
- pthread_mutex_lock(&_asl_global.lock);
- if (_asl_global.asl != NULL)
- {
- pthread_mutex_unlock(&_asl_global.lock);
- return _asl_global.asl;
- }
-
- /*
- * Do a sleight-of-hand with ASL_OPT_NO_REMOTE to avoid a deadlock
- * since asl_open(xxx, yyy, 0) calls _asl_notify_open(1)
- * which locks _asl_global.lock.
- */
- _asl_global.asl = asl_open(NULL, NULL, ASL_OPT_NO_REMOTE);
-
- /* Reset options to clear ASL_OPT_NO_REMOTE bit */
- if (_asl_global.asl != NULL) _asl_global.asl->options = 0;
-
- /* Now call _asl_notify_open(0) to finish the work */
- _asl_notify_open(0);
-
- pthread_mutex_unlock(&_asl_global.lock);
-
- return _asl_global.asl;
-}
-
-static uint32_t
-_asl_msg_index(asl_msg_t *msg, const char *k)
-{
- uint32_t i;
-
- if (msg == NULL) return (uint32_t)-1;
- if (k == NULL) return (uint32_t)-1;
+ uint32_t status;
- for (i = 0; i < msg->count; i++)
+ asl = (asl_client_t *)calloc(1, sizeof(asl_client_t));
+ if (asl == NULL)
{
- if (msg->key[i] == NULL) continue;
- if (streq(msg->key[i], k)) return i;
+ errno = ENOMEM;
+ return NULL;
}
- return (uint32_t)-1;
-}
-
-static void
-_asl_encode_char(char **m, uint32_t *x, uint32_t c, uint32_t encode, uint32_t encode_space)
-{
- char *p;
- int meta;
-
- meta = 0;
-
- p = *m + *x - 1;
-
- /* NUL is not allowed */
- if (c == 0) return;
+ asl->options = ASL_OPT_NO_REMOTE;
+ asl->sock = -1;
- /* Meta chars get \M prefix */
- if (c >= 128)
- {
- /* except meta-space, which is \240 */
- if (c == 160)
- {
- *p++ = '\\';
- *p++ = '2';
- *p++ = '4';
- *p++ = '0';
- *p = '\0';
- *x = *x + 4;
- return;
- }
+ asl->pid = getpid();
+ asl->uid = getuid();
+ asl->gid = getgid();
- *p++ = '\\';
- *p++ = 'M';
- *p = '\0';
- *x = *x + 2;
- c &= 0x7f;
- meta = 1;
- }
+ asl->filter = ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG);
- /* space is either ' ' or \s */
- if (c == 32)
+ if (ident != NULL)
{
- if (encode_space == 0)
+ asl->name = strdup(ident);
+ if (asl->name == NULL)
{
- *p++ = ' ';
- *p = '\0';
- *x = *x + 1;
- return;
+ free(asl);
+ return NULL;
}
-
- *p++ = '\\';
- *p++ = 's';
- *p = '\0';
- *x = *x + 2;
- return;
- }
-
- /* \ is escaped */
- if ((meta == 0) && (c == 92))
- {
- *p++ = '\\';
- *p++ = c;
- *p = '\0';
- *x = *x + 2;
- return;
- }
-
- /* [ and ] are escaped in ASL encoding */
- if ((encode == ASL_ENCODE_ASL) && (meta == 0) && ((c == 91) || (c == 93)))
- {
- *p++ = '\\';
- *p++ = c;
- *p = '\0';
- *x = *x + 2;
- return;
}
-
- /* DEL is \^? */
- if (c == 127)
+ else
{
- if (meta == 0)
+ name = *(*_NSGetArgv());
+ if (name != NULL)
{
- *p++ = '\\';
- *x = *x + 1;
+ x = strrchr(name, '/');
+ if (x != NULL) x++;
+ else x = name;
+ asl->name = strdup(x);
+ if (asl->name == NULL)
+ {
+ free(asl);
+ return NULL;
+ }
}
-
- *p++ = '^';
- *p++ = '?';
- *p = '\0';
- *x = *x + 2;
- return;
}
- /* 33-126 are printable (add a '-' prefix for meta) */
- if ((c >= 33) && (c <= 126))
+ asl->facility = NULL;
+ if (facility != NULL) asl->facility = strdup(facility);
+ else asl->facility = strdup(asl_syslog_faciliy_num_to_name(LOG_USER));
+ if (asl->facility == NULL)
{
- if (meta == 1)
- {
- *p++ = '-';
- *x = *x + 1;
- }
-
- *p++ = c;
- *p = '\0';
- *x = *x + 1;
- return;
+ if (asl->name != NULL) free(asl->name);
+ free(asl);
+ return NULL;
}
- /* non-meta BEL, BS, HT, NL, VT, NP, CR (7-13) are \a, \b, \t, \n, \v, \f, and \r */
- if ((meta == 0) && (c >= 7) && (c <= 13))
+ status = asl_file_open_write_fd(fd, &(asl->aslfile));
+ if (status != ASL_STATUS_OK)
{
- *p++ = '\\';
- *p++ = cvis_7_13[c - 7];
- *p = '\0';
- *x = *x + 2;
- return;
+ if (asl->name != NULL) free(asl->name);
+ if (asl->facility != NULL) free(asl->facility);
+ free(asl);
+ return NULL;
}
- /* 0 - 31 are ^@ - ^_ (non-meta get a leading \) */
- if ((c >= 0) && (c <= 31))
- {
- if (meta == 0)
- {
- *p++ = '\\';
- *x = *x + 1;
- }
-
- *p++ = '^';
- *p++ = 64 + c;
- *p = '\0';
- *x = *x + 2;
- return;
- }
+ asl->aslfileid = 1;
- return;
+ return (aslclient)asl;
}
-static void
-_asl_append_string(char **m, uint32_t *x, const char *s, uint32_t encode, uint32_t escspace)
+void
+asl_close(aslclient ac)
{
- uint32_t i, n, spextra;
- uint8_t c;
- char *p;
-
- if (m == NULL) return;
- if (x == NULL) return;
- if (s == NULL) return;
-
- if (encode == ASL_ENCODE_NONE)
- {
- /* no encoding - just allocate enough space and copy the string */
-
- n = strlen(s);
- if (n == 0) return;
-
- if (*m == NULL)
- {
- *m = malloc(n + 1);
- *x = 1;
- }
- else
- {
- *m = reallocf(*m, n + (*x));
- }
-
- if (*m == NULL) return;
-
- memcpy((*m) + (*x) - 1, s, n + 1);
- *x += n;
-
- return;
- }
- else if (encode == ASL_ENCODE_SAFE)
- {
- /*
- * Minor encoding to reduce the likelyhood of spoof attacks.
- *
- * - append a tab after newlines
- * - translate \r to newline & append a tab
- * - map backspace to ^H
- *
- * Note that there may be UTF-8 characters that could be used in a spoof
- * attack that we don't check. Caveat Reador.
- */
- n = 0;
- for (i = 0; s[i] != '\0'; i++)
- {
- n++;
- c = s[i];
- if ((c == 10) || (c == 13) || (c == 8)) n++;
- }
-
- if (n == 0) return;
-
- if (*m == NULL)
- {
- *m = malloc(n + 1);
- *x = 1;
- }
- else
- {
- *m = reallocf(*m, n + (*x));
- }
-
- if (*m == NULL) return;
-
- p = *m + *x - 1;
-
- for (i = 0; s[i] != '\0'; i++)
- {
- c = s[i];
- if ((c == 10) || (c == 13))
- {
- *p++ = '\n';
- *p++ = '\t';
- *x = *x + 2;
- }
- else if (c == 8)
- {
- *p++ = '^';
- *p++ = 'H';
- *x = *x + 2;
- }
- else
- {
- *p++ = c;
- *x = *x + 1;
- }
- }
-
- return;
- }
-
- spextra = 0;
-
- if (escspace != 0) spextra = 1;
-
- n = 0;
- for (i = 0; s[i] != '\0'; i++)
- {
- c = s[i];
-
- if (c >= 128)
- {
- n += 4;
- }
- else if ((c == 91) || (c == 93))
- {
- if (encode == ASL_ENCODE_ASL) n += 2;
- else n += 1;
- }
- else
- {
- n += char_encode_len[c];
- if (c == 32) n += spextra;
- }
- }
+ asl_client_t *asl;
+ uint32_t i;
- if (n == 0) return;
+ asl = (asl_client_t *)ac;
+ if (asl == NULL) return;
- if (*m == NULL)
- {
- *m = malloc(n + 1);
- *x = 1;
- }
- else
- {
- *m = reallocf(*m, n + (*x));
- }
+ free(asl->name);
+ free(asl->facility);
- if (*m == NULL) return;
+ if (asl->sock >= 0) close(asl->sock);
+ if (!(asl->options & ASL_OPT_NO_REMOTE)) _asl_notify_close();
+ if (asl->fd_list != NULL) free(asl->fd_list);
- for (i = 0; s[i] != '\0'; i++)
+ if (asl->fd_mfmt != NULL)
{
- c = s[i];
- _asl_encode_char(m, x, c, encode, escspace);
- }
-
- return;
-}
-
-static void
-_asl_append_xml_string(char **m, uint32_t *x, char *s)
-{
- uint32_t i, n;
- uint8_t c;
- char tmp[8], *p;
-
- if (m == NULL) return;
- if (x == NULL) return;
- if (s == NULL) return;
-
- n = 0;
- for (i = 0; s[i] != '\0'; i++)
- {
- c = s[i];
-
- /*
- * XML wants & < > " and '
- * We use &#xnn; for control chars.
- * Everything else just gets printed "as is" (we know the input is UTF8)
- */
- if (c == '&') n += 5;
- else if (c == '<') n += 4;
- else if (c == '>') n += 4;
- else if (c == '"') n += 6;
- else if (c == '\'') n += 6;
- else if (iscntrl(c)) n += 6;
- else n += 1;
- }
-
- if (n == 0) return;
-
- if (*m == NULL)
- {
- *m = malloc(n + 1);
- *x = 1;
- }
- else
- {
- *m = reallocf(*m, n + (*x));
- }
-
- if (*m == NULL) return;
-
- for (i = 0; s[i] != '\0'; i++)
- {
- c = s[i];
-
- if (c == '&')
- {
- p = *m + *x - 1;
- memcpy(p, "&", 5);
- p += 5;
- *p = '\0';
- *x = *x + 5;
- }
- else if (c == '<')
- {
- p = *m + *x - 1;
- memcpy(p, "<", 4);
- p += 4;
- *p = '\0';
- *x = *x + 4;
- }
- else if (c == '>')
- {
- p = *m + *x - 1;
- memcpy(p, ">", 4);
- p += 4;
- *p = '\0';
- *x = *x + 4;
- }
- else if (c == '"')
- {
- p = *m + *x - 1;
- memcpy(p, """, 6);
- p += 6;
- *p = '\0';
- *x = *x + 6;
- }
- else if (c == '\'')
- {
- p = *m + *x - 1;
- memcpy(p, "'", 6);
- p += 6;
- *p = '\0';
- *x = *x + 6;
- }
- else if (iscntrl(c))
- {
- snprintf(tmp, sizeof(tmp), "&#x%02hhu;", c);
- p = *m + *x - 1;
- memcpy(p, tmp, 6);
- p += 6;
- *p = '\0';
- *x = *x + 6;
- }
- else
- {
- p = *m + *x - 1;
- *p++ = c;
- *p = '\0';
- *x = *x + 1;
- }
- }
-
- return;
-}
-
-static void
-_asl_append_xml_tag(char **m, uint32_t *x, int tag, char *s)
-{
- char *b64;
-
- if (m == NULL) return;
- if (x == NULL) return;
-
- if (tag == XML_TAG_KEY)
- {
- _asl_append_string(m, x, "\t\t<key>", ASL_ENCODE_NONE, 0);
- _asl_append_xml_string(m, x, s);
- _asl_append_string(m, x, "</key>\n", ASL_ENCODE_NONE, 0);
- return;
- }
-
- if (tag == XML_TAG_STRING)
- {
- _asl_append_string(m, x, "\t\t<string>", ASL_ENCODE_NONE, 0);
- _asl_append_xml_string(m, x, s);
- _asl_append_string(m, x, "</string>\n", ASL_ENCODE_NONE, 0);
- return;
- }
-
- if (tag == XML_TAG_DATA)
- {
- _asl_append_string(m, x, "\t\t<data>", ASL_ENCODE_NONE, 0);
- b64 = (char *)asl_b64_encode((uint8_t *)s, strlen(s));
- if (b64 != NULL)
- {
- _asl_append_string(m, x, b64, ASL_ENCODE_NONE, 0);
- free(b64);
- }
- _asl_append_string(m, x, "</data>\n", ASL_ENCODE_NONE, 0);
- return;
- }
-}
-
-static void
-_asl_append_op(char **m, uint32_t *x, uint32_t op)
-{
- char opstr[8];
- uint32_t i;
-
- if (m == NULL) return;
- if (x == NULL) return;
-
- if (op == ASL_QUERY_OP_NULL) return _asl_append_string(m, x, ".", ASL_ENCODE_NONE, 0);
-
- i = 0;
- if (op & ASL_QUERY_OP_CASEFOLD) opstr[i++] = 'C';
-
- if (op & ASL_QUERY_OP_REGEX) opstr[i++] = 'R';
-
- if (op & ASL_QUERY_OP_NUMERIC) opstr[i++] = 'N';
-
- if (op & ASL_QUERY_OP_PREFIX)
- {
- if (op & ASL_QUERY_OP_SUFFIX) opstr[i++] = 'S';
- else opstr[i++] = 'A';
- }
- if (op & ASL_QUERY_OP_SUFFIX) opstr[i++] = 'Z';
-
- switch (op & ASL_QUERY_OP_TRUE)
- {
- case ASL_QUERY_OP_EQUAL:
- opstr[i++] = '=';
- break;
- case ASL_QUERY_OP_GREATER:
- opstr[i++] = '>';
- break;
- case ASL_QUERY_OP_GREATER_EQUAL:
- opstr[i++] = '>';
- opstr[i++] = '=';
- break;
- case ASL_QUERY_OP_LESS:
- opstr[i++] = '<';
- break;
- case ASL_QUERY_OP_LESS_EQUAL:
- opstr[i++] = '<';
- opstr[i++] = '=';
- break;
- case ASL_QUERY_OP_NOT_EQUAL:
- opstr[i++] = '!';
- break;
- case ASL_QUERY_OP_TRUE:
- opstr[i++] = 'T';
- break;
- default:
- break;
- }
-
- if (i == 0) return _asl_append_string(m, x, ".", ASL_ENCODE_NONE, 0);
-
- opstr[i++] = '\0';
- return _asl_append_string(m, x, opstr, ASL_ENCODE_NONE, 0);
-}
-
-static char *
-_asl_time_string(int fmt, const char *str)
-{
- time_t tick;
- struct tm *stm;
- char *ltime;
- char *out;
- char ltbuf[32];
- out = NULL;
-
- tick = 0;
- if (str != NULL) tick = asl_parse_time(str);
-
- if (fmt == TFMT_SEC)
- {
- asprintf(&out, "%lu", tick);
- return out;
- }
-
- if (fmt == TFMT_UTC)
- {
- stm = gmtime(&tick);
- asprintf(&out, "%d.%02d.%02d %02d:%02d:%02d UTC", stm->tm_year + 1900, stm->tm_mon + 1, stm->tm_mday, stm->tm_hour, stm->tm_min, stm->tm_sec);
- return out;
- }
-
- if (fmt == TFMT_LCL)
- {
- ltime = ctime_r(&tick, ltbuf);
- if (ltime == NULL) return NULL;
- ltime[19] = '\0';
- asprintf(&out, "%s", ltime);
- return out;
- }
-
- return NULL;
-}
-
-static char *
-_asl_msg_to_string_time_fmt(asl_msg_t *msg, uint32_t *len, int tf)
-{
- uint32_t i, outlen;
- char *out, *s;
-
- *len = 0;
-
- if (msg == NULL) return NULL;
-
- s = NULL;
- out = NULL;
- outlen = 0;
-
- if (msg->count == 0)
- {
- if (out == NULL) return NULL;
- *len = outlen;
- return out;
- }
-
- for (i = 0; i < msg->count; i++)
- {
- if (msg->key[i] == NULL) continue;
- if (i > 0) _asl_append_string(&out, &outlen, " [", ASL_ENCODE_NONE, 0);
- else _asl_append_string(&out, &outlen, "[", ASL_ENCODE_NONE, 0);
-
- _asl_append_string(&out, &outlen, msg->key[i], ASL_ENCODE_ASL, 1);
-
- if ((tf != TFMT_SEC) && (!strcmp(msg->key[i], ASL_KEY_TIME)))
- {
- s = _asl_time_string(tf, msg->val[i]);
- if (s != NULL)
- {
- _asl_append_string(&out, &outlen, " ", ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, &outlen, s, ASL_ENCODE_ASL, 0);
- }
- }
- else if (msg->val[i] != NULL)
- {
- _asl_append_string(&out, &outlen, " ", ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, &outlen, msg->val[i], ASL_ENCODE_ASL, 0);
- }
-
- _asl_append_string(&out, &outlen, "]", ASL_ENCODE_NONE, 0);
- }
-
- _asl_append_string(&out, &outlen, "\n", ASL_ENCODE_NONE, 0);
-
- *len = outlen;
- return out;
-}
-
-char *
-asl_msg_to_string(asl_msg_t *msg, uint32_t *len)
-{
- uint32_t i, outlen;
- char *out, *s;
-
- *len = 0;
-
- if (msg == NULL) return NULL;
-
- s = NULL;
- out = NULL;
- outlen = 0;
-
- if (msg->type == ASL_TYPE_QUERY)
- {
- _asl_append_string(&out, &outlen, "Q ", ASL_ENCODE_NONE, 0);
- if (out == NULL) return NULL;
- }
-
- if (msg->count == 0)
- {
- if (out == NULL) return NULL;
- *len = outlen;
- return out;
- }
-
- for (i = 0; i < msg->count; i++)
- {
- if (msg->key[i] == NULL) continue;
-
- if (i > 0) _asl_append_string(&out, &outlen, " [", ASL_ENCODE_NONE, 0);
- else _asl_append_string(&out, &outlen, "[", ASL_ENCODE_NONE, 0);
-
- if (msg->type == ASL_TYPE_QUERY)
- {
- _asl_append_op(&out, &outlen, msg->op[i]);
- _asl_append_string(&out, &outlen, " ", ASL_ENCODE_NONE, 0);
- }
-
- _asl_append_string(&out, &outlen, msg->key[i], ASL_ENCODE_ASL, 1);
-
- if (msg->val[i] != NULL)
- {
- _asl_append_string(&out, &outlen, " ", ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, &outlen, msg->val[i], ASL_ENCODE_ASL, 0);
- }
-
- _asl_append_string(&out, &outlen, "]", ASL_ENCODE_NONE, 0);
- }
-
- *len = outlen;
- return out;
-}
-
-static uint32_t
-_asl_msg_op_from_string(char *o)
-{
- uint32_t op, i;
-
- op = ASL_QUERY_OP_NULL;
-
- if (o == NULL) return op;
-
- for (i = 0; o[i] != '\0'; i++)
- {
- if (o[i] == '.') return ASL_QUERY_OP_NULL;
- if (o[i] == 'C') op |= ASL_QUERY_OP_CASEFOLD;
- if (o[i] == 'R') op |= ASL_QUERY_OP_REGEX;
- if (o[i] == 'N') op |= ASL_QUERY_OP_NUMERIC;
- if (o[i] == 'S') op |= ASL_QUERY_OP_SUBSTRING;
- if (o[i] == 'A') op |= ASL_QUERY_OP_PREFIX;
- if (o[i] == 'Z') op |= ASL_QUERY_OP_SUFFIX;
- if (o[i] == '<') op |= ASL_QUERY_OP_LESS;
- if (o[i] == '>') op |= ASL_QUERY_OP_GREATER;
- if (o[i] == '=') op |= ASL_QUERY_OP_EQUAL;
- if (o[i] == '!') op |= ASL_QUERY_OP_NOT_EQUAL;
- if (o[i] == 'T') op |= ASL_QUERY_OP_TRUE;
- }
-
- return op;
-}
-
-static char *
-_asl_msg_get_next_word(char **p, uint32_t *tt, uint32_t spacedel)
-{
- char *str, *out, c, oval;
- uint32_t i, len, n, outlen;
-
- *tt = TOKEN_NULL;
-
- if (p == NULL) return NULL;
- if (*p == NULL) return NULL;
- if (**p == '\0') return NULL;
-
- /* skip one space if it's there (word separator) */
- if (**p == ' ') (*p)++;
-
- /* skip leading white space */
- if (spacedel != 0)
- {
- while ((**p == ' ') || (**p == '\t')) (*p)++;
- }
-
- if (**p == '\0') return NULL;
- if (**p == '\n') return NULL;
-
- str = *p;
-
- /* opening [ */
- if (**p == '[')
- {
- *tt = TOKEN_OPEN;
-
- (*p)++;
- out = malloc(2);
- if (out == NULL) return NULL;
-
- out[0] = '[';
- out[1] = '\0';
- return out;
- }
-
- /* scan for token and calulate it's length (input and decoded output len) */
- len = 0;
- outlen = 0;
-
- forever
- {
- c = str[len];
-
- /* stop scanning when we hit a delimiter */
- if (((spacedel != 0) && (c == ' ')) || (c == ']') || (c == '\0')) break;
-
- if (c == '\\')
- {
- len++;
- c = str[len];
- if ((c == 'a') || (c == 'b') || (c == 't') || (c == 'n') || (c == 'v') || (c == 'f') || (c == 'r') || (c == 's') || (c == '[') || (c == '\\') || (c == ']'))
- {
- }
- else if (c == '^')
- {
- if (str[++len] == '\0') return NULL;
- }
- else if (c == 'M')
- {
- if (str[++len] == '\0') return NULL;
- if (str[++len] == '\0') return NULL;
- }
- else if ((c >= '0') && (c <= '3'))
- {
- if (str[++len] == '\0') return NULL;
- if (str[++len] == '\0') return NULL;
- }
- else
- {
- return NULL;
- }
- }
-
- len++;
- outlen++;
- }
-
- (*p) += len;
-
- if ((len == 0) && (**p == ']'))
- {
- *tt = TOKEN_CLOSE;
- (*p)++;
- out = malloc(2);
- if (out == NULL) return NULL;
-
- out[0] = ']';
- out[1] = '\0';
- return out;
- }
-
- *tt = TOKEN_INT;
-
- out = malloc(outlen + 1);
- if (out == NULL) return NULL;
-
- n = 0;
- for (i = 0; i < len; i++)
- {
- c = str[i];
-
- if (c == '\\')
- {
- *tt = TOKEN_WORD;
-
- i++;
- c = str[i];
- if (c == 'a')
- {
- out[n++] = '\a';
- }
- else if (c == 'b')
- {
- out[n++] = '\b';
- }
- else if (c == 't')
- {
- out[n++] = '\t';
- }
- else if (c == 'n')
- {
- out[n++] = '\n';
- }
- else if (c == 'v')
- {
- out[n++] = '\v';
- }
- else if (c == 'f')
- {
- out[n++] = '\f';
- }
- else if (c == 'r')
- {
- out[n++] = '\r';
- }
- else if (c == 's')
- {
- out[n++] = ' ';
- }
- else if (c == '[')
- {
- out[n++] = '[';
- }
- else if (c == '\\')
- {
- out[n++] = '\\';
- }
- else if (c == ']')
- {
- out[n++] = ']';
- }
- else if (c == '^')
- {
- i++;
- if (str[i] == '?') out[n++] = 127;
- else out[n++] = str[i] - 64;
- }
- else if (c == 'M')
- {
- i++;
- c = str[i];
- if (c == '^')
- {
- i++;
- if (str[i] == '?') out[n++] = 255;
- else out[n++] = str[i] + 64;
- }
- else if (c == '-')
- {
- i++;
- out[n++] = str[i] + 128;
- }
- else
- {
- *tt = TOKEN_NULL;
- free(out);
- return NULL;
- }
-
- }
- else if ((c >= '0') && (c <= '3'))
- {
- oval = (c - '0') * 64;
-
- i++;
- c = str[i];
- if ((c < '0') || (c > '7'))
- {
- *tt = TOKEN_NULL;
- free(out);
- return NULL;
- }
-
- oval += ((c - '0') * 8);
-
- i++;
- c = str[i];
- if ((c < '0') || (c > '7'))
- {
- *tt = TOKEN_NULL;
- free(out);
- return NULL;
- }
-
- oval += (c - '0');
-
- out[n++] = oval;
- }
- else
- {
- *tt = TOKEN_NULL;
- free(out);
- return NULL;
- }
- }
- else
- {
-
- if ((c < '0') || (c > '9')) *tt = TOKEN_WORD;
- out[n++] = c;
- }
- }
-
- out[n] = '\0';
-
- return out;
-}
-
-asl_msg_t *
-asl_msg_from_string(const char *buf)
-{
- uint32_t tt, type, op;
- char *k, *v, *o, *p;
- asl_msg_t *msg;
-
- if (buf == NULL) return NULL;
-
- type = ASL_TYPE_MSG;
- p = (char *)buf;
-
- k = _asl_msg_get_next_word(&p, &tt, 1);
- if (k == NULL) return NULL;
-
- if (streq(k, "Q"))
- {
- type = ASL_TYPE_QUERY;
- free(k);
-
- k = _asl_msg_get_next_word(&p, &tt, 1);
- }
- else if (tt == TOKEN_INT)
- {
- /* Leading integer is a string length - skip it */
- free(k);
- k = _asl_msg_get_next_word(&p, &tt, 1);
- if (k == NULL) return NULL;
- }
-
- msg = calloc(1, sizeof(asl_msg_t));
- if (msg == NULL) return NULL;
-
- msg->type = type;
-
- /* OPEN WORD [WORD [WORD]] CLOSE */
- while (k != NULL)
- {
- op = ASL_QUERY_OP_NULL;
-
- if (tt != TOKEN_OPEN)
- {
- asl_free(msg);
- return NULL;
- }
-
- free(k);
-
- /* get op for query type */
- if (type == ASL_TYPE_QUERY)
- {
- o = _asl_msg_get_next_word(&p, &tt, 1);
- if ((o == NULL) || (tt != TOKEN_WORD))
- {
- if (o != NULL) free(o);
- asl_free(msg);
- return NULL;
- }
-
- op = _asl_msg_op_from_string(o);
- free(o);
- }
-
- k = _asl_msg_get_next_word(&p, &tt, 1);
- if (tt == TOKEN_INT) tt = TOKEN_WORD;
- if ((k == NULL) || (tt != TOKEN_WORD))
- {
- if (k != NULL) free(k);
- asl_free(msg);
- return NULL;
- }
-
- v = _asl_msg_get_next_word(&p, &tt, 0);
- if (tt == TOKEN_INT) tt = TOKEN_WORD;
- if (v == NULL)
- {
- asl_set_query(msg, k, NULL, op);
- break;
- }
-
- if (tt == TOKEN_CLOSE)
- {
- asl_set_query(msg, k, NULL, op);
- }
- else if (tt == TOKEN_WORD)
- {
- asl_set_query(msg, k, v, op);
- }
- else
- {
- if (k != NULL) free(k);
- if (v != NULL) free(v);
- asl_free(msg);
- return NULL;
- }
-
- if (k != NULL) free(k);
- if (v != NULL) free(v);
-
- if (tt != TOKEN_CLOSE)
- {
- k = _asl_msg_get_next_word(&p, &tt, 1);
- if (k == NULL) break;
-
- if (tt != TOKEN_CLOSE)
- {
- asl_free(msg);
- return NULL;
- }
-
- free(k);
- }
-
- k = _asl_msg_get_next_word(&p, &tt, 1);
- if (k == NULL) break;
- }
-
- return msg;
-}
-
-char *
-asl_list_to_string(asl_search_result_t *list, uint32_t *outlen)
-{
- uint32_t i, len, newlen;
- char *msgbuf, *out;
-
- if (list == NULL) return NULL;
- if (list->count == 0) return NULL;
- if (list->msg == NULL) return NULL;
-
- out = NULL;
- asprintf(&out, "%u\n", list->count);
- if (out == NULL) return NULL;
- *outlen = strlen(out) + 1;
-
- for (i = 0; i < list->count; i++)
- {
- len = 0;
- msgbuf = asl_msg_to_string(list->msg[i], &len);
- if (msgbuf == NULL)
- {
- free(out);
- *outlen = 0;
- return NULL;
- }
-
- newlen = *outlen + len;
- out = reallocf(out, newlen);
- if (out == NULL)
- {
- *outlen = 0;
- return NULL;
- }
-
- memmove((out + *outlen - 1), msgbuf, len);
- out[newlen - 2] = '\n';
- out[newlen - 1] = '\0';
- *outlen = newlen;
-
- free(msgbuf);
- }
-
- return out;
-}
-
-asl_search_result_t *
-asl_list_from_string(const char *buf)
-{
- uint32_t i, n;
- const char *p;
- asl_search_result_t *out;
- asl_msg_t *m;
-
- if (buf == NULL) return NULL;
- p = buf;
-
- n = atoi(buf);
- if (n == 0) return NULL;
-
- out = (asl_search_result_t *)calloc(1, sizeof(asl_search_result_t));
- if (out == NULL) return NULL;
-
- out->msg = (asl_msg_t **)calloc(n, sizeof(asl_msg_t *));
- if (out->msg == NULL)
- {
- free(out);
- return NULL;
- }
-
- for (i = 0; i < n; i++)
- {
- p = strchr(p, '\n');
- if (p == NULL)
- {
- aslresponse_free((aslresponse)out);
- return NULL;
- }
-
- p++;
-
- m = asl_msg_from_string(p);
- if (m == NULL)
- {
- aslresponse_free((aslresponse)out);
- return NULL;
- }
-
- out->msg[i] = m;
- out->count += 1;
- }
-
- return out;
-}
-
-static int
-_asl_msg_equal(asl_msg_t *a, asl_msg_t *b)
-{
- uint32_t i, j;
-
- if (a->count != b->count) return 0;
-
- for (i = 0; i < a->count; i++)
- {
- j = _asl_msg_index(b, a->key[i]);
- if (j == (uint32_t)-1) return 0;
-
- if (a->val[i] == NULL)
- {
- if (b->val[j] != NULL) return 0;
- }
- else
- {
- if (b->val[j] == NULL) return 0;
- if (strcmp(a->val[i], b->val[j])) return 0;
- }
-
- if (a->type == ASL_TYPE_QUERY)
- {
- if (a->op[i] != b->op[j]) return 0;
- }
- }
-
- return 1;
-}
-
-static int
-_asl_isanumber(char *s)
-{
- int i;
-
- if (s == NULL) return 0;
-
- i = 0;
- if ((s[0] == '-') || (s[0] == '+')) i = 1;
-
- if (s[i] == '\0') return 0;
-
- for (; s[i] != '\0'; i++)
- {
- if (!isdigit(s[i])) return 0;
- }
-
- return 1;
-}
-
-static int
-_asl_msg_basic_test(uint32_t op, char *q, char *m, uint32_t n)
-{
- int cmp;
- uint32_t t;
- int nq, nm, rflags;
- regex_t rex;
-
- t = op & ASL_QUERY_OP_TRUE;
-
- /* NULL value from query or message string fails */
- if ((q == NULL) || (m == NULL)) return (t & ASL_QUERY_OP_NOT_EQUAL);
-
- if (op & ASL_QUERY_OP_REGEX)
- {
- /* greater than or less than make no sense in substring search */
- if ((t == ASL_QUERY_OP_GREATER) || (t == ASL_QUERY_OP_LESS)) return 0;
-
- memset(&rex, 0, sizeof(regex_t));
-
- rflags = REG_EXTENDED | REG_NOSUB;
- if (op & ASL_QUERY_OP_CASEFOLD) rflags |= REG_ICASE;
-
- /* A bad reqular expression matches nothing */
- if (regcomp(&rex, q, rflags) != 0) return (t & ASL_QUERY_OP_NOT_EQUAL);
-
- cmp = regexec(&rex, m, 0, NULL, 0);
- regfree(&rex);
-
- if (t == ASL_QUERY_OP_NOT_EQUAL) return (cmp != 0);
- return (cmp == 0);
- }
-
- if (op & ASL_QUERY_OP_NUMERIC)
- {
- if (_asl_isanumber(q) == 0) return (t == ASL_QUERY_OP_NOT_EQUAL);
- if (_asl_isanumber(m) == 0) return (t == ASL_QUERY_OP_NOT_EQUAL);
-
- nq = atoi(q);
- nm = atoi(m);
-
- switch (t)
- {
- case ASL_QUERY_OP_EQUAL: return (nm == nq);
- case ASL_QUERY_OP_GREATER: return (nm > nq);
- case ASL_QUERY_OP_GREATER_EQUAL: return (nm >= nq);
- case ASL_QUERY_OP_LESS: return (nm < nq);
- case ASL_QUERY_OP_LESS_EQUAL: return (nm <= nq);
- case ASL_QUERY_OP_NOT_EQUAL: return (nm != nq);
- default: return (t == ASL_QUERY_OP_NOT_EQUAL);
- }
- }
-
- cmp = 0;
- if (op & ASL_QUERY_OP_CASEFOLD)
- {
- if (n == 0) cmp = strcasecmp(m, q);
- else cmp = strncasecmp(m, q, n);
- }
- else
- {
- if (n == 0) cmp = strcmp(m, q);
- else cmp = strncmp(m, q, n);
- }
-
- switch (t)
- {
- case ASL_QUERY_OP_EQUAL: return (cmp == 0);
- case ASL_QUERY_OP_GREATER: return (cmp > 0);
- case ASL_QUERY_OP_GREATER_EQUAL: return (cmp >= 0);
- case ASL_QUERY_OP_LESS: return (cmp < 0);
- case ASL_QUERY_OP_LESS_EQUAL: return (cmp <= 0);
- case ASL_QUERY_OP_NOT_EQUAL: return (cmp != 0);
- }
-
- return (t == ASL_QUERY_OP_NOT_EQUAL);
-}
-
-static int
-_asl_msg_test_substring(uint32_t op, char *q, char *m)
-{
- uint32_t t, i, d, lm, lq, match, newop;
-
- t = op & ASL_QUERY_OP_TRUE;
-
- lm = 0;
- if (m != NULL) lm = strlen(m);
-
- lq = 0;
- if (q != NULL) lq = strlen(q);
-
- /* NULL is a substring of any string */
- if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
-
- /* A long string is defined to be not equal to a short string */
- if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
-
- /* greater than or less than make no sense in substring search */
- if ((t == ASL_QUERY_OP_GREATER) || (t == ASL_QUERY_OP_LESS)) return 0;
-
- /*
- * We scan the string doing an equality test.
- * If the input test is equality, we stop as soon as we hit a match.
- * Otherwise we keep scanning the whole message string.
- */
- newop = op & 0xff0;
- newop |= ASL_QUERY_OP_EQUAL;
-
- match = 0;
- d = lm - lq;
- for (i = 0; i <= d; i++)
- {
- if (_asl_msg_basic_test(newop, q, m + i, lq) != 0)
- {
- if (t & ASL_QUERY_OP_EQUAL) return 1;
- match++;
- }
- }
-
- /* If the input test was for equality, no matches were found */
- if (t & ASL_QUERY_OP_EQUAL) return 0;
-
- /* The input test was for not equal. Return true if no matches were found */
- return (match == 0);
-}
-
-static int
-_asl_msg_test_prefix(uint32_t op, char *q, char *m)
-{
- uint32_t lm, lq, t;
-
- t = op & ASL_QUERY_OP_TRUE;
-
- lm = 0;
- if (m != NULL) lm = strlen(m);
-
- lq = 0;
- if (q != NULL) lq = strlen(q);
-
- /* NULL is a prefix of any string */
- if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
-
- /* A long string is defined to be not equal to a short string */
- if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
-
- /* Compare two equal-length strings */
- return _asl_msg_basic_test(op, q, m, lq);
-}
-
-static int
-_asl_msg_test_suffix(uint32_t op, char *q, char *m)
-{
- uint32_t lm, lq, d, t;
-
- t = op & ASL_QUERY_OP_TRUE;
-
- lm = 0;
- if (m != NULL) lm = strlen(m);
-
- lq = 0;
- if (q != NULL) lq = strlen(q);
-
- /* NULL is a suffix of any string */
- if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
-
- /* A long string is defined to be not equal to a short string */
- if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
-
- /* Compare two equal-length strings */
- d = lm - lq;
- return _asl_msg_basic_test(op, q, m + d, lq);
-}
-
-/*
- * Splits out prefix, suffix, and substring tests.
- * Sends the rest to _asl_msg_basic_test().
- */
-static int
-_asl_msg_test_expression(uint32_t op, char *q, char *m)
-{
- uint32_t t;
-
- t = op & ASL_QUERY_OP_TRUE;
- if (t == ASL_QUERY_OP_TRUE) return 1;
-
- if (op & ASL_QUERY_OP_PREFIX)
- {
- if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_substring(op, q, m);
- return _asl_msg_test_prefix(op, q, m);
- }
- if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_suffix(op, q, m);
-
- return _asl_msg_basic_test(op, q, m, 0);
-}
-
-/*
- * Special case for comparing time values.
- * If both inputs are time strings, this compares the time
- * value in seconds. Otherwise it just does normal matching.
- */
-static int
-_asl_msg_test_time_expression(uint32_t op, char *q, char *m)
-{
- time_t tq, tm;
- uint32_t t;
-
- if ((op & ASL_QUERY_OP_PREFIX) || (op & ASL_QUERY_OP_SUFFIX) || (op & ASL_QUERY_OP_REGEX)) return _asl_msg_test_expression(op, q, m);
- if ((q == NULL) || (m == NULL)) return _asl_msg_test_expression(op, q, m);
-
- tq = asl_parse_time(q);
- if (tq < 0) return _asl_msg_test_expression(op, q, m);
-
- tm = asl_parse_time(m);
- if (tm < 0) return _asl_msg_test_expression(op, q, m);
-
- t = op & ASL_QUERY_OP_TRUE;
-
- switch (t)
- {
- case ASL_QUERY_OP_FALSE:
- {
- return 0;
- }
- case ASL_QUERY_OP_EQUAL:
- {
- if (tm == tq) return 1;
- return 0;
- }
- case ASL_QUERY_OP_GREATER:
- {
- if (tm > tq) return 1;
- return 0;
- }
- case ASL_QUERY_OP_GREATER_EQUAL:
- {
- if (tm >= tq) return 1;
- return 0;
- }
- case ASL_QUERY_OP_LESS:
- {
- if (tm < tq) return 1;
- return 0;
- }
- case ASL_QUERY_OP_LESS_EQUAL:
- {
- if (tm <= tq) return 1;
- return 0;
- }
- case ASL_QUERY_OP_NOT_EQUAL:
- {
- if (tm != tq) return 1;
- return 0;
- }
- case ASL_QUERY_OP_TRUE:
- {
- return 1;
- }
- }
-
- /* NOTREACHED */
- return 0;
-}
-
-/* test a query against a message */
-static int
-_asl_msg_test(asl_msg_t *q, asl_msg_t *m)
-{
- uint32_t i, j, t;
- int cmp;
-
- /*
- * Check each simple expression (key op val) separately.
- * The query suceeds (returns 1) if all simple expressions
- * succeed (i.e. AND the simple expressions).
- */
- for (i = 0; i < q->count; i++)
- {
- /* Find query key[i] in the message */
- j = _asl_msg_index(m, q->key[i]);
-
- /* NULL op is meaningless, but we allow it to succeed */
- if (q->op == NULL) continue;
-
- /* ASL_QUERY_OP_TRUE tests if key[i] is present in the message */
- t = q->op[i] & ASL_QUERY_OP_TRUE;
- if (t == ASL_QUERY_OP_TRUE)
- {
- if (j == (uint32_t)-1) return 0;
- continue;
- }
-
- /* ASL_QUERY_OP_FALSE tests if the key is NOT present in the message */
- if (t == ASL_QUERY_OP_FALSE)
- {
- if (j != (uint32_t)-1) return 0;
- continue;
- }
-
- if (j == (uint32_t)-1)
- {
- /* the message does NOT have query key[i] - fail unless we are testing not equal */
- if (t == ASL_QUERY_OP_NOT_EQUAL) continue;
- return 0;
- }
-
- cmp = 1;
- if (streq(q->key[i], ASL_KEY_TIME))
- {
- cmp = _asl_msg_test_time_expression(q->op[i], q->val[i], m->val[j]);
- }
- else
- {
- cmp = _asl_msg_test_expression(q->op[i], q->val[i], m->val[j]);
- }
+ for (i = 0; i < asl->fd_count; i++) if (asl->fd_mfmt[i] != NULL) free(asl->fd_mfmt[i]);
+ free(asl->fd_mfmt);
+ }
- if (cmp == 0) return 0;
+ if (asl->fd_tfmt != NULL)
+ {
+ for (i = 0; i < asl->fd_count; i++) if (asl->fd_tfmt[i] != NULL) free(asl->fd_tfmt[i]);
+ free(asl->fd_tfmt);
}
- return 1;
+ if (asl->fd_encoding != NULL) free(asl->fd_encoding);
+
+ memset(asl, 0, sizeof(asl_client_t));
+ free(asl);
}
-int
-asl_msg_cmp(asl_msg_t *a, asl_msg_t *b)
+__private_extern__ asl_client_t *
+_asl_open_default()
{
- if (a == NULL) return 0;
- if (b == NULL) return 0;
+ static dispatch_once_t once;
+
+ dispatch_once(&once, ^{
+ /*
+ * Do a sleight-of-hand with ASL_OPT_NO_REMOTE to avoid a deadlock
+ * since asl_open(xxx, yyy, 0) calls _asl_notify_open(1)
+ * which locks _asl_global.lock.
+ */
+ _asl_global.asl = asl_open(NULL, NULL, ASL_OPT_NO_REMOTE);
+
+ /* Reset options to clear ASL_OPT_NO_REMOTE bit */
+ if (_asl_global.asl != NULL) _asl_global.asl->options = 0;
+
+ /* Now call _asl_notify_open(0) to finish the work */
+ _asl_notify_open(0);
+ });
- if (a->type == b->type) return _asl_msg_equal(a, b);
- if (a->type == ASL_TYPE_QUERY) return _asl_msg_test(a, b);
- return _asl_msg_test(b, a);
+ return _asl_global.asl;
}
/*
return last;
}
-/*
- * asl_key: examine attribute keys
- * returns the key of the nth attribute in a message (beginning at zero)
- * returns NULL if the message has fewer attributes
- */
-const char *
-asl_key(aslmsg a, uint32_t n)
-{
- asl_msg_t *msg;
-
- msg = (asl_msg_t *)a;
- if (msg == NULL) return NULL;
-
- if (n >= msg->count) return NULL;
- return msg->key[n];
-}
-
-/*
- * asl_new: create a new log message.
- */
-aslmsg
-asl_new(uint32_t type)
-{
- uint32_t i;
- asl_msg_t *msg;
-
- msg = calloc(1, sizeof(asl_msg_t));
- if (msg == NULL) return NULL;
-
- msg->type = type;
- if (type == ASL_TYPE_QUERY) return (aslmsg)msg;
-
- /*
- * Defaut attributes are:
- * 0 Time
- * 1 Host
- * 2 Sender
- * 3 PID
- * 4 UID
- * 5 GID
- * 6 Level
- * 7 Message
- */
- msg->count = 8;
-
- msg->key = calloc(msg->count, sizeof(char *));
- if (msg->key == NULL)
- {
- free(msg);
- return NULL;
- }
-
- msg->val = calloc(msg->count, sizeof(char *));
- if (msg->val == NULL)
- {
- free(msg->key);
- free(msg);
- return NULL;
- }
-
- i = 0;
- msg->key[i] = strdup(ASL_KEY_TIME);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- i++;
- msg->key[i] = strdup(ASL_KEY_HOST);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- i++;
- msg->key[i] = strdup(ASL_KEY_SENDER);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- i++;
- msg->key[i] = strdup(ASL_KEY_PID);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- i++;
- msg->key[i] = strdup(ASL_KEY_UID);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- i++;
- msg->key[i] = strdup(ASL_KEY_GID);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- i++;
- msg->key[i] = strdup(ASL_KEY_LEVEL);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- i++;
- msg->key[i] = strdup(ASL_KEY_MSG);
- if (msg->key[i] == NULL)
- {
- asl_free(msg);
- return NULL;
- }
-
- return (aslmsg)msg;
-}
-
-/*
- * asl_get: get attribute values from a message
- * msg: an aslmsg
- * key: attribute key
- * returns the attribute value
- * returns NULL if the message does not contain the key
- */
-const char *
-asl_get(aslmsg a, const char *key)
-{
- asl_msg_t *msg;
- uint32_t i;
-
- msg = (asl_msg_t *)a;
-
- if (msg == NULL) return NULL;
-
- i = _asl_msg_index(msg, key);
- if (i == (uint32_t)-1) return NULL;
- return msg->val[i];
-}
-
#endif /* BUILDING_VARIANT */
/*
* returns 0 for success, non-zero for failure
*/
int
-asl_vlog(aslclient ac, aslmsg a, int level, const char *format, va_list ap)
+asl_vlog(aslclient ac, aslmsg msg, int level, const char *format, va_list ap)
{
- int status, saved_errno;
- asl_msg_t *msg;
- char *str, *fmt, *estr;
- uint32_t i, len, elen, expand, my_msg;
+ int saved_errno = errno;
+ int status;
+ char *str, *fmt, estr[NL_TEXTMAX];
+ uint32_t i, len, elen, expand;
asl_client_t *asl;
asl = (asl_client_t *)ac;
if (asl == NULL) return -1;
}
- saved_errno = errno;
-
if (format == NULL) return -1;
- msg = (asl_msg_t *)a;
-
- my_msg = 0;
- if (msg == NULL)
- {
- my_msg = 1;
- msg = asl_new(ASL_TYPE_MSG);
- if (msg == NULL) return -1;
- }
-
- if (msg->type != ASL_TYPE_MSG) return -1;
-
- if (level < ASL_LEVEL_EMERG) level = ASL_LEVEL_EMERG;
- if (level > ASL_LEVEL_DEBUG) level = ASL_LEVEL_DEBUG;
-
/* insert strerror for %m */
len = 0;
elen = 0;
- estr = strdup(strerror(saved_errno));
- if (estr == NULL)
- {
- if ((msg != NULL) && (my_msg != 0)) asl_free(msg);
- return -1;
- }
expand = 0;
-
- if (estr != NULL)
+ for (i = 0; format[i] != '\0'; i++)
{
- elen = strlen(estr);
-
- for (i = 0; format[i] != '\0'; i++)
+ if (format[i] == '%')
{
- if (format[i] == '%')
+ if (format[i+1] == '\0') len++;
+ else if (format[i+1] == 'm')
{
- if (format[i+1] == '\0') len++;
- else if (format[i+1] == 'm')
- {
- expand = 1;
- len += elen;
- i++;
- }
- else
- {
- len += 2;
- i++;
- }
+ expand = 1;
+ strerror_r(saved_errno, estr, sizeof(estr));
+ elen = strlen(estr);
+ len += elen;
+ i++;
+ }
+ else
+ {
+ len += 2;
+ i++;
}
- else len++;
}
+ else len++;
}
fmt = (char *)format;
if (format[i+1] == '\0')
{
}
- else if (format[i+1] == 'm')
+ else if ((format[i+1] == 'm') && (elen != 0))
{
memcpy(fmt+len, estr, elen);
len += elen;
fmt[len] = '\0';
}
- if (estr != NULL) free(estr);
-
vasprintf(&str, fmt, ap);
if (expand != 0) free(fmt);
- if (str == NULL)
- {
- if ((msg != NULL) && (my_msg != 0)) asl_free(msg);
- return -1;
- }
+ if (str == NULL) return -1;
- status = _asl_send_level_message(ac, (aslmsg)msg, level, str);
+ status = _asl_send_message(ac, (asl_msg_t *)msg, level, str);
free(str);
- if ((msg != NULL) && (my_msg != 0)) asl_free(msg);
return status;
}
#ifndef BUILDING_VARIANT
-static const char *
-_asl_level_string(int level)
+static asl_msg_t *
+_asl_merge_msg_aux0(asl_msg_t *msg, asl_msg_aux_0_t aux0)
{
- if (level == ASL_LEVEL_EMERG) return ASL_STRING_EMERG;
- if (level == ASL_LEVEL_ALERT) return ASL_STRING_ALERT;
- if (level == ASL_LEVEL_CRIT) return ASL_STRING_CRIT;
- if (level == ASL_LEVEL_ERR) return ASL_STRING_ERR;
- if (level == ASL_LEVEL_WARNING) return ASL_STRING_WARNING;
- if (level == ASL_LEVEL_NOTICE) return ASL_STRING_NOTICE;
- if (level == ASL_LEVEL_INFO) return ASL_STRING_INFO;
- if (level == ASL_LEVEL_DEBUG) return ASL_STRING_DEBUG;
- return "Unknown";
-}
-
-/*
- * format a message for printing
- * out parameter len returns string length including trailing NUL
- */
-char *
-asl_format_message(aslmsg msg, const char *mfmt, const char *tfmt, uint32_t text_encoding, uint32_t *len)
-{
- char *out, *tstr, *k, c[2];
- const char *hstr, *sstr, *pstr, *mstr, *lstr, *rprc, *rpid, *v;
- int i, j, l, mf, tf, paren, oval, level;
-
- out = NULL;
- *len = 0;
+ const char *key, *val;
+ asl_msg_t *out;
+ uint32_t x;
+ int klevel, ktime, knano, khost, ksender, kfac, kpid, kuid, kgid, kmsg, kaux, kuti, kurl;
- if (msg == NULL) return NULL;
-
- mf = MFMT_RAW;
- tf = TFMT_SEC;
-
- if (mfmt == NULL) mf = MFMT_RAW;
- else if (!strcmp(mfmt, ASL_MSG_FMT_RAW)) mf = MFMT_RAW;
- else if (!strcmp(mfmt, ASL_MSG_FMT_STD)) mf = MFMT_STD;
- else if (!strcmp(mfmt, ASL_MSG_FMT_BSD)) mf = MFMT_BSD;
- else if (!strcmp(mfmt, ASL_MSG_FMT_XML)) mf = MFMT_XML;
- else if (!strcmp(mfmt, ASL_MSG_FMT_MSG)) mf = MFMT_MSG;
- else mf = MFMT_STR;
-
- if (tfmt == NULL) tf = TFMT_SEC;
- else if (!strcmp(tfmt, ASL_TIME_FMT_SEC)) tf = TFMT_SEC;
- else if (!strcmp(tfmt, ASL_TIME_FMT_UTC)) tf = TFMT_UTC;
- else if (!strcmp(tfmt, ASL_TIME_FMT_LCL)) tf = TFMT_LCL;
-
- if (mf == MFMT_RAW)
- {
- out = _asl_msg_to_string_time_fmt((asl_msg_t *)msg, len, tf);
- return out;
- }
-
- if (mf == MFMT_MSG)
- {
- mstr = asl_get(msg, ASL_KEY_MSG);
- if (mstr == NULL) return NULL;
+ out = asl_msg_new(ASL_TYPE_MSG);
+ if (out == NULL) return NULL;
- _asl_append_string(&out, len, mstr, text_encoding, 0);
- _asl_append_string(&out, len, "\n", ASL_ENCODE_NONE, 0);
+ klevel = 0;
+ ktime = 0;
+ knano = 0;
+ khost = 0;
+ ksender= 0;
+ kfac = 0;
+ kpid = 0;
+ kuid = 0;
+ kgid = 0;
+ kmsg = 0;
+ kaux = 0;
+ kuti = 0;
+ kurl = 0;
- return out;
- }
+ key = NULL;
+ val = NULL;
- if ((mf == MFMT_STD) || (mf == MFMT_BSD))
+ for (x = asl_msg_fetch(msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch(msg, x, &key, &val, NULL))
{
- /* BSD: Mth dd hh:mm:ss host sender[pid]: message */
- /* BSD: Mth dd hh:mm:ss host sender[pid] (refproc[refpid]): message */
- /* STD: Mth dd hh:mm:ss host sender[pid] <Level>: message */
- /* STD: Mth dd hh:mm:ss host sender[pid] (refproc[refpid]) <Level>: message */
-
- v = asl_get(msg, ASL_KEY_TIME);
- tstr = _asl_time_string(tf, v);
-
- hstr = asl_get(msg, ASL_KEY_HOST);
- sstr = asl_get(msg, ASL_KEY_SENDER);
- pstr = asl_get(msg, ASL_KEY_PID);
- mstr = asl_get(msg, ASL_KEY_MSG);
-
- rprc = asl_get(msg, ASL_KEY_REF_PROC);
- rpid = asl_get(msg, ASL_KEY_REF_PID);
-
- level = -1;
-
- if (mf == MFMT_STD)
+ if (streq(key, ASL_KEY_LEVEL))
{
- lstr = asl_get(msg, ASL_KEY_LEVEL);
- if (lstr != NULL) level = atoi(lstr);
+ klevel = 1;
+ if (aux0.level != NULL) asl_msg_set_key_val(out, key, aux0.level);
+ else asl_msg_set_key_val(out, key, val);
}
-
- if (tstr == NULL)
+ else if (streq(key, ASL_KEY_TIME))
{
- _asl_append_string(&out, len, "0", ASL_ENCODE_NONE, 0);
+ ktime = 1;
+ if (aux0.time != NULL) asl_msg_set_key_val(out, key, aux0.time);
+ else asl_msg_set_key_val(out, key, val);
}
- else
+ else if (streq(key, ASL_KEY_TIME_NSEC))
{
- _asl_append_string(&out, len, tstr, ASL_ENCODE_NONE, 0);
- free(tstr);
+ knano = 1;
+ if (aux0.nano != NULL) asl_msg_set_key_val(out, key, aux0.nano);
+ else asl_msg_set_key_val(out, key, val);
}
-
- _asl_append_string(&out, len, " ", ASL_ENCODE_NONE, 0);
-
- if (hstr == NULL) _asl_append_string(&out, len, "unknown", ASL_ENCODE_NONE, 0);
- else _asl_append_string(&out, len, hstr, text_encoding, 0);
-
- _asl_append_string(&out, len, " ", ASL_ENCODE_NONE, 0);
-
- if (sstr == NULL) _asl_append_string(&out, len, "unknown", ASL_ENCODE_NONE, 0);
- else _asl_append_string(&out, len, sstr, text_encoding, 0);
-
- if ((pstr != NULL) && (strcmp(pstr, "-1")))
+ else if (streq(key, ASL_KEY_HOST))
{
- _asl_append_string(&out, len, "[", ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, len, pstr, ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, len, "]", ASL_ENCODE_NONE, 0);
+ khost = 1;
+ if (aux0.host != NULL) asl_msg_set_key_val(out, key, aux0.host);
+ else asl_msg_set_key_val(out, key, val);
}
-
- if ((rprc != NULL) || (rpid != NULL)) _asl_append_string(&out, len, " (", ASL_ENCODE_NONE, 0);
-
- if (rprc != NULL) _asl_append_string(&out, len, rprc, text_encoding, 0);
- if (rpid != NULL)
+ else if (streq(key, ASL_KEY_SENDER))
{
- _asl_append_string(&out, len, "[", ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, len, rpid, ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, len, "]", ASL_ENCODE_NONE, 0);
+ ksender = 1;
+ if (aux0.sender != NULL) asl_msg_set_key_val(out, key, aux0.sender);
+ else asl_msg_set_key_val(out, key, val);
}
-
- if ((rprc != NULL) || (rpid != NULL)) _asl_append_string(&out, len, ")", ASL_ENCODE_NONE, 0);
-
- if (mf == MFMT_STD)
+ else if (streq(key, ASL_KEY_FACILITY))
{
- _asl_append_string(&out, len, " <", ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, len, _asl_level_string(level), ASL_ENCODE_NONE, 0);
- _asl_append_string(&out, len, ">", ASL_ENCODE_NONE, 0);
+ kfac = 1;
+ if (aux0.facility != NULL) asl_msg_set_key_val(out, key, aux0.facility);
+ else asl_msg_set_key_val(out, key, val);
}
-
- _asl_append_string(&out, len, ": ", ASL_ENCODE_NONE, 0);
-
- if (mstr != NULL) _asl_append_string(&out, len, mstr, text_encoding, 0);
-
- _asl_append_string(&out, len, "\n", ASL_ENCODE_NONE, 0);
- return out;
- }
-
- if (mf == MFMT_XML)
- {
- _asl_append_string(&out, len, "\t<dict>\n", ASL_ENCODE_NONE, 0);
-
- for (i = 0; i < msg->count; i++)
+ else if (streq(key, ASL_KEY_PID))
{
- if (asl_is_utf8(msg->key[i]) == 1)
- {
- _asl_append_xml_tag(&out, len, XML_TAG_KEY, msg->key[i]);
- if (!strcmp(msg->key[i], ASL_KEY_TIME))
- {
- tstr = _asl_time_string(tf, msg->val[i]);
- _asl_append_xml_tag(&out, len, XML_TAG_STRING, tstr);
- if (tstr != NULL) free(tstr);
- }
- else
- {
- if (asl_is_utf8(msg->val[i]) == 1) _asl_append_xml_tag(&out, len, XML_TAG_STRING, msg->val[i]);
- else _asl_append_xml_tag(&out, len, XML_TAG_DATA, msg->val[i]);
- }
- }
+ kpid = 1;
+ if (aux0.pid != NULL) asl_msg_set_key_val(out, key, aux0.pid);
+ else asl_msg_set_key_val(out, key, val);
}
-
- _asl_append_string(&out, len, "\t</dict>\n", ASL_ENCODE_NONE, 0);
-
- return out;
- }
-
- c[1] = '\0';
-
- for (i = 0; mfmt[i] != '\0'; i++)
- {
- if (mfmt[i] == '$')
+ else if (streq(key, ASL_KEY_UID))
+ {
+ kuid = 1;
+ if (aux0.uid != NULL) asl_msg_set_key_val(out, key, aux0.uid);
+ else asl_msg_set_key_val(out, key, val);
+ }
+ else if (streq(key, ASL_KEY_GID))
+ {
+ kgid = 1;
+ if (aux0.gid != NULL) asl_msg_set_key_val(out, key, aux0.gid);
+ else asl_msg_set_key_val(out, key, val);
+ }
+ else if (streq(key, ASL_KEY_MSG))
+ {
+ kmsg = 1;
+ if (aux0.message != NULL) asl_msg_set_key_val(out, key, aux0.message);
+ else asl_msg_set_key_val(out, key, val);
+ }
+ else if (streq(key, ASL_KEY_AUX_TITLE))
+ {
+ kaux = 1;
+ if (aux0.auxtitle != NULL) asl_msg_set_key_val(out, key, aux0.auxtitle);
+ else asl_msg_set_key_val(out, key, val);
+ }
+ else if (streq(key, ASL_KEY_AUX_UTI))
+ {
+ kuti = 1;
+ if (aux0.auxuti != NULL) asl_msg_set_key_val(out, key, aux0.auxuti);
+ else asl_msg_set_key_val(out, key, val);
+ }
+ else if (streq(key, ASL_KEY_AUX_URL))
+ {
+ kurl = 1;
+ if (aux0.auxurl != NULL) asl_msg_set_key_val(out, key, aux0.auxurl);
+ else asl_msg_set_key_val(out, key, val);
+ }
+ else
{
- i++;
- paren = 0;
+ asl_msg_set_key_val(out, key, val);
+ }
+ }
- if (mfmt[i] == '(')
- {
- paren = 1;
- i++;
- }
+ if ((klevel == 0) && (aux0.level != NULL)) asl_msg_set_key_val(out, ASL_KEY_LEVEL, aux0.level);
+ if ((ktime == 0) && (aux0.time != NULL)) asl_msg_set_key_val(out, ASL_KEY_TIME, aux0.time);
+ if ((knano == 0) && (aux0.nano != NULL)) asl_msg_set_key_val(out, ASL_KEY_TIME_NSEC, aux0.nano);
+ if ((khost == 0) && (aux0.host != NULL)) asl_msg_set_key_val(out, ASL_KEY_HOST, aux0.host);
+ if ((ksender == 0) && (aux0.sender != NULL)) asl_msg_set_key_val(out, ASL_KEY_SENDER, aux0.sender);
+ if ((kfac == 0) && (aux0.facility != NULL)) asl_msg_set_key_val(out, ASL_KEY_FACILITY, aux0.facility);
+ if ((kpid == 0) && (aux0.pid != NULL)) asl_msg_set_key_val(out, ASL_KEY_PID, aux0.pid);
+ if ((kuid == 0) && (aux0.uid != NULL)) asl_msg_set_key_val(out, ASL_KEY_UID, aux0.uid);
+ if ((kgid == 0) && (aux0.gid != NULL)) asl_msg_set_key_val(out, ASL_KEY_GID, aux0.gid);
+ if ((kmsg == 0) && (aux0.message != NULL)) asl_msg_set_key_val(out, ASL_KEY_MSG, aux0.message);
+ if ((kaux == 0) && (aux0.auxtitle != NULL)) asl_msg_set_key_val(out, ASL_KEY_AUX_TITLE, aux0.auxtitle);
+ if ((kuti == 0) && (aux0.auxuti != NULL)) asl_msg_set_key_val(out, ASL_KEY_AUX_UTI, aux0.auxuti);
+ if ((kurl == 0) && (aux0.auxurl != NULL)) asl_msg_set_key_val(out, ASL_KEY_AUX_URL, aux0.auxurl);
- k = calloc(1, 1);
- if (k == NULL)
- {
- if (out != NULL) free(out);
- return NULL;
- }
+ return out;
+}
- l = 0;
+/*
+ * asl_get_filter: gets the values for the local, master, and remote filters,
+ * and indicates which one is active.
+ */
+int
+asl_get_filter(aslclient ac, int *local, int *master, int *remote, int *active)
+{
+ asl_client_t *asl, *asl_default;
+ int l, m, r, x;
+ int status, check;
+ uint64_t v64;
- for (j = i; mfmt[j] != '\0'; j++)
- {
- c[0] = '\0';
- if (mfmt[j] == '\\') c[0] = mfmt[++j];
- else if ((paren == 1) && (mfmt[j] ==')')) break;
- else if (mfmt[j] != ' ') c[0] = mfmt[j];
+ l = 0;
+ m = 0;
+ r = 0;
+ x = 0;
- if (c[0] == '\0') break;
+ asl_default = _asl_open_default();
- k = reallocf(k, l + 1);
- if (k == NULL)
- {
- if (out != NULL) free(out);
- return NULL;
- }
+ asl = (asl_client_t *)ac;
+ if (asl == NULL) asl = asl_default;
+ if (asl != NULL) l = asl->filter & 0xff;
- k[l] = c[0];
- k[l + 1] = '\0';
- l++;
- }
+ if ((asl_default != NULL) && (!(asl_default->options & ASL_OPT_NO_REMOTE)))
+ {
+ pthread_mutex_lock(&_asl_global.lock);
- if (paren == 1) j++;
- i = j;
- if (l > 0)
+ if (_asl_global.rc_change_token >= 0)
+ {
+ /* initialize or re-check process-specific and master filters */
+ check = 0;
+ status = notify_check(_asl_global.rc_change_token, &check);
+ if ((status == NOTIFY_STATUS_OK) && (check != 0))
{
- v = asl_get(msg, k);
- if (v != NULL)
+ if (_asl_global.master_token >= 0)
{
- if (!strcmp(k, ASL_KEY_TIME))
- {
- tstr = _asl_time_string(tf, v);
- _asl_append_string(&out, len, tstr, ASL_ENCODE_NONE, 0);
- if (tstr != NULL) free(tstr);
- }
- else
- {
- _asl_append_string(&out, len, (char *)v, ASL_ENCODE_NONE, 0);
- }
+ v64 = 0;
+ status = notify_get_state(_asl_global.master_token, &v64);
+ if (status == NOTIFY_STATUS_OK) _asl_global.master_filter = v64;
}
- }
- free(k);
- }
- if (mfmt[i] == '\\')
- {
- i++;
- if (mfmt[i] == '$') _asl_append_string(&out, len, "$", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 'e') _asl_append_string(&out, len, "\e", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 's') _asl_append_string(&out, len, " ", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 'a') _asl_append_string(&out, len, "\a", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 'b') _asl_append_string(&out, len, "\b", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 'f') _asl_append_string(&out, len, "\f", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 'n') _asl_append_string(&out, len, "\n", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 'r') _asl_append_string(&out, len, "\r", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 't') _asl_append_string(&out, len, "\t", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == 'v') _asl_append_string(&out, len, "\v", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == '\'') _asl_append_string(&out, len, "\'", ASL_ENCODE_NONE, 0);
- else if (mfmt[i] == '\\') _asl_append_string(&out, len, "\\", ASL_ENCODE_NONE, 0);
- else if (isdigit(mfmt[i]))
- {
- oval = mfmt[i] - '0';
- if (isdigit(mfmt[i+1]))
+ if (_asl_global.notify_token >= 0)
{
- i++;
- oval = (oval * 8) + (mfmt[i] - '0');
- if (isdigit(mfmt[i+1]))
- {
- i++;
- oval = (oval * 8) + (mfmt[i] - '0');
- }
+ v64 = 0;
+ status = notify_get_state(_asl_global.notify_token, &v64);
+ if (status == NOTIFY_STATUS_OK) _asl_global.proc_filter = v64;
}
- c[0] = oval;
- _asl_append_string(&out, len, c, ASL_ENCODE_NONE, 0);
}
- continue;
}
- if (mfmt[i] == '\0') break;
- c[0] = mfmt[i];
- _asl_append_string(&out, len, c, ASL_ENCODE_NONE, 0);
+ m = _asl_global.master_filter;
+ if (m != 0) x = 1;
+
+ r = _asl_global.proc_filter;
+ if (r != 0) x = 2;
+
+ pthread_mutex_unlock(&_asl_global.lock);
}
- _asl_append_string(&out, len, "\n", ASL_ENCODE_NONE, 0);
+ if (local != NULL) *local = l;
+ if (master != NULL) *master = m;
+ if (remote != NULL) *remote = r;
+ if (active != NULL) *active = x;
- return out;
+ return 0;
}
/*
- * asl_send (internal version): send a message
+ * asl_send: send a message
* This routine may be used instead of asl_log() or asl_vlog() if asl_set()
* has been used to set all of a message's attributes.
+ * msg: an aslmsg
* returns 0 for success, non-zero for failure
*/
__private_extern__ int
-_asl_send_level_message(aslclient ac, aslmsg msg, int level, const char *message)
+_asl_send_message(aslclient ac, asl_msg_t *msg, int slevel, const char *aux_message)
{
- char *str, *out_raw;
vm_address_t out;
- uint32_t i, len, outlen, lmask, outstatus, filter, check, senderx, facilityx;
+ uint32_t i, len, outlen, level, lmask, outstatus, filter, fd_write;
uint64_t v64;
const char *val;
- char *name, *x;
+ char *name, *x, *str;
time_t tick;
struct timeval tval;
- int status, rc_filter;
+ int status, check, tunnel;
asl_client_t *asl;
int use_global_lock;
- asl_msg_t *mt, *tmp_msg;
- char hname[_POSIX_HOST_NAME_MAX];
kern_return_t kstatus;
+ char aux_level[64], aux_time[64], aux_nano[64], aux_pid[64], aux_uid[64], aux_gid[64];
+ char *aux_option, aux_host[_POSIX_HOST_NAME_MAX];
+ asl_msg_aux_t aux;
+ asl_msg_aux_0_t aux0;
use_global_lock = 0;
asl = (asl_client_t *)ac;
use_global_lock = 1;
}
- if (msg == NULL) return 0;
+ if (asl->aslfile != NULL)
+ {
+ use_global_lock = 1;
+ }
+
+ level = ASL_LEVEL_DEBUG;
+ if (slevel >= 0) level = slevel;
- val = asl_get(msg, ASL_KEY_LEVEL);
- if (val != NULL) level = atoi(val);
+ val = asl_get((aslmsg)msg, ASL_KEY_LEVEL);
+ if (val != NULL)
+ {
+ check = atoi(val);
+ if (check < ASL_LEVEL_EMERG) check = ASL_LEVEL_EMERG;
+ else if (check > ASL_LEVEL_DEBUG) check = ASL_LEVEL_DEBUG;
+ level = check;
+ }
lmask = ASL_FILTER_MASK(level);
pthread_mutex_unlock(&_asl_global.lock);
}
- filter = asl->filter;
- rc_filter = 0;
+ filter = asl->filter & 0xff;
+ tunnel = (asl->filter & ASL_FILTER_MASK_TUNNEL) >> 8;
/* master filter overrides local filter */
if (_asl_global.master_filter != 0)
{
filter = _asl_global.master_filter;
- rc_filter = 1;
+ tunnel = 1;
}
/* process-specific filter overrides local and master */
if (_asl_global.proc_filter != 0)
{
filter = _asl_global.proc_filter;
- rc_filter = 1;
+ tunnel = 1;
}
- /*
- * Copy the message to tmp_msg to make setting values thread-safe
+ /*
+ * Time, TimeNanoSec, Host, PID, UID, and GID values get set here.
+ * Also sets Sender & Facility (if unset) and "ASLOption store" if remote control is active.
*/
- tmp_msg = calloc(1, sizeof(asl_msg_t));
- if (tmp_msg == NULL) return -1;
- tmp_msg->type = ASL_TYPE_MSG;
+ aux.type = ASL_MSG_TYPE_AUX_0;
- mt = (asl_msg_t *)msg;
- for (i = 0; i < mt->count; i++)
- {
- asl_set(tmp_msg, mt->key[i], mt->val[i]);
- }
+ memset(&aux0, 0, sizeof(asl_msg_aux_0_t));
+ aux.data.aux0 = &aux0;
- /*
- * Set Level and Message from parameters.
- */
- if (message != NULL) asl_set(tmp_msg, ASL_KEY_MSG, message);
- asl_set(tmp_msg, ASL_KEY_LEVEL, _asl_level_string(level));
+ aux0.message = aux_message;
+
+ snprintf(aux_level, sizeof(aux_level), "%u", level);
+ aux0.level = aux_level;
- /*
- * Time, TimeNanoSec, Host, PID, UID, and GID values get set here
- */
- str = NULL;
memset(&tval, 0, sizeof(struct timeval));
status = gettimeofday(&tval, NULL);
if (status == 0)
{
- asprintf(&str, "%lu", tval.tv_sec);
- if (str != NULL)
- {
- asl_set(tmp_msg, ASL_KEY_TIME, str);
- free(str);
- str = NULL;
- }
-
- asprintf(&str, "%lu", tval.tv_usec * 1000);
- if (str != NULL)
- {
- asl_set(tmp_msg, ASL_KEY_TIME_NSEC, str);
- free(str);
- str = NULL;
- }
+ snprintf(aux_time, sizeof(aux_time), "%lu", tval.tv_sec);
+ snprintf(aux_nano, sizeof(aux_nano), "%d", tval.tv_usec * 1000);
+ aux0.time = aux_time;
+ aux0.nano = aux_nano;
}
else
{
tick = time(NULL);
- asprintf(&str, "%lu", tick);
- if (str != NULL)
- {
- asl_set(tmp_msg, ASL_KEY_TIME, str);
- free(str);
- str = NULL;
- }
- }
-
- memset(&hname, 0, _POSIX_HOST_NAME_MAX);
- if (gethostname(hname, _POSIX_HOST_NAME_MAX) == 0)
- {
- asl_set(tmp_msg, ASL_KEY_HOST, hname);
- }
-
- str = NULL;
- asprintf(&str, "%u", getpid());
- if (str != NULL)
- {
- asl_set(tmp_msg, ASL_KEY_PID, str);
- free(str);
+ snprintf(aux_time, sizeof(aux_time), "%lu", tick);
+ aux0.time = aux_time;
}
- str = NULL;
- asprintf(&str, "%d", getuid());
- if (str != NULL)
+ memset(&aux_host, 0, _POSIX_HOST_NAME_MAX);
+ if (gethostname(aux_host, _POSIX_HOST_NAME_MAX) == 0)
{
- asl_set(tmp_msg, ASL_KEY_UID, str);
- free(str);
+ aux0.host = aux_host;
}
- str = NULL;
- asprintf(&str, "%u", getgid());
- if (str != NULL)
- {
- asl_set(tmp_msg, ASL_KEY_GID, str);
- free(str);
- }
+ snprintf(aux_pid, sizeof(aux_pid), "%u", getpid());
+ aux0.pid = aux_pid;
- senderx = (uint32_t)-1;
- facilityx = (uint32_t)-1;
+ snprintf(aux_uid, sizeof(aux_uid), "%d", getuid());
+ aux0.uid = aux_uid;
- for (i = 0; (i < tmp_msg->count) && ((senderx == (uint32_t)-1) || (facilityx == (uint32_t)-1)); i++)
- {
- if (tmp_msg->key[i] == NULL) continue;
- if (streq(tmp_msg->key[i], ASL_KEY_SENDER)) senderx = i;
- else if (streq(tmp_msg->key[i], ASL_KEY_FACILITY)) facilityx = i;
- }
+ snprintf(aux_gid, sizeof(aux_uid), "%d", getgid());
+ aux0.gid = aux_gid;
/*
* Set Sender if needed
*/
- if ((senderx == (uint32_t)-1) || (tmp_msg->val[senderx] == NULL))
+ status = asl_msg_lookup((asl_msg_t *)msg, ASL_KEY_SENDER, &val, NULL);
+ if ((status != 0) || (val == NULL))
{
if ((ac != NULL) && (ac->name != NULL))
{
/* Use the Sender name from the client handle */
- asl_set(tmp_msg, ASL_KEY_SENDER, ac->name);
+ aux0.sender = ac->name;
}
else
{
else x = name;
pthread_mutex_lock(&_asl_global.lock);
-
if (_asl_global.sender == NULL) _asl_global.sender = strdup(x);
pthread_mutex_unlock(&_asl_global.lock);
}
}
- if (_asl_global.sender != NULL) asl_set(tmp_msg, ASL_KEY_SENDER, _asl_global.sender);
- else asl_set(tmp_msg, ASL_KEY_SENDER, "Unknown");
+ if (_asl_global.sender != NULL) aux0.sender = _asl_global.sender;
+ else aux0.sender = "Unknown";
}
}
/*
* Set Facility
*/
- if ((facilityx == (uint32_t)-1) || (tmp_msg->val[facilityx] == NULL))
+ status = asl_msg_lookup((asl_msg_t *)msg, ASL_KEY_FACILITY, &val, NULL);
+ if ((status != 0) || (val == NULL))
{
if ((ac != NULL) && (ac->facility != NULL))
{
/* Use the Facility name from the client handle */
- asl_set(tmp_msg, ASL_KEY_FACILITY, ac->facility);
+ aux0.facility = ac->facility;
}
}
/* Set "ASLOption store" if remote control is active */
- if (rc_filter != 0)
+
+ aux_option = NULL;
+
+ if (tunnel != 0)
{
- val = asl_get(msg, ASL_KEY_OPTION);
+ val = asl_get((aslmsg)msg, ASL_KEY_OPTION);
if (val == NULL)
{
- asl_set(tmp_msg, ASL_KEY_OPTION, ASL_OPT_STORE);
+ aux0.option = ASL_OPT_STORE;
}
else
{
- str = NULL;
- asprintf(&str, "%s %s", ASL_OPT_STORE, val);
- if (str != NULL)
- {
- asl_set(tmp_msg, ASL_KEY_OPTION, str);
- free(str);
- str = NULL;
- }
+ asprintf(&aux_option, "%s %s", ASL_OPT_STORE, val);
+ aux0.option = aux_option;
}
}
if (use_global_lock != 0) pthread_mutex_lock(&_asl_global.lock);
- if ((filter != 0) && ((filter & lmask) != 0))
+ /*
+ * If there is an aslfile this is a stand-alone file client.
+ * Just save to the file.
+ */
+ if (asl->aslfile != NULL)
{
- len = 0;
- out_raw = asl_msg_to_string(tmp_msg, &len);
+ asl_msg_t *merged_msg;
+
+ outstatus = ASL_STATUS_FAILED;
+
+ merged_msg = _asl_merge_msg_aux0(msg, aux0);
+ if (merged_msg != NULL)
+ {
+ outstatus = asl_file_save(asl->aslfile, (aslmsg)merged_msg, &(asl->aslfileid));
+ asl->aslfileid++;
+ asl_msg_release(merged_msg);
+ }
+
+ if (use_global_lock != 0) pthread_mutex_unlock(&_asl_global.lock);
+ return outstatus;
+ }
+
+ _asl_global_init();
+ if ((_asl_global.server_port != MACH_PORT_NULL) && (filter != 0) && ((filter & lmask) != 0))
+ {
+ len = _asl_msg_string_length_aux(msg, &aux);
- if ((out_raw != NULL) && (len != 0))
+ if (len != 0)
{
/* send a mach message to syslogd */
out = 0;
outlen = len + 11;
- kstatus = vm_allocate(mach_task_self(), &out, outlen + 1, TRUE);
+ kstatus = vm_allocate(mach_task_self(), &out, outlen, TRUE);
if (kstatus == KERN_SUCCESS)
{
- memset((void *)out, 0, outlen + 1);
- snprintf((char *)out, outlen, "%10u %s", len, out_raw);
+ memset((void *)out, 0, outlen);
+ snprintf((char *)out, 12, "%10u ", len);
- status = 0;
-
- pthread_mutex_lock(&(_asl_global.port_lock));
-
- if (_asl_global.server_port == MACH_PORT_NULL)
+ status = _asl_msg_to_string_buffer_aux(msg, &aux, (char *)(out + 11), len);
+ if (status == 0)
{
- _asl_global.port_count = 0;
+ if (kstatus == KERN_SUCCESS) kstatus = _asl_server_message(_asl_global.server_port, (caddr_t)out, outlen);
+ else vm_deallocate(mach_task_self(), out, outlen);
- kstatus = bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &_asl_global.server_port);
- if (kstatus == KERN_SUCCESS) _asl_global.port_count = 1;
- else _asl_global.server_port = MACH_PORT_NULL;
+ if (kstatus == KERN_SUCCESS) outstatus = 0;
+ }
+ else
+ {
+ vm_deallocate(mach_task_self(), (vm_address_t)out, outlen);
}
-
- pthread_mutex_unlock(&(_asl_global.port_lock));
-
- if (kstatus == KERN_SUCCESS) kstatus = _asl_server_message(_asl_global.server_port, (caddr_t)out, outlen + 1);
- else vm_deallocate(mach_task_self(), out, outlen + 1);
-
- if (kstatus == KERN_SUCCESS) outstatus = 0;
}
-
- free(out_raw);
}
}
+ if (aux_option != NULL) free(aux_option);
+ aux0.option = NULL;
+
outstatus = 0;
- /* write to file descriptors */
- for (i = 0; i < asl->fd_count; i++)
+ /* messages from syslog() get filtered on the way out to stderr */
+ fd_write = 1;
+ if ((asl->options & ASL_OPT_SYSLOG_LEGACY) && (filter != 0) && ((filter & lmask) == 0)) fd_write = 0;
+
+ if ((fd_write != 0) && (asl->fd_count > 0))
{
- if (asl->fd_list[i] < 0) continue;
+ asl_msg_t *merged_msg;
- len = 0;
- str = asl_format_message(tmp_msg, asl->fd_mfmt[i], asl->fd_tfmt[i], asl->fd_encoding[i], &len);
- if (str == NULL) continue;
+ /*
+ * It's easier to merge the aux fields with the msg into a new message
+ * than to have asl_format_messge deal with two inputs. Since this is
+ * an infrequently used code path, we pay a small price to merge them
+ * here and save a lot of code complexity.
+ */
- status = write(asl->fd_list[i], str, len - 1);
- if (status < 0)
+ merged_msg = _asl_merge_msg_aux0(msg, aux0);
+ if (merged_msg != NULL)
{
- asl->fd_list[i] = -1;
- outstatus = -1;
- }
+ /* write to file descriptors */
- free(str);
- }
+ for (i = 0; i < asl->fd_count; i++)
+ {
+ if (asl->fd_list[i] < 0) continue;
+
+ len = 0;
+ str = asl_format_message(merged_msg, asl->fd_mfmt[i], asl->fd_tfmt[i], asl->fd_encoding[i], &len);
+ if (str == NULL) continue;
- asl_free((aslmsg)tmp_msg);
+ status = write(asl->fd_list[i], str, len - 1);
+ if (status < 0)
+ {
+ asl->fd_list[i] = -1;
+ outstatus = -1;
+ }
+
+ free(str);
+ }
+
+ asl_msg_release(merged_msg);
+ }
+ }
if (use_global_lock != 0) pthread_mutex_unlock(&_asl_global.lock);
return outstatus;
}
-/*
- * asl_send: send a message
- * returns 0 for success, non-zero for failure
- */
int
asl_send(aslclient ac, aslmsg msg)
{
- return _asl_send_level_message(ac, msg, ASL_LEVEL_DEBUG, NULL);
+ return _asl_send_message(ac, (asl_msg_t *)msg, -1, NULL);
}
-char *
-asl_msg_string(aslmsg a)
+static int
+_asl_aux_save_context(asl_aux_context_t *ctx)
{
- uint32_t len;
+ if (ctx == NULL) return -1;
+
+ pthread_mutex_lock(&_asl_global.lock);
- return asl_msg_to_string((asl_msg_t *)a, &len);
+ _asl_global.aux_ctx = (asl_aux_context_t **)reallocf(_asl_global.aux_ctx, (_asl_global.aux_count + 1) * sizeof(asl_aux_context_t *));
+ if (_asl_global.aux_ctx == NULL)
+ {
+ _asl_global.aux_count = 0;
+ return -1;
+ }
+
+ _asl_global.aux_ctx[_asl_global.aux_count++] = ctx;
+
+ pthread_mutex_unlock(&_asl_global.lock);
+
+ return 0;
}
/*
- * asl_free: free a message
- * msg: an aslmsg to free
+ * Creates an auxiliary file that may be used to save arbitrary data. The ASL message msg
+ * will be saved at the time that the auxiliary file is created. The message will include
+ * any keys and values found in msg, and it will include the title and Uniform Type
+ * Identifier specified. Output parameter out_fd will contain the file descriptor of the
+ * new auxiliary file.
*/
-void
-asl_free(aslmsg a)
+static int
+_asl_auxiliary(aslmsg msg, const char *title, const char *uti, const char *url, int *out_fd)
{
- uint32_t i;
- asl_msg_t *msg;
+ asl_msg_t *merged_msg;
+ asl_msg_aux_t aux;
+ asl_msg_aux_0_t aux0;
+ fileport_t fileport;
+ kern_return_t kstatus;
+ uint32_t outlen, newurllen, len, where;
+ int status, fd, fdpair[2];
+ caddr_t out, newurl;
+ dispatch_queue_t pipe_q;
+ dispatch_io_t pipe_channel;
+ dispatch_semaphore_t sem;
+
+ aux.type = ASL_MSG_TYPE_AUX_0;
- msg = (asl_msg_t *)a;
+ memset(&aux0, 0, sizeof(asl_msg_aux_0_t));
+ aux.data.aux0 = &aux0;
- if (msg == NULL) return;
+ aux0.auxtitle = title;
+ if (uti == NULL) aux0.auxuti = "public.data";
+ else aux0.auxuti = uti;
+ aux0.auxurl = url;
- for (i = 0; i < msg->count; i++)
+ merged_msg = _asl_merge_msg_aux0((asl_msg_t *)msg, aux0);
+ if (merged_msg == NULL) return -1;
+
+ /* if (out_fd == NULL), this is from asl_log_auxiliary_location */
+ if (out_fd == NULL)
{
- if (msg->key[i] != NULL) free(msg->key[i]);
- if (msg->val[i] != NULL) free(msg->val[i]);
+ status = _asl_send_message(NULL, merged_msg, -1, NULL);
+ asl_msg_release(merged_msg);
+ return status;
}
- if (msg->count > 0)
+ where = asl_store_location();
+
+ if (where == ASL_STORE_LOCATION_MEMORY)
{
- if (msg->key != NULL) free(msg->key);
- if (msg->val != NULL) free(msg->val);
- if (msg->op != NULL) free(msg->op);
- }
+ /* create a pipe */
- free(msg);
-}
+ asl_aux_context_t *ctx = (asl_aux_context_t *)calloc(1, sizeof(asl_aux_context_t));
+ if (ctx == NULL) return -1;
-/*
- * Called if there's a malloc error while manipulating a message in asl_set_query.
- * Cleans up the key, val, and op fields, sets count to zero.
- */
-static void
-_asl_clear_msg(asl_msg_t *msg)
-{
- uint32_t i;
+ status = pipe(fdpair);
+ if (status < 0)
+ {
+ free(ctx);
+ return -1;
+ }
- if (msg == NULL) return;
+ /* give read end to dispatch_io_read */
+ fd = fdpair[0];
+ sem = dispatch_semaphore_create(0);
+ ctx->sem = sem;
+ ctx->fd = fdpair[1];
- for (i = 0; i < msg->count; i++)
- {
- if (msg->key != NULL && msg->key[i] != NULL) free(msg->key[i]);
- if (msg->val != NULL && msg->val[i] != NULL) free(msg->val[i]);
- }
+ status = _asl_aux_save_context(ctx);
+ if (status != 0)
+ {
+ close(fdpair[0]);
+ close(fdpair[1]);
+ dispatch_release(sem);
+ free(ctx);
+ return -1;
+ }
- if (msg->key != NULL) free(msg->key);
- if (msg->val != NULL) free(msg->val);
- if (msg->op != NULL) free(msg->op);
+ pipe_q = dispatch_queue_create("PipeQ", NULL);
+ pipe_channel = dispatch_io_create(DISPATCH_IO_STREAM, fd, pipe_q, ^(int err){
+ close(fd);
+ });
- msg->key = NULL;
- msg->val = NULL;
- msg->op = NULL;
+ *out_fd = fdpair[1];
- msg->count = 0;
-}
+ dispatch_io_set_low_water(pipe_channel, SIZE_MAX);
-/*
- * asl_set_query: set arbitrary parameters of a query
- * Similar to als_set, but allows richer query operations.
- * See ASL_QUERY_OP_* above.
- * msg: an aslmsg
- * key: attribute key
- * value: attribute value
- * op: an operation from the set above.
- * returns 0 for success, non-zero for failure
- */
-int
-asl_set_query(aslmsg a, const char *key, const char *val, uint32_t op)
-{
- uint32_t i, len;
- char *dk, *dv;
- asl_msg_t *msg;
+ dispatch_io_read(pipe_channel, 0, SIZE_MAX, pipe_q, ^(bool done, dispatch_data_t pipedata, int err){
+ if (err == 0)
+ {
+ size_t len = dispatch_data_get_size(pipedata);
+ if (len > 0)
+ {
+ const char *bytes = NULL;
+ char *encoded;
+
+ dispatch_data_t md = dispatch_data_create_map(pipedata, (const void **)&bytes, &len);
+ encoded = asl_core_encode_buffer(bytes, len);
+ asl_set((aslmsg)merged_msg, ASL_KEY_AUX_DATA, encoded);
+ free(encoded);
+ _asl_send_message(NULL, merged_msg, -1, NULL);
+ asl_msg_release(merged_msg);
+ dispatch_release(md);
+ }
+ }
- msg = (asl_msg_t *)a;
+ if (done)
+ {
+ dispatch_semaphore_signal(sem);
+ dispatch_release(pipe_channel);
+ dispatch_release(pipe_q);
+ }
+ });
- if (msg == NULL) return 0;
- if (key == NULL) return -1;
+ return 0;
+ }
- dv = NULL;
+ _asl_global_init();
+ if (_asl_global.server_port == MACH_PORT_NULL) return -1;
- if ((streq(key, ASL_KEY_MSG)) && (val != NULL))
+ len = _asl_msg_string_length_aux(merged_msg, NULL);
+ if (len == 0)
{
- /* strip trailing newlines */
- dv = strdup(val);
- if (dv == NULL) return -1;
-
- len = strlen(dv);
- i = len - 1;
- while ((len > 0) && (dv[i] == '\n'))
- {
- dv[i] = '\0';
- i--;
- len--;
- }
+ asl_msg_release(merged_msg);
+ return -1;
}
- else if (streq(key, ASL_KEY_LEVEL))
+
+ outlen = len + 11;
+ kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&out, outlen, TRUE);
+ if (kstatus != KERN_SUCCESS)
{
- if (val == NULL) return -1;
- if (val[0] == '\0') return -1;
- if ((val[0] >= '0') && (val[0] <= '9'))
- {
- i = atoi(val);
- asprintf(&dv, "%d", i);
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_EMERG))
- {
- dv = strdup("0");
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_ALERT))
- {
- dv = strdup("1");
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_CRIT))
- {
- dv = strdup("2");
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_ERR))
- {
- dv = strdup("3");
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_WARNING))
- {
- dv = strdup("4");
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_NOTICE))
- {
- dv = strdup("5");
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_INFO))
- {
- dv = strdup("6");
- if (dv == NULL) return -1;
- }
- else if (!strcasecmp(val, ASL_STRING_DEBUG))
- {
- dv = strdup("7");
- if (dv == NULL) return -1;
- }
- else return -1;
+ asl_msg_release(merged_msg);
+ return -1;
}
- if ((dv == NULL) && (val != NULL))
+ memset(out, 0, outlen);
+ snprintf((char *)out, 12, "%10u ", len);
+
+ status = _asl_msg_to_string_buffer_aux(merged_msg, NULL, (char *)(out + 11), len);
+ if (status != 0)
{
- dv = strdup(val);
- if (dv == NULL) return -1;
+ asl_msg_release(merged_msg);
+ vm_deallocate(mach_task_self(), (vm_address_t)out, outlen);
+ return -1;
}
- for (i = 0; i < msg->count; i++)
+ status = 0;
+ fileport = MACH_PORT_NULL;
+ status = KERN_SUCCESS;
+
+ kstatus = _asl_server_create_aux_link(_asl_global.server_port, out, outlen, &fileport, &newurl, &newurllen, &status);
+ if (kstatus != KERN_SUCCESS)
{
- if (msg->key[i] == NULL) continue;
+ asl_msg_release(merged_msg);
+ return -1;
+ }
- if ((msg->type != ASL_TYPE_QUERY) && (streq(msg->key[i], key)))
- {
- if (msg->val[i] != NULL) free(msg->val[i]);
- msg->val[i] = NULL;
- if (val != NULL) msg->val[i] = dv;
- if (msg->op != NULL) msg->op[i] = op;
- return 0;
- }
+ if (status != 0)
+ {
+ asl_msg_release(merged_msg);
+ return status;
}
- if (msg->count == 0)
+ if (newurl != NULL)
{
- msg->key = (char **)calloc(1, sizeof(char *));
- if (msg->key == NULL)
- {
- _asl_clear_msg(msg);
- return -1;
- }
+ asl_msg_set_key_val(merged_msg, ASL_KEY_AUX_URL, newurl);
+ vm_deallocate(mach_task_self(), (vm_address_t)newurl, newurllen);
+ }
- msg->val = (char **)calloc(1, sizeof(char *));
- if (msg->val == NULL)
- {
- _asl_clear_msg(msg);
- return -1;
- }
+ if (fileport == MACH_PORT_NULL)
+ {
+ asl_msg_release(merged_msg);
+ return -1;
+ }
- if (msg->type == ASL_TYPE_QUERY)
- {
- msg->op = (uint32_t *)calloc(1, sizeof(uint32_t));
- if (msg->op == NULL)
- {
- _asl_clear_msg(msg);
- return -1;
- }
- }
+ fd = fileport_makefd(fileport);
+ mach_port_deallocate(mach_task_self(), fileport);
+ if (fd < 0)
+ {
+ asl_msg_release(merged_msg);
+ status = -1;
}
else
{
- msg->key = (char **)reallocf(msg->key, (msg->count + 1) * sizeof(char *));
- if (msg->key == NULL)
+ asl_aux_context_t *ctx = (asl_aux_context_t *)calloc(1, sizeof(asl_aux_context_t));
+ if (ctx == NULL)
{
- _asl_clear_msg(msg);
- return -1;
+ status = -1;
}
-
- msg->val = (char **)reallocf(msg->val, (msg->count + 1) * sizeof(char *));
- if (msg->val == NULL)
+ else
{
- _asl_clear_msg(msg);
- return -1;
- }
+ *out_fd = fd;
- if (msg->type == ASL_TYPE_QUERY)
- {
- msg->op = (uint32_t *)reallocf(msg->op, (msg->count + 1) * sizeof(uint32_t));
- if (msg->op == NULL)
- {
- _asl_clear_msg(msg);
- return -1;
- }
+ ctx->fd = fd;
+ ctx->msg = merged_msg;
+
+ status = _asl_aux_save_context(ctx);
}
}
- dk = strdup(key);
- if (dk == NULL)
- {
- if (dv != NULL) free(dv);
- _asl_clear_msg(msg);
- return -1;
- }
+ return status;
+}
- msg->key[msg->count] = dk;
- msg->val[msg->count] = dv;
- if (msg->op != NULL) msg->op[msg->count] = op;
- msg->count++;
+int
+asl_create_auxiliary_file(aslmsg msg, const char *title, const char *uti, int *out_fd)
+{
+ if (out_fd == NULL) return -1;
- return 0;
+ return _asl_auxiliary(msg, title, uti, NULL, out_fd);
}
-/*
- * asl_set: set attributes of a message
- * msg: an aslmsg
- * key: attribute key
- * value: attribute value
- * returns 0 for success, non-zero for failure
- */
int
-asl_set(aslmsg msg, const char *key, const char *val)
+asl_log_auxiliary_location(aslmsg msg, const char *title, const char *uti, const char *url)
{
- return asl_set_query(msg, key, val, 0);
+ return _asl_auxiliary(msg, title, uti, url, NULL);
}
/*
- * asl_unset: remove attributes of a message
- * msg: an aslmsg
- * key: attribute key
- * returns 0 for success, non-zero for failure
+ * Close an auxiliary file.
+ * Sends the cached auxiliary message to syslogd.
*/
int
-asl_unset(aslmsg a, const char *key)
+asl_close_auxiliary_file(int fd)
{
- uint32_t i, j;
- asl_msg_t *msg;
+ int i, j, status;
+ asl_msg_t *aux_msg;
+ dispatch_semaphore_t aux_sem;
- msg = (asl_msg_t *)a;
+ pthread_mutex_lock(&(_asl_global.lock));
- if (msg == NULL) return 0;
- if (key == NULL) return 0;
+ aux_msg = NULL;
+ status = -1;
- for (i = 0; i < msg->count; i++)
+ for (i = 0; i < _asl_global.aux_count; i++)
{
- if (msg->key[i] == NULL) continue;
-
- if (streq(msg->key[i], key))
+ if (_asl_global.aux_ctx[i]->fd == fd)
{
- free(msg->key[i]);
- if (msg->val[i] != NULL) free(msg->val[i]);
+ status = 0;
- for (j = i + 1; j < msg->count; j++, i++)
- {
- msg->key[i] = msg->key[j];
- msg->val[i] = msg->val[j];
- if (msg->op != NULL) msg->op[i] = msg->op[j];
- }
+ aux_msg = _asl_global.aux_ctx[i]->msg;
+ aux_sem = _asl_global.aux_ctx[i]->sem;
- msg->count--;
+ free(_asl_global.aux_ctx[i]);
- if (msg->count == 0)
+ for (j = i + 1; j < _asl_global.aux_count; i++, j++)
{
- free(msg->key);
- msg->key = NULL;
+ _asl_global.aux_ctx[i] = _asl_global.aux_ctx[j];
+ }
- free(msg->val);
- msg->val = NULL;
+ _asl_global.aux_count--;
- if (msg->op != NULL) free(msg->op);
- msg->op = NULL;
+ if (_asl_global.aux_count == 0)
+ {
+ free(_asl_global.aux_ctx);
+ _asl_global.aux_ctx = NULL;
}
else
{
- msg->key = (char **)reallocf(msg->key, msg->count * sizeof(char *));
- if (msg->key == NULL) return -1;
-
- msg->val = (char **)reallocf(msg->val, msg->count * sizeof(char *));
- if (msg->val == NULL) return -1;
-
- if (msg->op != NULL)
+ _asl_global.aux_ctx = (asl_aux_context_t **)reallocf(_asl_global.aux_ctx, _asl_global.aux_count * sizeof(asl_aux_context_t *));
+ if (_asl_global.aux_ctx == NULL)
{
- msg->op = (uint32_t *)reallocf(msg->op, msg->count * sizeof(uint32_t));
- if (msg->op == NULL) return -1;
+ _asl_global.aux_count = 0;
+ status = -1;
}
}
- return 0;
+ break;
}
}
- return 0;
+ pthread_mutex_unlock(&(_asl_global.lock));
+
+ close(fd);
+
+ if (aux_msg != NULL)
+ {
+ if (_asl_send_message(NULL, aux_msg, -1, NULL) != ASL_STATUS_OK) status = -1;
+ asl_msg_release(aux_msg);
+ }
+
+ if (aux_sem != NULL)
+ {
+ dispatch_semaphore_wait(aux_sem, DISPATCH_TIME_FOREVER);
+ dispatch_release(aux_sem);
+ }
+
+ return status;
}
/*
{
asl_search_result_t query, *out;
asl_msg_t *q, *qlist[1];
- uint32_t status, x;
+ uint32_t status, op;
uint64_t last_id, start_id;
asl_store_t *store;
+ const char *val;
if (a == NULL) return NULL;
/* check for "ASLMessageId >[=] n" and set start_id */
start_id = 0;
- x = _asl_msg_index(q, ASL_KEY_MSG_ID);
- if ((x != (uint32_t)-1) && (q->val[x] != NULL) && (q->op != NULL) && (q->op[x] & ASL_QUERY_OP_GREATER))
+ val = NULL;
+
+ status = asl_msg_lookup(q, ASL_KEY_MSG_ID, &val, &op);
+ if ((status == 0) && (val != NULL) && (op & ASL_QUERY_OP_GREATER))
{
- if (q->op[x] & ASL_QUERY_OP_EQUAL) start_id = atoi(q->val[x]);
- else start_id = atoi(q->val[x]) + 1;
+ if (op & ASL_QUERY_OP_EQUAL) start_id = atoll(val);
+ else start_id = atoll(val) + 1;
}
store = NULL;
{
asl_search_result_t *batch, *out;
char *qstr, *str, *res;
- uint32_t i, len, reslen, status;
+ uint32_t len, reslen, status;
uint64_t cmax, qmin;
kern_return_t kstatus;
security_token_t sec;
if (a == NULL) return 0;
- _asl_get_global_server_port();
+ _asl_global_init();
if (_asl_global.server_port == MACH_PORT_NULL) return NULL;
len = 0;
else
{
asprintf(&str, "1\n%s\n", qstr);
- len += 4;
+ len += 3;
free(qstr);
}
- if (str == NULL)
- {
- _asl_release_global_server_port();
- return NULL;
- }
+ if (str == NULL) return NULL;
/*
* Fetch a batch of results each time through the loop.
status = ASL_STATUS_OK;
kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&vmstr, len, TRUE);
- if (kstatus != KERN_SUCCESS)
- {
- _asl_release_global_server_port();
- return NULL;
- }
+ if (kstatus != KERN_SUCCESS) return NULL;
memmove(vmstr, str, len);
status = _asl_search_concat_results(batch, &out);
if (status != ASL_STATUS_OK) break;
- if (i < FETCH_BATCH) break;
+ if (out->count < FETCH_BATCH) break;
- if (cmax > qmin) qmin = cmax + 1;
+ if (cmax >= qmin) qmin = cmax + 1;
}
free(str);
- _asl_release_global_server_port();
return out;
}
uint64_t cmax;
security_token_t sec;
- _asl_get_global_server_port();
+ _asl_global_init();
if (_asl_global.server_port == MACH_PORT_NULL) return ASL_STORE_LOCATION_FILE;
res = NULL;
status = ASL_STATUS_OK;
kstatus = _asl_server_query(_asl_global.server_port, NULL, 0, 0, -1, 0, (caddr_t *)&res, &reslen, &cmax, (int *)&status, &sec);
- _asl_release_global_server_port();
/* res should never be returned, but just to be certain we don't leak VM ... */
if (res != NULL) vm_deallocate(mach_task_self(), (vm_address_t)res, reslen);
int where;
asl_search_result_t *out;
- /* prevents fetching and destroying the send right twice if nobody has already lookup up the port */
- _asl_get_global_server_port();
+ _asl_global_init();
where = asl_store_location();
if (where == ASL_STORE_LOCATION_FILE) out = _asl_search_store(ac, a);
else out = _asl_search_memory(ac, a);
- _asl_release_global_server_port();
return out;
}
-/*
- * aslresponse_next: Iterate over responses returned from asl_search()
- * a: a response returned from asl_search();
- * returns: The next log message (an aslmsg) or NULL on failure
- */
-aslmsg
-aslresponse_next(aslresponse r)
-{
- asl_search_result_t *res;
- aslmsg m;
-
- res = (asl_search_result_t *)r;
- if (res == NULL) return NULL;
-
- if (res->curr >= res->count) return NULL;
- m = res->msg[res->curr];
- res->curr++;
-
- return m;
-}
-
-/*
- * aslresponse_free: Free a response returned from asl_search()
- * a: a response returned from asl_search()
- */
-void
-aslresponse_free(aslresponse r)
-{
- asl_search_result_t *res;
- uint32_t i;
-
- res = (asl_search_result_t *)r;
- if (res == NULL) return;
-
- for (i = 0; i < res->count; i++) asl_free(res->msg[i]);
- free(res->msg);
- free(res);
-}
-
int
asl_syslog_faciliy_name_to_num(const char *name)
{
#define SECONDS_PER_DAY 86400
#define SECONDS_PER_WEEK 604800
+static regex_t rex_canon, rex_ctime, rex_abs, rex_rel;
+static int reg_status = 0;
+
/*
* We use the last letter in the month name to determine
* the month number (0-11). There are two collisions:
time_t
asl_parse_time(const char *in)
{
- int len, y, status, rflags;
+ int len, y;
struct tm t;
time_t tick, delta, factor;
char *str, *p, *x;
- static regex_t rex_canon, rex_ctime, rex_abs, rex_rel;
- static int init_canon = 0;
- static int init_ctime = 0;
- static int init_abs = 0;
- static int init_rel = 0;
+ static dispatch_once_t once;
if (in == NULL) return -1;
- rflags = REG_EXTENDED | REG_NOSUB | REG_ICASE;
+ dispatch_once(&once, ^{
+ int status;
+ int rflags = REG_EXTENDED | REG_NOSUB | REG_ICASE;
- if (init_canon == 0)
- {
memset(&rex_canon, 0, sizeof(regex_t));
status = regcomp(&rex_canon, CANONICAL_TIME_REX, rflags);
- if (status != 0) return -1;
- init_canon = 1;
- }
+ if (status != 0) reg_status = -1;
- if (init_ctime == 0)
- {
memset(&rex_ctime, 0, sizeof(regex_t));
status = regcomp(&rex_ctime, CTIME_REX, rflags);
- if (status != 0) return -1;
- init_ctime = 1;
- }
+ if (status != 0) reg_status = -1;
- if (init_abs == 0)
- {
memset(&rex_abs, 0, sizeof(regex_t));
status = regcomp(&rex_abs, ABSOLUTE_TIME_REX, rflags);
- if (status != 0) return -1;
- init_abs = 1;
- }
+ if (status != 0) reg_status = -1;
- if (init_rel == 0)
- {
memset(&rex_rel, 0, sizeof(regex_t));
status = regcomp(&rex_rel, RELATIVE_TIME_REX, rflags);
- if (status != 0) return -1;
- init_rel = 1;
- }
+ if (status != 0) reg_status = -1;
+ });
+
+ if (reg_status < 0) return -1;
len = strlen(in) + 1;
*/
#include <asl_core.h>
+#include <stdlib.h>
#include <string.h>
#include <membership.h>
#include <pthread.h>
return out;
}
+
+/*
+ * asl_core_encode_buffer
+ * encode arbitrary data as a C string without embedded zero (nul) characters
+ *
+ * The routine computes a histogram of the input buffer and finds
+ * the two least frequently used non-nul chars (L[0] and L[1]).
+ *
+ * L[0] is used to stand in for nul.
+ * L[1] is used as the escape character.
+ * Occurrences of nul in the data are encoded as L[0]
+ * Occurrences of L[0] in the data are encoded as the sequence L[1] 1.
+ * Occurrences of L[1] in the data are encoded as the sequence L[1] 2.
+ *
+ * The output string is preceded by L[0] L[1], and is nul terminated.
+ * The output length is 2 + n + N(L[0]) + N(L[1]) + 1
+ * where N(x) is the number of occurrences of x in the input string.
+ * The worst case occurs when all characters are equally frequent,
+ * In that case the output size will less that 1% larger than the input.
+ */
+char *
+asl_core_encode_buffer(const char *in, uint32_t len)
+{
+ char *str;
+ uint32_t i, j, k, outlen, breakit, min, hist[256];
+ uint32_t lfu[2], save[2];
+ uint8_t v;
+
+ if (in == NULL) return NULL;
+ if (len == 0) return NULL;
+
+ memset(hist, 0, sizeof(hist));
+ save[0] = 0;
+ save[1] = 0;
+
+ for (i = 0; i < len; i++)
+ {
+ v = in[i];
+ hist[v]++;
+ }
+
+ for (j = 0; j < 2; j++)
+ {
+ lfu[j] = 1;
+ min = hist[1];
+
+ for (i = 2; i < 256; i++)
+ {
+ if (hist[i] < min)
+ {
+ lfu[j] = i;
+ min = hist[i];
+
+ /*
+ * Stop if there are no occurances or character i in the input.
+ * The minimum will never be less than zero.
+ */
+ if (min == 0) break;
+
+ /*
+ * When looking for the second least frequently used character,
+ * stop scanning if we hit the same minimum as we saw in the first
+ * pass. There will be no smaller values.
+ */
+ if ((j == 1) && (min == save[0])) break;
+ }
+ }
+
+ save[j] = hist[lfu[j]];
+ hist[lfu[j]] = (uint32_t)-1;
+ }
+
+ outlen = 2 + len + save[0] + save[1] + 1;
+
+ str = malloc(outlen);
+ if (str == NULL) return NULL;
+
+ str[outlen - 1] = '\0';
+
+ str[0] = lfu[0];
+ str[1] = lfu[1];
+
+ j = 2;
+
+ for (i = 0; i < len; i++)
+ {
+ v = in[i];
+ if (v == 0)
+ {
+ str[j++] = lfu[0];
+ continue;
+ }
+
+ breakit = 0;
+ for (k = 0; (k < 2) && (breakit == 0); k++)
+ {
+ if (v == lfu[k])
+ {
+ str[j++] = lfu[1];
+ str[j++] = k + 1;
+ breakit = 1;
+ }
+ }
+
+ if (breakit == 1) continue;
+
+ str[j++] = v;
+ }
+
+ return str;
+}
+
+/*
+ * asl_core_decode_buffer
+ * decode a string produced by asl_encode_buffer to recreate the original data
+ */
+int32_t
+asl_core_decode_buffer(const char *in, char **buf, uint32_t *len)
+{
+ uint8_t v;
+ uint32_t i, j, n, outlen;
+ uint32_t lfu[2];
+ char *out;
+
+ if (buf == NULL) return -1;
+ if (len == NULL) return -1;
+
+ lfu[0] = in[0];
+ lfu[1] = in[1];
+
+ outlen = 0;
+
+ /* strip trailing nul */
+ n = strlen(in);
+
+ /* determine output length and check for invalid input */
+ for (i = 2; i < n; i++)
+ {
+ if (in[i] == lfu[1])
+ {
+ if ((i + 1) == n) return -1;
+ i++;
+ if ((in[i] < 1) || (in[i] > 2)) return -1;
+ outlen++;
+ }
+ else outlen++;
+ }
+
+ if (outlen == 0) return -1;
+
+ out = malloc(outlen);
+ if (out == NULL) return -1;
+
+ j = 0;
+ for (i = 2; i < n; i++)
+ {
+ v = in[i];
+ if (v == lfu[0])
+ {
+ out[j++] = 0;
+ }
+ else if (v == lfu[1])
+ {
+ i++;
+ v = in[i];
+ out[j++] = lfu[v - 1];
+ }
+ else out[j++] = v;
+ }
+
+ *len = outlen;
+ *buf = out;
+ return 0;
+}
*/
#include <stdint.h>
+#include <Availability.h>
#define asl_msg_list_t asl_search_result_t
#define ASL_QUERY_MATCH_FALSE 0x40000000
#define ASL_QUERY_MATCH_ERROR 0x20000000
-uint32_t asl_core_string_hash(const char *str, uint32_t len);
-const char *asl_core_error(uint32_t code);
-uint32_t asl_core_check_access(int32_t msgu, int32_t msgg, int32_t readu, int32_t readg, uint16_t flags);
-uint64_t asl_core_htonq(uint64_t n);
-uint64_t asl_core_ntohq(uint64_t n);
-uint64_t asl_core_new_msg_id(uint64_t start);
+uint32_t asl_core_string_hash(const char *str, uint32_t len) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+const char *asl_core_error(uint32_t code) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_core_check_access(int32_t msgu, int32_t msgg, int32_t readu, int32_t readg, uint16_t flags) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint64_t asl_core_htonq(uint64_t n) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint64_t asl_core_ntohq(uint64_t n)__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint64_t asl_core_new_msg_id(uint64_t start) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+char *asl_core_encode_buffer(const char *in, uint32_t len) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
+int32_t asl_core_decode_buffer(const char *in, char **buf, uint32_t *len) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
-#endif __ASL_CORE_H__
\ No newline at end of file
+#endif __ASL_CORE_H__
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 2007 Apple Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <sys/errno.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <membership.h>
#include <time.h>
#include <sys/time.h>
#include <asl_private.h>
#include <asl_legacy1.h>
extern time_t asl_parse_time(const char *str);
-extern int asl_msg_cmp(asl_msg_t *a, asl_msg_t *b);
+extern int asl_msg_cmp(aslmsg a, aslmsg b);
#define forever for(;;)
#define MILLION 1000000
return ASL_STATUS_OK;
}
-uint32_t
-asl_file_open_write(const char *path, mode_t mode, uid_t uid, gid_t gid, asl_file_t **s)
+__private_extern__ uint32_t
+asl_file_open_write_fd(int fd, asl_file_t **s)
{
time_t now;
- int i, status, fd;
- struct stat sb;
+ int status;
char buf[DB_HEADER_LEN];
asl_file_t *out;
- uint32_t aslstatus, vers;
- memset(&sb, 0, sizeof(struct stat));
+ if (fd < 0) return ASL_STATUS_FAILED;
+ if (s == NULL) return ASL_STATUS_FAILED;
- status = stat(path, &sb);
- if (status == 0)
+ out = (asl_file_t *)calloc(1, sizeof(asl_file_t));
+ if (out == NULL) return ASL_STATUS_NO_MEMORY;
+
+ out->store = fdopen(fd, "w+");
+ if (out->store == NULL)
{
- /* XXX Check that mode, uid, and gid are correct */
- out = (asl_file_t *)calloc(1, sizeof(asl_file_t));
- if (out == NULL) return ASL_STATUS_NO_MEMORY;
+ free(out);
+ return ASL_STATUS_FAILED;
+ }
- out->store = fopen(path, "r+");
- if (out->store == NULL)
- {
- free(out);
- return ASL_STATUS_FAILED;
- }
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, ASL_DB_COOKIE, ASL_DB_COOKIE_LEN);
- i = fread(buf, DB_HEADER_LEN, 1, out->store);
- if (i < 1)
- {
- asl_file_close(out);
- return ASL_STATUS_READ_FAILED;
- }
+ _asl_put_32(DB_VERSION, buf + DB_HEADER_VERS_OFFSET);
- /* check cookie */
- if (strncmp(buf, ASL_DB_COOKIE, ASL_DB_COOKIE_LEN))
- {
- asl_file_close(out);
- return ASL_STATUS_INVALID_STORE;
- }
+ now = time(NULL);
+ out->dob = now;
+ _asl_put_64(out->dob, buf + DB_HEADER_TIME_OFFSET);
- /* check version */
- vers = _asl_get_32(buf + DB_HEADER_VERS_OFFSET);
- if (vers != DB_VERSION)
- {
- asl_file_close(out);
- return ASL_STATUS_INVALID_STORE;
- }
+ _asl_put_32(CACHE_SIZE, buf + DB_HEADER_CSIZE_OFFSET);
- out->dob = _asl_get_64(buf + DB_HEADER_TIME_OFFSET);
- out->first = _asl_get_64(buf + DB_HEADER_FIRST_OFFSET);
- out->last = _asl_get_64(buf + DB_HEADER_LAST_OFFSET);
- out->file_size = (size_t)sb.st_size;
+ status = fwrite(buf, sizeof(buf), 1, out->store);
+ if (status != 1)
+ {
+ fclose(out->store);
+ free(out);
+ return ASL_STATUS_FAILED;
+ }
- /* detect bogus last pointer */
- if (out->last >= out->file_size) out->last = 0;
+ /* flush data */
+ fflush(out->store);
- aslstatus = asl_file_read_set_position(out, ASL_FILE_POSITION_LAST);
- if (aslstatus != ASL_STATUS_OK)
- {
- asl_file_close(out);
- return aslstatus;
- }
+ out->file_size = sizeof(buf);
- out->prev = out->cursor;
- status = fseeko(out->store, 0, SEEK_END);
- if (status != 0)
- {
- asl_file_close(out);
- return ASL_STATUS_READ_FAILED;
- }
+ /* scratch buffer for file writes (we test for NULL before using it) */
+ out->scratch = malloc(SCRATCH_BUFFER_SIZE);
- out->file_size = (size_t)ftello(out->store);
+ *s = out;
- /* scratch buffer for file writes (we test for NULL before using it) */
- out->scratch = malloc(SCRATCH_BUFFER_SIZE);
+ return ASL_STATUS_OK;
+}
- *s = out;
+__private_extern__ int
+asl_file_create(const char *path, uid_t uid, gid_t gid, mode_t mode)
+{
+ acl_t acl;
+ uuid_t uuid;
+ acl_entry_t entry;
+ acl_permset_t perms;
+ int status;
+ int fd = -1;
- return ASL_STATUS_OK;
- }
+ acl = acl_init(1);
- if (errno != ENOENT) return ASL_STATUS_FAILED;
+ if (gid != 0)
+ {
+ status = mbr_gid_to_uuid(gid, uuid);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_create_entry_np(&acl, &entry, ACL_FIRST_ENTRY);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_set_tag_type(entry, ACL_EXTENDED_ALLOW);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_set_qualifier(entry, &uuid);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_get_permset(entry, &perms);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_add_perm(perms, ACL_READ_DATA);
+ if (status != 0) goto asl_file_create_return;
+ }
+
+ if (uid != 0)
+ {
+ status = mbr_uid_to_uuid(uid, uuid);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_create_entry_np(&acl, &entry, ACL_FIRST_ENTRY);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_set_tag_type(entry, ACL_EXTENDED_ALLOW);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_set_qualifier(entry, &uuid);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_get_permset(entry, &perms);
+ if (status != 0) goto asl_file_create_return;
+
+ status = acl_add_perm(perms, ACL_READ_DATA);
+ if (status != 0) goto asl_file_create_return;
+ }
fd = open(path, O_RDWR | O_CREAT | O_EXCL, mode);
- if (fd < 0) return ASL_STATUS_FAILED;
+ if (fd < 0) goto asl_file_create_return;
- status = fchown(fd, uid, gid);
+ status = acl_set_fd(fd, acl);
if (status != 0)
{
close(fd);
+ fd = -1;
unlink(path);
- return ASL_STATUS_FAILED;
}
- out = (asl_file_t *)calloc(1, sizeof(asl_file_t));
- if (out == NULL) return ASL_STATUS_NO_MEMORY;
+asl_file_create_return:
+
+ acl_free(acl);
+ return fd;
+}
- out->store = fdopen(fd, "w+");
- if (out->store == NULL)
+uint32_t
+asl_file_open_write(const char *path, mode_t mode, uid_t uid, gid_t gid, asl_file_t **s)
+{
+ int i, status, fd;
+ struct stat sb;
+ char buf[DB_HEADER_LEN];
+ asl_file_t *out;
+ uint32_t aslstatus, vers, last_len;
+ off_t off;
+
+ memset(&sb, 0, sizeof(struct stat));
+
+ status = stat(path, &sb);
+ if (status == 0)
{
- free(out);
- return ASL_STATUS_FAILED;
- }
+ /* must be a plain file */
+ if (!S_ISREG(sb.st_mode)) return ASL_STATUS_INVALID_STORE;
- memset(buf, 0, sizeof(buf));
- memcpy(buf, ASL_DB_COOKIE, ASL_DB_COOKIE_LEN);
+ if (sb.st_size == 0)
+ {
+ fd = open(path, O_RDWR | O_EXCL, mode);
+ if (fd < 0) return ASL_STATUS_FAILED;
- _asl_put_32(DB_VERSION, buf + DB_HEADER_VERS_OFFSET);
+ return asl_file_open_write_fd(fd, s);
+ }
+ else
+ {
+ /* XXX Check that mode, uid, and gid are correct */
+ out = (asl_file_t *)calloc(1, sizeof(asl_file_t));
+ if (out == NULL) return ASL_STATUS_NO_MEMORY;
- now = time(NULL);
- out->dob = now;
- _asl_put_64(out->dob, buf + DB_HEADER_TIME_OFFSET);
+ out->store = fopen(path, "r+");
+ if (out->store == NULL)
+ {
+ free(out);
+ return ASL_STATUS_FAILED;
+ }
- _asl_put_32(CACHE_SIZE, buf + DB_HEADER_CSIZE_OFFSET);
+ i = fread(buf, DB_HEADER_LEN, 1, out->store);
+ if (i < 1)
+ {
+ asl_file_close(out);
+ return ASL_STATUS_READ_FAILED;
+ }
- status = fwrite(buf, sizeof(buf), 1, out->store);
- if (status != 1)
+ /* check cookie */
+ if (strncmp(buf, ASL_DB_COOKIE, ASL_DB_COOKIE_LEN))
+ {
+ asl_file_close(out);
+ return ASL_STATUS_INVALID_STORE;
+ }
+
+ /* check version */
+ vers = _asl_get_32(buf + DB_HEADER_VERS_OFFSET);
+ if (vers != DB_VERSION)
+ {
+ asl_file_close(out);
+ return ASL_STATUS_INVALID_STORE;
+ }
+
+ out->dob = _asl_get_64(buf + DB_HEADER_TIME_OFFSET);
+ out->first = _asl_get_64(buf + DB_HEADER_FIRST_OFFSET);
+ out->last = _asl_get_64(buf + DB_HEADER_LAST_OFFSET);
+ out->file_size = (size_t)sb.st_size;
+
+ /*
+ * Detect bogus last pointer and check for odd-sized files.
+ * Setting out->last to zero forces asl_file_read_set_position to
+ * follow the linked list of records in the file to the last record.
+ * It's slower, but it's better at preventing crashes in corrupt files.
+ */
+
+ /* records are at least MSG_RECORD_FIXED_LENGTH bytes */
+ if ((out->last + MSG_RECORD_FIXED_LENGTH) > out->file_size)
+ {
+ out->last = 0;
+ }
+ else
+ {
+ /* read last record length and make sure the file is at least that large */
+ off = out->last + RECORD_TYPE_LEN;
+ status = asl_file_read_uint32(out, off, &last_len);
+ if (status != ASL_STATUS_OK)
+ {
+ asl_file_close(out);
+ return status;
+ }
+
+ if ((out->last + last_len) > out->file_size) out->last = 0;
+ }
+
+ aslstatus = asl_file_read_set_position(out, ASL_FILE_POSITION_LAST);
+ if (aslstatus != ASL_STATUS_OK)
+ {
+ asl_file_close(out);
+ return aslstatus;
+ }
+
+ out->prev = out->cursor;
+ status = fseeko(out->store, 0, SEEK_END);
+ if (status != 0)
+ {
+ asl_file_close(out);
+ return ASL_STATUS_READ_FAILED;
+ }
+
+ out->file_size = (size_t)ftello(out->store);
+
+ /* scratch buffer for file writes (we test for NULL before using it) */
+ out->scratch = malloc(SCRATCH_BUFFER_SIZE);
+
+ *s = out;
+
+ return ASL_STATUS_OK;
+ }
+ }
+ else if (errno != ENOENT)
{
- fclose(out->store);
- free(out);
- unlink(path);
+ /* unexpected status */
return ASL_STATUS_FAILED;
}
- out->file_size = sizeof(buf);
+ /* the file does not exist */
+ fd = asl_file_create(path, uid, gid, mode);
+ if (fd < 0) return ASL_STATUS_FAILED;
- *s = out;
+ aslstatus = asl_file_open_write_fd(fd, s);
+ if (aslstatus != ASL_STATUS_OK) unlink(path);
- return ASL_STATUS_OK;
+ return aslstatus;
}
uint32_t
i = fwrite(str, len + 1, 1, s->store);
if (i != 1) return ASL_STATUS_WRITE_FAILED;
+ /* flush data */
+ fflush(s->store);
+
/* create file_string_t and insert into the cache */
sx = (file_string_t *)calloc(1, offsetof(file_string_t, str) + len + 1);
if (sx == NULL) return ASL_STATUS_NO_MEMORY;
* Creates and caches strings.
*/
uint32_t
-asl_file_save(asl_file_t *s, aslmsg msg, uint64_t *mid)
+asl_file_save(asl_file_t *s, aslmsg in, uint64_t *mid)
{
char *buf, *p;
- uint32_t len, i, status;
+ uint32_t i, len, x, status;
file_record_t r;
uint64_t k, v;
uint64_t *kvlist;
off_t off;
+ asl_msg_t *msg;
+ const char *key, *val;
if (s == NULL) return ASL_STATUS_INVALID_STORE;
- if (msg == NULL) return ASL_STATUS_INVALID_MESSAGE;
+ if (in == NULL) return ASL_STATUS_INVALID_MESSAGE;
if (s->flags & ASL_FILE_FLAG_READ_ONLY) return ASL_STATUS_READ_ONLY;
+ msg = (asl_msg_t *)in;
+
memset(&r, 0, sizeof(file_record_t));
r.flags = 0;
r.prev = s->prev;
kvlist = NULL;
- for (i = 0; i < msg->count; i++)
+ key = NULL;
+ val = NULL;
+
+ for (x = asl_msg_fetch(msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch(msg, x, &key, &val, NULL))
{
- if (msg->key[i] == NULL)
+ if (key == NULL)
{
continue;
}
- else if (!strcmp(msg->key[i], ASL_KEY_TIME))
+ else if (!strcmp(key, ASL_KEY_TIME))
{
- if (msg->val[i] != NULL) r.time = asl_parse_time(msg->val[i]);
+ if (val != NULL) r.time = asl_parse_time(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_TIME_NSEC))
+ else if (!strcmp(key, ASL_KEY_TIME_NSEC))
{
- if (msg->val[i] != NULL) r.nano = atoi(msg->val[i]);
+ if (val != NULL) r.nano = atoi(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_HOST))
+ else if (!strcmp(key, ASL_KEY_HOST))
{
- if (msg->val[i] != NULL)
+ if (val != NULL)
{
- status = asl_file_string_encode(s, msg->val[i], &(r.host));
+ status = asl_file_string_encode(s, val, &(r.host));
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
}
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_SENDER))
+ else if (!strcmp(key, ASL_KEY_SENDER))
{
- if (msg->val[i] != NULL)
+ if (val != NULL)
{
- status = asl_file_string_encode(s, msg->val[i], &(r.sender));
+ status = asl_file_string_encode(s, val, &(r.sender));
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
}
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_PID))
+ else if (!strcmp(key, ASL_KEY_PID))
{
- if (msg->val[i] != NULL) r.pid = atoi(msg->val[i]);
+ if (val != NULL) r.pid = atoi(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_REF_PID))
+ else if (!strcmp(key, ASL_KEY_REF_PID))
{
- if (msg->val[i] != NULL) r.refpid = atoi(msg->val[i]);
+ if (val != NULL) r.refpid = atoi(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_UID))
+ else if (!strcmp(key, ASL_KEY_UID))
{
- if (msg->val[i] != NULL) r.uid = atoi(msg->val[i]);
+ if (val != NULL) r.uid = atoi(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_GID))
+ else if (!strcmp(key, ASL_KEY_GID))
{
- if (msg->val[i] != NULL) r.gid = atoi(msg->val[i]);
+ if (val != NULL) r.gid = atoi(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_LEVEL))
+ else if (!strcmp(key, ASL_KEY_LEVEL))
{
- if (msg->val[i] != NULL) r.level = atoi(msg->val[i]);
+ if (val != NULL) r.level = atoi(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_MSG))
+ else if (!strcmp(key, ASL_KEY_MSG))
{
- if (msg->val[i] != NULL)
+ if (val != NULL)
{
- status = asl_file_string_encode(s, msg->val[i], &(r.message));
+ status = asl_file_string_encode(s, val, &(r.message));
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
}
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_FACILITY))
+ else if (!strcmp(key, ASL_KEY_FACILITY))
{
- if (msg->val[i] != NULL)
+ if (val != NULL)
{
- status = asl_file_string_encode(s, msg->val[i], &(r.facility));
+ status = asl_file_string_encode(s, val, &(r.facility));
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
}
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_REF_PROC))
+ else if (!strcmp(key, ASL_KEY_REF_PROC))
{
- if (msg->val[i] != NULL)
+ if (val != NULL)
{
- status = asl_file_string_encode(s, msg->val[i], &(r.refproc));
+ status = asl_file_string_encode(s, val, &(r.refproc));
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
}
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_SESSION))
+ else if (!strcmp(key, ASL_KEY_SESSION))
{
- if (msg->val[i] != NULL)
+ if (val != NULL)
{
- status = asl_file_string_encode(s, msg->val[i], &(r.session));
+ status = asl_file_string_encode(s, val, &(r.session));
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
}
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_READ_UID))
+ else if (!strcmp(key, ASL_KEY_READ_UID))
{
- if (((r.flags & ASL_MSG_FLAG_READ_UID_SET) == 0) && (msg->val[i] != NULL))
+ if (((r.flags & ASL_MSG_FLAG_READ_UID_SET) == 0) && (val != NULL))
{
- r.ruid = atoi(msg->val[i]);
+ r.ruid = atoi(val);
r.flags |= ASL_MSG_FLAG_READ_UID_SET;
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_READ_GID))
+ else if (!strcmp(key, ASL_KEY_READ_GID))
{
- if (((r.flags & ASL_MSG_FLAG_READ_GID_SET) == 0) && (msg->val[i] != NULL))
+ if (((r.flags & ASL_MSG_FLAG_READ_GID_SET) == 0) && (val != NULL))
{
- r.rgid = atoi(msg->val[i]);
+ r.rgid = atoi(val);
r.flags |= ASL_MSG_FLAG_READ_GID_SET;
}
}
- else if (!strcmp(msg->key[i], ASL_KEY_MSG_ID))
+ else if (!strcmp(key, ASL_KEY_MSG_ID))
{
- if (s->flags & ASL_FILE_FLAG_PRESERVE_MSG_ID) *mid = atoll(msg->val[i]);
+ if (s->flags & ASL_FILE_FLAG_PRESERVE_MSG_ID) *mid = atoll(val);
}
- else if (!strcmp(msg->key[i], ASL_KEY_OPTION))
+ else if (!strcmp(key, ASL_KEY_OPTION))
{
/* ignore - we don't save ASLOption */
}
else
{
- status = asl_file_string_encode(s, msg->key[i], &k);
+ status = asl_file_string_encode(s, key, &k);
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
}
v = 0;
- if (msg->val[i] != NULL)
+ if (val != NULL)
{
- status = asl_file_string_encode(s, msg->val[i], &v);
+ status = asl_file_string_encode(s, val, &v);
if (status != ASL_STATUS_OK)
{
if (kvlist != NULL) free(kvlist);
status = fseeko(s->store, 0, SEEK_END);
if (status != 0) return ASL_STATUS_WRITE_FAILED;
+ /* flush data */
+ fflush(s->store);
+
s->file_size = (size_t)ftello(s->store);
s->prev = s->last;
asl_file_t *out;
FILE *f;
int i;
- uint32_t status, vers;
+ uint32_t status, vers, last_len;
char buf[DB_HEADER_LEN];
off_t off;
asl_legacy1_t *legacy;
return ASL_STATUS_NO_MEMORY;
}
+ out->store = f;
out->flags = ASL_FILE_FLAG_READ_ONLY;
out->version = vers;
out->last = _asl_get_64(buf + DB_HEADER_LAST_OFFSET);
out->file_size = (size_t)sb.st_size;
- /* detect bogus last pointer */
- if (out->last >= out->file_size) out->last = 0;
+ /*
+ * Detect bogus last pointer and check for odd-sized files.
+ * Setting out->last to zero forces us to follow the linked
+ * list of records in the file to the last record. That's
+ * done in the set_position code. It's a bit slower, but it's
+ * better at preventing crashes in corrupt files.
+ */
- out->store = f;
+ /* records are at least MSG_RECORD_FIXED_LENGTH bytes */
+ if ((out->last + MSG_RECORD_FIXED_LENGTH) > out->file_size)
+ {
+ out->last = 0;
+ }
+ else
+ {
+ /* read last record length and make sure the file is at least that large */
+ off = out->last + RECORD_TYPE_LEN;
+ status = asl_file_read_uint32(out, off, &last_len);
+ if (status != ASL_STATUS_OK)
+ {
+ fclose(out->store);
+ free(out);
+ return status;
+ }
+
+ if ((out->last + last_len) > out->file_size) out->last = 0;
+ }
out->cursor = out->first;
if (out->cursor != 0)
status = asl_file_read_uint64(out, off, &(out->cursor_xid));
if (status != ASL_STATUS_OK)
{
- fclose(f);
+ fclose(out->store);
+ free(out);
return status;
}
}
if (status != ASL_STATUS_OK) return status;
/* detect bogus next pointer */
- if (next >= s->file_size) next = 0;
+ if (((next + MSG_RECORD_FIXED_LENGTH) > s->file_size) || (next <= s->cursor)) next = 0;
if (next == 0)
{
uint32_t
asl_file_read_set_position(asl_file_t *s, uint32_t pos)
{
+ uint64_t next;
uint32_t len, status;
off_t off;
/*
* read offset of next / previous
*/
- status = asl_file_read_uint64(s, off, &(s->cursor));
+ next = 0;
+ status = asl_file_read_uint64(s, off, &next);
if (status != ASL_STATUS_OK) return ASL_STATUS_READ_FAILED;
/* detect bogus next pointer */
- if (s->cursor >= s->file_size) s->cursor = 0;
+ if ((next + MSG_RECORD_FIXED_LENGTH) > s->file_size) next = 0;
+ else if ((pos == ASL_FILE_POSITION_PREVIOUS) && (next >= s->cursor)) next = 0;
+ else if ((pos == ASL_FILE_POSITION_NEXT) && (next <= s->cursor)) next = 0;
+ s->cursor = next;
if (s->cursor == 0) return ASL_STATUS_NO_RECORDS;
/* read ID of the record */
return asl_file_fetch_pos(s, s->cursor, 1, msg);
}
-uint64_t
+__private_extern__ uint64_t
asl_file_cursor(asl_file_t *s)
{
if (s == NULL) return 0;
return s->cursor_xid;
}
-uint32_t
+__private_extern__ uint32_t
asl_file_match_start(asl_file_t *s, uint64_t start_id, int32_t direction)
{
uint32_t status, d;
return status;
}
-uint32_t
-asl_file_match_next(asl_file_t *s, aslresponse query, asl_msg_t **msg, uint64_t *last_id, int32_t direction)
+__private_extern__ uint32_t
+asl_file_match_next(asl_file_t *s, aslresponse query, aslmsg *msg, uint64_t *last_id, int32_t direction)
{
uint32_t status, d, i, do_match, did_match;
aslmsg m;
for (i = 0; (i < query->count) && (did_match == 0); i++)
{
- did_match = asl_msg_cmp(query->msg[i], m);
+ did_match = asl_msg_cmp((aslmsg)(query->msg[i]), m);
}
}
asl_file_match(asl_file_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction)
{
uint32_t status, d, i, do_match, did_match, rescount;
- asl_msg_t *m;
+ aslmsg m;
if (s == NULL) return ASL_STATUS_INVALID_STORE;
if (res == NULL) return ASL_STATUS_INVALID_ARG;
for (i = 0; (i < query->count) && (did_match == 0); i++)
{
- did_match = asl_msg_cmp(query->msg[i], m);
+ did_match = asl_msg_cmp((aslmsg)query->msg[i], m);
}
}
{
*res = (aslresponse)calloc(1, sizeof(aslresponse));
if (*res == NULL) return ASL_STATUS_NO_MEMORY;
- (*res)->msg = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
+ (*res)->msg = (asl_msg_t **)calloc(1, sizeof(aslmsg));
if ((*res)->msg == NULL)
{
free(*res);
}
else
{
- (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, ((*res)->count + 1) * sizeof(asl_msg_t *));
+ (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, ((*res)->count + 1) * sizeof(aslmsg));
if ((*res)->msg == NULL)
{
free(*res);
}
}
- (*res)->msg[(*res)->count] = m;
+ (*res)->msg[(*res)->count] = (asl_msg_t *)m;
(*res)->count++;
rescount++;
}
}
-asl_file_list_t *
+static asl_file_list_t *
asl_file_list_insert(asl_file_list_t *list, asl_file_t *f, int32_t dir)
{
asl_file_list_t *a, *b, *tmp;
{
uint32_t status, rescount;
asl_file_list_t *n;
- asl_msg_t *m;
+ aslmsg m;
asl_file_match_token_t *work;
uint64_t last_id;
return ASL_STATUS_NO_MEMORY;
}
- if ((*res)->msg == NULL) (*res)->msg = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
- else (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, ((*res)->count + 1) * sizeof(asl_msg_t *));
+ if ((*res)->msg == NULL) (*res)->msg = (asl_msg_t **)calloc(1, sizeof(aslmsg));
+ else (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, ((*res)->count + 1) * sizeof(aslmsg));
if ((*res)->msg == NULL)
{
free(*res);
return ASL_STATUS_NO_MEMORY;
}
- (*res)->msg[(*res)->count] = m;
+ (*res)->msg[(*res)->count] = (asl_msg_t *)m;
(*res)->count++;
rescount++;
}
{
uint32_t status, rescount;
asl_file_list_t *files, *n;
- asl_msg_t *m;
+ aslmsg m;
struct timeval now, finish;
if (list == NULL) return ASL_STATUS_INVALID_ARG;
return ASL_STATUS_NO_MEMORY;
}
- if ((*res)->msg == NULL) (*res)->msg = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
- else (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, ((*res)->count + 1) * sizeof(asl_msg_t *));
+ if ((*res)->msg == NULL) (*res)->msg = (asl_msg_t **)calloc(1, sizeof(aslmsg));
+ else (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, ((*res)->count + 1) * sizeof(aslmsg));
if ((*res)->msg == NULL)
{
free(*res);
return ASL_STATUS_NO_MEMORY;
}
- (*res)->msg[(*res)->count] = m;
+ (*res)->msg[(*res)->count] = (asl_msg_t *)m;
(*res)->count++;
rescount++;
}
-#ifndef __ASL_FILE_H__
-#define __ASL_FILE_H__
-
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 2007 Apple Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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 __ASL_FILE_H__
+#define __ASL_FILE_H__
+
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <asl.h>
+#include <Availability.h>
#define DB_HEADER_LEN 80
#define DB_HEADER_COOKIE_OFFSET 0
struct asl_file_list_s *next;
} asl_file_list_t;
-asl_file_list_t *asl_file_list_add(asl_file_list_t *list, asl_file_t *f);
-void asl_file_list_close(asl_file_list_t *list);
+asl_file_list_t *asl_file_list_add(asl_file_list_t *list, asl_file_t *f) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+void asl_file_list_close(asl_file_list_t *list) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_file_open_write(const char *path, mode_t mode, uid_t uid, gid_t gid, asl_file_t **s);
-uint32_t asl_file_close(asl_file_t *s);
+uint32_t asl_file_open_write(const char *path, mode_t mode, uid_t uid, gid_t gid, asl_file_t **s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_file_close(asl_file_t *s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_file_save(asl_file_t *s, aslmsg msg, uint64_t *mid);
+uint32_t asl_file_save(asl_file_t *s, aslmsg msg, uint64_t *mid) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_file_open_read(const char *path, asl_file_t **s);
-uint32_t asl_file_fetch(asl_file_t *s, uint64_t mid, aslmsg *msg);
+uint32_t asl_file_open_read(const char *path, asl_file_t **s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_file_fetch(asl_file_t *s, uint64_t mid, aslmsg *msg) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_file_read_set_position(asl_file_t *s, uint32_t pos);
-uint32_t asl_file_fetch_next(asl_file_t *s, aslmsg *msg);
-uint32_t asl_file_fetch_previous(asl_file_t *s, aslmsg *msg);
+uint32_t asl_file_read_set_position(asl_file_t *s, uint32_t pos) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_file_fetch_next(asl_file_t *s, aslmsg *msg) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_file_fetch_previous(asl_file_t *s, aslmsg *msg) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_file_match(asl_file_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction);
-uint32_t asl_file_list_match_timeout(asl_file_list_t *list, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, uint32_t usec);
-uint32_t asl_file_list_match(asl_file_list_t *list, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction);
+uint32_t asl_file_match(asl_file_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_file_list_match_timeout(asl_file_list_t *list, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, uint32_t usec) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
+uint32_t asl_file_list_match(asl_file_list_t *list, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-void *asl_file_list_match_start(asl_file_list_t *list, uint64_t start_id, int32_t direction);
-uint32_t asl_file_list_match_next(void *token, aslresponse query, aslresponse *res, uint32_t count);
-void asl_file_list_match_end(void *token);
+void *asl_file_list_match_start(asl_file_list_t *list, uint64_t start_id, int32_t direction) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_file_list_match_next(void *token, aslresponse query, aslresponse *res, uint32_t count) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+void asl_file_list_match_end(void *token) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-size_t asl_file_size(asl_file_t *s);
-uint64_t asl_file_ctime(asl_file_t *s);
+size_t asl_file_size(asl_file_t *s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint64_t asl_file_ctime(asl_file_t *s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_file_compact(asl_file_t *s, const char *path, mode_t mode, uid_t uid, gid_t gid);
+uint32_t asl_file_compact(asl_file_t *s, const char *path, mode_t mode, uid_t uid, gid_t gid) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
#endif __ASL_FILE_H__
/*
- * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
-subsystem asl_ipc 1;
+subsystem asl_ipc 114;
serverprefix _;
import <sys/types.h>;
SecToken token : security_token_t
);
+routine _asl_server_create_aux_link
+(
+ server : mach_port_t;
+ message : ooline_data, dealloc;
+ out fileport : mach_port_move_send_t;
+ out url : ooline_data, dealloc;
+ out status : int;
+ ServerAuditToken token : audit_token_t
+);
+
simpleroutine _asl_server_message
(
server : mach_port_t;
message : ooline_data, dealloc;
ServerAuditToken token : audit_token_t
);
+
+simpleroutine _asl_server_register_direct_watch
+(
+ server : mach_port_t;
+ port : int;
+ ServerAuditToken token : audit_token_t
+);
+
+simpleroutine _asl_server_cancel_direct_watch
+(
+ server : mach_port_t;
+ port : int;
+ ServerAuditToken token : audit_token_t
+);
#define MSG_OFF_KEY_FLAGS 77
extern time_t asl_parse_time(const char *str);
-extern int asl_msg_cmp(asl_msg_t *a, asl_msg_t *b);
+extern int asl_msg_cmp(aslmsg a, aslmsg b);
#define asl_msg_list_t asl_search_result_t
-#define PMSG_SEL_TIME 0x0001
-#define PMSG_SEL_HOST 0x0002
-#define PMSG_SEL_SENDER 0x0004
-#define PMSG_SEL_FACILITY 0x0008
-#define PMSG_SEL_MESSAGE 0x0010
-#define PMSG_SEL_LEVEL 0x0020
-#define PMSG_SEL_PID 0x0040
-#define PMSG_SEL_UID 0x0080
-#define PMSG_SEL_GID 0x0100
-#define PMSG_SEL_RUID 0x0200
-#define PMSG_SEL_RGID 0x0400
-
-#define PMSG_FETCH_ALL 0
-#define PMSG_FETCH_STD 1
-#define PMSG_FETCH_KV 2
-
#define Q_NULL 100001
#define Q_FAST 100002
#define Q_SLOW 100003
#define Q_FAIL 100004
-typedef struct
-{
- uint16_t kselect;
- uint16_t vselect;
- uint64_t msgid;
- uint64_t time;
- uint64_t host;
- uint64_t sender;
- uint64_t facility;
- uint64_t message;
- uint32_t level;
- uint32_t pid;
- int32_t uid;
- int32_t gid;
- int32_t ruid;
- int32_t rgid;
- uint32_t next;
- uint32_t kvcount;
- uint64_t *kvlist;
-} pmsg_t;
-
static uint64_t
_asl_htonq(uint64_t n)
{
}
static uint32_t
-pmsg_fetch(asl_legacy1_t *s, uint32_t slot, uint32_t action, pmsg_t **pmsg)
+asl_legacy1_fetch_helper_32(asl_legacy1_t *s, char **p, aslmsg m, const char *key, int ignore, uint32_t ignoreval)
{
- off_t offset;
- uint32_t status, i, n, v32, next;
- int32_t msgu, msgg;
- uint64_t msgid;
- uint16_t flags;
- pmsg_t *out;
- char *p, tmp[DB_RECORD_LEN];
+ uint32_t out, doit;
+ char str[256];
- if (s == NULL) return ASL_STATUS_INVALID_STORE;
- if (pmsg == NULL) return ASL_STATUS_INVALID_ARG;
+ out = _asl_get_32(*p);
+ *p += sizeof(uint32_t);
- out = NULL;
+ if ((m == NULL) || (key == NULL)) return out;
- if ((action == PMSG_FETCH_ALL) || (action == PMSG_FETCH_STD))
+ doit = 1;
+ if ((ignore != 0) && (out == ignoreval)) doit = 0;
+ if (doit != 0)
{
- *pmsg = NULL;
-
- offset = slot * DB_RECORD_LEN;
- status = fseek(s->db, offset, SEEK_SET);
+ snprintf(str, sizeof(str), "%u", out);
+ asl_set(m, key, str);
+ }
- if (status < 0) return ASL_STATUS_READ_FAILED;
+ return out;
+}
- status = fread(tmp, DB_RECORD_LEN, 1, s->db);
- if (status != 1) return ASL_STATUS_READ_FAILED;
+static uint64_t
+asl_legacy1_fetch_helper_64(asl_legacy1_t *s, char **p, aslmsg m, const char *key)
+{
+ uint64_t out;
+ char str[256];
- msgid = _asl_get_64(tmp + MSG_OFF_KEY_ID);
- msgu = _asl_get_32(tmp + MSG_OFF_KEY_RUID);
- msgg = _asl_get_32(tmp + MSG_OFF_KEY_RGID);
- flags = _asl_get_16(tmp + MSG_OFF_KEY_FLAGS);
+ out = _asl_get_64(*p);
+ *p += sizeof(uint64_t);
- out = (pmsg_t *)calloc(1, sizeof(pmsg_t));
- if (out == NULL) return ASL_STATUS_NO_MEMORY;
+ if ((m == NULL) || (key == NULL)) return out;
+ snprintf(str, sizeof(str), "%llu", out);
+ asl_set(m, key, str);
- p = tmp + 21;
+ return out;
+}
- /* ID */
- out->msgid = msgid;
+static uint64_t
+asl_legacy1_fetch_helper_str(asl_legacy1_t *s, char **p, aslmsg m, const char *key, uint32_t *err)
+{
+ uint64_t out;
+ char *val;
+ uint32_t status;
- /* ReadUID */
- out->ruid = msgu;
+ out = _asl_get_64(*p);
+ *p += sizeof(uint64_t);
- /* ReadGID */
- out->rgid = msgg;
+ val = NULL;
+ status = ASL_STATUS_OK;
+ if (out != 0) status = string_fetch_sid(s, out, &val);
- /* Time */
- out->time = _asl_get_64(p);
- p += 8;
+ if (err != NULL) *err = status;
+ if ((status == ASL_STATUS_OK) && (val != NULL))
+ {
+ asl_set(m, key, val);
+ free(val);
+ }
- /* Host */
- out->host = _asl_get_64(p);
- p += 8;
+ return out;
+}
- /* Sender */
- out->sender = _asl_get_64(p);
- p += 8;
+static uint32_t
+msg_fetch(asl_legacy1_t *s, uint32_t slot, aslmsg *out)
+{
+ off_t offset;
+ uint32_t status, i, n, kvcount, next;
+ uint16_t flags;
+ uint64_t sid;
+ aslmsg msg;
+ char *p, tmp[DB_RECORD_LEN], *key, *val;
- /* Facility */
- out->facility = _asl_get_64(p);
- p += 8;
+ if (s == NULL) return ASL_STATUS_INVALID_STORE;
+ if (out == NULL) return ASL_STATUS_INVALID_ARG;
- /* Level */
- out->level = _asl_get_32(p);
- p += 4;
+ *out = NULL;
- /* PID */
- out->pid = _asl_get_32(p);
- p += 4;
+ offset = slot * DB_RECORD_LEN;
+ status = fseek(s->db, offset, SEEK_SET);
- /* UID */
- out->uid = _asl_get_32(p);
- p += 4;
+ if (status < 0) return ASL_STATUS_READ_FAILED;
- /* GID */
- out->gid = _asl_get_32(p);
- p += 4;
+ status = fread(tmp, DB_RECORD_LEN, 1, s->db);
+ if (status != 1) return ASL_STATUS_READ_FAILED;
- /* Message */
- out->message = _asl_get_64(p);
- p += 8;
+ flags = _asl_get_16(tmp + MSG_OFF_KEY_FLAGS);
- next = header_get_next(tmp);
- out->next = next;
+ msg = asl_new(ASL_TYPE_MSG);
+ if (msg == NULL) return ASL_STATUS_NO_MEMORY;
- if (action == PMSG_FETCH_STD)
- {
- /* caller only wants "standard" keys */
- *pmsg = out;
- return ASL_STATUS_OK;
- }
+ p = tmp + 5;
+
+ asl_legacy1_fetch_helper_64(s, &p, msg, ASL_KEY_MSG_ID);
+ asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_READ_UID, 1, (uint32_t)-1);
+ asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_READ_GID, 1, (uint32_t)-1);
+ asl_legacy1_fetch_helper_64(s, &p, msg, ASL_KEY_TIME);
+ asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_HOST, &status);
+ asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_SENDER, &status);
+ asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_FACILITY, &status);
+ asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_LEVEL, 0, 0);
+ asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_PID, 0, 0);
+ asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_UID, 0, 0);
+ asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_GID, 0, 0);
+ asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_MSG, &status);
- *pmsg = out;
- }
- else
- {
- out = *pmsg;
- }
+ next = header_get_next(tmp);
+ kvcount = 0;
n = 0;
- next = out->next;
while (next != 0)
{
status = fseek(s->db, offset, SEEK_SET);
if (status < 0)
{
- *pmsg = NULL;
free(out);
return ASL_STATUS_READ_FAILED;
}
status = fread(tmp, DB_RECORD_LEN, 1, s->db);
if (status != 1)
{
- *pmsg = NULL;
free(out);
return ASL_STATUS_READ_FAILED;
}
- if (out->kvcount == 0)
- {
- v32 = _asl_get_32(tmp + 5);
- out->kvcount = v32 * 2;
- out->kvlist = (uint64_t *)calloc(out->kvcount, sizeof(uint64_t));
- if (out->kvlist == NULL)
- {
- *pmsg = NULL;
- free(out);
- return ASL_STATUS_NO_MEMORY;
- }
- }
+ if (kvcount == 0) kvcount = _asl_get_32(tmp + 5);
p = tmp + 9;
- for (i = 0; (i < 4) && (n < out->kvcount); i++)
+ for (i = 0; (i < 4) && (n < kvcount); i++)
{
- out->kvlist[n++] = _asl_get_64(p);
+ key = NULL;
+ sid = _asl_get_64(p);
p += 8;
+ status = string_fetch_sid(s, sid, &key);
- out->kvlist[n++] = _asl_get_64(p);
+ val = NULL;
+ sid = _asl_get_64(p);
p += 8;
- }
-
- next = header_get_next(tmp);
- }
-
- return ASL_STATUS_OK;
-}
-
-static uint32_t
-pmsg_match(asl_legacy1_t *s, pmsg_t *q, pmsg_t *m)
-{
- uint32_t i, j;
-
- if (s == NULL) return 0;
- if (q == NULL) return 1;
- if (m == NULL) return 0;
-
- if (q->kselect & PMSG_SEL_TIME)
- {
- if (q->time == ASL_REF_NULL) return 0;
- if ((q->vselect & PMSG_SEL_TIME) && (q->time != m->time)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_HOST)
- {
- if (q->host == ASL_REF_NULL) return 0;
- if ((q->vselect & PMSG_SEL_HOST) && (q->host != m->host)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_SENDER)
- {
- if (q->sender == ASL_REF_NULL) return 0;
- if ((q->vselect & PMSG_SEL_SENDER) && (q->sender != m->sender)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_FACILITY)
- {
- if (q->facility == ASL_REF_NULL) return 0;
- if ((q->vselect & PMSG_SEL_FACILITY) && (q->facility != m->facility)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_MESSAGE)
- {
- if (q->message == ASL_REF_NULL) return 0;
- if ((q->vselect & PMSG_SEL_MESSAGE) && (q->message != m->message)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_LEVEL)
- {
- if (q->level == ASL_INDEX_NULL) return 0;
- if ((q->vselect & PMSG_SEL_LEVEL) && (q->level != m->level)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_PID)
- {
- if (q->pid == -1) return 0;
- if ((q->vselect & PMSG_SEL_PID) && (q->pid != m->pid)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_UID)
- {
- if (q->uid == -2) return 0;
- if ((q->vselect & PMSG_SEL_UID) && (q->uid != m->uid)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_GID)
- {
- if (q->gid == -2) return 0;
- if ((q->vselect & PMSG_SEL_GID) && (q->gid != m->gid)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_RUID)
- {
- if (q->ruid == -1) return 0;
- if ((q->vselect & PMSG_SEL_RUID) && (q->ruid != m->ruid)) return 0;
- }
-
- if (q->kselect & PMSG_SEL_RGID)
- {
- if (q->rgid == -1) return 0;
- if ((q->vselect & PMSG_SEL_RGID) && (q->rgid != m->rgid)) return 0;
- }
-
- for (i = 0; i < q->kvcount; i += 2)
- {
- for (j = 0; j < m->kvcount; j += 2)
- {
- if (q->kvlist[i] == m->kvlist[j])
- {
- if (q->kvlist[i + 1] == m->kvlist[j + 1]) break;
- return 0;
- }
- }
-
- if (j >= m->kvcount) return 0;
- }
-
- return 1;
-}
-
-static void
-free_pmsg(pmsg_t *p)
-{
- if (p == NULL) return;
- if (p->kvlist != NULL) free(p->kvlist);
- free(p);
-}
-
-static uint32_t
-pmsg_fetch_by_id(asl_legacy1_t *s, uint64_t msgid, pmsg_t **pmsg, uint32_t *slot)
-{
- uint32_t i, status;
-
- if (s == NULL) return ASL_STATUS_INVALID_STORE;
- if (msgid == ASL_REF_NULL) return ASL_STATUS_INVALID_ARG;
- if (slot == NULL) return ASL_STATUS_INVALID_ARG;
-
- *slot = ASL_INDEX_NULL;
-
- i = slotlist_find(s, msgid, 0);
- if (i == ASL_INDEX_NULL) return ASL_STATUS_INVALID_ID;
-
- *slot = s->slotlist[i].slot;
-
- /* read the message */
- *pmsg = NULL;
- status = pmsg_fetch(s, s->slotlist[i].slot, PMSG_FETCH_ALL, pmsg);
- if (status != ASL_STATUS_OK) return status;
- if (pmsg == NULL) return ASL_STATUS_FAILED;
-
- return status;
-}
-
-static uint32_t
-msg_decode(asl_legacy1_t *s, pmsg_t *pmsg, asl_msg_t **out)
-{
- uint32_t status, i, n;
- char *key, *val;
- asl_msg_t *msg;
-
- if (s == NULL) return ASL_STATUS_INVALID_STORE;
- if (out == NULL) return ASL_STATUS_INVALID_ARG;
- if (pmsg == NULL) return ASL_STATUS_INVALID_ARG;
-
- *out = NULL;
-
- msg = (asl_msg_t *)calloc(1, sizeof(asl_msg_t));
- if (msg == NULL) return ASL_STATUS_NO_MEMORY;
-
- msg->type = ASL_TYPE_MSG;
- msg->count = 0;
- if (pmsg->time != ASL_REF_NULL) msg->count++;
- if (pmsg->host != ASL_REF_NULL) msg->count++;
- if (pmsg->sender != ASL_REF_NULL) msg->count++;
- if (pmsg->facility != ASL_REF_NULL) msg->count++;
- if (pmsg->message != ASL_REF_NULL) msg->count++;
- if (pmsg->level != ASL_INDEX_NULL) msg->count++;
- if (pmsg->pid != -1) msg->count++;
- if (pmsg->uid != -2) msg->count++;
- if (pmsg->gid != -2) msg->count++;
- if (pmsg->ruid != -1) msg->count++;
- if (pmsg->rgid != -1) msg->count++;
-
- msg->count += pmsg->kvcount / 2;
-
- if (msg->count == 0)
- {
- free(msg);
- return ASL_STATUS_INVALID_MESSAGE;
- }
-
- /* Message ID */
- msg->count += 1;
-
- msg->key = (char **)calloc(msg->count, sizeof(char *));
- if (msg->key == NULL)
- {
- free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- msg->val = (char **)calloc(msg->count, sizeof(char *));
- if (msg->val == NULL)
- {
- free(msg->key);
- free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- n = 0;
-
- /* Time */
- if (pmsg->time != ASL_REF_NULL)
- {
- msg->key[n] = strdup(ASL_KEY_TIME);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%llu", pmsg->time);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
- }
-
- /* Host */
- if (pmsg->host != ASL_REF_NULL)
- {
- msg->key[n] = strdup(ASL_KEY_HOST);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- status = string_fetch_sid(s, pmsg->host, &(msg->val[n]));
- n++;
- }
-
- /* Sender */
- if (pmsg->sender != ASL_REF_NULL)
- {
- msg->key[n] = strdup(ASL_KEY_SENDER);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- status = string_fetch_sid(s, pmsg->sender, &(msg->val[n]));
- n++;
- }
-
- /* Facility */
- if (pmsg->facility != ASL_REF_NULL)
- {
- msg->key[n] = strdup(ASL_KEY_FACILITY);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- status = string_fetch_sid(s, pmsg->facility, &(msg->val[n]));
- n++;
- }
-
- /* Level */
- if (pmsg->level != ASL_INDEX_NULL)
- {
- msg->key[n] = strdup(ASL_KEY_LEVEL);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%u", pmsg->level);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
- }
-
- /* PID */
- if (pmsg->pid != -1)
- {
- msg->key[n] = strdup(ASL_KEY_PID);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%d", pmsg->pid);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
- }
-
- /* UID */
- if (pmsg->uid != -2)
- {
- msg->key[n] = strdup(ASL_KEY_UID);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%d", pmsg->uid);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
- }
-
- /* GID */
- if (pmsg->gid != -2)
- {
- msg->key[n] = strdup(ASL_KEY_GID);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%d", pmsg->gid);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
- }
-
- /* Message */
- if (pmsg->message != ASL_REF_NULL)
- {
- msg->key[n] = strdup(ASL_KEY_MSG);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- status = string_fetch_sid(s, pmsg->message, &(msg->val[n]));
- n++;
- }
-
- /* ReadUID */
- if (pmsg->ruid != -1)
- {
- msg->key[n] = strdup(ASL_KEY_READ_UID);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%d", pmsg->ruid);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
- }
-
- /* ReadGID */
- if (pmsg->rgid != -1)
- {
- msg->key[n] = strdup(ASL_KEY_READ_GID);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%d", pmsg->rgid);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
- }
-
- /* Message ID */
- msg->key[n] = strdup(ASL_KEY_MSG_ID);
- if (msg->key[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
-
- asprintf(&(msg->val[n]), "%llu", pmsg->msgid);
- if (msg->val[n] == NULL)
- {
- asl_free(msg);
- return ASL_STATUS_NO_MEMORY;
- }
- n++;
+ if (status == ASL_STATUS_OK) status = string_fetch_sid(s, sid, &val);
- /* Key - Value List */
- for (i = 0; i < pmsg->kvcount; i++)
- {
- key = NULL;
- status = string_fetch_sid(s, pmsg->kvlist[i++], &key);
- if (status != ASL_STATUS_OK)
- {
- if (key != NULL) free(key);
- continue;
- }
-
- val = NULL;
- status = string_fetch_sid(s, pmsg->kvlist[i], &val);
- if (status != ASL_STATUS_OK)
- {
+ if ((status == ASL_STATUS_OK) && (key != NULL)) asl_set(msg, key, val);
if (key != NULL) free(key);
if (val != NULL) free(val);
- continue;
+
+ n++;
}
- msg->key[n] = key;
- msg->val[n] = val;
- n++;
+ next = header_get_next(tmp);
}
*out = msg;
return ASL_STATUS_OK;
}
-/*
- * Finds string either in the string cache or in the database
- */
-static uint32_t
-store_string_find(asl_legacy1_t *s, uint32_t hash, const char *str, uint32_t *index)
-{
- uint32_t i, status;
- char *tmp;
-
- if (s == NULL) return ASL_STATUS_INVALID_STORE;
- if (str == NULL) return ASL_STATUS_INVALID_ARG;
- if (index == NULL) return ASL_STATUS_INVALID_ARG;
- if (s->slotlist == NULL) return ASL_STATUS_FAILED;
-
- /* check the database */
- for (i = 0; i < s->slotlist_count; i++)
- {
- if ((s->slotlist[i].type != DB_TYPE_STRING) || (s->slotlist[i].hash != hash)) continue;
-
- /* read the whole string */
- tmp = NULL;
- status = string_fetch_slot(s, s->slotlist[i].slot, &tmp);
- if (status != ASL_STATUS_OK) return status;
- if (tmp == NULL) return ASL_STATUS_FAILED;
-
- status = strcmp(tmp, str);
- free(tmp);
- if (status != 0) continue;
-
- /* Bingo! */
- *index = i;
- return ASL_STATUS_OK;
- }
-
- return ASL_STATUS_FAILED;
-}
-
-/*
- * Looks up a string ID number.
- */
-static uint64_t
-string_lookup(asl_legacy1_t *s, const char *str)
-{
- uint32_t status, hash, index, slot, len;
- uint64_t nsid, sid;
- char *p;
- uint8_t inls;
-
- if (s == NULL) return ASL_REF_NULL;
- if (str == NULL) return ASL_REF_NULL;
-
- sid = ASL_REF_NULL;
- index = ASL_INDEX_NULL;
- slot = ASL_INDEX_NULL;
-
- len = strlen(str);
- if (len < 8)
- {
- /* inline string */
- inls = len;
- inls |= 0x80;
-
- nsid = 0;
- p = (char *)&nsid;
- memcpy(p, &inls, 1);
- memcpy(p + 1, str, len);
- sid = _asl_ntohq(nsid);
- return sid;
- }
-
- hash = asl_core_string_hash(str, len);
-
- /* check the database */
- status = store_string_find(s, hash, str, &index);
- if (status == ASL_STATUS_OK)
- {
- if (index == ASL_INDEX_NULL) return ASL_REF_NULL;
- return s->slotlist[index].xid;
- }
-
- return ASL_REF_NULL;
-}
-
uint32_t
-asl_legacy1_fetch(asl_legacy1_t *s, uint64_t msgid, asl_msg_t **msg)
+asl_legacy1_fetch(asl_legacy1_t *s, uint64_t msgid, aslmsg *out)
{
- uint32_t status, slot;
- pmsg_t *pmsg;
+ uint32_t i, status;
if (s == NULL) return ASL_STATUS_INVALID_STORE;
if (msgid == ASL_REF_NULL) return ASL_STATUS_INVALID_ARG;
+ if (out == NULL) return ASL_STATUS_INVALID_ARG;
- pmsg = NULL;
- slot = ASL_INDEX_NULL;
+ i = slotlist_find(s, msgid, 0);
+ if (i == ASL_INDEX_NULL) return ASL_STATUS_INVALID_ID;
- status = pmsg_fetch_by_id(s, msgid, &pmsg, &slot);
+ /* read the message */
+ status = msg_fetch(s, s->slotlist[i].slot, out);
if (status != ASL_STATUS_OK) return status;
- if (pmsg == NULL) return ASL_STATUS_FAILED;
-
- status = msg_decode(s, pmsg, msg);
- free_pmsg(pmsg);
+ if (*out == NULL) return ASL_STATUS_FAILED;
return status;
}
-static uint32_t
-query_to_pmsg(asl_legacy1_t *s, asl_msg_t *q, pmsg_t **p)
-{
- pmsg_t *out;
- uint32_t i, j;
- uint64_t ksid, vsid;
-
- if (s == NULL) return ASL_STATUS_INVALID_STORE;
- if (p == NULL) return ASL_STATUS_INVALID_ARG;
-
- if (q == NULL) return Q_NULL;
- if (q->count == 0) return Q_NULL;
-
- *p = NULL;
-
- if (q->op != NULL)
- {
- for (i = 0; i < q->count; i++) if (q->op[i] != ASL_QUERY_OP_EQUAL) return Q_SLOW;
- }
-
- out = (pmsg_t *)calloc(1, sizeof(pmsg_t));
- if (out == NULL) return ASL_STATUS_NO_MEMORY;
-
- for (i = 0; i < q->count; i++)
- {
- if (q->key[i] == NULL) continue;
-
- else if (!strcmp(q->key[i], ASL_KEY_TIME))
- {
- if (out->kselect & PMSG_SEL_TIME)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_TIME;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_TIME;
- out->time = asl_parse_time(q->val[i]);
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_HOST))
- {
- if (out->kselect & PMSG_SEL_HOST)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_HOST;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_HOST;
- out->host = string_lookup(s, q->val[i]);
- if (out->host == ASL_REF_NULL)
- {
- free_pmsg(out);
- return Q_FAIL;
- }
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_SENDER))
- {
- if (out->kselect & PMSG_SEL_SENDER)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_SENDER;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_SENDER;
- out->sender = string_lookup(s, q->val[i]);
- if (out->sender == ASL_REF_NULL)
- {
- free_pmsg(out);
- return Q_FAIL;
- }
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_PID))
- {
- if (out->kselect & PMSG_SEL_PID)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_PID;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_PID;
- out->pid = atoi(q->val[i]);
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_UID))
- {
- if (out->kselect & PMSG_SEL_UID)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_UID;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_UID;
- out->uid = atoi(q->val[i]);
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_GID))
- {
- if (out->kselect & PMSG_SEL_GID)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_GID;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_GID;
- out->gid = atoi(q->val[i]);
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_LEVEL))
- {
- if (out->kselect & PMSG_SEL_LEVEL)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_LEVEL;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_LEVEL;
- out->level = atoi(q->val[i]);
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_MSG))
- {
- if (out->kselect & PMSG_SEL_MESSAGE)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_MESSAGE;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_MESSAGE;
- out->message = string_lookup(s, q->val[i]);
- if (out->message == ASL_REF_NULL)
- {
- free_pmsg(out);
- return Q_FAIL;
- }
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_FACILITY))
- {
- if (out->kselect & PMSG_SEL_FACILITY)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_FACILITY;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_FACILITY;
- out->facility = string_lookup(s, q->val[i]);
- if (out->facility == ASL_REF_NULL)
- {
- free_pmsg(out);
- return Q_FAIL;
- }
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_READ_UID))
- {
- if (out->kselect & PMSG_SEL_RUID)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_RUID;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_RUID;
- out->ruid = atoi(q->val[i]);
- }
- }
- else if (!strcmp(q->key[i], ASL_KEY_READ_GID))
- {
- if (out->kselect & PMSG_SEL_RGID)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
-
- out->kselect |= PMSG_SEL_RGID;
- if (q->val[i] != NULL)
- {
- out->vselect |= PMSG_SEL_RGID;
- out->rgid = atoi(q->val[i]);
- }
- }
- else
- {
- ksid = string_lookup(s, q->key[i]);
- if (ksid == ASL_REF_NULL)
- {
- free_pmsg(out);
- return Q_FAIL;
- }
-
- for (j = 0; j < out->kvcount; j += 2)
- {
- if (out->kvlist[j] == ksid)
- {
- free_pmsg(out);
- return Q_SLOW;
- }
- }
-
- vsid = ASL_REF_NULL;
- if (q->val[i] != NULL)
- {
- vsid = string_lookup(s, q->val[i]);
- if (ksid == ASL_REF_NULL)
- {
- free_pmsg(out);
- return Q_FAIL;
- }
- }
-
- if (out->kvcount == 0)
- {
- out->kvlist = (uint64_t *)calloc(2, sizeof(uint64_t));
- }
- else
- {
- out->kvlist = (uint64_t *)reallocf(out->kvlist, (out->kvcount + 2) * sizeof(uint64_t));
- }
-
- if (out->kvlist == NULL)
- {
- free_pmsg(out);
- return ASL_STATUS_NO_MEMORY;
- }
-
- out->kvlist[out->kvcount++] = ksid;
- out->kvlist[out->kvcount++] = vsid;
- }
- }
-
- *p = out;
- return Q_FAST;
-}
-
-static uint32_t
-msg_match(asl_legacy1_t *s, uint32_t qtype, pmsg_t *qp, asl_msg_t *q, uint32_t slot, pmsg_t **iopm, asl_msg_t **iomsg, asl_msg_list_t **res, uint32_t *didmatch)
-{
- uint32_t status, what;
-
- *didmatch = 0;
-
- if (qtype == Q_FAIL) return ASL_STATUS_OK;
-
- if (qtype == Q_NULL)
- {
- if (*iopm == NULL)
- {
- status = pmsg_fetch(s, slot, PMSG_FETCH_ALL, iopm);
- if (status != ASL_STATUS_OK) return status;
- if (*iopm == NULL) return ASL_STATUS_FAILED;
- }
- }
- else if (qtype == Q_FAST)
- {
- if (qp == NULL) return ASL_STATUS_INVALID_ARG;
-
- what = PMSG_FETCH_STD;
- if (qp->kvcount > 0) what = PMSG_FETCH_ALL;
-
- if (*iopm == NULL)
- {
- status = pmsg_fetch(s, slot, what, iopm);
- if (status != ASL_STATUS_OK) return status;
- if (*iopm == NULL) return ASL_STATUS_FAILED;
- }
-
- status = pmsg_match(s, qp, *iopm);
- if (status == 1)
- {
- if ((what == PMSG_FETCH_STD) && ((*iopm)->next != 0) && ((*iopm)->kvcount == 0))
- {
- status = pmsg_fetch(s, slot, PMSG_FETCH_KV, iopm);
- if (status != ASL_STATUS_OK) return status;
- if (*iopm == NULL) return ASL_STATUS_FAILED;
- }
- }
- else return ASL_STATUS_OK;
- }
- else if (qtype == Q_SLOW)
- {
- if (*iomsg == NULL)
- {
- if (*iopm == NULL)
- {
- status = pmsg_fetch(s, slot, PMSG_FETCH_ALL, iopm);
- if (status != ASL_STATUS_OK) return status;
- if (*iopm == NULL) return ASL_STATUS_FAILED;
- }
-
- status = msg_decode(s, *iopm, iomsg);
- if (status == ASL_STATUS_INVALID_MESSAGE) return ASL_STATUS_OK;
- if (status != ASL_STATUS_OK) return status;
- if (*iomsg == NULL) return ASL_STATUS_FAILED;
- }
-
- status = 0;
- if (asl_msg_cmp(q, *iomsg) != 0) status = 1;
- if (status == 0) return ASL_STATUS_OK;
- }
-
- *didmatch = 1;
-
- if (res == NULL) return ASL_STATUS_OK;
-
- if (*iomsg == NULL)
- {
- status = msg_decode(s, *iopm, iomsg);
- if (status == ASL_STATUS_INVALID_MESSAGE)
- {
- *didmatch = 0;
- return ASL_STATUS_OK;
- }
-
- if (status != ASL_STATUS_OK) return status;
- }
-
- if ((*res)->count == 0) (*res)->msg = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
- else (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, (1 + (*res)->count) * sizeof(asl_msg_t *));
- if ((*res)->msg == NULL) return ASL_STATUS_NO_MEMORY;
-
- (*res)->msg[(*res)->count++] = *iomsg;
-
- return ASL_STATUS_OK;
-}
-
static uint32_t
next_search_slot(asl_legacy1_t *s, uint32_t last_si, int32_t direction)
{
return ASL_INDEX_NULL;
}
-static uint32_t
-query_list_to_pmsg_list(asl_legacy1_t *s, asl_msg_list_t *query, uint32_t *match, pmsg_t ***qp, uint32_t **qtype, uint32_t *count)
-{
- pmsg_t **outp, *pm;
- uint32_t i, j, *outt;
- *match = 0;
- *qp = NULL;
- *qtype = 0;
- *count = 0;
-
- if (query == NULL) return ASL_STATUS_OK;
- if (match == NULL) return ASL_STATUS_INVALID_ARG;
- if (qp == NULL) return ASL_STATUS_INVALID_ARG;
- if (qtype == NULL) return ASL_STATUS_OK;
- if (query->msg == NULL) return ASL_STATUS_OK;
- if (query->count == 0) return ASL_STATUS_OK;
-
- outp = (pmsg_t **)calloc(query->count, sizeof(pmsg_t *));
- if (outp == NULL) return ASL_STATUS_NO_MEMORY;
-
- outt = (uint32_t *)calloc(query->count, sizeof(uint32_t));
- if (outt == NULL)
- {
- free(outp);
- return ASL_STATUS_NO_MEMORY;
- }
-
- *match = 1;
-
- for (i = 0; i < query->count; i++)
- {
- pm = NULL;
- outt[i] = query_to_pmsg(s, query->msg[i], &pm);
- if (outt[i] <= ASL_STATUS_FAILED)
- {
- if (pm != NULL) free_pmsg(pm);
- for (j = 0; j < i; j++) free_pmsg(outp[j]);
- free(outp);
- free(outt);
- return ASL_STATUS_NO_MEMORY;
- }
-
- outp[i] = pm;
- }
-
- *count = query->count;
- *qp = outp;
- *qtype = outt;
- return ASL_STATUS_OK;
-}
-
static void
-match_worker_cleanup(pmsg_t **ql, uint32_t *qt, uint32_t n, asl_msg_list_t **res)
+match_worker_cleanup(asl_msg_list_t **res)
{
uint32_t i;
- if (ql != NULL)
- {
- for (i = 0; i < n; i++) free_pmsg(ql[i]);
- free(ql);
- }
-
- if (qt != NULL) free(qt);
-
if (res != NULL)
{
- for (i = 0; i < (*res)->count; i++) asl_free((*res)->msg[i]);
+ for (i = 0; i < (*res)->count; i++) asl_free((aslmsg)(*res)->msg[i]);
free(*res);
}
}
* If any query is NULL, set match flog off (skips matching below).
* Else if all queries only check "standard" keys, set std flag to on.
*
- * If a query only tests equality, convert it to a pmsg_t. The conversion routine
- * checks for string values that are NOT in the database. If a string is not found,
- * the conversion fails and the query is markes as "never matches". Otherwise,
- * the query is marked "fast".
- *
* If all queries are marked as "never matches", return NULL.
*
* match loop:
* else for each query:
* if query is NULL (shouldn't happen) decode record and add it to result. Return to match loop.
* else if query never matches, ignore it.
- * else if query is fast, use pmsg_match. If it succeeds, decode record and add it to result. Return to match loop.
* else decode record and use asl_cmp. If it succeeds, add record to result. Return to match loop.
*
* return results.
static uint32_t
match_worker(asl_legacy1_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t **idlist, uint32_t *idcount, uint64_t start_id, int32_t count, int32_t direction)
{
- uint32_t mx, si, slot, i, qcount, match, didmatch, status, *qtype;
+ uint32_t mx, si, slot, i, qcount, match, didmatch, status;
uint64_t xid;
- pmsg_t **qp, *iopmsg;
- asl_msg_t *iomsg;
+ aslmsg msg;
if (s == NULL) return ASL_STATUS_INVALID_STORE;
if ((res == NULL) && (idlist == NULL)) return ASL_STATUS_INVALID_ARG;
slot = s->slotlist[si].slot;
- status = query_list_to_pmsg_list(s, query, &match, &qp, &qtype, &qcount);
- if (status != ASL_STATUS_OK) return status;
+ match = 1;
+ qcount = 0;
+
+ if (query == NULL) match = 0;
+ else if (query->count == 0) match = 0;
+ else qcount = query->count;
/*
* initialize result list if we've been asked to return messages
if (res != NULL)
{
*res = (asl_msg_list_t *)calloc(1, sizeof(asl_msg_list_t));
- if (*res == NULL)
- {
- match_worker_cleanup(qp, qtype, qcount, NULL);
- return ASL_STATUS_NO_MEMORY;
- }
+ if (*res == NULL) return ASL_STATUS_NO_MEMORY;
}
+ status = ASL_STATUS_OK;
+
/*
* loop through records
*/
*last_id = xid;
- iopmsg = NULL;
- iomsg = NULL;
+ status = msg_fetch(s, slot, &msg);
didmatch = 0;
if (match == 0)
{
- status = msg_match(s, Q_NULL, NULL, NULL, slot, &iopmsg, &iomsg, res, &didmatch);
- free_pmsg(iopmsg);
- if (didmatch == 0)
- {
- asl_free(iomsg);
- iomsg = NULL;
- }
- else
+ didmatch = 1;
+ }
+ else
+ {
+ for (i = 0; i < qcount; i++)
{
- if (idlist != NULL)
- {
- if (*idlist == NULL) *idlist = (uint64_t *)calloc(1, sizeof(uint64_t));
- else *idlist = (uint64_t *)reallocf(*idlist, (*idcount + 1) * sizeof(uint64_t));
- if (*idlist == NULL) status = ASL_STATUS_NO_MEMORY;
- else (*idlist)[*idcount] = xid;
- }
-
- (*idcount)++;
+ didmatch = asl_msg_cmp((aslmsg)(query->msg[i]), msg);
+ if (didmatch == 1) break;
}
+ }
- if (status != ASL_STATUS_OK)
+ if (didmatch == 1)
+ {
+ if ((*res)->count == 0) (*res)->msg = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *));
+ else (*res)->msg = (asl_msg_t **)reallocf((*res)->msg, (1 + (*res)->count) * sizeof(asl_msg_t *));
+ if ((*res)->msg == NULL)
{
- match_worker_cleanup(qp, qtype, qcount, res);
- return status;
+ match_worker_cleanup(res);
+ return ASL_STATUS_NO_MEMORY;
}
+
+ (*res)->msg[(*res)->count++] = (asl_msg_t *)msg;
}
else
{
- for (i = 0; i < qcount; i++)
- {
- status = msg_match(s, qtype[i], qp[i], query->msg[i], slot, &iopmsg, &iomsg, res, &didmatch);
- if (status != ASL_STATUS_OK)
- {
- free_pmsg(iopmsg);
- asl_free(iomsg);
- match_worker_cleanup(qp, qtype, qcount, res);
- return status;
- }
-
- if (didmatch == 1)
- {
- if (idlist != NULL)
- {
- if (*idlist == NULL) *idlist = (uint64_t *)calloc(1, sizeof(uint64_t));
- else *idlist = (uint64_t *)reallocf(*idlist, (*idcount + 1) * sizeof(uint64_t));
- if (*idlist == NULL)
- {
- match_worker_cleanup(qp, qtype, qcount, res);
- return ASL_STATUS_NO_MEMORY;
- }
-
- (*idlist)[*idcount] = xid;
- }
-
- (*idcount)++;
- break;
- }
- }
-
- free_pmsg(iopmsg);
- if ((didmatch == 0) || (res == NULL)) asl_free(iomsg);
+ asl_free(msg);
}
si = next_search_slot(s, si, direction);
}
- match_worker_cleanup(qp, qtype, qcount, NULL);
return status;
}
#include <stdint.h>
#include <unistd.h>
#include <asl.h>
+#include <Availability.h>
typedef struct
{
FILE *db;
} asl_legacy1_t;
-uint32_t asl_legacy1_open(const char *path, asl_legacy1_t **s);
-uint32_t asl_legacy1_close(asl_legacy1_t *s);
-uint32_t asl_legacy1_fetch(asl_legacy1_t *s, uint64_t msgid, aslmsg *msg);
-uint32_t asl_legacy1_match(asl_legacy1_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction);
+uint32_t asl_legacy1_open(const char *path, asl_legacy1_t **s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_legacy1_close(asl_legacy1_t *s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_legacy1_fetch(asl_legacy1_t *s, uint64_t msgid, aslmsg *msg) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_legacy1_match(asl_legacy1_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
#endif /*__ASL_LEGACY1_H__*/
--- /dev/null
+/*
+ * Copyright (c) 2009-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 <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <regex.h>
+#include <syslog.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <asl.h>
+#include <asl_private.h>
+#include <asl_core.h>
+#include <sys/types.h>
+#include <libkern/OSAtomic.h>
+#include <assert.h>
+#include "asl_msg.h"
+
+#define TOKEN_NULL 0
+#define TOKEN_OPEN 1
+#define TOKEN_CLOSE 2
+#define TOKEN_WORD 3
+#define TOKEN_INT 4
+
+#define MFMT_RAW 0
+#define MFMT_STD 1
+#define MFMT_BSD 2
+#define MFMT_XML 3
+#define MFMT_STR 4
+#define MFMT_MSG 5
+
+#define TFMT_SEC 0
+#define TFMT_UTC 1
+#define TFMT_LCL 2
+
+#define XML_TAG_KEY 0
+#define XML_TAG_STRING 1
+#define XML_TAG_DATA 2
+
+#define forever for(;;)
+
+#define streq(A, B) (strcmp(A, B) == 0)
+#define streq_len(A, B, C) (strncmp(A, B, C) == 0)
+#define strneq(A, B) (strcmp(A, B) != 0)
+#define strcaseeq(A, B) (strcasecmp(A, B) == 0)
+#define strcaseneq(A, B) (strcasecmp(A, B) != 0)
+
+#ifndef ASL_KEY_OPTION
+#define ASL_KEY_OPTION "ASLOption"
+#endif
+
+#ifndef ASL_QUERY_OP_FALSE
+#define ASL_QUERY_OP_FALSE 0
+#endif
+
+#define AUX_0_TIME 0x00000001
+#define AUX_0_TIME_NSEC 0x00000002
+#define AUX_0_HOST 0x00000004
+#define AUX_0_SENDER 0x00000008
+#define AUX_0_FACILITY 0x00000010
+#define AUX_0_PID 0x00000020
+#define AUX_0_UID 0x00000040
+#define AUX_0_GID 0x00000080
+#define AUX_0_MSG 0x00000100
+#define AUX_0_OPTION 0x00000200
+#define AUX_0_LEVEL 0x00000400
+
+/* character encoding lengths */
+static const uint8_t char_encode_len[128] =
+{
+ 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3
+};
+
+static const char *cvis_7_13 = "abtnvfr";
+
+extern time_t asl_parse_time(const char *in);
+
+/* from asl_util.c */
+int asl_is_utf8(const char *str);
+uint8_t *asl_b64_encode(const uint8_t *buf, size_t len);
+
+static const char *ASLStandardKey[] =
+{
+ ASL_KEY_TIME,
+ ASL_KEY_TIME_NSEC,
+ ASL_KEY_HOST,
+ ASL_KEY_SENDER,
+ ASL_KEY_FACILITY,
+ ASL_KEY_PID,
+ ASL_KEY_UID,
+ ASL_KEY_GID,
+ ASL_KEY_LEVEL,
+ ASL_KEY_MSG,
+ ASL_KEY_READ_UID,
+ ASL_KEY_READ_GID,
+ ASL_KEY_SESSION,
+ ASL_KEY_REF_PID,
+ ASL_KEY_REF_PROC,
+ ASL_KEY_MSG_ID,
+ ASL_KEY_EXPIRE_TIME,
+ ASL_KEY_OPTION
+};
+
+static const char *MTStandardKey[] =
+{
+ "com.apple.message.domain",
+ "com.apple.message.domain_scope",
+ "com.apple.message.result",
+ "com.apple.message.signature",
+ "com.apple.message.signature2",
+ "com.apple.message.signature3",
+ "com.apple.message.success",
+ "com.apple.message.uuid",
+ "com.apple.message.value",
+ "com.apple.message.value2",
+ "com.apple.message.value3",
+ "com.apple.message.value4",
+ "com.apple.message.value5"
+};
+
+static uint16_t
+_asl_msg_std_key(const char *s, uint32_t len)
+{
+ if ((len > 18) && (streq_len(s, "com.apple.message.", 18)))
+ {
+ if (streq(s + 18, "domain")) return ASL_MT_KEY_DOMAIN;
+ else if (streq(s + 18, "domain_scope")) return ASL_MT_KEY_SCOPE;
+ else if (streq(s + 18, "result")) return ASL_MT_KEY_RESULT;
+ else if (streq(s + 18, "signature")) return ASL_MT_KEY_SIG;
+ else if (streq(s + 18, "signature2")) return ASL_MT_KEY_SIG2;
+ else if (streq(s + 18, "signature3")) return ASL_MT_KEY_SIG3;
+ else if (streq(s + 18, "success")) return ASL_MT_KEY_SUCCESS;
+ else if (streq(s + 18, "uuid")) return ASL_MT_KEY_UUID;
+ else if (streq(s + 18, "value")) return ASL_MT_KEY_VAL;
+ else if (streq(s + 18, "value2")) return ASL_MT_KEY_VAL2;
+ else if (streq(s + 18, "value3")) return ASL_MT_KEY_VAL3;
+ else if (streq(s + 18, "value4")) return ASL_MT_KEY_VAL4;
+ else if (streq(s + 18, "value5")) return ASL_MT_KEY_VAL5;
+
+ return 0;
+ }
+
+ switch (len)
+ {
+ case 3:
+ {
+ if streq(s, ASL_KEY_PID) return ASL_STD_KEY_PID;
+ else if streq(s, ASL_KEY_UID) return ASL_STD_KEY_UID;
+ else if streq(s, ASL_KEY_GID) return ASL_STD_KEY_GID;
+ }
+ case 4:
+ {
+ if streq(s, ASL_KEY_TIME) return ASL_STD_KEY_TIME;
+ else if streq(s, ASL_KEY_HOST) return ASL_STD_KEY_HOST;
+ }
+ case 5:
+ {
+ if streq(s, ASL_KEY_LEVEL) return ASL_STD_KEY_LEVEL;
+ }
+ case 6:
+ {
+ if streq(s, ASL_KEY_SENDER) return ASL_STD_KEY_SENDER;
+ else if streq(s, ASL_KEY_REF_PID) return ASL_STD_KEY_REF_PID;
+ }
+ case 7:
+ {
+ if streq(s, ASL_KEY_MSG) return ASL_STD_KEY_MESSAGE;
+ else if streq(s, ASL_KEY_SESSION) return ASL_STD_KEY_SESSION;
+ else if streq(s, ASL_KEY_READ_UID) return ASL_STD_KEY_READ_UID;
+ else if streq(s, ASL_KEY_READ_GID) return ASL_STD_KEY_READ_GID;
+ else if streq(s, ASL_KEY_REF_PROC) return ASL_STD_KEY_REF_PROC;
+ }
+ case 8:
+ {
+ if streq(s, ASL_KEY_FACILITY) return ASL_STD_KEY_FACILITY;
+ }
+ case 9:
+ {
+ if streq(s, ASL_KEY_OPTION) return ASL_STD_KEY_OPTION;
+ }
+ case 11:
+ {
+ if streq(s, ASL_KEY_TIME_NSEC) return ASL_STD_KEY_NANO;
+ }
+ case 12:
+ {
+ if streq(s, ASL_KEY_MSG_ID) return ASL_STD_KEY_MSG_ID;
+ }
+ case 13:
+ {
+ if streq(s, ASL_KEY_EXPIRE_TIME) return ASL_STD_KEY_EXPIRE;
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static asl_msg_t *
+_asl_msg_make_page()
+{
+ asl_msg_t *out;
+ int i;
+
+ out = calloc(1, sizeof(asl_msg_t));
+ if (out == NULL) return NULL;
+
+ for (i = 0; i < ASL_MSG_PAGE_SLOTS; i++)
+ {
+ out->key[i] = ASL_MSG_SLOT_FREE;
+ out->val[i] = ASL_MSG_SLOT_FREE;
+ }
+
+ return out;
+}
+
+static const char *
+_asl_msg_slot_key(asl_msg_t *page, uint32_t slot)
+{
+ const char *out;
+ uint16_t x;
+
+ if (page == NULL) return NULL;
+ if (slot >= ASL_MSG_PAGE_SLOTS) return NULL;
+
+ if (page->key[slot] == ASL_MSG_SLOT_FREE) return NULL;
+
+ switch (page->key[slot] & ASL_MSG_KV_MASK)
+ {
+ case ASL_MSG_KV_INLINE:
+ {
+ return page->data + page->key[slot];
+ }
+ case ASL_MSG_KV_DICT:
+ {
+ if ((page->key[slot] > ASL_STD_KEY_BASE) && (page->key[slot] <= ASL_STD_KEY_LAST))
+ {
+ x = page->key[slot] - ASL_STD_KEY_BASE - 1;
+ return ASLStandardKey[x];
+ }
+ else if ((page->key[slot] > ASL_MT_KEY_BASE) && (page->key[slot] <= ASL_MT_KEY_LAST))
+ {
+ x = page->key[slot] - ASL_MT_KEY_BASE - 1;
+ return MTStandardKey[x];
+ }
+
+ return NULL;
+ }
+ case ASL_MSG_KV_EXTERN:
+ {
+ x = page->key[slot] & ASL_MSG_OFFSET_MASK;
+ memcpy(&out, page->data + x, sizeof(char *));
+ return out;
+ }
+ }
+
+ return NULL;
+}
+
+static const char *
+_asl_msg_slot_val(asl_msg_t *page, uint32_t slot)
+{
+ const char *out;
+ uint16_t x, type;
+
+ if (page == NULL) return NULL;
+ if (slot >= ASL_MSG_PAGE_SLOTS) return NULL;
+
+ if (page->val[slot] == ASL_MSG_SLOT_FREE) return NULL;
+
+ type = page->val[slot] & ASL_MSG_KV_MASK;
+
+ if (type == ASL_MSG_KV_INLINE)
+ {
+ return page->data + page->val[slot];
+ }
+ else if (type == ASL_MSG_KV_EXTERN)
+ {
+ x = page->val[slot] & ASL_MSG_OFFSET_MASK;
+ memcpy(&out, page->data + x, sizeof(char *));
+ return out;
+ }
+
+ return NULL;
+}
+
+/*
+ * asl_new: create a new log message.
+ */
+asl_msg_t *
+asl_msg_new(uint32_t type)
+{
+ asl_msg_t *out;
+
+ out = _asl_msg_make_page();
+ if (out == NULL) return NULL;
+
+ out->type = type;
+ out->refcount = 1;
+
+ return out;
+}
+
+asl_msg_t *
+asl_msg_retain(asl_msg_t *msg)
+{
+ int32_t new;
+
+ if (msg == NULL) return NULL;
+
+ new = OSAtomicIncrement32Barrier(&msg->refcount);
+ assert(new >= 1);
+
+ return msg;
+}
+
+static void
+_asl_msg_free(asl_msg_t *page)
+{
+ uint32_t i;
+ char *p;
+
+ if (page == NULL) return;
+
+ for (i = 0; i < ASL_MSG_PAGE_SLOTS; i++)
+ {
+ if ((page->key[i] & ASL_MSG_KV_MASK) == ASL_MSG_KV_EXTERN)
+ {
+ memcpy(&p, page->data + (page->key[i] & ASL_MSG_OFFSET_MASK), sizeof(char *));
+ free(p);
+ }
+
+ if ((page->val[i] & ASL_MSG_KV_MASK) == ASL_MSG_KV_EXTERN)
+ {
+ memcpy(&p, page->data + (page->val[i] & ASL_MSG_OFFSET_MASK), sizeof(char *));
+ free(p);
+ }
+ }
+
+ free(page);
+}
+
+void
+asl_msg_release(asl_msg_t *msg)
+{
+ int32_t new;
+ asl_msg_t *next;
+
+ if (msg == NULL) return;
+
+ new = OSAtomicDecrement32Barrier(&msg->refcount);
+ assert(new >= 0);
+
+ if (new > 0) return;
+
+ while (msg != NULL)
+ {
+ next = msg->next;
+ _asl_msg_free(msg);
+ msg = next;
+ }
+}
+
+static uint32_t
+_asl_msg_index(asl_msg_t *msg, const char *key, uint32_t *oslot, asl_msg_t **opage)
+{
+ uint32_t i, len, slot;
+ uint16_t kx;
+ asl_msg_t *page;
+ const char *kp;
+
+ if (msg == NULL) return IndexNull;
+ if (key == NULL) return IndexNull;
+
+ i = 0;
+ slot = 0;
+ if (oslot != NULL) *oslot = slot;
+
+ page = msg;
+ if (opage != NULL) *opage = page;
+
+ len = strlen(key);
+ kx = _asl_msg_std_key(key, len);
+
+ forever
+ {
+ if (page->key[slot] != ASL_MSG_SLOT_FREE)
+ {
+ if (kx != 0)
+ {
+ if (page->key[slot] == kx) return i;
+ }
+ else if ((page->key[slot] & ASL_MSG_KV_MASK) == ASL_MSG_KV_DICT)
+ {
+ /* page->key[slot] is a dictionary key, but key is not (kx == 0) so skip this slot */
+ }
+ else if ((page->key[slot] & ASL_MSG_KV_MASK) == ASL_MSG_KV_EXTERN)
+ {
+ memcpy(&kp, page->data + (page->key[slot] & ASL_MSG_OFFSET_MASK), sizeof(char *));
+ if (streq(key, kp)) return i;
+ }
+ else
+ {
+ kp = page->data + page->key[slot];
+ if (streq(key, kp)) return i;
+ }
+ }
+
+ i++;
+ slot++;
+ if (oslot != NULL) *oslot = slot;
+
+ if (slot >= ASL_MSG_PAGE_SLOTS)
+ {
+ if (page->next == NULL) return IndexNull;
+
+ slot = 0;
+ if (oslot != NULL) *oslot = slot;
+
+ page = page->next;
+ if (opage != NULL) *opage = page;
+ }
+ }
+
+ return IndexNull;
+}
+
+/*
+ * asl_msg_key: iterate over entries
+ * initial value of n should be 0
+ * after that, the value of n should be previously returned value
+ * sets the pointers for the next key, value, and op in the msgionary
+ * returns IndexNull when there are no more entries
+ */
+static uint32_t
+_asl_msg_fetch_internal(asl_msg_t *msg, uint32_t n, const char **keyout, const char **valout, uint32_t *opout, asl_msg_t **outpage, uint32_t *outslot)
+{
+ uint32_t slot;
+ asl_msg_t *page;
+
+ if (msg == NULL) return IndexNull;
+ if (outpage != NULL) *outpage = NULL;
+ if (outslot != NULL) *outslot = IndexNull;
+
+ slot = n;
+ page = msg;
+
+ while (slot >= ASL_MSG_PAGE_SLOTS)
+ {
+ if (page->next == NULL) return IndexNull;
+ page = page->next;
+ slot -= ASL_MSG_PAGE_SLOTS;
+ }
+
+ while (page->key[slot] == ASL_MSG_SLOT_FREE)
+ {
+ slot++;
+ n++;
+
+ if (slot >= ASL_MSG_PAGE_SLOTS)
+ {
+ if (page->next == NULL) return IndexNull;
+ page = page->next;
+ slot = 0;
+ }
+ }
+
+ n++;
+
+ if (keyout != NULL) *keyout = _asl_msg_slot_key(page, slot);
+ if (valout != NULL) *valout = _asl_msg_slot_val(page, slot);
+ if (opout != NULL) *opout = page->op[slot];
+
+ if (outpage != NULL) *outpage = page;
+ if (outslot != NULL) *outslot = slot;
+
+ return n;
+}
+
+uint32_t
+asl_msg_fetch(asl_msg_t *msg, uint32_t n, const char **keyout, const char **valout, uint32_t *opout)
+{
+ return _asl_msg_fetch_internal(msg, n, keyout, valout, opout, NULL, NULL);
+}
+
+static int
+_asl_msg_new_key_val_op(asl_msg_t *msg, const char *key, const char *val, uint32_t op)
+{
+ uint32_t slot, keylen, vallen, total;
+ uint16_t kx;
+ asl_msg_t *page, *last;
+ char *extkey, *extval;
+
+ if (msg == NULL) return -1;
+ if (key == NULL) return -1;
+
+ extkey = NULL;
+ extval = NULL;
+
+ keylen = strlen(key);
+ kx = _asl_msg_std_key(key, keylen);
+
+ if (kx == 0) keylen++;
+ else keylen = 0;
+
+ total = keylen;
+
+ vallen = 0;
+ if (val != NULL)
+ {
+ vallen = strlen(val) + 1;
+ total += vallen;
+ }
+
+ /* check if one or both of key and value must be "external" (in its own malloced space) */
+ if (keylen > ASL_MSG_PAGE_DATA_SIZE)
+ {
+ extkey = strdup(key);
+ keylen = sizeof(char *);
+ }
+
+ if (vallen > ASL_MSG_PAGE_DATA_SIZE)
+ {
+ extval = strdup(val);
+ vallen = sizeof(char *);
+ }
+
+ total = keylen + vallen;
+ if ((total > ASL_MSG_PAGE_DATA_SIZE) && (extval == NULL) && (keylen > 0))
+ {
+ extval = strdup(val);
+ vallen = sizeof(char *);
+ total = keylen + vallen;
+ }
+
+ if ((total > ASL_MSG_PAGE_DATA_SIZE) && (extkey == NULL))
+ {
+ extkey = strdup(key);
+ keylen = sizeof(char *);
+ total = keylen + vallen;
+ }
+
+ if (total > ASL_MSG_PAGE_DATA_SIZE)
+ {
+ /* can't happen, but... */
+ if (extkey != NULL) free(extkey);
+ if (extval != NULL) free(extval);
+ return -1;
+ }
+
+ /* find a page with space for the key and value and a free slot*/
+ slot = 0;
+ last = msg;
+
+ for (page = msg; page != NULL; page = page->next)
+ {
+ last = page;
+
+ if (total <= (ASL_MSG_PAGE_DATA_SIZE - page->data_size))
+ {
+ /* check for a free slot */
+ for (slot = 0; (slot < ASL_MSG_PAGE_SLOTS) && (page->key[slot] != ASL_MSG_SLOT_FREE); slot++);
+ if (slot < ASL_MSG_PAGE_SLOTS) break;
+ }
+ }
+
+ if (page == NULL)
+ {
+ /* allocate a new page and attach it */
+ page = _asl_msg_make_page();
+ if (page == NULL)
+ {
+ if (extkey != NULL) free(extkey);
+ if (extval != NULL) free(extval);
+ return -1;
+ }
+
+ last->next = page;
+ slot = 0;
+ }
+
+ /* copy key or external key pointer into page data */
+ if (kx != 0)
+ {
+ page->key[slot] = kx;
+ }
+ else if (extkey == NULL)
+ {
+ page->key[slot] = page->data_size;
+ memcpy(page->data + page->data_size, key, keylen);
+ }
+ else
+ {
+ page->key[slot] = page->data_size | ASL_MSG_KV_EXTERN;
+ memcpy(page->data + page->data_size, &extkey, keylen);
+ }
+
+ page->data_size += keylen;
+
+ /* copy val or external val pointer into page data */
+ page->val[slot] = ASL_MSG_SLOT_FREE;
+
+ if (val != NULL)
+ {
+ if (extval == NULL)
+ {
+ page->val[slot] = page->data_size;
+ memcpy(page->data + page->data_size, val, vallen);
+ }
+ else
+ {
+ page->val[slot] = page->data_size | ASL_MSG_KV_EXTERN;
+ memcpy(page->data + page->data_size, &extval, vallen);
+ }
+
+ page->data_size += vallen;
+ }
+
+ /* set op */
+ page->op[slot] = op;
+
+ /* update page count */
+ page->count++;
+
+ return 0;
+}
+
+/*
+ * Most of the code in asl_msg_set_key_val_op is concerned with trying to re-use
+ * space in an asl_msg_t page when given a new value for an existing key.
+ * If the key is new, we just call _asl_msg_new_key_val_op.
+ *
+ * Note that queries can have duplicate keys, so for ASL_TYPE_QUERY we just
+ * call through to _asl_msg_new_key_val_op.
+ */
+static int
+_asl_msg_set_kvo(asl_msg_t *msg, const char *key, const char *val, uint32_t op)
+{
+ uint32_t i, slot, newexternal;
+ asl_msg_t *page;
+ uint32_t intvallen, extvallen, newvallen;
+ char *intval, *extval, *newval;
+
+ if (msg == NULL) return -1;
+ if (key == NULL) return -1;
+
+ slot = IndexNull;
+ page = NULL;
+
+ if ((msg->type == ASL_TYPE_QUERY) || (IndexNull == _asl_msg_index(msg, key, &slot, &page)))
+ {
+ /* add key */
+ return _asl_msg_new_key_val_op(msg, key, val, op);
+ }
+
+ intval = NULL;
+ intvallen = 0;
+
+ extval = NULL;
+ extvallen = 0;
+
+ if (page->val[slot] != ASL_MSG_SLOT_FREE)
+ {
+ if ((page->val[slot] & ASL_MSG_KV_MASK) == ASL_MSG_KV_EXTERN)
+ {
+ i = page->val[slot] & ASL_MSG_OFFSET_MASK;
+ memcpy(&extval, page->data + i, sizeof(char *));
+ extvallen = sizeof(char *);
+ }
+ else
+ {
+ intval = page->data + page->val[slot];
+ intvallen = strlen(intval) + 1;
+ }
+ }
+
+ /* replace val and op for existing entry */
+
+ /* easy case - remove val */
+ if (val == NULL)
+ {
+ if (extval != NULL) free(extval);
+ page->val[slot] = ASL_MSG_SLOT_FREE;
+ if (op != IndexNull) page->op[slot] = op;
+ return 0;
+ }
+
+ /* trivial case - internal val doesn't change */
+ if ((intval != NULL) && (streq(val, intval)))
+ {
+ if (op != IndexNull) page->op[slot] = op;
+ return 0;
+ }
+
+ /* trivial case - external val doesn't change */
+ if ((extval != NULL) && (streq(val, extval)))
+ {
+ if (op != IndexNull) page->op[slot] = op;
+ return 0;
+ }
+
+ /*
+ * special case: we generally don't compress out holes in the data
+ * space, but if this is the last string in the currently used data space
+ * we can just back up the data_size and reset page->val[slot]
+ */
+ i = page->val[slot] & ASL_MSG_OFFSET_MASK;
+ if ((intval != NULL) && ((i + intvallen) == page->data_size))
+ {
+ page->val[slot] = ASL_MSG_SLOT_FREE;
+ page->data_size -= intvallen;
+ intval = NULL;
+ intvallen = 0;
+ }
+ else if ((extval != NULL) && ((i + extvallen) == page->data_size))
+ {
+ page->val[slot] = ASL_MSG_SLOT_FREE;
+ page->data_size -= extvallen;
+ free(extval);
+ extval = NULL;
+ extvallen = 0;
+ }
+
+ /* val changes - see if it needs to be external */
+ newvallen = strlen(val) + 1;
+ newexternal = 0;
+
+ if (newvallen > ASL_MSG_PAGE_DATA_SIZE)
+ {
+ newexternal = 1;
+ newvallen = sizeof(char *);
+ }
+
+ /* check if there is room to change val in place */
+ if (((extval != NULL) && (newvallen <= extvallen)) || ((extval == NULL) && (newvallen <= intvallen)))
+ {
+ if (extval != NULL) free(extval);
+ extval = NULL;
+
+ /* we can re-use the space of the old value */
+ i = page->val[slot] & ASL_MSG_OFFSET_MASK;
+
+ if (newexternal == 1)
+ {
+ /* create an external val and copy in the new pointer */
+ newval = strdup(val);
+ if (newval == NULL) return -1;
+
+ page->val[slot] = i | ASL_MSG_KV_EXTERN;
+ memcpy(page->data + i, &newval, sizeof(char *));
+ }
+ else
+ {
+ /* new internal value */
+ page->val[slot] = i;
+ memcpy(page->data + i, val, newvallen);
+ }
+
+ if (op != IndexNull) page->op[slot] = op;
+ return 0;
+ }
+
+ /* we're done with the old value if it is external - free it now */
+ if (extval != NULL) free(extval);
+ extval = NULL;
+
+ if (newvallen <= (ASL_MSG_PAGE_DATA_SIZE - page->data_size))
+ {
+ /* can't re-use the old space, but there's room on the page */
+ i = page->data_size;
+ page->data_size += newvallen;
+
+ if (newexternal == 1)
+ {
+ /* create an external val and copy in the new pointer */
+ newval = strdup(val);
+ if (newval == NULL) return -1;
+
+ page->val[slot] = i | ASL_MSG_KV_EXTERN;
+ memcpy(page->data + i, &newval, sizeof(char *));
+ }
+ else
+ {
+ /* new internal value */
+ page->val[slot] = i;
+ memcpy(page->data + i, val, newvallen);
+ }
+
+ if (op != IndexNull) page->op[slot] = op;
+ return 0;
+
+ }
+
+ /* no room on this page - free up existing entry and treat this as a new entry */
+ if ((page->key[slot] & ASL_MSG_KV_MASK) == ASL_MSG_KV_EXTERN)
+ {
+ memcpy(&extval, page->data + (page->key[slot] & ASL_MSG_OFFSET_MASK), sizeof(char *));
+ free(extval);
+ }
+
+ page->key[slot] = ASL_MSG_SLOT_FREE;
+ page->val[slot] = ASL_MSG_SLOT_FREE;
+ page->op[slot] = 0;
+
+ return _asl_msg_new_key_val_op(msg, key, val, op);
+}
+
+int
+asl_msg_set_key_val_op(asl_msg_t *msg, const char *key, const char *val, uint32_t op)
+{
+ char *special, buf[512];
+ uint32_t i, len;
+ int status;
+
+ /* Special case handling */
+ special = NULL;
+
+ /* convert "Level" values to "0" through "7" */
+ if (streq(key, ASL_KEY_LEVEL))
+ {
+ if (val == NULL) val = "7";
+ else if ((val[0] >= '0') && (val[0] <= '7') && (val[1] == '\0')) /* do nothing */;
+ else if (strcaseeq(val, ASL_STRING_EMERG)) val = "0";
+ else if (strcaseeq(val, ASL_STRING_ALERT)) val = "1";
+ else if (strcaseeq(val, ASL_STRING_CRIT)) val = "2";
+ else if (strcaseeq(val, ASL_STRING_ERR)) val = "3";
+ else if (strcaseeq(val, ASL_STRING_WARNING)) val = "4";
+ else if (strcaseeq(val, ASL_STRING_NOTICE)) val = "5";
+ else if (strcaseeq(val, ASL_STRING_INFO)) val = "6";
+ else if (strcaseeq(val, ASL_STRING_DEBUG)) val = "7";
+ else val = "7";
+ }
+
+ /* strip trailing newlines from "Message" values */
+ if ((streq(key, ASL_KEY_MSG)) && (val != NULL))
+ {
+ len = strlen(val);
+ i = len;
+ while ((i > 0) && (val[i - 1] == '\n')) i--;
+ if (i == 0) val = NULL;
+ else if (i < len)
+ {
+ /* use buf if it is big enough, else malloc a temporary buffer */
+ if (i < sizeof(buf))
+ {
+ memcpy(buf, val, i);
+ buf[i] = 0;
+ val = (const char *)buf;
+ }
+ else
+ {
+ special = malloc(i + 1);
+ if (special == NULL) return -1;
+ memcpy(special, val, i);
+ special[i] = 0;
+ val = (const char *)special;
+ }
+ }
+ }
+
+ status = _asl_msg_set_kvo(msg, key, val, op);
+
+ if (special != NULL) free(special);
+ return status;
+}
+
+int
+asl_msg_set_key_val(asl_msg_t *msg, const char *key, const char *val)
+{
+ return asl_msg_set_key_val_op(msg, key, val, 0);
+}
+
+/*
+ * asl_msg_unset
+ * Frees external key and val strings, but does not try to reclaim data space.
+ */
+void
+asl_msg_unset(asl_msg_t *msg, const char *key)
+{
+ uint32_t i, slot;
+ asl_msg_t *page;
+ char *ext;
+
+ if (msg == NULL) return;
+ if (key == NULL) return;
+
+ slot = IndexNull;
+ page = NULL;
+
+ i = _asl_msg_index(msg, key, &slot, &page);
+ if (i == IndexNull) return;
+
+ if ((page->key[slot] & ASL_MSG_KV_MASK) == ASL_MSG_KV_EXTERN)
+ {
+ memcpy(&ext, page->data + (page->key[slot] & ASL_MSG_OFFSET_MASK), sizeof(char *));
+ free(ext);
+ }
+
+ if ((page->val[slot] & ASL_MSG_KV_MASK) == ASL_MSG_KV_EXTERN)
+ {
+ memcpy(&ext, page->data + (page->val[slot] & ASL_MSG_OFFSET_MASK), sizeof(char *));
+ free(ext);
+ }
+
+ page->key[slot] = ASL_MSG_SLOT_FREE;
+ page->val[slot] = ASL_MSG_SLOT_FREE;
+ page->op[slot] = 0;
+
+ page->count--;
+}
+
+int
+asl_msg_lookup(asl_msg_t *msg, const char *key, const char **valout, uint32_t *opout)
+{
+ uint32_t i, slot;
+ asl_msg_t *page;
+
+ slot = IndexNull;
+ page = NULL;
+
+ i = _asl_msg_index(msg, key, &slot, &page);
+ if (i == IndexNull) return -1;
+
+ if (valout != NULL) *valout = _asl_msg_slot_val(page, slot);
+ if (opout != NULL) *opout = page->op[slot];
+
+ return 0;
+}
+
+uint32_t
+asl_msg_type(asl_msg_t *msg)
+{
+ if (msg == NULL) return 0;
+ return msg->type;
+}
+
+uint32_t
+asl_msg_count(asl_msg_t *msg)
+{
+ uint32_t total;
+
+ total = 0;
+
+ for (; msg != NULL; msg = msg->next) total += msg->count;
+ return total;
+}
+
+/*
+ * Compare messages
+ */
+static int
+_asl_msg_equal(asl_msg_t *a, asl_msg_t *b)
+{
+ uint32_t x, oa, ob;
+ const char *key, *va, *vb;
+
+ if (asl_msg_count(a) != asl_msg_count(b)) return 0;
+
+ key = NULL;
+ va = NULL;
+ oa = 0;
+
+
+ for (x = asl_msg_fetch(a, 0, &key, &va, &oa); x != IndexNull; x = asl_msg_fetch(a, x, &key, &va, &oa))
+ {
+ if (asl_msg_lookup(b, key, &vb, &ob) != 0) return 0;
+ if (strcmp(va, vb)) return 0;
+ if ((a->type == ASL_TYPE_QUERY) && (oa != ob)) return 0;
+ }
+
+ return 1;
+}
+
+static int
+_asl_isanumber(const char *s)
+{
+ int i;
+
+ if (s == NULL) return 0;
+
+ i = 0;
+ if ((s[0] == '-') || (s[0] == '+')) i = 1;
+
+ if (s[i] == '\0') return 0;
+
+ for (; s[i] != '\0'; i++)
+ {
+ if (!isdigit(s[i])) return 0;
+ }
+
+ return 1;
+}
+
+static int
+_asl_msg_basic_test(uint32_t op, const char *q, const char *m, uint32_t n)
+{
+ int cmp;
+ uint32_t t;
+ int64_t nq, nm;
+ int rflags;
+ regex_t rex;
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ /* NULL value from query or message string fails */
+ if ((q == NULL) || (m == NULL)) return (t & ASL_QUERY_OP_NOT_EQUAL);
+
+ if (op & ASL_QUERY_OP_REGEX)
+ {
+ /* greater than or less than make no sense in substring search */
+ if ((t == ASL_QUERY_OP_GREATER) || (t == ASL_QUERY_OP_LESS)) return 0;
+
+ memset(&rex, 0, sizeof(regex_t));
+
+ rflags = REG_EXTENDED | REG_NOSUB;
+ if (op & ASL_QUERY_OP_CASEFOLD) rflags |= REG_ICASE;
+
+ /* A bad reqular expression matches nothing */
+ if (regcomp(&rex, q, rflags) != 0) return (t & ASL_QUERY_OP_NOT_EQUAL);
+
+ cmp = regexec(&rex, m, 0, NULL, 0);
+ regfree(&rex);
+
+ if (t == ASL_QUERY_OP_NOT_EQUAL) return (cmp != 0);
+ return (cmp == 0);
+ }
+
+ if (op & ASL_QUERY_OP_NUMERIC)
+ {
+ if (_asl_isanumber(q) == 0) return (t == ASL_QUERY_OP_NOT_EQUAL);
+ if (_asl_isanumber(m) == 0) return (t == ASL_QUERY_OP_NOT_EQUAL);
+
+ nq = atoll(q);
+ nm = atoll(m);
+
+ switch (t)
+ {
+ case ASL_QUERY_OP_EQUAL: return (nm == nq);
+ case ASL_QUERY_OP_GREATER: return (nm > nq);
+ case ASL_QUERY_OP_GREATER_EQUAL: return (nm >= nq);
+ case ASL_QUERY_OP_LESS: return (nm < nq);
+ case ASL_QUERY_OP_LESS_EQUAL: return (nm <= nq);
+ case ASL_QUERY_OP_NOT_EQUAL: return (nm != nq);
+ default: return (t == ASL_QUERY_OP_NOT_EQUAL);
+ }
+ }
+
+ cmp = 0;
+ if (op & ASL_QUERY_OP_CASEFOLD)
+ {
+ if (n == 0) cmp = strcasecmp(m, q);
+ else cmp = strncasecmp(m, q, n);
+ }
+ else
+ {
+ if (n == 0) cmp = strcmp(m, q);
+ else cmp = strncmp(m, q, n);
+ }
+
+ switch (t)
+ {
+ case ASL_QUERY_OP_EQUAL: return (cmp == 0);
+ case ASL_QUERY_OP_GREATER: return (cmp > 0);
+ case ASL_QUERY_OP_GREATER_EQUAL: return (cmp >= 0);
+ case ASL_QUERY_OP_LESS: return (cmp < 0);
+ case ASL_QUERY_OP_LESS_EQUAL: return (cmp <= 0);
+ case ASL_QUERY_OP_NOT_EQUAL: return (cmp != 0);
+ }
+
+ return (t == ASL_QUERY_OP_NOT_EQUAL);
+}
+
+static int
+_asl_msg_test_substring(uint32_t op, const char *q, const char *m)
+{
+ uint32_t t, i, d, lm, lq, match, newop;
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ lm = 0;
+ if (m != NULL) lm = strlen(m);
+
+ lq = 0;
+ if (q != NULL) lq = strlen(q);
+
+ /* NULL is a substring of any string */
+ if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
+
+ /* A long string is defined to be not equal to a short string */
+ if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
+
+ /* greater than or less than make no sense in substring search */
+ if ((t == ASL_QUERY_OP_GREATER) || (t == ASL_QUERY_OP_LESS)) return 0;
+
+ /*
+ * We scan the string doing an equality test.
+ * If the input test is equality, we stop as soon as we hit a match.
+ * Otherwise we keep scanning the whole message string.
+ */
+ newop = op & 0xff0;
+ newop |= ASL_QUERY_OP_EQUAL;
+
+ match = 0;
+ d = lm - lq;
+ for (i = 0; i <= d; i++)
+ {
+ if (_asl_msg_basic_test(newop, q, m + i, lq) != 0)
+ {
+ if (t & ASL_QUERY_OP_EQUAL) return 1;
+ match++;
+ }
+ }
+
+ /* If the input test was for equality, no matches were found */
+ if (t & ASL_QUERY_OP_EQUAL) return 0;
+
+ /* The input test was for not equal. Return true if no matches were found */
+ return (match == 0);
+}
+
+static int
+_asl_msg_test_prefix(uint32_t op, const char *q, const char *m)
+{
+ uint32_t lm, lq, t;
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ lm = 0;
+ if (m != NULL) lm = strlen(m);
+
+ lq = 0;
+ if (q != NULL) lq = strlen(q);
+
+ /* NULL is a prefix of any string */
+ if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
+
+ /* A long string is defined to be not equal to a short string */
+ if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
+
+ /* Compare two equal-length strings */
+ return _asl_msg_basic_test(op, q, m, lq);
+}
+
+static int
+_asl_msg_test_suffix(uint32_t op, const char *q, const char *m)
+{
+ uint32_t lm, lq, d, t;
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ lm = 0;
+ if (m != NULL) lm = strlen(m);
+
+ lq = 0;
+ if (q != NULL) lq = strlen(q);
+
+ /* NULL is a suffix of any string */
+ if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
+
+ /* A long string is defined to be not equal to a short string */
+ if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
+
+ /* Compare two equal-length strings */
+ d = lm - lq;
+ return _asl_msg_basic_test(op, q, m + d, lq);
+}
+
+/*
+ * Splits out prefix, suffix, and substring tests.
+ * Sends the rest to _asl_msg_basic_test().
+ */
+static int
+_asl_msg_test_expression(uint32_t op, const char *q, const char *m)
+{
+ uint32_t t;
+
+ t = op & ASL_QUERY_OP_TRUE;
+ if (t == ASL_QUERY_OP_TRUE) return 1;
+
+ if (op & ASL_QUERY_OP_PREFIX)
+ {
+ if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_substring(op, q, m);
+ return _asl_msg_test_prefix(op, q, m);
+ }
+ if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_suffix(op, q, m);
+
+ return _asl_msg_basic_test(op, q, m, 0);
+}
+
+/*
+ * Special case for comparing time values.
+ * If both inputs are time strings, this compares the time
+ * value in seconds. Otherwise it just does normal matching.
+ */
+static int
+_asl_msg_test_time_expression(uint32_t op, const char *q, const char *m)
+{
+ time_t tq, tm;
+ uint32_t t;
+
+ if ((op & ASL_QUERY_OP_PREFIX) || (op & ASL_QUERY_OP_SUFFIX) || (op & ASL_QUERY_OP_REGEX)) return _asl_msg_test_expression(op, q, m);
+ if ((q == NULL) || (m == NULL)) return _asl_msg_test_expression(op, q, m);
+
+ tq = asl_parse_time(q);
+ if (tq < 0) return _asl_msg_test_expression(op, q, m);
+
+ tm = asl_parse_time(m);
+ if (tm < 0) return _asl_msg_test_expression(op, q, m);
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ switch (t)
+ {
+ case ASL_QUERY_OP_FALSE:
+ {
+ return 0;
+ }
+ case ASL_QUERY_OP_EQUAL:
+ {
+ if (tm == tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_GREATER:
+ {
+ if (tm > tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_GREATER_EQUAL:
+ {
+ if (tm >= tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_LESS:
+ {
+ if (tm < tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_LESS_EQUAL:
+ {
+ if (tm <= tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_NOT_EQUAL:
+ {
+ if (tm != tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_TRUE:
+ {
+ return 1;
+ }
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+/* test a query against a message */
+static int
+_asl_msg_test(asl_msg_t *q, asl_msg_t *m)
+{
+ uint32_t i, t, x, op;
+ int cmp;
+ const char *kq, *vq, *vm;
+
+ /*
+ * Check each simple expression (key op val) separately.
+ * The query suceeds (returns 1) if all simple expressions
+ * succeed (i.e. AND the simple expressions).
+ */
+
+ kq = NULL;
+ vq = NULL;
+ op = 0;
+
+ for (x = asl_msg_fetch(q, 0, &kq, &vq, &op); x != IndexNull; x = asl_msg_fetch(q, x, &kq, &vq, &op))
+ {
+ /* Find query key in the message */
+ vm = NULL;
+ i = asl_msg_lookup(m, kq, &vm, NULL);
+
+ /* ASL_QUERY_OP_TRUE tests if key is present in the message */
+ t = op & ASL_QUERY_OP_TRUE;
+ if (t == ASL_QUERY_OP_TRUE)
+ {
+ if (i != 0) return 0;
+ continue;
+ }
+
+ /* ASL_QUERY_OP_FALSE tests if the key is NOT present in the message */
+ if (t == ASL_QUERY_OP_FALSE)
+ {
+ if (i == 0) return 0;
+ continue;
+ }
+
+ if (i != 0)
+ {
+ /* the message does NOT have query key - fail unless we are testing not equal */
+ if (t == ASL_QUERY_OP_NOT_EQUAL) continue;
+ return 0;
+ }
+
+ cmp = 1;
+ if (streq(kq, ASL_KEY_TIME))
+ {
+ cmp = _asl_msg_test_time_expression(op, vq, vm);
+ }
+ else
+ {
+ cmp = _asl_msg_test_expression(op, vq, vm);
+ }
+
+ if (cmp == 0) return 0;
+ }
+
+ return 1;
+}
+
+int
+asl_msg_cmp(asl_msg_t *a, asl_msg_t *b)
+{
+
+ if (a == NULL) return 0;
+ if (b == NULL) return 0;
+
+ if (a->type == b->type) return _asl_msg_equal(a, b);
+ if (a->type == ASL_TYPE_QUERY) return _asl_msg_test(a, b);
+ return _asl_msg_test(b, a);
+}
+
+static void
+_asl_encode_char(char *buf, uint32_t *cursor, uint32_t c, uint32_t encode, uint32_t encode_space)
+{
+ char *p;
+ int meta;
+
+ meta = 0;
+
+ p = buf + *cursor;
+
+ /* NUL is not allowed */
+ if (c == 0) return;
+
+ /* Meta chars get \M prefix */
+ if (c >= 128)
+ {
+ /* except meta-space, which is \240 */
+ if (c == 160)
+ {
+ *p++ = '\\';
+ *p++ = '2';
+ *p++ = '4';
+ *p++ = '0';
+ *p = '\0';
+ *cursor = *cursor + 4;
+ return;
+ }
+
+ *p++ = '\\';
+ *p++ = 'M';
+ *p = '\0';
+ *cursor = *cursor + 2;
+ c &= 0x7f;
+ meta = 1;
+ }
+
+ /* space is either ' ' or \s */
+ if (c == 32)
+ {
+ if (encode_space == 0)
+ {
+ *p++ = ' ';
+ *p = '\0';
+ *cursor = *cursor + 1;
+ return;
+ }
+
+ *p++ = '\\';
+ *p++ = 's';
+ *p = '\0';
+ *cursor = *cursor + 2;
+ return;
+ }
+
+ /* \ is escaped */
+ if ((meta == 0) && (c == 92))
+ {
+ *p++ = '\\';
+ *p++ = c;
+ *p = '\0';
+ *cursor = *cursor + 2;
+ return;
+ }
+
+ /* [ and ] are escaped in ASL encoding */
+ if ((encode == ASL_ENCODE_ASL) && (meta == 0) && ((c == 91) || (c == 93)))
+ {
+ *p++ = '\\';
+ *p++ = c;
+ *p = '\0';
+ *cursor = *cursor + 2;
+ return;
+ }
+
+ /* DEL is \^? */
+ if (c == 127)
+ {
+ if (meta == 0)
+ {
+ *p++ = '\\';
+ *cursor = *cursor + 1;
+ }
+
+ *p++ = '^';
+ *p++ = '?';
+ *p = '\0';
+ *cursor = *cursor + 2;
+ return;
+ }
+
+ /* 33-126 are printable (add a '-' prefix for meta) */
+ if ((c >= 33) && (c <= 126))
+ {
+ if (meta == 1)
+ {
+ *p++ = '-';
+ *cursor = *cursor + 1;
+ }
+
+ *p++ = c;
+ *p = '\0';
+ *cursor = *cursor + 1;
+ return;
+ }
+
+ /* non-meta BEL, BS, HT, NL, VT, NP, CR (7-13) are \a, \b, \t, \n, \v, \f, and \r */
+ if ((meta == 0) && (c >= 7) && (c <= 13))
+ {
+ *p++ = '\\';
+ *p++ = cvis_7_13[c - 7];
+ *p = '\0';
+ *cursor = *cursor + 2;
+ return;
+ }
+
+ /* 0 - 31 are ^@ - ^_ (non-meta get a leading \) */
+ if ((c >= 0) && (c <= 31))
+ {
+ if (meta == 0)
+ {
+ *p++ = '\\';
+ *cursor = *cursor + 1;
+ }
+
+ *p++ = '^';
+ *p++ = 64 + c;
+ *p = '\0';
+ *cursor = *cursor + 2;
+ return;
+ }
+
+ return;
+}
+
+static uint32_t
+_asl_append_string_length(const char *s, uint32_t encode, uint32_t escspace)
+{
+ uint32_t i, n, spextra, outlen;
+ uint8_t c;
+
+ if (s == NULL) return 0;
+
+ outlen = 0;
+
+ if (encode == ASL_ENCODE_NONE)
+ {
+ /* no encoding - just need enough space for the string */
+ return strlen(s);
+ }
+ else if (encode == ASL_ENCODE_SAFE)
+ {
+ /* minor encoding to reduce the likelyhood of spoof attacks */
+ n = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ n++;
+ c = s[i];
+ if ((c == 10) || (c == 13) || (c == 8)) n++;
+ }
+
+ return n;
+ }
+
+ spextra = 0;
+ if (escspace != 0) spextra = 1;
+
+ n = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ c = s[i];
+
+ if (c >= 128)
+ {
+ n += 4;
+ }
+ else if ((c == 91) || (c == 93))
+ {
+ if (encode == ASL_ENCODE_ASL) n += 2;
+ else n += 1;
+ }
+ else
+ {
+ n += char_encode_len[c];
+ if (c == 32) n += spextra;
+ }
+ }
+
+ return n;
+}
+
+
+/*
+ * Append a string using the requested encoding to a buffer.
+ */
+static void
+_asl_append_string(char *buf, uint32_t bufsize, uint32_t *cursor, const char *s, uint32_t encode, uint32_t escspace)
+{
+ uint32_t i, n, spextra;
+ uint8_t c;
+ char *p;
+
+ if (buf == NULL) return;
+ if (cursor == NULL) return;
+ if (s == NULL) return;
+
+ if (encode == ASL_ENCODE_NONE)
+ {
+ /* no encoding - just use enough space and copy the string */
+
+ n = strlen(s);
+ if (n == 0) return;
+
+ assert((*cursor + n) < bufsize);
+
+ memcpy(buf + *cursor, s, n);
+ *cursor = *cursor + n;
+
+ return;
+ }
+ else if (encode == ASL_ENCODE_SAFE)
+ {
+ /*
+ * Minor encoding to reduce the likelyhood of spoof attacks.
+ *
+ * - append a tab after newlines
+ * - translate \r to newline & append a tab
+ * - map backspace to ^H
+ *
+ * Note that there may be UTF-8 characters that could be used in a spoof
+ * attack that we don't check. Caveat Reador.
+ */
+ n = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ n++;
+ c = s[i];
+ if ((c == 10) || (c == 13) || (c == 8)) n++;
+ }
+
+ if (n == 0) return;
+
+ assert((*cursor + n) < bufsize);
+
+ p = buf + *cursor;
+
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ c = s[i];
+ if ((c == 10) || (c == 13))
+ {
+ *p++ = '\n';
+ *p++ = '\t';
+ *cursor = *cursor + 2;
+ }
+ else if (c == 8)
+ {
+ *p++ = '^';
+ *p++ = 'H';
+ *cursor = *cursor + 2;
+ }
+ else
+ {
+ *p++ = c;
+ *cursor = *cursor + 1;
+ }
+ }
+
+ return;
+ }
+
+ spextra = 0;
+
+ if (escspace != 0) spextra = 1;
+
+ n = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ c = s[i];
+
+ if (c >= 128)
+ {
+ n += 4;
+ }
+ else if ((c == 91) || (c == 93))
+ {
+ if (encode == ASL_ENCODE_ASL) n += 2;
+ else n += 1;
+ }
+ else
+ {
+ n += char_encode_len[c];
+ if (c == 32) n += spextra;
+ }
+ }
+
+ if (n == 0) return;
+
+ assert((*cursor + n) < bufsize);
+
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ c = s[i];
+ _asl_encode_char(buf, cursor, c, encode, escspace);
+ }
+}
+
+
+static uint32_t
+_asl_append_xml_string_length(const char *s)
+{
+ uint32_t i, n;
+ uint8_t c;
+
+ if (s == NULL) return 0;
+
+ n = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ c = s[i];
+
+ /*
+ * XML wants & < > " and '
+ * We use &#xnn; for control chars.
+ * Everything else just gets printed "as is" (we know the input is UTF8)
+ */
+ if (c == '&') n += 5;
+ else if (c == '<') n += 4;
+ else if (c == '>') n += 4;
+ else if (c == '"') n += 6;
+ else if (c == '\'') n += 6;
+ else if (iscntrl(c)) n += 6;
+ else n += 1;
+ }
+
+ return n;
+}
+
+static int
+_asl_append_xml_string(char *buf, uint32_t bufsize, uint32_t *cursor, const char *s)
+{
+ uint32_t i, n;
+ uint8_t c;
+ char tmp[8], *p;
+
+ if (buf == NULL) return -1;
+ if (cursor == NULL) return -1;
+ if (s == NULL) return -1;
+
+ n = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ c = s[i];
+
+ /*
+ * XML wants & < > " and '
+ * We use &#xnn; for control chars.
+ * Everything else just gets printed "as is" (we know the input is UTF8)
+ */
+ if (c == '&') n += 5;
+ else if (c == '<') n += 4;
+ else if (c == '>') n += 4;
+ else if (c == '"') n += 6;
+ else if (c == '\'') n += 6;
+ else if (iscntrl(c)) n += 6;
+ else n += 1;
+ }
+
+ if (n == 0) return 0;
+
+ assert((*cursor + n) < bufsize);
+ p = buf + *cursor;
+
+ for (i = 0; s[i] != '\0'; i++)
+ {
+ c = s[i];
+
+ if (c == '&')
+ {
+ memcpy(p, "&", 5);
+ p += 5;
+ *cursor = *cursor + 5;
+ }
+ else if (c == '<')
+ {
+ memcpy(p, "<", 4);
+ p += 4;
+ *cursor = *cursor + 4;
+ }
+ else if (c == '>')
+ {
+ memcpy(p, ">", 4);
+ p += 4;
+ *cursor = *cursor + 4;
+ }
+ else if (c == '"')
+ {
+ memcpy(p, """, 6);
+ p += 6;
+ *cursor = *cursor + 6;
+ }
+ else if (c == '\'')
+ {
+ memcpy(p, "'", 6);
+ p += 6;
+ *cursor = *cursor + 6;
+ }
+ else if (iscntrl(c))
+ {
+ snprintf(tmp, sizeof(tmp), "&#x%02hhx;", c);
+ memcpy(p, tmp, 6);
+ p += 6;
+ *cursor = *cursor + 6;
+ }
+ else
+ {
+ *p++ = c;
+ *cursor = *cursor + 1;
+ }
+ }
+
+ return 0;
+}
+
+static uint32_t
+_asl_append_xml_tag_length(int tag, const char *s)
+{
+ uint32_t len, slen;
+
+ len = 0;
+
+ if (tag == XML_TAG_KEY)
+ {
+ len += 14; /* "\t\t<key>" + "</key>\n" */
+ len += _asl_append_xml_string_length(s);
+ }
+ else if (tag == XML_TAG_STRING)
+ {
+ len += 20; /* "\t\t<string>" + "</string>\n" */
+ len += _asl_append_xml_string_length(s);
+ }
+ else if (tag == XML_TAG_DATA)
+ {
+ len += 16; /* "\t\t<data>" + "</data>\n" */
+ slen = strlen(s);
+ len += ((len + 2) / 3) * 4;
+ }
+
+ return len;
+}
+
+/* called from asl_format_message */
+static void
+_asl_append_xml_tag(char *buf, uint32_t bufsize, uint32_t *cursor, int tag, const char *s)
+{
+ char *b64;
+
+ if (buf == NULL) return;
+ if (cursor == NULL) return;
+
+ if (tag == XML_TAG_KEY)
+ {
+ _asl_append_string(buf, bufsize, cursor, "\t\t<key>", ASL_ENCODE_NONE, 0);
+ _asl_append_xml_string(buf, bufsize, cursor, s);
+ _asl_append_string(buf, bufsize, cursor, "</key>\n", ASL_ENCODE_NONE, 0);
+ return;
+ }
+ else if (tag == XML_TAG_STRING)
+ {
+ _asl_append_string(buf, bufsize, cursor, "\t\t<string>", ASL_ENCODE_NONE, 0);
+ _asl_append_xml_string(buf, bufsize, cursor, s);
+ _asl_append_string(buf, bufsize, cursor, "</string>\n", ASL_ENCODE_NONE, 0);
+ return;
+ }
+ else if (tag == XML_TAG_DATA)
+ {
+ _asl_append_string(buf, bufsize, cursor, "\t\t<data>", ASL_ENCODE_NONE, 0);
+ b64 = (char *)asl_b64_encode((uint8_t *)s, strlen(s));
+ if (b64 != NULL)
+ {
+ _asl_append_string(buf, bufsize, cursor, b64, ASL_ENCODE_NONE, 0);
+ free(b64);
+ }
+
+ _asl_append_string(buf, bufsize, cursor, "</data>\n", ASL_ENCODE_NONE, 0);
+ return;
+ }
+}
+
+static uint32_t
+_asl_append_op_length(uint32_t op)
+{
+ uint32_t i;
+
+ if (op == ASL_QUERY_OP_NULL) return 1;
+
+ i = 0;
+
+ if (op & ASL_QUERY_OP_CASEFOLD) i++;
+ if (op & ASL_QUERY_OP_REGEX) i++;
+ if (op & ASL_QUERY_OP_NUMERIC) i++;
+ if (op & ASL_QUERY_OP_PREFIX) i++;
+ if (op & ASL_QUERY_OP_SUFFIX) i++;
+
+ switch (op & ASL_QUERY_OP_TRUE)
+ {
+ case ASL_QUERY_OP_EQUAL:
+ case ASL_QUERY_OP_GREATER:
+ case ASL_QUERY_OP_LESS:
+ case ASL_QUERY_OP_NOT_EQUAL:
+ case ASL_QUERY_OP_TRUE:
+ i++;
+ break;
+ case ASL_QUERY_OP_LESS_EQUAL:
+ case ASL_QUERY_OP_GREATER_EQUAL:
+ i += 2;
+ break;
+ default:
+ break;
+ }
+
+ if (i == 0) return 1;
+ return i;
+}
+
+
+static void
+_asl_append_op(char *buf, uint32_t bufsize, uint32_t *cursor, uint32_t op)
+{
+ char opstr[8];
+ uint32_t i;
+
+ if (buf == NULL) return;
+ if (cursor == NULL) return;
+
+ if (op == ASL_QUERY_OP_NULL)
+ {
+ _asl_append_string(buf, bufsize, cursor, ".", ASL_ENCODE_NONE, 0);
+ return;
+ }
+
+ i = 0;
+ if (op & ASL_QUERY_OP_CASEFOLD) opstr[i++] = 'C';
+
+ if (op & ASL_QUERY_OP_REGEX) opstr[i++] = 'R';
+
+ if (op & ASL_QUERY_OP_NUMERIC) opstr[i++] = 'N';
+
+ if (op & ASL_QUERY_OP_PREFIX)
+ {
+ if (op & ASL_QUERY_OP_SUFFIX) opstr[i++] = 'S';
+ else opstr[i++] = 'A';
+ }
+ if (op & ASL_QUERY_OP_SUFFIX) opstr[i++] = 'Z';
+
+ switch (op & ASL_QUERY_OP_TRUE)
+ {
+ case ASL_QUERY_OP_EQUAL:
+ opstr[i++] = '=';
+ break;
+ case ASL_QUERY_OP_GREATER:
+ opstr[i++] = '>';
+ break;
+ case ASL_QUERY_OP_GREATER_EQUAL:
+ opstr[i++] = '>';
+ opstr[i++] = '=';
+ break;
+ case ASL_QUERY_OP_LESS:
+ opstr[i++] = '<';
+ break;
+ case ASL_QUERY_OP_LESS_EQUAL:
+ opstr[i++] = '<';
+ opstr[i++] = '=';
+ break;
+ case ASL_QUERY_OP_NOT_EQUAL:
+ opstr[i++] = '!';
+ break;
+ case ASL_QUERY_OP_TRUE:
+ opstr[i++] = 'T';
+ break;
+ default:
+ break;
+ }
+
+ if (i == 0)
+ {
+ _asl_append_string(buf, bufsize, cursor, ".", ASL_ENCODE_NONE, 0);
+ return;
+ }
+
+ opstr[i] = '\0';
+ _asl_append_string(buf, bufsize, cursor, opstr, ASL_ENCODE_NONE, 0);
+}
+
+static char *
+_asl_time_string(int fmt, const char *str)
+{
+ time_t tick;
+ struct tm *stm;
+ char *ltime;
+ char *out;
+ char ltbuf[32];
+ out = NULL;
+
+ tick = 0;
+ if (str != NULL) tick = asl_parse_time(str);
+
+ if (fmt == TFMT_SEC)
+ {
+ asprintf(&out, "%lu", tick);
+ return out;
+ }
+
+ if (fmt == TFMT_UTC)
+ {
+ stm = gmtime(&tick);
+ asprintf(&out, "%d.%02d.%02d %02d:%02d:%02d UTC", stm->tm_year + 1900, stm->tm_mon + 1, stm->tm_mday, stm->tm_hour, stm->tm_min, stm->tm_sec);
+ return out;
+ }
+
+ if (fmt == TFMT_LCL)
+ {
+ ltime = ctime_r(&tick, ltbuf);
+ if (ltime == NULL) return NULL;
+ ltime[19] = '\0';
+ asprintf(&out, "%s", ltime + 4);
+ return out;
+ }
+
+ return NULL;
+}
+
+/* called from asl_format_message */
+static char *
+_asl_msg_to_string_time_fmt(asl_msg_t *msg, uint32_t *len, int tf)
+{
+ uint32_t i, x, count, bufsize, cursor;
+ char *buf, *timestr;
+ const char *key, *val;
+
+ *len = 0;
+
+ if (msg == NULL) return NULL;
+
+ timestr = NULL;
+ buf = NULL;
+
+ count = asl_msg_count(msg);
+
+ if (count == 0) return NULL;
+
+ key = NULL;
+ val = NULL;
+
+ /* first pass: determine output string length */
+ bufsize = 0;
+ i = 0;
+
+ for (x = asl_msg_fetch(msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch(msg, x, &key, &val, NULL))
+ {
+ if (key == NULL) continue;
+
+ if (i > 0) bufsize += 1; /* " " */
+
+ /* "[" */
+ bufsize += 1;
+
+ bufsize += _asl_append_string_length(key, ASL_ENCODE_ASL, 1);
+
+ if ((tf != TFMT_SEC) && (!strcmp(key, ASL_KEY_TIME)))
+ {
+ timestr = _asl_time_string(tf, val);
+ if (timestr != NULL)
+ {
+ /* " " */
+ bufsize += 1;
+ bufsize += _asl_append_string_length(timestr, ASL_ENCODE_ASL, 0);
+ }
+ }
+ else if (val != NULL)
+ {
+ /* " " */
+ bufsize += 1;
+ bufsize += _asl_append_string_length(val, ASL_ENCODE_ASL, 0);
+ }
+
+ /* "]" */
+ bufsize += 1;
+
+ i++;
+ }
+
+ /* "\n\0" */
+ bufsize += 2;
+
+ /* allocate the output string */
+ buf = malloc(bufsize);
+ if (buf == NULL) return NULL;
+
+ cursor = 0;
+ i = 0;
+
+ /* second pass: construct the output string */
+
+ for (x = asl_msg_fetch(msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch(msg, x, &key, &val, NULL))
+ {
+ if (key == NULL) continue;
+
+ if (i > 0)
+ {
+ assert(cursor < bufsize);
+ buf[cursor++] = ' ';
+ }
+
+ assert(cursor < bufsize);
+ buf[cursor++] = '[';
+
+ _asl_append_string(buf, bufsize, &cursor, key, ASL_ENCODE_ASL, 1);
+
+ if ((tf != TFMT_SEC) && (!strcmp(key, ASL_KEY_TIME)))
+ {
+ if (timestr != NULL)
+ {
+ assert(cursor < bufsize);
+ buf[cursor++] = ' ';
+ _asl_append_string(buf, bufsize, &cursor, timestr, ASL_ENCODE_ASL, 0);
+ free(timestr);
+ }
+ }
+ else if (val != NULL)
+ {
+ assert(cursor < bufsize);
+ buf[cursor++] = ' ';
+ _asl_append_string(buf, bufsize, &cursor, val, ASL_ENCODE_ASL, 0);
+ }
+
+ assert(cursor < bufsize);
+ buf[cursor++] = ']';
+
+ i++;
+ }
+
+ assert((cursor + 1) < bufsize);
+ buf[cursor++] = '\n';
+ buf[cursor] = '\0';
+
+ *len = bufsize;
+ return buf;
+}
+
+static uint32_t
+_msg_length_helper(uint32_t *i, uint32_t type, const char *key, const char *val, uint32_t op)
+{
+ uint32_t outlen;
+
+ outlen = 0;
+
+ if (*i > 0) outlen = 1; /* " " */
+ *i = *i + 1;
+
+ /* "[" */
+ outlen += 1;
+
+ if (type == ASL_TYPE_QUERY)
+ {
+ outlen += _asl_append_op_length(op);
+
+ /* " " */
+ outlen += 1;
+ }
+
+ outlen += _asl_append_string_length(key, ASL_ENCODE_ASL, 1);
+
+ if (val != NULL)
+ {
+ /* " " */
+ outlen += 1;
+ outlen += _asl_append_string_length(val, ASL_ENCODE_ASL, 0);
+ }
+
+ /* "]" */
+ outlen += 1;
+
+ return outlen;
+}
+
+__private_extern__ uint32_t
+_asl_msg_string_length_aux(asl_msg_t *msg, asl_msg_aux_t *aux)
+{
+ uint32_t i, x, slot, op, outlen, auxbits, type;
+ char *s;
+ const char *key, *val;
+ asl_msg_t *page;
+
+ s = NULL;
+ type = ASL_TYPE_MSG;
+
+ outlen = 0;
+ if ((msg != NULL) && (msg->type == ASL_TYPE_QUERY))
+ {
+ type = ASL_TYPE_QUERY;
+ outlen = 2; /* "Q " */
+ if (asl_msg_count(msg) == 0) return outlen + 1;
+ }
+
+ auxbits = 0;
+
+ key = NULL;
+ val = NULL;
+ op = 0;
+ i = 0;
+
+ /* process aux keys */
+ if ((aux != NULL) && (aux->type == ASL_MSG_TYPE_AUX_0))
+ {
+ if (aux->data.aux0->level != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_LEVEL, aux->data.aux0->level, op);
+ auxbits |= AUX_0_LEVEL;
+ }
+
+ if (aux->data.aux0->time != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_TIME, aux->data.aux0->time, op);
+ auxbits |= AUX_0_TIME;
+ }
+
+ if (aux->data.aux0->nano != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_TIME_NSEC, aux->data.aux0->nano, op);
+ auxbits |= AUX_0_TIME_NSEC;
+ }
+
+ if (aux->data.aux0->host != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_HOST, aux->data.aux0->host, op);
+ auxbits |= AUX_0_HOST;
+ }
+
+ if (aux->data.aux0->sender != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_SENDER, aux->data.aux0->sender, op);
+ auxbits |= AUX_0_SENDER;
+ }
+
+ if (aux->data.aux0->facility != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_FACILITY, aux->data.aux0->facility, op);
+ auxbits |= AUX_0_FACILITY;
+ }
+
+ if (aux->data.aux0->pid != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_PID, aux->data.aux0->pid, op);
+ auxbits |= AUX_0_PID;
+ }
+
+ if (aux->data.aux0->uid != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_UID, aux->data.aux0->uid, op);
+ auxbits |= AUX_0_UID;
+ }
+
+ if (aux->data.aux0->gid != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_GID, aux->data.aux0->gid, op);
+ auxbits |= AUX_0_GID;
+ }
+
+ if (aux->data.aux0->message != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_MSG, aux->data.aux0->message, op);
+ auxbits |= AUX_0_MSG;
+ }
+
+ if (aux->data.aux0->option != NULL)
+ {
+ outlen += _msg_length_helper(&i, type, ASL_KEY_OPTION, aux->data.aux0->option, op);
+ auxbits |= AUX_0_OPTION;
+ }
+ }
+
+ page = NULL;
+ slot = IndexNull;
+
+ for (x = _asl_msg_fetch_internal(msg, 0, &key, &val, &op, &page, &slot); x != IndexNull; x = _asl_msg_fetch_internal(msg, x, &key, &val, &op, &page, &slot))
+ {
+ if ((key == NULL) || (page == NULL) || (slot == IndexNull)) continue;
+
+ /* ignore in msg if an override value was supplied in aux */
+ if ((page->key[slot] == ASL_STD_KEY_LEVEL) && (auxbits & AUX_0_LEVEL)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_TIME) && (auxbits & AUX_0_TIME)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_NANO) && (auxbits & AUX_0_TIME_NSEC)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_HOST) && (auxbits & AUX_0_HOST)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_SENDER) && (auxbits & AUX_0_SENDER)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_FACILITY) && (auxbits & AUX_0_FACILITY)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_PID) && (auxbits & AUX_0_PID)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_UID) && (auxbits & AUX_0_UID)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_GID) && (auxbits & AUX_0_GID)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_MESSAGE) && (auxbits & AUX_0_MSG)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_OPTION) && (auxbits & AUX_0_OPTION)) continue;
+
+ outlen += _msg_length_helper(&i, type, key, val, op);
+ }
+
+ if (outlen > 0) outlen++; /* trailing NUL */
+
+ return outlen;
+}
+
+uint32_t
+asl_msg_string_length(asl_msg_t *msg)
+{
+ return _asl_msg_string_length_aux(msg, NULL);
+}
+
+static void
+_msg_to_string_buffer_helper(uint32_t *i, uint32_t type, char *buf, uint32_t bufsize, uint32_t *cursor, const char *key, const char *val, uint32_t op)
+{
+ if (*i > 0)
+ {
+ assert(*cursor < bufsize);
+ buf[*cursor] = ' ';
+ *cursor = *cursor + 1;
+ }
+
+ *i = *i + 1;
+
+ assert(*cursor < bufsize);
+ buf[*cursor] = '[';
+ *cursor = *cursor + 1;
+
+ if (type == ASL_TYPE_QUERY)
+ {
+ _asl_append_op(buf, bufsize, cursor, op);
+
+ assert(*cursor < bufsize);
+ buf[*cursor] = ' ';
+ *cursor = *cursor + 1;
+ }
+
+ _asl_append_string(buf, bufsize, cursor, key, ASL_ENCODE_ASL, 1);
+
+ if (val != NULL)
+ {
+ assert(*cursor < bufsize);
+ buf[*cursor] = ' ';
+ *cursor = *cursor + 1;
+
+ _asl_append_string(buf, bufsize, cursor, val, ASL_ENCODE_ASL, 0);
+ }
+
+ assert(*cursor < bufsize);
+ buf[*cursor] = ']';
+ *cursor = *cursor + 1;
+}
+
+__private_extern__ uint32_t
+_asl_msg_to_string_buffer_aux(asl_msg_t *msg, asl_msg_aux_t *aux, char *buf, uint32_t bufsize)
+{
+ uint32_t i, x, slot, op, cursor, auxbits, type;
+ char *s;
+ const char *key, *val;
+ asl_msg_t *page;
+
+ cursor = 0;
+
+ if (buf == NULL) return -1;
+
+ s = NULL;
+ type = ASL_TYPE_MSG;
+
+ if ((msg != NULL) && (msg->type == ASL_TYPE_QUERY))
+ {
+ type = ASL_TYPE_QUERY;
+ assert((cursor + 1) < bufsize);
+ buf[cursor++] = 'Q';
+ buf[cursor++] = ' ';
+ if (asl_msg_count(msg) == 0)
+ {
+ assert(cursor < bufsize);
+ buf[cursor] = '\0';
+ return 0;
+ }
+ }
+
+ auxbits = 0;
+
+ key = NULL;
+ val = NULL;
+ op = 0;
+ i = 0;
+
+ /* process aux keys */
+ if ((aux != NULL) && (aux->type == ASL_MSG_TYPE_AUX_0))
+ {
+ if (aux->data.aux0->level != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_LEVEL, aux->data.aux0->level, op);
+ auxbits |= AUX_0_LEVEL;
+ }
+
+ if (aux->data.aux0->time != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_TIME, aux->data.aux0->time, op);
+ auxbits |= AUX_0_TIME;
+ }
+
+ if (aux->data.aux0->nano != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_TIME_NSEC, aux->data.aux0->nano, op);
+ auxbits |= AUX_0_TIME_NSEC;
+ }
+
+ if (aux->data.aux0->host != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_HOST, aux->data.aux0->host, op);
+ auxbits |= AUX_0_HOST;
+ }
+
+ if (aux->data.aux0->sender != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_SENDER, aux->data.aux0->sender, op);
+ auxbits |= AUX_0_SENDER;
+ }
+
+ if (aux->data.aux0->facility != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_FACILITY, aux->data.aux0->facility, op);
+ auxbits |= AUX_0_FACILITY;
+ }
+
+ if (aux->data.aux0->pid != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_PID, aux->data.aux0->pid, op);
+ auxbits |= AUX_0_PID;
+ }
+
+ if (aux->data.aux0->uid != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_UID, aux->data.aux0->uid, op);
+ auxbits |= AUX_0_UID;
+ }
+
+ if (aux->data.aux0->gid != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_GID, aux->data.aux0->gid, op);
+ auxbits |= AUX_0_GID;
+ }
+
+ if (aux->data.aux0->message != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_MSG, aux->data.aux0->message, op);
+ auxbits |= AUX_0_MSG;
+ }
+
+ if (aux->data.aux0->option != NULL)
+ {
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, ASL_KEY_OPTION, aux->data.aux0->option, op);
+ auxbits |= AUX_0_OPTION;
+ }
+ }
+
+ page = NULL;
+ slot = IndexNull;
+
+ for (x = _asl_msg_fetch_internal(msg, 0, &key, &val, &op, &page, &slot); x != IndexNull; x = _asl_msg_fetch_internal(msg, x, &key, &val, &op, &page, &slot))
+ {
+ if ((key == NULL) || (page == NULL) || (slot == IndexNull)) continue;
+
+ /* ignore in msg if an override value was supplied in aux */
+ if ((page->key[slot] == ASL_STD_KEY_LEVEL) && (auxbits & AUX_0_LEVEL)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_TIME) && (auxbits & AUX_0_TIME)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_NANO) && (auxbits & AUX_0_TIME_NSEC)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_HOST) && (auxbits & AUX_0_HOST)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_SENDER) && (auxbits & AUX_0_SENDER)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_FACILITY) && (auxbits & AUX_0_FACILITY)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_PID) && (auxbits & AUX_0_PID)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_UID) && (auxbits & AUX_0_UID)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_GID) && (auxbits & AUX_0_GID)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_MESSAGE) && (auxbits & AUX_0_MSG)) continue;
+ if ((page->key[slot] == ASL_STD_KEY_OPTION) && (auxbits & AUX_0_OPTION)) continue;
+
+ _msg_to_string_buffer_helper(&i, type, buf, bufsize, &cursor, key, val, op);
+ }
+
+ assert(cursor < bufsize);
+ buf[cursor] = '\0';
+
+ return 0;
+}
+
+uint32_t
+asl_msg_to_string_buffer(asl_msg_t *msg, char *buf, uint32_t bufsize)
+{
+ return _asl_msg_to_string_buffer_aux(msg, NULL, buf, bufsize);
+}
+
+char *
+asl_msg_to_string(asl_msg_t *in, uint32_t *len)
+{
+ uint32_t status, outlen;
+ char *out;
+
+ *len = 0;
+
+ if (in == NULL) return NULL;
+
+ out = NULL;
+ outlen = _asl_msg_string_length_aux(in, NULL);
+ if (outlen == 0) return NULL;
+
+ out = malloc(outlen);
+ if (out == NULL) return NULL;
+
+ status = _asl_msg_to_string_buffer_aux(in, NULL, out, outlen);
+ if (status != 0)
+ {
+ free(out);
+ return NULL;
+ }
+
+ *len = outlen;
+ return out;
+}
+
+static uint32_t
+_asl_msg_op_from_string(char *o)
+{
+ uint32_t op, i;
+
+ op = ASL_QUERY_OP_NULL;
+
+ if (o == NULL) return op;
+
+ for (i = 0; o[i] != '\0'; i++)
+ {
+ if (o[i] == '.') return ASL_QUERY_OP_NULL;
+ if (o[i] == 'C') op |= ASL_QUERY_OP_CASEFOLD;
+ if (o[i] == 'R') op |= ASL_QUERY_OP_REGEX;
+ if (o[i] == 'N') op |= ASL_QUERY_OP_NUMERIC;
+ if (o[i] == 'S') op |= ASL_QUERY_OP_SUBSTRING;
+ if (o[i] == 'A') op |= ASL_QUERY_OP_PREFIX;
+ if (o[i] == 'Z') op |= ASL_QUERY_OP_SUFFIX;
+ if (o[i] == '<') op |= ASL_QUERY_OP_LESS;
+ if (o[i] == '>') op |= ASL_QUERY_OP_GREATER;
+ if (o[i] == '=') op |= ASL_QUERY_OP_EQUAL;
+ if (o[i] == '!') op |= ASL_QUERY_OP_NOT_EQUAL;
+ if (o[i] == 'T') op |= ASL_QUERY_OP_TRUE;
+ }
+
+ return op;
+}
+
+static char *
+_asl_msg_get_next_word(char **p, uint32_t *tt, uint32_t spacedel)
+{
+ char *str, *out, c, oval;
+ uint32_t i, len, n, outlen;
+
+ *tt = TOKEN_NULL;
+
+ if (p == NULL) return NULL;
+ if (*p == NULL) return NULL;
+ if (**p == '\0') return NULL;
+
+ /* skip one space if it's there (word separator) */
+ if (**p == ' ') (*p)++;
+
+ /* skip leading white space */
+ if (spacedel != 0)
+ {
+ while ((**p == ' ') || (**p == '\t')) (*p)++;
+ }
+
+ if (**p == '\0') return NULL;
+ if (**p == '\n') return NULL;
+
+ str = *p;
+
+ /* opening [ */
+ if (**p == '[')
+ {
+ *tt = TOKEN_OPEN;
+
+ (*p)++;
+ out = malloc(2);
+ if (out == NULL) return NULL;
+
+ out[0] = '[';
+ out[1] = '\0';
+ return out;
+ }
+
+ /* scan for token and calulate it's length (input and decoded output len) */
+ len = 0;
+ outlen = 0;
+
+ forever
+ {
+ c = str[len];
+
+ /* stop scanning when we hit a delimiter */
+ if (((spacedel != 0) && (c == ' ')) || (c == ']') || (c == '\0')) break;
+
+ if (c == '\\')
+ {
+ len++;
+ c = str[len];
+ if ((c == 'a') || (c == 'b') || (c == 't') || (c == 'n') || (c == 'v') || (c == 'f') || (c == 'r') || (c == 's') || (c == '[') || (c == '\\') || (c == ']'))
+ {
+ }
+ else if (c == '^')
+ {
+ if (str[++len] == '\0') return NULL;
+ }
+ else if (c == 'M')
+ {
+ if (str[++len] == '\0') return NULL;
+ if (str[++len] == '\0') return NULL;
+ }
+ else if ((c >= '0') && (c <= '3'))
+ {
+ if (str[++len] == '\0') return NULL;
+ if (str[++len] == '\0') return NULL;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ len++;
+ outlen++;
+ }
+
+ (*p) += len;
+
+ if ((len == 0) && (**p == ']'))
+ {
+ *tt = TOKEN_CLOSE;
+ (*p)++;
+ out = malloc(2);
+ if (out == NULL) return NULL;
+
+ out[0] = ']';
+ out[1] = '\0';
+ return out;
+ }
+
+ *tt = TOKEN_INT;
+
+ out = malloc(outlen + 1);
+ if (out == NULL) return NULL;
+
+ n = 0;
+ for (i = 0; i < len; i++)
+ {
+ c = str[i];
+
+ if (c == '\\')
+ {
+ *tt = TOKEN_WORD;
+
+ i++;
+ c = str[i];
+ if (c == 'a')
+ {
+ out[n++] = '\a';
+ }
+ else if (c == 'b')
+ {
+ out[n++] = '\b';
+ }
+ else if (c == 't')
+ {
+ out[n++] = '\t';
+ }
+ else if (c == 'n')
+ {
+ out[n++] = '\n';
+ }
+ else if (c == 'v')
+ {
+ out[n++] = '\v';
+ }
+ else if (c == 'f')
+ {
+ out[n++] = '\f';
+ }
+ else if (c == 'r')
+ {
+ out[n++] = '\r';
+ }
+ else if (c == 's')
+ {
+ out[n++] = ' ';
+ }
+ else if (c == '[')
+ {
+ out[n++] = '[';
+ }
+ else if (c == '\\')
+ {
+ out[n++] = '\\';
+ }
+ else if (c == ']')
+ {
+ out[n++] = ']';
+ }
+ else if (c == '^')
+ {
+ i++;
+ if (str[i] == '?') out[n++] = 127;
+ else out[n++] = str[i] - 64;
+ }
+ else if (c == 'M')
+ {
+ i++;
+ c = str[i];
+ if (c == '^')
+ {
+ i++;
+ if (str[i] == '?') out[n++] = 255;
+ else out[n++] = str[i] + 64;
+ }
+ else if (c == '-')
+ {
+ i++;
+ out[n++] = str[i] + 128;
+ }
+ else
+ {
+ *tt = TOKEN_NULL;
+ free(out);
+ return NULL;
+ }
+
+ }
+ else if ((c >= '0') && (c <= '3'))
+ {
+ oval = (c - '0') * 64;
+
+ i++;
+ c = str[i];
+ if ((c < '0') || (c > '7'))
+ {
+ *tt = TOKEN_NULL;
+ free(out);
+ return NULL;
+ }
+
+ oval += ((c - '0') * 8);
+
+ i++;
+ c = str[i];
+ if ((c < '0') || (c > '7'))
+ {
+ *tt = TOKEN_NULL;
+ free(out);
+ return NULL;
+ }
+
+ oval += (c - '0');
+
+ out[n++] = oval;
+ }
+ else
+ {
+ *tt = TOKEN_NULL;
+ free(out);
+ return NULL;
+ }
+ }
+ else
+ {
+
+ if ((c < '0') || (c > '9')) *tt = TOKEN_WORD;
+ out[n++] = c;
+ }
+ }
+
+ out[n] = '\0';
+
+ return out;
+}
+
+asl_msg_t *
+asl_msg_from_string(const char *buf)
+{
+ uint32_t tt, type, op;
+ char *k, *v, *o, *p;
+ asl_msg_t *out;
+
+ if (buf == NULL) return NULL;
+
+ type = ASL_TYPE_MSG;
+ p = (char *)buf;
+
+ k = _asl_msg_get_next_word(&p, &tt, 1);
+ if (k == NULL) return NULL;
+
+ if (streq(k, "Q"))
+ {
+ type = ASL_TYPE_QUERY;
+ free(k);
+
+ k = _asl_msg_get_next_word(&p, &tt, 1);
+ }
+ else if (tt == TOKEN_INT)
+ {
+ /* Leading integer is a string length - skip it */
+ free(k);
+ k = _asl_msg_get_next_word(&p, &tt, 1);
+ if (k == NULL) return NULL;
+ }
+
+ out = asl_msg_new(ASL_TYPE_MSG);
+ if (out == NULL) return NULL;
+
+ out->type = type;
+
+ /* OPEN WORD [WORD [WORD]] CLOSE */
+ while (k != NULL)
+ {
+ op = ASL_QUERY_OP_NULL;
+
+ if (tt != TOKEN_OPEN)
+ {
+ asl_msg_release(out);
+ return NULL;
+ }
+
+ free(k);
+
+ /* get op for query type */
+ if (type == ASL_TYPE_QUERY)
+ {
+ o = _asl_msg_get_next_word(&p, &tt, 1);
+ if ((o == NULL) || (tt != TOKEN_WORD))
+ {
+ if (o != NULL) free(o);
+ asl_msg_release(out);
+ return NULL;
+ }
+
+ op = _asl_msg_op_from_string(o);
+ free(o);
+ }
+
+ k = _asl_msg_get_next_word(&p, &tt, 1);
+ if (tt == TOKEN_INT) tt = TOKEN_WORD;
+ if ((k == NULL) || (tt != TOKEN_WORD))
+ {
+ if (k != NULL) free(k);
+ asl_msg_release(out);
+ return NULL;
+ }
+
+ v = _asl_msg_get_next_word(&p, &tt, 0);
+ if (tt == TOKEN_INT) tt = TOKEN_WORD;
+ if (v == NULL)
+ {
+ asl_msg_set_key_val_op(out, k, NULL, op);
+ free(k);
+ break;
+ }
+
+ if (tt == TOKEN_CLOSE)
+ {
+ asl_msg_set_key_val_op(out, k, NULL, op);
+ }
+ else if (tt == TOKEN_WORD)
+ {
+ asl_msg_set_key_val_op(out, k, v, op);
+ }
+ else
+ {
+ if (k != NULL) free(k);
+ if (v != NULL) free(v);
+ asl_msg_release(out);
+ return NULL;
+ }
+
+ if (k != NULL) free(k);
+ if (v != NULL) free(v);
+
+ if (tt != TOKEN_CLOSE)
+ {
+ k = _asl_msg_get_next_word(&p, &tt, 1);
+ if (k == NULL) break;
+
+ if (tt != TOKEN_CLOSE)
+ {
+ asl_msg_release(out);
+ return NULL;
+ }
+
+ free(k);
+ }
+
+ k = _asl_msg_get_next_word(&p, &tt, 1);
+ if (k == NULL) break;
+ }
+
+ return out;
+}
+
+char *
+asl_list_to_string(asl_search_result_t *list, uint32_t *outlen)
+{
+ uint32_t i, len, newlen;
+ char *msgbuf, *out;
+
+ if (list == NULL) return NULL;
+ if (list->count == 0) return NULL;
+ if (list->msg == NULL) return NULL;
+
+ out = NULL;
+ asprintf(&out, "%u\n", list->count);
+ if (out == NULL) return NULL;
+ *outlen = strlen(out) + 1;
+
+ for (i = 0; i < list->count; i++)
+ {
+ len = 0;
+ msgbuf = asl_msg_to_string(list->msg[i], &len);
+ if (msgbuf == NULL)
+ {
+ free(out);
+ *outlen = 0;
+ return NULL;
+ }
+
+ newlen = *outlen + len;
+ out = reallocf(out, newlen);
+ if (out == NULL)
+ {
+ *outlen = 0;
+ return NULL;
+ }
+
+ memmove((out + *outlen - 1), msgbuf, len);
+ out[newlen - 2] = '\n';
+ out[newlen - 1] = '\0';
+ *outlen = newlen;
+
+ free(msgbuf);
+ }
+
+ return out;
+}
+
+asl_search_result_t *
+asl_list_from_string(const char *buf)
+{
+ uint32_t i, n;
+ const char *p;
+ asl_search_result_t *out;
+ asl_msg_t *m;
+
+ if (buf == NULL) return NULL;
+ p = buf;
+
+ n = atoi(buf);
+ if (n == 0) return NULL;
+
+ out = (asl_search_result_t *)calloc(1, sizeof(asl_search_result_t));
+ if (out == NULL) return NULL;
+
+ out->msg = (asl_msg_t **)calloc(n, sizeof(asl_msg_t *));
+ if (out->msg == NULL)
+ {
+ free(out);
+ return NULL;
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ p = strchr(p, '\n');
+ if (p == NULL)
+ {
+ aslresponse_free((aslresponse)out);
+ return NULL;
+ }
+
+ p++;
+
+ m = asl_msg_from_string(p);
+ if (m == NULL)
+ {
+ aslresponse_free((aslresponse)out);
+ return NULL;
+ }
+
+ out->msg[i] = (asl_msg_t *)m;
+ out->count += 1;
+ }
+
+ return out;
+}
+
+static const char *
+_asl_level_string(int level)
+{
+ if (level == ASL_LEVEL_EMERG) return ASL_STRING_EMERG;
+ if (level == ASL_LEVEL_ALERT) return ASL_STRING_ALERT;
+ if (level == ASL_LEVEL_CRIT) return ASL_STRING_CRIT;
+ if (level == ASL_LEVEL_ERR) return ASL_STRING_ERR;
+ if (level == ASL_LEVEL_WARNING) return ASL_STRING_WARNING;
+ if (level == ASL_LEVEL_NOTICE) return ASL_STRING_NOTICE;
+ if (level == ASL_LEVEL_INFO) return ASL_STRING_INFO;
+ if (level == ASL_LEVEL_DEBUG) return ASL_STRING_DEBUG;
+ return "Unknown";
+}
+
+/*
+ * format a message for printing
+ * out parameter len returns string length including trailing NUL
+ */
+char *
+asl_format_message(asl_msg_t *msg, const char *mfmt, const char *tfmt, uint32_t text_encoding, uint32_t *len)
+{
+ char *buf, *tstr, *k, c[2], skey[512];
+ const char *hstr, *sstr, *pstr, *mstr, *lstr, *rprc, *rpid, *v, *key, *val;
+ int i, j, l, mf, tf, paren, oval, level;
+ uint32_t x, cursor, bufsize;
+
+ buf = NULL;
+ *len = 0;
+
+ if (msg == NULL) return NULL;
+
+ mf = MFMT_RAW;
+ tf = TFMT_SEC;
+
+ if (mfmt == NULL) mf = MFMT_RAW;
+ else if (!strcmp(mfmt, ASL_MSG_FMT_RAW)) mf = MFMT_RAW;
+ else if (!strcmp(mfmt, ASL_MSG_FMT_STD)) mf = MFMT_STD;
+ else if (!strcmp(mfmt, ASL_MSG_FMT_BSD)) mf = MFMT_BSD;
+ else if (!strcmp(mfmt, ASL_MSG_FMT_XML)) mf = MFMT_XML;
+ else if (!strcmp(mfmt, ASL_MSG_FMT_MSG)) mf = MFMT_MSG;
+ else mf = MFMT_STR;
+
+ if (tfmt == NULL) tf = TFMT_SEC;
+ else if (!strcmp(tfmt, ASL_TIME_FMT_SEC)) tf = TFMT_SEC;
+ else if (!strcmp(tfmt, ASL_TIME_FMT_UTC)) tf = TFMT_UTC;
+ else if (!strcmp(tfmt, ASL_TIME_FMT_LCL)) tf = TFMT_LCL;
+
+ if (mf == MFMT_RAW)
+ {
+ return _asl_msg_to_string_time_fmt(msg, len, tf);
+ }
+
+ if (mf == MFMT_MSG)
+ {
+ mstr = NULL;
+ if (asl_msg_lookup(msg, ASL_KEY_MSG, &mstr, NULL) != 0) return NULL;
+
+ bufsize = _asl_append_string_length(mstr, text_encoding, 0);
+ bufsize += 2; /* \n\0 */
+
+ buf = malloc(bufsize);
+ if (buf == NULL) return NULL;
+
+ cursor = 0;
+ _asl_append_string(buf, bufsize, &cursor, mstr, text_encoding, 0);
+
+ buf[cursor++] = '\n';
+ buf[cursor] = '\0';
+
+ *len = bufsize;
+ return buf;
+ }
+
+ if ((mf == MFMT_STD) || (mf == MFMT_BSD))
+ {
+ /* BSD: Mth dd hh:mm:ss host sender[pid]: message */
+ /* BSD: Mth dd hh:mm:ss host sender[pid] (refproc[refpid]): message */
+ /* STD: Mth dd hh:mm:ss host sender[pid] <Level>: message */
+ /* STD: Mth dd hh:mm:ss host sender[pid] (refproc[refpid]) <Level>: message */
+
+ v = NULL;
+ hstr = NULL;
+ sstr = NULL;
+ pstr = NULL;
+ mstr = NULL;
+ lstr = NULL;
+ rprc = NULL;
+ rpid = NULL;
+
+ asl_msg_lookup(msg, ASL_KEY_TIME, &v, NULL);
+ tstr = _asl_time_string(tf, v);
+
+ asl_msg_lookup(msg, ASL_KEY_HOST, &hstr, NULL);
+ asl_msg_lookup(msg, ASL_KEY_SENDER, &sstr, NULL);
+ asl_msg_lookup(msg, ASL_KEY_PID, &pstr, NULL);
+ asl_msg_lookup(msg, ASL_KEY_MSG, &mstr, NULL);
+
+ asl_msg_lookup(msg, ASL_KEY_REF_PROC, &rprc, NULL);
+ asl_msg_lookup(msg, ASL_KEY_REF_PID, &rpid, NULL);
+
+ level = 7;
+
+ if (mf == MFMT_STD)
+ {
+ asl_msg_lookup(msg, ASL_KEY_LEVEL, &lstr, NULL);
+ if (lstr != NULL) level = atoi(lstr);
+
+ lstr = _asl_level_string(level);
+ }
+
+ if (hstr == NULL) hstr = "unknown";
+ if (sstr == NULL) sstr = "unknown";
+
+ /* first pass: calculate output line length */
+ bufsize = 0;
+
+ if (tstr == NULL) bufsize++;
+ else bufsize += _asl_append_string_length(tstr, ASL_ENCODE_NONE, 0);
+
+ /* " " */
+ bufsize++;
+
+ bufsize += _asl_append_string_length(hstr, text_encoding, 0);
+
+ /* " " */
+ bufsize++;
+
+ bufsize += _asl_append_string_length(sstr, text_encoding, 0);
+
+ if ((pstr != NULL) && (strcmp(pstr, "-1")))
+ {
+ /* "[" + "]" */
+ bufsize += 2;
+ bufsize += _asl_append_string_length(pstr, ASL_ENCODE_NONE, 0);
+ }
+
+ if ((rprc != NULL) || (rpid != NULL)) bufsize += 3; /* " (" + ")" */
+
+ if (rprc != NULL) bufsize += _asl_append_string_length(rprc, text_encoding, 0);
+ if (rpid != NULL)
+ {
+ /* "[" + "]" */
+ bufsize += 2;
+ bufsize += _asl_append_string_length(rpid, ASL_ENCODE_NONE, 0);
+ }
+
+ if (mf == MFMT_STD)
+ {
+ /* " <" + ">" */
+ bufsize += 3;
+ bufsize += _asl_append_string_length(lstr, ASL_ENCODE_NONE, 0);
+ }
+
+ /* ": " */
+ bufsize += 2;
+
+ if (mstr != NULL) bufsize += _asl_append_string_length(mstr, text_encoding, 0);
+
+ /* "\n\0" */
+ bufsize += 2;
+
+ /* second pass: construct the output line */
+
+ buf = malloc(bufsize);
+ if (buf == NULL) return NULL;
+
+ cursor = 0;
+
+ if (tstr == NULL)
+ {
+ buf[cursor++] = '0';
+ }
+ else
+ {
+ _asl_append_string(buf, bufsize, &cursor, tstr, ASL_ENCODE_NONE, 0);
+ free(tstr);
+ }
+
+ buf[cursor++] = ' ';
+
+ _asl_append_string(buf, bufsize, &cursor, hstr, text_encoding, 0);
+
+ buf[cursor++] = ' ';
+
+ _asl_append_string(buf, bufsize, &cursor, sstr, text_encoding, 0);
+
+ if ((pstr != NULL) && (strcmp(pstr, "-1")))
+ {
+ buf[cursor++] = '[';
+ _asl_append_string(buf, bufsize, &cursor, pstr, ASL_ENCODE_NONE, 0);
+ buf[cursor++] = ']';
+ }
+
+ if ((rprc != NULL) || (rpid != NULL))
+ {
+ buf[cursor++] = ' ';
+ buf[cursor++] = '(';
+ }
+
+ if (rprc != NULL) _asl_append_string(buf, bufsize, &cursor, rprc, text_encoding, 0);
+ if (rpid != NULL)
+ {
+ buf[cursor++] = '[';
+ _asl_append_string(buf, bufsize, &cursor, rpid, ASL_ENCODE_NONE, 0);
+ buf[cursor++] = ']';
+ }
+
+ if ((rprc != NULL) || (rpid != NULL)) buf[cursor++] = ')';
+
+ if (mf == MFMT_STD)
+ {
+ buf[cursor++] = ' ';
+ buf[cursor++] = '<';
+ _asl_append_string(buf, bufsize, &cursor, _asl_level_string(level), ASL_ENCODE_NONE, 0);
+ buf[cursor++] = '>';
+ }
+
+ buf[cursor++] = ':';
+ buf[cursor++] = ' ';
+
+ if (mstr != NULL) _asl_append_string(buf, bufsize, &cursor, mstr, text_encoding, 0);
+
+ buf[cursor++] = '\n';
+ buf[cursor++] = '\0';
+
+ *len = bufsize;
+ return buf;
+ }
+
+ if (mf == MFMT_XML)
+ {
+ /* first pass: calculate output line length */
+ tstr = NULL;
+ bufsize = 0;
+
+ bufsize += 8; /* "\t<dict>\n" */
+
+ for (x = asl_msg_fetch(msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch(msg, x, &key, &val, NULL))
+ {
+ if (asl_is_utf8(key) == 1)
+ {
+ bufsize += _asl_append_xml_tag_length(XML_TAG_KEY, key);
+ if (!strcmp(key, ASL_KEY_TIME))
+ {
+ tstr = _asl_time_string(tf, val);
+ bufsize += _asl_append_xml_tag_length(XML_TAG_STRING, tstr);
+ }
+ else
+ {
+ if (asl_is_utf8(val) == 1) bufsize += _asl_append_xml_tag_length(XML_TAG_STRING, val);
+ else bufsize += _asl_append_xml_tag_length(XML_TAG_DATA, val);
+ }
+ }
+ }
+
+ bufsize += 10; /* "\t</dict>\n\0" */
+
+ /* second pass: construct the output line */
+
+ buf = malloc(bufsize);
+ if (buf == NULL) return NULL;
+
+ cursor = 0;
+
+ _asl_append_string(buf, bufsize, &cursor, "\t<dict>\n", ASL_ENCODE_NONE, 0);
+
+ for (x = asl_msg_fetch(msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch(msg, x, &key, &val, NULL))
+ {
+ if (asl_is_utf8(key) == 1)
+ {
+ _asl_append_xml_tag(buf, bufsize, &cursor, XML_TAG_KEY, key);
+ if (!strcmp(key, ASL_KEY_TIME))
+ {
+ _asl_append_xml_tag(buf, bufsize, &cursor, XML_TAG_STRING, tstr);
+ }
+ else
+ {
+ if (asl_is_utf8(val) == 1) _asl_append_xml_tag(buf, bufsize, &cursor, XML_TAG_STRING, val);
+ else _asl_append_xml_tag(buf, bufsize, &cursor, XML_TAG_DATA, val);
+ }
+ }
+ }
+
+ _asl_append_string(buf, bufsize, &cursor, "\t</dict>\n", ASL_ENCODE_NONE, 0);
+
+ buf[cursor] = '\0';
+
+ if (tstr != NULL) free(tstr);
+
+ *len = bufsize;
+ return buf;
+ }
+
+ /* custom format */
+
+ c[1] = '\0';
+
+ /*
+ * We need enough space to copy any keys found in mfmt.
+ * The key obviously can't be longer than strlen(mfmt),
+ * in fact, keys must be shorter, since there's at least a '$'
+ * in front of the key, so we allocate a buffer with strlen(mfmt).
+ * If strlen(mfmt) <= sizeof(skey), we use skey to avoid a malloc.
+ */
+
+ x = strlen(mfmt);
+ if (x <= sizeof(skey))
+ {
+ k = skey;
+ }
+ else
+ {
+ k = malloc(x);
+ if (k == NULL) return NULL;
+ }
+
+ /* first pass: calculate output line length */
+
+ tstr = NULL;
+ bufsize = 0;
+
+ for (i = 0; mfmt[i] != '\0'; i++)
+ {
+ if (mfmt[i] == '$')
+ {
+ i++;
+ paren = 0;
+
+ if (mfmt[i] == '(')
+ {
+ paren = 1;
+ i++;
+ }
+
+ l = 0;
+
+ for (j = i; mfmt[j] != '\0'; j++)
+ {
+ c[0] = '\0';
+ if (mfmt[j] == '\\') c[0] = mfmt[++j];
+ else if ((paren == 1) && (mfmt[j] ==')')) break;
+ else if (mfmt[j] != ' ') c[0] = mfmt[j];
+
+ if (c[0] == '\0') break;
+
+ k[l] = c[0];
+ k[l + 1] = '\0';
+ l++;
+ }
+
+ if (paren == 1) j++;
+ i = j;
+ if (l > 0)
+ {
+ v = NULL;
+
+ if (asl_msg_lookup(msg, k, &v, NULL) == 0)
+ {
+ if (!strcmp(k, ASL_KEY_TIME))
+ {
+ tstr = _asl_time_string(tf, v);
+ bufsize += _asl_append_string_length(tstr, ASL_ENCODE_NONE, 0);
+ }
+ else
+ {
+ bufsize += _asl_append_string_length(v, ASL_ENCODE_NONE, 0);
+ }
+ }
+ }
+ }
+
+ if (mfmt[i] == '\\')
+ {
+ i++;
+ if (mfmt[i] == '$') bufsize++;
+ else if (mfmt[i] == 'e') bufsize += 2;
+ else if (mfmt[i] == 's') bufsize++;
+ else if (mfmt[i] == 'a') bufsize += 2;
+ else if (mfmt[i] == 'b') bufsize += 2;
+ else if (mfmt[i] == 'f') bufsize += 2;
+ else if (mfmt[i] == 'n') bufsize += 2;
+ else if (mfmt[i] == 'r') bufsize += 2;
+ else if (mfmt[i] == 't') bufsize += 2;
+ else if (mfmt[i] == 'v') bufsize += 2;
+ else if (mfmt[i] == '\'') bufsize += 2;
+ else if (mfmt[i] == '\\') bufsize += 2;
+ else if (isdigit(mfmt[i]))
+ {
+ oval = mfmt[i] - '0';
+ if (isdigit(mfmt[i+1]))
+ {
+ i++;
+ oval = (oval * 8) + (mfmt[i] - '0');
+ if (isdigit(mfmt[i+1]))
+ {
+ i++;
+ oval = (oval * 8) + (mfmt[i] - '0');
+ }
+ }
+
+ c[0] = oval;
+ bufsize += _asl_append_string_length(c, ASL_ENCODE_NONE, 0);
+ }
+ continue;
+ }
+
+ if (mfmt[i] == '\0') break;
+ c[0] = mfmt[i];
+ bufsize += _asl_append_string_length(c, ASL_ENCODE_NONE, 0);
+ }
+
+ bufsize += 2; /* "\n\0" */
+
+ /* second pass: construct the output line */
+
+ buf = malloc(bufsize);
+ if (buf == NULL) return NULL;
+
+ cursor = 0;
+
+ for (i = 0; mfmt[i] != '\0'; i++)
+ {
+ if (mfmt[i] == '$')
+ {
+ i++;
+ paren = 0;
+
+ if (mfmt[i] == '(')
+ {
+ paren = 1;
+ i++;
+ }
+
+ l = 0;
+
+ for (j = i; mfmt[j] != '\0'; j++)
+ {
+ c[0] = '\0';
+ if (mfmt[j] == '\\') c[0] = mfmt[++j];
+ else if ((paren == 1) && (mfmt[j] ==')')) break;
+ else if (mfmt[j] != ' ') c[0] = mfmt[j];
+
+ if (c[0] == '\0') break;
+
+ k[l] = c[0];
+ k[l + 1] = '\0';
+ l++;
+ }
+
+ if (paren == 1) j++;
+ i = j;
+ if (l > 0)
+ {
+ v = NULL;
+
+ if (asl_msg_lookup(msg, k, &v, NULL) == 0)
+ {
+ if (!strcmp(k, ASL_KEY_TIME))
+ {
+ _asl_append_string(buf, bufsize, &cursor, tstr, ASL_ENCODE_NONE, 0);
+ }
+ else
+ {
+ _asl_append_string(buf, bufsize, &cursor, v, ASL_ENCODE_NONE, 0);
+ }
+ }
+ }
+ }
+
+ if (mfmt[i] == '\\')
+ {
+ i++;
+ if (mfmt[i] == '$') _asl_append_string(buf, bufsize, &cursor, "$", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 'e') _asl_append_string(buf, bufsize, &cursor, "\e", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 's') _asl_append_string(buf, bufsize, &cursor, " ", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 'a') _asl_append_string(buf, bufsize, &cursor, "\a", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 'b') _asl_append_string(buf, bufsize, &cursor, "\b", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 'f') _asl_append_string(buf, bufsize, &cursor, "\f", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 'n') _asl_append_string(buf, bufsize, &cursor, "\n", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 'r') _asl_append_string(buf, bufsize, &cursor, "\r", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 't') _asl_append_string(buf, bufsize, &cursor, "\t", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == 'v') _asl_append_string(buf, bufsize, &cursor, "\v", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == '\'') _asl_append_string(buf, bufsize, &cursor, "\'", ASL_ENCODE_NONE, 0);
+ else if (mfmt[i] == '\\') _asl_append_string(buf, bufsize, &cursor, "\\", ASL_ENCODE_NONE, 0);
+ else if (isdigit(mfmt[i]))
+ {
+ oval = mfmt[i] - '0';
+ if (isdigit(mfmt[i+1]))
+ {
+ i++;
+ oval = (oval * 8) + (mfmt[i] - '0');
+ if (isdigit(mfmt[i+1]))
+ {
+ i++;
+ oval = (oval * 8) + (mfmt[i] - '0');
+ }
+ }
+ c[0] = oval;
+ _asl_append_string(buf, bufsize, &cursor, c, ASL_ENCODE_NONE, 0);
+ }
+ continue;
+ }
+
+ if (mfmt[i] == '\0') break;
+ c[0] = mfmt[i];
+ _asl_append_string(buf, bufsize, &cursor, c, ASL_ENCODE_NONE, 0);
+ }
+
+ buf[cursor++] = '\n';
+ buf[cursor] = '\0';
+
+ if (tstr != NULL) free(tstr);
+ if (k != skey) free(k);
+
+ *len = bufsize;
+ return buf;
+}
+
+/*
+ * OLD ASLMSG COMPATIBILITY
+ */
+const char *
+asl_key(aslmsg msg, uint32_t n)
+{
+ uint32_t slot, i;
+ asl_msg_t *page;
+
+ i = 0;
+ for (page = (asl_msg_t *)msg; page != NULL; page = page->next)
+ {
+ for (slot = 0; slot < ASL_MSG_PAGE_SLOTS; slot++)
+ {
+ if (page->key[slot] != ASL_MSG_SLOT_FREE)
+ {
+ if (i == n) return _asl_msg_slot_key(page, slot);
+ i++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+aslmsg
+asl_new(uint32_t type)
+{
+ return (aslmsg)asl_msg_new(type);
+}
+
+int
+asl_set(aslmsg msg, const char *key, const char *value)
+{
+ return asl_msg_set_key_val_op((asl_msg_t *)msg, key, value, IndexNull);
+}
+
+int
+asl_set_query(aslmsg msg, const char *key, const char *value, uint32_t op)
+{
+ return asl_msg_set_key_val_op((asl_msg_t *)msg, key, value, op);
+}
+
+int
+asl_unset(aslmsg msg, const char *key)
+{
+ asl_msg_unset((asl_msg_t *)msg, key);
+ return 0;
+}
+
+const char *
+asl_get(aslmsg msg, const char *key)
+{
+ const char *val;
+ int status;
+
+ val = NULL;
+ status = asl_msg_lookup((asl_msg_t *)msg, key, &val, NULL);
+ if (status != 0) return NULL;
+ return val;
+}
+
+void
+asl_free(aslmsg msg)
+{
+ asl_msg_release((asl_msg_t *)msg);
+}
+
+/* aslresponse */
+
+/*
+ * aslresponse_next: Iterate over responses returned from asl_search()
+ * a: a response returned from asl_search();
+ * returns: The next log message (an aslmsg) or NULL on failure
+ */
+aslmsg
+aslresponse_next(aslresponse r)
+{
+ asl_search_result_t *res;
+ asl_msg_t *m;
+
+ res = (asl_search_result_t *)r;
+ if (res == NULL) return NULL;
+
+ if (res->curr >= res->count) return NULL;
+ m = res->msg[res->curr];
+ res->curr++;
+
+ return (aslmsg)m;
+}
+
+/*
+ * aslresponse_free: Free a response returned from asl_search()
+ * a: a response returned from asl_search()
+ */
+void
+aslresponse_free(aslresponse r)
+{
+ asl_search_result_t *res;
+ uint32_t i;
+
+ res = (asl_search_result_t *)r;
+ if (res == NULL) return;
+
+ for (i = 0; i < res->count; i++) asl_msg_release(res->msg[i]);
+ free(res->msg);
+ free(res);
+}
--- /dev/null
+/*
+ * Copyright (c) 2009-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@
+ */
+
+#ifndef __ASL_MSG_H__
+#define __ASL_MSG_H__
+
+#include <stdint.h>
+
+#define IndexNull ((uint32_t)-1)
+
+#define ASL_MSG_PAGE_DATA_SIZE 800
+#define ASL_MSG_PAGE_SLOTS 24
+
+#define ASL_MSG_OFFSET_MASK 0x3fff
+#define ASL_MSG_KV_MASK 0xc000
+#define ASL_MSG_KV_INLINE 0x0000
+#define ASL_MSG_KV_DICT 0x8000
+#define ASL_MSG_KV_EXTERN 0x4000
+
+#define ASL_MSG_SLOT_FREE 0xffff
+
+#define ASL_STD_KEY_BASE 0x8000
+#define ASL_STD_KEY_TIME 0x8001
+#define ASL_STD_KEY_NANO 0x8002
+#define ASL_STD_KEY_HOST 0x8003
+#define ASL_STD_KEY_SENDER 0x8004
+#define ASL_STD_KEY_FACILITY 0x8005
+#define ASL_STD_KEY_PID 0x8006
+#define ASL_STD_KEY_UID 0x8007
+#define ASL_STD_KEY_GID 0x8008
+#define ASL_STD_KEY_LEVEL 0x8009
+#define ASL_STD_KEY_MESSAGE 0x800a
+#define ASL_STD_KEY_READ_UID 0x800b
+#define ASL_STD_KEY_READ_GID 0x800c
+#define ASL_STD_KEY_SESSION 0x800d
+#define ASL_STD_KEY_REF_PID 0x800e
+#define ASL_STD_KEY_REF_PROC 0x800f
+#define ASL_STD_KEY_MSG_ID 0x8010
+#define ASL_STD_KEY_EXPIRE 0x8011
+#define ASL_STD_KEY_OPTION 0x8012
+#define ASL_STD_KEY_LAST ASL_STD_KEY_OPTION
+
+#define ASL_MT_KEY_BASE 0x8100
+#define ASL_MT_KEY_DOMAIN 0x8101
+#define ASL_MT_KEY_SCOPE 0x8102
+#define ASL_MT_KEY_RESULT 0x8103
+#define ASL_MT_KEY_SIG 0x8104
+#define ASL_MT_KEY_SIG2 0x8105
+#define ASL_MT_KEY_SIG3 0x8106
+#define ASL_MT_KEY_SUCCESS 0x8107
+#define ASL_MT_KEY_UUID 0x8108
+#define ASL_MT_KEY_VAL 0x8109
+#define ASL_MT_KEY_VAL2 0x810a
+#define ASL_MT_KEY_VAL3 0x810b
+#define ASL_MT_KEY_VAL4 0x810c
+#define ASL_MT_KEY_VAL5 0x810d
+#define ASL_MT_KEY_LAST ASL_MT_KEY_VAL5
+
+#define ASL_PRIVATE_KEY_BASE 0x8200
+
+#define ASL_MSG_TYPE_AUX_0 0
+
+typedef struct
+{
+ const char *level;
+ const char *time;
+ const char *nano;
+ const char *host;
+ const char *sender;
+ const char *facility;
+ const char *pid;
+ const char *uid;
+ const char *gid;
+ const char *message;
+ const char *option;
+ const char *auxtitle;
+ const char *auxuti;
+ const char *auxurl;
+} asl_msg_aux_0_t;
+
+typedef struct
+{
+ uint32_t type;
+ union
+ {
+ asl_msg_aux_0_t *aux0;
+ } data;
+} asl_msg_aux_t;
+
+typedef struct asl_msg_s
+{
+ uint32_t type;
+ int32_t refcount;
+ uint32_t count;
+ uint32_t data_size;
+ void *aux;
+ struct asl_msg_s *next;
+ uint16_t key[ASL_MSG_PAGE_SLOTS];
+ uint16_t val[ASL_MSG_PAGE_SLOTS];
+ uint32_t op[ASL_MSG_PAGE_SLOTS];
+ char data[ASL_MSG_PAGE_DATA_SIZE];
+} asl_msg_t;
+
+asl_msg_t *asl_msg_new(uint32_t type) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+asl_msg_t *asl_msg_retain(asl_msg_t *msg) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+void asl_msg_release(asl_msg_t *msg) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+
+int asl_msg_set_key_val(asl_msg_t *msg, const char *key, const char *val) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int asl_msg_set_key_val_op(asl_msg_t *msg, const char *key, const char *val, uint32_t op) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+void asl_msg_unset(asl_msg_t *msg, const char *key) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+
+int asl_msg_lookup(asl_msg_t *msg, const char *key, const char **valout, uint32_t *opout) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+uint32_t asl_msg_fetch(asl_msg_t *msg, uint32_t n, const char **keyout, const char **valout, uint32_t *opout) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+
+uint32_t asl_msg_type(asl_msg_t *msg) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+uint32_t asl_msg_count(asl_msg_t *msg) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+
+#endif /* __ASL_MSG_H__ */
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 2007 Apple Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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 __ASL_PRIVATE_H__
+#define __ASL_PRIVATE_H__
+
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-
-#define _PATH_ASL_OUT "/var/log/asl.log"
+#include "asl_file.h"
+#include "asl_msg.h"
+#include <Availability.h>
#define ASL_QUERY_OP_NULL 0x00000
#define ASL_ENCODE_VIS 2
#define ASL_ENCODE_ASL 3
-#define ASL_KEY_REF_PID "RefPID"
-#define ASL_KEY_REF_PROC "RefProc"
-#define ASL_KEY_OPTION "ASLOption"
-
#define ASL_OPT_IGNORE "ignore"
#define ASL_OPT_STORE "store"
#define ASL_STORE_LOCATION_FILE 0
#define ASL_STORE_LOCATION_MEMORY 1
+#define ASL_OPT_SYSLOG_LEGACY 0x00010000
+
+/* SPI to enable ASL filter tunneling using asl_set_filter() */
+#define ASL_FILTER_MASK_TUNNEL 0x100
+
typedef struct __aslclient
{
uint32_t options;
char **fd_mfmt;
char **fd_tfmt;
uint32_t *fd_encoding;
+ asl_file_t *aslfile;
+ uint64_t aslfileid;
uint32_t reserved1;
void *reserved2;
} asl_client_t;
-typedef struct __aslmsg
-{
- uint32_t type;
- uint32_t count;
- char **key;
- char **val;
- uint32_t *op;
-} asl_msg_t;
-
typedef struct __aslresponse
{
uint32_t count;
asl_msg_t **msg;
} asl_search_result_t;
-
__BEGIN_DECLS
-int asl_add_output(aslclient asl, int fd, const char *msg_fmt, const char *time_fmt, uint32_t text_encoding);
-int asl_remove_output(aslclient asl, int fd);
-char *asl_format_message(aslmsg msg, const char *msg_fmt, const char *time_fmt, uint32_t text_encoding, uint32_t *outlen);
-int asl_store_location();
+int asl_add_output(aslclient asl, int fd, const char *msg_fmt, const char *time_fmt, uint32_t text_encoding) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int asl_remove_output(aslclient asl, int fd) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+char *asl_format_message(asl_msg_t *msg, const char *msg_fmt, const char *time_fmt, uint32_t text_encoding, uint32_t *outlen) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_msg_string_length(asl_msg_t *msg) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+uint32_t asl_msg_to_string_buffer(asl_msg_t *msg, char *buf, uint32_t bufsize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+char *asl_msg_to_string(asl_msg_t *in, uint32_t *len) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
+asl_search_result_t *asl_list_from_string(const char *buf) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+char *asl_list_to_string(asl_search_result_t *, uint32_t *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int asl_store_location() __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int asl_get_filter(aslclient asl, int *local, int *master, int *remote, int *active) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+char *asl_remote_notify_name() __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
__END_DECLS
+#endif /* __ASL_PRIVATE_H__ */
/*
- * Copyright (c) 2007-2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 2007 Apple Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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@
*/
extern uint64_t asl_file_cursor(asl_file_t *s);
extern uint32_t asl_file_match_start(asl_file_t *s, uint64_t start_id, int32_t direction);
extern uint32_t asl_file_match_next(asl_file_t *s, aslresponse query, asl_msg_t **msg, uint64_t *last_id, int32_t direction, int32_t ruid, int32_t rgid);
+extern int asl_file_create(const char *path, uid_t uid, gid_t gid, mode_t mode);
#define SECONDS_PER_DAY 86400
memset(&sb, 0, sizeof(struct stat));
if (stat(basedir, &sb) != 0) return ASL_STATUS_INVALID_STORE;
- if ((sb.st_mode & S_IFDIR) == 0) return ASL_STATUS_INVALID_STORE;
+ if (!S_ISDIR(sb.st_mode)) return ASL_STATUS_INVALID_STORE;
path = NULL;
asprintf(&path, "%s/%s", basedir, FILE_ASL_STORE_DATA);
fclose(sd);
return ASL_STATUS_WRITE_FAILED;
}
+
+ /* flush data */
+ fflush(sd);
}
else
{
if (s == NULL) return ASL_STATUS_INVALID_STORE;
if (msg == NULL) return ASL_STATUS_INVALID_ARG;
- out = (aslmsg)calloc(1, sizeof(asl_msg_t));
+ out = asl_new(ASL_TYPE_MSG);
if (out == NULL) return ASL_STATUS_NO_MEMORY;
/* does nothing for now */
memset(&sb, 0, sizeof(struct stat));
if (stat(basedir, &sb) != 0) return ASL_STATUS_INVALID_STORE;
- if ((sb.st_mode & S_IFDIR) == 0) return ASL_STATUS_INVALID_STORE;
+ if (!S_ISDIR(sb.st_mode)) return ASL_STATUS_INVALID_STORE;
out = (asl_store_t *)calloc(1, sizeof(asl_store_t));
if (out == NULL) return ASL_STATUS_NO_MEMORY;
return ASL_STATUS_OK;
}
-void
+__private_extern__ void
asl_store_file_closeall(asl_store_t *s)
{
uint32_t i;
return ASL_STATUS_OK;
}
+static char *
+asl_store_make_ug_path(const char *dir, const char *base, const char *ext, uid_t ruid, gid_t rgid, uid_t *u, gid_t *g, mode_t *m)
+{
+ char *path = NULL;
+
+ *u = 0;
+ *g = 0;
+ *m = 0644;
+
+ if (ruid == -1)
+ {
+ if (rgid == -1)
+ {
+ if (ext == NULL) asprintf(&path, "%s/%s", dir, base);
+ else asprintf(&path, "%s/%s.%s", dir, base, ext);
+ }
+ else
+ {
+ *g = rgid;
+ *m = 0600;
+ if (ext == NULL) asprintf(&path, "%s/%s.G%d", dir, base, *g);
+ else asprintf(&path, "%s/%s.G%d.%s", dir, base, *g, ext);
+ }
+ }
+ else
+ {
+ *u = ruid;
+ if (rgid == -1)
+ {
+ *m = 0600;
+ if (ext == NULL) asprintf(&path, "%s/%s.U%d", dir, base, *u);
+ else asprintf(&path, "%s/%s.U%d.%s", dir, base, *u, ext);
+ }
+ else
+ {
+ *g = rgid;
+ *m = 0600;
+ if (ext == NULL) asprintf(&path, "%s/%s.U%d.G%d", dir, base, *u, *g);
+ else asprintf(&path, "%s/%s.U%d.G%u.%s", dir, base, *u, *g, ext);
+ }
+ }
+
+ return path;
+}
+
static uint32_t
asl_store_file_open_write(asl_store_t *s, char *tstring, int32_t ruid, int32_t rgid, time_t bb, asl_file_t **f, time_t now, uint32_t check_cache)
{
char *path;
mode_t m;
- int32_t i, x, u, g;
+ int32_t i, x;
+ uid_t u;
+ gid_t g;
uint32_t status;
asl_file_t *out;
}
}
- path = NULL;
u = 0;
g = 0;
m = 0644;
-
- if (ruid == -1)
- {
- if (rgid == -1)
- {
- asprintf(&path, "%s/%s.asl", s->base_dir, tstring);
- }
- else
- {
- g = rgid;
- m = 0640;
- asprintf(&path, "%s/%s.G%d.asl", s->base_dir, tstring, g);
- }
- }
- else
- {
- u = ruid;
- if (rgid == -1)
- {
- m = 0600;
- asprintf(&path, "%s/%s.U%d.asl", s->base_dir, tstring, u);
- }
- else
- {
- g = rgid;
- m = 0640;
- asprintf(&path, "%s/%s.U%d.G%u.asl", s->base_dir, tstring, u, g);
- }
- }
-
+ path = asl_store_make_ug_path(s->base_dir, tstring, "asl", (uid_t)ruid, (gid_t)rgid, &u, &g, &m);
if (path == NULL) return ASL_STATUS_NO_MEMORY;
out = NULL;
return ASL_STATUS_OK;
}
-char *
+__private_extern__ char *
asl_store_file_path(asl_store_t *s, asl_file_t *f)
{
uint32_t i;
return NULL;
}
-void
+__private_extern__ void
asl_store_file_close(asl_store_t *s, asl_file_t *f)
{
uint32_t i;
xid = asl_core_htonq(s->next_id);
if (fwrite(&xid, sizeof(uint64_t), 1, s->storedata) != 1) return ASL_STATUS_WRITE_FAILED;
+ /* flush data */
+ fflush(s->storedata);
+
xid = s->next_id;
s->next_id++;
if (bb == 1)
{
/*
- * This supports 12 monthy "Best Before" buckets.
+ * This supports 12 monthly "Best Before" buckets.
* We advance the actual expiry time to day zero of the following month.
* mktime() is clever enough to know that you actually mean the last day
* of the previous month. What we get back from localtime is the last
return status;
}
+static uint32_t
+asl_store_mkdir(asl_store_t *s, const char *dir, mode_t m)
+{
+ char *tstring = NULL;
+ int status;
+ struct stat sb;
+
+ asprintf(&tstring, "%s/%s", s->base_dir, dir);
+ if (tstring == NULL) return ASL_STATUS_NO_MEMORY;
+
+ memset(&sb, 0, sizeof(struct stat));
+ status = stat(tstring, &sb);
+
+ if (status == 0)
+ {
+ /* must be a directory */
+ if (!S_ISDIR(sb.st_mode))
+ {
+ free(tstring);
+ return ASL_STATUS_INVALID_STORE;
+ }
+ }
+ else
+ {
+ if (errno == ENOENT)
+ {
+ /* doesn't exist - create it */
+ if (mkdir(tstring, m) != 0)
+ {
+ free(tstring);
+ return ASL_STATUS_WRITE_FAILED;
+ }
+ }
+ else
+ {
+ /* stat failed for some other reason */
+ free(tstring);
+ return ASL_STATUS_FAILED;
+ }
+ }
+
+ free(tstring);
+ return ASL_STATUS_OK;
+}
+
+uint32_t
+asl_store_open_aux(asl_store_t *s, aslmsg msg, int *out_fd, char **url)
+{
+ struct tm ctm;
+ time_t msg_time, bb;
+ char *path, *dir, *tstring;
+ const char *val;
+ uid_t ruid, u;
+ gid_t rgid, g;
+ mode_t m;
+ uint32_t status;
+ uint64_t fid;
+ int fd;
+
+ if (s == NULL) return ASL_STATUS_INVALID_STORE;
+ if (msg == NULL) return ASL_STATUS_INVALID_ARG;
+ if (out_fd == NULL) return ASL_STATUS_INVALID_ARG;
+ if (url == NULL) return ASL_STATUS_INVALID_ARG;
+
+ msg_time = time(NULL);
+
+ val = asl_get(msg, ASL_KEY_READ_UID);
+ ruid = -1;
+ if (val != NULL) ruid = atoi(val);
+
+ val = asl_get(msg, ASL_KEY_READ_GID);
+ rgid = -1;
+ if (val != NULL) rgid = atoi(val);
+
+ bb = 0;
+ val = asl_get(msg, ASL_KEY_EXPIRE_TIME);
+ if (val != NULL)
+ {
+ bb = 1;
+ msg_time = asl_parse_time(val);
+ }
+
+ if (localtime_r((const time_t *)&msg_time, &ctm) == NULL) return ASL_STATUS_FAILED;
+
+ dir = NULL;
+ if (bb == 1)
+ {
+ /*
+ * This supports 12 monthly "Best Before" buckets.
+ * We advance the actual expiry time to day zero of the following month.
+ * mktime() is clever enough to know that you actually mean the last day
+ * of the previous month. What we get back from localtime is the last
+ * day of the month in which the message expires, which we use in the name.
+ */
+ ctm.tm_sec = 0;
+ ctm.tm_min = 0;
+ ctm.tm_hour = 0;
+ ctm.tm_mday = 0;
+ ctm.tm_mon += 1;
+
+ bb = mktime(&ctm);
+
+ if (localtime_r((const time_t *)&bb, &ctm) == NULL) return ASL_STATUS_FAILED;
+ asprintf(&dir, "BB.AUX.%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
+ }
+ else
+ {
+ asprintf(&dir, "AUX.%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
+ }
+
+ if (dir == NULL) return ASL_STATUS_NO_MEMORY;
+
+ status = asl_store_mkdir(s, dir, 0755);
+ if (status != ASL_STATUS_OK)
+ {
+ free(dir);
+ return status;
+ }
+
+ fid = s->next_id;
+ s->next_id++;
+ tstring = NULL;
+
+ asprintf(&tstring, "%s/%llu", dir, fid);
+ free(dir);
+ if (tstring == NULL) return ASL_STATUS_NO_MEMORY;
+
+ u = 0;
+ g = 0;
+ m = 0644;
+ path = asl_store_make_ug_path(s->base_dir, tstring, NULL, ruid, rgid, &u, &g, &m);
+ free(tstring);
+ if (path == NULL) return ASL_STATUS_NO_MEMORY;
+
+ fd = asl_file_create(path, u, g, m);
+ if (fd < 0)
+ {
+ free(path);
+ *out_fd = -1;
+ return ASL_STATUS_WRITE_FAILED;
+ }
+
+ /* URL is file://<path> */
+ *url = NULL;
+ asprintf(url, "file://%s", path);
+ free(path);
+
+ *out_fd = fd;
+
+ return status;
+}
+
uint32_t
asl_store_match_timeout(asl_store_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, uint32_t usec)
{
-#ifndef __ASL_STORE_H__
-#define __ASL_STORE_H__
-
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 2007 Apple Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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 __ASL_STORE_H__
+#define __ASL_STORE_H__
+
#include <stdio.h>
#include <stdint.h>
#include <sys/time.h>
#include <asl.h>
-#include <asl_file.h>
+#include "asl_file.h"
+#include <Availability.h>
#define PATH_ASL_STORE "/var/log/asl"
#define PATH_ASL_ARCHIVE "/var/log/asl.archive"
size_t max_file_size;
} asl_store_t;
-uint32_t asl_store_open_write(const char *basedir, asl_store_t **s);
-uint32_t asl_store_open_read(const char *basedir, asl_store_t **s);
-uint32_t asl_store_close(asl_store_t *s);
-uint32_t asl_store_statistics(asl_store_t *s, aslmsg *msg);
+uint32_t asl_store_open_write(const char *basedir, asl_store_t **s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_store_open_read(const char *basedir, asl_store_t **s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_store_close(asl_store_t *s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_store_statistics(asl_store_t *s, aslmsg *msg) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+
+uint32_t asl_store_save(asl_store_t *s, aslmsg msg) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_store_save(asl_store_t *s, aslmsg msg);
+uint32_t asl_store_match(asl_store_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_store_match_timeout(asl_store_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, uint32_t usec) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
-uint32_t asl_store_match(asl_store_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction);
-uint32_t asl_store_match_timeout(asl_store_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, uint32_t usec);
+uint32_t asl_store_match_start(asl_store_t *s, uint64_t start_id, int32_t direction) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_store_match_next(asl_store_t *s, aslresponse query, aslresponse *res, uint32_t count) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
-uint32_t asl_store_match_start(asl_store_t *s, uint64_t start_id, int32_t direction);
-uint32_t asl_store_match_next(asl_store_t *s, aslresponse query, aslresponse *res, uint32_t count);
+uint32_t asl_store_max_file_size(asl_store_t *s, size_t max) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_store_signal_sweep(asl_store_t *s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+uint32_t asl_store_sweep_file_cache(asl_store_t *s) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
-uint32_t asl_store_max_file_size(asl_store_t *s, size_t max);
-uint32_t asl_store_signal_sweep(asl_store_t *s);
-uint32_t asl_store_sweep_file_cache(asl_store_t *s);
+uint32_t asl_store_open_aux(asl_store_t *s, aslmsg msg, int *fd, char **url) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
#endif __ASL_STORE_H__
* 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.
static char sccsid[] = "@(#)assert.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/assert.c,v 1.7 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/assert.c,v 1.8 2007/01/09 00:27:53 imp Exp $");
#include <assert.h>
-#include <stdio.h>
#include <stdlib.h>
-
-extern const char *__crashreporter_info__;
-static const char badasprintf[] =
- "Assertion failed and asprintf also failed to create full error string";
+#include <unistd.h>
+#include "CrashReporterClient.h"
+#include "_simple.h"
void
__assert_rtn(func, file, line, failedexpr)
int line;
const char *failedexpr;
{
- char *str = NULL;
-
- if (func == NULL) {
- (void)fprintf(stderr,
+ if (func == (const char *)-1L) {
+ /* 8462256: special case to replace __eprintf */
+ _simple_dprintf(STDERR_FILENO,
+ "%s:%u: failed assertion `%s'\n", file, line, failedexpr);
+ if (!CRGetCrashLogMessage()) {
+ _SIMPLE_STRING s = _simple_salloc();
+ if (s) {
+ _simple_sprintf(s,
+ "%s:%u: failed assertion `%s'\n",
+ file, line, failedexpr);
+ CRSetCrashLogMessage(_simple_string(s));
+ } else
+ CRSetCrashLogMessage(failedexpr);
+ }
+ } else if (func == NULL) {
+ _simple_dprintf(STDERR_FILENO,
"Assertion failed: (%s), file %s, line %d.\n", failedexpr,
file, line);
- if (!__crashreporter_info__) {
- asprintf(&str,
- "Assertion failed: (%s), file %s, line %d.\n",
- failedexpr, file, line);
- __crashreporter_info__ = str ? str : badasprintf;
+ if (!CRGetCrashLogMessage()) {
+ _SIMPLE_STRING s = _simple_salloc();
+ if (s) {
+ _simple_sprintf(s,
+ "Assertion failed: (%s), file %s, line %d.\n",
+ failedexpr, file, line);
+ CRSetCrashLogMessage(_simple_string(s));
+ } else
+ CRSetCrashLogMessage(failedexpr);
}
} else {
- (void)fprintf(stderr,
+ _simple_dprintf(STDERR_FILENO,
"Assertion failed: (%s), function %s, file %s, line %d.\n",
failedexpr, func, file, line);
- if (!__crashreporter_info__) {
- asprintf(&str,
- "Assertion failed: (%s), function %s, file %s, line %d.\n",
- failedexpr, func, file, line);
- __crashreporter_info__ = str ? str : badasprintf;
+ if (!CRGetCrashLogMessage()) {
+ _SIMPLE_STRING s = _simple_salloc();
+ if (s) {
+ _simple_sprintf(s,
+ "Assertion failed: (%s), function %s, file %s, line %d.\n",
+ failedexpr, func, file, line);
+ CRSetCrashLogMessage(_simple_string(s));
+ } else
+ CRSetCrashLogMessage(failedexpr);
}
}
abort();
--- /dev/null
+#include <dispatch/dispatch.h>
+#include <uuid/uuid.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <mach-o/loader.h>
+#include <sys/types.h>
+#include <execinfo.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <asl.h>
+#include <errno.h>
+#include "assumes.h"
+
+/* TODO: Re-enable after deciding how best to interact with this symbol. */
+/*
+ * NOTE: 8006611: converted to using libCrashReporterClient.a, so shouldn't
+ * use __crashreporter_info__.
+ */
+#if 0
+static char __crashreporter_info_buff__[2048];
+const char *__crashreporter_info__ = &__crashreporter_info_buff__[0];
+asm (".desc __crashreporter_info__, 0x10");
+#endif
+
+#define osx_atomic_cmpxchg(p, o, n) __sync_bool_compare_and_swap((p), (o), (n))
+
+static const char *
+_osx_basename(const char *p)
+{
+ return ((strrchr(p, '/') ? : p - 1) + 1);
+}
+
+static char *
+_osx_get_build(void)
+{
+ static char s_build[16];
+ static long s_once = 0;
+ if (osx_atomic_cmpxchg(&s_once, 0, 1)) {
+ int mib[] = { CTL_KERN, KERN_OSVERSION };
+ size_t sz = sizeof(s_build);
+
+ (void)sysctl(mib, 2, s_build, &sz, NULL, 0);
+ }
+
+ return s_build;
+}
+
+static void
+_osx_get_image_uuid(void *hdr, uuid_t uuid)
+{
+#if __LP64__
+ struct mach_header_64 *_hdr = (struct mach_header_64 *)hdr;
+#else
+ struct mach_header *_hdr = (struct mach_header *)hdr;
+#endif /* __LP64__ */
+
+ size_t i = 0;
+ size_t next = sizeof(*_hdr);
+ struct load_command *cur = NULL;
+ for (i = 0; i < _hdr->ncmds; i++) {
+ cur = (struct load_command *)((uintptr_t)_hdr + next);
+ if (cur->cmd == LC_UUID) {
+ struct uuid_command *cmd = (struct uuid_command *)cur;
+ uuid_copy(uuid, cmd->uuid);
+ break;
+ }
+ next += cur->cmdsize;
+ }
+
+ if (i == _hdr->ncmds) {
+ uuid_clear(uuid);
+ }
+}
+
+void
+_osx_assumes_log(uint64_t code)
+{
+ Dl_info info;
+
+ const char *image_name = NULL;
+ uintptr_t offset = 0;
+ uuid_string_t uuid_str;
+
+ void *arr[2];
+ /* Get our caller's address so we can look it up with dladdr(3) and
+ * get info about the image.
+ */
+ if (backtrace(arr, 2) == 2) {
+ /* dladdr(3) returns non-zero on success... for some reason. */
+ if (dladdr(arr[1], &info)) {
+ uuid_t uuid;
+ _osx_get_image_uuid(info.dli_fbase, uuid);
+
+ uuid_unparse(uuid, uuid_str);
+ image_name = _osx_basename(info.dli_fname);
+
+ offset = arr[1] - info.dli_fbase;
+ }
+ } else {
+ uuid_t null_uuid;
+ uuid_string_t uuid_str;
+
+ uuid_clear(null_uuid);
+ uuid_unparse(null_uuid, uuid_str);
+
+ image_name = "unknown";
+ }
+
+ char name[256];
+ (void)snprintf(name, sizeof(name), "com.apple.assumes.%s", image_name);
+
+ char sig[64];
+ (void)snprintf(sig, sizeof(sig), "%s:%lu", uuid_str, offset);
+
+ char result[24];
+ (void)snprintf(result, sizeof(result), "0x%llx", code);
+
+ char *prefix = "Bug";
+ char message[1024];
+ (void)snprintf(message, sizeof(message), "%s: %s: %s + %lu [%s]: %s", prefix, _osx_get_build(), image_name, offset, uuid_str, result);
+
+ aslmsg msg = asl_new(ASL_TYPE_MSG);
+ if (msg != NULL) {
+ /* MessageTracer messages aren't logged to the regular syslog store, so
+ * we pre-log the message without any MessageTracer attributes so that
+ * we can see it in our regular syslog.
+ */
+ (void)asl_log(NULL, msg, ASL_LEVEL_ERR, "%s", message);
+
+ (void)asl_set(msg, "com.apple.message.domain", name);
+ (void)asl_set(msg, "com.apple.message.signature", sig);
+ (void)asl_set(msg, "com.apple.message.value", result);
+
+ (void)asl_log(NULL, msg, ASL_LEVEL_ERR, "%s", message);
+ asl_free(msg);
+ }
+}
+
+/* For osx_assert(). We need to think more about how best to set the __crashreporter_info__ string.
+ * For example, calling into two functions will basically smash the register state at the time of
+ * the assertion failure, causing potentially valuable information to be lost. Also, just setting
+ * the __crashreporter_info__ to a static string only involves one instruction, whereas a function
+ * call involves... well, more.
+ */
+#if 0
+void
+osx_hardware_trap(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ osx_hardware_trapv(fmt, ap);
+
+ va_end(ap);
+}
+
+void
+osx_hardware_trapv(const char *fmt, va_list ap)
+{
+ (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), fmt, ap);
+ fflush(NULL);
+ __builtin_trap();
+}
+#endif
--- /dev/null
+#ifndef __OSX_ASSUMES_H__
+#define __OSX_ASSUMES_H__
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#include <Availability.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <asl.h>
+
+#if __GNUC__
+#define osx_fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
+#define osx_slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
+#define osx_constant(x) __builtin_constant_p((x))
+
+#define __OSX_COMPILETIME_ASSERT__(e) ({ \
+ char __compile_time_assert__[(e) ? 1 : -1]; \
+ (void)__compile_time_assert__; \
+})
+#else
+#define osx_fastpath(x) (x)
+#define osx_slowpath(x) (x)
+#define osx_constant(x) ((long)0)
+
+#define __OSX_COMPILETIME_ASSERT__(e) (e)
+#endif /* __GNUC__ */
+
+#define osx_assumes(e) ({ \
+ typeof(e) _e = osx_fastpath(e); /* Force evaluation of 'e' */ \
+ if (!_e) { \
+ if (osx_constant(e)) { \
+ __OSX_COMPILETIME_ASSERT__(e); \
+ } \
+ _osx_assumes_log((uintptr_t)_e); \
+ } \
+ _e; \
+})
+
+#define osx_assumes_zero(e) ({ \
+ typeof(e) _e = osx_slowpath(e); /* Force evaluation of 'e' */ \
+ if (_e) { \
+ if (osx_constant(e)) { \
+ __OSX_COMPILETIME_ASSERT__(!e); \
+ } \
+ _osx_assumes_log((uintptr_t)_e); \
+ } \
+ _e; \
+})
+
+__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
+extern void
+_osx_assumes_log(uint64_t code);
+
+__END_DECLS
+
+#endif /* __OSX_ASSUMES_H__ */
#if __LP64__
#define _BACKTRACE_FORMAT "%-4d%-35s 0x%016lx %s + %lu"
-#define _BACKTRACE_FORMAT_SIZE 82
+#define _BACKTRACE_FORMAT_SIZE 83 /* %lu can take up to 20, does not include %s, includes NUL */
+#define _BACKTRACE_ADDRESS_LEN 18 /* 0x + 16 (no NUL) */
#else
#define _BACKTRACE_FORMAT "%-4d%-35s 0x%08lx %s + %lu"
-#define _BACKTRACE_FORMAT_SIZE 65
+#define _BACKTRACE_FORMAT_SIZE 65 /* %lu can take up to 10, does not include %s, includes NUL */
+#define _BACKTRACE_ADDRESS_LEN 10 /* 0x + 8 (no NUL) */
#endif
-
static int _backtrace_snprintf(char* buf, size_t size, int frame, const void* addr, const Dl_info* info) {
- char symbuf[19];
+ char symbuf[_BACKTRACE_ADDRESS_LEN + 1];
const char* image = "???";
- const char* symbol = symbuf;
+ const char* symbol = "0x0";
+ uintptr_t symbol_offset = 0;
if (info->dli_fname) {
- image = strrchr(info->dli_fname, '/') + 1;
- if (image == NULL) image = info->dli_fname;
+ const char *tmp = strrchr(info->dli_fname, '/');
+ if(tmp == NULL)
+ image = info->dli_fname;
+ else
+ image = tmp + 1;
}
if (info->dli_sname) {
symbol = info->dli_sname;
+ symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_saddr;
+ } else if(info->dli_fname) {
+ symbol = image;
+ symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_fbase;
+ } else if(0 < snprintf(symbuf, sizeof(symbuf), "0x%lx", (uintptr_t)info->dli_saddr)) {
+ symbol = symbuf;
+ symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_saddr;
} else {
- snprintf(symbuf, sizeof(symbuf), "0x%lx", (uintptr_t)info->dli_saddr);
+ symbol_offset = (uintptr_t)addr;
}
return snprintf(buf, size,
image,
(uintptr_t)addr,
symbol,
- (uintptr_t)addr - (uintptr_t)info->dli_saddr) + 1;
+ symbol_offset) + 1;
}
char** backtrace_symbols(void* const* buffer, int size) {
size_t total_bytes;
char** result;
char** ptrs;
- intptr_t strs;
+ intptr_t strs, end;
Dl_info* info = calloc(size, sizeof (Dl_info));
if (info == NULL) return NULL;
// Plus each symbol description
for (i = 0 ; i < size; ++i) {
dladdr(buffer[i], &info[i]);
- total_bytes += _BACKTRACE_FORMAT_SIZE + 1;
- if (info[i].dli_sname) total_bytes += strlen(info[i].dli_sname);
+ total_bytes += _BACKTRACE_FORMAT_SIZE;
+ if (info[i].dli_sname) {
+ total_bytes += strlen(info[i].dli_sname);
+ } else if(info[i].dli_fname) {
+ const char *tmp = strrchr(info->dli_fname, '/');
+ if(tmp == NULL)
+ total_bytes += strlen(info->dli_fname);
+ else
+ total_bytes += strlen(tmp + 1);
+ } else {
+ total_bytes += _BACKTRACE_ADDRESS_LEN;
+ }
}
result = (char**)malloc(total_bytes);
free(info);
return NULL;
}
+ end = (intptr_t)result + total_bytes;
// Fill in the array of pointers and append the strings for
// each symbol description.
ptrs = result;
strs = ((intptr_t)result) + sizeof(char*) * size;
-
+
for (i = 0; i < size; ++i) {
+ int chk = _backtrace_snprintf((char*)strs, end - (intptr_t)strs, i, buffer[i], &info[i]);
+
+ if(chk < 0) {
+ free(info);
+ return NULL;
+ }
+
ptrs[i] = (char*)strs;
- strs += _backtrace_snprintf((char*)strs, total_bytes, i, buffer[i], &info[i]);
+ strs += chk;
}
free(info);
* 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.
static char sccsid[] = "@(#)closedir.c 8.1 (Berkeley) 6/10/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/closedir.c,v 1.10 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/closedir.c,v 1.13 2007/12/03 14:33:50 des Exp $");
#include "namespace.h"
#include <sys/types.h>
int fd;
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
#if !__DARWIN_UNIX03
_seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */
#endif /* __DARWIN_UNIX03 */
free((void *)dirp->dd_buf);
_reclaim_telldir(dirp);
if (__isthreaded) {
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
- _pthread_mutex_destroy((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ _pthread_mutex_destroy(&dirp->dd_lock);
}
free((void *)dirp);
return(_close(fd));
-.Dd October 23, 2005
+.Dd June 30, 2010
.Os Darwin
.Dt COMPAT 5
.Sh NAME
.Sh DESCRIPTION
Setting the environment variable
.Ev COMMAND_MODE
-to the value legacy causes utility programs to behave as closely to Mac OS X 10.3's utility programs as possible. When in this mode all of 10.3's flags are accepted, and in some cases extra flags are accepted, but no flags that were used in 10.3 will have been removed or changed in meaning. Any behavioral changes in this mode are documented in the LEGACY sections of the individual utilities.
+to the value legacy causes utility programs to behave as closely to
+Mac OS X 10.3's utility programs as possible. When in this mode all of 10.3's
+flags are accepted, and in some cases extra flags are accepted, but no flags
+that were used in 10.3 will have been removed or changed in meaning. Any
+behavioral changes in this mode are documented in the LEGACY sections of the
+individual utilities.
.Pp
Setting the environment variable
.Ev COMMAND_MODE
.Pp
The value of
.Ev COMMAND_MODE
-is case insensitive and if it is unset or set to something other than legacy or unix2003 it behaves as if it were set to unix2003.
-.Sh 32-BIT COMPILATION
+is case insensitive and if it is unset or set to something other than legacy
+or unix2003 it behaves as if it were set to unix2003.
+.Sh COMPILATION
Defining
.Dv _NONSTD_SOURCE
-causes library and kernel calls to behave as closely to Mac OS X 10.3's library and kernel calls as possible. Any behavioral changes in this mode are documented in the LEGACY sections of the individual function calls.
+for i386 causes library and kernel calls to behave as closely to Mac
+OS X 10.3's library and kernel calls as possible. Any behavioral changes are
+documented in the LEGACY sections of the man pages for the individual function
+calls. Defining this macro when compiling for any other architecture will
+result in a compilation error.
.Pp
Defining
.Dv _POSIX_C_SOURCE
be on by default, and non-POSIX extensions will also be available
(this is the equivalent of defining
.Dv _DARWIN_C_SOURCE ) .
-For version values less that 10.5, UNIX conformance will be off (the
-equivalent of defining
+For version values less that 10.5, UNIX conformance will be off when targeting
+i386 (the equivalent of defining
.Dv _NONSTD_SOURCE ) .
-.Sh 64-BIT COMPILATION
-When compiling for 64-bit architectures, the
-.Dv __LP64__
-macro will be defined to 1, and UNIX conformance is always on (the
-.Dv _DARWIN_FEATURE_UNIX_CONFORMANCE
-macro will also be defined to the SUS conformance level).
-Defining
-.Dv _NONSTD_SOURCE
-will cause a compilation error.
+.Pp
+In order to provide both legacy and conformance versions of functions, two
+versions of affected functions are provided. Legacy variants have symbol names
+with no suffix in order to maintain ABI compatibility. Conformance versions
+have a $UNIX2003 suffix appended to their symbol name. These $UNIX2003
+suffixes are automatically appended by the compiler tool-chain and should not
+be used directly.
+.Pp
+Platforms that were released after these updates only have conformance variants
+available and do not have a $UNIX2003 suffix.
+.Pp
+.TS
+center;
+c s s s s
+c c | c c c
+c c | c c c
+l c | c c c
+l c | c c c
+l c | c c c
+l c | c c c
+l c | c c c
+l c | c c c
+l c | c c c.
+T{
+.Dv i386
+T}
+=
+user defines deployment namespace conformance suffix
+ target
+_
+T{
+.Em (none)
+T} < 10.5 full 10.3 compatibility (none)
+T{
+.Em (none)
+T} >= 10.5 full SUSv3 conformance $UNIX2003
+T{
+.Em _NONSTD_SOURCE
+T} (any) full 10.3 compatibility (none)
+T{
+.Em _DARWIN_C_SOURCE
+T} < 10.4 full 10.3 compatibility (none)
+T{
+.Em _DARWIN_C_SOURCE
+T} >= 10.4 full SUSv3 conformance $UNIX2003
+T{
+.Em _POSIX_C_SOURCE
+T} < 10.4 strict 10.3 compatibility (none)
+T{
+.Em _POSIX_C_SOURCE
+T} >= 10.4 strict SUSv3 conformance $UNIX2003
+_
+.T&
+c s s s s
+c s s s s
+c c | c c c
+c c | c c c
+l c | c c c
+l c | c s s
+l c | c c c
+l c | c c c.
+T{
+.Dv Newer Architectures
+T}
+=
+user defines deployment namespace conformance suffix
+ target
+_
+T{
+.Em (none)
+T} (any) full SUSv3 conformance (none)
+T{
+.Em _NONSTD_SOURCE
+T} (any) (error)
+T{
+.Em _DARWIN_C_SOURCE
+T} (any) full SUSv3 conformance (none)
+T{
+.Em _POSIX_C_SOURCE
+T} (any) strict SUSv3 conformance (none)
+_
+.TE
.Sh STANDARDS
-With COMMAND_MODE set to unix2003 utility functions conform to
+With COMMAND_MODE set to anything other than legacy, utility functions conform to
.St -susv3 .
.Pp
With
-.Dv _POSIX_C_SOURCE ,
-.Dv _DARWIN_C_SOURCE ,
+.Dv _POSIX_C_SOURCE
or
-.Dv __LP64__ ,
+.Dv _DARWIN_C_SOURCE
+for i386, or when building for any other architecture,
system and library calls conform to
.St -susv3 .
.Sh BUGS
#endif
#ifndef BUILDING_VARIANT
STATIC void init_des(), init_perm(), permute();
-#endif /* BUILDING_VARIANT */
-__private_extern__ int __crypt_des_cipher(), __crypt_des_setkey();
#ifdef DEBUG
-STATIC prtab();
+#include <stdio.h>
+STATIC void prtab();
#endif
+#endif /* BUILDING_VARIANT */
+__private_extern__ int __crypt_des_cipher(), __crypt_des_setkey();
/* ==================================== */
#ifndef BUILDING_VARIANT
#ifdef DEBUG
-STATIC
+STATIC void
prtab(s, t, num_rows)
char *s;
unsigned char *t;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ctermid.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/ctermid.3,v 1.11 2003/09/08 19:57:14 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/ctermid.3,v 1.12 2007/01/09 00:27:53 imp Exp $
.\"
.Dd June 4, 1993
.Dt CTERMID 3
* 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.
static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/daemon.c,v 1.6 2003/11/10 22:01:42 ghelmer Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/daemon.c,v 1.8 2007/01/09 00:27:53 imp Exp $");
#ifndef VARIANT_PRE1050
#include <mach/mach.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
+#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include "un-namespace.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)daemon.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/gen/daemon.3,v 1.14 2003/11/10 22:04:51 ghelmer Exp $
+.\" $FreeBSD: src/lib/libc/gen/daemon.3,v 1.15 2007/01/09 00:27:53 imp Exp $
.\"
.Dd June 9, 1993
.Dt DAEMON 3
+/* $OpenBSD: dirname.c,v 1.13 2005/08/08 08:05:33 espie Exp $ */
+
/*
- * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
+ * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED ``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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if 0
-#ifndef lint
-static char rcsid[] = "$OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $";
-#endif /* not lint */
-#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/dirname.c,v 1.7 2002/12/30 01:41:14 marcel Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/dirname.c,v 1.8 2008/11/03 05:19:45 delphij Exp $");
#include <errno.h>
#include <libgen.h>
#endif
char *
-dirname(path)
- const char *path;
+dirname(const char *path)
{
- static char *bname = NULL;
+ static char *dname = NULL;
+ size_t len;
const char *endp;
- if (bname == NULL) {
- bname = (char *)malloc(MAXPATHLEN);
- if (bname == NULL)
+ if (dname == NULL) {
+ dname = (char *)malloc(MAXPATHLEN);
+ if (dname == NULL)
return(NULL);
}
/* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') {
- (void)strcpy(bname, ".");
- return(bname);
+ dname[0] = '.';
+ dname[1] = '\0';
+ return (dname);
}
- /* Strip trailing slashes */
+ /* Strip any trailing slashes */
endp = path + strlen(path) - 1;
while (endp > path && *endp == '/')
endp--;
/* Either the dir is "/" or there are no slashes */
if (endp == path) {
- (void)strcpy(bname, *endp == '/' ? "/" : ".");
- return(bname);
+ dname[0] = *endp == '/' ? '/' : '.';
+ dname[1] = '\0';
+ return (dname);
} else {
+ /* Move forward past the separating slashes */
do {
endp--;
} while (endp > path && *endp == '/');
}
- if (endp - path + 2 > MAXPATHLEN) {
+ len = endp - path + 1;
+ if (len >= MAXPATHLEN) {
errno = ENAMETOOLONG;
- return(NULL);
+ return (NULL);
}
- (void)strncpy(bname, path, endp - path + 1);
- bname[endp - path + 1] = '\0';
- return(bname);
+ memcpy(dname, path, len);
+ dname[len] = '\0';
+ return (dname);
}
+.\" $OpenBSD: dirname.3,v 1.17 2007/05/31 19:19:28 jmc Exp $
.\"
.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
-.\" 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. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
.\"
-.\" THIS SOFTWARE IS PROVIDED ``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.
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $OpenBSD: dirname.3,v 1.9 2000/04/18 03:01:25 aaron Exp $
-.\" $FreeBSD: src/lib/libc/gen/dirname.3,v 1.8 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/dirname.3,v 1.10 2008/11/03 05:19:45 delphij Exp $
.\"
-.Dd August 17, 1997
+.Dd October 12, 2006
.Dt DIRNAME 3
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn dirname
-function
-is the converse of
+function is the converse of
.Xr basename 3 ;
it returns a pointer to the parent directory of the pathname pointed to by
.Fa path .
returns a pointer to the string
.Qq \&. ,
signifying the current directory.
-.Sh RETURN VALUES
-On successful completion,
-.Fn dirname
-returns a pointer to the parent directory of
-.Fa path .
-.Pp
-If
-.Fn dirname
-fails, a null pointer is returned and the global variable
-.Va errno
-is set to indicate the error.
-.Sh ERRORS
-The following error codes may be set in
-.Va errno :
-.Bl -tag -width Er
-.It Bq Er ENAMETOOLONG
-The path component to be returned was larger than
-.Dv MAXPATHLEN .
-.El
-.Sh WARNINGS
+.Sh IMPLEMENTATION NOTES
The
.Fn dirname
function
-returns a pointer to internal static storage space that will be overwritten
-by subsequent calls (each function has its own separate storage).
+returns a pointer to internal storage space allocated on the first call
+that will be overwritten
+by subsequent calls.
.Pp
Other vendor implementations of
.Fn dirname
In legacy mode,
.Fa path
will not be changed.
+.Sh RETURN VALUES
+On successful completion,
+.Fn dirname
+returns a pointer to the parent directory of
+.Fa path .
+.Pp
+If
+.Fn dirname
+fails, a null pointer is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The following error codes may be set in
+.Va errno :
+.Bl -tag -width Er
+.It Bq Er ENAMETOOLONG
+The path component to be returned was larger than
+.Dv MAXPATHLEN .
+.El
.Sh SEE ALSO
.Xr basename 1 ,
.Xr dirname 1 ,
and
.Fx 4.2 .
.Sh AUTHORS
-.An "Todd C. Miller" Aq Todd.Miller@courtesan.com
+.An "Todd C. Miller"
-.\" $NetBSD: endutxent.3,v 1.4 2004/05/04 02:38:35 atatat Exp $
+.\" $NetBSD: endutxent.3,v 1.5 2008/04/30 13:10:50 martin Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
.El
.Ss Other extensions to the standards
The
-.Fa ut_tv
+.Fa ut_type
value may also be OR-ed with the following masks:
.Bl -tag -width XXXX -compact -offset indent
.It Dv UTMPX_AUTOFILL_MASK
-Depending on the
+Depending on the main part of
.Fa ut_type
value, other fields are automatically filled in (as specified in the
meaningful fields table above).
--- /dev/null
+.\" $NetBSD: endutxent.3,v 1.5 2008/04/30 13:10:50 martin Exp $
+.\"
+.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Thomas Klausner.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd September 26, 2002
+.Dt ENDUTXENT 3
+.Os
+.Sh NAME
+.Nm endutxent ,
+.Nm getutxent ,
+.Nm getutxid ,
+.Nm getutxline ,
+.Nm pututxline ,
+.Nm setutxent
+.Nd user accounting database functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In utmpx.h
+.Ft void
+.Fn endutxent void
+.Ft struct utmpx *
+.Fn getutxent void
+.Ft struct utmpx *
+.Fn getutxid "const struct utmpx *"
+.Ft struct utmpx *
+.Fn getutxline "const struct utmpx *"
+.Ft struct utmpx *
+.Fn pututxline "const struct utmpx *"
+.Ft void
+.Fn setutxent void
+.Sh DESCRIPTION
+These functions provide access to the
+.Xr utmpx 5
+user accounting database.
+.Pp
+.Fn getutxent
+reads the next entry from the database;
+if the database was not yet open, it also opens it.
+.Fn setutxent
+resets the database, so that the next
+.Fn getutxent
+call will get the first entry.
+.Fn endutxent
+closes the database.
+.Pp
+.Fn getutxid
+returns the next entry of the type specified in its argument's
+.Va ut_type
+field, or
+.Dv NULL
+if none is found.
+.Fn getutxline
+returns the next
+.Dv LOGIN_PROCESS
+or
+.Dv USER_PROCESS
+entry which has the same name as specified in the
+.Va ut_line
+field, or
+.Dv NULL
+if no match is found.
+.Pp
+.Fn pututxline
+adds the argument
+.Xr utmpx 5
+entry line to the accounting database, replacing a previous entry for
+the same user if it exists.
+.Ss The utmpx structure
+The
+.Nm utmpx
+structure has the following definition:
+.Pp
+.Bd -literal
+struct utmpx {
+ char ut_name[_UTX_USERSIZE]; /* login name */
+ char ut_id[_UTX_IDSIZE]; /* inittab id */
+ char ut_line[_UTX_LINESIZE]; /* tty name */
+ char ut_host[_UTX_HOSTSIZE]; /* host name */
+ uint16_t ut_session; /* session id used for windowing */
+ uint16_t ut_type; /* type of this entry */
+ pid_t ut_pid; /* process id creating the entry */
+ struct {
+ uint16_t e_termination; /* process termination signal */
+ uint16_t e_exit; /* process exit status */
+ } ut_exit;
+ struct sockaddr_storage ut_ss; /* address where entry was made from */
+ struct timeval ut_tv; /* time entry was created */
+ uint32_t ut_pad[10]; /* reserved for future use */
+};
+.Ed
+.Pp
+Valid entries for
+.Fa ut_type
+are:
+.Bl -tag -width LOGIN_PROCESSXX -compact -offset indent
+.It Dv BOOT_TIME
+Time of a system boot.
+.It Dv DEAD_PROCESS
+A session leader exited.
+.It Dv EMPTY
+No valid user accounting information.
+.It Dv INIT_PROCESS
+A process spawned by
+.Xr init 8 .
+.It Dv LOGIN_PROCESS
+The session leader of a logged-in user.
+.It Dv NEW_TIME
+Time after system clock change.
+.It Dv OLD_TIME
+Time before system clock change.
+.It Dv RUN_LVL
+Run level.
+Provided for compatibility, not used on
+.Nx .
+.It Dv USER_PROCESS
+A user process.
+.El
+.Sh RETURN VALUES
+.Fn getutxent
+returns the next entry, or
+.Dv NULL
+on failure (end of database or problems reading from the database).
+.Fn getutxid
+and
+.Fn getutxline
+return the matching structure on success, or
+.Dv NULL
+if no match was found.
+.Fn pututxline
+returns the structure that was successfully written, or
+.Dv NULL .
+.Sh SEE ALSO
+.Xr logwtmpx 3 ,
+.Xr utmpx 5
+.Sh STANDARDS
+The
+.Fn endutxent ,
+.Fn getutxent ,
+.Fn getutxid ,
+.Fn getutxline ,
+.Fn pututxline ,
+.Fn setutxent
+all conform to
+.St -p1003.1-2001
+(XSI extension), and previously to
+.St -xpg4.2 .
+The fields
+.Fa ut_user ,
+.Fa ut_id ,
+.Fa ut_line ,
+.Fa ut_pid ,
+.Fa ut_type ,
+and
+.Fa ut_tv
+conform to
+.St -p1003.1-2001
+(XSI extension), and previously to
+.St -xpg4.2 .
+.\" .Fa ut_host ,
+.\" .Fa ut_session ,
+.\" .Fa ut_exit ,
+.\" and
+.\" .Fa ut_ss
+.\" are from
+.\" SVR3/4?
+.\" .Dv RUN_LVL
+.\" is for compatibility with
+.\" what exactly?
+.\" .Sh HISTORY
+.\" The
+.\" .Nm utmpx ,
+.\" .Nm wtmpx ,
+.\" and
+.\" .Nm lastlogx
+.\" files first appeared in
+.\" SVR3? 4?
* 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.
static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.13 2002/03/29 22:43:41 markm Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.15 2008/04/03 20:36:44 imp Exp $");
#include "namespace.h"
#include <err.h>
* (NUL isn't used)
*/
static unsigned char escape[256] = {
- /* NUL SOH STX ETX EOT ENQ ACK BEL */
- 0 , 255, 255, 255, 255, 255, 255, 'a',
+ /* NUL */
+ 0, /* Unused: strings can't contain nulls */
+ /* SOH STX ETX EOT ENQ ACK BEL */
+ 255, 255, 255, 255, 255, 255, 'a',
/* BS HT NL VT NP CR SO SI */
- 'b', 't', 'n', 'v', 'f', 'r', 255, 255,
+ 'b', 0, 0, 'v', 'f', 'r', 255, 255,
/* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
255, 255, 255, 255, 255, 255, 255, 255,
/* CAN EM SUB ESC FS GS RS US */
*tp++ = *fp;
break;
case 255:
- sprintf(tp, "\\%03o", *fp);
+ sprintf((char *)tp, "\\%03o", *fp);
tp += 4;
break;
default:
}
void
-verrc(eval, code, fmt, ap)
- int eval;
- int code;
- const char *fmt;
- va_list ap;
+verrc(int eval, int code, const char *fmt, va_list ap)
{
if (_e_err_file == 0)
err_set_file((FILE *)0);
}
void
-verrx(eval, fmt, ap)
- int eval;
- const char *fmt;
- va_list ap;
+verrx(int eval, const char *fmt, va_list ap)
{
if (_e_err_file == 0)
err_set_file((FILE *)0);
}
void
-vwarn(fmt, ap)
- const char *fmt;
- va_list ap;
+vwarn(const char *fmt, va_list ap)
{
vwarnc(errno, fmt, ap);
}
}
void
-vwarnc(code, fmt, ap)
- int code;
- const char *fmt;
- va_list ap;
+vwarnc(int code, const char *fmt, va_list ap)
{
if (_e_err_file == 0)
err_set_file((FILE *)0);
}
void
-vwarnx(fmt, ap)
- const char *fmt;
- va_list ap;
+vwarnx(const char *fmt, va_list ap)
{
if (_e_err_file == 0)
err_set_file((FILE *)0);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)err.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/gen/err.3,v 1.20 2004/10/04 14:04:37 jkoshy Exp $
+.\" $FreeBSD: src/lib/libc/gen/err.3,v 1.24 2008/10/31 15:14:40 rwatson Exp $
.\"
.Dd May 20, 2008
.Dt ERR 3
If the
.Fa fmt
argument is not NULL, the
-.Xr printf 3
+.Xr printf 3 Ns
-like formatted error message is output.
The output is terminated by a newline character.
.Pp
.Fn vwarnc
functions append an error message obtained from
.Xr strerror 3
-based on a code or the global variable
+based on a supplied error code value or the global variable
.Va errno ,
preceded by another colon and space unless the
.Fa fmt
Display the current errno information string and exit:
.Bd -literal -offset indent
if ((p = malloc(size)) == NULL)
- err(1, NULL);
+ err(EX_OSERR, NULL);
if ((fd = open(file_name, O_RDONLY, 0)) == -1)
- err(1, "%s", file_name);
+ err(EX_NOINPUT, "%s", file_name);
.Ed
.Pp
Display an error message and exit:
.Bd -literal -offset indent
if (tm.tm_hour < START_TIME)
- errx(1, "too early, wait until %s", start_time_string);
+ errx(EX_DATAERR, "too early, wait until %s",
+ start_time_string);
.Ed
.Pp
Warn of an error:
warnx("%s: %s: trying the block device",
raw_device, strerror(errno));
if ((fd = open(block_device, O_RDONLY, 0)) == -1)
- err(1, "%s", block_device);
+ err(EX_OSFILE, "%s", block_device);
.Ed
.Pp
Warn of an error without using the global variable
"STREAM ioctl timeout", /* 101 - ETIME */
"Operation not supported on socket", /* 102 - EOPNOTSUPP */
"Policy not found", /* 103 - ENOPOLICY */
+ "State not recoverable", /* 104 - ENOTRECOVERABLE */
+ "Previous owner died", /* 105 - EOWNERDEAD */
};
const int sys_nerr = sizeof(sys_errlist) / sizeof(sys_errlist[0]);
+++ /dev/null
-./errno_.c
\ No newline at end of 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.
- * 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.
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/exec.c,v 1.22 2003/07/01 12:30:03 bde Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/exec.c,v 1.27 2009/12/05 18:55:16 ed Exp $");
#include "namespace.h"
#include <sys/param.h>
#include <stdarg.h>
#include "un-namespace.h"
+#include "libc_private.h"
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
+int
+_execvpe(const char *name, char * const argv[], char * const envp[]);
+
int
execl(const char *name, const char *arg, ...)
{
va_list ap;
- char **argv;
+ const char **argv;
int n;
va_start(ap, arg);
}
va_start(ap, arg);
n = 1;
- argv[0] = (char *)arg;
+ argv[0] = arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
va_end(ap);
- return (_execve(name, argv, environ));
+ return (_execve(name, __DECONST(char **, argv), environ));
}
int
execle(const char *name, const char *arg, ...)
{
va_list ap;
- char **argv, **envp;
+ const char **argv;
+ char **envp;
int n;
va_start(ap, arg);
}
va_start(ap, arg);
n = 1;
- argv[0] = (char *)arg;
+ argv[0] = arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
envp = va_arg(ap, char **);
va_end(ap);
- return (_execve(name, argv, envp));
+ return (_execve(name, __DECONST(char **, argv), envp));
}
int
execlp(const char *name, const char *arg, ...)
{
va_list ap;
- char **argv;
+ const char **argv;
int n;
va_start(ap, arg);
}
va_start(ap, arg);
n = 1;
- argv[0] = (char *)arg;
+ argv[0] = arg;
while ((argv[n] = va_arg(ap, char *)) != NULL)
n++;
va_end(ap);
- return (execvp(name, argv));
+ return (execvp(name, __DECONST(char **, argv)));
}
int
int
execvp(const char *name, char * const *argv)
{
- const char *path;
-
- /* Get the path we're searching. */
- if ((path = getenv("PATH")) == NULL)
- path = _PATH_DEFPATH;
-
- return (execvP(name, path, argv));
+ return (_execvpe(name, argv, environ));
}
-int
-execvP(name, path, argv)
- const char *name;
- const char *path;
- char * const *argv;
+static int
+execvPe(const char *name, const char *path, char * const *argv,
+ char * const *envp)
{
- char **memp;
- int cnt, lp, ln;
- char *p;
+ const char **memp;
+ size_t cnt, lp, ln;
int eacces, save_errno;
- char *bp, *cur, buf[MAXPATHLEN];
+ char *cur, buf[MAXPATHLEN];
+ const char *p, *bp;
struct stat sb;
eacces = 0;
/* If it's an absolute or relative path name, it's easy. */
if (index(name, '/')) {
- bp = (char *)name;
+ bp = name;
cur = NULL;
goto retry;
}
bcopy(name, buf + lp + 1, ln);
buf[lp + ln + 1] = '\0';
-retry: (void)_execve(bp, argv, environ);
+retry: (void)_execve(bp, argv, envp);
switch (errno) {
case E2BIG:
goto done;
memp[0] = "sh";
memp[1] = bp;
bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
- (void)_execve(_PATH_BSHELL, memp, environ);
+ (void)_execve(_PATH_BSHELL,
+ __DECONST(char **, memp), envp);
goto done;
case ENOMEM:
goto done;
done:
return (-1);
}
+
+int
+execvP(const char *name, const char *path, char * const argv[])
+{
+ return execvPe(name, path, argv, environ);
+}
+
+__private_extern__ int
+_execvpe(const char *name, char * const argv[], char * const envp[])
+{
+ const char *path;
+
+ /* Get the path we're searching. */
+ if ((path = getenv("PATH")) == NULL)
+ path = _PATH_DEFPATH;
+
+ return (execvPe(name, path, argv, envp));
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)exec.3 8.3 (Berkeley) 1/24/94
-.\" $FreeBSD: src/lib/libc/gen/exec.3,v 1.23 2003/09/10 19:24:32 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/exec.3,v 1.28 2008/06/23 05:22:06 ed Exp $
.\"
.Dd January 24, 1994
.Dt EXEC 3
search path is the path specified in the environment by
.Dq Ev PATH
variable.
-If this variable isn't specified,
+If this variable is not specified,
the default path is set according to the
.Dv _PATH_DEFPATH
definition in
according to whether at least one file with suitable execute permissions
was found.
.Pp
-If the header of a file isn't recognized (the attempted
+If the header of a file is not recognized (the attempted
.Fn execve
returned
.Er ENOEXEC ) ,
.It Pa /bin/sh
The shell.
.El
-.Sh ERRORS
-The
-.Fn execl ,
-.Fn execle ,
-.Fn execlp ,
-.Fn execvp ,
-and
-.Fn execvP
-functions
-may fail and set
-.Va errno
-for any of the errors specified for the library functions
-.Xr execve 2
-and
-.Xr malloc 3 .
-.Pp
-The
-.Fn execv
-function may fail and set
-.Va errno
-for any of the errors specified for the library function
-.Xr execve 2 .
-.Sh SEE ALSO
-.Xr sh 1 ,
-.Xr execve 2 ,
-.Xr fork 2 ,
-.Xr ptrace 2 ,
-.Xr environ 7
.Sh COMPATIBILITY
Historically, the default path for the
.Fn execlp
.Tn POSIX
standard.
.Pp
-Traditionally, the
+Traditionally, the functions
.Fn execlp
and
.Fn execvp
-functions ignored all errors except for the ones described above and
+ignored all errors except for the ones described above and
.Er ETXTBSY ,
upon which they retried after sleeping for several seconds, and
.Er ENOMEM
.Er EIO .
The behaviour was changed to match the behaviour of
.Xr sh 1 .
+.Sh ERRORS
+The
+.Fn execl ,
+.Fn execle ,
+.Fn execlp ,
+.Fn execvp ,
+and
+.Fn execvP
+functions
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr execve 2
+and
+.Xr malloc 3 .
+.Pp
+The
+.Fn execv
+function may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr execve 2 .
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr execve 2 ,
+.Xr fork 2 ,
+.Xr ptrace 2 ,
+.Xr environ 7
.Sh STANDARDS
The
.Fn execl ,
#define _EXECINFO_H_ 1
#include <sys/cdefs.h>
+#include <Availability.h>
__BEGIN_DECLS
-int backtrace(void**,int);
-char** backtrace_symbols(void* const*,int);
-void backtrace_symbols_fd(void* const*,int,int);
+int backtrace(void**,int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+char** backtrace_symbols(void* const*,int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+void backtrace_symbols_fd(void* const*,int,int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
__END_DECLS
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/fmtmsg.c,v 1.5 2003/05/01 19:03:13 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/fmtmsg.c,v 1.6 2009/11/08 14:02:54 brueffer Exp $");
#include <fmtmsg.h>
#include <stdio.h>
size += strlen(sevname);
if (text != MM_NULLTXT)
size += strlen(text);
- if (text != MM_NULLACT)
+ if (act != MM_NULLACT)
size += strlen(act);
if (tag != MM_NULLTAG)
size += strlen(tag);
* 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.
static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.16 2004/07/29 03:13:10 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.19 2010/04/16 22:29:24 jilles Exp $");
#include "xlocale_private.h"
#define EOS '\0'
-#if __DARWIN_UNIX03
#define RETURN_ERROR 2 /* neither 0 or FNM_NOMATCH */
-#endif /* __DARWIN_UNIX03 */
#define RANGE_MATCH 1
#define RANGE_NOMATCH 0
#define RANGE_ERROR (-1)
+#define RECURSION_MAX 64
+
__private_extern__ int rangematch(const char *, wchar_t, const char *, int, char **, char **, mbstate_t *, mbstate_t *, locale_t);
-static int fnmatch1(const char *, const char *, int, mbstate_t, mbstate_t, locale_t);
+static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
+ mbstate_t, locale_t, int);
int
fnmatch(pattern, string, flags)
int flags;
{
static const mbstate_t initial;
-
- return (fnmatch1(pattern, string, flags, initial, initial, __current_locale()));
+#if __DARWIN_UNIX03
+ return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX));
+#else /* !__DARWIN_UNIX03 */
+ return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX) != 0 ? FNM_NOMATCH : 0);
+#endif /* __DARWIN_UNIX03 */
}
static int
-fnmatch1(pattern, string, flags, patmbs, strmbs, loc)
- const char *pattern, *string;
+fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs, loc, recursion)
+ const char *pattern, *string, *stringstart;
int flags;
mbstate_t patmbs, strmbs;
locale_t loc;
+ int recursion;
{
- const char *stringstart;
char *newp, *news;
char c;
wchar_t pc, sc;
size_t pclen, sclen;
- for (stringstart = string;;) {
+ if (recursion-- <= 0)
+ return RETURN_ERROR;
+ for (;;) {
pclen = mbrtowc_l(&pc, pattern, MB_LEN_MAX, &patmbs, loc);
if (pclen == (size_t)-1 || pclen == (size_t)-2)
#if __DARWIN_UNIX03
}
/* General case, use recursion. */
+ int ret;
while (sc != EOS) {
- if (!fnmatch1(pattern, string,
- flags & ~FNM_PERIOD, patmbs, strmbs, loc))
- return (0);
+ if ((ret = fnmatch1(pattern, string, stringstart,
+ flags, patmbs, strmbs, loc, recursion)) != FNM_NOMATCH)
+ return (ret);
sclen = mbrtowc_l(&sc, string, MB_LEN_MAX,
&strmbs, loc);
if (sclen == (size_t)-1 ||
} else if (*pattern == '\0') {
return (RANGE_ERROR);
} else if (*pattern == '/' && (flags & FNM_PATHNAME)) {
- pattern++;
return (RANGE_NOMATCH);
} else if (*pattern == '\\' && !(flags & FNM_NOESCAPE))
pattern++;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fnmatch.3 8.3 (Berkeley) 4/28/95
-.\" $FreeBSD: src/lib/libc/gen/fnmatch.3,v 1.18 2004/07/18 06:56:40 tjr Exp $
+.\" $FreeBSD: src/lib/libc/gen/fnmatch.3,v 1.19 2007/01/09 00:27:53 imp Exp $
.\"
.Dd July 18, 2004
.Dt FNMATCH 3
function returns zero if
.Fa string
matches the pattern specified by
+.Fa pattern .
+It returns the value
+.Dv FNM_NOMATCH
+if no match is found.
+Otherwise, another non-zero value is returned on error.
+.Sh LEGACY RETURN VALUES
+The
+.Fn fnmatch
+function returns zero if
+.Fa string
+matches the pattern specified by
.Fa pattern ;
otherwise, it returns the value
.Dv FNM_NOMATCH .
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/gen/ftok.3,v 1.16 2004/07/02 23:52:10 ru Exp $
-.Dd June 24, 1994
+.\" $FreeBSD: src/lib/libc/gen/ftok.3,v 1.17 2009/07/13 12:53:43 trasz Exp $
+.Dd July 9, 2009
.Os
.Dt FTOK 3
.Sh NAME
The
.Fn ftok
function attempts to create a unique key suitable for use with the
-.Xr msgget 3 ,
.Xr semget 2 ,
and
.Xr shmget 2
.Sh SEE ALSO
.Xr semget 2 ,
.Xr shmget 2 ,
-.Xr msgget 3 ,
.Xr compat 5
.Sh HISTORY
The
{
register FTSENT *p, *root;
register int nitems;
- FTSENT *parent, *tmp;
+ FTSENT *parent, *tmp = NULL;
int len;
/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
/* Move to the next node on this level. */
next: tmp = p;
if (p = p->fts_link) {
- free(tmp);
-
/*
* If reached the top, return to the original directory, and
* load the paths for the next root.
return (NULL);
}
fts_load(sp, p);
+ free(tmp);
return (sp->fts_cur = p);
}
* ignore. If followed, get a file descriptor so we can
* get back if necessary.
*/
- if (p->fts_instr == FTS_SKIP)
+ if (p->fts_instr == FTS_SKIP) {
+ free(tmp);
goto next;
+ }
if (p->fts_instr == FTS_FOLLOW) {
p->fts_info = fts_stat(sp, p, 1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR))
p->fts_instr = FTS_NOINSTR;
}
+ free(tmp);
name: t = sp->fts_path + NAPPEND(p->fts_parent);
*t++ = '/';
memmove(t, p->fts_name, p->fts_namelen + 1);
DIR *dirp;
void *adjaddr;
int cderrno, descend, len, level, maxlen, dostat, oflag, saved_errno;
- char *cp;
+ char *cp = NULL;
/* Set current node pointer. */
cur = sp->fts_cur;
#include <string.h>
#include <pthread.h>
-static bool def_unix03 = false;
/* Catastrophic errors only, including "out of memory" */
static bool parse_error = false;
static bool bootstrapping = false;
* 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.
static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getcap.c,v 1.19 2003/01/02 10:19:43 thomas Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getcap.c,v 1.23 2009/11/25 04:45:45 wollman Exp $");
#include "xlocale_private.h"
{
DB *capdbp;
char *r_end, *rp, **db_p;
- int myfd, eof, foundit, retval, clen;
+ int myfd, eof, foundit, retval;
char *record, *cbuf;
int tc_not_resolved;
char pbuf[_POSIX_PATH_MAX];
return (retval);
}
/* save the data; close frees it */
- clen = strlen(record);
- cbuf = malloc(clen + 1);
- memcpy(cbuf, record, clen + 1);
+ cbuf = strdup(record);
if (capdbp->close(capdbp) < 0) {
free(cbuf);
return (-2);
}
- *len = clen;
+ if (cbuf == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ *len = strlen(cbuf);
*cap = cbuf;
return (retval);
} else {
cgetnext(char **bp, char **db_array)
{
size_t len;
- int done, hadreaderr, i, savederrno, status;
+ int done, hadreaderr, savederrno, status;
char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
u_int dummy;
locale_t loc = __current_locale();
(void)cgetclose();
return (-1);
}
- for(;;) {
+ for (;;) {
if (toprec && !gottoprec) {
gottoprec = 1;
line = toprec;
/*
* Line points to a name line.
*/
- i = 0;
done = 0;
np = nbuf;
for (;;) {
--- /dev/null
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Casey Leedom of Lawrence Livermore National Laboratory.
+ *
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getcap.c,v 1.23 2009/11/25 04:45:45 wollman Exp $");
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+
+#define BFRAG 1024
+#define BSIZE 1024
+#define ESC ('[' & 037) /* ASCII ESC */
+#define MAX_RECURSION 32 /* maximum getent recursion */
+#define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */
+
+#define RECOK (char)0
+#define TCERR (char)1
+#define SHADOW (char)2
+
+static size_t topreclen; /* toprec length */
+static char *toprec; /* Additional record specified by cgetset() */
+static int gottoprec; /* Flag indicating retrieval of toprecord */
+
+static int cdbget(DB *, char **, const char *);
+static int getent(char **, u_int *, char **, int, const char *, int, char *);
+static int nfcmp(char *, char *);
+
+/*
+ * Cgetset() allows the addition of a user specified buffer to be added
+ * to the database array, in effect "pushing" the buffer on top of the
+ * virtual database. 0 is returned on success, -1 on failure.
+ */
+int
+cgetset(const char *ent)
+{
+ if (ent == NULL) {
+ if (toprec)
+ free(toprec);
+ toprec = NULL;
+ topreclen = 0;
+ return (0);
+ }
+ topreclen = strlen(ent);
+ if ((toprec = malloc (topreclen + 1)) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ gottoprec = 0;
+ (void)strcpy(toprec, ent);
+ return (0);
+}
+
+/*
+ * Cgetcap searches the capability record buf for the capability cap with
+ * type `type'. A pointer to the value of cap is returned on success, NULL
+ * if the requested capability couldn't be found.
+ *
+ * Specifying a type of ':' means that nothing should follow cap (:cap:).
+ * In this case a pointer to the terminating ':' or NUL will be returned if
+ * cap is found.
+ *
+ * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
+ * return NULL.
+ */
+char *
+cgetcap(char *buf, const char *cap, int type)
+{
+ char *bp;
+ const char *cp;
+
+ bp = buf;
+ for (;;) {
+ /*
+ * Skip past the current capability field - it's either the
+ * name field if this is the first time through the loop, or
+ * the remainder of a field whose name failed to match cap.
+ */
+ for (;;)
+ if (*bp == '\0')
+ return (NULL);
+ else
+ if (*bp++ == ':')
+ break;
+
+ /*
+ * Try to match (cap, type) in buf.
+ */
+ for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
+ continue;
+ if (*cp != '\0')
+ continue;
+ if (*bp == '@')
+ return (NULL);
+ if (type == ':') {
+ if (*bp != '\0' && *bp != ':')
+ continue;
+ return(bp);
+ }
+ if (*bp != type)
+ continue;
+ bp++;
+ return (*bp == '@' ? NULL : bp);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Cgetent extracts the capability record name from the NULL terminated file
+ * array db_array and returns a pointer to a malloc'd copy of it in buf.
+ * Buf must be retained through all subsequent calls to cgetcap, cgetnum,
+ * cgetflag, and cgetstr, but may then be free'd. 0 is returned on success,
+ * -1 if the requested record couldn't be found, -2 if a system error was
+ * encountered (couldn't open/read a file, etc.), and -3 if a potential
+ * reference loop is detected.
+ */
+int
+cgetent(char **buf, char **db_array, const char *name)
+{
+ u_int dummy;
+
+ return (getent(buf, &dummy, db_array, -1, name, 0, NULL));
+}
+
+/*
+ * Getent implements the functions of cgetent. If fd is non-negative,
+ * *db_array has already been opened and fd is the open file descriptor. We
+ * do this to save time and avoid using up file descriptors for tc=
+ * recursions.
+ *
+ * Getent returns the same success/failure codes as cgetent. On success, a
+ * pointer to a malloc'ed capability record with all tc= capabilities fully
+ * expanded and its length (not including trailing ASCII NUL) are left in
+ * *cap and *len.
+ *
+ * Basic algorithm:
+ * + Allocate memory incrementally as needed in chunks of size BFRAG
+ * for capability buffer.
+ * + Recurse for each tc=name and interpolate result. Stop when all
+ * names interpolated, a name can't be found, or depth exceeds
+ * MAX_RECURSION.
+ */
+static int
+getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
+ int depth, char *nfield)
+{
+ DB *capdbp;
+ char *r_end, *rp, **db_p;
+ int myfd, eof, foundit, retval;
+ char *record, *cbuf;
+ int tc_not_resolved;
+ char pbuf[_POSIX_PATH_MAX];
+
+ /*
+ * Return with ``loop detected'' error if we've recursed more than
+ * MAX_RECURSION times.
+ */
+ if (depth > MAX_RECURSION)
+ return (-3);
+
+ /*
+ * Check if we have a top record from cgetset().
+ */
+ if (depth == 0 && toprec != NULL && cgetmatch(toprec, name) == 0) {
+ if ((record = malloc (topreclen + BFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ (void)strcpy(record, toprec);
+ myfd = 0;
+ db_p = db_array;
+ rp = record + topreclen + 1;
+ r_end = rp + BFRAG;
+ goto tc_exp;
+ }
+ /*
+ * Allocate first chunk of memory.
+ */
+ if ((record = malloc(BFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ r_end = record + BFRAG;
+ foundit = 0;
+ /*
+ * Loop through database array until finding the record.
+ */
+
+ for (db_p = db_array; *db_p != NULL; db_p++) {
+ eof = 0;
+
+ /*
+ * Open database if not already open.
+ */
+
+ if (fd >= 0) {
+ (void)lseek(fd, (off_t)0, SEEK_SET);
+ myfd = 0;
+ } else {
+ (void)snprintf(pbuf, sizeof(pbuf), "%s.db", *db_p);
+ if ((capdbp = dbopen(pbuf, O_RDONLY, 0, DB_HASH, 0))
+ != NULL) {
+ free(record);
+ retval = cdbget(capdbp, &record, name);
+ if (retval < 0) {
+ /* no record available */
+ (void)capdbp->close(capdbp);
+ return (retval);
+ }
+ /* save the data; close frees it */
+ cbuf = strdup(record);
+ if (capdbp->close(capdbp) < 0) {
+ free(cbuf);
+ return (-2);
+ }
+ if (cbuf == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ *len = strlen(cbuf);
+ *cap = cbuf;
+ return (retval);
+ } else {
+ fd = _open(*db_p, O_RDONLY, 0);
+ if (fd < 0)
+ continue;
+ myfd = 1;
+ }
+ }
+ /*
+ * Find the requested capability record ...
+ */
+ {
+ char buf[BUFSIZ];
+ char *b_end, *bp;
+ int c;
+
+ /*
+ * Loop invariants:
+ * There is always room for one more character in record.
+ * R_end always points just past end of record.
+ * Rp always points just past last character in record.
+ * B_end always points just past last character in buf.
+ * Bp always points at next character in buf.
+ */
+ b_end = buf;
+ bp = buf;
+ for (;;) {
+
+ /*
+ * Read in a line implementing (\, newline)
+ * line continuation.
+ */
+ rp = record;
+ for (;;) {
+ if (bp >= b_end) {
+ int n;
+
+ n = _read(fd, buf, sizeof(buf));
+ if (n <= 0) {
+ if (myfd)
+ (void)_close(fd);
+ if (n < 0) {
+ free(record);
+ return (-2);
+ } else {
+ fd = -1;
+ eof = 1;
+ break;
+ }
+ }
+ b_end = buf+n;
+ bp = buf;
+ }
+
+ c = *bp++;
+ if (c == '\n') {
+ if (rp > record && *(rp-1) == '\\') {
+ rp--;
+ continue;
+ } else
+ break;
+ }
+ *rp++ = c;
+
+ /*
+ * Enforce loop invariant: if no room
+ * left in record buffer, try to get
+ * some more.
+ */
+ if (rp >= r_end) {
+ u_int pos;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + BFRAG;
+ record = reallocf(record, newsize);
+ if (record == NULL) {
+ errno = ENOMEM;
+ if (myfd)
+ (void)_close(fd);
+ return (-2);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ }
+ }
+ /* loop invariant let's us do this */
+ *rp++ = '\0';
+
+ /*
+ * If encountered eof check next file.
+ */
+ if (eof)
+ break;
+
+ /*
+ * Toss blank lines and comments.
+ */
+ if (*record == '\0' || *record == '#')
+ continue;
+
+ /*
+ * See if this is the record we want ...
+ */
+ if (cgetmatch(record, name) == 0) {
+ if (nfield == NULL || !nfcmp(nfield, record)) {
+ foundit = 1;
+ break; /* found it! */
+ }
+ }
+ }
+ }
+ if (foundit)
+ break;
+ }
+
+ if (!foundit) {
+ free(record);
+ return (-1);
+ }
+
+ /*
+ * Got the capability record, but now we have to expand all tc=name
+ * references in it ...
+ */
+tc_exp: {
+ char *newicap, *s;
+ int newilen;
+ u_int ilen;
+ int diff, iret, tclen;
+ char *icap, *scan, *tc, *tcstart, *tcend;
+
+ /*
+ * Loop invariants:
+ * There is room for one more character in record.
+ * R_end points just past end of record.
+ * Rp points just past last character in record.
+ * Scan points at remainder of record that needs to be
+ * scanned for tc=name constructs.
+ */
+ scan = record;
+ tc_not_resolved = 0;
+ for (;;) {
+ if ((tc = cgetcap(scan, "tc", '=')) == NULL)
+ break;
+
+ /*
+ * Find end of tc=name and stomp on the trailing `:'
+ * (if present) so we can use it to call ourselves.
+ */
+ s = tc;
+ for (;;)
+ if (*s == '\0')
+ break;
+ else
+ if (*s++ == ':') {
+ *(s - 1) = '\0';
+ break;
+ }
+ tcstart = tc - 3;
+ tclen = s - tcstart;
+ tcend = s;
+
+ iret = getent(&icap, &ilen, db_p, fd, tc, depth+1,
+ NULL);
+ newicap = icap; /* Put into a register. */
+ newilen = ilen;
+ if (iret != 0) {
+ /* an error */
+ if (iret < -1) {
+ if (myfd)
+ (void)_close(fd);
+ free(record);
+ return (iret);
+ }
+ if (iret == 1)
+ tc_not_resolved = 1;
+ /* couldn't resolve tc */
+ if (iret == -1) {
+ *(s - 1) = ':';
+ scan = s - 1;
+ tc_not_resolved = 1;
+ continue;
+
+ }
+ }
+ /* not interested in name field of tc'ed record */
+ s = newicap;
+ for (;;)
+ if (*s == '\0')
+ break;
+ else
+ if (*s++ == ':')
+ break;
+ newilen -= s - newicap;
+ newicap = s;
+
+ /* make sure interpolated record is `:'-terminated */
+ s += newilen;
+ if (*(s-1) != ':') {
+ *s = ':'; /* overwrite NUL with : */
+ newilen++;
+ }
+
+ /*
+ * Make sure there's enough room to insert the
+ * new record.
+ */
+ diff = newilen - tclen;
+ if (diff >= r_end - rp) {
+ u_int pos, tcpos, tcposend;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + diff + BFRAG;
+ tcpos = tcstart - record;
+ tcposend = tcend - record;
+ record = reallocf(record, newsize);
+ if (record == NULL) {
+ errno = ENOMEM;
+ if (myfd)
+ (void)_close(fd);
+ free(icap);
+ return (-2);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ tcstart = record + tcpos;
+ tcend = record + tcposend;
+ }
+
+ /*
+ * Insert tc'ed record into our record.
+ */
+ s = tcstart + newilen;
+ bcopy(tcend, s, rp - tcend);
+ bcopy(newicap, tcstart, newilen);
+ rp += diff;
+ free(icap);
+
+ /*
+ * Start scan on `:' so next cgetcap works properly
+ * (cgetcap always skips first field).
+ */
+ scan = s-1;
+ }
+
+ }
+ /*
+ * Close file (if we opened it), give back any extra memory, and
+ * return capability, length and success.
+ */
+ if (myfd)
+ (void)_close(fd);
+ *len = rp - record - 1; /* don't count NUL */
+ if (r_end > rp)
+ if ((record =
+ reallocf(record, (size_t)(rp - record))) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+
+ *cap = record;
+ if (tc_not_resolved)
+ return (1);
+ return (0);
+}
+
+static int
+cdbget(DB *capdbp, char **bp, const char *name)
+{
+ DBT key, data;
+ char *namebuf;
+
+ namebuf = strdup(name);
+ if (namebuf == NULL)
+ return (-2);
+ key.data = namebuf;
+ key.size = strlen(namebuf);
+
+ for (;;) {
+ /* Get the reference. */
+ switch(capdbp->get(capdbp, &key, &data, 0)) {
+ case -1:
+ free(namebuf);
+ return (-2);
+ case 1:
+ free(namebuf);
+ return (-1);
+ }
+
+ /* If not an index to another record, leave. */
+ if (((char *)data.data)[0] != SHADOW)
+ break;
+
+ key.data = (char *)data.data + 1;
+ key.size = data.size - 1;
+ }
+
+ *bp = (char *)data.data + 1;
+ free(namebuf);
+ return (((char *)(data.data))[0] == TCERR ? 1 : 0);
+}
+
+/*
+ * Cgetmatch will return 0 if name is one of the names of the capability
+ * record buf, -1 if not.
+ */
+int
+cgetmatch(const char *buf, const char *name)
+{
+ const char *np, *bp;
+
+ if (name == NULL || *name == '\0')
+ return -1;
+
+ /*
+ * Start search at beginning of record.
+ */
+ bp = buf;
+ for (;;) {
+ /*
+ * Try to match a record name.
+ */
+ np = name;
+ for (;;)
+ if (*np == '\0')
+ if (*bp == '|' || *bp == ':' || *bp == '\0')
+ return (0);
+ else
+ break;
+ else
+ if (*bp++ != *np++)
+ break;
+
+ /*
+ * Match failed, skip to next name in record.
+ */
+ bp--; /* a '|' or ':' may have stopped the match */
+ for (;;)
+ if (*bp == '\0' || *bp == ':')
+ return (-1); /* match failed totally */
+ else
+ if (*bp++ == '|')
+ break; /* found next name */
+ }
+}
+
+
+
+
+
+int
+cgetfirst(char **buf, char **db_array)
+{
+ (void)cgetclose();
+ return (cgetnext(buf, db_array));
+}
+
+static FILE *pfp;
+static int slash;
+static char **dbp;
+
+int
+cgetclose(void)
+{
+ if (pfp != NULL) {
+ (void)fclose(pfp);
+ pfp = NULL;
+ }
+ dbp = NULL;
+ gottoprec = 0;
+ slash = 0;
+ return(0);
+}
+
+/*
+ * Cgetnext() gets either the first or next entry in the logical database
+ * specified by db_array. It returns 0 upon completion of the database, 1
+ * upon returning an entry with more remaining, and -1 if an error occurs.
+ */
+int
+cgetnext(char **bp, char **db_array)
+{
+ size_t len;
+ int done, hadreaderr, savederrno, status;
+ char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
+ u_int dummy;
+
+ if (dbp == NULL)
+ dbp = db_array;
+
+ if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL) {
+ (void)cgetclose();
+ return (-1);
+ }
+ for (;;) {
+ if (toprec && !gottoprec) {
+ gottoprec = 1;
+ line = toprec;
+ } else {
+ line = fgetln(pfp, &len);
+ if (line == NULL && pfp) {
+ hadreaderr = ferror(pfp);
+ if (hadreaderr)
+ savederrno = errno;
+ fclose(pfp);
+ pfp = NULL;
+ if (hadreaderr) {
+ cgetclose();
+ errno = savederrno;
+ return (-1);
+ } else {
+ if (*++dbp == NULL) {
+ (void)cgetclose();
+ return (0);
+ } else if ((pfp =
+ fopen(*dbp, "r")) == NULL) {
+ (void)cgetclose();
+ return (-1);
+ } else
+ continue;
+ }
+ } else
+ line[len - 1] = '\0';
+ if (len == 1) {
+ slash = 0;
+ continue;
+ }
+ if (isspace((unsigned char)*line) ||
+ *line == ':' || *line == '#' || slash) {
+ if (line[len - 2] == '\\')
+ slash = 1;
+ else
+ slash = 0;
+ continue;
+ }
+ if (line[len - 2] == '\\')
+ slash = 1;
+ else
+ slash = 0;
+ }
+
+
+ /*
+ * Line points to a name line.
+ */
+ done = 0;
+ np = nbuf;
+ for (;;) {
+ for (cp = line; *cp != '\0'; cp++) {
+ if (*cp == ':') {
+ *np++ = ':';
+ done = 1;
+ break;
+ }
+ if (*cp == '\\')
+ break;
+ *np++ = *cp;
+ }
+ if (done) {
+ *np = '\0';
+ break;
+ } else { /* name field extends beyond the line */
+ line = fgetln(pfp, &len);
+ if (line == NULL && pfp) {
+ /* Name extends beyond the EOF! */
+ hadreaderr = ferror(pfp);
+ if (hadreaderr)
+ savederrno = errno;
+ fclose(pfp);
+ pfp = NULL;
+ if (hadreaderr) {
+ cgetclose();
+ errno = savederrno;
+ return (-1);
+ } else {
+ cgetclose();
+ return (-1);
+ }
+ } else
+ line[len - 1] = '\0';
+ }
+ }
+ rp = buf;
+ for(cp = nbuf; *cp != '\0'; cp++)
+ if (*cp == '|' || *cp == ':')
+ break;
+ else
+ *rp++ = *cp;
+
+ *rp = '\0';
+ /*
+ * XXX
+ * Last argument of getent here should be nbuf if we want true
+ * sequential access in the case of duplicates.
+ * With NULL, getent will return the first entry found
+ * rather than the duplicate entry record. This is a
+ * matter of semantics that should be resolved.
+ */
+ status = getent(bp, &dummy, db_array, -1, buf, 0, NULL);
+ if (status == -2 || status == -3)
+ (void)cgetclose();
+
+ return (status + 1);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Cgetstr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf. A pointer to a decoded, NUL
+ * terminated, malloc'd copy of the string is returned in the char *
+ * pointed to by str. The length of the string not including the trailing
+ * NUL is returned on success, -1 if the requested string capability
+ * couldn't be found, -2 if a system error was encountered (storage
+ * allocation failure).
+ */
+int
+cgetstr(char *buf, const char *cap, char **str)
+{
+ u_int m_room;
+ char *bp, *mp;
+ int len;
+ char *mem;
+
+ /*
+ * Find string capability cap
+ */
+ bp = cgetcap(buf, cap, '=');
+ if (bp == NULL)
+ return (-1);
+
+ /*
+ * Conversion / storage allocation loop ... Allocate memory in
+ * chunks SFRAG in size.
+ */
+ if ((mem = malloc(SFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2); /* couldn't even allocate the first fragment */
+ }
+ m_room = SFRAG;
+ mp = mem;
+
+ while (*bp != ':' && *bp != '\0') {
+ /*
+ * Loop invariants:
+ * There is always room for one more character in mem.
+ * Mp always points just past last character in mem.
+ * Bp always points at next character in buf.
+ */
+ if (*bp == '^') {
+ bp++;
+ if (*bp == ':' || *bp == '\0')
+ break; /* drop unfinished escape */
+ if (*bp == '?') {
+ *mp++ = '\177';
+ bp++;
+ } else
+ *mp++ = *bp++ & 037;
+ } else if (*bp == '\\') {
+ bp++;
+ if (*bp == ':' || *bp == '\0')
+ break; /* drop unfinished escape */
+ if ('0' <= *bp && *bp <= '7') {
+ int n, i;
+
+ n = 0;
+ i = 3; /* maximum of three octal digits */
+ do {
+ n = n * 8 + (*bp++ - '0');
+ } while (--i && '0' <= *bp && *bp <= '7');
+ *mp++ = n;
+ }
+ else switch (*bp++) {
+ case 'b': case 'B':
+ *mp++ = '\b';
+ break;
+ case 't': case 'T':
+ *mp++ = '\t';
+ break;
+ case 'n': case 'N':
+ *mp++ = '\n';
+ break;
+ case 'f': case 'F':
+ *mp++ = '\f';
+ break;
+ case 'r': case 'R':
+ *mp++ = '\r';
+ break;
+ case 'e': case 'E':
+ *mp++ = ESC;
+ break;
+ case 'c': case 'C':
+ *mp++ = ':';
+ break;
+ default:
+ /*
+ * Catches '\', '^', and
+ * everything else.
+ */
+ *mp++ = *(bp-1);
+ break;
+ }
+ } else
+ *mp++ = *bp++;
+ m_room--;
+
+ /*
+ * Enforce loop invariant: if no room left in current
+ * buffer, try to get some more.
+ */
+ if (m_room == 0) {
+ size_t size = mp - mem;
+
+ if ((mem = reallocf(mem, size + SFRAG)) == NULL)
+ return (-2);
+ m_room = SFRAG;
+ mp = mem + size;
+ }
+ }
+ *mp++ = '\0'; /* loop invariant let's us do this */
+ m_room--;
+ len = mp - mem - 1;
+
+ /*
+ * Give back any extra memory and return value and success.
+ */
+ if (m_room != 0)
+ if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
+ return (-2);
+ *str = mem;
+ return (len);
+}
+
+/*
+ * Cgetustr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf. The difference between cgetustr()
+ * and cgetstr() is that cgetustr does not decode escapes but rather treats
+ * all characters literally. A pointer to a NUL terminated malloc'd
+ * copy of the string is returned in the char pointed to by str. The
+ * length of the string not including the trailing NUL is returned on success,
+ * -1 if the requested string capability couldn't be found, -2 if a system
+ * error was encountered (storage allocation failure).
+ */
+int
+cgetustr(char *buf, const char *cap, char **str)
+{
+ u_int m_room;
+ char *bp, *mp;
+ int len;
+ char *mem;
+
+ /*
+ * Find string capability cap
+ */
+ if ((bp = cgetcap(buf, cap, '=')) == NULL)
+ return (-1);
+
+ /*
+ * Conversion / storage allocation loop ... Allocate memory in
+ * chunks SFRAG in size.
+ */
+ if ((mem = malloc(SFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2); /* couldn't even allocate the first fragment */
+ }
+ m_room = SFRAG;
+ mp = mem;
+
+ while (*bp != ':' && *bp != '\0') {
+ /*
+ * Loop invariants:
+ * There is always room for one more character in mem.
+ * Mp always points just past last character in mem.
+ * Bp always points at next character in buf.
+ */
+ *mp++ = *bp++;
+ m_room--;
+
+ /*
+ * Enforce loop invariant: if no room left in current
+ * buffer, try to get some more.
+ */
+ if (m_room == 0) {
+ size_t size = mp - mem;
+
+ if ((mem = reallocf(mem, size + SFRAG)) == NULL)
+ return (-2);
+ m_room = SFRAG;
+ mp = mem + size;
+ }
+ }
+ *mp++ = '\0'; /* loop invariant let's us do this */
+ m_room--;
+ len = mp - mem - 1;
+
+ /*
+ * Give back any extra memory and return value and success.
+ */
+ if (m_room != 0)
+ if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
+ return (-2);
+ *str = mem;
+ return (len);
+}
+
+/*
+ * Cgetnum retrieves the value of the numeric capability cap from the
+ * capability record pointed to by buf. The numeric value is returned in
+ * the long pointed to by num. 0 is returned on success, -1 if the requested
+ * numeric capability couldn't be found.
+ */
+int
+cgetnum(char *buf, const char *cap, long *num)
+{
+ long n;
+ int base, digit;
+ char *bp;
+
+ /*
+ * Find numeric capability cap
+ */
+ bp = cgetcap(buf, cap, '#');
+ if (bp == NULL)
+ return (-1);
+
+ /*
+ * Look at value and determine numeric base:
+ * 0x... or 0X... hexadecimal,
+ * else 0... octal,
+ * else decimal.
+ */
+ if (*bp == '0') {
+ bp++;
+ if (*bp == 'x' || *bp == 'X') {
+ bp++;
+ base = 16;
+ } else
+ base = 8;
+ } else
+ base = 10;
+
+ /*
+ * Conversion loop ...
+ */
+ n = 0;
+ for (;;) {
+ if ('0' <= *bp && *bp <= '9')
+ digit = *bp - '0';
+ else if ('a' <= *bp && *bp <= 'f')
+ digit = 10 + *bp - 'a';
+ else if ('A' <= *bp && *bp <= 'F')
+ digit = 10 + *bp - 'A';
+ else
+ break;
+
+ if (digit >= base)
+ break;
+
+ n = n * base + digit;
+ bp++;
+ }
+
+ /*
+ * Return value and success.
+ */
+ *num = n;
+ return (0);
+}
+
+
+/*
+ * Compare name field of record.
+ */
+static int
+nfcmp(char *nf, char *rec)
+{
+ char *cp, tmp;
+ int ret;
+
+ for (cp = rec; *cp != ':'; cp++)
+ ;
+
+ tmp = *(cp + 1);
+ *(cp + 1) = '\0';
+ ret = strcmp(nf, rec);
+ *(cp + 1) = tmp;
+
+ return (ret);
+}
* 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.
static char sccsid[] = "@(#)getcwd.c 8.5 (Berkeley) 2/7/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getcwd.c,v 1.25 2003/10/29 10:45:01 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getcwd.c,v 1.29 2007/01/09 00:27:53 imp Exp $");
#include "namespace.h"
#include <sys/param.h>
*bpt = '\0';
/*
- * Allocate bytes MAXPATHLEN) for the string of "../"'s.
- * Should always be enough (it's 340 levels). If it's not, allocate
+ * Allocate MAXPATHLEN bytes for the string of "../"'s.
+ * Should always be enough. If it's not, allocate
* as necessary. Special case the first stat, it's ".", not "..".
*/
if ((up = malloc(upsize = MAXPATHLEN)) == NULL)
* as necessary. Max length is 3 for "../", the largest
* possible component name, plus a trailing NUL.
*/
- if (bup + 3 + MAXNAMLEN + 1 >= eup) {
+ while (bup + 3 + MAXNAMLEN + 1 >= eup) {
if ((up = reallocf(up, upsize *= 2)) == NULL)
goto err;
bup = up;
* Check for length of the current name, preceding slash,
* leading slash.
*/
- if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
+ while (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
size_t len, off;
if (!ptsize) {
* 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.
static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/gethostname.c,v 1.5 2003/08/19 23:01:46 wollman Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/gethostname.c,v 1.8 2007/01/09 00:27:54 imp Exp $");
#include <string.h>
#include <sys/param.h>
#include <limits.h>
#include <errno.h>
+#include <unistd.h>
int
gethostname(name, namelen)
{
int mib[2];
- /* Kluge to avoid ABI breakage. */
- namelen = (int)namelen;
-
mib[0] = CTL_KERN;
mib[1] = KERN_HOSTNAME;
if (namelen < MAXHOSTNAMELEN + 1) {
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)gethostname.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/gethostname.3,v 1.16 2004/07/03 22:30:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/gethostname.3,v 1.17 2007/01/09 00:27:54 imp Exp $
.\"
.Dd August 18, 2003
.Dt GETHOSTNAME 3
This call is restricted to the super-user and
is normally used only when the system is bootstrapped.
.Pp
-Host names are limited to
-.Brq Dv HOST_NAME_MAX
+Host names are limited in length to
+.Brq Dv sysconf(_SC_HOST_NAME_MAX)
characters, not including the trailing null, currently 255.
.Sh RETURN VALUES
.Rv -std
function conforms to
.St -p1003.1-2001 .
Callers should be aware that
-.Brq Dv HOST_NAME_MAX
+.Brq Dv sysconf(_SC_HOST_NAME_MAX)
may be variable or infinite, but is guaranteed to be no less than
.Brq Dv _POSIX_HOST_NAME_MAX .
On older systems, this limit was defined in the non-standard header
-.\" $NetBSD: getlastlogx.3,v 1.1 2003/08/26 17:37:51 wiz Exp $
+.\" $NetBSD: getlastlogx.3,v 1.2 2008/04/30 13:10:50 martin Exp $
.\"
.\" Copyright (c) 2003 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
--- /dev/null
+.\" $NetBSD: getlastlogx.3,v 1.2 2008/04/30 13:10:50 martin Exp $
+.\"
+.\" Copyright (c) 2003 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Thomas Klausner.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd August 26, 2003
+.Dt GETLASTLOGX 3
+.Os
+.Sh NAME
+.Nm getlastlogx ,
+.Nm getutmp ,
+.Nm getutmpx ,
+.Nm updlastlogx ,
+.Nm updwtmpx ,
+.Nm utmpxname
+.Nd user accounting database functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In utmpx.h
+.Ft struct lastlogx *
+.Fn getlastlogx "const char *fname" "uid_t uid" "struct lastlogx *ll"
+.Ft void
+.Fn getutmp "const struct utmpx *ux" "struct utmp *u"
+.Ft void
+.Fn getutmpx "const struct utmp *u" "struct utmpx *ux"
+.Ft int
+.Fn updlastlogx "const char *fname" "uid_t uid" "struct lastlogx *ll"
+.Ft int
+.Fn updwtmpx "const char *file" "const struct utmpx *utx"
+.Ft int
+.Fn utmpxname "const char *fname"
+.Sh DESCRIPTION
+The
+.Fn getlastlogx
+function looks up the entry for the user with user id
+.Fa uid
+in the
+.Xr lastlogx 5
+file given by
+.Fa fname
+and returns it in
+.Fa \&ll .
+If the provided
+.Fa \&ll
+is
+.Dv NULL ,
+the necessary space will be allocated by
+.Fn getlastlogx
+and should be
+.Fn free Ns d
+by the caller.
+.Pp
+The
+.Fn getutmp
+function fills out the entries in the struct utmp
+.Fa u
+with the data provided in the struct utmpx
+.Fa ux .
+.Fn getutmpx
+does the opposite, filling out the entries in the struct utmpx
+.Fa ux
+with the data provided in the struct utmp
+.Fa u ,
+and initializing all the unknown fields to 0.
+The sole exception is the
+.Fa ut_type
+field, which will be initialized to
+.Dv USER_PROCESS .
+.Pp
+The
+.Fn updlastlogx
+function tries to update the information for the user with the user id
+.Fa uid
+in the
+.Xr lastlogx 5
+file given by
+.Fa fname
+with the data supplied in
+.Fa \&ll .
+A
+.Ft struct lastlogx
+is defined like this:
+.Bd -literal
+struct lastlogx {
+ struct timeval ll_tv; /* time entry was created */
+ char ll_line[_UTX_LINESIZE]; /* tty name */
+ char ll_host[_UTX_HOSTSIZE]; /* host name */
+ struct sockaddr_storage ll_ss; /* address where entry was made from */
+};
+.Ed
+All the fields should be filled out by the caller.
+.Pp
+The
+.Fn updwtmpx
+function updates the
+.Xr wtmpx 5
+file
+.Fa file
+with the
+.Xr utmpx 5
+entry
+.Fa utx .
+.Pp
+The
+.Fn utmpxname
+function sets the default
+.Xr utmpx 5
+database file name to
+.Fa fname .
+.Sh RETURN VALUES
+.Fn getlastlogx
+returns the found entry on success, or
+.Dv NULL
+if it could not open the database, could not find an entry matching
+.Fa uid
+in there, or could not allocate the necessary space (in case
+.Fa \&ll
+was
+.Dv NULL ) .
+.Pp
+.Fn utmpxname
+returns 1 on success, or 0 if the supplied file name was too long or
+did not end with
+.Sq x .
+.Pp
+.Fn updlastlogx
+and
+.Fn updwtmpx
+return 0 on success, or \-1 in case the database or file respectively
+could not be opened or the data not written into it.
+.Sh SEE ALSO
+.Xr endutxent 3 ,
+.Xr loginx 3 ,
+.Xr utmpx 5
+.Sh HISTORY
+The functions
+.Fn getutmp ,
+.Fn getutmpx ,
+.Fn updwtmpx ,
+and
+.Fn utmpxname
+first appeared in
+.Tn Solaris .
+.Nm getlastlogx
+and
+.Nm updlastlogx
+first appeared in
+.Nx 2.0 .
* 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.
static char sccsid[] = "@(#)getlogin.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getlogin.c,v 1.9 2003/10/29 10:45:01 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getlogin.c,v 1.11 2009/12/05 19:04:21 ed Exp $");
#include <sys/param.h>
#include <errno.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getmntinfo.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/gen/getmntinfo.3,v 1.12 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/getmntinfo.3,v 1.13 2007/01/09 00:27:54 imp Exp $
.\"
-.Dd May 15, 2008
+.Dd May 4, 2010
.Dt GETMNTINFO 3
.Os
.Sh NAME
.Nm getmntinfo
+.Nm getmntinfo64
.Nd get information about mounted file systems
.Sh SYNOPSIS
.In sys/param.h
.In sys/mount.h
.Ft int
.Fn getmntinfo "struct statfs **mntbufp" "int flags"
-#ifdef UNIFDEF_LEGACY_64_APIS
.Sh TRANSITIIONAL SYNOPSIS (NOW DEPRECATED)
.Ft int
.br
.Fn getmntinfo64 "struct statfs64 **mntbufp" "int flags" ;
-#endif /* UNIFDEF_LEGACY_64_APIS */
.Sh DESCRIPTION
The
.Fn getmntinfo
.Ft statfs
structures describing each currently mounted file system (see
.Xr statfs 2 ) .
+As
+.Xr statfs 2
+indicates, the structure is defined differently depending on
+whether the macro _DARWIN_FEATURE_64_BIT_INODE is defined (see
+.Xr stat 2
+for more information on this macro).
.Pp
The
.Fn getmntinfo
.Fa flags
argument transparently to
.Xr getfsstat 2 .
-#ifdef UNIFDEF_LEGACY_64_APIS
-.Pp
-Like
-.Xr getfsstat 2 ,
-when the macro
-.Dv _DARWIN_FEATURE_64_BIT_INODE
-is defined, the
-.Ft ino_t
-type will be 64-bits (force 64-bit inode mode by defining the
-.Dv _DARWIN_USE_64_BIT_INODE
-macro before including header files).
-This will cause the symbol variant of
-.Fn getmntinfo ,
-with the
-.Fa $INODE64
-suffixes, to be automatically linked in.
-In addition, the
-.Ft statfs
-structure will be the 64-bit inode version.
-If
-.Dv _DARWIN_USE_64_BIT_INODE
-is not defined, both
-.Fn getmntinfo
-and the
-.Ft statfs
-structure will refer to the 32-bit inode versions.
-#endif /* UNIFDEF_LEGACY_64_APIS */
.Sh RETURN VALUES
On successful completion,
.Fn getmntinfo
.Xr getfsstat 2
or
.Xr malloc 3 .
-#ifdef UNIFDEF_LEGACY_64_APIS
.Sh TRANSITIONAL DESCRIPTION (NOW DEPRECATED)
The
.Fn getmntinfo64
structure used by this deprecated routine is the same as the
.Ft statfs
structure when 64-bit inodes are in effect.
-#endif /* UNIFDEF_LEGACY_64_APIS */
.Sh SEE ALSO
.Xr getfsstat 2 ,
.Xr mount 2 ,
+.Xr stat 2 ,
.Xr statfs 2 ,
.Xr mount 8
.Sh HISTORY
.Sh BUGS
The
.Fn getmntinfo
-#ifdef UNIFDEF_LEGACY_64_APIS
-and
-.Fn getmntinfo64
-functions write the array of structures to an internal static object
-#else /* !UNIFDEF_LEGACY_64_APIS */
function writes the array of structures to an internal static object
-#endif /* UNIFDEF_LEGACY_64_APIS */
and returns
a pointer to that object.
Subsequent calls to
.Fn getmntinfo
-#ifdef UNIFDEF_LEGACY_64_APIS
-and
-.Fn getmntinfo64
-#endif /* UNIFDEF_LEGACY_64_APIS */
will modify the same object.
.Pp
The memory allocated by
.Fn getmntinfo
-#ifdef UNIFDEF_LEGACY_64_APIS
-and
-.Fn getmntinfo64
-#endif /* UNIFDEF_LEGACY_64_APIS */
cannot be
.Xr free 3 Ns 'd
by the application.
* 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.
static char sccsid[] = "@(#)getmntinfo.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/getmntinfo.c,v 1.4 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/getmntinfo.c,v 1.5 2007/01/09 00:27:54 imp Exp $");
#include <sys/param.h>
#include <sys/ucred.h>
--- /dev/null
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getmntinfo.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/getmntinfo.c,v 1.5 2007/01/09 00:27:54 imp Exp $");
+
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <stdlib.h>
+
+/*
+ * Return information about mounted filesystems.
+ */
+int
+getmntinfo(mntbufp, flags)
+ struct statfs **mntbufp;
+ int flags;
+{
+ static struct statfs *mntbuf;
+ static int mntsize;
+ static long bufsize;
+
+ if (mntsize <= 0 && (mntsize = getfsstat(0, 0, MNT_NOWAIT)) < 0)
+ return (0);
+ if (bufsize > 0 && (mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+ return (0);
+ while (bufsize <= mntsize * sizeof(struct statfs)) {
+ if (mntbuf)
+ free(mntbuf);
+ bufsize = (mntsize + 1) * sizeof(struct statfs);
+ if ((mntbuf = (struct statfs *)malloc(bufsize)) == 0)
+ return (0);
+ if ((mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+ return (0);
+ }
+ *mntbufp = mntbuf;
+ return (mntsize);
+}
* 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.
static char sccsid[] = "@(#)isatty.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/isatty.c,v 1.5 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/isatty.c,v 1.6 2007/01/09 00:27:54 imp Exp $");
#include <termios.h>
#include <unistd.h>
+/* $NetBSD: lockf.c,v 1.3 2008/04/28 20:22:59 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
* 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
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* $NetBSD: lockf.c,v 1.1 1997/12/20 20:23:18 kleink Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/lockf.c,v 1.8 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/lockf.c,v 1.10 2009/03/04 01:01:26 delphij Exp $");
#ifdef VARIANT_CANCELABLE
int __fcntl(int, int, void *);
#include "un-namespace.h"
int
-lockf(filedes, function, size)
- int filedes;
- int function;
- off_t size;
+lockf(int filedes, int function, off_t size)
{
struct flock fl;
int cmd;
-
fl.l_start = 0;
fl.l_len = size;
fl.l_whence = SEEK_CUR;
}
#ifdef VARIANT_CANCELABLE
- return (__fcntl(filedes, cmd, &fl));
+ return (__fcntl(filedes, cmd, &fl));
#else /* !VARIANT_CANCELABLE */
- return (__fcntl_nocancel(filedes, cmd, &fl));
+ return (__fcntl_nocancel(filedes, cmd, &fl));
#endif /* VARIANT_CANCELABLE */
}
-.\" $NetBSD: lockf.3,v 1.2 1998/02/05 18:47:28 perry Exp $
+.\" $NetBSD: lockf.3,v 1.10 2008/04/30 13:10:50 martin Exp $
.\"
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/gen/lockf.3,v 1.13 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/lockf.3,v 1.14 2009/03/04 01:01:26 delphij Exp $
.\"
.Dd December 19, 1997
.Dt LOCKF 3
#include <mach/mach_init.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <sys/param.h>
+
+#if defined(__i386__) || defined(__x86_64__)
+#define __APPLE_API_PRIVATE
+#include <machine/cpu_capabilities.h>
+#define _COMM_PAGE_VERSION_REQD 9
+#undef __APPLE_API_PRIVATE
+#else
#include <sys/sysctl.h>
+#endif
+
#include <libkern/OSAtomic.h>
-#include <mach-o/dyld.h> /* for NSVersionOfLinkTimeLibrary() */
+#include <mach-o/dyld.h> /* for NSVersionOfLinkTimeLibrary() */
+#include <mach-o/dyld_priv.h> /* for _dyld_get_image_slide() */
+#include <crt_externs.h> /* for _NSGetMachExecuteHeader() */
+#include <mach/vm_param.h>
+#include <sys/vmparam.h>
+
+#include <CrashReporterClient.h>
/********************* DEFINITIONS ************************/
#define CACHE_ALIGN
#endif
+#if !__LP64__
+#define ASLR_INTERNAL 1
+#endif
+
/*
* Access to global variables is slow, so optimise our handling of vm_page_size
* and vm_page_shift.
typedef int mag_index_t;
#define CHECK_REGIONS (1 << 31)
+#define DISABLE_ASLR (1 << 30)
#define MAX_RECORDER_BUFFER 256
#define NUM_TINY_CEIL_BLOCKS (1 << SHIFT_TINY_CEIL_BLOCKS)
#define TINY_BLOCKS_ALIGN (SHIFT_TINY_CEIL_BLOCKS + SHIFT_TINY_QUANTUM) // 20
+#define TINY_ENTROPY_BITS 15
+#define TINY_ENTROPY_MASK ((1 << TINY_ENTROPY_BITS) - 1)
+
+/*
+ * Avoid having so much entropy that the end of a valid tiny allocation
+ * might overrun the end of the tiny region.
+ */
+#if TINY_ENTROPY_MASK + NUM_TINY_SLOTS > NUM_TINY_BLOCKS
+#error Too many entropy bits for tiny region requested
+#endif
+
/*
* Enough room for the data, followed by the bit arrays (2-bits per block)
* plus rounding to the nearest page.
struct region_trailer *next;
boolean_t recirc_suitable;
boolean_t failedREUSE;
+ volatile int pinned_to_depot;
unsigned bytes_used;
mag_index_t mag_index;
} region_trailer_t;
#define NUM_SMALL_CEIL_BLOCKS (1 << SHIFT_SMALL_CEIL_BLOCKS)
#define SMALL_BLOCKS_ALIGN (SHIFT_SMALL_CEIL_BLOCKS + SHIFT_SMALL_QUANTUM) // 23
+#define SMALL_ENTROPY_BITS 13
+#define SMALL_ENTROPY_MASK ((1 << SMALL_ENTROPY_BITS) - 1)
+
+/*
+ * Avoid having so much entropy that the end of a valid small allocation
+ * might overrun the end of the small region.
+ */
+#if SMALL_ENTROPY_MASK + NUM_SMALL_SLOTS > NUM_SMALL_BLOCKS
+#error Too many entropy bits for small region requested
+#endif
+
#define SMALL_METADATA_SIZE (sizeof(region_trailer_t) + NUM_SMALL_BLOCKS * sizeof(msize_t))
#define SMALL_REGION_SIZE \
((NUM_SMALL_BLOCKS * SMALL_QUANTUM + SMALL_METADATA_SIZE + vm_page_size - 1) & ~ (vm_page_size - 1))
*/
#define SMALL_PTR_SIZE(_p) (*SMALL_METADATA_FOR_PTR(_p) & ~SMALL_IS_FREE)
-#define PROTECT_SMALL 0 // Should be 0: 1 is too slow for normal use
-
#define SMALL_CACHE 1
#if !SMALL_CACHE
#warning SMALL_CACHE turned off
#endif
#define LARGE_CACHE_SIZE_ENTRY_LIMIT (LARGE_CACHE_SIZE_LIMIT/LARGE_ENTRY_CACHE_SIZE)
+#define SZONE_FLOTSAM_THRESHOLD_LOW (1024 * 512)
+#define SZONE_FLOTSAM_THRESHOLD_HIGH (1024 * 1024)
+
/*******************************************************************************
* Definitions for region hash
******************************************************************************/
typedef struct { // vm_allocate()'d, so the array of magazines is page-aligned to begin with.
// Take magazine_lock first, Depot lock when needed for recirc, then szone->{tiny,small}_regions_lock when needed for alloc
pthread_lock_t magazine_lock CACHE_ALIGN;
+ // Protection for the crtical section that does allocate_pages outside the magazine_lock
+ volatile boolean_t alloc_underway;
// One element deep "death row", optimizes malloc/free/malloc for identical size.
void *mag_last_free; // low SHIFT_{TINY,SMALL}_QUANTUM bits indicate the msize
free_list_t *mag_free_list[256]; // assert( 256 >= MAX( NUM_TINY_SLOTS, NUM_SMALL_SLOTS_LARGEMEM ))
unsigned mag_bitmap[8]; // assert( sizeof(mag_bitmap) << 3 >= sizeof(mag_free_list)/sizeof(free_list_t) )
- // the last free region in the last block is treated as a big block in use that is not accounted for
+ // the first and last free region in the last block are treated as big blocks in use that are not accounted for
size_t mag_bytes_free_at_end;
- region_t mag_last_region; // Valid iff mag_bytes_free_at_end > 0
+ size_t mag_bytes_free_at_start;
+ region_t mag_last_region; // Valid iff mag_bytes_free_at_end || mag_bytes_free_at_start > 0
// bean counting ...
unsigned mag_num_objects;
region_trailer_t *lastNode;
#if __LP64__
- uint64_t pad[49]; // So sizeof(magazine_t) is 2560 bytes. FIXME: assert this at compile time
+ uint64_t pad[48]; // So sizeof(magazine_t) is 2560 bytes. FIXME: assert this at compile time
#else
- uint32_t pad[45]; // So sizeof(magazine_t) is 1280 bytes. FIXME: assert this at compile time
+ uint32_t pad[12]; // So sizeof(magazine_t) is 1280 bytes. FIXME: assert this at compile time
#endif
} magazine_t;
*/
typedef struct szone_s { // vm_allocate()'d, so page-aligned to begin with.
- malloc_zone_t basic_zone;
- pthread_key_t cpu_id_key;
+ malloc_zone_t basic_zone; // first page will be given read-only protection
+ uint8_t pad[vm_page_size - sizeof(malloc_zone_t)];
+
+ pthread_key_t cpu_id_key; // remainder of structure is R/W (contains no function pointers)
unsigned debug_flags;
void *log_address;
int large_entry_cache_newest;
large_entry_t large_entry_cache[LARGE_ENTRY_CACHE_SIZE]; // "death row" for large malloc/free
boolean_t large_legacy_reset_mprotect;
- size_t large_entry_cache_hoard_bytes;
- size_t large_entry_cache_hoard_lmit;
+ size_t large_entry_cache_reserve_bytes;
+ size_t large_entry_cache_reserve_limit;
+ size_t large_entry_cache_bytes; // total size of death row, bytes
#endif
/* flag and limits pertaining to altered malloc behavior for systems with
/* The purgeable zone constructed by create_purgeable_zone() would like to hand off tiny and small
* allocations to the default scalable zone. Record the latter as the "helper" zone here. */
struct szone_s *helper_zone;
+
+ boolean_t flotsam_enabled;
} szone_t;
#define SZONE_PAGED_SIZE ((sizeof(szone_t) + vm_page_size - 1) & ~ (vm_page_size - 1))
static void protect(void *address, size_t size, unsigned protection, unsigned debug_flags);
static void *allocate_pages(szone_t *szone, size_t size, unsigned char align, unsigned debug_flags,
int vm_page_label);
+static void *allocate_pages_securely(szone_t *szone, size_t size, unsigned char align,
+ int vm_page_label);
static void deallocate_pages(szone_t *szone, void *addr, size_t size, unsigned debug_flags);
#if TARGET_OS_EMBEDDED
static int madvise_free_range(szone_t *szone, region_t r, uintptr_t pgLo, uintptr_t pgHi, uintptr_t *last);
static int tiny_free_detach_region(szone_t *szone, magazine_t *tiny_mag_ptr, region_t r);
static size_t tiny_free_reattach_region(szone_t *szone, magazine_t *tiny_mag_ptr, region_t r);
static void tiny_free_scan_madvise_free(szone_t *szone, magazine_t *depot_ptr, region_t r);
-static void tiny_free_try_depot_unmap_no_lock(szone_t *szone, magazine_t *depot_ptr, region_trailer_t *node);
-static void tiny_free_do_recirc_to_depot(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index);
-static region_t tiny_find_msize_region(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index, msize_t msize);
+static region_t tiny_free_try_depot_unmap_no_lock(szone_t *szone, magazine_t *depot_ptr, region_trailer_t *node);
+static boolean_t tiny_free_do_recirc_to_depot(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index);
+static region_t tiny_find_msize_region(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index, msize_t msize);
static boolean_t tiny_get_region_from_depot(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index, msize_t msize);
-static INLINE void tiny_free_no_lock(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index, region_t region,
+static INLINE boolean_t tiny_free_no_lock(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index, region_t region,
void *ptr, msize_t msize) ALWAYSINLINE;
static void *tiny_malloc_from_region_no_lock(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index,
- msize_t msize);
+ msize_t msize, void *fresh_region);
static boolean_t tiny_try_realloc_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_size);
static boolean_t tiny_check_region(szone_t *szone, region_t region);
static kern_return_t tiny_in_use_enumerator(task_t task, void *context, unsigned type_mask, szone_t *szone,
static INLINE void *tiny_malloc_should_clear(szone_t *szone, msize_t msize, boolean_t cleared_requested) ALWAYSINLINE;
static INLINE void free_tiny(szone_t *szone, void *ptr, region_t tiny_region, size_t known_size) ALWAYSINLINE;
static void print_tiny_free_list(szone_t *szone);
-static void print_tiny_region(boolean_t verbose, region_t region, size_t bytes_at_end);
+static void print_tiny_region(boolean_t verbose, region_t region, size_t bytes_at_start, size_t bytes_at_end);
static boolean_t tiny_free_list_check(szone_t *szone, grain_t slot);
static INLINE void small_meta_header_set_is_free(msize_t *meta_headers, unsigned index, msize_t msize) ALWAYSINLINE;
static void small_finalize_region(szone_t *szone, magazine_t *small_mag_ptr);
static int small_free_detach_region(szone_t *szone, magazine_t *small_mag_ptr, region_t r);
static size_t small_free_reattach_region(szone_t *szone, magazine_t *small_mag_ptr, region_t r);
-static void small_free_scan_depot_madvise_free(szone_t *szone, magazine_t *depot_ptr, region_t r);
-static void small_free_try_depot_unmap_no_lock(szone_t *szone, magazine_t *depot_ptr, region_trailer_t *node);
-static void small_free_do_recirc_to_depot(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index);
-static region_t small_find_msize_region(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index, msize_t msize);
+static void small_free_scan_madvise_free(szone_t *szone, magazine_t *depot_ptr, region_t r);
+static region_t small_free_try_depot_unmap_no_lock(szone_t *szone, magazine_t *depot_ptr, region_trailer_t *node);
+static boolean_t small_free_do_recirc_to_depot(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index);
+static region_t small_find_msize_region(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index, msize_t msize);
static boolean_t small_get_region_from_depot(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index, msize_t msize);
-static INLINE void small_free_no_lock(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index, region_t region,
+static INLINE boolean_t small_free_no_lock(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index, region_t region,
void *ptr, msize_t msize) ALWAYSINLINE;
static void *small_malloc_from_region_no_lock(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index,
- msize_t msize);
+ msize_t msize, void *fresh_region);
static boolean_t small_try_realloc_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_size);
static boolean_t small_check_region(szone_t *szone, region_t region);
static kern_return_t small_in_use_enumerator(task_t task, void *context, unsigned type_mask, szone_t *szone,
static INLINE void *small_malloc_should_clear(szone_t *szone, msize_t msize, boolean_t cleared_requested) ALWAYSINLINE;
static INLINE void free_small(szone_t *szone, void *ptr, region_t small_region, size_t known_size) ALWAYSINLINE;
static void print_small_free_list(szone_t *szone);
-static void print_small_region(szone_t *szone, boolean_t verbose, region_t region, size_t bytes_at_end);
+static void print_small_region(szone_t *szone, boolean_t verbose, region_t region, size_t bytes_at_start, size_t bytes_at_end);
static boolean_t small_free_list_check(szone_t *szone, grain_t grain);
#if DEBUG_MALLOC
static vm_range_t large_entry_free_no_lock(szone_t *szone, large_entry_t *entry);
static NOINLINE kern_return_t large_in_use_enumerator(task_t task, void *context,
unsigned type_mask, vm_address_t large_entries_address,
- unsigned num_entries, memory_reader_t reader, vm_range_recorder_t recorder);
+ unsigned num_entries, memory_reader_t reader,
+ vm_range_recorder_t recorder);
static void *large_malloc(szone_t *szone, size_t num_pages, unsigned char alignment, boolean_t cleared_requested);
static NOINLINE void free_large(szone_t *szone, void *ptr);
static INLINE int large_try_realloc_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_size) ALWAYSINLINE;
static void frozen_free(szone_t *zone, void *ptr);
static void frozen_destroy(szone_t *zone);
+static volatile uintptr_t entropic_address = 0;
+static volatile uintptr_t entropic_limit = 0;
+#define ENTROPIC_KABILLION 0x10000000 /* 256Mb */
+
+__private_extern__ uint64_t malloc_entropy[2];
+
#define SZONE_LOCK(szone) \
do { \
LOCK(szone->large_szone_lock); \
}
#endif
-extern const char *__crashreporter_info__;
-
// msg prints after fmt, ...
static NOINLINE void
szone_error(szone_t *szone, int is_corruption, const char *msg, const void *ptr, const char *fmt, ...)
// corruption flag is set, or if any error should abort.
if ((is_corruption && (szone->debug_flags & SCALABLE_MALLOC_ABORT_ON_CORRUPTION)) ||
(szone->debug_flags & SCALABLE_MALLOC_ABORT_ON_ERROR)) {
- __crashreporter_info__ = b ? _simple_string(b) : msg;
+ CRSetCrashLogMessage(b ? _simple_string(b) : msg);
abort();
} else if (b) {
_simple_sfree(b);
kern_return_t err;
if (!(debug_flags & SCALABLE_MALLOC_DONT_PROTECT_PRELUDE)) {
- err = vm_protect(mach_task_self(), (vm_address_t)(uintptr_t)address - vm_page_size, vm_page_size, 0, protection);
+ err = mprotect((void *)((uintptr_t)address - vm_page_size), vm_page_size, protection);
if (err) {
malloc_printf("*** can't protect(%p) region for prelude guard page at %p\n",
protection,(uintptr_t)address - (1 << vm_page_shift));
}
}
if (!(debug_flags & SCALABLE_MALLOC_DONT_PROTECT_POSTLUDE)) {
- err = vm_protect(mach_task_self(), (vm_address_t)(uintptr_t)address + size, vm_page_size, 0, protection);
+ err = mprotect((void *)((uintptr_t)address + size), vm_page_size, protection);
if (err) {
malloc_printf("*** can't protect(%p) region for postlude guard page at %p\n",
protection, (uintptr_t)address + size);
boolean_t purgeable = debug_flags & SCALABLE_MALLOC_PURGEABLE;
size_t allocation_size = round_page(size);
size_t delta;
- int flags = VM_MAKE_TAG(vm_page_label);
+ int alloc_flags = VM_MAKE_TAG(vm_page_label);
if (align) add_guard_pages = 0; // too cumbersome to deal with that
if (!allocation_size) allocation_size = 1 << vm_page_shift;
if (add_guard_pages) allocation_size += 2 * (1 << vm_page_shift);
if (align) allocation_size += (size_t)1 << align;
- if (purgeable) flags |= VM_FLAGS_PURGABLE;
+ if (purgeable) alloc_flags |= VM_FLAGS_PURGABLE;
if (allocation_size < size) // size_t arithmetic wrapped!
return NULL;
- vm_addr = mmap(0, allocation_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, flags, 0);
+ vm_addr = mmap(0 /* addr */,
+ allocation_size /* size */,
+ PROT_READ | PROT_WRITE /* prot */,
+ MAP_ANON | MAP_PRIVATE /* flags */,
+ alloc_flags /* fd being used to pass "purgeable" and "vm_page_label" */,
+ 0 /* offset */);
if ((uintptr_t)vm_addr == -1) {
szone_error(szone, 0, "can't allocate region", NULL, "*** mmap(size=%lu) failed (error code=%d)\n",
allocation_size, errno);
}
if (add_guard_pages) {
addr += (uintptr_t)1 << vm_page_shift;
- protect((void *)addr, size, 0, debug_flags);
+ protect((void *)addr, size, PROT_NONE, debug_flags);
+ }
+ return (void *)addr;
+}
+
+static void *
+allocate_pages_securely(szone_t *szone, size_t size, unsigned char align, int vm_page_label)
+{
+ // align specifies a desired alignment (as a log) or 0 if no alignment requested
+ void *vm_addr;
+ uintptr_t addr, aligned_address;
+ size_t delta, allocation_size = MAX(round_page(size), vm_page_size);
+ int alloc_flags = VM_MAKE_TAG(vm_page_label);
+
+ if (szone->debug_flags & DISABLE_ASLR)
+ return allocate_pages(szone, size, align, 0, vm_page_label);
+
+ if (align)
+ allocation_size += (size_t)1 << align;
+
+ if (allocation_size < size) // size_t arithmetic wrapped!
+ return NULL;
+
+retry:
+ vm_addr = mmap((void *)entropic_address /* kernel finds next available range at or above this address */,
+ allocation_size /* size */,
+ PROT_READ | PROT_WRITE /* prot */,
+ MAP_ANON | MAP_PRIVATE /* flags */,
+ alloc_flags /* fd being used to pass "vm_page_label" */,
+ 0 /* offset */);
+ if (MAP_FAILED == vm_addr) {
+ szone_error(szone, 0, "can't allocate region securely", NULL, "*** mmap(size=%lu) failed (error code=%d)\n",
+ size, errno);
+ return NULL;
+ }
+ addr = (uintptr_t)vm_addr;
+
+ // Don't allow allocation to rise above entropic_limit (for tidiness).
+ if (addr + allocation_size > entropic_limit) { // Exhausted current range?
+ uintptr_t t = entropic_address;
+ uintptr_t u = t - ENTROPIC_KABILLION;
+
+ if (u < t) { // provided we don't wrap, unmap and retry, in the expanded entropic range
+ munmap((void *)addr, allocation_size);
+ (void)__sync_bool_compare_and_swap(&entropic_address, t, u); // Just one reduction please
+ goto retry;
+ }
+ // fall through to use what we got
+ }
+
+ if (addr < entropic_address) { // mmap wrapped to find this allocation, expand the entropic range
+ uintptr_t t = entropic_address;
+ uintptr_t u = t - ENTROPIC_KABILLION;
+ if (u < t)
+ (void)__sync_bool_compare_and_swap(&entropic_address, t, u); // Just one reduction please
+ // fall through to use what we got
+ }
+
+ // unmap any excess address range used for alignment padding
+ if (align) {
+ aligned_address = (addr + ((uintptr_t)1 << align) - 1) & ~ (((uintptr_t)1 << align) - 1);
+ if (aligned_address != addr) {
+ delta = aligned_address - addr;
+ if (munmap((void *)addr, delta) == -1)
+ malloc_printf("*** munmap unaligned header failed with %d\n", errno);
+ addr = aligned_address;
+ allocation_size -= delta;
+ }
+ if (allocation_size > size) {
+ if (munmap((void *)(addr + size), allocation_size - size) == -1)
+ malloc_printf("*** munmap unaligned footer failed with %d\n", errno);
+ }
}
return (void *)addr;
}
#endif
/* -1 return: VM map entry change makes this unfit for reuse. Something evil lurks. */
#if DEBUG_MADVISE
- szone_error(szone, 0, "madvise_free_range madvise(..., MADV_FREE_REUSABLE) failed", (void *)pgLo, "length=%d\n", len);
+ szone_error(szone, 0, "madvise_free_range madvise(..., MADV_FREE_REUSABLE) failed",
+ (void *)pgLo, "length=%d\n", len);
#endif
}
}
((((uintptr_t)pthread_self()) >> vm_page_shift) * 2654435761UL) >> (32 - szone->num_tiny_magazines_mask_shift)
#endif
-#if defined(__i386__) || defined(__x86_64__)
-#define __APPLE_API_PRIVATE
-#include <machine/cpu_capabilities.h>
-#define _COMM_PAGE_VERSION_REQD 9
-#undef __APPLE_API_PRIVATE
-
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
/*
* These commpage routines provide fast access to the logical cpu number
* of the calling processor assuming no pre-emption occurs.
*/
-#define CPU_NUMBER() (((int (*)()) _COMM_PAGE_CPU_NUMBER)()) /* Zero-based */
static INLINE mag_index_t
mag_get_thread_index(szone_t *szone)
if (!__is_threaded)
return 0;
else
- return CPU_NUMBER() & (TINY_MAX_MAGAZINES - 1);
-}
-
-#elif defined(__arm__)
-
-static INLINE mag_index_t
-mag_get_thread_index(szone_t *szone)
-{
- return 0;
+ return cpu_number() & (TINY_MAX_MAGAZINES - 1);
}
#else
// at least 4 trailing zero bits.
//
// When an entry is added to the free list, a checksum of the previous and next
-// pointers is calculated and written to the low four bits of the respective
+// pointers is calculated and written to the high four bits of the respective
// pointers. Upon detection of an invalid checksum, an error is logged and NULL
// is returned. Since all code which un-checksums pointers checks for a NULL
// return, a potentially crashing or malicious dereference is avoided at the
return chk & (uintptr_t)0xF;
}
+#define NYBBLE 4
+#if __LP64__
+#define ANTI_NYBBLE (64 - NYBBLE)
+#else
+#define ANTI_NYBBLE (32 - NYBBLE)
+#endif
+
static INLINE uintptr_t
free_list_checksum_ptr(szone_t *szone, void *ptr)
{
uintptr_t p = (uintptr_t)ptr;
- return p | free_list_gen_checksum(p ^ szone->cookie);
+ return (p >> NYBBLE) | (free_list_gen_checksum(p ^ szone->cookie) << ANTI_NYBBLE); // compiles to rotate instruction
}
static INLINE void *
free_list_unchecksum_ptr(szone_t *szone, ptr_union *ptr)
{
ptr_union p;
- p.u = (ptr->u >> 4) << 4;
-
- if ((ptr->u & (uintptr_t)0xF) != free_list_gen_checksum(p.u ^ szone->cookie))
+ uintptr_t t = ptr->u;
+
+ t = (t << NYBBLE) | (t >> ANTI_NYBBLE); // compiles to rotate instruction
+ p.u = t & ~(uintptr_t)0xF;
+
+ if ((t & (uintptr_t)0xF) != free_list_gen_checksum(p.u ^ szone->cookie))
{
free_list_checksum_botch(szone, (free_list_t *)ptr);
return NULL;
return p.p;
}
+#undef ANTI_NYBBLE
+#undef NYBBLE
+
static unsigned
free_list_count(szone_t *szone, free_list_t *ptr)
{
uint32_t *last_header;
msize_t last_msize, previous_msize, last_index;
+ // It is possible that the block prior to the last block in the region has
+ // been free'd, but was not coalesced with the free bytes at the end of the
+ // block, since we treat the bytes at the end of the region as "in use" in
+ // the meta headers. Attempt to coalesce the last block with the previous
+ // block, so we don't violate the "no consecutive free blocks" invariant.
+ //
+ // FIXME: Need to investigate how much work would be required to increase
+ // 'mag_bytes_free_at_end' when freeing the preceding block, rather
+ // than performing this workaround.
+ //
+
+ if (tiny_mag_ptr->mag_bytes_free_at_end) {
last_block = (void *)
((uintptr_t)TINY_REGION_END(tiny_mag_ptr->mag_last_region) - tiny_mag_ptr->mag_bytes_free_at_end);
last_msize = TINY_MSIZE_FOR_BYTES(tiny_mag_ptr->mag_bytes_free_at_end);
if (last_index != (NUM_TINY_BLOCKS - 1))
BITARRAY_CLR(last_header, (last_index + 1));
- // It is possible that the block prior to the last block in the region has
- // been free'd, but was not coalesced with the free bytes at the end of the
- // block, since we treat the bytes at the end of the region as "in use" in
- // the meta headers. Attempt to coalesce the last block with the previous
- // block, so we don't violate the "no consecutive free blocks" invariant.
- //
- // FIXME: Need to investigate how much work would be required to increase
- // 'mag_bytes_free_at_end' when freeing the preceding block, rather
- // than performing this workaround.
- //
previous_block = tiny_previous_preceding_free(last_block, &previous_msize);
if (previous_block) {
set_tiny_meta_header_middle(last_block);
// splice last_block into the free list
tiny_free_list_add_ptr(szone, tiny_mag_ptr, last_block, last_msize);
tiny_mag_ptr->mag_bytes_free_at_end = 0;
+ }
+
+#if ASLR_INTERNAL
+ // Coalesce the big free block at start with any following free blocks
+ if (tiny_mag_ptr->mag_bytes_free_at_start) {
+ last_block = TINY_REGION_ADDRESS(tiny_mag_ptr->mag_last_region);
+ last_msize = TINY_MSIZE_FOR_BYTES(tiny_mag_ptr->mag_bytes_free_at_start);
+
+ void *next_block = (void *) ((uintptr_t)last_block + tiny_mag_ptr->mag_bytes_free_at_start);
+
+ // clear the in use bit we were using to mark the end of the big start block
+ set_tiny_meta_header_middle((uintptr_t)next_block - TINY_QUANTUM);
+
+ // Coalesce the big start block with any following free blocks
+ if (tiny_meta_header_is_free(next_block)) {
+ msize_t next_msize = get_tiny_free_size(next_block);
+ set_tiny_meta_header_middle(next_block);
+ tiny_free_list_remove_ptr(szone, tiny_mag_ptr, next_block, next_msize);
+ last_msize += next_msize;
+ }
+
+ // splice last_block into the free list
+ tiny_free_list_add_ptr(szone, tiny_mag_ptr, last_block, last_msize);
+ tiny_mag_ptr->mag_bytes_free_at_start = 0;
+ }
+#endif
+
tiny_mag_ptr->mag_last_region = NULL;
}
return total_alloc;
}
-static void
+typedef struct {
+ uint8_t pnum, size;
+} tiny_pg_pair_t;
+
+static void NOINLINE /* want private stack frame for automatic array */
tiny_free_scan_madvise_free(szone_t *szone, magazine_t *depot_ptr, region_t r) {
uintptr_t start = (uintptr_t)TINY_REGION_ADDRESS(r);
uintptr_t current = start;
uintptr_t limit = (uintptr_t)TINY_REGION_END(r);
boolean_t is_free;
msize_t msize;
- boolean_t did_advise = FALSE;
+ tiny_pg_pair_t advisory[((TINY_REGION_PAYLOAD_BYTES + vm_page_size - 1) >> vm_page_shift) >> 1]; // 256bytes stack allocated
+ int advisories = 0;
// Scan the metadata identifying blocks which span one or more pages. Mark the pages MADV_FREE taking care to preserve free list
// management data.
uintptr_t pgHi = trunc_page(start + TINY_REGION_SIZE - sizeof(msize_t));
if (pgLo < pgHi) {
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, r, pgLo, pgHi, NULL);
-#else
- madvise_free_range(szone, r, pgLo, pgHi);
-#endif
- did_advise = TRUE;
+ advisory[advisories].pnum = (pgLo - start) >> vm_page_shift;
+ advisory[advisories].size = (pgHi - pgLo) >> vm_page_shift;
+ advisories++;
}
break;
}
uintptr_t pgHi = trunc_page(current + TINY_BYTES_FOR_MSIZE(msize) - sizeof(msize_t));
if (pgLo < pgHi) {
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, r, pgLo, pgHi, NULL);
-#else
- madvise_free_range(szone, r, pgLo, pgHi);
-#endif
- did_advise = TRUE;
+ advisory[advisories].pnum = (pgLo - start) >> vm_page_shift;
+ advisory[advisories].size = (pgHi - pgLo) >> vm_page_shift;
+ advisories++;
}
}
current += TINY_BYTES_FOR_MSIZE(msize);
}
- if (did_advise) {
- /* Move the node to the tail of the Deopt's recirculation list to delay its re-use. */
- region_trailer_t *node = REGION_TRAILER_FOR_TINY_REGION(r);
- recirc_list_extract(szone, depot_ptr, node); // excise node from list
- recirc_list_splice_last(szone, depot_ptr, node); // connect to magazine as last node
+ if (advisories > 0) {
+ int i;
+
+ // So long as the following hold for this region:
+ // (1) No malloc()'s are ever performed from the depot (hence free pages remain free,)
+ // (2) The region is not handed over to a per-CPU magazine (where malloc()'s could be performed),
+ // (3) The entire region is not mumap()'d (so the madvise's are applied to the intended addresses),
+ // then the madvise opportunities collected just above can be applied outside all locks.
+ // (1) is ensured by design, (2) and (3) are ensured by bumping the globally visible counter node->pinned_to_depot.
+
+ OSAtomicIncrement32Barrier(&(REGION_TRAILER_FOR_TINY_REGION(r)->pinned_to_depot));
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, depot_ptr);
+ for (i = 0; i < advisories; ++i) {
+ uintptr_t addr = (advisory[i].pnum << vm_page_shift) + start;
+ size_t size = advisory[i].size << vm_page_shift;
+
+#if TARGET_OS_EMBEDDED
+ madvise_free_range(szone, r, addr, addr + size, NULL);
+#else
+ madvise_free_range(szone, r, addr, addr + size);
+#endif
+ }
+ SZONE_MAGAZINE_PTR_LOCK(szone, depot_ptr);
+ OSAtomicDecrement32Barrier(&(REGION_TRAILER_FOR_TINY_REGION(r)->pinned_to_depot));
}
}
-static void
+static region_t
tiny_free_try_depot_unmap_no_lock(szone_t *szone, magazine_t *depot_ptr, region_trailer_t *node)
{
-#warning Tune Depot headroom
if (0 < node->bytes_used ||
+ 0 < node->pinned_to_depot ||
depot_ptr->recirculation_entries < (szone->num_tiny_magazines * 2)) {
- return;
+ return NULL;
}
// disconnect node from Depot
rgnhdl_t pSlot = hash_lookup_region_no_lock(szone->tiny_region_generation->hashed_regions,
szone->tiny_region_generation->num_regions_allocated,
szone->tiny_region_generation->num_regions_allocated_shift, sparse_region);
+ if (NULL == pSlot) {
+ szone_error(szone, 1, "tiny_free_try_depot_unmap_no_lock hash lookup failed:", NULL, "%p\n", sparse_region);
+ return NULL;
+ }
*pSlot = HASHRING_REGION_DEALLOCATED;
depot_ptr->num_bytes_in_magazine -= TINY_REGION_PAYLOAD_BYTES;
-#if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1))) /* GCC 4.1 and forward supports atomic builtins */
__sync_fetch_and_add( &(szone->num_tiny_regions_dealloc), 1); // Atomically increment num_tiny_regions_dealloc
-#else
-#ifdef __LP64__
- OSAtomicIncrement64( (volatile int64_t *)&(szone->num_tiny_regions_dealloc) );
-#else
- OSAtomicIncrement32( (volatile int32_t *)&(szone->num_tiny_regions_dealloc) );
-#endif
-#endif
-
- // Transfer ownership of the region back to the OS
- SZONE_MAGAZINE_PTR_UNLOCK(szone, depot_ptr); // Avoid denial of service to Depot while in kernel
- deallocate_pages(szone, sparse_region, TINY_REGION_SIZE, 0);
- SZONE_MAGAZINE_PTR_LOCK(szone, depot_ptr);
-
- MAGMALLOC_DEALLOCREGION((void *)szone, (void *)sparse_region); // DTrace USDT Probe
+ // Caller will transfer ownership of the region back to the OS with no locks held
+ MAGMALLOC_DEALLOCREGION((void *)szone, (void *)sparse_region, TINY_REGION_SIZE); // DTrace USDT Probe
+ return sparse_region;
} else {
szone_error(szone, 1, "tiny_free_try_depot_unmap_no_lock objects_in_use not zero:", NULL, "%d\n", objects_in_use);
+ return NULL;
}
}
-static void
+static boolean_t
tiny_free_do_recirc_to_depot(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index)
{
// The entire magazine crossed the "emptiness threshold". Transfer a region
#if DEBUG_MALLOC
malloc_printf("*** tiny_free_do_recirc_to_depot end of list\n");
#endif
- return;
+ return TRUE; // Caller must SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
}
region_t sparse_region = TINY_REGION_FOR_PTR(node);
- // Deal with unclaimed memory -- mag_bytes_free_at_end
- if (sparse_region == tiny_mag_ptr->mag_last_region && tiny_mag_ptr->mag_bytes_free_at_end) {
+ // Deal with unclaimed memory -- mag_bytes_free_at_end or mag_bytes_free_at_start
+ if (sparse_region == tiny_mag_ptr->mag_last_region && (tiny_mag_ptr->mag_bytes_free_at_end || tiny_mag_ptr->mag_bytes_free_at_start)) {
tiny_finalize_region(szone, tiny_mag_ptr);
}
// this will cause tiny_free_list_add_ptr called by tiny_free_reattach_region to use
// the depot as its target magazine, rather than magazine formerly associated with sparse_region
MAGAZINE_INDEX_FOR_TINY_REGION(sparse_region) = DEPOT_MAGAZINE_INDEX;
+ node->pinned_to_depot = 0;
// Iterate the region putting its free entries on Depot's free list
size_t bytes_inplay = tiny_free_reattach_region(szone, depot_ptr, sparse_region);
tiny_mag_ptr->num_bytes_in_magazine -= TINY_REGION_PAYLOAD_BYTES;
tiny_mag_ptr->mag_num_objects -= objects_in_use;
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr); // Unlock the originating magazine
+
depot_ptr->mag_num_bytes_in_objects += bytes_inplay;
depot_ptr->num_bytes_in_magazine += TINY_REGION_PAYLOAD_BYTES;
depot_ptr->mag_num_objects += objects_in_use;
- // connect to Depot as first (MRU) node
- recirc_list_splice_first(szone, depot_ptr, node);
+ // connect to Depot as last node
+ recirc_list_splice_last(szone, depot_ptr, node);
- MAGMALLOC_RECIRCREGION((void *)szone, (int)mag_index, (int)BYTES_USED_FOR_TINY_REGION(sparse_region)); // DTrace USDT Probe
+ MAGMALLOC_RECIRCREGION((void *)szone, (int)mag_index, (void *)sparse_region, TINY_REGION_SIZE,
+ (int)BYTES_USED_FOR_TINY_REGION(sparse_region)); // DTrace USDT Probe
// Mark free'd dirty pages with MADV_FREE to reduce memory pressure
tiny_free_scan_madvise_free(szone, depot_ptr, sparse_region);
- // If the region is entirely empty vm_deallocate() it
- tiny_free_try_depot_unmap_no_lock(szone, depot_ptr, node);
-
+ // If the region is entirely empty vm_deallocate() it outside the depot lock
+ region_t r_dealloc = tiny_free_try_depot_unmap_no_lock(szone, depot_ptr, node);
SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
+ if (r_dealloc)
+ deallocate_pages(szone, r_dealloc, TINY_REGION_SIZE, 0);
+ return FALSE; // Caller need not unlock the originating magazine
}
static region_t
SZONE_MAGAZINE_PTR_LOCK(szone,depot_ptr);
- // Appropriate one of the Depot's regions that can satisfy requested msize.
- region_t sparse_region = tiny_find_msize_region(szone, depot_ptr, DEPOT_MAGAZINE_INDEX, msize);
- if (NULL == sparse_region) { // Depot empty?
- SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
+ // Appropriate a Depot'd region that can satisfy requested msize.
+ region_trailer_t *node;
+ region_t sparse_region;
+
+ while (1) {
+ sparse_region = tiny_find_msize_region(szone, depot_ptr, DEPOT_MAGAZINE_INDEX, msize);
+ if (NULL == sparse_region) { // Depot empty?
+ SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
return 0;
- }
+ }
- region_trailer_t *node = REGION_TRAILER_FOR_TINY_REGION(sparse_region);
+ node = REGION_TRAILER_FOR_TINY_REGION(sparse_region);
+ if (0 >= node->pinned_to_depot)
+ break;
+
+ SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
+ pthread_yield_np();
+ SZONE_MAGAZINE_PTR_LOCK(szone,depot_ptr);
+ }
- // disconnect node from Depot
+ // disconnect node from Depot
recirc_list_extract(szone, depot_ptr, node);
// Iterate the region pulling its free entries off the (locked) Depot's free list
// Transfer ownership of the region
MAGAZINE_INDEX_FOR_TINY_REGION(sparse_region) = mag_index;
+ node->pinned_to_depot = 0;
// Iterate the region putting its free entries on its new (locked) magazine's free list
size_t bytes_inplay = tiny_free_reattach_region(szone, tiny_mag_ptr, sparse_region);
tiny_mag_ptr->num_bytes_in_magazine += TINY_REGION_PAYLOAD_BYTES;
tiny_mag_ptr->mag_num_objects += objects_in_use;
- // connect to magazine as first node (it's maximally sparse at this moment)
+ // connect to magazine as first node
recirc_list_splice_first(szone, tiny_mag_ptr, node);
SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
-#if !TARGET_OS_EMBEDDED
+ // madvise() outside the Depot lock
+#if TARGET_OS_EMBEDDED
+ if (node->failedREUSE) {
+#else
if (node->failedREUSE ||
-1 == madvise((void *)sparse_region, TINY_REGION_PAYLOAD_BYTES, MADV_FREE_REUSE)) {
+#endif
/* -1 return: VM map entry change makes this unfit for reuse. Something evil lurks. */
#if DEBUG_MADVISE
- szone_error(szone, 0, "tiny_get_region_from_depot madvise(..., MADV_FREE_REUSE) failed", sparse_region, "length=%d\n", TINY_REGION_PAYLOAD_BYTES);
+ szone_error(szone, 0, "tiny_get_region_from_depot madvise(..., MADV_FREE_REUSE) failed",
+ sparse_region, "length=%d\n", TINY_REGION_PAYLOAD_BYTES);
#endif
node->failedREUSE = TRUE;
}
-#endif
- MAGMALLOC_DEPOTREGION((void *)szone, (int)mag_index, (int)BYTES_USED_FOR_TINY_REGION(sparse_region)); // DTrace USDT Probe
+ MAGMALLOC_DEPOTREGION((void *)szone, (int)mag_index, (void *)sparse_region, TINY_REGION_SIZE,
+ (int)BYTES_USED_FOR_TINY_REGION(sparse_region)); // DTrace USDT Probe
return 1;
}
-#warning Tune K and f!
#define K 1.5 // headroom measured in number of 1Mb regions
#define DENSITY_THRESHOLD(a) \
((a) - ((a) >> 2)) // "Emptiness" f = 0.25, so "Density" is (1 - f)*a. Generally: ((a) - ((a) >> -log2(f)))
-static INLINE void
+static INLINE boolean_t
tiny_free_no_lock(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index, region_t region, void *ptr,
msize_t msize)
{
free_list_t *big_free_block;
free_list_t *after_next_block;
free_list_t *before_next_block;
- boolean_t did_prepend = FALSE;
- boolean_t did_append = FALSE;
#if DEBUG_MALLOC
if (LOG(szone,ptr)) {
malloc_printf("in tiny_free_no_lock(), ptr=%p, msize=%d\n", ptr, msize);
}
- if (! msize) {
+ if (!msize) {
szone_error(szone, 1, "trying to free tiny block that is too small", ptr,
"in tiny_free_no_lock(), ptr=%p, msize=%d\n", ptr, msize);
}
malloc_printf("in tiny_free_no_lock(), coalesced backwards for %p previous=%p\n", ptr, previous);
}
#endif
- did_prepend = TRUE;
// clear the meta_header since this is no longer the start of a block
set_tiny_meta_header_middle(ptr);
}
// We try to coalesce with the next block
if ((next_block < TINY_REGION_END(region)) && tiny_meta_header_is_free(next_block)) {
- did_append = TRUE;
next_msize = get_tiny_free_size(next_block);
#if DEBUG_MALLOC
if (LOG(szone, ptr) || LOG(szone, next_block)) {
set_tiny_meta_header_middle(next_block); // clear the meta_header to enable coalescing backwards
msize += next_msize;
}
-#if !TINY_CACHE
+
// The tiny cache already scribbles free blocks as they go through the
- // cache, so we do not need to do it here.
- if ((szone->debug_flags & SCALABLE_MALLOC_DO_SCRIBBLE) && msize)
+ // cache whenever msize < TINY_QUANTUM , so we do not need to do it here.
+ if ((szone->debug_flags & SCALABLE_MALLOC_DO_SCRIBBLE) && msize && (msize >= TINY_QUANTUM))
memset(ptr, 0x55, TINY_BYTES_FOR_MSIZE(msize));
-#endif
tiny_free_list_add_ptr(szone, tiny_mag_ptr, ptr, msize);
+
tiny_free_ending:
- // When in proper debug mode we write on the memory to help debug memory smashers
tiny_mag_ptr->mag_num_objects--;
// we use original_size and not msize to avoid double counting the coalesced blocks
size_t a = tiny_mag_ptr->num_bytes_in_magazine; // Total bytes allocated to this magazine
size_t u = tiny_mag_ptr->mag_num_bytes_in_objects; // In use (malloc'd) from this magaqzine
- if (a - u > ((3 * TINY_REGION_PAYLOAD_BYTES) / 2) && u < DENSITY_THRESHOLD(a))
- tiny_free_do_recirc_to_depot(szone, tiny_mag_ptr, mag_index);
+ if (a - u > ((3 * TINY_REGION_PAYLOAD_BYTES) / 2) && u < DENSITY_THRESHOLD(a)) {
+ return tiny_free_do_recirc_to_depot(szone, tiny_mag_ptr, mag_index);
+ }
} else {
#endif
// Freed to Depot. N.B. Lock on tiny_magazines[DEPOT_MAGAZINE_INDEX] is already held
+ // Calcuate the first page in the coalesced block that would be safe to mark MADV_FREE
uintptr_t safe_ptr = (uintptr_t)ptr + sizeof(free_list_t) + sizeof(msize_t);
uintptr_t round_safe = round_page(safe_ptr);
+ // Calcuate the last page in the coalesced block that would be safe to mark MADV_FREE
uintptr_t safe_extent = (uintptr_t)ptr + TINY_BYTES_FOR_MSIZE(msize) - sizeof(msize_t);
uintptr_t trunc_extent = trunc_page(safe_extent);
// The newly freed block may complete a span of bytes that cover a page. Mark it with MADV_FREE.
- if (round_safe < trunc_extent) { // Safe area covers a page
- if (did_prepend & did_append) { // Coalesced preceding with original_ptr *and* with following
- uintptr_t trunc_safe_prev = trunc_page((uintptr_t)original_ptr - sizeof(msize_t));
- uintptr_t rnd_safe_follow =
- round_page((uintptr_t)original_ptr + original_size + sizeof(free_list_t) + sizeof(msize_t));
-
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), MIN(rnd_safe_follow, trunc_extent), &szone->last_tiny_advise);
-#else
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), MIN(rnd_safe_follow, trunc_extent));
-#endif
- } else if (did_prepend) { // Coalesced preceding with original_ptr
- uintptr_t trunc_safe_prev = trunc_page((uintptr_t)original_ptr - sizeof(msize_t));
-
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), trunc_extent, &szone->last_tiny_advise);
-#else
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), trunc_extent);
-#endif
- } else if (did_append) { // Coalesced original_ptr with following
- uintptr_t rnd_safe_follow =
- round_page((uintptr_t)original_ptr + original_size + sizeof(free_list_t) + sizeof(msize_t));
-
+ if (round_safe < trunc_extent) { // Safe area covers a page (perhaps many)
+ uintptr_t lo = trunc_page((uintptr_t)original_ptr);
+ uintptr_t hi = round_page((uintptr_t)original_ptr + original_size);
+
+ OSAtomicIncrement32Barrier(&(node->pinned_to_depot));
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, region, round_safe, MIN(rnd_safe_follow, trunc_extent), &szone->last_tiny_advise);
+ madvise_free_range(szone, region, MAX(round_safe, lo), MIN(trunc_extent, hi), &szone->last_tiny_advise);
#else
- madvise_free_range(szone, region, round_safe, MIN(rnd_safe_follow, trunc_extent));
+ madvise_free_range(szone, region, MAX(round_safe, lo), MIN(trunc_extent, hi));
#endif
- } else { // Isolated free cannot exceed 496 bytes, thus round_safe == trunc_extent, and so never get here.
- /* madvise_free_range(szone, region, round_safe, trunc_extent); */
- }
- }
+ SZONE_MAGAZINE_PTR_LOCK(szone, tiny_mag_ptr);
+ OSAtomicDecrement32Barrier(&(node->pinned_to_depot));
+ }
#if !TARGET_OS_EMBEDDED
- if (0 < bytes_used) {
+ if (0 < bytes_used || 0 < node->pinned_to_depot) {
/* Depot'd region is still live. Leave it in place on the Depot's recirculation list
so as to avoid thrashing between the Depot's free list and a magazines's free list
with detach_region/reattach_region */
} else {
/* Depot'd region is just now empty. Consider return to OS. */
- region_trailer_t *node = REGION_TRAILER_FOR_TINY_REGION(region);
- magazine_t *depot_ptr = &(szone->tiny_magazines[DEPOT_MAGAZINE_INDEX]);
- tiny_free_try_depot_unmap_no_lock(szone, depot_ptr, node); // FIXME: depot_ptr is simply tiny_mag_ptr?
+ region_t r_dealloc = tiny_free_try_depot_unmap_no_lock(szone, tiny_mag_ptr, node);
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
+ if (r_dealloc)
+ deallocate_pages(szone, r_dealloc, TINY_REGION_SIZE, 0);
+ return FALSE; // Caller need not unlock
}
}
#endif
+
+ return TRUE; // Caller must do SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr)
}
// Allocates from the last region or a freshly allocated region
static void *
-tiny_malloc_from_region_no_lock(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index, msize_t msize)
+tiny_malloc_from_region_no_lock(szone_t *szone, magazine_t *tiny_mag_ptr, mag_index_t mag_index,
+ msize_t msize, void * aligned_address)
{
- void *ptr, *aligned_address;
+ void *ptr;
- // Deal with unclaimed memory -- mag_bytes_free_at_end
- if (tiny_mag_ptr->mag_bytes_free_at_end)
+ // Deal with unclaimed memory -- mag_bytes_free_at_end or mag_bytes_free_at_start
+ if (tiny_mag_ptr->mag_bytes_free_at_end || tiny_mag_ptr->mag_bytes_free_at_start)
tiny_finalize_region(szone, tiny_mag_ptr);
- // time to create a new region
- aligned_address = allocate_pages(szone, TINY_REGION_SIZE, TINY_BLOCKS_ALIGN, 0, VM_MEMORY_MALLOC_TINY);
- if (!aligned_address) // out of memory!
- return NULL;
-
- MAGMALLOC_ALLOCREGION((void *)szone, (int)mag_index); // DTrace USDT Probe
-
// We set the unused bits of the header in the last pair to be all ones, and those of the inuse to zeroes.
((tiny_region_t)aligned_address)->pairs[CEIL_NUM_TINY_BLOCKS_WORDS-1].header =
(NUM_TINY_BLOCKS & 31) ? (0xFFFFFFFFU << (NUM_TINY_BLOCKS & 31)) : 0;
// Throw the switch to atomically advance to the next generation.
szone->tiny_region_generation = szone->tiny_region_generation->nextgen;
// Ensure everyone sees the advance.
-#if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1))) /* GCC 4.1 and forward supports atomic builtins */
- __sync_synchronize();
-#else
OSMemoryBarrier();
-#endif
}
// Tag the region at "aligned_address" as belonging to us,
// and so put it under the protection of the magazine lock we are holding.
tiny_mag_ptr->mag_last_region = aligned_address;
BYTES_USED_FOR_TINY_REGION(aligned_address) = TINY_BYTES_FOR_MSIZE(msize);
- ptr = aligned_address;
+#if ASLR_INTERNAL
+ int offset_msize = malloc_entropy[0] & TINY_ENTROPY_MASK;
+#if DEBUG_MALLOC
+ if (getenv("MallocASLRForce")) offset_msize = strtol(getenv("MallocASLRForce"), NULL, 0) & TINY_ENTROPY_MASK;
+ if (getenv("MallocASLRPrint")) malloc_printf("Region: %p offset: %d\n", aligned_address, offset_msize);
+#endif
+#else
+ int offset_msize = 0;
+#endif
+ ptr = (void *)((uintptr_t) aligned_address + TINY_BYTES_FOR_MSIZE(offset_msize));
set_tiny_meta_header_in_use(ptr, msize);
tiny_mag_ptr->mag_num_objects++;
tiny_mag_ptr->mag_num_bytes_in_objects += TINY_BYTES_FOR_MSIZE(msize);
// We put a header on the last block so that it appears in use (for coalescing, etc...)
set_tiny_meta_header_in_use_1((void *)((uintptr_t)ptr + TINY_BYTES_FOR_MSIZE(msize)));
- tiny_mag_ptr->mag_bytes_free_at_end = TINY_BYTES_FOR_MSIZE(NUM_TINY_BLOCKS - msize);
+ tiny_mag_ptr->mag_bytes_free_at_end = TINY_BYTES_FOR_MSIZE(NUM_TINY_BLOCKS - msize - offset_msize);
- // connect to magazine as first node (it's maximally sparse at this moment)
- recirc_list_splice_first(szone, tiny_mag_ptr, REGION_TRAILER_FOR_TINY_REGION(aligned_address));
+#if ASLR_INTERNAL
+ // Put a header on the previous block for same reason
+ tiny_mag_ptr->mag_bytes_free_at_start = TINY_BYTES_FOR_MSIZE(offset_msize);
+ if (offset_msize) {
+ set_tiny_meta_header_in_use_1((void *)((uintptr_t)ptr - TINY_QUANTUM));
+ }
+#else
+ tiny_mag_ptr->mag_bytes_free_at_start = 0;
+#endif
+
+ // connect to magazine as last node
+ recirc_list_splice_last(szone, tiny_mag_ptr, REGION_TRAILER_FOR_TINY_REGION(aligned_address));
#if DEBUG_MALLOC
if (LOG(szone,ptr)) {
return ptr;
}
+static INLINE void *
+tiny_try_shrink_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_good_size)
+{
+ msize_t new_msize = TINY_MSIZE_FOR_BYTES(new_good_size);
+ msize_t mshrinkage = TINY_MSIZE_FOR_BYTES(old_size) - new_msize;
+
+ if (mshrinkage) {
+ void *q = (void *)((uintptr_t)ptr + TINY_BYTES_FOR_MSIZE(new_msize));
+ magazine_t *tiny_mag_ptr = mag_lock_zine_for_region_trailer(szone, szone->tiny_magazines,
+ REGION_TRAILER_FOR_TINY_REGION(TINY_REGION_FOR_PTR(ptr)),
+ MAGAZINE_INDEX_FOR_TINY_REGION(TINY_REGION_FOR_PTR(ptr)));
+
+ // Mark q as block header and in-use, thus creating two blocks.
+ set_tiny_meta_header_in_use(q, mshrinkage);
+ tiny_mag_ptr->mag_num_objects++;
+
+ SZONE_MAGAZINE_PTR_UNLOCK(szone,tiny_mag_ptr);
+ szone_free(szone, q); // avoid inlining free_tiny(szone, q, ...);
+ }
+ return ptr;
+}
+
static INLINE boolean_t
tiny_try_realloc_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_size)
{
/* establish region limits */
start = (uintptr_t)TINY_REGION_ADDRESS(region);
ptr = start;
+ if (region == tiny_mag_ptr->mag_last_region) {
+ ptr += tiny_mag_ptr->mag_bytes_free_at_start;
+
+ /*
+ * Check the leading block's integrity here also.
+ */
+ if (tiny_mag_ptr->mag_bytes_free_at_start) {
+ msize = get_tiny_meta_header((void *)(ptr - TINY_QUANTUM), &is_free);
+ if (is_free || (msize != 1)) {
+ malloc_printf("*** invariant broken for leader block %p - %d %d\n", ptr - TINY_QUANTUM, msize, is_free);
+ }
+ }
+ }
region_end = (uintptr_t)TINY_REGION_END(region);
/*
msize_t msize;
void *mapped_ptr;
unsigned bit;
- vm_address_t mag_last_free_ptr = 0;
- msize_t mag_last_free_msize = 0;
-
+ magazine_t *tiny_mag_base = NULL;
+
region_hash_generation_t *trg_ptr;
err = reader(task, (vm_address_t)szone->tiny_region_generation, sizeof(region_hash_generation_t), (void **)&trg_ptr);
if (err) return err;
err = reader(task, (vm_address_t)trg_ptr->hashed_regions, sizeof(region_t) * num_regions, (void **)®ions);
if (err) return err;
+ if (type_mask & MALLOC_PTR_IN_USE_RANGE_TYPE) {
+ // Map in all active magazines. Do this outside the iteration over regions.
+ err = reader(task, (vm_address_t)(szone->tiny_magazines),
+ szone->num_tiny_magazines*sizeof(magazine_t),(void **)&tiny_mag_base);
+ if (err) return err;
+ }
+
for (index = 0; index < num_regions; ++index) {
region = regions[index];
if (HASHRING_OPEN_ENTRY != region && HASHRING_REGION_DEALLOCATED != region) {
recorder(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &ptr_range, 1);
}
if (type_mask & MALLOC_PTR_IN_USE_RANGE_TYPE) {
+ void *mag_last_free;
+ vm_address_t mag_last_free_ptr = 0;
+ msize_t mag_last_free_msize = 0;
+
err = reader(task, range.address, range.size, (void **)&mapped_region);
if (err)
return err;
mag_index_t mag_index = MAGAZINE_INDEX_FOR_TINY_REGION(mapped_region);
- magazine_t *tiny_mag_ptr;
- err = reader(task, (vm_address_t)&(szone->tiny_magazines[mag_index]), sizeof(magazine_t),
- (void **)&tiny_mag_ptr);
- if (err) return err;
-
- void *mag_last_free = tiny_mag_ptr->mag_last_free;
- if (mag_last_free) {
- mag_last_free_ptr = (uintptr_t) mag_last_free & ~(TINY_QUANTUM - 1);
- mag_last_free_msize = (uintptr_t) mag_last_free & (TINY_QUANTUM - 1);
+ magazine_t *tiny_mag_ptr = tiny_mag_base + mag_index;
+
+ if (DEPOT_MAGAZINE_INDEX != mag_index) {
+ mag_last_free = tiny_mag_ptr->mag_last_free;
+ if (mag_last_free) {
+ mag_last_free_ptr = (uintptr_t) mag_last_free & ~(TINY_QUANTUM - 1);
+ mag_last_free_msize = (uintptr_t) mag_last_free & (TINY_QUANTUM - 1);
+ }
+ } else {
+ for (mag_index = 0; mag_index < szone->num_tiny_magazines; mag_index++) {
+ if ((void *)range.address == (tiny_mag_base + mag_index)->mag_last_free_rgn) {
+ mag_last_free = (tiny_mag_base + mag_index)->mag_last_free;
+ if (mag_last_free) {
+ mag_last_free_ptr = (uintptr_t) mag_last_free & ~(TINY_QUANTUM - 1);
+ mag_last_free_msize = (uintptr_t) mag_last_free & (TINY_QUANTUM - 1);
+ }
+ }
+ }
}
block_header = (uint32_t *)(mapped_region + TINY_METADATA_START + sizeof(region_trailer_t));
in_use = TINY_INUSE_FOR_HEADER(block_header);
block_index = 0;
block_limit = NUM_TINY_BLOCKS;
- if (region == tiny_mag_ptr->mag_last_region)
+ if (region == tiny_mag_ptr->mag_last_region) {
+ block_index += TINY_MSIZE_FOR_BYTES(tiny_mag_ptr->mag_bytes_free_at_start);
block_limit -= TINY_MSIZE_FOR_BYTES(tiny_mag_ptr->mag_bytes_free_at_end);
+ }
while (block_index < block_limit) {
vm_size_t block_offset = TINY_BYTES_FOR_MSIZE(block_index);
#endif
goto return_tiny_alloc;
}
+#if ASLR_INTERNAL
+ // Try from start if nothing left at end
+ if (tiny_mag_ptr->mag_bytes_free_at_start >= TINY_BYTES_FOR_MSIZE(msize)) {
+ ptr = (free_list_t *)(TINY_REGION_ADDRESS(tiny_mag_ptr->mag_last_region) +
+ tiny_mag_ptr->mag_bytes_free_at_start - TINY_BYTES_FOR_MSIZE(msize));
+ tiny_mag_ptr->mag_bytes_free_at_start -= TINY_BYTES_FOR_MSIZE(msize);
+ if (tiny_mag_ptr->mag_bytes_free_at_start) {
+ // let's add an in use block before ptr to serve as boundary
+ set_tiny_meta_header_in_use_1((unsigned char *)ptr - TINY_QUANTUM);
+ }
+ this_msize = msize;
+#if DEBUG_MALLOC
+ if (LOG(szone, ptr)) {
+ malloc_printf("in tiny_malloc_from_free_list(), from start ptr=%p, msize=%d\n", ptr, msize);
+ }
+#endif
+ goto return_tiny_alloc;
+ }
+#endif
return NULL;
add_leftover_and_proceed:
if ((((uintptr_t)ptr) & (TINY_QUANTUM - 1)) == msize) {
// we have a winner
tiny_mag_ptr->mag_last_free = NULL;
+ tiny_mag_ptr->mag_last_free_rgn = NULL;
SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
CHECK(szone, __PRETTY_FUNCTION__);
ptr = (void *)((uintptr_t)ptr & ~ (TINY_QUANTUM - 1));
}
#endif /* TINY_CACHE */
- ptr = tiny_malloc_from_free_list(szone, tiny_mag_ptr, mag_index, msize);
- if (ptr) {
- SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
- CHECK(szone, __PRETTY_FUNCTION__);
- if (cleared_requested) {
- memset(ptr, 0, TINY_BYTES_FOR_MSIZE(msize));
- }
- return ptr;
- }
-
- if (tiny_get_region_from_depot(szone, tiny_mag_ptr, mag_index, msize)) {
+ while (1) {
ptr = tiny_malloc_from_free_list(szone, tiny_mag_ptr, mag_index, msize);
if (ptr) {
SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
}
return ptr;
}
- }
- ptr = tiny_malloc_from_region_no_lock(szone, tiny_mag_ptr, mag_index, msize);
- // we don't clear because this freshly allocated space is pristine
- SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
- CHECK(szone, __PRETTY_FUNCTION__);
- return ptr;
+ if (tiny_get_region_from_depot(szone, tiny_mag_ptr, mag_index, msize)) {
+ ptr = tiny_malloc_from_free_list(szone, tiny_mag_ptr, mag_index, msize);
+ if (ptr) {
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
+ CHECK(szone, __PRETTY_FUNCTION__);
+ if (cleared_requested) {
+ memset(ptr, 0, TINY_BYTES_FOR_MSIZE(msize));
+ }
+ return ptr;
+ }
+ }
+
+ // The magazine is exhausted. A new region (heap) must be allocated to satisfy this call to malloc().
+ // The allocation, an mmap() system call, will be performed outside the magazine spin locks by the first
+ // thread that suffers the exhaustion. That thread sets "alloc_underway" and enters a critical section.
+ // Threads arriving here later are excluded from the critical section, yield the CPU, and then retry the
+ // allocation. After some time the magazine is resupplied, the original thread leaves with its allocation,
+ // and retry-ing threads succeed in the code just above.
+ if (!tiny_mag_ptr->alloc_underway) {
+ void *fresh_region;
+
+ // time to create a new region (do this outside the magazine lock)
+ tiny_mag_ptr->alloc_underway = TRUE;
+ OSMemoryBarrier();
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
+ fresh_region = allocate_pages_securely(szone, TINY_REGION_SIZE, TINY_BLOCKS_ALIGN, VM_MEMORY_MALLOC_TINY);
+ SZONE_MAGAZINE_PTR_LOCK(szone, tiny_mag_ptr);
+
+ MAGMALLOC_ALLOCREGION((void *)szone, (int)mag_index, fresh_region, TINY_REGION_SIZE); // DTrace USDT Probe
+
+ if (!fresh_region) { // out of memory!
+ tiny_mag_ptr->alloc_underway = FALSE;
+ OSMemoryBarrier();
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
+ return NULL;
+ }
+
+ ptr = tiny_malloc_from_region_no_lock(szone, tiny_mag_ptr, mag_index, msize, fresh_region);
+
+ // we don't clear because this freshly allocated space is pristine
+ tiny_mag_ptr->alloc_underway = FALSE;
+ OSMemoryBarrier();
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
+ CHECK(szone, __PRETTY_FUNCTION__);
+ return ptr;
+ } else {
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
+ pthread_yield_np();
+ SZONE_MAGAZINE_PTR_LOCK(szone, tiny_mag_ptr);
+ }
+ }
+ /* NOTREACHED */
}
static NOINLINE void
SZONE_MAGAZINE_PTR_LOCK(szone, tiny_mag_ptr);
}
- tiny_free_no_lock(szone, tiny_mag_ptr, mag_index, tiny_region, ptr, msize);
+ if (tiny_free_no_lock(szone, tiny_mag_ptr, mag_index, tiny_region, ptr, msize))
SZONE_MAGAZINE_PTR_UNLOCK(szone, tiny_mag_ptr);
+
CHECK(szone, __PRETTY_FUNCTION__);
}
}
static void
-print_tiny_region(boolean_t verbose, region_t region, size_t bytes_at_end)
+print_tiny_region(boolean_t verbose, region_t region, size_t bytes_at_start, size_t bytes_at_end)
{
unsigned counts[1024];
unsigned in_use = 0;
uintptr_t start = (uintptr_t)TINY_REGION_ADDRESS(region);
- uintptr_t current = start;
+ uintptr_t current = start + bytes_at_end;
uintptr_t limit = (uintptr_t)TINY_REGION_END(region) - bytes_at_end;
boolean_t is_free;
msize_t msize;
_simple_sprintf(b, "Tiny region [%p-%p, %y] \t", (void *)start, TINY_REGION_END(region), (int)TINY_REGION_SIZE);
_simple_sprintf(b, "Magazine=%d \t", MAGAZINE_INDEX_FOR_TINY_REGION(region));
_simple_sprintf(b, "Allocations in use=%d \t Bytes in use=%ly \t", in_use, BYTES_USED_FOR_TINY_REGION(region));
- if (bytes_at_end)
- _simple_sprintf(b, "Untouched=%ly ", bytes_at_end);
+ if (bytes_at_end || bytes_at_start)
+ _simple_sprintf(b, "Untouched=%ly ", bytes_at_end + bytes_at_start);
if (DEPOT_MAGAZINE_INDEX == MAGAZINE_INDEX_FOR_TINY_REGION(region)) {
_simple_sprintf(b, "Advised MADV_FREE=%ly", pgTot);
} else {
void *last_block, *previous_block;
msize_t last_msize, previous_msize, last_index;
- last_block = SMALL_REGION_END(small_mag_ptr->mag_last_region) - small_mag_ptr->mag_bytes_free_at_end;
- last_msize = SMALL_MSIZE_FOR_BYTES(small_mag_ptr->mag_bytes_free_at_end);
-
// It is possible that the block prior to the last block in the region has
// been free'd, but was not coalesced with the free bytes at the end of the
// block, since we treat the bytes at the end of the region as "in use" in
// 'mag_bytes_free_at_end' when freeing the preceding block, rather
// than performing this workaround.
//
+ if (small_mag_ptr->mag_bytes_free_at_end) {
+ last_block = SMALL_REGION_END(small_mag_ptr->mag_last_region) - small_mag_ptr->mag_bytes_free_at_end;
+ last_msize = SMALL_MSIZE_FOR_BYTES(small_mag_ptr->mag_bytes_free_at_end);
+
last_index = SMALL_META_INDEX_FOR_PTR(last_block);
previous_msize = SMALL_PREVIOUS_MSIZE(last_block);
// splice last_block into the free list
small_free_list_add_ptr(szone, small_mag_ptr, last_block, last_msize);
small_mag_ptr->mag_bytes_free_at_end = 0;
+ }
+
+#if ASLR_INTERNAL
+ if (small_mag_ptr->mag_bytes_free_at_start) {
+ last_block = SMALL_REGION_ADDRESS(small_mag_ptr->mag_last_region);
+ last_msize = SMALL_MSIZE_FOR_BYTES(small_mag_ptr->mag_bytes_free_at_start);
+
+ void *next_block = (void *) ((uintptr_t)last_block + small_mag_ptr->mag_bytes_free_at_start);
+ if (SMALL_PTR_IS_FREE(next_block)) {
+ msize_t next_msize = SMALL_PTR_SIZE(next_block);
+
+ small_meta_header_set_middle(SMALL_META_HEADER_FOR_PTR(next_block), SMALL_META_INDEX_FOR_PTR(next_block));
+ small_free_list_remove_ptr(szone, small_mag_ptr, next_block, next_msize);
+ last_msize += next_msize;
+ }
+
+ // splice last_block into the free list
+ small_free_list_add_ptr(szone, small_mag_ptr, last_block, last_msize);
+ small_mag_ptr->mag_bytes_free_at_start = 0;
+ }
+#endif
+
+ // TODO: Will we ever need to coalesce the blocks at the beginning and end when we finalize?
+
small_mag_ptr->mag_last_region = NULL;
}
return total_alloc;
}
-static void
-small_free_scan_depot_madvise_free(szone_t *szone, magazine_t *depot_ptr, region_t r) {
+typedef struct {
+ uint16_t pnum, size;
+} small_pg_pair_t;
+
+static void NOINLINE /* want private stack frame for automatic array */
+small_free_scan_madvise_free(szone_t *szone, magazine_t *depot_ptr, region_t r) {
uintptr_t start = (uintptr_t)SMALL_REGION_ADDRESS(r);
uintptr_t current = start;
uintptr_t limit = (uintptr_t)SMALL_REGION_END(r);
msize_t *meta_headers = SMALL_META_HEADER_FOR_PTR(start);
- boolean_t did_advise = FALSE;
+ small_pg_pair_t advisory[((SMALL_REGION_PAYLOAD_BYTES + vm_page_size - 1) >> vm_page_shift) >> 1]; // 4096bytes stack allocated
+ int advisories = 0;
// Scan the metadata identifying blocks which span one or more pages. Mark the pages MADV_FREE taking care to preserve free list
// management data.
if (is_free && !msize && (current == start)) {
#if DEBUG_MALLOC
// first block is all free
- malloc_printf("*** small_free_scan_depot_madvise_free first block is all free! %p: msize=%d is_free =%d\n",
+ malloc_printf("*** small_free_scan_madvise_free first block is all free! %p: msize=%d is_free =%d\n",
(void *)current, msize, is_free);
#endif
uintptr_t pgLo = round_page(start + sizeof(free_list_t) + sizeof(msize_t));
uintptr_t pgHi = trunc_page(start + SMALL_REGION_SIZE - sizeof(msize_t));
if (pgLo < pgHi) {
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, r, pgLo, pgHi, NULL);
-#else
- madvise_free_range(szone, r, pgLo, pgHi);
-#endif
- did_advise = TRUE;
+ advisory[advisories].pnum = (pgLo - start) >> vm_page_shift;
+ advisory[advisories].size = (pgHi - pgLo) >> vm_page_shift;
+ advisories++;
}
break;
}
if (!msize) {
#if DEBUG_MALLOC
- malloc_printf("*** small_free_scan_depot_madvise_free error with %p: msize=%d is_free =%d\n",
+ malloc_printf("*** small_free_scan_madvise_free error with %p: msize=%d is_free =%d\n",
(void *)current, msize, is_free);
#endif
break;
uintptr_t pgHi = trunc_page(current + SMALL_BYTES_FOR_MSIZE(msize) - sizeof(msize_t));
if (pgLo < pgHi) {
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, r, pgLo, pgHi, NULL);
-#else
- madvise_free_range(szone, r, pgLo, pgHi);
-#endif
- did_advise = TRUE;
+ advisory[advisories].pnum = (pgLo - start) >> vm_page_shift;
+ advisory[advisories].size = (pgHi - pgLo) >> vm_page_shift;
+ advisories++;
}
}
current += SMALL_BYTES_FOR_MSIZE(msize);
}
- if (did_advise) {
- /* Move the node to the tail of the Deopt's recirculation list to delay its re-use. */
- region_trailer_t *node = REGION_TRAILER_FOR_SMALL_REGION(r);
- recirc_list_extract(szone, depot_ptr, node); // excise node from list
- recirc_list_splice_last(szone, depot_ptr, node); // connect to magazine as last node
+ if (advisories > 0) {
+ int i;
+
+ OSAtomicIncrement32Barrier(&(REGION_TRAILER_FOR_SMALL_REGION(r)->pinned_to_depot));
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, depot_ptr);
+ for (i = 0; i < advisories; ++i) {
+ uintptr_t addr = (advisory[i].pnum << vm_page_shift) + start;
+ size_t size = advisory[i].size << vm_page_shift;
+
+#if TARGET_OS_EMBEDDED
+ madvise_free_range(szone, r, addr, addr + size, NULL);
+#else
+ madvise_free_range(szone, r, addr, addr + size);
+#endif
+ }
+ SZONE_MAGAZINE_PTR_LOCK(szone, depot_ptr);
+ OSAtomicDecrement32Barrier(&(REGION_TRAILER_FOR_SMALL_REGION(r)->pinned_to_depot));
}
}
-static void
+static region_t
small_free_try_depot_unmap_no_lock(szone_t *szone, magazine_t *depot_ptr, region_trailer_t *node)
{
-#warning Tune Depot headroom
if (0 < node->bytes_used ||
+ 0 < node->pinned_to_depot ||
depot_ptr->recirculation_entries < (szone->num_small_magazines * 2)) {
- return;
+ return NULL;
}
- // disconnect node from Depot
+ // disconnect first node from Depot
recirc_list_extract(szone, depot_ptr, node);
// Iterate the region pulling its free entries off the (locked) Depot's free list
rgnhdl_t pSlot = hash_lookup_region_no_lock(szone->small_region_generation->hashed_regions,
szone->small_region_generation->num_regions_allocated,
szone->small_region_generation->num_regions_allocated_shift, sparse_region);
+ if (NULL == pSlot) {
+ szone_error(szone, 1, "small_free_try_depot_unmap_no_lock hash lookup failed:", NULL, "%p\n", sparse_region);
+ return NULL;
+ }
*pSlot = HASHRING_REGION_DEALLOCATED;
depot_ptr->num_bytes_in_magazine -= SMALL_REGION_PAYLOAD_BYTES;
-#if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1))) /* GCC 4.1 and forward supports atomic builtins */
__sync_fetch_and_add( &(szone->num_small_regions_dealloc), 1); // Atomically increment num_small_regions_dealloc
-#else
-#ifdef __LP64__
- OSAtomicIncrement64( (volatile int64_t *)&(szone->num_small_regions_dealloc) );
-#else
- OSAtomicIncrement32( (volatile int32_t *)&(szone->num_small_regions_dealloc) );
-#endif
-#endif
- // Transfer ownership of the region back to the OS
- SZONE_MAGAZINE_PTR_UNLOCK(szone, depot_ptr); // Avoid denial of service to Depot while in kernel
- deallocate_pages(szone, sparse_region, SMALL_REGION_SIZE, 0);
- SZONE_MAGAZINE_PTR_LOCK(szone, depot_ptr);
-
- MAGMALLOC_DEALLOCREGION((void *)szone, (void *)sparse_region); // DTrace USDT Probe
+ // Caller will transfer ownership of the region back to the OS with no locks held
+ MAGMALLOC_DEALLOCREGION((void *)szone, (void *)sparse_region, SMALL_REGION_SIZE); // DTrace USDT Probe
+ return sparse_region;
} else {
szone_error(szone, 1, "small_free_try_depot_unmap_no_lock objects_in_use not zero:", NULL, "%d\n", objects_in_use);
+ return NULL;
}
}
-static void
+static boolean_t
small_free_do_recirc_to_depot(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index)
{
// The entire magazine crossed the "emptiness threshold". Transfer a region
#if DEBUG_MALLOC
malloc_printf("*** small_free_do_recirc_to_depot end of list\n");
#endif
- return;
+ return TRUE; // Caller must SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
}
region_t sparse_region = SMALL_REGION_FOR_PTR(node);
- // Deal with unclaimed memory -- mag_bytes_free_at_end
- if (sparse_region == small_mag_ptr->mag_last_region && small_mag_ptr->mag_bytes_free_at_end) {
+ // Deal with unclaimed memory -- mag_bytes_free_at_end or mag_bytes_free_at start
+ if (sparse_region == small_mag_ptr->mag_last_region && (small_mag_ptr->mag_bytes_free_at_end || small_mag_ptr->mag_bytes_free_at_start)) {
small_finalize_region(szone, small_mag_ptr);
}
- // disconnect first node from magazine
+ // disconnect "suitable" node from magazine
recirc_list_extract(szone, small_mag_ptr, node);
// Iterate the region pulling its free entries off its (locked) magazine's free list
// this will cause small_free_list_add_ptr called by small_free_reattach_region to use
// the depot as its target magazine, rather than magazine formerly associated with sparse_region
MAGAZINE_INDEX_FOR_SMALL_REGION(sparse_region) = DEPOT_MAGAZINE_INDEX;
+ node->pinned_to_depot = 0;
// Iterate the region putting its free entries on Depot's free list
size_t bytes_inplay = small_free_reattach_region(szone, depot_ptr, sparse_region);
small_mag_ptr->num_bytes_in_magazine -= SMALL_REGION_PAYLOAD_BYTES;
small_mag_ptr->mag_num_objects -= objects_in_use;
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr); // Unlock the originating magazine
+
depot_ptr->mag_num_bytes_in_objects += bytes_inplay;
depot_ptr->num_bytes_in_magazine += SMALL_REGION_PAYLOAD_BYTES;
depot_ptr->mag_num_objects += objects_in_use;
- // connect to Depot as first node
- recirc_list_splice_first(szone, depot_ptr, node);
+ // connect to Depot as last node
+ recirc_list_splice_last(szone, depot_ptr, node);
- MAGMALLOC_RECIRCREGION((void *)szone, (int)mag_index, (int)BYTES_USED_FOR_SMALL_REGION(sparse_region)); // DTrace USDT Probe
+ MAGMALLOC_RECIRCREGION((void *)szone, (int)mag_index, (void *)sparse_region, SMALL_REGION_SIZE,
+ (int)BYTES_USED_FOR_SMALL_REGION(sparse_region)); // DTrace USDT Probe
// Mark free'd dirty pages with MADV_FREE to reduce memory pressure
- small_free_scan_depot_madvise_free(szone, depot_ptr, sparse_region);
+ small_free_scan_madvise_free(szone, depot_ptr, sparse_region);
- // If the region is entirely empty vm_deallocate() it
- small_free_try_depot_unmap_no_lock(szone, depot_ptr, node);
-
+ // If the region is entirely empty vm_deallocate() it outside the depot lock
+ region_t r_dealloc = small_free_try_depot_unmap_no_lock(szone, depot_ptr, node);
SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
+ if (r_dealloc)
+ deallocate_pages(szone, r_dealloc, SMALL_REGION_SIZE, 0);
+ return FALSE; // Caller need not unlock the originating magazine
}
static region_t
SZONE_MAGAZINE_PTR_LOCK(szone,depot_ptr);
- // Appropriate one of the Depot's regions that can satisfy requested msize.
- region_t sparse_region = small_find_msize_region(szone, depot_ptr, DEPOT_MAGAZINE_INDEX, msize);
- if (NULL == sparse_region) { // Depot empty?
+ // Appropriate a Depot'd region that can satisfy requested msize.
+ region_trailer_t *node;
+ region_t sparse_region;
+
+ while (1) {
+ sparse_region = small_find_msize_region(szone, depot_ptr, DEPOT_MAGAZINE_INDEX, msize);
+ if (NULL == sparse_region) { // Depot empty?
+ SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
+ return 0;
+ }
+
+ node = REGION_TRAILER_FOR_SMALL_REGION(sparse_region);
+ if (0 >= node->pinned_to_depot)
+ break;
+
SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
- return 0;
+ pthread_yield_np();
+ SZONE_MAGAZINE_PTR_LOCK(szone,depot_ptr);
}
- region_trailer_t *node = REGION_TRAILER_FOR_SMALL_REGION(sparse_region);
// disconnect node from Depot
recirc_list_extract(szone, depot_ptr, node);
// Transfer ownership of the region
MAGAZINE_INDEX_FOR_SMALL_REGION(sparse_region) = mag_index;
+ node->pinned_to_depot = 0;
// Iterate the region putting its free entries on its new (locked) magazine's free list
size_t bytes_inplay = small_free_reattach_region(szone, small_mag_ptr, sparse_region);
small_mag_ptr->num_bytes_in_magazine += SMALL_REGION_PAYLOAD_BYTES;
small_mag_ptr->mag_num_objects += objects_in_use;
- // connect to magazine as first node (it's maximally sparse at this moment)
+ // connect to magazine as first node
recirc_list_splice_first(szone, small_mag_ptr, node);
SZONE_MAGAZINE_PTR_UNLOCK(szone,depot_ptr);
-#if !TARGET_OS_EMBEDDED
+ // madvise() outside the Depot lock
+#if TARGET_OS_EMBEDDED
+ if (node->failedREUSE) {
+#else
if (node->failedREUSE ||
-1 == madvise((void *)sparse_region, SMALL_REGION_PAYLOAD_BYTES, MADV_FREE_REUSE)) {
+#endif
/* -1 return: VM map entry change makes this unfit for reuse. Something evil lurks. */
#if DEBUG_MADVISE
- szone_error(szone, 0, "small_get_region_from_depot madvise(..., MADV_FREE_REUSE) failed", sparse_region, "length=%d\n", SMALL_REGION_PAYLOAD_BYTES);
+ szone_error(szone, 0, "small_get_region_from_depot madvise(..., MADV_FREE_REUSE) failed",
+ sparse_region, "length=%d\n", SMALL_REGION_PAYLOAD_BYTES);
#endif
node->failedREUSE = TRUE;
}
-#endif
- MAGMALLOC_DEPOTREGION((void *)szone, (int)mag_index, (int)BYTES_USED_FOR_SMALL_REGION(sparse_region)); // DTrace USDT Probe
+ MAGMALLOC_DEPOTREGION((void *)szone, (int)mag_index, (void *)sparse_region, SMALL_REGION_SIZE,
+ (int)BYTES_USED_FOR_SMALL_REGION(sparse_region)); // DTrace USDT Probe
return 1;
}
-#warning Tune K and f!
#define K 1.5 // headroom measured in number of 8Mb regions
#define DENSITY_THRESHOLD(a) \
((a) - ((a) >> 2)) // "Emptiness" f = 0.25, so "Density" is (1 - f)*a. Generally: ((a) - ((a) >> -log2(f)))
-static INLINE void
+static INLINE boolean_t
small_free_no_lock(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index, region_t region, void *ptr, msize_t msize)
{
msize_t *meta_headers = SMALL_META_HEADER_FOR_PTR(ptr);
msize_t next_index = index + msize;
msize_t previous_msize, next_msize;
void *previous;
- boolean_t did_prepend = FALSE;
- boolean_t did_append = FALSE;
#if DEBUG_MALLOC
if (LOG(szone,ptr)) {
malloc_printf("in small_free_no_lock(), ptr=%p, msize=%d\n", ptr, msize);
}
- if (! msize) {
+ if (!msize) {
szone_error(szone, 1, "trying to free small block that is too small", ptr,
"in small_free_no_lock(), ptr=%p, msize=%d\n", ptr, msize);
}
if (meta_headers[index - previous_msize] == (previous_msize | SMALL_IS_FREE)) {
previous = (void *)((uintptr_t)ptr - SMALL_BYTES_FOR_MSIZE(previous_msize));
// previous is really to be coalesced
- did_prepend = TRUE;
#if DEBUG_MALLOC
if (LOG(szone, ptr) || LOG(szone,previous)) {
malloc_printf("in small_free_no_lock(), coalesced backwards for %p previous=%p\n", ptr, previous);
// We try to coalesce with the next block
if ((next_block < SMALL_REGION_END(region)) && (meta_headers[next_index] & SMALL_IS_FREE)) {
// next block is free, we coalesce
- did_append = TRUE;
next_msize = meta_headers[next_index] & ~ SMALL_IS_FREE;
#if DEBUG_MALLOC
if (LOG(szone,ptr))
size_t a = small_mag_ptr->num_bytes_in_magazine; // Total bytes allocated to this magazine
size_t u = small_mag_ptr->mag_num_bytes_in_objects; // In use (malloc'd) from this magaqzine
- if (a - u > ((3 * SMALL_REGION_PAYLOAD_BYTES) / 2) && u < DENSITY_THRESHOLD(a))
- small_free_do_recirc_to_depot(szone, small_mag_ptr, mag_index);
+ if (a - u > ((3 * SMALL_REGION_PAYLOAD_BYTES) / 2) && u < DENSITY_THRESHOLD(a)) {
+ return small_free_do_recirc_to_depot(szone, small_mag_ptr, mag_index);
+ }
} else {
#endif
// Freed to Depot. N.B. Lock on small_magazines[DEPOT_MAGAZINE_INDEX] is already held
+ // Calcuate the first page in the coalesced block that would be safe to mark MADV_FREE
uintptr_t safe_ptr = (uintptr_t)ptr + sizeof(free_list_t) + sizeof(msize_t);
uintptr_t round_safe = round_page(safe_ptr);
+ // Calcuate the last page in the coalesced block that would be safe to mark MADV_FREE
uintptr_t safe_extent = (uintptr_t)ptr + SMALL_BYTES_FOR_MSIZE(msize) - sizeof(msize_t);
uintptr_t trunc_extent = trunc_page(safe_extent);
- // The newly freed block may complete a span of bytes that cover a page. Mark it with MADV_FREE.
+ // The newly freed block may complete a span of bytes that cover one or more pages. Mark the span with MADV_FREE.
if (round_safe < trunc_extent) { // Safe area covers a page (perhaps many)
- if (did_prepend & did_append) { // Coalesced preceding with original_ptr *and* with following
- uintptr_t trunc_safe_prev = trunc_page((uintptr_t)original_ptr - sizeof(msize_t));
- uintptr_t rnd_safe_follow =
- round_page((uintptr_t)original_ptr + original_size + sizeof(free_list_t) + sizeof(msize_t));
-
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), MIN(rnd_safe_follow, trunc_extent), &szone->last_small_advise);
-#else
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), MIN(rnd_safe_follow, trunc_extent));
-#endif
- } else if (did_prepend) { // Coalesced preceding with original_ptr
- uintptr_t trunc_safe_prev = trunc_page((uintptr_t)original_ptr - sizeof(msize_t));
-
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), trunc_extent, &szone->last_small_advise);
-#else
- madvise_free_range(szone, region, MAX(round_safe, trunc_safe_prev), trunc_extent);
-#endif
- } else if (did_append) { // Coalesced original_ptr with following
- uintptr_t rnd_safe_follow =
- round_page((uintptr_t)original_ptr + original_size + sizeof(free_list_t) + sizeof(msize_t));
-
-#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, region, round_safe, MIN(rnd_safe_follow, trunc_extent), &szone->last_small_advise);
-#else
- madvise_free_range(szone, region, round_safe, MIN(rnd_safe_follow, trunc_extent));
-#endif
- } else // Isolated free
+ uintptr_t lo = trunc_page((uintptr_t)original_ptr);
+ uintptr_t hi = round_page((uintptr_t)original_ptr + original_size);
+
+ OSAtomicIncrement32Barrier(&(node->pinned_to_depot));
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
#if TARGET_OS_EMBEDDED
- madvise_free_range(szone, region, round_safe, trunc_extent, &szone->last_small_advise);
+ madvise_free_range(szone, region, MAX(round_safe, lo), MIN(trunc_extent, hi), &szone->last_small_advise);
#else
- madvise_free_range(szone, region, round_safe, trunc_extent);
+ madvise_free_range(szone, region, MAX(round_safe, lo), MIN(trunc_extent, hi));
#endif
- }
+ SZONE_MAGAZINE_PTR_LOCK(szone, small_mag_ptr);
+ OSAtomicDecrement32Barrier(&(node->pinned_to_depot));
+ }
#if !TARGET_OS_EMBEDDED
- if (0 < bytes_used) {
+ if (0 < bytes_used || 0 < node->pinned_to_depot) {
/* Depot'd region is still live. Leave it in place on the Depot's recirculation list
so as to avoid thrashing between the Depot's free list and a magazines's free list
with detach_region/reattach_region */
} else {
/* Depot'd region is just now empty. Consider return to OS. */
- region_trailer_t *node = REGION_TRAILER_FOR_SMALL_REGION(region);
- magazine_t *depot_ptr = &(szone->small_magazines[DEPOT_MAGAZINE_INDEX]);
- small_free_try_depot_unmap_no_lock(szone, depot_ptr, node);
+ region_t r_dealloc = small_free_try_depot_unmap_no_lock(szone, small_mag_ptr, node);
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
+ if (r_dealloc)
+ deallocate_pages(szone, r_dealloc, SMALL_REGION_SIZE, 0);
+ return FALSE; // Caller need not unlock
}
}
#endif
+
+ return TRUE; // Caller must do SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr)
}
// Allocates from the last region or a freshly allocated region
static void *
-small_malloc_from_region_no_lock(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index, msize_t msize)
+small_malloc_from_region_no_lock(szone_t *szone, magazine_t *small_mag_ptr, mag_index_t mag_index,
+ msize_t msize, void *aligned_address)
{
- void *ptr, *aligned_address;
+ void *ptr;
- // Before anything we transform the mag_bytes_free_at_end - if any - to a regular free block
+ // Before anything we transform the mag_bytes_free_at_end or mag_bytes_free_at_start - if any - to a regular free block
/* FIXME: last_block needs to be coalesced with previous entry if free, <rdar://5462322> */
- if (small_mag_ptr->mag_bytes_free_at_end)
+ if (small_mag_ptr->mag_bytes_free_at_end || small_mag_ptr->mag_bytes_free_at_start)
small_finalize_region(szone, small_mag_ptr);
- // time to create a new region
- aligned_address = allocate_pages(szone, SMALL_REGION_SIZE, SMALL_BLOCKS_ALIGN, 0, VM_MEMORY_MALLOC_SMALL);
- if (!aligned_address)
- return NULL;
-
- MAGMALLOC_ALLOCREGION((void *)szone, (int)mag_index); // DTrace USDT Probe
-
// Here find the only place in smallville that (infrequently) takes the small_regions_lock.
// Only one thread at a time should be permitted to assess the density of the hash
// ring and adjust if needed.
// Throw the switch to atomically advance to the next generation.
szone->small_region_generation = szone->small_region_generation->nextgen;
// Ensure everyone sees the advance.
-#if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1))) /* GCC 4.1 and forward supports atomic builtins */
- __sync_synchronize();
-#else
OSMemoryBarrier();
-#endif
}
// Tag the region at "aligned_address" as belonging to us,
// and so put it under the protection of the magazine lock we are holding.
small_mag_ptr->mag_last_region = aligned_address;
BYTES_USED_FOR_SMALL_REGION(aligned_address) = SMALL_BYTES_FOR_MSIZE(msize);
- ptr = aligned_address;
- small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(ptr), 0, msize);
+#if ASLR_INTERNAL
+ int offset_msize = malloc_entropy[1] & SMALL_ENTROPY_MASK;
+#if DEBUG_MALLOC
+ if (getenv("MallocASLRForce")) offset_msize = strtol(getenv("MallocASLRForce"), NULL, 0) & SMALL_ENTROPY_MASK;
+ if (getenv("MallocASLRPrint")) malloc_printf("Region: %p offset: %d\n", aligned_address, offset_msize);
+#endif
+#else
+ int offset_msize = 0;
+#endif
+ ptr = (void *)((uintptr_t) aligned_address + SMALL_BYTES_FOR_MSIZE(offset_msize));
+ small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(ptr), offset_msize, msize);
small_mag_ptr->mag_num_objects++;
small_mag_ptr->mag_num_bytes_in_objects += SMALL_BYTES_FOR_MSIZE(msize);
small_mag_ptr->num_bytes_in_magazine += SMALL_REGION_PAYLOAD_BYTES;
- // add a big free block
- small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(ptr) , msize, NUM_SMALL_BLOCKS - msize);
- small_mag_ptr->mag_bytes_free_at_end = SMALL_BYTES_FOR_MSIZE(NUM_SMALL_BLOCKS - msize);
+ // add a big free block at the end
+ small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(ptr), offset_msize + msize, NUM_SMALL_BLOCKS - msize - offset_msize);
+ small_mag_ptr->mag_bytes_free_at_end = SMALL_BYTES_FOR_MSIZE(NUM_SMALL_BLOCKS - msize - offset_msize);
+
+#if ASLR_INTERNAL
+ // add a big free block at the start
+ small_mag_ptr->mag_bytes_free_at_start = SMALL_BYTES_FOR_MSIZE(offset_msize);
+ if (offset_msize) {
+ small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(ptr), 0, offset_msize);
+ }
+#else
+ small_mag_ptr->mag_bytes_free_at_start = 0;
+#endif
+
+ // connect to magazine as last node
+ recirc_list_splice_last(szone, small_mag_ptr, REGION_TRAILER_FOR_SMALL_REGION(aligned_address));
+
+ return ptr;
+}
+
+static INLINE void *
+small_try_shrink_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_good_size)
+{
+ msize_t new_msize = SMALL_MSIZE_FOR_BYTES(new_good_size);
+ msize_t mshrinkage = SMALL_MSIZE_FOR_BYTES(old_size) - new_msize;
+
+ if (mshrinkage) {
+ void *q = (void *)((uintptr_t)ptr + SMALL_BYTES_FOR_MSIZE(new_msize));
+ magazine_t *small_mag_ptr = mag_lock_zine_for_region_trailer(szone, szone->small_magazines,
+ REGION_TRAILER_FOR_SMALL_REGION(SMALL_REGION_FOR_PTR(ptr)),
+ MAGAZINE_INDEX_FOR_SMALL_REGION(SMALL_REGION_FOR_PTR(ptr)));
+
+ // Mark q as block header and in-use, thus creating two blocks.
+ small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(ptr), SMALL_META_INDEX_FOR_PTR(ptr), new_msize);
+ small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(q), SMALL_META_INDEX_FOR_PTR(q), mshrinkage);
+ small_mag_ptr->mag_num_objects++;
- // connect to magazine as first node (it's maximally sparse at this moment)
- recirc_list_splice_first(szone, small_mag_ptr, REGION_TRAILER_FOR_SMALL_REGION(aligned_address));
+ SZONE_MAGAZINE_PTR_UNLOCK(szone,small_mag_ptr);
+ szone_free(szone, q); // avoid inlining free_small(szone, q, ...);
+ }
return ptr;
}
small_meta_header_set_in_use(meta_headers, index, new_msize);
#if DEBUG_MALLOC
if (LOG(szone,ptr)) {
- malloc_printf("in szone_realloc(), ptr=%p, msize=%d\n", ptr, *SMALL_METADATA_FOR_PTR(ptr));
+ malloc_printf("in small_try_realloc_in_place(), ptr=%p, msize=%d\n", ptr, *SMALL_METADATA_FOR_PTR(ptr));
}
#endif
small_mag_ptr->mag_num_bytes_in_objects += SMALL_BYTES_FOR_MSIZE(new_msize - old_msize);
// Assumes locked
CHECK_MAGAZINE_PTR_LOCKED(szone, small_mag_ptr, __PRETTY_FUNCTION__);
- if (region == small_mag_ptr->mag_last_region)
+ if (region == small_mag_ptr->mag_last_region) {
+ ptr += small_mag_ptr->mag_bytes_free_at_start;
region_end -= small_mag_ptr->mag_bytes_free_at_end;
+ }
while (ptr < region_end) {
index = SMALL_META_INDEX_FOR_PTR(ptr);
unsigned block_limit;
msize_t msize_and_free;
msize_t msize;
- vm_address_t mag_last_free_ptr = 0;
- msize_t mag_last_free_msize = 0;
-
+ magazine_t *small_mag_base = NULL;
+
region_hash_generation_t *srg_ptr;
err = reader(task, (vm_address_t)szone->small_region_generation, sizeof(region_hash_generation_t), (void **)&srg_ptr);
if (err) return err;
err = reader(task, (vm_address_t)srg_ptr->hashed_regions, sizeof(region_t) * num_regions, (void **)®ions);
if (err) return err;
+ if (type_mask & MALLOC_PTR_IN_USE_RANGE_TYPE) {
+ // Map in all active magazines. Do this outside the iteration over regions.
+ err = reader(task, (vm_address_t)(szone->small_magazines),
+ szone->num_small_magazines*sizeof(magazine_t),(void **)&small_mag_base);
+ if (err) return err;
+ }
+
for (index = 0; index < num_regions; ++index) {
region = regions[index];
if (HASHRING_OPEN_ENTRY != region && HASHRING_REGION_DEALLOCATED != region) {
recorder(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &ptr_range, 1);
}
if (type_mask & MALLOC_PTR_IN_USE_RANGE_TYPE) {
+ void *mag_last_free;
+ vm_address_t mag_last_free_ptr = 0;
+ msize_t mag_last_free_msize = 0;
+
err = reader(task, range.address, range.size, (void **)&mapped_region);
if (err)
return err;
mag_index_t mag_index = MAGAZINE_INDEX_FOR_SMALL_REGION(mapped_region);
- magazine_t *small_mag_ptr;
- err = reader(task, (vm_address_t)&(szone->small_magazines[mag_index]), sizeof(magazine_t),
- (void **)&small_mag_ptr);
- if (err) return err;
-
- void *mag_last_free = small_mag_ptr->mag_last_free;
- if (mag_last_free) {
- mag_last_free_ptr = (uintptr_t) mag_last_free & ~(SMALL_QUANTUM - 1);
- mag_last_free_msize = (uintptr_t) mag_last_free & (SMALL_QUANTUM - 1);
+ magazine_t *small_mag_ptr = small_mag_base + mag_index;
+
+ if (DEPOT_MAGAZINE_INDEX != mag_index) {
+ mag_last_free = small_mag_ptr->mag_last_free;
+ if (mag_last_free) {
+ mag_last_free_ptr = (uintptr_t) mag_last_free & ~(SMALL_QUANTUM - 1);
+ mag_last_free_msize = (uintptr_t) mag_last_free & (SMALL_QUANTUM - 1);
+ }
+ } else {
+ for (mag_index = 0; mag_index < szone->num_small_magazines; mag_index++) {
+ if ((void *)range.address == (small_mag_base + mag_index)->mag_last_free_rgn) {
+ mag_last_free = (small_mag_base + mag_index)->mag_last_free;
+ if (mag_last_free) {
+ mag_last_free_ptr = (uintptr_t) mag_last_free & ~(SMALL_QUANTUM - 1);
+ mag_last_free_msize = (uintptr_t) mag_last_free & (SMALL_QUANTUM - 1);
+ }
+ }
+ }
}
block_header = (msize_t *)(mapped_region + SMALL_METADATA_START + sizeof(region_trailer_t));
block_index = 0;
block_limit = NUM_SMALL_BLOCKS;
- if (region == small_mag_ptr->mag_last_region)
+ if (region == small_mag_ptr->mag_last_region) {
+ block_index += SMALL_MSIZE_FOR_BYTES(small_mag_ptr->mag_bytes_free_at_start);
block_limit -= SMALL_MSIZE_FOR_BYTES(small_mag_ptr->mag_bytes_free_at_end);
+ }
while (block_index < block_limit) {
msize_and_free = block_header[block_index];
msize = msize_and_free & ~ SMALL_IS_FREE;
this_msize = msize;
goto return_small_alloc;
}
+#if ASLR_INTERNAL
+ // Try from start if nothing left at end
+ if (small_mag_ptr->mag_bytes_free_at_start >= SMALL_BYTES_FOR_MSIZE(msize)) {
+ ptr = (free_list_t *)(SMALL_REGION_ADDRESS(small_mag_ptr->mag_last_region) +
+ small_mag_ptr->mag_bytes_free_at_start - SMALL_BYTES_FOR_MSIZE(msize));
+ small_mag_ptr->mag_bytes_free_at_start -= SMALL_BYTES_FOR_MSIZE(msize);
+ if (small_mag_ptr->mag_bytes_free_at_start) {
+ // let's mark this block as in use to serve as boundary
+ small_meta_header_set_in_use(SMALL_META_HEADER_FOR_PTR(ptr), 0, SMALL_MSIZE_FOR_BYTES(small_mag_ptr->mag_bytes_free_at_start));
+ }
+ this_msize = msize;
+ goto return_small_alloc;
+ }
+#endif
return NULL;
add_leftover_and_proceed:
if ((((uintptr_t)ptr) & (SMALL_QUANTUM - 1)) == msize) {
// we have a winner
small_mag_ptr->mag_last_free = NULL;
+ small_mag_ptr->mag_last_free_rgn = NULL;
SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
CHECK(szone, __PRETTY_FUNCTION__);
ptr = (void *)((uintptr_t)ptr & ~ (SMALL_QUANTUM - 1));
}
#endif /* SMALL_CACHE */
- ptr = small_malloc_from_free_list(szone, small_mag_ptr, mag_index, msize);
- if (ptr) {
- SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
- CHECK(szone, __PRETTY_FUNCTION__);
- if (cleared_requested) {
- memset(ptr, 0, SMALL_BYTES_FOR_MSIZE(msize));
- }
- return ptr;
- }
-
- if (small_get_region_from_depot(szone, small_mag_ptr, mag_index, msize)) {
+ while(1) {
ptr = small_malloc_from_free_list(szone, small_mag_ptr, mag_index, msize);
if (ptr) {
SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
}
return ptr;
}
- }
- ptr = small_malloc_from_region_no_lock(szone, small_mag_ptr, mag_index, msize);
- // we don't clear because this freshly allocated space is pristine
- SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
- CHECK(szone, __PRETTY_FUNCTION__);
- return ptr;
+ if (small_get_region_from_depot(szone, small_mag_ptr, mag_index, msize)) {
+ ptr = small_malloc_from_free_list(szone, small_mag_ptr, mag_index, msize);
+ if (ptr) {
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
+ CHECK(szone, __PRETTY_FUNCTION__);
+ if (cleared_requested) {
+ memset(ptr, 0, SMALL_BYTES_FOR_MSIZE(msize));
+ }
+ return ptr;
+ }
+ }
+
+ // The magazine is exhausted. A new region (heap) must be allocated to satisfy this call to malloc().
+ // The allocation, an mmap() system call, will be performed outside the magazine spin locks by the first
+ // thread that suffers the exhaustion. That thread sets "alloc_underway" and enters a critical section.
+ // Threads arriving here later are excluded from the critical section, yield the CPU, and then retry the
+ // allocation. After some time the magazine is resupplied, the original thread leaves with its allocation,
+ // and retry-ing threads succeed in the code just above.
+ if (!small_mag_ptr->alloc_underway) {
+ void *fresh_region;
+
+ // time to create a new region (do this outside the magazine lock)
+ small_mag_ptr->alloc_underway = TRUE;
+ OSMemoryBarrier();
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
+ fresh_region = allocate_pages_securely(szone, SMALL_REGION_SIZE, SMALL_BLOCKS_ALIGN, VM_MEMORY_MALLOC_SMALL);
+ SZONE_MAGAZINE_PTR_LOCK(szone, small_mag_ptr);
+
+ MAGMALLOC_ALLOCREGION((void *)szone, (int)mag_index, fresh_region, SMALL_REGION_SIZE); // DTrace USDT Probe
+
+ if (!fresh_region) { // out of memory!
+ small_mag_ptr->alloc_underway = FALSE;
+ OSMemoryBarrier();
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
+ return NULL;
+ }
+
+ ptr = small_malloc_from_region_no_lock(szone, small_mag_ptr, mag_index, msize, fresh_region);
+
+ // we don't clear because this freshly allocated space is pristine
+ small_mag_ptr->alloc_underway = FALSE;
+ OSMemoryBarrier();
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
+ CHECK(szone, __PRETTY_FUNCTION__);
+ return ptr;
+ } else {
+ SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
+ pthread_yield_np();
+ SZONE_MAGAZINE_PTR_LOCK(szone, small_mag_ptr);
+ }
+ }
+ /* NOTREACHED */
}
static NOINLINE void
SZONE_MAGAZINE_PTR_LOCK(szone, small_mag_ptr);
}
- small_free_no_lock(szone, small_mag_ptr, mag_index, small_region, ptr, msize);
+ if (small_free_no_lock(szone, small_mag_ptr, mag_index, small_region, ptr, msize))
SZONE_MAGAZINE_PTR_UNLOCK(szone, small_mag_ptr);
+
CHECK(szone, __PRETTY_FUNCTION__);
}
}
static void
-print_small_region(szone_t *szone, boolean_t verbose, region_t region, size_t bytes_at_end)
+print_small_region(szone_t *szone, boolean_t verbose, region_t region, size_t bytes_at_start, size_t bytes_at_end)
{
unsigned counts[1024];
unsigned in_use = 0;
uintptr_t start = (uintptr_t)SMALL_REGION_ADDRESS(region);
- uintptr_t current = start;
+ uintptr_t current = start + bytes_at_start;
uintptr_t limit = (uintptr_t)SMALL_REGION_END(region) - bytes_at_end;
msize_t msize_and_free;
msize_t msize;
in_use++;
} else {
uintptr_t pgLo = round_page(current + sizeof(free_list_t) + sizeof(msize_t));
- uintptr_t pgHi = trunc_page(current + TINY_BYTES_FOR_MSIZE(msize) - sizeof(msize_t));
+ uintptr_t pgHi = trunc_page(current + SMALL_BYTES_FOR_MSIZE(msize) - sizeof(msize_t));
if (pgLo < pgHi) {
pgTot += (pgHi - pgLo);
_simple_sprintf(b, "Small region [%p-%p, %y] \t", (void *)start, SMALL_REGION_END(region), (int)SMALL_REGION_SIZE);
_simple_sprintf(b, "Magazine=%d \t", MAGAZINE_INDEX_FOR_SMALL_REGION(region));
_simple_sprintf(b, "Allocations in use=%d \t Bytes in use=%ly \t", in_use, BYTES_USED_FOR_SMALL_REGION(region));
- if (bytes_at_end)
- _simple_sprintf(b, "Untouched=%ly ", bytes_at_end);
+ if (bytes_at_end || bytes_at_start)
+ _simple_sprintf(b, "Untouched=%ly ", bytes_at_end + bytes_at_start);
if (DEPOT_MAGAZINE_INDEX == MAGAZINE_INDEX_FOR_SMALL_REGION(region)) {
_simple_sprintf(b, "Advised MADV_FREE=%ly", pgTot);
} else {
range.size = entry->size;
if (szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) {
- protect((void *)range.address, range.size, VM_PROT_READ | VM_PROT_WRITE, szone->debug_flags);
+ protect((void *)range.address, range.size, PROT_READ | PROT_WRITE, szone->debug_flags);
range.address -= vm_page_size;
range.size += 2 * vm_page_size;
}
while (1) { // Scan large_entry_cache for best fit, starting with most recent entry
size_t this_size = szone->large_entry_cache[idx].size;
+ addr = (void *)szone->large_entry_cache[idx].address;
+
+ if (0 == alignment || 0 == (((uintptr_t) addr) & (((uintptr_t) 1 << alignment) - 1))) {
+ if (size == this_size) { // size match!
+ best = idx;
+ best_size = this_size;
+ break;
+ }
- if (size == this_size) { // size match!
- best = idx;
- best_size = this_size;
- break;
- }
-
- if (size <= this_size && this_size < best_size) { // improved fit?
- best = idx;
- best_size = this_size;
+ if (size <= this_size && this_size < best_size) { // improved fit?
+ best = idx;
+ best_size = this_size;
+ }
}
if (idx == stop_idx) // exhausted live ring?
szone->num_large_objects_in_use ++;
szone->num_bytes_in_large_objects += best_size;
if (!was_madvised_reusable)
- szone->large_entry_cache_hoard_bytes -= best_size;
+ szone->large_entry_cache_reserve_bytes -= best_size;
+
+ szone->large_entry_cache_bytes -= best_size;
+
+ if (szone->flotsam_enabled && szone->large_entry_cache_bytes < SZONE_FLOTSAM_THRESHOLD_LOW) {
+ szone->flotsam_enabled = FALSE;
+ }
+
SZONE_UNLOCK(szone);
if (range_to_deallocate.size) {
// Perform the madvise() outside the lock.
// Typically the madvise() is successful and we'll quickly return from this routine.
// In the unusual case of failure, reacquire the lock to unwind.
+#if TARGET_OS_EMBEDDED
+ // Ok to do this madvise on embedded because we won't call MADV_FREE_REUSABLE on a large
+ // cache block twice without MADV_FREE_REUSE in between.
+#endif
if (was_madvised_reusable && -1 == madvise(addr, size, MADV_FREE_REUSE)) {
/* -1 return: VM map entry change makes this unfit for reuse. */
#if DEBUG_MADVISE
- szone_error(szone, 0, "large_malloc madvise(..., MADV_FREE_REUSE) failed", addr, "length=%d\n", size);
+ szone_error(szone, 0, "large_malloc madvise(..., MADV_FREE_REUSE) failed",
+ addr, "length=%d\n", size);
#endif
SZONE_LOCK(szone);
int idx = szone->large_entry_cache_newest, stop_idx = szone->large_entry_cache_oldest;
large_entry_t this_entry = *entry; // Make a local copy, "entry" is volatile when lock is let go.
boolean_t reusable = TRUE;
- boolean_t should_madvise = szone->large_entry_cache_hoard_bytes + this_entry.size > szone->large_entry_cache_hoard_lmit;
+ boolean_t should_madvise = szone->large_entry_cache_reserve_bytes + this_entry.size > szone->large_entry_cache_reserve_limit;
// Already freed?
// [Note that repeated entries in death-row risk vending the same entry subsequently
int state = VM_PURGABLE_NONVOLATILE; // restore to default condition
if (KERN_SUCCESS != vm_purgable_control(mach_task_self(), this_entry.address, VM_PURGABLE_SET_STATE, &state)) {
- malloc_printf("*** can't vm_purgable_control(..., VM_PURGABLE_SET_STATE) for large freed block at %p\n", this_entry.address);
+ malloc_printf("*** can't vm_purgable_control(..., VM_PURGABLE_SET_STATE) for large freed block at %p\n",
+ this_entry.address);
reusable = FALSE;
}
}
if (szone->large_legacy_reset_mprotect) { // Linked for Leopard?
// Accomodate Leopard apps that (illegally) mprotect() their own guard pages on large malloc'd allocations
- kern_return_t err = vm_protect(mach_task_self(), (vm_address_t)(this_entry.address), this_entry.size,
- 0, PROT_READ | PROT_WRITE);
+ int err = mprotect((void *)(this_entry.address), this_entry.size, PROT_READ | PROT_WRITE);
if (err) {
malloc_printf("*** can't reset protection for large freed block at %p\n", this_entry.address);
reusable = FALSE;
}
}
- // madvise(..., MADV_REUSABLE) death-row arrivals if hoarding would exceed large_entry_cache_hoard_lmit
+ // madvise(..., MADV_REUSABLE) death-row arrivals if hoarding would exceed large_entry_cache_reserve_limit
if (should_madvise) {
// Issue madvise to avoid paging out the dirtied free()'d pages in "entry"
MAGMALLOC_MADVFREEREGION((void *)szone, (void *)0, (void *)(this_entry.address), this_entry.size); // DTrace USDT Probe
+#if TARGET_OS_EMBEDDED
+ // Ok to do this madvise on embedded because we won't call MADV_FREE_REUSABLE on a large
+ // cache block twice without MADV_FREE_REUSE in between.
+#endif
if (-1 == madvise((void *)(this_entry.address), this_entry.size, MADV_FREE_REUSABLE)) {
/* -1 return: VM map entry change makes this unfit for reuse. */
#if DEBUG_MADVISE
- szone_error(szone, 0, "free_large madvise(..., MADV_FREE_REUSABLE) failed", (void *)this_entry.address, "length=%d\n", this_entry.size);
+ szone_error(szone, 0, "free_large madvise(..., MADV_FREE_REUSABLE) failed",
+ (void *)this_entry.address, "length=%d\n", this_entry.size);
#endif
reusable = FALSE;
}
// Drop this entry from the cache and deallocate the VM
addr = szone->large_entry_cache[idx].address;
adjsize = szone->large_entry_cache[idx].size;
+ szone->large_entry_cache_bytes -= adjsize;
if (!szone->large_entry_cache[idx].did_madvise_reusable)
- szone->large_entry_cache_hoard_bytes -= adjsize;
+ szone->large_entry_cache_reserve_bytes -= adjsize;
} else {
// Using an unoccupied cache slot
addr = 0;
entry->did_madvise_reusable = should_madvise; // Was madvise()'d above?
if (!should_madvise) // Entered on death-row without madvise() => up the hoard total
- szone->large_entry_cache_hoard_bytes += entry->size;
+ szone->large_entry_cache_reserve_bytes += entry->size;
+ szone->large_entry_cache_bytes += entry->size;
+
+ if (!szone->flotsam_enabled && szone->large_entry_cache_bytes > SZONE_FLOTSAM_THRESHOLD_HIGH) {
+ szone->flotsam_enabled = TRUE;
+ }
+
szone->large_entry_cache[idx] = *entry;
szone->large_entry_cache_newest = idx;
}
}
+static INLINE void *
+large_try_shrink_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_good_size)
+{
+ size_t shrinkage = old_size - new_good_size;
+
+ if (shrinkage) {
+ SZONE_LOCK(szone);
+ /* contract existing large entry */
+ large_entry_t *large_entry = large_entry_for_pointer_no_lock(szone, ptr);
+ if (!large_entry) {
+ szone_error(szone, 1, "large entry reallocated is not properly in table", ptr, NULL);
+ SZONE_UNLOCK(szone);
+ return ptr;
+ }
+
+ large_entry->address = (vm_address_t)ptr;
+ large_entry->size = new_good_size;
+ szone->num_bytes_in_large_objects -= shrinkage;
+ SZONE_UNLOCK(szone); // we release the lock asap
+
+ deallocate_pages(szone, (void *)((uintptr_t)ptr + new_good_size), shrinkage, 0);
+ }
+ return ptr;
+}
+
static INLINE int
large_try_realloc_in_place(szone_t *szone, void *ptr, size_t old_size, size_t new_size)
{
szone_error(szone, 1, "Non-aligned pointer being freed (2)", ptr, NULL);
return;
}
- if (!((szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) && PROTECT_SMALL) &&
- (size <= szone->large_threshold)) {
+ if (size <= szone->large_threshold) {
if (SMALL_META_INDEX_FOR_PTR(ptr) >= NUM_SMALL_BLOCKS) {
szone_error(szone, 1, "Pointer to metadata being freed (2)", ptr, NULL);
return;
if (!msize)
msize = 1;
ptr = tiny_malloc_should_clear(szone, msize, cleared_requested);
- } else if (!((szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) && PROTECT_SMALL) &&
- (size <= szone->large_threshold)) {
+ } else if (size <= szone->large_threshold) {
// think small
msize = SMALL_MSIZE_FOR_BYTES(size + SMALL_QUANTUM - 1);
- if (! msize)
+ if (!msize)
msize = 1;
ptr = small_malloc_should_clear(szone, msize, cleared_requested);
} else {
#if TINY_CACHE
{
mag_index_t mag_index = MAGAZINE_INDEX_FOR_TINY_REGION(TINY_REGION_FOR_PTR(ptr));
- magazine_t *tiny_mag_ptr = &(szone->tiny_magazines[mag_index]);
+ if (DEPOT_MAGAZINE_INDEX != mag_index) {
+ magazine_t *tiny_mag_ptr = &(szone->tiny_magazines[mag_index]);
- if (msize < TINY_QUANTUM && ptr == (void *)((uintptr_t)(tiny_mag_ptr->mag_last_free) & ~ (TINY_QUANTUM - 1)))
- return 0;
+ if (msize < TINY_QUANTUM && ptr == (void *)((uintptr_t)(tiny_mag_ptr->mag_last_free) & ~ (TINY_QUANTUM - 1)))
+ return 0;
+ } else {
+ for (mag_index = 0; mag_index < szone->num_tiny_magazines; mag_index++) {
+ magazine_t *tiny_mag_ptr = &(szone->tiny_magazines[mag_index]);
+
+ if (msize < TINY_QUANTUM && ptr == (void *)((uintptr_t)(tiny_mag_ptr->mag_last_free) & ~ (TINY_QUANTUM - 1)))
+ return 0;
+ }
+ }
}
#endif
return TINY_BYTES_FOR_MSIZE(msize);
#if SMALL_CACHE
{
mag_index_t mag_index = MAGAZINE_INDEX_FOR_SMALL_REGION(SMALL_REGION_FOR_PTR(ptr));
- magazine_t *small_mag_ptr = &(szone->small_magazines[mag_index]);
+ if (DEPOT_MAGAZINE_INDEX != mag_index) {
+ magazine_t *small_mag_ptr = &(szone->small_magazines[mag_index]);
- if (ptr == (void *)((uintptr_t)(small_mag_ptr->mag_last_free) & ~ (SMALL_QUANTUM - 1)))
- return 0;
+ if (ptr == (void *)((uintptr_t)(small_mag_ptr->mag_last_free) & ~ (SMALL_QUANTUM - 1)))
+ return 0;
+ } else {
+ for (mag_index = 0; mag_index < szone->num_small_magazines; mag_index++) {
+ magazine_t *small_mag_ptr = &(szone->small_magazines[mag_index]);
+
+ if (ptr == (void *)((uintptr_t)(small_mag_ptr->mag_last_free) & ~ (SMALL_QUANTUM - 1)))
+ return 0;
+ }
+ }
}
#endif
return SMALL_BYTES_FOR_MSIZE(msize_and_free);
static NOINLINE void *
szone_realloc(szone_t *szone, void *ptr, size_t new_size)
{
- size_t old_size;
+ size_t old_size, new_good_size, valid_size;
void *new_ptr;
#if DEBUG_MALLOC
malloc_printf("in szone_realloc for %p, %d\n", ptr, (unsigned)new_size);
}
#endif
- if (!ptr) {
- ptr = szone_malloc(szone, new_size);
- return ptr;
+ if (NULL == ptr) {
+ // If ptr is a null pointer, realloc() shall be equivalent to malloc() for the specified size.
+ return szone_malloc(szone, new_size);
+ } else if (0 == new_size) {
+ // If size is 0 and ptr is not a null pointer, the object pointed to is freed.
+ szone_free(szone, ptr);
+ // If size is 0, either a null pointer or a unique pointer that can be successfully passed
+ // to free() shall be returned.
+ return szone_malloc(szone, 1);
}
+
old_size = szone_size(szone, ptr);
if (!old_size) {
szone_error(szone, 1, "pointer being reallocated was not allocated", ptr, NULL);
return NULL;
}
- /* we never shrink an allocation */
- if (old_size >= new_size)
+
+ new_good_size = szone_good_size(szone, new_size);
+ if (new_good_size == old_size) { // Existing allocation is best fit evar?
return ptr;
+ }
/*
* If the new size suits the tiny allocator and the pointer being resized
* belongs to a tiny region, try to reallocate in-place.
*/
- if ((new_size + TINY_QUANTUM - 1) <= (NUM_TINY_SLOTS - 1) * TINY_QUANTUM) {
- if (tiny_region_for_ptr_no_lock(szone, ptr) != NULL) {
- if (tiny_try_realloc_in_place(szone, ptr, old_size, new_size)) {
+ if (new_good_size <= (NUM_TINY_SLOTS - 1) * TINY_QUANTUM) {
+ if (old_size <= (NUM_TINY_SLOTS - 1) * TINY_QUANTUM) {
+ if (new_good_size <= (old_size >> 1)) {
+ /*
+ * Serious shrinkage (more than half). free() the excess.
+ */
+ return tiny_try_shrink_in_place(szone, ptr, old_size, new_good_size);
+ } else if (new_good_size <= old_size) {
+ /*
+ * new_good_size smaller than old_size but not by much (less than half).
+ * Avoid thrashing at the expense of some wasted storage.
+ */
+ return ptr;
+ } else if (tiny_try_realloc_in_place(szone, ptr, old_size, new_good_size)) { // try to grow the allocation
return ptr;
}
}
/*
- * If the new size suits the small allocator and the pointer being resized
+ * Else if the new size suits the small allocator and the pointer being resized
* belongs to a small region, and we're not protecting the small allocations
* try to reallocate in-place.
*/
- } else if (!((szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) && PROTECT_SMALL) &&
- ((new_size + SMALL_QUANTUM - 1) <= szone->large_threshold) &&
- (small_region_for_ptr_no_lock(szone, ptr) != NULL)) {
- if (small_try_realloc_in_place(szone, ptr, old_size, new_size)) {
+ } else if (new_good_size <= szone->large_threshold) {
+ if ((NUM_TINY_SLOTS - 1) * TINY_QUANTUM < old_size && old_size <= szone->large_threshold) {
+ if (new_good_size <= (old_size >> 1)) {
+ return small_try_shrink_in_place(szone, ptr, old_size, new_good_size);
+ } else if (new_good_size <= old_size) {
+ return ptr;
+ } else if (small_try_realloc_in_place(szone, ptr, old_size, new_good_size)) {
return ptr;
}
-
+ }
/*
- * If the allocation's a large allocation, try to reallocate in-place there.
+ * Else if the allocation's a large allocation, try to reallocate in-place there.
*/
- } else if (!((szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) && PROTECT_SMALL) &&
- !(szone->debug_flags & SCALABLE_MALLOC_PURGEABLE) &&
- (old_size > szone->large_threshold)) {
- if (large_try_realloc_in_place(szone, ptr, old_size, new_size)) {
+ } else if (!(szone->debug_flags & SCALABLE_MALLOC_PURGEABLE) && // purgeable needs fresh allocation
+ (old_size > szone->large_threshold) &&
+ (new_good_size > szone->large_threshold)) {
+ if (new_good_size <= (old_size >> 1)) {
+ return large_try_shrink_in_place(szone, ptr, old_size, new_good_size);
+ } else if (new_good_size <= old_size) {
+ return ptr;
+ } else if (large_try_realloc_in_place(szone, ptr, old_size, new_good_size)) {
return ptr;
}
}
/*
* Can't reallocate in place for whatever reason; allocate a new buffer and copy.
*/
+ if (new_good_size <= (old_size >> 1)) {
+ /* Serious shrinkage (more than half). FALL THROUGH to alloc/copy/free. */
+ } else if (new_good_size <= old_size) {
+ return ptr;
+ }
+
new_ptr = szone_malloc(szone, new_size);
if (new_ptr == NULL)
return NULL;
* If the allocation's large enough, try to copy using VM. If that fails, or
* if it's too small, just copy by hand.
*/
- if ((old_size < szone->vm_copy_threshold) ||
- vm_copy(mach_task_self(), (vm_address_t)ptr, old_size, (vm_address_t)new_ptr))
- memcpy(new_ptr, ptr, old_size);
+ valid_size = MIN(old_size, new_size);
+ if ((valid_size < szone->vm_copy_threshold) ||
+ vm_copy(mach_task_self(), (vm_address_t)ptr, valid_size, (vm_address_t)new_ptr))
+ memcpy(new_ptr, ptr, valid_size);
szone_free(szone, ptr);
#if DEBUG_MALLOC
} else if ((NUM_TINY_SLOTS - 1)*TINY_QUANTUM < size && alignment <= SMALL_QUANTUM) {
return szone_malloc(szone, size); // Trivially satisfied by small or large
- } else if (!((szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) && PROTECT_SMALL) && (span <= szone->large_threshold)) {
+ } else if (span <= szone->large_threshold) {
if (size <= (NUM_TINY_SLOTS - 1)*TINY_QUANTUM) {
size = (NUM_TINY_SLOTS - 1)*TINY_QUANTUM + TINY_QUANTUM; // ensure block allocated by small does not have a tiny-possible size
if (is_free)
break; // a double free; let the standard free deal with it
- tiny_free_no_lock(szone, tiny_mag_ptr, mag_index, tiny_region, ptr, msize);
+ if (!tiny_free_no_lock(szone, tiny_mag_ptr, mag_index, tiny_region, ptr, msize)) {
+ // Arrange to re-acquire magazine lock
+ tiny_mag_ptr = NULL;
+ tiny_region = NULL;
+ }
to_be_freed[cc] = NULL;
} else {
// No region in this zone claims ptr; let the standard free deal with it
large_entry_t *large;
vm_range_t range_to_deallocate;
- /* destroy large entries cache */
+#if LARGE_CACHE
+ SZONE_LOCK(szone);
+
+ /* disable any memory pressure responder */
+ szone->flotsam_enabled = FALSE;
+
+ // stack allocated copy of the death-row cache
int idx = szone->large_entry_cache_oldest, idx_max = szone->large_entry_cache_newest;
+ large_entry_t local_entry_cache[LARGE_ENTRY_CACHE_SIZE];
+
+ memcpy((void *)local_entry_cache, (void *)szone->large_entry_cache, sizeof(local_entry_cache));
+
+ szone->large_entry_cache_oldest = szone->large_entry_cache_newest = 0;
+ szone->large_entry_cache[0].address = 0x0;
+ szone->large_entry_cache[0].size = 0;
+ szone->large_entry_cache_bytes = 0;
+ szone->large_entry_cache_reserve_bytes = 0;
+
+ SZONE_UNLOCK(szone);
+
+ // deallocate the death-row cache outside the zone lock
while (idx != idx_max) {
- deallocate_pages(szone, (void *) szone->large_entry_cache[idx].address, szone->large_entry_cache[idx].size, 0);
+ deallocate_pages(szone, (void *) local_entry_cache[idx].address, local_entry_cache[idx].size, 0);
if (++idx == LARGE_ENTRY_CACHE_SIZE) idx = 0;
}
- if (0 != szone->large_entry_cache[idx].address && 0 != szone->large_entry_cache[idx].size)
- deallocate_pages(szone, (void *) szone->large_entry_cache[idx].address, szone->large_entry_cache[idx].size, 0);
+ if (0 != local_entry_cache[idx].address && 0 != local_entry_cache[idx].size) {
+ deallocate_pages(szone, (void *) local_entry_cache[idx].address, local_entry_cache[idx].size, 0);
+ }
+#endif
/* destroy large entries */
index = szone->num_large_entries;
(void)pthread_key_delete(szone->cpu_id_key);
deallocate_pages(szone, (void *)&(szone->tiny_magazines[-1]), TINY_MAGAZINE_PAGED_SIZE, SCALABLE_MALLOC_ADD_GUARD_PAGES);
deallocate_pages(szone, (void *)&(szone->small_magazines[-1]), SMALL_MAGAZINE_PAGED_SIZE, SCALABLE_MALLOC_ADD_GUARD_PAGES);
- deallocate_pages(szone, (void *)szone, SZONE_PAGED_SIZE, SCALABLE_MALLOC_ADD_GUARD_PAGES);
+ deallocate_pages(szone, (void *)szone, SZONE_PAGED_SIZE, 0);
}
static NOINLINE size_t
szone_good_size(szone_t *szone, size_t size)
{
msize_t msize;
- int guard_small = (szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) && PROTECT_SMALL;
// Find a good size for this tiny allocation.
if (size <= (NUM_TINY_SLOTS - 1) * TINY_QUANTUM) {
}
// Find a good size for this small allocation.
- if (!guard_small && (size <= szone->large_threshold)) {
+ if (size <= szone->large_threshold) {
msize = SMALL_MSIZE_FOR_BYTES(size + SMALL_QUANTUM - 1);
if (!msize)
msize = 1;
mag_index_t mag_index;
for (mag_index = -1; mag_index < szone->num_tiny_magazines; mag_index++) {
+ s += szone->tiny_magazines[mag_index].mag_bytes_free_at_start;
s += szone->tiny_magazines[mag_index].mag_bytes_free_at_end;
t += szone->tiny_magazines[mag_index].mag_num_objects;
u += szone->tiny_magazines[mag_index].mag_num_bytes_in_objects;
info[5] = u;
for (t = 0, u = 0, mag_index = -1; mag_index < szone->num_small_magazines; mag_index++) {
+ s += szone->small_magazines[mag_index].mag_bytes_free_at_start;
s += szone->small_magazines[mag_index].mag_bytes_free_at_end;
t += szone->small_magazines[mag_index].mag_num_objects;
u += szone->small_magazines[mag_index].mag_num_bytes_in_objects;
region = szone->tiny_region_generation->hashed_regions[index];
if (HASHRING_OPEN_ENTRY != region && HASHRING_REGION_DEALLOCATED != region) {
mag_index_t mag_index = MAGAZINE_INDEX_FOR_TINY_REGION(region);
- print_tiny_region(verbose, region, (region == szone->tiny_magazines[mag_index].mag_last_region) ?
+ print_tiny_region(verbose, region,
+ (region == szone->tiny_magazines[mag_index].mag_last_region) ?
+ szone->tiny_magazines[mag_index].mag_bytes_free_at_start : 0,
+ (region == szone->tiny_magazines[mag_index].mag_last_region) ?
szone->tiny_magazines[mag_index].mag_bytes_free_at_end : 0);
}
}
if (HASHRING_OPEN_ENTRY != region && HASHRING_REGION_DEALLOCATED != region) {
mag_index_t mag_index = MAGAZINE_INDEX_FOR_SMALL_REGION(region);
print_small_region(szone, verbose, region,
+ (region == szone->small_magazines[mag_index].mag_last_region) ?
+ szone->small_magazines[mag_index].mag_bytes_free_at_start : 0,
(region == szone->small_magazines[mag_index].mag_last_region) ?
szone->small_magazines[mag_index].mag_bytes_free_at_end : 0);
}
return 0;
}
+static size_t
+szone_pressure_relief(szone_t *szone, size_t goal)
+{
+#if LARGE_CACHE
+ if (!szone->flotsam_enabled)
+ return 0;
+
+ SZONE_LOCK(szone);
+
+ // stack allocated copy of the death-row cache
+ int idx = szone->large_entry_cache_oldest, idx_max = szone->large_entry_cache_newest;
+ large_entry_t local_entry_cache[LARGE_ENTRY_CACHE_SIZE];
+
+ memcpy((void *)local_entry_cache, (void *)szone->large_entry_cache, sizeof(local_entry_cache));
+
+ szone->large_entry_cache_oldest = szone->large_entry_cache_newest = 0;
+ szone->large_entry_cache[0].address = 0x0;
+ szone->large_entry_cache[0].size = 0;
+ szone->large_entry_cache_bytes = 0;
+ szone->large_entry_cache_reserve_bytes = 0;
+
+ szone->flotsam_enabled = FALSE;
+
+ SZONE_UNLOCK(szone);
+
+ // deallocate the death-row cache outside the zone lock
+ size_t total = 0;
+ while (idx != idx_max) {
+ deallocate_pages(szone, (void *) local_entry_cache[idx].address, local_entry_cache[idx].size, 0);
+ total += local_entry_cache[idx].size;
+ if (++idx == LARGE_ENTRY_CACHE_SIZE) idx = 0;
+ }
+ if (0 != local_entry_cache[idx].address && 0 != local_entry_cache[idx].size) {
+ deallocate_pages(szone, (void *) local_entry_cache[idx].address, local_entry_cache[idx].size, 0);
+ total += local_entry_cache[idx].size;
+ }
+ MAGMALLOC_PRESSURERELIEF((void *)szone, goal, total); // DTrace USDT Probe
+ return total;
+#else
+ return 0;
+#endif
+}
+
boolean_t
scalable_zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats, unsigned subzone)
{
mag_index_t mag_index;
for (mag_index = -1; mag_index < szone->num_tiny_magazines; mag_index++) {
+ s += szone->tiny_magazines[mag_index].mag_bytes_free_at_start;
s += szone->tiny_magazines[mag_index].mag_bytes_free_at_end;
t += szone->tiny_magazines[mag_index].mag_num_objects;
u += szone->tiny_magazines[mag_index].mag_num_bytes_in_objects;
mag_index_t mag_index;
for (mag_index = -1; mag_index < szone->num_small_magazines; mag_index++) {
+ s += szone->small_magazines[mag_index].mag_bytes_free_at_start;
s += szone->small_magazines[mag_index].mag_bytes_free_at_end;
t += szone->small_magazines[mag_index].mag_num_objects;
u += szone->small_magazines[mag_index].mag_num_bytes_in_objects;
mag_index_t mag_index;
for (mag_index = -1; mag_index < szone->num_tiny_magazines; mag_index++) {
+ s += szone->tiny_magazines[mag_index].mag_bytes_free_at_start;
s += szone->tiny_magazines[mag_index].mag_bytes_free_at_end;
t += szone->tiny_magazines[mag_index].mag_num_objects;
u += szone->tiny_magazines[mag_index].mag_num_bytes_in_objects;
}
for (mag_index = -1; mag_index < szone->num_small_magazines; mag_index++) {
+ s += szone->small_magazines[mag_index].mag_bytes_free_at_start;
s += szone->small_magazines[mag_index].mag_bytes_free_at_end;
t += szone->small_magazines[mag_index].mag_num_objects;
u += szone->small_magazines[mag_index].mag_num_bytes_in_objects;
szone_t *szone = (szone_t *)zone;
if (szone) {
+ mprotect(szone, sizeof(szone->basic_zone), PROT_READ | PROT_WRITE);
szone->basic_zone.malloc = (void *)legacy_zeroing_large_malloc;
szone->basic_zone.valloc = (void *)legacy_zeroing_large_valloc;
+ mprotect(szone, sizeof(szone->basic_zone), PROT_READ);
}
}
(void *)szone_force_unlock,
(void *)szone_statistics,
(void *)szone_locked,
+ NULL, NULL, NULL, NULL, /* Zone enumeration version 7 and forward. */
}; // marked as const to spare the DATA section
malloc_zone_t *
{
szone_t *szone;
uint64_t hw_memsize = 0;
- size_t uint64_t_size = sizeof(hw_memsize);
- int err;
/*
* Sanity-check our build-time assumptions about the size of a page.
}
#endif
- /* get memory for the zone, which is now separate from any region.
- add guard pages to prevent walking from any other vm allocations
- to here and overwriting the function pointers in basic_zone. */
- szone = allocate_pages(NULL, SZONE_PAGED_SIZE, 0, SCALABLE_MALLOC_ADD_GUARD_PAGES, VM_MEMORY_MALLOC);
+ /* get memory for the zone. */
+ szone = allocate_pages(NULL, SZONE_PAGED_SIZE, 0, 0, VM_MEMORY_MALLOC);
if (!szone)
return NULL;
* upon the amount of memory in the system. Switch to a larger number of
* free list entries at 1GB.
*/
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ if ((hw_memsize = *(uint64_t *)(uintptr_t)_COMM_PAGE_MEMORY_SIZE) >= (1ULL << 30))
+#else
+ size_t uint64_t_size = sizeof(hw_memsize);
+
if (0 == sysctlbyname("hw.memsize", &hw_memsize, &uint64_t_size, 0, 0) &&
- hw_memsize >= (1ULL << 30)) {
+ hw_memsize >= (1ULL << 30))
+#endif
+ {
szone->is_largemem = 1;
szone->num_small_slots = NUM_SMALL_SLOTS_LARGEMEM;
szone->large_threshold = LARGE_THRESHOLD_LARGEMEM;
szone->vm_copy_threshold = VM_COPY_THRESHOLD;
}
#if LARGE_CACHE
- szone->large_entry_cache_hoard_lmit = hw_memsize >> 10; // madvise(..., MADV_REUSABLE) death-row arrivals above this threshold [~0.1%]
+ szone->large_entry_cache_reserve_limit =
+ hw_memsize >> 10; // madvise(..., MADV_REUSABLE) death-row arrivals above this threshold [~0.1%]
/* <rdar://problem/6610904> Reset protection when returning a previous large allocation? */
int32_t libSystemVersion = NSVersionOfLinkTimeLibrary("System");
#endif
// Initialize the security token.
-#if __LP64__
- szone->cookie = ((uintptr_t)arc4random() << 32) | (uintptr_t)arc4random();
+ szone->cookie = (uintptr_t)malloc_entropy[0];
+
+ // Prepare ASLR
+#if __i386__ || __LP64__ || TARGET_OS_EMBEDDED
+#if __i386__
+ uintptr_t stackbase = 0x8fe00000;
+ int entropic_bits = 3;
+#elif __LP64__
+ uintptr_t stackbase = USRSTACK64;
+ int entropic_bits = 16;
+#else
+ uintptr_t stackbase = USRSTACK;
+ int entropic_bits = 3;
+#endif
+ if (0 != _dyld_get_image_slide((const struct mach_header*)_NSGetMachExecuteHeader())) {
+ if (0 == entropic_address) {
+ uintptr_t t = stackbase - MAXSSIZ - ((uintptr_t) (malloc_entropy[1] & ((1 << entropic_bits) - 1)) << SMALL_BLOCKS_ALIGN);
+ (void)__sync_bool_compare_and_swap(&entropic_limit, 0, t); // Just one initialization please
+ (void)__sync_bool_compare_and_swap(&entropic_address, 0, t - ENTROPIC_KABILLION); // Just one initialization please
+ }
+ debug_flags &= ~DISABLE_ASLR;
+ } else {
+ debug_flags |= DISABLE_ASLR;
+ }
+
#else
- szone->cookie = arc4random();
+ debug_flags |= DISABLE_ASLR;
#endif
- szone->basic_zone.version = 6;
+ szone->basic_zone.version = 8;
szone->basic_zone.size = (void *)szone_size;
szone->basic_zone.malloc = (void *)szone_malloc;
szone->basic_zone.calloc = (void *)szone_calloc;
szone->basic_zone.introspect = (struct malloc_introspection_t *)&szone_introspect;
szone->basic_zone.memalign = (void *)szone_memalign;
szone->basic_zone.free_definite_size = (void *)szone_free_definite_size;
+ szone->basic_zone.pressure_relief = (void *)szone_pressure_relief;
+
+ szone->basic_zone.reserved1 = 0; /* Set to zero once and for all as required by CFAllocator. */
+ szone->basic_zone.reserved2 = 0; /* Set to zero once and for all as required by CFAllocator. */
+ mprotect(szone, sizeof(szone->basic_zone), PROT_READ); /* Prevent overwriting the function pointers in basic_zone. */
+
szone->debug_flags = debug_flags;
LOCK_INIT(szone->large_szone_lock);
zeroify_scalable_zone((malloc_zone_t *)szone);
#endif
+#if defined(__i386__) || defined(__x86_64__)
+ szone->cpu_id_key = (pthread_key_t) -1; // Unused. _COMM_PAGE_CPU_NUMBER preferred.
+#else
+ int err;
if ((err = pthread_key_create(&(szone->cpu_id_key), NULL))) {
malloc_printf("*** ERROR -pthread_key_create failure err=%d.\n", err);
szone->cpu_id_key = (pthread_key_t) -1;
}
+#endif
// Query the number of configured processors.
// Uniprocessor case gets just one tiny and one small magazine (whose index is zero). This gives
// the same behavior as the original scalable malloc. MP gets per-CPU magazines
// that scale (way) better.
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ int nproc = *(uint8_t *)(uintptr_t)_COMM_PAGE_NCPUS;
+#else
int nproc = sysconf(_SC_NPROCESSORS_CONF);
+#endif
szone->num_tiny_magazines = (nproc > 1) ? MIN(nproc, TINY_MAX_MAGAZINES) : 1;
// FIXME vm_allocate() based on number of configured CPUs
static size_t
purgeable_size(szone_t *szone, const void *ptr)
{
- size_t t = szone_size_try_large(szone, ptr);
-
- if (t)
- return t;
- else
- return szone_size(szone->helper_zone, ptr);
+ // Only claim our large allocations, leave the shared tiny/small for the helper zone to claim.
+ return szone_size_try_large(szone, ptr);
}
static void *
static void *
purgeable_realloc(szone_t *szone, void *ptr, size_t new_size)
{
- if (new_size <= szone->large_threshold)
- return szone_realloc(szone->helper_zone, ptr, new_size);
- else
- return szone_realloc(szone, ptr, new_size);
+ size_t old_size;
+
+ if (NULL == ptr) {
+ // If ptr is a null pointer, realloc() shall be equivalent to malloc() for the specified size.
+ return purgeable_malloc(szone, new_size);
+ } else if (0 == new_size) {
+ // If size is 0 and ptr is not a null pointer, the object pointed to is freed.
+ purgeable_free(szone, ptr);
+ // If size is 0, either a null pointer or a unique pointer that can be successfully passed
+ // to free() shall be returned.
+ return purgeable_malloc(szone, 1);
+ }
+
+ old_size = purgeable_size(szone, ptr); // Now ptr can be safely size()'d
+ if (!old_size)
+ old_size = szone_size(szone->helper_zone, ptr);
+
+ if (!old_size) {
+ szone_error(szone, 1, "pointer being reallocated was not allocated", ptr, NULL);
+ return NULL;
+ }
+
+ // Distinguish 4 cases: {oldsize, newsize} x { <= , > large_threshold }
+ // and deal with the allocation crossing from the purgeable zone to the helper zone and vice versa.
+ if (old_size <= szone->large_threshold) {
+ if (new_size <= szone->large_threshold)
+ return szone_realloc(szone->helper_zone, ptr, new_size);
+ else {
+ // allocation crosses from helper to purgeable zone
+ void * new_ptr = purgeable_malloc(szone, new_size);
+ if (new_ptr) {
+ memcpy(new_ptr, ptr, old_size);
+ szone_free_definite_size(szone->helper_zone, ptr, old_size);
+ }
+ return new_ptr; // in state VM_PURGABLE_NONVOLATILE
+ }
+ } else {
+ if (new_size <= szone->large_threshold) {
+ // allocation crosses from purgeable to helper zone
+ void * new_ptr = szone_malloc(szone->helper_zone, new_size);
+ if (new_ptr) {
+ memcpy(new_ptr, ptr, new_size);
+ purgeable_free_definite_size(szone, ptr, old_size);
+ }
+ return new_ptr;
+ } else {
+ void * new_ptr = purgeable_malloc(szone, new_size);
+ if (new_ptr) {
+ memcpy(new_ptr, ptr, MIN(old_size, new_size));
+ purgeable_free_definite_size(szone, ptr, old_size);
+ }
+ return new_ptr; // in state VM_PURGABLE_NONVOLATILE
+ }
+ }
+ /* NOTREACHED */
}
static void
deallocate_pages(szone, (void *)range_to_deallocate.address, (size_t)range_to_deallocate.size, 0);
/* Now destroy the separate szone region */
- deallocate_pages(szone, (void *)szone, SZONE_PAGED_SIZE, SCALABLE_MALLOC_ADD_GUARD_PAGES);
+ deallocate_pages(szone, (void *)szone, SZONE_PAGED_SIZE, 0);
}
static unsigned
return 0;
}
+static size_t
+purgeable_pressure_relief(szone_t *szone, size_t goal)
+{
+ return szone_pressure_relief(szone, goal) + szone_pressure_relief(szone->helper_zone, goal);
+}
+
static const struct malloc_introspection_t purgeable_introspect = {
(void *)purgeable_ptr_in_use_enumerator,
(void *)purgeable_good_size,
(void *)purgeable_force_unlock,
(void *)purgeable_statistics,
(void *)purgeable_locked,
+ NULL, NULL, NULL, NULL, /* Zone enumeration version 7 and forward. */
}; // marked as const to spare the DATA section
-malloc_zone_t *
+__private_extern__ malloc_zone_t *
create_purgeable_zone(size_t initial_size, malloc_zone_t *malloc_default_zone, unsigned debug_flags)
{
szone_t *szone;
+ uint64_t hw_memsize = 0;
- /* get memory for the zone, which is now separate from any region.
- add guard pages to prevent walking from any other vm allocations
- to here and overwriting the function pointers in basic_zone. */
- szone = allocate_pages(NULL, SZONE_PAGED_SIZE, 0, SCALABLE_MALLOC_ADD_GUARD_PAGES, VM_MEMORY_MALLOC);
+ /* get memory for the zone. */
+ szone = allocate_pages(NULL, SZONE_PAGED_SIZE, 0, 0, VM_MEMORY_MALLOC);
if (!szone)
return NULL;
szone->log_address = ~0;
#endif
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ hw_memsize = *(uint64_t *)(uintptr_t)_COMM_PAGE_MEMORY_SIZE;
+#else
+ size_t uint64_t_size = sizeof(hw_memsize);
+
+ sysctlbyname("hw.memsize", &hw_memsize, &uint64_t_size, 0, 0);
+#endif
/* Purgeable zone does not participate in the adaptive "largemem" sizing. */
szone->is_largemem = 0;
szone->large_threshold = LARGE_THRESHOLD;
szone->vm_copy_threshold = VM_COPY_THRESHOLD;
#if LARGE_CACHE
+ szone->large_entry_cache_reserve_limit =
+ hw_memsize >> 10; // madvise(..., MADV_REUSABLE) death-row arrivals above this threshold [~0.1%]
+
/* <rdar://problem/6610904> Reset protection when returning a previous large allocation? */
int32_t libSystemVersion = NSVersionOfLinkTimeLibrary("System");
if ((-1 != libSystemVersion) && ((libSystemVersion >> 16) < 112) /* CFSystemVersionSnowLeopard */)
szone->large_legacy_reset_mprotect = FALSE;
#endif
- szone->basic_zone.version = 6;
+ szone->basic_zone.version = 8;
szone->basic_zone.size = (void *)purgeable_size;
szone->basic_zone.malloc = (void *)purgeable_malloc;
szone->basic_zone.calloc = (void *)purgeable_calloc;
szone->basic_zone.introspect = (struct malloc_introspection_t *)&purgeable_introspect;
szone->basic_zone.memalign = (void *)purgeable_memalign;
szone->basic_zone.free_definite_size = (void *)purgeable_free_definite_size;
+ szone->basic_zone.pressure_relief = (void *)purgeable_pressure_relief;
+ szone->basic_zone.reserved1 = 0; /* Set to zero once and for all as required by CFAllocator. */
+ szone->basic_zone.reserved2 = 0; /* Set to zero once and for all as required by CFAllocator. */
+ mprotect(szone, sizeof(szone->basic_zone), PROT_READ); /* Prevent overwriting the function pointers in basic_zone. */
+
szone->debug_flags = debug_flags | SCALABLE_MALLOC_PURGEABLE;
-
+
/* Purgeable zone does not support SCALABLE_MALLOC_ADD_GUARD_PAGES. */
if (szone->debug_flags & SCALABLE_MALLOC_ADD_GUARD_PAGES) {
_malloc_printf(ASL_LEVEL_INFO, "purgeable zone does not support guard pages\n");
return ptr;
}
-malloc_zone_t *
+__private_extern__ malloc_zone_t *
create_legacy_scalable_zone(size_t initial_size, unsigned debug_flags)
{
malloc_zone_t *mzone = create_scalable_zone(initial_size, debug_flags);
szone->large_threshold = LARGE_THRESHOLD;
szone->vm_copy_threshold = VM_COPY_THRESHOLD;
+ mprotect(szone, sizeof(szone->basic_zone), PROT_READ | PROT_WRITE);
szone->basic_zone.valloc = (void *)legacy_valloc;
szone->basic_zone.free_definite_size = NULL;
+ mprotect(szone, sizeof(szone->basic_zone), PROT_READ);
return mzone;
}
provider magmalloc {
probe refreshIndex(void *, int, int);
- probe depotRegion(void *, int, int);
- probe recircRegion(void *, int, int);
- probe allocRegion(void *, int);
- probe deallocRegion(void *, void *);
+ probe depotRegion(void *, int, void *, int, int);
+ probe recircRegion(void *, int, void *, int, int);
+ probe allocRegion(void *, int, void *, int);
+ probe deallocRegion(void *, void *, int);
probe madvfreeRegion(void *, void *, void *, int);
+ probe pressureRelief(void *, int, int);
probe mallocErrorBreak();
};
is not
.Dv NULL ,
a new, minimum sized object is allocated and the original object is freed.
+When extending a region allocated with calloc(3), realloc(3) does not guarantee
+that the additional memory is also zero-filled.
.Pp
The
.Fn reallocf
#include <pthread_internals.h>
#include "magmallocProvider.h"
+#include <mach-o/dyld.h> /* for NSVersionOfLinkTimeLibrary() */
#import <stdlib.h>
#import <stdio.h>
#import "stack_logging.h"
#import "malloc_printf.h"
#import "_simple.h"
+#import "CrashReporterClient.h"
/*
* MALLOC_ABSOLUTE_MAX_SIZE - There are many instances of addition to a
/* The following variables are exported for the benefit of performance tools
*
* It should always be safe to first read malloc_num_zones, then read
- * malloc_zones without taking the lock, if only iteration is required
+ * malloc_zones without taking the lock, if only iteration is required and
+ * provided that when malloc_destroy_zone is called all prior operations on that
+ * zone are complete and no further calls referencing that zone can be made.
*/
unsigned malloc_num_zones = 0;
unsigned malloc_num_zones_allocated = 0;
#define MALLOC_LOCK() LOCK(_malloc_lock)
#define MALLOC_UNLOCK() UNLOCK(_malloc_lock)
+/*
+ * Counters that coordinate zone destruction (in malloc_zone_unregister) with
+ * find_registered_zone (here abbreviated as FRZ).
+ */
+static int counterAlice = 0, counterBob = 0;
+static int *pFRZCounterLive= &counterAlice, *pFRZCounterDrain = &counterBob;
+
#define MALLOC_LOG_TYPE_ALLOCATE stack_logging_type_alloc
#define MALLOC_LOG_TYPE_DEALLOCATE stack_logging_type_dealloc
#define MALLOC_LOG_TYPE_HAS_ZONE stack_logging_flag_zone
#define MALLOC_LOG_TYPE_CLEARED stack_logging_flag_cleared
/********* Utilities ************/
+__private_extern__ uint64_t malloc_entropy[2] = {0, 0};
+
+void __malloc_entropy_setup(const char *apple[]) __attribute__ ((visibility ("hidden")));
+
+static int
+__entropy_from_kernel(const char *str)
+{
+ unsigned long long val;
+ char tmp[20], *p;
+ int idx = 0;
+
+ /* Skip over key to the first value */
+ str = strchr(str, '=');
+ if (str == NULL)
+ return 0;
+ str++;
+
+ while (str && idx < sizeof(malloc_entropy)/sizeof(malloc_entropy[0])) {
+ strlcpy(tmp, str, 20);
+ p = strchr(tmp, ',');
+ if (p) *p = '\0';
+ val = strtoull(tmp, NULL, 0);
+ malloc_entropy[idx] = (uint64_t)val;
+ idx++;
+ if ((str = strchr(str, ',')) != NULL)
+ str++;
+ }
+ return idx;
+}
+
+void
+__malloc_entropy_setup(const char *apple[])
+{
+ const char **p;
+ for (p = apple; p && *p; p++) {
+ if (strstr(*p, "malloc_entropy") == *p) {
+ if (sizeof(malloc_entropy)/sizeof(malloc_entropy[0]) == __entropy_from_kernel(*p))
+ return;
+ else
+ break;
+ }
+ }
+
+ malloc_entropy[0] = ((uint64_t)arc4random()) << 32 | ((uint64_t)arc4random());
+ malloc_entropy[1] = ((uint64_t)arc4random()) << 32 | ((uint64_t)arc4random());
+ return;
+}
static inline malloc_zone_t * find_registered_zone(const void *, size_t *) __attribute__((always_inline));
static inline malloc_zone_t *
find_registered_zone(const void *ptr, size_t *returned_size) {
// Returns a zone which contains ptr, else NULL
- unsigned index;
- malloc_zone_t **zones = malloc_zones;
+
+ if (0 == malloc_num_zones) {
+ if (returned_size) *returned_size = 0;
+ return NULL;
+ }
+
+ // The default zone is registered in malloc_zones[0]. There's no danger that it will ever be unregistered.
+ // So don't advance the FRZ counter yet.
+ malloc_zone_t *zone = malloc_zones[0];
+ size_t size = zone->size(zone, ptr);
+ if (size) { // Claimed by this zone?
+ if (returned_size) *returned_size = size;
+ return zone;
+ }
+
+ int *pFRZCounter = pFRZCounterLive; // Capture pointer to the counter of the moment
+ __sync_fetch_and_add(pFRZCounter, 1); // Advance this counter -- our thread is in FRZ
- for (index = 0; index < malloc_num_zones; ++index, ++zones) {
- malloc_zone_t *zone = *zones;
- size_t size = zone->size(zone, ptr);
+ unsigned index;
+ unsigned limit = malloc_num_zones;
+ malloc_zone_t **zones = &malloc_zones[1];
+
+ for (index = 1; index < limit; ++index, ++zones) {
+ zone = *zones;
+ size = zone->size(zone, ptr);
if (size) { // Claimed by this zone?
if (returned_size) *returned_size = size;
+ __sync_fetch_and_sub(pFRZCounter, 1); // our thread is leaving FRZ
return zone;
}
}
// Unclaimed by any zone.
if (returned_size) *returned_size = 0;
+ __sync_fetch_and_sub(pFRZCounter, 1); // our thread is leaving FRZ
return NULL;
}
/* If we don't need to reallocate zones, we need to briefly change the
* page protection the malloc zones to allow writes */
protect_size = malloc_num_zones_allocated * sizeof(malloc_zone_t *);
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ | VM_PROT_WRITE);
+ mprotect(malloc_zones, protect_size, PROT_READ | PROT_WRITE);
}
malloc_zones[malloc_num_zones++] = zone;
/* Finally, now that the zone is registered, disallow write access to the
* malloc_zones array */
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ);
+ mprotect(malloc_zones, protect_size, PROT_READ);
//_malloc_printf(ASL_LEVEL_INFO, "Registered malloc_zone %p in malloc_zones %p [%u zones, %u bytes]\n", zone, malloc_zones, malloc_num_zones, protect_size);
}
if (n != 0) { // make the default first, for efficiency
unsigned protect_size = malloc_num_zones_allocated * sizeof(malloc_zone_t *);
malloc_zone_t *hold = malloc_zones[0];
+
if(hold->zone_name && strcmp(hold->zone_name, "DefaultMallocZone") == 0) {
- free((void *)hold->zone_name);
- hold->zone_name = NULL;
+ malloc_set_zone_name(hold, NULL);
}
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ | VM_PROT_WRITE);
+
+ mprotect(malloc_zones, protect_size, PROT_READ | PROT_WRITE);
malloc_zones[0] = malloc_zones[n];
malloc_zones[n] = hold;
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ);
+ mprotect(malloc_zones, protect_size, PROT_READ);
}
// _malloc_printf(ASL_LEVEL_INFO, "%d registered zones\n", malloc_num_zones);
// _malloc_printf(ASL_LEVEL_INFO, "malloc_zones is at %p; malloc_num_zones is at %p\n", (unsigned)&malloc_zones, (unsigned)&malloc_num_zones);
return inline_malloc_default_zone();
}
+static inline malloc_zone_t *inline_malloc_default_scalable_zone(void) __attribute__((always_inline));
+static inline malloc_zone_t *
+inline_malloc_default_scalable_zone(void) {
+ unsigned index;
+
+ if (malloc_def_zone_state < 2) _malloc_initialize();
+ // _malloc_printf(ASL_LEVEL_INFO, "In inline_malloc_default_scalable_zone with %d %d\n", malloc_num_zones, malloc_has_debug_zone);
+
+ MALLOC_LOCK();
+ for (index = 0; index < malloc_num_zones; ++index) {
+ malloc_zone_t *z = malloc_zones[index];
+
+ if(z->zone_name && strcmp(z->zone_name, "DefaultMallocZone") == 0) {
+ MALLOC_UNLOCK();
+ return z;
+ }
+ }
+ MALLOC_UNLOCK();
+
+ malloc_printf("*** malloc_default_scalable_zone() failed to find 'DefaultMallocZone'\n");
+ return NULL; // FIXME: abort() instead?
+}
+
malloc_zone_t *
malloc_default_purgeable_zone(void) {
static malloc_zone_t *dpz;
if (!dpz) {
- malloc_zone_t *tmp = create_purgeable_zone(0, malloc_default_zone(), malloc_debug_flags);
+ //
+ // PR_7288598: Must pass a *scalable* zone (szone) as the helper for create_purgeable_zone().
+ // Take care that the zone so obtained is not subject to interposing.
+ //
+ malloc_zone_t *tmp = create_purgeable_zone(0, inline_malloc_default_scalable_zone(), malloc_debug_flags);
malloc_zone_register(tmp);
malloc_set_zone_name(tmp, "DefaultPurgeableMallocZone");
if (!__sync_bool_compare_and_swap(&dpz, NULL, tmp))
#if __LP64__
malloc_debug_flags = SCALABLE_MALLOC_ABORT_ON_CORRUPTION; // Set always on 64-bit processes
#else
- malloc_debug_flags = 0;
+ int libSystemVersion = NSVersionOfLinkTimeLibrary("System");
+ if ((-1 != libSystemVersion) && ((libSystemVersion >> 16) < 126) /* CFSystemVersionBarolo */)
+ malloc_debug_flags = 0;
+ else
+ malloc_debug_flags = SCALABLE_MALLOC_ABORT_ON_CORRUPTION;
#endif
stack_logging_enable_logging = 0;
stack_logging_dontcompact = 0;
}
}
if (getenv("MallocGuardEdges")) {
- malloc_debug_flags = SCALABLE_MALLOC_ADD_GUARD_PAGES;
+ malloc_debug_flags |= SCALABLE_MALLOC_ADD_GUARD_PAGES;
_malloc_printf(ASL_LEVEL_INFO, "protecting edges\n");
if (getenv("MallocDoNotProtectPrelude")) {
malloc_debug_flags |= SCALABLE_MALLOC_DONT_PROTECT_PRELUDE;
#if __LP64__
/* initialization above forces SCALABLE_MALLOC_ABORT_ON_CORRUPTION of 64-bit processes */
#else
- if (getenv("MallocCorruptionAbort")) { // Set from an environment variable in 32-bit processes
- malloc_debug_flags |= SCALABLE_MALLOC_ABORT_ON_CORRUPTION;
+ flag = getenv("MallocCorruptionAbort");
+ if (flag && (flag[0] == '0')) { // Set from an environment variable in 32-bit processes
+ malloc_debug_flags &= ~SCALABLE_MALLOC_ABORT_ON_CORRUPTION;
+ } else if (flag) {
+ malloc_debug_flags |= SCALABLE_MALLOC_ABORT_ON_CORRUPTION;
}
#endif
flag = getenv("MallocCheckHeapStart");
//
malloc_zone_t *hold = malloc_zones[0];
if(hold->zone_name && strcmp(hold->zone_name, "DefaultMallocZone") == 0) {
- free((void *)hold->zone_name);
- hold->zone_name = NULL;
+ malloc_set_zone_name(hold, NULL);
}
malloc_set_zone_name(zone, "DefaultMallocZone");
unsigned protect_size = malloc_num_zones_allocated * sizeof(malloc_zone_t *);
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ | VM_PROT_WRITE);
+ mprotect(malloc_zones, protect_size, PROT_READ | PROT_WRITE);
// assert(zone == malloc_zones[malloc_num_zones - 1];
for (i = malloc_num_zones - 1; i > 0; --i) {
}
malloc_zones[0] = zone;
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ);
+ mprotect(malloc_zones, protect_size, PROT_READ);
MALLOC_UNLOCK();
}
void
malloc_destroy_zone(malloc_zone_t *zone) {
+ malloc_set_zone_name(zone, NULL); // Deallocate zone name wherever it may reside PR_7701095
malloc_zone_unregister(zone);
zone->destroy(zone);
}
__malloc_check_env_name(const char *name)
{
MALLOC_LOCK();
+ /*
+ * <rdar://problem/8686255>
+ *
+ * 2. malloc will no longer take notice of *programmatic* changes to the MALLOC_* environment variables
+ * (i.e. calls to putenv() or setenv() that manipulate these environment variables.)
+ *
+ */
+#if 0
if(malloc_def_zone_state == 2 && strncmp(name, "Malloc", 6) == 0)
malloc_def_zone_state = 1;
+#endif
MALLOC_UNLOCK();
}
/********* Block creation and manipulation ************/
-extern const char *__crashreporter_info__;
-
static void
internal_check(void) {
static vm_address_t *frames = NULL;
malloc_printf("*** Recommend using 'setenv MallocCheckHeapStart %d; setenv MallocCheckHeapEach %d' to narrow down failure\n", recomm_start, recomm_each);
}
if (malloc_check_abort) {
- __crashreporter_info__ = b ? _simple_string(b) : "*** MallocCheckHeap: FAILED check";
+ CRSetCrashLogMessage(b ? _simple_string(b) : "*** MallocCheckHeap: FAILED check");
abort();
} else if (b)
_simple_sfree(b);
return NULL;
}
ptr = zone->malloc(zone, size);
- if (malloc_logger) malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)size, 0, (uintptr_t)ptr, 0);
+ if (malloc_logger)
+ malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)size, 0, (uintptr_t)ptr, 0);
return ptr;
}
return NULL;
}
ptr = zone->calloc(zone, num_items, size);
- if (malloc_logger) malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE | MALLOC_LOG_TYPE_CLEARED, (uintptr_t)zone, (uintptr_t)(num_items * size), 0, (uintptr_t)ptr, 0);
+ if (malloc_logger)
+ malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE | MALLOC_LOG_TYPE_CLEARED, (uintptr_t)zone, (uintptr_t)(num_items * size), 0,
+ (uintptr_t)ptr, 0);
return ptr;
}
return NULL;
}
ptr = zone->valloc(zone, size);
- if (malloc_logger) malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)size, 0, (uintptr_t)ptr, 0);
+ if (malloc_logger)
+ malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)size, 0, (uintptr_t)ptr, 0);
return ptr;
}
return NULL;
}
new_ptr = zone->realloc(zone, ptr, size);
- if (malloc_logger) malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_DEALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)ptr, (uintptr_t)size, (uintptr_t)new_ptr, 0);
+ if (malloc_logger)
+ malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_DEALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)ptr, (uintptr_t)size,
+ (uintptr_t)new_ptr, 0);
return new_ptr;
}
void
malloc_zone_free(malloc_zone_t *zone, void *ptr) {
- if (malloc_logger) malloc_logger(MALLOC_LOG_TYPE_DEALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)ptr, 0, 0, 0);
+ if (malloc_logger)
+ malloc_logger(MALLOC_LOG_TYPE_DEALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)ptr, 0, 0, 0);
if (malloc_check_start && (malloc_check_counter++ >= malloc_check_start)) {
internal_check();
}
static void
malloc_zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) {
- if (malloc_logger) malloc_logger(MALLOC_LOG_TYPE_DEALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)ptr, 0, 0, 0);
+ if (malloc_logger)
+ malloc_logger(MALLOC_LOG_TYPE_DEALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)ptr, 0, 0, 0);
if (malloc_check_start && (malloc_check_counter++ >= malloc_check_start)) {
internal_check();
}
return NULL;
}
ptr = zone->memalign(zone, alignment, size);
- if (malloc_logger) malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)size, 0, (uintptr_t)ptr, 0);
+ if (malloc_logger)
+ malloc_logger(MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_HAS_ZONE, (uintptr_t)zone, (uintptr_t)size, 0, (uintptr_t)ptr, 0);
return ptr;
}
// Modify the page to be allow write access, so that we can update the
// malloc_zones array.
size_t protect_size = malloc_num_zones_allocated * sizeof(malloc_zone_t *);
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ | VM_PROT_WRITE);
+ mprotect(malloc_zones, protect_size, PROT_READ | PROT_WRITE);
+
+ // If we found a match, replace it with the entry at the end of the list, shrink the list,
+ // and leave the end of the list intact to avoid racing with find_registered_zone().
- // If we found a match, swap it with the entry on the back of the list
- // and null out the back of the list.
malloc_zones[index] = malloc_zones[malloc_num_zones - 1];
- malloc_zones[malloc_num_zones - 1] = NULL;
--malloc_num_zones;
- vm_protect(mach_task_self(), (uintptr_t)malloc_zones, protect_size, 0, VM_PROT_READ);
+ mprotect(malloc_zones, protect_size, PROT_READ);
+
+ // Exchange the roles of the FRZ counters. The counter that has captured the number of threads presently
+ // executing *inside* find_regiatered_zone is swapped with the counter drained to zero last time through.
+ // The former is then allowed to drain to zero while this thread yields.
+ int *p = pFRZCounterLive;
+ pFRZCounterLive = pFRZCounterDrain;
+ pFRZCounterDrain = p;
+ __sync_synchronize(); // Full memory barrier
+
+ while (0 != *pFRZCounterDrain) { pthread_yield_np(); }
+
MALLOC_UNLOCK();
+
return;
}
MALLOC_UNLOCK();
void
malloc_set_zone_name(malloc_zone_t *z, const char *name) {
char *newName;
+
+ mprotect(z, sizeof(malloc_zone_t), PROT_READ | PROT_WRITE);
if (z->zone_name) {
free((char *)z->zone_name);
z->zone_name = NULL;
}
- newName = malloc_zone_malloc(z, strlen(name) + 1);
- strcpy(newName, name);
- z->zone_name = (const char *)newName;
+ if (name) {
+ size_t buflen = strlen(name) + 1;
+ newName = malloc_zone_malloc(z, buflen);
+ if (newName) {
+ strlcpy(newName, name, buflen);
+ z->zone_name = (const char *)newName;
+ } else {
+ z->zone_name = NULL;
+ }
+ }
+ mprotect(z, sizeof(malloc_zone_t), PROT_READ);
}
const char *
malloc_printf("*** error for object %p: pointer being freed was not allocated\n"
"*** set a breakpoint in malloc_error_break to debug\n", ptr);
malloc_error_break();
- if ((malloc_debug_flags & (SCALABLE_MALLOC_ABORT_ON_CORRUPTION|SCALABLE_MALLOC_ABORT_ON_ERROR)))
- abort();
+ if ((malloc_debug_flags & (SCALABLE_MALLOC_ABORT_ON_CORRUPTION|SCALABLE_MALLOC_ABORT_ON_ERROR))) {
+ _SIMPLE_STRING b = _simple_salloc();
+ if (b) {
+ _simple_sprintf(b, "*** error for object %p: pointer being freed was not allocated\n", ptr);
+ CRSetCrashLogMessage(_simple_string(b));
+ } else {
+ CRSetCrashLogMessage("*** error: pointer being freed was not allocated\n");
+ }
+ abort();
+ }
} else if (zone->version >= 6 && zone->free_definite_size)
malloc_zone_free_definite_size(zone, ptr, size);
else
void *
realloc(void *in_ptr, size_t new_size) {
- void *retval;
+ void *retval = NULL;
void *old_ptr;
malloc_zone_t *zone;
size_t old_size = 0;
retval = malloc_zone_malloc(inline_malloc_default_zone(), new_size);
} else {
zone = find_registered_zone(old_ptr, &old_size);
- if (zone && old_size >= new_size)
- return old_ptr;
-
- if (!zone)
- zone = inline_malloc_default_zone();
-
- retval = malloc_zone_realloc(zone, old_ptr, new_size);
+ if (!zone) {
+ malloc_printf("*** error for object %p: pointer being realloc'd was not allocated\n"
+ "*** set a breakpoint in malloc_error_break to debug\n", old_ptr);
+ malloc_error_break();
+ if ((malloc_debug_flags & (SCALABLE_MALLOC_ABORT_ON_CORRUPTION|SCALABLE_MALLOC_ABORT_ON_ERROR))) {
+ _SIMPLE_STRING b = _simple_salloc();
+ if (b) {
+ _simple_sprintf(b, "*** error for object %p: pointer being realloc'd was not allocated\n", old_ptr);
+ CRSetCrashLogMessage(_simple_string(b));
+ } else {
+ CRSetCrashLogMessage("*** error: pointer being realloc'd was not allocated\n");
+ }
+ abort();
+ }
+ } else {
+ retval = malloc_zone_realloc(zone, old_ptr, new_size);
+ }
}
if (retval == NULL) {
errno = ENOMEM;
return 0;
}
+size_t malloc_zone_pressure_relief(malloc_zone_t *zone, size_t goal)
+{
+ if (!zone) {
+ unsigned index = 0;
+ size_t total = 0;
+
+ // Take lock to defend against malloc_destroy_zone()
+ MALLOC_LOCK();
+ while (index < malloc_num_zones) {
+ zone = malloc_zones[index++];
+ if (zone->version < 8)
+ continue;
+ if (NULL == zone->pressure_relief)
+ continue;
+ if (0 == goal) /* Greedy */
+ total += zone->pressure_relief(zone, 0);
+ else if (goal > total)
+ total += zone->pressure_relief(zone, goal - total);
+ else /* total >= goal */
+ break;
+ }
+ MALLOC_UNLOCK();
+ return total;
+ } else {
+ // Assumes zone is not destroyed for the duration of this call
+ if (zone->version < 8)
+ return 0;
+ if (NULL == zone->pressure_relief)
+ return 0;
+ return zone->pressure_relief(zone, goal);
+ }
+}
+
/********* Batch methods ************/
unsigned
malloc_zone_batch_malloc(malloc_zone_t *zone, size_t size, void **results, unsigned num_requested) {
unsigned (*batch_malloc)(malloc_zone_t *, size_t, void **, unsigned) = zone-> batch_malloc;
- if (! batch_malloc) return 0;
+ if (! batch_malloc)
+ return 0;
if (malloc_check_start && (malloc_check_counter++ >= malloc_check_start)) {
internal_check();
}
if (b) {
_simple_sprintf(b, "*** error %d", x);
malloc_printf("%s\n", _simple_string(b));
- __crashreporter_info__ = _simple_string(b);
+ CRSetCrashLogMessage(_simple_string(b));
} else {
_malloc_printf(MALLOC_PRINTF_NOLOG, "*** error %d", x);
- __crashreporter_info__ = "*** DefaultMallocError called";
+ CRSetCrashLogMessage("*** DefaultMallocError called");
}
abort();
#endif
return(m);
}
+boolean_t
+malloc_zone_enable_discharge_checking(malloc_zone_t *zone)
+{
+ if (zone->version < 7) // Version must be >= 7 to look at the new discharge checking fields.
+ return FALSE;
+ if (NULL == zone->introspect->enable_discharge_checking)
+ return FALSE;
+ return zone->introspect->enable_discharge_checking(zone);
+}
+
+void
+malloc_zone_disable_discharge_checking(malloc_zone_t *zone)
+{
+ if (zone->version < 7) // Version must be >= 7 to look at the new discharge checking fields.
+ return;
+ if (NULL == zone->introspect->disable_discharge_checking)
+ return;
+ zone->introspect->disable_discharge_checking(zone);
+}
+
+void
+malloc_zone_discharge(malloc_zone_t *zone, void *memory)
+{
+ if (NULL == zone)
+ zone = malloc_zone_from_ptr(memory);
+ if (NULL == zone)
+ return;
+ if (zone->version < 7) // Version must be >= 7 to look at the new discharge checking fields.
+ return;
+ if (NULL == zone->introspect->discharge)
+ return;
+ zone->introspect->discharge(zone, memory);
+}
+
+void
+malloc_zone_enumerate_discharged_pointers(malloc_zone_t *zone, void (^report_discharged)(void *memory, void *info))
+{
+ if (!zone) {
+ unsigned index = 0;
+ while (index < malloc_num_zones) {
+ zone = malloc_zones[index++];
+ if (zone->version < 7)
+ continue;
+ if (NULL == zone->introspect->enumerate_discharged_pointers)
+ continue;
+ zone->introspect->enumerate_discharged_pointers(zone, report_discharged);
+ }
+ } else {
+ if (zone->version < 7)
+ return;
+ if (NULL == zone->introspect->enumerate_discharged_pointers)
+ return;
+ zone->introspect->enumerate_discharged_pointers(zone, report_discharged);
+ }
+}
+
/***************** OBSOLETE ENTRY POINTS ********************/
#if PHASE_OUT_OLD_MALLOC
.Fa start_size
bytes, and specifying
.Fa flags
-that alter the standard behavior of the zone.
The returned malloc zone can be used to provide custom allocation and
deallocation behavior, and to retrieve additional information about the
allocations in that zone.
+At present there are no client settable flag values recognized by malloc_create_zone(),
+the flags argument should always be passed as zero.
.Pp
The
.Fn malloc_destroy_zone
/*
- * Copyright (c) 1999, 2003, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 1999, 2003, 2006, 2007, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <mach/mach_error.h>
#include <mach/mach_time.h>
#include <stdio.h>
+#include <string.h>
#if __DARWIN_UNIX03
#include "pthread_internals.h"
#include <mach/clock.h>
-extern int __unix_conforming;
-extern mach_port_t clock_port;
+#ifndef BUILDING_VARIANT
+semaphore_t clock_sem = MACH_PORT_NULL;
+mach_port_t clock_port = MACH_PORT_NULL;
+
+void _init_clock_port() {
+ kern_return_t kr;
+ mach_port_t host = mach_host_self();
+
+ /* Get the clock service port for nanosleep */
+ kr = host_get_clock_service(host, SYSTEM_CLOCK, &clock_port);
+ if (kr != KERN_SUCCESS) {
+ abort();
+ }
+
+ kr = semaphore_create(mach_task_self_, &clock_sem, SYNC_POLICY_FIFO, 0);
+ if (kr != KERN_SUCCESS) {
+ abort();
+ }
+ mach_port_deallocate(mach_task_self(), host);
+}
+#else
extern semaphore_t clock_sem;
+extern mach_port_t clock_port;
+#endif /* !BUILDING_VARIANT */
+
+extern int __unix_conforming;
#ifdef VARIANT_CANCELABLE
extern void _pthread_testcancel(pthread_t thread, int isconforming);
extern int __semwait_signal(int cond_sem, int mutex_sem, int timeout, int relative, __int64_t tv_sec, __int32_t tv_nsec);
nanosleep(const struct timespec *requested_time, struct timespec *remaining_time) {
kern_return_t kret;
int ret;
- mach_timespec_t remain;
mach_timespec_t current;
+ mach_timespec_t completion;
if (__unix_conforming == 0)
__unix_conforming = 1;
if (remaining_time != NULL) {
- kret = clock_get_time(clock_port, ¤t);
+ /* once we add requested_time, this will be the completion time */
+ kret = clock_get_time(clock_port, &completion);
if (kret != KERN_SUCCESS) {
fprintf(stderr, "clock_get_time() failed: %s\n", mach_error_string(kret));
+ errno = EINVAL;
return -1;
}
}
return 0;
} else if (errno == EINTR) {
if (remaining_time != NULL) {
- ret = clock_get_time(clock_port, &remain);
+ ret = clock_get_time(clock_port, ¤t);
if (ret != KERN_SUCCESS) {
fprintf(stderr, "clock_get_time() failed: %s\n", mach_error_string(ret));
return -1;
}
/* This depends on the layout of a mach_timespec_t and timespec_t being equivalent */
- ADD_MACH_TIMESPEC(¤t, requested_time);
- SUB_MACH_TIMESPEC(¤t, &remain);
- remaining_time->tv_sec = current.tv_sec;
- remaining_time->tv_nsec = current.tv_nsec;
+ ADD_MACH_TIMESPEC(&completion, requested_time);
+ /* We have to compare first, since mach_timespect_t contains unsigned integers */
+ if(CMP_MACH_TIMESPEC(&completion, ¤t) > 0) {
+ SUB_MACH_TIMESPEC(&completion, ¤t);
+ remaining_time->tv_sec = completion.tv_sec;
+ remaining_time->tv_nsec = completion.tv_nsec;
+ } else {
+ bzero(remaining_time, sizeof(*remaining_time));
+ }
}
} else {
errno = EINVAL;
const char *paths[2];
struct FTW ftw;
FTSENT *cur;
- FTS *ftsp;
+ FTS *ftsp = NULL;
int ftsflags, fnflag, error, postorder, sverrno;
int cwd_fd = -1; /* cwd_fd != -1 means call chdir a lot */
/* XXX - nfds is currently unused */
if (nfds < 1 || nfds > OPEN_MAX) {
errno = EINVAL;
- return (-1);
+ error = -1;
+ goto done;
}
ftsflags = FTS_COMFOLLOW;
if (ftwflags & FTW_CHDIR) {
cwd_fd = open(".", O_RDONLY, 0);
if (cwd_fd < 0) {
- return -1;
+ error = -1;
+ goto done;
}
/* Prevent problems if fts ever starts using chdir when passed
FTS_PHYSICAL */
ENOTDIR, and EACCES */
{
int rc = stat(path, &path_stat);
- int e = errno;
if (rc < 0
&& (errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT
|| errno == ENOTDIR || errno == EACCES)) {
- return -1;
+ error = -1;
+ goto done;
}
if (rc >= 0 && nfn) {
if (!S_ISDIR(path_stat.st_mode)) {
errno = ENOTDIR;
- return -1;
+ error = -1;
+ goto done;
}
}
}
paths[1] = NULL;
ftsp = fts_open((char * const *)paths, ftsflags, NULL);
if (ftsp == NULL) {
- return (-1);
+ error = -1;
+ goto done;
}
error = 0;
while ((cur = fts_read(ftsp)) != NULL) {
free(free_me);
}
if (rc < 0) {
+ if(cur->fts_pathlen == cur->fts_namelen &&
+ fnflag == FTW_DNR) {
+ /* If cwd_fd is our last FD, fts_read will give us FTS_DNR
+ * and fts_path == fts_name == "."
+ * This check results in the correct errno being returned.
+ */
+ errno = EMFILE;
+ }
error = -1;
goto done;
}
}
done:
sverrno = errno;
- (void) fts_close(ftsp);
+ if(ftsp != NULL)
+ (void) fts_close(ftsp);
+ if(cwd_fd >= 0)
+ (void) close(cwd_fd);
errno = sverrno;
return (error);
}
* 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.
static char sccsid[] = "@(#)nice.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/nice.c,v 1.3 2002/03/22 21:52:05 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/nice.c,v 1.4 2007/01/09 00:27:54 imp Exp $");
#include <sys/types.h>
#include <sys/time.h>
-/*
+/*-
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* 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.
static char sccsid[] = "@(#)opendir.c 8.8 (Berkeley) 5/1/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/opendir.c,v 1.22 2004/08/14 17:46:10 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/opendir.c,v 1.24 2008/04/16 18:40:52 delphij Exp $");
#include "namespace.h"
#include <sys/param.h>
* Open a directory.
*/
DIR *
-opendir(name)
- const char *name;
+opendir(const char *name)
{
return (__opendir2(name, DTF_HIDEW|DTF_NODUP));
}
DIR *
-__opendir2(name, flags)
- const char *name;
- int flags;
+__opendir2(const char *name, int flags)
{
DIR *dirp;
int fd;
* 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.
#endif /* VARIANT_CANCELABLE */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/pause.c,v 1.6 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/pause.c,v 1.8 2009/12/05 19:31:38 ed Exp $");
#include <signal.h>
#include <unistd.h>
* Backwards compatible pause.
*/
int
-__pause()
+__pause(void)
{
sigset_t set;
--- /dev/null
+/*
+ * Copyright (c) 1983, 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)pause.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/pause.c,v 1.8 2009/12/05 19:31:38 ed Exp $");
+
+#include <signal.h>
+#include <unistd.h>
+
+/*
+ * Backwards compatible pause.
+ */
+int
+__pause(void)
+{
+ return sigpause(sigblock(0L));
+}
+__weak_reference(__pause, pause);
+__weak_reference(__pause, _pause);
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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@
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <stdlib.h>
+#include <platfunc.h>
+#include <machine/cpu_capabilities.h>
+
+#define PLAT_CAP_MASK (kHasMMX | kHasSSE | kHasSSE2 | kHasSSE3 | kCache32 | kCache64 | kCache128 | kFastThreadLocalStorage | kHasSupplementalSSE3 | k64Bit | kHasSSE4_1 | kHasSSE4_2 | kHasAES | kInOrderPipeline | kSlow | kUP)
+
+inline static int num_cpus(int capabilities) {
+ return (capabilities & kNumCPUs) >> kNumCPUsShift;
+}
+
+/* TODO: If 8151810 is fixed (or full support for visibility("internal") is added), change this to visibility("internal") */
+void __attribute__((visibility("hidden"))) *find_platform_function(const platfunc_descriptor *descriptors[]) {
+ int cap = _get_cpu_capabilities(),
+ have_cpus = num_cpus(cap);
+
+ for (int i = 0; descriptors[i] != 0; i++) {
+ int musthave_cpus = num_cpus(descriptors[i]->musthave),
+ canthave_cpus = num_cpus(descriptors[i]->canthave);
+ uint32_t musthave = descriptors[i]->musthave & PLAT_CAP_MASK,
+ canthave = descriptors[i]->canthave & PLAT_CAP_MASK;
+ /* First check that the CPU supports all the features that are in musthave */
+ if ((musthave & cap) != musthave)
+ continue;
+ /* Now check that the CPU doesn't have any of the features that are in canthave */
+ if ((canthave & cap) != 0)
+ continue;
+ /* Special case check for the number of CPUs. */
+ /* TODO: Should there be a way to specify < or > num cpus? */
+ if (musthave_cpus != 0 && have_cpus != musthave_cpus)
+ continue;
+ if (canthave_cpus != 0 && have_cpus == canthave_cpus)
+ continue;
+ /* otherwise, we have found our preferred implementation */
+ return descriptors[i]->address;
+ }
+
+ /* We didn't find an acceptable implementation. (bug in data structures!) */
+ return NULL;
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2003-2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#ifndef _I386_PLATFUNC_H
+#define _I386_PLATFUNC_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER__ */
+
+// This is a shared macro which calls PLATFUNC_VARIANT_NAME which has different
+// implementations in __ASSEMBLER__ and !__ASSEMBLER__
+#define PLATFUNC_DESCRIPTOR_NAME(name, variant) \
+ PLATFUNC_VARIANT_NAME(platfunc_ ## name, variant)
+
+#ifdef __ASSEMBLER__
+
+/* When trying to acquire a spinlock or mutex, we will spin in
+ * user mode for awhile, before entering the kernel to relinquish.
+ * MP_SPIN_TRIES is the initial value of _COMM_PAGE_SPIN_COUNT.
+ * The idea is that _COMM_PAGE_SPIN_COUNT will be adjusted up or
+ * down as the machine is plugged in/out, etc.
+ * At present spinlocks do not use _COMM_PAGE_SPIN_COUNT.
+ * They use MP_SPIN_TRIES directly.
+ */
+#define MP_SPIN_TRIES 1000
+
+#define PLATFUNC_VARIANT_NAME(name, variant) _ ## name ## $VARIANT$ ## variant
+
+#if defined (__i386__)
+#define PLATFUNC_DESCRIPTOR_FIELD_POINTER .long
+#define PLATFUNC_DESCRIPTOR_REFERENCE(name, variant) \
+ .long PLATFUNC_DESCRIPTOR_NAME(name, variant)
+#elif defined (__x86_64__)
+#define PLATFUNC_DESCRIPTOR_FIELD_POINTER .quad
+#define PLATFUNC_DESCRIPTOR_REFERENCE(name, variant) \
+ .quad PLATFUNC_DESCRIPTOR_NAME(name, variant)
+#else
+#error unsupported architecture
+#endif
+
+#ifdef VARIANT_DYLD
+
+#define PLATFUNC_FUNCTION_START_GENERIC(name, variant, codetype, alignment) \
+ PLATFUNC_FUNCTION_START(name, variant, codetype, alignment) \
+ .globl _ ## name ;\
+ _ ## name ## :
+
+#define PLATFUNC_DESCRIPTOR(name, variant, must, cant)
+
+#else /* VARIANT_DYLD */
+
+#define PLATFUNC_FUNCTION_START_GENERIC PLATFUNC_FUNCTION_START
+
+#define PLATFUNC_DESCRIPTOR(name, variant, must, cant) \
+ .const_data ;\
+ .private_extern PLATFUNC_DESCRIPTOR_NAME(name, variant) ;\
+ PLATFUNC_DESCRIPTOR_NAME(name, variant) ## : ;\
+ PLATFUNC_DESCRIPTOR_FIELD_POINTER PLATFUNC_VARIANT_NAME(name, variant) ;\
+ .long must ;\
+ .long cant ;\
+ .text
+
+#endif /* VARIANT_DYLD */
+
+#define PLATFUNC_FUNCTION_START(name, variant, codetype, alignment) \
+ .text ;\
+ .align alignment, 0x90 ;\
+ .private_extern PLATFUNC_VARIANT_NAME(name, variant) ;\
+ PLATFUNC_VARIANT_NAME(name, variant) ## :
+
+#else /* __ASSEMBLER__ */
+
+#define PLATFUNC_VARIANT_NAME(name, variant) name ## $VARIANT$ ## variant
+#define PLATFUNC_DESCRIPTOR_PROTOTYPE(name, variant) extern const platfunc_descriptor PLATFUNC_DESCRIPTOR_NAME(name, variant);
+#define PLATFUNC_DESCRIPTOR_REFERENCE(name, variant) &PLATFUNC_DESCRIPTOR_NAME(name, variant)
+
+#define PLATFUNC_DESCRIPTOR(name, variant, must, cant) \
+ extern void PLATFUNC_VARIANT_NAME(name, variant) (void); \
+ const platfunc_descriptor PLATFUNC_DESCRIPTOR_NAME(name, variant) = { \
+ .address = PLATFUNC_VARIANT_NAME(name, variant), \
+ .musthave = must, \
+ .canthave = cant \
+ }
+
+/*
+ * Each potential platfunc routine is described by one of these.
+ * Note that the PLATFUNC_DESCRIPTOR macro (above), used in
+ * assembly language, must agree with this.
+ */
+
+typedef struct platfunc_descriptor {
+ void *address; // address of code
+ uint32_t musthave; // _cpu_capability bits we must have
+ uint32_t canthave; // _cpu_capability bits we can't have
+} platfunc_descriptor;
+
+void *find_platform_function(const platfunc_descriptor *descriptors[]);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* _I386_PLATFUNC_H */
+
+#endif /* __i386__ || __x86_64__ */
* 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.
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/popen.c,v 1.18 2003/01/04 00:15:15 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/popen.c,v 1.21 2009/05/27 19:28:04 ed Exp $");
#include "namespace.h"
#include <sys/param.h>
+#include <sys/queue.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <wchar.h> /* fwide() */
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
+/* Our queue.h doesn't have SLIST_REMOVE_AFTER in it yet
+ * <rdar://problem/7431558> API: Add SLIST_REMOVE_AFTER to sys/queue.h (from FreeBSD)
+ */
+#ifndef SLIST_REMOVE_AFTER
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ SLIST_NEXT(elm, field) = \
+ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
+} while (0)
+#endif
+
/* 3516149 - store file descriptor and use that to close to prevent blocking */
struct pid {
- struct pid *next;
+ SLIST_ENTRY(pid) next;
FILE *fp;
int fd;
pid_t pid;
#define pidlist __popen_pidlist
#define pidlist_mutex __popen_pidlist_mutex
#ifndef BUILDING_VARIANT
-__private_extern__ struct pid *pidlist = NULL;
+__private_extern__ SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
__private_extern__ pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
#else /* BUILDING_VARIANT */
-extern struct pid *pidlist;
+extern SLIST_HEAD(, pid) pidlist;
extern pthread_mutex_t pidlist_mutex;
#endif /* !BUILDING_VARIANT */
}
(void)posix_spawn_file_actions_addclose(&file_actions, pdes[1]);
}
- for (p = pidlist; p; p = p->next) {
+ SLIST_FOREACH(p, &pidlist, next)
(void)posix_spawn_file_actions_addclose(&file_actions, p->fd);
- }
argv[0] = "sh";
argv[1] = "-c";
cur->fp = iop;
cur->pid = pid;
THREAD_LOCK();
- cur->next = pidlist;
- pidlist = cur;
+ SLIST_INSERT_HEAD(&pidlist, cur, next);
THREAD_UNLOCK();
fwide(iop, -1); /* byte stream */
return (iop);
pclose(iop)
FILE *iop;
{
- struct pid *cur, *last;
+ struct pid *cur, *last = NULL;
int pstat;
pid_t pid;
* Find the appropriate file pointer and remove it from the list.
*/
THREAD_LOCK();
- for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ SLIST_FOREACH(cur, &pidlist, next) {
if (cur->fp == iop)
break;
+ last = cur;
+ }
if (cur == NULL) {
THREAD_UNLOCK();
return (-1);
}
if (last == NULL)
- pidlist = cur->next;
+ SLIST_REMOVE_HEAD(&pidlist, next);
else
- last->next = cur->next;
+ SLIST_REMOVE_AFTER(last, next);
THREAD_UNLOCK();
(void)fclose(iop);
+++ /dev/null
-./psignal.3
\ No newline at end of file
--- /dev/null
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 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.
+.\"
+.\" @(#)psignal.3 8.2 (Berkeley) 2/27/95
+.\" $FreeBSD: src/lib/libc/gen/psignal.3,v 1.17 2007/01/09 00:27:54 imp Exp $
+.\"
+.Dd February 27, 1995
+.Dt PSIGNAL 3
+.Os
+.Sh NAME
+.Nm psignal ,
+.Nm strsignal ,
+.Nm sys_siglist ,
+.Nm sys_signame
+.Nd system signal messages
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Ft void
+.Fn psignal "unsigned sig" "const char *s"
+.Vt extern const char * const sys_siglist[] ;
+.Vt extern const char * const sys_signame[] ;
+.In string.h
+.Ft "char *"
+.Fn strsignal "int sig"
+.Sh DESCRIPTION
+The
+.Fn psignal
+and
+.Fn strsignal
+functions locate the descriptive message
+string for a signal number.
+.Pp
+The
+.Fn strsignal
+function accepts a signal number argument
+.Fa sig
+and returns a pointer to the corresponding message string.
+.Pp
+The
+.Fn psignal
+function accepts a signal number argument
+.Fa sig
+and writes it to the standard error.
+If the argument
+.Fa s
+is
+.Pf non- Dv NULL
+and does not point to the null character,
+.Fa s
+is written to the standard error file descriptor
+prior to the message string,
+immediately followed by a colon and a space.
+If the signal number is not recognized
+.Pq Xr sigaction 2 ,
+the string
+.Dq "Unknown signal
+is produced.
+.Pp
+The message strings can be accessed directly
+through the external array
+.Va sys_siglist ,
+indexed by recognized signal numbers.
+The external array
+.Va sys_signame
+is used similarly and
+contains short, lower-case abbreviations for signals
+which are useful for recognizing signal names
+in user input.
+The defined variable
+.Dv NSIG
+contains a count of the strings in
+.Va sys_siglist
+and
+.Va sys_signame .
+.Sh RETURN VALUES
+.Fn strsignal
+a pointer to the desired message or a NULL value indicating an error. This
+string is not to be freed by the caller. Beginning with Mac OSX 10.7, this
+string is unique to each thread.
+.Sh ERRORS
+.Fn strsignal
+will fail and no additional memory will be allocated if
+one of the following are true:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+There was insufficient memory to allocate storage space for the return value in the running thread.
+.El
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr perror 3 ,
+.Xr strerror 3
+.Sh HISTORY
+The
+.Fn psignal
+function appeared in
+.Bx 4.2 .
.\" to anyone/anything when using this software.
.\"
.\" @(#)rand48.3 V1.0 MB 8 Oct 1993
-.\" $FreeBSD: src/lib/libc/gen/rand48.3,v 1.16 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/rand48.3,v 1.17 2005/01/20 09:17:02 ru Exp $
.\"
.Dd October 8, 1993
.Dt RAND48 3
The
particular formula employed is
r(n+1) = (a * r(n) + c) mod m.
-The default value for the multiplicand `a' is 0xfdeece66d (25214903917).
+The default value for the multiplicand `a' is 0x5deece66d (25214903917).
The default value for the the addend `c' is 0xb (11).
The modulo is always fixed at m = 2 ** 48.
r(n) is called the seed of the random number generator.
.Pp
For a more powerful random number generator, see
.Xr random 3 .
-.Sh AUTHORS
-.An Martin Birgmeier
.Sh SEE ALSO
.Xr rand 3 ,
.Xr random 3
+.Sh AUTHORS
+.An Martin Birgmeier
* 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.
static char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/readdir.c,v 1.11 2002/02/26 21:39:32 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/readdir.c,v 1.15 2008/05/05 14:05:23 kib Exp $");
#include "namespace.h"
#include <sys/param.h>
#include <unistd.h>
#include "un-namespace.h"
-#include "telldir.h"
#include "libc_private.h"
+#include "telldir.h"
/*
* get next entry in a directory.
*/
struct dirent *
-_readdir_unlocked(dirp)
+_readdir_unlocked(dirp, skip)
DIR *dirp;
+ int skip;
{
struct dirent *dp;
dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
return (NULL);
dirp->dd_loc += dp->d_reclen;
- if (dp->d_ino == 0)
+ if (dp->d_ino == 0 && skip)
continue;
if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW))
continue;
struct dirent *dp;
if (__isthreaded) {
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
- dp = _readdir_unlocked(dirp);
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
+ dp = _readdir_unlocked(dirp, 1);
+ _pthread_mutex_unlock(&dirp->dd_lock);
}
else
- dp = _readdir_unlocked(dirp);
+ dp = _readdir_unlocked(dirp, 1);
return (dp);
}
saved_errno = errno;
errno = 0;
if (__isthreaded) {
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
- if ((dp = _readdir_unlocked(dirp)) != NULL)
+ _pthread_mutex_lock(&dirp->dd_lock);
+ if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
}
- else if ((dp = _readdir_unlocked(dirp)) != NULL)
+ else if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
if (errno != 0) {
* 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.
static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.7 2002/02/01 01:32:19 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.9 2008/03/16 19:08:53 das Exp $");
/*
* Scan the directory dirname calling select to make a list of selected
*/
#include "namespace.h"
-#include <sys/types.h>
-#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
{
struct dirent *d, *p, **names = NULL;
size_t nitems = 0;
- struct stat stb;
long arraysz;
DIR *dirp;
if ((dirp = opendir(dirname)) == NULL)
return(-1);
- if (_fstat(dirp->dd_fd, &stb) < 0)
- goto fail;
- /*
- * estimate the array size by taking the size of the directory file
- * and dividing it by a multiple of the minimum size entry.
- */
- arraysz = (stb.st_size / 24);
+ arraysz = 32; /* initial estimate of the array size */
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
if (names == NULL)
goto fail;
* realloc the maximum size.
*/
if (nitems >= arraysz) {
- const int inc = 10; /* increase by this much */
struct dirent **names2;
names2 = (struct dirent **)realloc((char *)names,
- (arraysz + inc) * sizeof(struct dirent *));
+ (arraysz * 2) * sizeof(struct dirent *));
if (names2 == NULL) {
free(p);
goto fail;
}
names = names2;
- arraysz += inc;
+ arraysz *= 2;
}
names[nitems++] = p;
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)scandir.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/scandir.3,v 1.8 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/scandir.3,v 1.9 2007/01/09 00:27:55 imp Exp $
.\"
.Dd May 20, 2008
.Dt SCANDIR 3
* 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.
static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.7 2002/02/01 01:32:19 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.9 2008/03/16 19:08:53 das Exp $");
/*
* Scan the directory dirname calling select to make a list of selected
*/
#include "namespace.h"
-#include <sys/types.h>
-#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
{
struct dirent *d, *p, **names = NULL;
size_t nitems = 0;
- struct stat stb;
long arraysz;
DIR *dirp;
if ((dirp = opendir(dirname)) == NULL)
return(-1);
- if (_fstat(dirp->dd_fd, &stb) < 0)
- goto fail;
- /*
- * estimate the array size by taking the size of the directory file
- * and dividing it by a multiple of the minimum size entry.
- */
- arraysz = (stb.st_size / 24);
+ arraysz = 32; /* initial estimate of the array size */
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
if (names == NULL)
goto fail;
* realloc the maximum size.
*/
if (nitems >= arraysz) {
- const int inc = 10; /* increase by this much */
struct dirent **names2;
names2 = (struct dirent **)realloc((char *)names,
- (arraysz + inc) * sizeof(struct dirent *));
+ (arraysz * 2) * sizeof(struct dirent *));
if (names2 == NULL) {
free(p);
goto fail;
}
names = names2;
- arraysz += inc;
+ arraysz *= 2;
}
names[nitems++] = p;
}
* 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.
static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/setmode.c,v 1.9 2003/02/23 00:24:03 mikeh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/setmode.c,v 1.11 2007/01/09 00:27:55 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
* bits) followed by a '+' (set bits).
*/
mode_t
-getmode(bbox, omode)
- const void *bbox;
- mode_t omode;
+getmode(const void *bbox, mode_t omode)
{
const BITCMD *set;
mode_t clrval, newmode, value;
#endif /* !VARIANT_LEGACY */
void *
-setmode(p)
- const char *p;
+setmode(const char *p)
{
int perm, who;
char op, *ep;
}
static BITCMD *
-addcmd(set, op, who, oparg, mask)
- BITCMD *set;
- int oparg, who;
- int op;
- u_int mask;
+addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
{
switch (op) {
case '=':
#ifdef SETMODE_DEBUG
static void
-dumpmode(set)
- BITCMD *set;
+dumpmode(BITCMD *set)
{
for (; set->cmd; ++set)
(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
* compacted, but it's not worth the effort.
*/
__private_extern__ void
-compress_mode(set)
- BITCMD *set;
+compress_mode(BITCMD *set)
{
BITCMD *nset;
int setbits, clrbits, Xbits, op;
p = strrchr(progname, '/');
if (p != NULL)
- __progname = (char *)(p + 1);
+ __progname = (char *)(p = p + 1);
else
__progname = (char *)(p = progname);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)siginterrupt.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/siginterrupt.3,v 1.14 2002/12/19 09:40:21 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/siginterrupt.3,v 1.15 2007/01/09 00:27:55 imp Exp $
.\"
.Dd June 4, 1993
.Dt SIGINTERRUPT 3
* 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.
static char sccsid[] = "@(#)siglist.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/siglist.c,v 1.4 2002/09/07 08:14:19 jmallett Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/siglist.c,v 1.6 2007/01/20 08:24:01 maxim Exp $");
-#include <sys/cdefs.h>
#include <signal.h>
const char *const sys_signame[NSIG] = {
* 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.
static char sccsid[] = "@(#)signal.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/signal.c,v 1.3 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/signal.c,v 1.4 2007/01/09 00:27:55 imp Exp $");
/*
* Almost backwards compatible signal.
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)signal.3 8.3 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/signal.3,v 1.38 2004/07/03 22:30:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/signal.3,v 1.43 2008/07/17 21:54:23 simon Exp $
.\"
.Dd June 7, 2004
.Dt SIGNAL 3
.Lb libc
.Sh SYNOPSIS
.In signal.h
-.\" The following is Quite Ugly, but syntactically correct.
-.\" Don't try to
-.\" fix it.
-.Ft void \*(lp*
-.Fn signal "int sig" "void \*(lp*func\*(rp\*(lpint\*(rp\*(rp\*(rp\*(lpint"
+.\" XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
+.\" The prototype for signal(3) cannot be cleanly marked up in -mdoc
+.\" without the following lower-level tweak.
+.nr in-synopsis-section 0
.Pp
+.Ft "void \*(lp*" Ns
+.Fo signal
+.Fa "int sig"
+.Fa "void \*(lp*func\*(rp\*(lpint\*(rp"
+.Fc Ns
+.Ft "\*(rp\*(lpint\*(rp" ;
+.Pp
+.nr in-synopsis-section 1
+.\" XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
or in the equivalent but easier to read typedef'd version:
.Ft typedef "void \*(lp*sig_t\*(rp \*(lpint\*(rp" ;
+.Pp
.Ft sig_t
.Fn signal "int sig" "sig_t func"
.Sh DESCRIPTION
For some system calls, if a signal is caught while the call is
executing and the call is prematurely terminated,
the call is automatically restarted.
-(The handler is installed using the
+Any handler installed with
+.Xr signal 3
+will have the
.Dv SA_RESTART
-flag with
-.Xr sigaction 2 . )
+flag set, meaning that any restartable system call will not return on
+receipt of a signal.
The affected system calls include
.Xr read 2 ,
.Xr write 2 ,
An attempt is made to ignore or supply a handler for
.Dv SIGKILL
or
-.Ev SIGSTOP .
+.Dv SIGSTOP .
.El
.Sh SEE ALSO
.Xr kill 1 ,
.Xr siginterrupt 3 ,
.Xr tty 4
.Sh HISTORY
-This
-.Fn signal
+The
+.Nm
facility appeared in
.Bx 4.0 .
The option to avoid the creation of child zombies through ignoring
* 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.
static char sccsid[] = "@(#)sleep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/sleep.c,v 1.31 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/sleep.c,v 1.33 2009/12/05 19:31:38 ed Exp $");
#include "namespace.h"
#include <errno.h>
#include "un-namespace.h"
unsigned int
-__sleep(seconds)
- unsigned int seconds;
+__sleep(unsigned int seconds)
{
struct timespec time_to_sleep;
struct timespec time_remaining;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)sleep.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/sleep.3,v 1.16 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/sleep.3,v 1.17 2007/01/09 00:27:55 imp Exp $
.\"
.Dd February 13, 1998
.Dt SLEEP 3
#include <mach/vm_statistics.h>
#import <malloc/malloc.h>
#import <stdlib.h>
+#import <CrashReporterClient.h>
extern void spin_lock(int *);
extern void spin_unlock(int *);
extern void thread_stack_pcs(vm_address_t *, unsigned, unsigned *);
-extern const char *__crashreporter_info__;
static inline void *allocate_pages(unsigned) __attribute__((always_inline));
static inline void *allocate_pages(unsigned bytes) {
if (vm_allocate(mach_task_self(), (vm_address_t *)&address, bytes,
VM_MAKE_TAG(VM_MEMORY_ANALYSIS_TOOL)| TRUE)) {
malloc_printf("*** out of memory while stack logging\n");
- __crashreporter_info__ = "*** out of memory while stack logging\n";
+ CRSetCrashLogMessage("*** out of memory while stack logging\n");
abort();
}
return (void *)address;
arg1 *= arg2; arg2 = arg3; arg3 = 0; type &= ~stack_logging_flag_calloc;
}
if (type & stack_logging_flag_object) {
- unsigned *class = (unsigned *)(long)arg1;
+ unsigned *class = (unsigned *)(uintptr_t)arg1;
arg1 = arg2 + class[5]; // corresponds to the instance_size field
arg2 = 0; arg3 = 0; type = stack_logging_type_alloc;
}
if (stack_logging_type_alloc) {
if (!result) return;
stack_logging_log_stack(stack_logging_type_alloc, 0, 0, 0, result, num_hot_to_skip+1);
- stack_logging_log_stack(stack_logging_type_alloc, arg1, 0, 0, *((int *)(long)result), num_hot_to_skip+1);
+ stack_logging_log_stack(stack_logging_type_alloc, arg1, 0, 0, *((int *)(uintptr_t)result), num_hot_to_skip+1);
return;
}
if (stack_logging_type_dealloc) {
if (!arg1) return;
- stack_logging_log_stack(stack_logging_type_dealloc, *((int *)(long)arg1), 0, 0, 0, num_hot_to_skip+1);
+ stack_logging_log_stack(stack_logging_type_dealloc, *((int *)(uintptr_t)arg1), 0, 0, 0, num_hot_to_skip+1);
stack_logging_log_stack(stack_logging_type_dealloc, arg1, 0, 0, 0, num_hot_to_skip+1);
return;
}
if (type == stack_logging_flag_set_handle_size) {
if (!arg1) return;
// Thanks to a horrible hack, arg3 contains the prvious handle value
- if (arg3 == *((int *)(long)arg1)) return;
+ if (arg3 == *((int *)(uintptr_t)arg1)) return;
stack_logging_log_stack(stack_logging_type_dealloc, arg3, 0, 0, 0, num_hot_to_skip+1);
- stack_logging_log_stack(stack_logging_type_alloc, arg2, 0, 0, *((int *)(long)arg1), num_hot_to_skip+1);
+ stack_logging_log_stack(stack_logging_type_alloc, arg2, 0, 0, *((int *)(uintptr_t)arg1), num_hot_to_skip+1);
return;
}
if (type == (stack_logging_type_dealloc|stack_logging_type_alloc)) {
// printf("Before getting samples 0x%x 0x%x 0x%x 0x%x -> 0x%x\n", type, arg1, arg2, arg3, result);
thread_stack_pcs((vm_address_t *)stack_entries, MAX_NUM_PC - 1, &count);
// We put at the bottom of the stack a marker that denotes the thread (+1 for good measure...)
- stack_entries[count++] = (int)(long)pthread_self() + 1;
+ stack_entries[count++] = (int)(uintptr_t)pthread_self() + 1;
/* now let's unique the sample */
// printf("Uniquing 0x%x 0x%x 0x%x 0x%x -> 0x%x\n", type, arg1, arg2, arg3, result);
rec->uniqued_stack = stack_logging_get_unique_stack(&stack_logging_the_record_list->uniquing_table, &stack_logging_the_record_list->uniquing_table_num_pages, stack_entries, count, num_hot_to_skip+2); // we additionally skip the warmest 2 entries that are an artefact of the code
}
index++;
}
- fprintf(stderr, "*** stack_logging: no record found for 0x%lx\n", (long)address);
+ fprintf(stderr, "*** stack_logging: no record found for %p\n", address);
return 0;
}
mach_vm_address_t address;
} mach_stack_logging_record_t;
+extern kern_return_t __mach_stack_logging_set_file_path(task_t task, char* file_path);
+
extern kern_return_t __mach_stack_logging_get_frames(task_t task, mach_vm_address_t address, mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, uint32_t *count);
/* Gets the last allocation record (malloc, realloc, or free) about address */
static const char *stack_log_file_suffix = ".index";
static const char *stack_log_link_suffix = ".link";
-static char stack_log_location[PATH_MAX];
-static char stack_log_reference_file[PATH_MAX];
-static char index_file_path[PATH_MAX];
+static void *stack_log_path_buffers = NULL;
+static char *stack_log_location = NULL;
+static char *stack_log_reference_file = NULL;
+char *__stack_log_file_path__ = NULL;
static int index_file_descriptor = -1;
// for accessing remote log files
}
}
-// If successful, returns path to log file that was created. Otherwise returns NULL.
+/*
+ * Check various temporary directory options starting with _PATH_TMP and use confstr.
+ * Allocating and releasing target buffer is the caller's responsibility.
+ */
+static bool
+get_writeable_temp_dir(char* target)
+{
+ if (!target) return false;
+ if (-1 != access(_PATH_TMP, W_OK)) {
+ strlcpy(target, _PATH_TMP, (size_t)PATH_MAX);
+ return true;
+ }
+ size_t n = confstr(_CS_DARWIN_USER_TEMP_DIR, target, (size_t) PATH_MAX);
+ if ((n > 0) && (n < PATH_MAX)) return true;
+ n = confstr(_CS_DARWIN_USER_CACHE_DIR, target, (size_t) PATH_MAX);
+ if ((n > 0) && (n < PATH_MAX)) return true;
+ /* No writeable tmp directory found. Maybe shd try /private/var/tmp for device here ... */
+ *target = '\0';
+ return false;
+}
+
+/*
+ * If successful, returns path to log file that was created, otherwise NULL.
+ *
+ * The log could be in one of 3 places (in decreasing order of preference)
+ *
+ * 1) value of environment variable MallocStackLoggingDirectory
+ * 2) the temp directory /tmp for desktop apps and internal apps on devices, or
+ * 3) the sandbox location + tmp/ in case of 3rd party apps on the device.
+ *
+ * For 1 and 3, we create a .link file with the path of the file. We prefer to
+ * create this file in /tmp, but if we are unable to (device 3rd party case),
+ * we create it in the same location as the .index file and issue a message
+ * in syslog asking for it to be copied to /tmp to enable tools.
+ *
+ */
static char *
create_log_file(void)
{
const char *progname = getprogname();
char *created_log_location = NULL;
+ if (stack_log_path_buffers == NULL) {
+ /*
+ * on first use, allocate buffers directly from the OS without
+ * using malloc
+ */
+
+ stack_log_path_buffers = allocate_pages((uint64_t)round_page(3*PATH_MAX));
+ if (stack_log_path_buffers == NULL) {
+ _malloc_printf(ASL_LEVEL_INFO, "unable to allocate memory for path buffers\n");
+ return NULL;
+ }
+
+ stack_log_location = &((char *)stack_log_path_buffers)[0*PATH_MAX];
+ stack_log_reference_file = &((char *)stack_log_path_buffers)[1*PATH_MAX];
+ __stack_log_file_path__ = &((char *)stack_log_path_buffers)[2*PATH_MAX];
+ }
+
// WARNING! use of snprintf can induce malloc() calls
bool use_alternate_location = false;
char *evn_log_directory = getenv("MallocStackLoggingDirectory");
+ size_t stack_log_len;
if (evn_log_directory && *evn_log_directory) {
use_alternate_location = true;
strlcpy(stack_log_location, evn_log_directory, (size_t)PATH_MAX);
- size_t evn_log_len = strlen(stack_log_location);
- // add the '/' only if it's not already there.
- if (evn_log_directory[evn_log_len-1] != '/') {
- strlcat(stack_log_location, "/", (size_t)PATH_MAX);
+ }
+ if (!use_alternate_location || (access(stack_log_location, W_OK) == -1)) {
+ if (!get_writeable_temp_dir(stack_log_location)) {
+ _malloc_printf(ASL_LEVEL_INFO, "No writeable tmp dir\n");
+ return NULL;
}
- } else {
- strlcpy(stack_log_location, _PATH_TMP, (size_t)PATH_MAX);
+ if (0 != strcmp(stack_log_location, _PATH_TMP))
+ use_alternate_location = true;
+ }
+ stack_log_len = strlen(stack_log_location);
+ // add the '/' only if it's not already there.
+ if (stack_log_location[stack_log_len-1] != '/') {
+ strlcat(stack_log_location, "/", (size_t)PATH_MAX);
+ ++stack_log_len;
}
- strlcat(stack_log_location, stack_log_file_base_name, (size_t)PATH_MAX);
- append_int(stack_log_location, pid, (size_t)PATH_MAX);
+ strlcpy(__stack_log_file_path__, stack_log_location, (size_t)PATH_MAX);
+
+ strlcat(__stack_log_file_path__, stack_log_file_base_name, (size_t)PATH_MAX);
+ append_int(__stack_log_file_path__, pid, (size_t)PATH_MAX);
if (progname && progname[0] != '\0') {
- strlcat(stack_log_location, ".", (size_t)PATH_MAX);
- strlcat(stack_log_location, progname, (size_t)PATH_MAX);
+ strlcat(__stack_log_file_path__, ".", (size_t)PATH_MAX);
+ strlcat(__stack_log_file_path__, progname, (size_t)PATH_MAX);
+ }
+ if (!use_alternate_location) strlcat(__stack_log_file_path__, ".XXXXXX", (size_t)PATH_MAX);
+ strlcat(__stack_log_file_path__, stack_log_file_suffix, (size_t)PATH_MAX);
+
+ // Securely create the log file.
+ if ((index_file_descriptor = mkstemps(__stack_log_file_path__, (int)strlen(stack_log_file_suffix))) != -1) {
+ _malloc_printf(ASL_LEVEL_INFO, "stack logs being written into %s\n", __stack_log_file_path__);
+ created_log_location = __stack_log_file_path__;
+ } else {
+ _malloc_printf(ASL_LEVEL_INFO, "unable to create stack logs at %s\n", stack_log_location);
+ if (use_alternate_location) delete_logging_file(stack_log_reference_file);
+ stack_log_reference_file[0] = '\0';
+ stack_log_location[0] = '\0';
+ __stack_log_file_path__[0] = '\0';
+ created_log_location = NULL;
+ return created_log_location;
}
- if (!use_alternate_location) strlcat(stack_log_location, ".XXXXXX", (size_t)PATH_MAX);
- strlcat(stack_log_location, stack_log_file_suffix, (size_t)PATH_MAX);
// in the case where the user has specified an alternate location, drop a reference file
// in /tmp with the suffix 'stack_log_link_suffix' (".link") and save the path of the
// stack logging file there.
+ bool use_alternate_link_location = false;
if (use_alternate_location) {
strlcpy(stack_log_reference_file, _PATH_TMP, (size_t)PATH_MAX);
+ if (access(stack_log_reference_file, W_OK) == -1) {
+ strlcpy(stack_log_reference_file, stack_log_location, (size_t)PATH_MAX);
+ use_alternate_link_location = true;
+ }
strlcat(stack_log_reference_file, stack_log_file_base_name, (size_t)PATH_MAX);
append_int(stack_log_reference_file, pid, (size_t)PATH_MAX);
if (progname && progname[0] != '\0') {
strlcat(stack_log_reference_file, ".", (size_t)PATH_MAX);
strlcat(stack_log_reference_file, progname, (size_t)PATH_MAX);
}
+ if (!use_alternate_link_location)
+ strlcat(stack_log_reference_file, ".XXXXXX", (size_t)PATH_MAX);
strlcat(stack_log_reference_file, ".XXXXXX", (size_t)PATH_MAX);
strlcat(stack_log_reference_file, stack_log_link_suffix, (size_t)PATH_MAX);
int link_file_descriptor = mkstemps(stack_log_reference_file, (int)strlen(stack_log_link_suffix));
if (link_file_descriptor == -1) {
- _malloc_printf(ASL_LEVEL_INFO, "unable to create stack reference file at %s\n", stack_log_location);
- return NULL;
+ _malloc_printf(ASL_LEVEL_INFO, "unable to create stack reference file %s at %s\n",
+ stack_log_reference_file, stack_log_location);
+ } else {
+ ssize_t written = write(link_file_descriptor, __stack_log_file_path__, strlen(__stack_log_file_path__));
+ if (written < (ssize_t)strlen(__stack_log_file_path__)) {
+ _malloc_printf(ASL_LEVEL_INFO, "unable to write to stack reference file %s at %s\n",
+ stack_log_reference_file, stack_log_location);
+ } else {
+ const char *description_string = "\n(This is a reference file to the stack logs at the path above.)\n";
+ write(link_file_descriptor, description_string, strlen(description_string));
}
- ssize_t written = write(link_file_descriptor, stack_log_location, strlen(stack_log_location));
- if (written < (ssize_t)strlen(stack_log_location)) {
- _malloc_printf(ASL_LEVEL_INFO, "unable to write to stack reference file at %s\n", stack_log_location);
- return NULL;
}
- const char *description_string = "\n(This is a reference file to the stack logs at the path above.)\n";
- write(link_file_descriptor, description_string, strlen(description_string));
close(link_file_descriptor);
}
-
- // Securely create the log file.
- if ((index_file_descriptor = mkstemps(stack_log_location, (int)strlen(stack_log_file_suffix))) != -1) {
- _malloc_printf(ASL_LEVEL_INFO, "stack logs being written into %s\n", stack_log_location);
- created_log_location = stack_log_location;
- } else {
- _malloc_printf(ASL_LEVEL_INFO, "unable to create stack logs at %s\n", stack_log_location);
- if (use_alternate_location) delete_logging_file(stack_log_reference_file);
- stack_log_reference_file[0] = '\0';
- stack_log_location[0] = '\0';
- created_log_location = NULL;
+ if (use_alternate_link_location) {
+ _malloc_printf(ASL_LEVEL_INFO, "Please issue: cp %s %s\n", stack_log_reference_file, _PATH_TMP);
}
return created_log_location;
}
static void
delete_log_files(void)
{
- if (stack_log_location && stack_log_location[0]) {
- if (delete_logging_file(stack_log_location) == 0) {
- _malloc_printf(ASL_LEVEL_INFO, "stack logs deleted from %s\n", stack_log_location);
- index_file_path[0] = '\0';
+ if (__stack_log_file_path__ && __stack_log_file_path__[0]) {
+ if (delete_logging_file(__stack_log_file_path__) == 0) {
+ _malloc_printf(ASL_LEVEL_INFO, "stack logs deleted from %s\n", __stack_log_file_path__);
+ __stack_log_file_path__[0] = '\0';
} else {
- _malloc_printf(ASL_LEVEL_INFO, "unable to delete stack logs from %s\n", stack_log_location);
+ _malloc_printf(ASL_LEVEL_INFO, "unable to delete stack logs from %s\n", __stack_log_file_path__);
}
}
if (stack_log_reference_file && stack_log_reference_file[0]) {
// descriptor was closed on us. We need to reopen it
if (fd == index_file_descriptor) {
- file_to_reopen = index_file_path;
+ file_to_reopen = __stack_log_file_path__;
fd_to_reset = &index_file_descriptor;
} else {
// We don't know about this file. Return (and abort()).
while (remaining > 0) {
written = robust_write(index_file_descriptor, p, remaining);
if (written == -1) {
- _malloc_printf(ASL_LEVEL_INFO, "Unable to write to stack logging file %s (%s)\n", index_file_path, strerror(errno));
+ _malloc_printf(ASL_LEVEL_INFO, "Unable to write to stack logging file %s (%s)\n",
+ __stack_log_file_path__, strerror(errno));
disable_stack_logging();
return;
}
pre_write_buffers = (stack_buffer_shared_memory*)mmap(0, full_shared_mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, (off_t)0);
close(shmid);
- if (!pre_write_buffers) {
+ if (MAP_FAILED == pre_write_buffers) {
_malloc_printf(ASL_LEVEL_INFO, "error mapping in shared memory for disk-based stack logging output buffers\n");
disable_stack_logging();
return;
close(shmid);
}
- if (shmid < 0 || cache->shmem == NULL) {
+ if (shmid < 0 || cache->shmem == MAP_FAILED) {
// failed to connect to the shared memory region; warn and continue.
_malloc_printf(ASL_LEVEL_INFO, "warning: unable to connect to remote process' shared memory; allocation histories may not be up-to-date.\n");
}
}
// if a snapshot is necessary, memcpy from remote frozen process' memory
- // note: there were two ways to do this – spin lock or suspend. suspend allows us to
+ // note: there were two ways to do this - spin lock or suspend. suspend allows us to
// analyze processes even if they were artificially suspended. with a lock, there'd be
// worry that the target was suspended with the lock taken.
if (update_snapshot) {
// In the stack log analysis process, find the stack logging files for target process <pid>
// by scanning the temporary directory for directory entries with names of the form "stack-logs.<pid>."
// If we find such a directory then open the stack logging files in there.
+// We might also have been passed the file path if the client first read it from __stack_log_file_path__
+// global variable in the target task, as will be needed if the .link cannot be put in /tmp.
static void
-open_log_files(pid_t pid, remote_task_file_streams *this_task_streams)
+open_log_files(pid_t pid, char* file_path, remote_task_file_streams *this_task_streams)
{
DIR *dp;
struct dirent *entry;
reap_orphaned_log_files(false); // reap any left-over log files (for non-existant processes, but not for this analysis process)
+ if (file_path != NULL) {
+ this_task_streams->index_file_stream = fopen(file_path, "r");
+ return;
+ }
+
if ((dp = opendir(_PATH_TMP)) == NULL) {
return;
}
}
static remote_task_file_streams*
-retain_file_streams_for_task(task_t task)
+retain_file_streams_for_task(task_t task, char* file_path)
{
if (task == MACH_PORT_NULL) return NULL;
remote_task_file_streams *this_task_streams = &remote_fds[next_remote_task_fd];
- open_log_files(pid, this_task_streams);
+ open_log_files(pid, file_path, this_task_streams);
// check if opens failed
if (this_task_streams->index_file_stream == NULL) {
#pragma mark - extern
+//
+// The following is used by client tools like malloc_history and Instruments to pass along the path
+// of the index file as read from the target task's __stack_log_file_path__ variable (set in this file)
+// Eventually, at a suitable point, this additional argument should just be added to the other APIs below.
+//
+kern_return_t
+__mach_stack_logging_set_file_path(task_t task, char* file_path)
+{
+ remote_task_file_streams *remote_fd = retain_file_streams_for_task(task, file_path);
+ if (remote_fd == NULL) {
+ return KERN_FAILURE;
+ }
+ return KERN_SUCCESS;
+}
+
kern_return_t
__mach_stack_logging_get_frames(task_t task, mach_vm_address_t address, mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, uint32_t *count)
{
- remote_task_file_streams *remote_fd = retain_file_streams_for_task(task);
+ remote_task_file_streams *remote_fd = retain_file_streams_for_task(task, NULL);
if (remote_fd == NULL) {
return KERN_FAILURE;
}
kern_return_t
__mach_stack_logging_enumerate_records(task_t task, mach_vm_address_t address, void enumerator(mach_stack_logging_record_t, void *), void *context)
{
- remote_task_file_streams *remote_fd = retain_file_streams_for_task(task);
+ remote_task_file_streams *remote_fd = retain_file_streams_for_task(task, NULL);
if (remote_fd == NULL) {
return KERN_FAILURE;
}
kern_return_t
__mach_stack_logging_frames_for_uniqued_stack(task_t task, uint64_t stack_identifier, mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, uint32_t *count)
{
- remote_task_file_streams *remote_fd = retain_file_streams_for_task(task);
+ remote_task_file_streams *remote_fd = retain_file_streams_for_task(task, NULL);
if (remote_fd == NULL) return KERN_FAILURE;
__unwind_stack_from_table_index(&remote_fd->cache->uniquing_table, stack_identifier, stack_frames_buffer, count, max_stack_frames);
fprintf(stderr, "sizeof stack_log_file_base_name: %lu\n", sizeof(stack_log_file_base_name)); total_globals += sizeof(stack_log_file_base_name);
fprintf(stderr, "sizeof stack_log_file_suffix: %lu\n", sizeof(stack_log_file_suffix)); total_globals += sizeof(stack_log_file_suffix);
fprintf(stderr, "sizeof stack_log_link_suffix: %lu\n", sizeof(stack_log_link_suffix)); total_globals += sizeof(stack_log_link_suffix);
- fprintf(stderr, "sizeof stack_log_location: %lu\n", sizeof(stack_log_location)); total_globals += sizeof(stack_log_location);
- fprintf(stderr, "sizeof stack_log_reference_file: %lu\n", sizeof(stack_log_reference_file)); total_globals += sizeof(stack_log_reference_file);
- fprintf(stderr, "sizeof index_file_path: %lu\n", sizeof(index_file_path)); total_globals += sizeof(index_file_path);
+ fprintf(stderr, "sizeof stack_log_location: %lu\n", (size_t)PATH_MAX); total_globals += (size_t)PATH_MAX;
+ fprintf(stderr, "sizeof stack_log_reference_file: %lu\n", (size_t)PATH_MAX); total_globals += (size_t)PATH_MAX;
+ fprintf(stderr, "sizeof __stack_log_file_path__ (index_file_path): %lu\n", (size_t)PATH_MAX); total_globals += (size_t)PATH_MAX;
fprintf(stderr, "sizeof index_file_descriptor: %lu\n", sizeof(index_file_descriptor)); total_globals += sizeof(index_file_descriptor);
fprintf(stderr, "sizeof remote_fds: %lu\n", sizeof(remote_fds)); total_globals += sizeof(remote_fds);
fprintf(stderr, "sizeof next_remote_task_fd: %lu\n", sizeof(next_remote_task_fd)); total_globals += sizeof(next_remote_task_fd);
{ "nodump", UF_NODUMP, 1 },
{ "noopaque", UF_OPAQUE, 0 },
{ "nohidden", UF_HIDDEN, 0 },
+ { "nocompressed", UF_COMPRESSED, 0 },
};
#define longestflaglen 12
#define nmappings (sizeof(mapping) / sizeof(mapping[0]))
+++ /dev/null
-./sysctl.c
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sysctl.c 8.2 (Berkeley) 1/4/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/gen/sysctl.c,v 1.6 2007/01/09 00:27:55 imp Exp $");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
+ void *newp, size_t newlen);
+
+int
+sysctl(name, namelen, oldp, oldlenp, newp, newlen)
+ int *name;
+ u_int namelen;
+ void *oldp, *newp;
+ size_t *oldlenp, newlen;
+{
+ if (name[0] != CTL_USER) {
+ if (namelen == 2 && name[0] == CTL_KERN && name[1] == KERN_EXEC) {
+ /*
+ * 7723306: intercept kern.exec and fake a return of
+ * a dummy string ("/" in this case)
+ */
+ if (newp != NULL) {
+ errno = EPERM;
+ return -1;
+ }
+ if (oldp == NULL) {
+ if (oldlenp != NULL) *oldlenp = 2;
+ return 0;
+ }
+ if (oldlenp == NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+ if (*oldlenp < 2) {
+ errno = ENOMEM;
+ return -1;
+ }
+ memmove(oldp, "/", 2);
+ *oldlenp = 2;
+ return 0;
+ }
+ return (__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+ }
+
+ if (newp != NULL) {
+ errno = EPERM;
+ return (-1);
+ }
+ if (namelen != 2) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch (name[1]) {
+ case USER_CS_PATH:
+ if (oldp && *oldlenp < sizeof(_PATH_STDPATH)) {
+ errno = ENOMEM;
+ return -1;
+ }
+ *oldlenp = sizeof(_PATH_STDPATH);
+ if (oldp != NULL)
+ memmove(oldp, _PATH_STDPATH, sizeof(_PATH_STDPATH));
+ return (0);
+ }
+
+ if (oldp && *oldlenp < sizeof(int)) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ *oldlenp = sizeof(int);
+ if (oldp == NULL)
+ return (0);
+
+ switch (name[1]) {
+ case USER_BC_BASE_MAX:
+ *(int *)oldp = BC_BASE_MAX;
+ return (0);
+ case USER_BC_DIM_MAX:
+ *(int *)oldp = BC_DIM_MAX;
+ return (0);
+ case USER_BC_SCALE_MAX:
+ *(int *)oldp = BC_SCALE_MAX;
+ return (0);
+ case USER_BC_STRING_MAX:
+ *(int *)oldp = BC_STRING_MAX;
+ return (0);
+ case USER_COLL_WEIGHTS_MAX:
+ *(int *)oldp = COLL_WEIGHTS_MAX;
+ return (0);
+ case USER_EXPR_NEST_MAX:
+ *(int *)oldp = EXPR_NEST_MAX;
+ return (0);
+ case USER_LINE_MAX:
+ *(int *)oldp = LINE_MAX;
+ return (0);
+ case USER_RE_DUP_MAX:
+ *(int *)oldp = RE_DUP_MAX;
+ return (0);
+ case USER_POSIX2_VERSION:
+ *(int *)oldp = _POSIX2_VERSION;
+ return (0);
+ case USER_POSIX2_C_BIND:
+#ifdef POSIX2_C_BIND
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_C_DEV:
+#ifdef POSIX2_C_DEV
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_CHAR_TERM:
+#ifdef POSIX2_CHAR_TERM
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_FORT_DEV:
+#ifdef POSIX2_FORT_DEV
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_FORT_RUN:
+#ifdef POSIX2_FORT_RUN
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_LOCALEDEF:
+#ifdef POSIX2_LOCALEDEF
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_SW_DEV:
+#ifdef POSIX2_SW_DEV
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_UPE:
+#ifdef POSIX2_UPE
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_STREAM_MAX:
+ *(int *)oldp = FOPEN_MAX;
+ return (0);
+ case USER_TZNAME_MAX:
+ *(int *)oldp = NAME_MAX;
+ return (0);
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
-- to print whatever data deemed necessary from the large
.Vt kinfo_proc
structure (
-.In sysctl.h
+.In sys/sysctl.h
) -- is left as an exercise for the reader.
.Pp
The top level names are defined with a CTL_ prefix in
.It Sy "Second level name Type Changeable"
.It "HW_MACHINE string no"
.It "HW_MODEL string no"
-.It "HW_NCPU integer no"
+.It "HW_NCPU integer no (DEPRECATED)"
.It "HW_BYTEORDER integer no"
.It "HW_PHYSMEM integer no"
.It "HW_MEMSIZE integer no"
The machine class.
.It Li HW_MODEL
The machine model
-.It Li HW_NCPU
-The number of cpus.
+.It Li HW_NCPU (DEPRECATED)
+The number of cpus. It is recommended that you use "hw.physicalcpu" "hw.physicalcpu_max" "hw.logicalcpu" or "hw.logicalcpu_max" instead.
+.It Li "hw.physicalcpu"
+The number of physical processors available in the current power management mode.
+.It Li "hw.physicalcpu_max"
+The maximum number of physical processors that could be available this boot.
+.It Li "hw.logicalcpu"
+The number of logical processors available in the current power management mode.
+.It Li "hw.logicalcpu_max"
+The maximum number of logical processors that could be available this boot.
.It Li HW_BYTEORDER
The byteorder (4,321, or 1,234).
.It Li HW_PHYSMEM
.It "KERN_OSREV integer no"
.It "KERN_OSTYPE string no"
.It "KERN_POSIX1 integer no"
-.It "KERN_PROC struct proc no"
+.It "KERN_PROC struct kinfo_proc no"
.It "KERN_PROF node not applicable"
.It "KERN_QUANTUM integer yes"
.It "KERN_SAVED_IDS integer no"
attempts to comply.
.It Li KERN_PROC
Return the entire process table, or a subset of it.
-An array of pairs of
-.Va struct proc
-followed by corresponding
-.Va struct eproc
+An array of
+.Va struct kinfo_proc
structures is returned,
whose size depends on the current number of such objects in the system.
The third and fourth level names are as follows:
These cannot be generated by any user processes.
.It Dv LOG_LPR
The line printer spooling system:
-.Xr lpr 1 ,
-.Xr lpc 8 ,
-.Xr lpd 8 ,
+.Xr cups-lpd 8 ,
+.Xr cupsd 8 ,
etc.
.It Dv LOG_MAIL
The mail system.
.Pp
These include files are necessary for all functions.
.Sh SEE ALSO
+.Xr asl 3 ,
.Xr logger 1 ,
.Xr compat 5 ,
.Xr syslogd 8
.Pp
Always use the proper secure idiom:
.Pp
-.Dl syslog(LOG_ERR, "%s", string);
+.Bd -literal -offset indent -compact
+syslog(LOG_ERR, "%s", string);
+.Ed
/*
- * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 1999-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
+
/*
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
* SUCH DAMAGE.
*/
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
#include <sys/syslog.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <netdb.h>
-#include <mach/mach.h>
-#include <servers/bootstrap.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
#include <string.h>
-#include <time.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <notify.h>
+#include <stdint.h>
+#include <pthread.h>
#include <asl.h>
-#include <asl_private.h>
-#include <asl_ipc.h>
+#include "asl_private.h"
#ifdef __STDC__
#include <stdarg.h>
#include <varargs.h>
#endif
-#include <crt_externs.h>
-
#define LOG_NO_NOTIFY 0x1000
-#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
+extern const char *asl_syslog_faciliy_num_to_name(int n);
#ifdef BUILDING_VARIANT
-__private_extern__ int _sl_LogStat; /* status bits, set by openlog() */
-__private_extern__ const char *_sl_LogTag; /* string to tag the entry with */
-__private_extern__ int _sl_LogFacility; /* default facility code */
-__private_extern__ int _sl_LogMask; /* local mask of priorities to be logged */
-__private_extern__ int _sl_MasterLogMask; /* master (remote control) mask of priorities to be logged */
-__private_extern__ int _sl_ProcLogMask; /* process-specific (remote control) mask of priorities to be logged */
-__private_extern__ int _sl_RCToken; /* for remote control change notification */
-__private_extern__ int _sl_NotifyToken; /* for remote control of priority filter */
-__private_extern__ int _sl_NotifyMaster; /* for remote control of priority filter */
-__private_extern__ int _sl_pid; /* pid */
+__private_extern__ pthread_mutex_t _sl_lock;
+__private_extern__ aslclient _sl_asl;
+__private_extern__ char *_sl_ident;
+__private_extern__ int _sl_fac;
+__private_extern__ int _sl_opts;
+__private_extern__ int _sl_mask;
#else /* !BUILDING_VARIANT */
-__private_extern__ int _sl_LogStat = 0; /* status bits, set by openlog() */
-__private_extern__ const char *_sl_LogTag = NULL; /* string to tag the entry with */
-__private_extern__ int _sl_LogFacility = LOG_USER; /* default facility code */
-__private_extern__ int _sl_LogMask = 0xff; /* mask of priorities to be logged */
-__private_extern__ int _sl_MasterLogMask = 0; /* master mask of priorities to be logged */
-__private_extern__ int _sl_ProcLogMask = 0; /* process-specific mask of priorities to be logged */
-__private_extern__ int _sl_RCToken = -1; /* for remote control change notification */
-__private_extern__ int _sl_NotifyToken = -1; /* for remote control of max logged priority */
-__private_extern__ int _sl_NotifyMaster = -1; /* for remote control of max logged priority */
-__private_extern__ int _sl_pid = -1; /* pid */
+__private_extern__ pthread_mutex_t _sl_lock = PTHREAD_MUTEX_INITIALIZER;
+__private_extern__ aslclient _sl_asl = NULL;
+__private_extern__ char *_sl_ident = NULL;
+__private_extern__ int _sl_fac = 0;
+__private_extern__ int _sl_opts = 0;
+__private_extern__ int _sl_mask = 0;
#endif /* BUILDING_VARIANT */
-__private_extern__ void _sl_init_notify();
-
-#define ASL_SERVICE_NAME "com.apple.system.logger"
-static mach_port_t asl_server_port = MACH_PORT_NULL;
-
-#define NOTIFY_SYSTEM_MASTER "com.apple.system.syslog.master"
-#define NOTIFY_PREFIX_SYSTEM "com.apple.system.syslog"
-#define NOTIFY_PREFIX_USER "user.syslog"
-#define NOTIFY_STATE_OFFSET 1000
-
-/* notify SPI */
-uint32_t notify_register_plain(const char *name, int *out_token);
-const char *asl_syslog_faciliy_num_to_name(int);
-
/*
* syslog, vsyslog --
* print message on log file; output is intended for syslogd(8).
void
vsyslog(int pri, const char *fmt, va_list ap)
{
- int status, i, saved_errno, filter, check, rc_filter;
- time_t tick;
- struct timeval tval;
- uint32_t elen, count, outlen;
- char *p, *str, *expanded, *err_str, hname[MAXHOSTNAMELEN+1];
- const char *val;
- uint64_t cval;
- int fd, mask, level, facility;
- aslmsg msg;
- kern_return_t kstatus;
- caddr_t out;
-
- saved_errno = errno;
-
- if (_sl_pid == -1) _sl_pid = getpid();
-
- /* Check for invalid bits. */
- if (pri & ~(LOG_PRIMASK | LOG_FACMASK))
- {
- syslog(INTERNALLOG, "syslog: unknown facility/priority: %x", pri);
- pri &= (LOG_PRIMASK | LOG_FACMASK);
- }
-
- level = LOG_PRI(pri);
- facility = pri & LOG_FACMASK;
-
- if (facility == 0) facility = _sl_LogFacility;
-
- _sl_init_notify();
-
- /* initialize or re-check process-specific and master filters */
- if (_sl_RCToken >= 0)
- {
- check = 0;
- status = notify_check(_sl_RCToken, &check);
- if ((status == NOTIFY_STATUS_OK) && (check != 0))
- {
- if (_sl_NotifyMaster >= 0)
- {
- cval = 0;
- if (notify_get_state(_sl_NotifyMaster, &cval) == NOTIFY_STATUS_OK) _sl_MasterLogMask = cval;
- }
-
- if (_sl_NotifyToken >= 0)
- {
- cval = 0;
- if (notify_get_state(_sl_NotifyToken, &cval) == NOTIFY_STATUS_OK) _sl_ProcLogMask = cval;
- }
- }
- }
-
- filter = _sl_LogMask;
- rc_filter = 0;
-
- /* master filter overrides local filter */
- if (_sl_MasterLogMask != 0)
- {
- filter = _sl_MasterLogMask;
- rc_filter = 1;
- }
-
- /* process-specific filter overrides local and master */
- if (_sl_ProcLogMask != 0)
- {
- filter = _sl_ProcLogMask;
- rc_filter = 1;
- }
-
- mask = LOG_MASK(level);
- if ((mask & filter) == 0) return;
-
- /* Build the message. */
- msg = asl_new(ASL_TYPE_MSG);
-
- if (_sl_LogTag == NULL) _sl_LogTag = *(*_NSGetArgv());
- if (_sl_LogTag != NULL)
- {
- asl_set(msg, ASL_KEY_SENDER, _sl_LogTag);
- }
-
- str = (char *)asl_syslog_faciliy_num_to_name(facility);
- if (str != NULL) asl_set(msg, ASL_KEY_FACILITY, str);
-
- str = NULL;
- memset(&tval, 0, sizeof(struct timeval));
-
- status = gettimeofday(&tval, NULL);
- if (status == 0)
- {
- str = NULL;
- asprintf(&str, "%lu", tval.tv_sec);
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_TIME, str);
- free(str);
- }
-
- str = NULL;
- asprintf(&str, "%lu", tval.tv_usec * 1000);
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_TIME_NSEC, str);
- free(str);
- }
- }
- else
- {
- tick = time(NULL);
- str = NULL;
- asprintf(&str, "%lu", tick);
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_TIME, str);
- free(str);
- }
- }
-
- str = NULL;
- asprintf(&str, "%u", _sl_pid);
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_PID, str);
- free(str);
- }
-
- str = NULL;
- asprintf(&str, "%d", getuid());
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_UID, str);
- free(str);
- }
-
- str = NULL;
- asprintf(&str, "%u", getgid());
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_GID, str);
- free(str);
- }
-
- str = NULL;
- asprintf(&str, "%u", level);
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_LEVEL, str);
- free(str);
- }
-
- status = gethostname(hname, MAXHOSTNAMELEN);
- if (status < 0) asl_set(msg, ASL_KEY_HOST, "localhost");
- else asl_set(msg, ASL_KEY_HOST, hname);
-
- /* check for %m */
- count = 0;
- for (i = 0; fmt[i] != '\0'; i++)
- {
- if ((fmt[i] == '%') && (fmt[i+1] == 'm')) count++;
- }
-
- expanded = NULL;
- elen = 0;
- err_str = NULL;
-
- /* deal with malloc failures gracefully */
- if (count > 0)
- {
- err_str = strdup(strerror(saved_errno));
- if (err_str == NULL) count = 0;
- else
- {
- elen = strlen(err_str);
- expanded = malloc(i + (count * elen));
- if (expanded == NULL) count = 0;
- }
- }
+ int fac;
+ aslmsg facmsg;
+ const char *facility;
- if (expanded == NULL) expanded = (char *)fmt;
- if (count > 0)
+ facmsg = NULL;
+ fac = pri & LOG_FACMASK;
+ if (fac != 0)
{
- p = expanded;
-
- for (i = 0; fmt[i] != '\0'; i++)
+ facility = asl_syslog_faciliy_num_to_name(fac);
+ if (facility != NULL)
{
- if ((fmt[i] == '%') && (fmt[i+1] == 'm'))
- {
- memcpy(p, err_str, elen);
- p += elen;
- i++;
- }
- else
- {
- *p++ = fmt[i];
- }
+ facmsg = asl_new(ASL_TYPE_MSG);
+ asl_set(facmsg, ASL_KEY_FACILITY, facility);
}
-
- *p = '\0';
}
- if (err_str != NULL) free(err_str);
-
- vasprintf(&str, expanded, ap);
- if (count > 0) free(expanded);
-
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_MSG, str);
-
- /* Output to stderr if requested. */
- if (_sl_LogStat & LOG_PERROR)
- {
- p = NULL;
- if (_sl_LogStat & LOG_PID) asprintf(&p, "%s[%u]: %s", (_sl_LogTag == NULL) ? "???" : _sl_LogTag, _sl_pid, str);
- else asprintf(&p, "%s: %s", (_sl_LogTag == NULL) ? "???" : _sl_LogTag, str);
-
- if (p != NULL)
- {
- struct iovec iov[2];
-
- iov[0].iov_base = p;
- iov[0].iov_len = strlen(p);
- iov[1].iov_base = "\n";
- iov[1].iov_len = 1;
- writev(STDERR_FILENO, iov, 2);
- free(p);
- }
- }
-
- free(str);
- }
-
- /* Set "ASLOption store" if remote control is active */
- if (rc_filter != 0)
- {
- val = asl_get(msg, ASL_KEY_OPTION);
- if (val == NULL)
- {
- asl_set(msg, ASL_KEY_OPTION, ASL_OPT_STORE);
- }
- else
- {
- str = NULL;
- asprintf(&str, "%s %s", ASL_OPT_STORE, val);
- if (str != NULL)
- {
- asl_set(msg, ASL_KEY_OPTION, str);
- free(str);
- str = NULL;
- }
- }
- }
-
- /* send a mach message to syslogd */
- str = asl_format_message(msg, ASL_MSG_FMT_RAW, ASL_TIME_FMT_SEC, ASL_ENCODE_ASL, &count);
- if (str != NULL)
- {
- outlen = count + 11;
- kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&out, outlen + 1, TRUE);
- if (kstatus == KERN_SUCCESS)
- {
- memset(out, 0, outlen + 1);
- snprintf((char *)out, outlen, "%10u %s", count, str);
-
- status = 0;
- if (asl_server_port == MACH_PORT_NULL) kstatus = bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &asl_server_port);
-
- if (kstatus == KERN_SUCCESS) kstatus = _asl_server_message(asl_server_port, (caddr_t)out, outlen + 1);
- else vm_deallocate(mach_task_self(), (vm_address_t)out, outlen + 1);
-
- if (kstatus == KERN_SUCCESS)
- {
- free(str);
- asl_free(msg);
- return;
- }
- }
-
- free(str);
- }
-
- /*
- * Output the message to the console.
- */
- if (_sl_LogStat & LOG_CONS && (fd = open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0)
- {
- count = 0;
-
- p = asl_format_message(msg, ASL_MSG_FMT_STD, ASL_TIME_FMT_LCL, ASL_ENCODE_SAFE, &count);
- if (p != NULL)
- {
- struct iovec iov;
-
- /* count includes trailing nul */
- iov.iov_len = count - 1;
- iov.iov_base = p;
- writev(fd, &iov, 1);
-
- free(p);
- }
-
- close(fd);
- }
-
- asl_free(msg);
+ asl_vlog(_sl_asl, facmsg, LOG_PRI(pri), fmt, ap);
+ if (facmsg != NULL) asl_free(facmsg);
}
#ifndef BUILDING_VARIANT
-__private_extern__ void
-_syslog_fork_child()
-{
- _sl_RCToken = -1;
- _sl_NotifyToken = -1;
- _sl_NotifyMaster = -1;
-
- asl_server_port = MACH_PORT_NULL;
-
- _sl_pid = getpid();
-}
-
-__private_extern__ void
-_sl_init_notify()
+void
+openlog(const char *ident, int opts, int logfac)
{
- int status;
- char *notify_name;
- uint32_t euid;
+ const char *facility;
+ uint32_t asl_opts;
- if (_sl_LogStat & LOG_NO_NOTIFY)
- {
- _sl_RCToken = -2;
- _sl_NotifyMaster = -2;
- _sl_NotifyToken = -2;
- return;
- }
-
- if (_sl_RCToken == -1)
- {
- status = notify_register_check(NOTIFY_RC, &_sl_RCToken);
- if (status != NOTIFY_STATUS_OK) _sl_RCToken = -2;
- }
+ pthread_mutex_lock(&_sl_lock);
- if (_sl_NotifyMaster == -1)
- {
- status = notify_register_plain(NOTIFY_SYSTEM_MASTER, &_sl_NotifyMaster);
- if (status != NOTIFY_STATUS_OK) _sl_NotifyMaster = -2;
- }
+ /* close existing aslclient */
+ if (_sl_asl != NULL) asl_close(_sl_asl);
+ _sl_asl = NULL;
- if (_sl_NotifyToken == -1)
- {
- _sl_NotifyToken = -2;
+ if (_sl_ident != NULL) free(_sl_ident);
+ _sl_ident = NULL;
- euid = geteuid();
- notify_name = NULL;
- if (euid == 0) asprintf(¬ify_name, "%s.%d", NOTIFY_PREFIX_SYSTEM, getpid());
- else asprintf(¬ify_name, "user.uid.%d.syslog.%d", euid, getpid());
+ /* open with specified parameters */
- if (notify_name != NULL)
- {
- status = notify_register_plain(notify_name, &_sl_NotifyToken);
- free(notify_name);
- if (status != NOTIFY_STATUS_OK) _sl_NotifyToken = -2;
- }
- }
-}
+ if (ident != NULL) _sl_ident = strdup(ident);
+ /* NB we allow the strdup to fail silently */
-void
-openlog(const char *ident, int logstat, int logfac)
-{
- kern_return_t kstatus;
+ _sl_fac = logfac;
+ facility = asl_syslog_faciliy_num_to_name(_sl_fac);
- if (ident != NULL) _sl_LogTag = ident;
+ _sl_opts = opts;
+ asl_opts = ASL_OPT_SYSLOG_LEGACY;
- _sl_LogStat = logstat;
+ if (_sl_opts & LOG_NO_NOTIFY) asl_opts |= ASL_OPT_NO_REMOTE;
+ if (_sl_opts & LOG_PERROR) asl_opts |= ASL_OPT_STDERR;
- if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) _sl_LogFacility = logfac;
+ _sl_mask = ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG);
- if (asl_server_port == MACH_PORT_NULL)
- {
- kstatus = bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &asl_server_port);
- }
+ _sl_asl = asl_open(_sl_ident, facility, asl_opts);
+ asl_set_filter(_sl_asl, _sl_mask);
- _sl_pid = getpid();
- _sl_init_notify();
+ pthread_mutex_unlock(&_sl_lock);
}
void
closelog()
{
- if (asl_server_port != MACH_PORT_NULL) mach_port_deallocate(mach_task_self(), asl_server_port);
- asl_server_port = MACH_PORT_NULL;
+ pthread_mutex_lock(&_sl_lock);
- if (_sl_NotifyToken != -1) notify_cancel(_sl_NotifyToken);
- _sl_NotifyToken = -1;
+ if (_sl_asl != NULL) asl_close(_sl_asl);
+ _sl_asl = NULL;
- if (_sl_NotifyMaster != -1) notify_cancel(_sl_NotifyMaster);
- _sl_NotifyMaster = -1;
+ if (_sl_ident != NULL) free(_sl_ident);
+ _sl_ident = NULL;
+
+ pthread_mutex_unlock(&_sl_lock);
}
/* setlogmask -- set the log mask level */
int
-setlogmask(int pmask)
+setlogmask(int mask)
{
- int omask;
+ int oldmask;
+
+ pthread_mutex_lock(&_sl_lock);
+
+ _sl_mask = mask;
+ oldmask = asl_set_filter(_sl_asl, mask);
+
+ pthread_mutex_unlock(&_sl_lock);
- omask = _sl_LogMask;
- if (pmask != 0) _sl_LogMask = pmask;
- return (omask);
+ return oldmask;
}
#endif /* !BUILDING_VARIANT */
* 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.
static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/telldir.c,v 1.8 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/telldir.c,v 1.11 2008/05/05 14:05:23 kib Exp $");
#include "namespace.h"
#include <sys/param.h>
#if __DARWIN_UNIX03
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) {
if (
#if __DARWIN_64_BIT_INO_T
}
if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) {
if (__isthreaded)
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
return (-1);
}
#else /* !__DARWIN_UNIX03 */
if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
return (-1);
if (__isthreaded)
- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_lock(&dirp->dd_lock);
#endif /* __DARWIN_UNIX03 */
lp->loc_index = dirp->dd_td->td_loccnt++;
#if __DARWIN_64_BIT_INO_T
found:
#endif /* __DARWIN_UNIX03 */
if (__isthreaded)
- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
+ _pthread_mutex_unlock(&dirp->dd_lock);
return (lp->loc_index);
}
#endif /* __DARWIN_64_BIT_INO_T */
dirp->dd_loc = 0;
while (dirp->dd_loc < lp->loc_loc) {
- dp = _readdir_unlocked(dirp);
+ dp = _readdir_unlocked(dirp, 0);
if (dp == NULL)
break;
}
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/lib/libc/gen/telldir.h,v 1.2 2001/01/24 12:59:24 deischen Exp $
+ * $FreeBSD: src/lib/libc/gen/telldir.h,v 1.3 2008/05/05 14:05:23 kib Exp $
*/
#ifndef _TELLDIR_H_
#if __DARWIN_64_BIT_INO_T
size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep);
#endif /* __DARWIN_64_BIT_INO_T */
-struct dirent *_readdir_unlocked(DIR *) __DARWIN_INODE64(_readdir_unlocked);
+struct dirent *_readdir_unlocked(DIR *, int) __DARWIN_INODE64(_readdir_unlocked);
void _reclaim_telldir(DIR *);
void _seekdir(DIR *, long) __DARWIN_ALIAS_I(_seekdir);
long telldir(DIR *) __DARWIN_ALIAS_I(telldir);
* 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.
static char sccsid[] = "@(#)termios.c 8.2 (Berkeley) 2/21/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/termios.c,v 1.13 2002/05/28 16:59:39 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/termios.c,v 1.16 2009/05/07 13:49:48 ed Exp $");
#if __DARWIN_UNIX03
#ifdef VARIANT_CANCELABLE
return ((pid_t)s);
}
+#if 0 // Needs API review first
+pid_t
+tcgetsid(int fd)
+{
+ int s;
+
+ if (_ioctl(fd, TIOCGSID, &s) < 0)
+ return ((pid_t)-1);
+
+ return ((pid_t)s);
+}
+
+int
+tcsetsid(int fd, pid_t pid)
+{
+
+ if (pid != getsid(0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (_ioctl(fd, TIOCSCTTY, NULL));
+}
+#endif
+
speed_t
cfgetospeed(t)
const struct termios *t;
* 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.
static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/time.c,v 1.4 2003/07/19 02:53:46 wollman Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/time.c,v 1.5 2007/01/09 00:27:55 imp Exp $");
#include <sys/types.h>
#include <sys/time.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)time.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/time.3,v 1.13 2004/07/02 19:07:30 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/time.3,v 1.15 2007/01/09 00:27:55 imp Exp $
.\"
.Dd July 18, 2003
.Dt TIME 3
.Nm
function conforms to
.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Fn time
+function appeared in
+.At v6 .
.Sh BUGS
Neither
.St -isoC-99
did not set
.No \&* Ns Va tloc
in the error case.
-.Sh HISTORY
-A
-.Fn time
-function appeared in
-.At v6 .
#include "libc_private.h"
#ifndef BUILDING_VARIANT
-static char buf[sizeof(_PATH_DEV) + MAXNAMLEN];
+static pthread_once_t ttyname_buf_control = PTHREAD_ONCE_INIT;
+static char *buf = NULL;
static char *ttyname_threaded(int fd);
static char *ttyname_unthreaded(int fd);
}
#endif /* __DARWIN_UNIX03 */
- strcpy(thrbuf, _PATH_DEV);
+ strlcpy(thrbuf, _PATH_DEV, len);
if (devname_r(sb.st_rdev, S_IFCHR,
thrbuf + strlen(thrbuf), len - strlen(thrbuf)) == NULL)
#if __DARWIN_UNIX03
#endif /* __DARWIN_UNIX03 */
}
+static void
+ttyname_buf_allocate(void)
+{
+ buf = malloc(sizeof(_PATH_DEV) + MAXNAMLEN);
+}
+
static char *
ttyname_unthreaded(int fd)
{
return (NULL);
}
- strcpy(buf, _PATH_DEV);
+ if (pthread_once(&ttyname_buf_control, ttyname_buf_allocate)
+ || !buf) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+
+ strlcpy(buf, _PATH_DEV, sizeof(_PATH_DEV) + MAXNAMLEN);
if (devname_r(sb.st_rdev, S_IFCHR,
- buf + strlen(buf), sizeof(buf) - strlen(buf)) == NULL) {
+ buf + strlen(buf), sizeof(_PATH_DEV) + MAXNAMLEN - strlen(buf)) == NULL) {
errno = ERANGE;
return (NULL);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)ualarm.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/gen/ualarm.3,v 1.19 2004/07/02 23:52:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/ualarm.3,v 1.20 2007/01/09 00:27:56 imp Exp $
.\"
.Dd April 19, 1994
.Dt UALARM 3
* 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.
static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/unvis.c,v 1.9 2004/08/02 08:46:23 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/unvis.c,v 1.10 2007/01/09 00:27:56 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)usleep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/usleep.c,v 1.28 2002/12/29 00:59:09 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/usleep.c,v 1.31 2009/12/05 19:31:38 ed Exp $");
#include "namespace.h"
#include <time.h>
#include "un-namespace.h"
int
-usleep(useconds)
- useconds_t useconds;
+usleep(useconds_t useconds)
{
struct timespec time_to_sleep;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)usleep.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/usleep.3,v 1.18 2002/12/29 00:59:09 mike Exp $
+.\" $FreeBSD: src/lib/libc/gen/usleep.3,v 1.19 2007/01/09 00:27:56 imp Exp $
.\"
.Dd February 13, 1998
.Dt USLEEP 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)utime.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/utime.3,v 1.11 2002/08/24 00:39:43 mike Exp $
+.\" $FreeBSD: src/lib/libc/gen/utime.3,v 1.14 2007/01/09 00:27:56 imp Exp $
.\"
.Dd June 4, 1993
.Dt UTIME 3
The
.Fn utime
function sets the access and modification times of the named file,
-based on the structures in the argument array
+based on the
+.Va actime
+and
+.Va modtime
+fields of the
+.Vt "struct utimbuf"
+pointed at by
.Fa times .
.Pp
If the times are specified (the
.Sh SEE ALSO
.Xr stat 2 ,
.Xr utimes 2
-.Sh HISTORY
-A
-.Fn utime
-function appeared in
-.At v7 .
.Sh STANDARDS
The
.Fn utime
function conforms to
.St -p1003.1-88 .
+.Sh HISTORY
+A
+.Fn utime
+function appeared in
+.At v7 .
/*
- * Copyright (c) 2005-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#endif /* UTMP_COMPAT */
#include <utmpx.h>
#include <utmpx-darwin.h>
+#include <utmpx_thread.h>
#include <asl.h>
#include <asl_private.h>
#include <asl_store.h>
#include <ttyent.h>
#endif /* UTMP_COMPAT */
+__private_extern__ const char __utx_magic__[UTMPX_MAGIC] = __UTX_MAGIC__;
+
extern const char _utmpx_vers[]; /* in utmpx.c */
-extern char *asl_list_to_string(asl_search_result_t *, uint32_t *);
-extern asl_search_result_t *asl_list_from_string(const char *);
static void msg2lastlogx(const aslmsg, struct lastlogx *);
static void msg2utmpx(const aslmsg, struct utmpx *);
/* indirection causes argument to be substituted before stringification */
#define STR(x) __STRING(x)
+#ifdef UTMP_COMPAT
static char *
_pwnam_r(const char *user, struct passwd *pw)
{
}
return buf;
}
+#endif
static char *
_pwuid_r(uid_t uid, struct passwd *pw)
asl_set_query(m, FACILITY, LASTLOG_FACILITY, ASL_QUERY_OP_EQUAL);
asl_set_query(m, "ut_user", user, ASL_QUERY_OP_EQUAL);
- qm[0] = m;
+ qm[0] = (asl_msg_t *)m;
query.count = 1;
query.msg = qm;
utmpx2msg(const struct utmpx *u, aslmsg m)
{
char buf[_UTX_HOSTSIZE + 1]; /* the largest string in struct utmpx */
- char *cp;
+ const char *cp;
#define ISET(e) { snprintf(buf, sizeof(buf), "%d", u->e); \
asl_set(m, #e, buf); }
#define LSET(e) { snprintf(buf, sizeof(buf), "%ld", u->e); \
}
SSET(ut_user);
- cp = u->ut_id + sizeof(u->ut_id);
+ cp = (char *)u->ut_id + sizeof(u->ut_id);
while(--cp >= u->ut_id && isprint(*cp)) {}
if(cp < u->ut_id) {
SSET(ut_id);
static struct {
int fd;
int dir;
- char file[MAXPATHLEN];
+ char *file;
off_t off;
size_t count;
#ifdef __LP64__
}
len = strlen(fname);
- if (len >= sizeof(wtmp_file.file))
+ if (len >= MAXPATHLEN)
return 0;
/* must end in x! */
if (fname[len - 1] != 'x')
return 0;
- (void)strlcpy(wtmp_file.file, fname, sizeof(wtmp_file.file));
-
if (wtmp_func.which == WTMP_ASL)
end_asl();
else if (wtmp_file.fd >= 0) {
close(wtmp_file.fd);
wtmp_file.fd = -1;
}
+
+ if (wtmp_file.file)
+ free(wtmp_file.file);
+
+ wtmp_file.file = strdup(fname);
+ if (wtmp_file.file == NULL)
+ return 0;
+
wtmp_func.which = WTMP_FILE;
wtmp_func.end = end_file;
wtmp_func.get = get_file;
asl_set_query(q0, FACILITY, UTMPX_FACILITY, ASL_QUERY_OP_EQUAL);
asl_set_query(q1, FACILITY, LASTLOG_FACILITY, ASL_QUERY_OP_EQUAL);
- m[0] = q0;
- m[1] = q1;
+ m[0] = (asl_msg_t *)q0;
+ m[1] = (asl_msg_t *)q1;
query.count = 2;
query.msg = m;
(void) close(fd);
}
#endif /* UTMP_COMPAT */
+
+/*
+ * thread aware SPI
+ */
+utmpx_t
+_openutx(const char *name)
+{
+ struct _utmpx *U;
+
+ if ((U = calloc(1, sizeof(struct _utmpx))) == NULL)
+ return NULL;
+ memcpy(U->magic, __utx_magic__, UTMPX_MAGIC);
+ U->utmpx_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
+ if (__utmpxname(U, name) == 0) {
+ if (!U->utfile_system)
+ free(U->utfile);
+ free(U);
+ errno = EINVAL;
+ return NULL;
+ }
+ return (utmpx_t)U;
+}
+
+int
+_closeutx(utmpx_t u)
+{
+ struct _utmpx *U = (struct _utmpx *)u;
+
+ if (!U || memcmp(U->magic, __utx_magic__, UTMPX_MAGIC) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ UTMPX_LOCK(U);
+ __endutxent(U);
+ if (!U->utfile_system)
+ free(U->utfile);
+ UTMPX_UNLOCK(U);
+ free(U);
+ return 0;
+}
/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005, 2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
#ifdef UTMP_COMPAT
#define UTMP_COMPAT_UTMP0 0x01
#define LASTLOG_FACILITY "com.apple.system.lastlog"
#define UTMPX_FACILITY "com.apple.system.utmpx"
-#define UTMPX_LOCK if (__is_threaded) pthread_mutex_lock(&utmpx_mutex)
-#define UTMPX_UNLOCK if (__is_threaded) pthread_mutex_unlock(&utmpx_mutex)
+#define UTMPX_LOCK(x) if (__is_threaded) pthread_mutex_lock(&(x)->utmpx_mutex)
+#define UTMPX_UNLOCK(x) if (__is_threaded) pthread_mutex_unlock(&(x)->utmpx_mutex)
+#define UTMPX_MAGIC 8
+#define __UTX_MAGIC__ { 'u', 't', 'x', 0, 'v', 1, 0, 0 }
+
+#define TEST_UTMPX_T(x,y) { \
+ if (!(y)) \
+ LIBC_ABORT("%s: NULL utmpx_t", (x)); \
+ if (memcmp((y)->magic, __utx_magic__, UTMPX_MAGIC) != 0) \
+ LIBC_ABORT("%s: magic mismatch", (x)); \
+ }
-extern int utfile_system; /* are we using _PATH_UTMPX? */
extern int __is_threaded;
-extern pthread_mutex_t utmpx_mutex;
+
+struct _utmpx {
+ char magic[UTMPX_MAGIC];
+ struct utmpx ut;
+ pthread_mutex_t utmpx_mutex;
+ char *utfile;
+ FILE *fp;
+ unsigned int utfile_system :1; /* are we using _PATH_UTMPX? */
+ unsigned int readonly :1;
+};
+extern struct _utmpx __utx__; /* the default struct _utmpx */
+extern const char __utx_magic__[]; /* size of UTMPX_MAGIC */
#ifdef __LP64__
#define __need_struct_timeval32
};
#endif /* __LP64__ */
-void _endutxent(void);
-void _setutxent(void);
-struct utmpx *_pututxline(const struct utmpx *);
+void __endutxent(struct _utmpx *);
+struct utmpx *__getutxent(struct _utmpx *);
+void __setutxent(struct _utmpx *);
+struct utmpx *__pututxline(struct _utmpx *, const struct utmpx *);
+int __utmpxname(struct _utmpx *, const char *);
#ifdef __LP64__
void _utmpx32_64(const struct utmpx32 *, struct utmpx *);
void _utmpx64_32(const struct utmpx *, struct utmpx32 *);
-/* $NetBSD: utmpx.c,v 1.21 2003/09/06 16:42:10 wiz Exp $ */
+/* $NetBSD: utmpx.c,v 1.25 2008/04/28 20:22:59 martin Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* 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
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: utmpx.c,v 1.21 2003/09/06 16:42:10 wiz Exp $");
+__RCSID("$NetBSD: utmpx.c,v 1.25 2008/04/28 20:22:59 martin Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#ifdef LEGACY_UTMP_APIS
+#ifdef UNIFDEF_LEGACY_UTMP_APIS
#include <utmp.h>
-#endif /* LEGACY_UTMP_APIS */
+#endif /* UNIFDEF_LEGACY_UTMP_APIS */
#include <utmpx.h>
#include <utmpx-darwin.h>
#include <errno.h>
#include <vis.h>
#include <notify.h>
-static FILE *fp;
-static int readonly = 0;
-static struct utmpx ut;
-static char utfile[MAXPATHLEN] = _PATH_UTMPX;
-__private_extern__ int utfile_system = 1; /* are we using _PATH_UTMPX? */
-__private_extern__ pthread_mutex_t utmpx_mutex = PTHREAD_MUTEX_INITIALIZER;
+/* This is the default struct _utmpx shared by the POSIX APIs */
+__private_extern__
+struct _utmpx __utx__ = {
+ __UTX_MAGIC__, /* magic */
+ {}, /* ut */
+ PTHREAD_MUTEX_INITIALIZER, /* utmpx_mutex */
+ _PATH_UTMPX, /* utfile */
+ NULL, /* fp */
+ 1, /* utfile_system */
+ 0, /* readonly */
+};
-static struct utmpx *_getutxid(const struct utmpx *);
+static struct utmpx *__getutxid(struct _utmpx *, const struct utmpx *);
__private_extern__ const char _utmpx_vers[] = "utmpx-1.00";
__private_extern__ void
-_setutxent()
+__setutxent(struct _utmpx *U)
{
- (void)memset(&ut, 0, sizeof(ut));
- if (fp == NULL)
+ (void)memset(&U->ut, 0, sizeof(U->ut));
+ if (U->fp == NULL)
return;
#ifdef __LP64__
- (void)fseeko(fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
+ (void)fseeko(U->fp, (off_t)sizeof(struct utmpx32), SEEK_SET);
#else /* __LP64__ */
- (void)fseeko(fp, (off_t)sizeof(ut), SEEK_SET);
+ (void)fseeko(U->fp, (off_t)sizeof(U->ut), SEEK_SET);
#endif /* __LP64__ */
}
+void
+_setutxent(struct _utmpx *U)
+{
+
+ TEST_UTMPX_T("_setutxent", U);
+ UTMPX_LOCK(U);
+ __setutxent(U);
+ UTMPX_UNLOCK(U);
+}
+
void
setutxent()
{
- UTMPX_LOCK;
- _setutxent();
- UTMPX_UNLOCK;
+ _setutxent(&__utx__);
}
__private_extern__ void
-_endutxent()
+__endutxent(struct _utmpx *U)
{
-
- (void)memset(&ut, 0, sizeof(ut));
- if (fp != NULL) {
- (void)fclose(fp);
- fp = NULL;
- readonly = 0;
+ (void)memset(&U->ut, 0, sizeof(U->ut));
+ if (U->fp != NULL) {
+ int saveerrno = errno;
+ (void)fclose(U->fp);
+ errno = saveerrno;
+ U->fp = NULL;
+ U->readonly = 0;
}
}
+void
+_endutxent(struct _utmpx *U)
+{
+ TEST_UTMPX_T("_endutxent", U);
+ UTMPX_LOCK(U);
+ __endutxent(U);
+ UTMPX_UNLOCK(U);
+}
+
+
void
endutxent()
{
- UTMPX_LOCK;
- _endutxent();
- UTMPX_UNLOCK;
+ _endutxent(&__utx__);
}
-static struct utmpx *
-_getutxent()
+__private_extern__ struct utmpx *
+__getutxent(struct _utmpx *U)
{
+ int saveerrno;
#ifdef __LP64__
struct utmpx32 ut32;
#endif /* __LP64__ */
- if (fp == NULL) {
+ if (U->fp == NULL) {
struct stat st;
- if ((fp = fopen(utfile, "r+")) == NULL)
- if ((fp = fopen(utfile, "w+")) == NULL) {
- if ((fp = fopen(utfile, "r")) == NULL)
+ if ((U->fp = fopen(U->utfile, "r+")) == NULL)
+ if ((U->fp = fopen(U->utfile, "w+")) == NULL) {
+ if ((U->fp = fopen(U->utfile, "r")) == NULL)
goto fail;
else
- readonly = 1;
+ U->readonly = 1;
}
- fcntl(fileno(fp), F_SETFD, 1); /* set close-on-exec flag */
+ fcntl(fileno(U->fp), F_SETFD, 1); /* set close-on-exec flag */
/* get file size in order to check if new file */
- if (fstat(fileno(fp), &st) == -1)
+ if (fstat(fileno(U->fp), &st) == -1)
goto failclose;
if (st.st_size == 0) {
(void)memset(&ut32, 0, sizeof(ut32));
ut32.ut_type = SIGNATURE;
(void)memcpy(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
- if (fwrite(&ut32, sizeof(ut32), 1, fp) != 1)
+ if (fwrite(&ut32, sizeof(ut32), 1, U->fp) != 1)
#else /* __LP64__ */
- (void)memset(&ut, 0, sizeof(ut));
- ut.ut_type = SIGNATURE;
- (void)memcpy(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
- if (fwrite(&ut, sizeof(ut), 1, fp) != 1)
+ (void)memset(&U->ut, 0, sizeof(U->ut));
+ U->ut.ut_type = SIGNATURE;
+ (void)memcpy(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers));
+ if (fwrite(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
#endif /* __LP64__ */
goto failclose;
} else {
/* old file, read signature record */
#ifdef __LP64__
- if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
+ if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
#else /* __LP64__ */
- if (fread(&ut, sizeof(ut), 1, fp) != 1)
+ if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
#endif /* __LP64__ */
goto failclose;
#ifdef __LP64__
if (memcmp(ut32.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
ut32.ut_type != SIGNATURE)
#else /* __LP64__ */
- if (memcmp(ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
- ut.ut_type != SIGNATURE)
+ if (memcmp(U->ut.ut_user, _utmpx_vers, sizeof(_utmpx_vers)) != 0 ||
+ U->ut.ut_type != SIGNATURE)
#endif /* __LP64__ */
+ {
+ errno = EINVAL;
goto failclose;
+ }
}
}
#ifdef __LP64__
- if (fread(&ut32, sizeof(ut32), 1, fp) != 1)
+ if (fread(&ut32, sizeof(ut32), 1, U->fp) != 1)
#else /* __LP64__ */
- if (fread(&ut, sizeof(ut), 1, fp) != 1)
+ if (fread(&U->ut, sizeof(U->ut), 1, U->fp) != 1)
#endif /* __LP64__ */
goto fail;
#ifdef __LP64__
- _utmpx32_64(&ut32, &ut);
+ _utmpx32_64(&ut32, &U->ut);
#endif /* __LP64__ */
- return &ut;
+ return &U->ut;
failclose:
- (void)fclose(fp);
- fp = NULL;
+ saveerrno = errno;
+ (void)fclose(U->fp);
+ errno = saveerrno;
+ U->fp = NULL;
fail:
- (void)memset(&ut, 0, sizeof(ut));
+ (void)memset(&U->ut, 0, sizeof(U->ut));
return NULL;
}
struct utmpx *
-getutxent()
+_getutxent(struct _utmpx *U)
{
struct utmpx *ret;
- UTMPX_LOCK;
- ret = _getutxent();
- UTMPX_UNLOCK;
+
+ TEST_UTMPX_T("_getutxent", U);
+ UTMPX_LOCK(U);
+ ret = __getutxent(U);
+ UTMPX_UNLOCK(U);
return ret;
}
+
struct utmpx *
-getutxid(const struct utmpx *utx)
+getutxent()
+{
+ return _getutxent(&__utx__);
+}
+
+
+struct utmpx *
+_getutxid(struct _utmpx *U, const struct utmpx *utx)
{
struct utmpx temp;
const struct utmpx *ux;
struct utmpx *ret;
- _DIAGASSERT(utx != NULL);
-
if (utx->ut_type == EMPTY)
return NULL;
- UTMPX_LOCK;
+ TEST_UTMPX_T("_getutxid", U);
+ UTMPX_LOCK(U);
/* make a copy as needed, and auto-fill if requested */
ux = _utmpx_working_copy(utx, &temp, 1);
if (!ux) {
- UTMPX_UNLOCK;
+ UTMPX_UNLOCK(U);
return NULL;
}
- ret = _getutxid(ux);
- UTMPX_UNLOCK;
+ ret = __getutxid(U, ux);
+ UTMPX_UNLOCK(U);
return ret;
}
+struct utmpx *
+getutxid(const struct utmpx *utx)
+{
+ return _getutxid(&__utx__, utx);
+}
+
+
static struct utmpx *
-_getutxid(const struct utmpx *utx)
+__getutxid(struct _utmpx *U, const struct utmpx *utx)
{
do {
- if (ut.ut_type == EMPTY)
+ if (U->ut.ut_type == EMPTY)
continue;
switch (utx->ut_type) {
case EMPTY:
case BOOT_TIME:
case OLD_TIME:
case NEW_TIME:
- if (ut.ut_type == utx->ut_type)
- return &ut;
+ if (U->ut.ut_type == utx->ut_type)
+ return &U->ut;
break;
case INIT_PROCESS:
case LOGIN_PROCESS:
case USER_PROCESS:
case DEAD_PROCESS:
- switch (ut.ut_type) {
+ switch (U->ut.ut_type) {
case INIT_PROCESS:
case LOGIN_PROCESS:
case USER_PROCESS:
case DEAD_PROCESS:
- if (memcmp(ut.ut_id, utx->ut_id,
- sizeof(ut.ut_id)) == 0)
- return &ut;
+ if (memcmp(U->ut.ut_id, utx->ut_id,
+ sizeof(U->ut.ut_id)) == 0)
+ return &U->ut;
break;
default:
break;
default:
return NULL;
}
- } while (_getutxent() != NULL);
+ } while (__getutxent(U) != NULL);
return NULL;
}
-struct utmpx *
-getutxline(const struct utmpx *utx)
+static struct utmpx *
+__getutxline(struct _utmpx *U, const struct utmpx *utx)
{
-
- _DIAGASSERT(utx != NULL);
-
- UTMPX_LOCK;
do {
- switch (ut.ut_type) {
+ switch (U->ut.ut_type) {
case EMPTY:
break;
case LOGIN_PROCESS:
case USER_PROCESS:
- if (strncmp(ut.ut_line, utx->ut_line,
- sizeof(ut.ut_line)) == 0) {
- UTMPX_UNLOCK;
- return &ut;
- }
+ if (strncmp(U->ut.ut_line, utx->ut_line,
+ sizeof(U->ut.ut_line)) == 0)
+ return &U->ut;
break;
default:
break;
}
- } while (_getutxent() != NULL);
- UTMPX_UNLOCK;
+ } while (__getutxent(U) != NULL);
return NULL;
}
struct utmpx *
-pututxline(const struct utmpx *utx)
+_getutxline(struct _utmpx *U, const struct utmpx *utx)
{
- struct utmpx *ux;
+ struct utmpx *ret;
+
+ TEST_UTMPX_T("_getutxline", U);
+ UTMPX_LOCK(U);
+ ret = __getutxline(U, utx);
+ UTMPX_UNLOCK(U);
+ return ret;
+}
- _DIAGASSERT(utx != NULL);
+
+struct utmpx *
+getutxline(const struct utmpx *utx)
+{
+ return _getutxline(&__utx__, utx);
+}
+
+
+struct utmpx *
+_pututxline(struct _utmpx *U, const struct utmpx *utx)
+{
+ struct utmpx *ux;
if (utx == NULL) {
errno = EINVAL;
return NULL;
}
- UTMPX_LOCK;
- if ((ux = _pututxline(utx)) != NULL && utfile_system) {
+ TEST_UTMPX_T("_pututxline", U);
+ UTMPX_LOCK(U);
+ if ((ux = __pututxline(&__utx__, utx)) != NULL && __utx__.utfile_system) {
_utmpx_asl(ux); /* the equivalent of wtmpx and lastlogx */
#ifdef UTMP_COMPAT
_write_utmp_compat(ux);
#endif /* UTMP_COMPAT */
}
- UTMPX_UNLOCK;
+ UTMPX_UNLOCK(U);
return ux;
}
+
+struct utmpx *
+pututxline(const struct utmpx *utx)
+{
+ return _pututxline(&__utx__, utx);
+}
+
__private_extern__ struct utmpx *
-_pututxline(const struct utmpx *utx)
+__pututxline(struct _utmpx *U, const struct utmpx *utx)
{
struct utmpx temp, *u = NULL, *x;
const struct utmpx *ux;
#define gotlock (fl.l_start >= 0)
fl.l_start = -1; /* also means we haven't locked */
- if (utfile_system)
- if ((fp != NULL && readonly) || (fp == NULL && geteuid() != 0)) {
+ if (U->utfile_system)
+ if ((U->fp != NULL && U->readonly) || (U->fp == NULL && geteuid() != 0)) {
errno = EPERM;
return NULL;
}
- if (fp == NULL) {
- (void)_getutxent();
- if (fp == NULL || readonly) {
+ if (U->fp == NULL) {
+ (void)__getutxent(U);
+ if (U->fp == NULL || U->readonly) {
errno = EPERM;
return NULL;
}
if (!ux)
return NULL;
- if ((x = _getutxid(ux)) == NULL) {
- _setutxent();
- if ((x = _getutxid(ux)) == NULL) {
+ if ((x = __getutxid(U, ux)) == NULL) {
+ __setutxent(U);
+ if ((x = __getutxid(U, ux)) == NULL) {
/*
* utx->ut_type has any original mask bits, while
* ux->ut_type has those mask bits removed. If we
* Replace lockf() with fcntl() and a fixed start
* value. We should already be at EOF.
*/
- if ((fl.l_start = lseek(fileno(fp), 0, SEEK_CUR)) < 0)
+ if ((fl.l_start = lseek(fileno(U->fp), 0, SEEK_CUR)) < 0)
return NULL;
fl.l_len = 0;
fl.l_whence = SEEK_SET;
fl.l_type = F_WRLCK;
- if (fcntl(fileno(fp), F_SETLKW, &fl) == -1)
+ if (fcntl(fileno(U->fp), F_SETLKW, &fl) == -1)
return NULL;
- if (fseeko(fp, (off_t)0, SEEK_END) == -1)
+ if (fseeko(U->fp, (off_t)0, SEEK_END) == -1)
goto fail;
}
}
}
/* we are not appending */
#ifdef __LP64__
- if (fseeko(fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
+ if (fseeko(U->fp, -(off_t)sizeof(ut32), SEEK_CUR) == -1)
#else /* __LP64__ */
- if (fseeko(fp, -(off_t)sizeof(ut), SEEK_CUR) == -1)
+ if (fseeko(U->fp, -(off_t)sizeof(U->ut), SEEK_CUR) == -1)
#endif /* __LP64__ */
return NULL;
}
#ifdef __LP64__
_utmpx64_32(ux, &ut32);
- if (fwrite(&ut32, sizeof (ut32), 1, fp) != 1)
+ if (fwrite(&ut32, sizeof (ut32), 1, U->fp) != 1)
#else /* __LP64__ */
- if (fwrite(ux, sizeof (*ux), 1, fp) != 1)
+ if (fwrite(ux, sizeof (*ux), 1, U->fp) != 1)
#endif /* __LP64__ */
goto fail;
- if (fflush(fp) == -1)
+ if (fflush(U->fp) == -1)
goto fail;
- u = memcpy(&ut, ux, sizeof(ut));
+ u = memcpy(&U->ut, ux, sizeof(U->ut));
notify_post(UTMPX_CHANGE_NOTIFICATION);
fail:
if (gotlock) {
int save = errno;
fl.l_type = F_UNLCK;
- if (fcntl(fileno(fp), F_SETLK, &fl) == -1)
+ if (fcntl(fileno(U->fp), F_SETLK, &fl) == -1)
return NULL;
errno = save;
}
/*
* The following are extensions and not part of the X/Open spec.
*/
-int
-utmpxname(const char *fname)
+__private_extern__ int
+__utmpxname(struct _utmpx *U, const char *fname)
{
size_t len;
- UTMPX_LOCK;
if (fname == NULL) {
- strcpy(utfile, _PATH_UTMPX);
- utfile_system = 1;
- _endutxent();
- UTMPX_UNLOCK;
+ if(!U->utfile_system)
+ free(U->utfile);
+ U->utfile = _PATH_UTMPX;
+ U->utfile_system = 1;
+ __endutxent(U);
return 1;
}
len = strlen(fname);
- if (len >= sizeof(utfile)) {
- UTMPX_UNLOCK;
+ if (len >= MAXPATHLEN)
return 0;
- }
/* must end in x! */
- if (fname[len - 1] != 'x') {
- UTMPX_UNLOCK;
+ if (fname[len - 1] != 'x')
+ return 0;
+
+ if (U->utfile_system)
+ U->utfile = NULL;
+ U->utfile_system = 0;
+ if ((U->utfile = reallocf(U->utfile, len + 1)) == NULL)
return 0;
- }
- (void)strlcpy(utfile, fname, sizeof(utfile));
- _endutxent();
- utfile_system = 0;
- UTMPX_UNLOCK;
+ (void)strcpy(U->utfile, fname);
+ __endutxent(U);
return 1;
}
-#ifdef LEGACY_UTMP_APIS
+int
+_utmpxname(struct _utmpx *U, const char *fname)
+{
+ int ret;
+
+ TEST_UTMPX_T("_utmpxname", U);
+ UTMPX_LOCK(U);
+ ret = __utmpxname(U, fname);
+ UTMPX_UNLOCK(U);
+ return ret;
+}
+
+int
+utmpxname(const char *fname)
+{
+ return _utmpxname(&__utx__, fname);
+}
+
+#ifdef UNIFDEF_LEGACY_UTMP_APIS
void
getutmp(const struct utmpx *ux, struct utmp *u)
{
ux->ut_pid = getpid();
ux->ut_type = USER_PROCESS;
}
-#endif /* LEGACY_UTMP_APIS */
+#endif /* UNIFDEF_LEGACY_UTMP_APIS */
-.\" $NetBSD: utmpx.5,v 1.2 2003/04/16 13:35:24 wiz Exp $
+.\" $NetBSD: utmpx.5,v 1.7 2008/04/30 13:10:57 martin Exp $
.\"
.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" 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
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd Dec 26, 2005
+.Dd January 31, 2007
.Dt UTMPX 5
.Os
.Sh NAME
.Sh SYNOPSIS
.In utmpx.h
.Sh DESCRIPTION
+In contrast to
+.Pa utmp
+and
+.Pa wtmp ,
+the extended databases in
+.Pa utmpx
+and
+.Pa wtmpx
+reserve more space for logging hostnames, and also
+information on a process' ID, termination signal and exit status.
+.Pp
The
.Aq Pa utmpx.h
header defines the structures and functions for logging user.
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.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.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Thread-aware utmpx SPI
+ */
+#ifndef _UTMPX_THREAD_H_
+#define _UTMPX_THREAD_H_
+
+#include <utmpx.h>
+
+struct _utmpx; /* forward reference */
+typedef struct _utmpx *utmpx_t;
+
+__BEGIN_DECLS
+int _closeutx(utmpx_t);
+void _endutxent(utmpx_t);
+struct utmpx *_getutxent(utmpx_t);
+struct utmpx *_getutxid(utmpx_t, const struct utmpx *);
+struct utmpx *_getutxline(utmpx_t, const struct utmpx *);
+utmpx_t _openutx(const char *);
+struct utmpx *_pututxline(utmpx_t, const struct utmpx *);
+void _setutxent(utmpx_t);
+int _utmpxname(utmpx_t, const char *);
+__END_DECLS
+
+#endif /* !_UTMPX_THREAD_H_ */
* 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.
static char sccsid[] = "@(#)vis.c 8.1 (Berkeley) 7/19/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/vis.c,v 1.13 2003/10/30 12:41:50 phk Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/vis.c,v 1.14 2007/01/09 00:27:56 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)wait.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/wait.c,v 1.6 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/wait.c,v 1.7 2007/01/09 00:27:56 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
* 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.
static char sccsid[] = "@(#)waitpid.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/waitpid.c,v 1.6 2002/02/01 00:57:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/gen/waitpid.c,v 1.7 2007/01/09 00:27:56 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
/* Similar to popen, but captures stderr for you. Doesn't interoperate
with pclose. Call wait4 on your own */
-pid_t popen_oe(char *cmd, FILE **out, FILE **err) {
+static pid_t popen_oe(char *cmd, FILE **out, FILE **err) {
int out_pipe[2], err_pipe[2];
char *argv[4];
pid_t pid;
return pid;
}
-void re_init(void) {
+static void re_init(void) {
int rc = regcomp(&re_cmd, "(^|[^\\])(`|\\$\\([^(])", REG_EXTENDED|REG_NOSUB);
/* XXX I'm not sure the { } stuff is correct,
it may be overly restrictave */
if(!init)
add_profil(m->sbuf + sizeof(gmonhdr_t),
m->ssiz - sizeof(gmonhdr_t),
- (long)m->lowpc, m->scale);
+ (uintptr_t)m->lowpc, m->scale);
}
}
mon_t *m;
uint32_t image_count;
intptr_t image_header;
- char *image_name;
+ const char *image_name;
moncontrol(0);
m = mon;
((uintptr_t)frompcindex - (uintptr_t)m->lowpc);
}
frompcindex =
- &m->froms[((long)frompcindex) / (HASHFRACTION * sizeof(*m->froms))];
+ &m->froms[((uintptr_t)frompcindex) / (HASHFRACTION * sizeof(*m->froms))];
toindex = *frompcindex;
if(toindex == 0){
/*
.PATH: ${.CURDIR}/i386/gen
+
MDSRCS+= _ctx_start.S \
_setcontext.S \
getcontext.S \
mcount.s \
setcontext.c \
setjmperr.c \
- swapcontext.c
+ swapcontext.c \
+ cpu_number.s
.for _src in makecontext.c setcontext.c swapcontext.c
CFLAGS-${_src} += -fomit-frame-pointer
# -pg and -fomit-frame-pointer don't work together, so just use -g
${_src:R}.po: ${_src} _STANDARD_DEBUG
.endfor
+
+CFLAGS += -I${.CURDIR}/i386/gen
+
+DYLDSRCS += icacheinval.s \
+ cpu_number.s
--- /dev/null
+/*
+ * Copyright (c) 2008 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * These platfunc routines provide fast access to the logical cpu number
+ * of the calling processor assuming no pre-emption occurs. This number
+ * is encoded in the bottom 12-bits of the limit field of the IDTR (the
+ * Interrupt Descriptor Table Register). The SIDT instruction is used in
+ * userspace to read this register and thus to gain access to the cpu number.
+ * The IDTR is loaded by the kernel for each processor at startup - see
+ * osfmk/i386/mp_desc.c.
+ */
+
+/* return logical cpu number in %eax */
+
+ .align 4
+ .private_extern _cpu_number
+_cpu_number:
+ push %ebp
+ mov %esp,%ebp
+ sub $8, %esp // space to read IDTR
+
+ sidt (%esp) // store limit:base on stack
+ movw (%esp), %ax // get limit
+ and $0xfff, %eax // mask off lower 12 bits to return
+
+ mov %ebp,%esp
+ pop %ebp
+ ret
/*
- * Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/* void sys_icache_invalidate(addr_t start, int length) */
-.globl _sys_icache_invalidate
+ .globl _sys_icache_invalidate
_sys_icache_invalidate:
- movl $(_COMM_PAGE_FLUSH_ICACHE), %eax
- jmpl *%eax
+ // This is a NOP on intel processors, since the intent of the API
+ // is to make data executable, and Intel L1Is are coherent with L1D.
+ ret
/* void sys_dcache_flush(addr_t start, int length) */
-.globl _sys_dcache_flush
+ .globl _sys_dcache_flush
_sys_dcache_flush:
- movl $(_COMM_PAGE_FLUSH_DCACHE), %eax
- jmpl *%eax
+ movl 8(%esp),%ecx // get length
+ movl 4(%esp),%edx // get ptr
+ testl %ecx,%ecx // length 0?
+ jz 2f // yes
+ mfence // ensure previous stores make it to memory
+ clflush -1(%edx,%ecx) // make sure last line is flushed
+1:
+ clflush (%edx) // flush a line
+ addl $64,%edx
+ subl $64,%ecx
+ ja 1b
+ mfence // make sure memory is updated before we return
+2:
+ ret
MDSRCS += \
init_cpu_capabilities.c \
get_cpu_capabilities.s \
+ preempt.s \
pthread_mutex_lock.s \
pthread_set_self.s \
pthread_self.s \
pthread_getspecific.s \
start_wqthread.s \
thread_start.s
+
+DYLDSRCS += \
+ preempt.s \
+ pthread_set_self.s \
+ pthread_self.s \
+ pthread_getspecific.s
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <mach/i386/syscall_sw.h>
+
+/* Subroutine to make a preempt syscall. Called when we notice %ebx is
+ * nonzero after returning from a PFZ subroutine.
+ * When we enter kernel:
+ * %edx = return address
+ * %ecx = stack ptr
+ * Destroys %eax, %ecx, and %edx.
+ */
+ .align 4
+ .private_extern _preempt
+_preempt:
+ popl %edx // get return address
+ movl %esp,%ecx // save stack ptr here
+ movl $(-58),%eax /* 58 = pfz_exit */
+ xorl %ebx,%ebx // clear "preemption pending" flag
+ sysenter
+
+
+/* Subroutine to back off if we cannot get the spinlock. Called
+ * after a few attempts inline in the PFZ subroutines. This code is
+ * not in the PFZ.
+ * %edi = ptr to queue head structure
+ * %ebx = preemption flag (nonzero if preemption pending)
+ * Destroys %eax.
+ */
+
+ .align 4
+ .private_extern _backoff
+_backoff:
+ testl %ebx,%ebx // does kernel want to preempt us?
+ jz 1f // no
+ xorl %ebx,%ebx // yes, clear flag
+ pushl %edx // preserve regs used by preempt syscall
+ pushl %ecx
+ call _preempt
+ popl %ecx
+ popl %edx
+1:
+ pause // SMT-friendly backoff
+ cmpl $0,8(%edi) // sniff the lockword
+ jnz 1b // loop if still taken
+ ret // lockword is free, so reenter PFZ
.globl _pthread_getspecific
_pthread_getspecific:
movl 4(%esp),%eax
- movl %gs:_PTHREAD_TSD_OFFSET(,%eax,4),%eax
+ movl %gs:(,%eax,4),%eax
ret
.align 2
.globl __commpage_pthread_mutex_lock
__commpage_pthread_mutex_lock:
- movl $(_COMM_PAGE_MUTEX_LOCK), %eax
- jmpl *%eax
+ pushl %ebp // set up frame for backtrace
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ xorl %ebx,%ebx // clear "preemption pending" flag
+ movl 20(%esp),%edi // %edi == ptr to LVAL/UVAL structure
+ lea 20(%esp),%esi // %esi == ptr to argument list
+ movl _COMM_PAGE_SPIN_COUNT, %edx
+ movl 16(%esi),%ecx // get mask (ie, PTHRW_EBIT etc)
+1:
+ testl 0(%edi),%ecx // is mutex available?
+ jz 2f // yes, it is available
+ pause
+ decl %edx // decrement max spin count
+ jnz 1b // keep spinning
+2:
+ movl $(_COMM_PAGE_PFZ_MUTEX_LOCK), %ecx
+ call *%ecx
+ testl %ebx,%ebx // pending preemption?
+ jz 3f
+ pushl %eax // save return value across sysenter
+ call _preempt
+ popl %eax
+3:
+ popl %ebx
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
.align 2, 0x90
.globl _pthread_self
_pthread_self:
- movl %gs:_PTHREAD_TSD_OFFSET,%eax
+ movl %gs:0,%eax
ret
#
#
.PATH: ${.CURDIR}/i386/string
-MDSRCS += bcopy.s \
- bzero.s \
+MDSRCS += \
+ bcopy.c \
+ bcopy_scalar.s \
+ bcopy_sse2.s \
+ bcopy_sse3x.s \
+ bcopy_sse42.s \
+ bzero.c \
+ bzero_scalar.s \
+ bzero_sse2.s \
+ bzero_sse42.s \
+ __bzero.s \
+ longcopy_sse3x.s \
+ memset_pattern_sse2.s \
ffs.s \
- memcpy.s \
- memmove.s \
+ memcpy.c \
+ memmove.c \
strlcat.s \
strlcpy.s \
strlen.s \
memset.s
SUPPRESSSRCS += bcmp.c
+
+DYLDSRCS += \
+ __bzero.s \
+ bcopy_scalar.s \
+ bzero_scalar.s \
+ ffs.s \
+ memcmp.s \
+ memset_pattern_sse2.s \
+ strcmp.s \
+ strlen.s
--- /dev/null
+ .globl ___bzero
+___bzero:
+ jmp _bzero
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bcopy, sse42);
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bcopy, sse3x);
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bcopy, sse2);
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bcopy, scalar);
+
+static const platfunc_descriptor *bcopy_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(bcopy, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(bcopy, sse3x),
+ PLATFUNC_DESCRIPTOR_REFERENCE(bcopy, sse2),
+ PLATFUNC_DESCRIPTOR_REFERENCE(bcopy, scalar),
+ 0
+};
+
+void *bcopy_chooser() __asm__("_bcopy");
+void *bcopy_chooser() {
+ __asm__(".desc _bcopy, 0x100");
+ return find_platform_function((const platfunc_descriptor **) bcopy_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 1999-2003 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@
- */
-
-/*
- * Call the comm page routines
- */
-
-#include <machine/cpu_capabilities.h>
-
-#include <architecture/i386/asm_help.h>
-
- TEXT
- ALIGN
-
-#if defined(MEMCOPY)
-LEAF(_memcpy,0)
- movl $(_COMM_PAGE_MEMCPY), %eax
- jmpl *%eax
-#elif defined(MEMMOVE)
-LEAF(_memmove,0)
- movl $(_COMM_PAGE_MEMMOVE), %eax
- jmpl *%eax
-#else
-LEAF(_bcopy,0)
- movl $(_COMM_PAGE_BCOPY), %eax
- jmpl *%eax
-#endif
--- /dev/null
+/*
+ * Copyright (c) 2003-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from locore.s.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+#include <machine/asm.h>
+
+ /*
+ * (ov)bcopy (src,dst,cnt)
+ * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
+ */
+
+PLATFUNC_FUNCTION_START_GENERIC(bcopy, scalar, 32, 5)
+ pushl %ebp /* set up a frame for backtraces */
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ movl 8(%ebp),%esi
+ movl 12(%ebp),%edi
+ jmp 1f
+
+PLATFUNC_FUNCTION_START_GENERIC(memcpy, scalar, 32, 0)
+PLATFUNC_FUNCTION_START_GENERIC(memmove, scalar, 32, 0)
+ pushl %ebp /* set up a frame for backtraces */
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ movl 8(%ebp),%edi
+ movl 12(%ebp),%esi
+ movl %edi,%eax
+1:
+ movl 16(%ebp),%ecx
+ movl %edi,%edx
+ subl %esi,%edx
+ cmpl %ecx,%edx /* overlapping? */
+ jb 2f
+ cld /* nope, copy forwards. */
+ movl %ecx,%edx
+ shrl $2,%ecx /* copy by words */
+ rep
+ movsl
+ movl %edx,%ecx
+ andl $3,%ecx /* any bytes left? */
+ rep
+ movsb
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+2:
+ addl %ecx,%edi /* copy backwards. */
+ addl %ecx,%esi
+ std
+ movl %ecx,%edx
+ andl $3,%ecx /* any fractional bytes? */
+ decl %edi
+ decl %esi
+ rep
+ movsb
+ movl %edx,%ecx /* copy remainder by words */
+ shrl $2,%ecx
+ subl $3,%esi
+ subl $3,%edi
+ rep
+ movsl
+ popl %edi
+ popl %esi
+ popl %ebp
+ cld
+ ret
+
+PLATFUNC_DESCRIPTOR(bcopy,scalar,0,0)
+PLATFUNC_DESCRIPTOR(memcpy,scalar,0,0)
+PLATFUNC_DESCRIPTOR(memmove,scalar,0,0)
--- /dev/null
+/*
+ * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * The bcopy/memcpy loops, tuned for Pentium-M class processors with SSE2
+ * and 64-byte cache lines, such as Core and Core 2.
+ *
+ * The following #defines are tightly coupled to the u-architecture:
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+#define kVeryLong (500*1024) // large enough for non-temporal stores (must be >= 8192)
+#define kBigChunk (256*1024) // outer loop chunk size for kVeryLong sized operands
+#define kFastUCode (16*1024) // cutoff for microcode fastpath for "rep/movsl"
+
+
+// void bcopy(const void *src, void *dst, size_t len);
+
+PLATFUNC_FUNCTION_START(bcopy, sse2, 32, 5)
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ movl 8(%ebp),%esi // get source ptr
+ movl 12(%ebp),%edi // get dest ptr
+ jmp Ljoin
+
+//
+// void *memcpy(void *dst, const void *src, size_t len);
+// void *memmove(void *dst, const void *src, size_t len);
+//
+
+PLATFUNC_FUNCTION_START(memcpy, sse2, 32, 0) // void *memcpy(void *dst, const void *src, size_t len)
+PLATFUNC_FUNCTION_START(memmove, sse2, 32, 0) // void *memmove(void *dst, const void *src, size_t len)
+Lmemcpy_sse2:
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ movl 8(%ebp),%edi // get dest ptr
+ movl 12(%ebp),%esi // get source ptr
+
+Ljoin: // here from bcopy() with esi and edi loaded
+ movl 16(%ebp),%ecx // get length
+ movl %edi,%edx
+ subl %esi,%edx // (dest - source)
+ cmpl %ecx,%edx // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+Lrejoin: // here from very-long-operand copies
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ ja LNotShort // yes
+
+// Handle short forward copies. As the most common case, this is the fall-through path.
+// ecx = length (<= kShort)
+// esi = source ptr
+// edi = dest ptr
+
+Lshort:
+ movl %ecx,%edx // copy length
+ shrl $2,%ecx // get #doublewords
+ jz LLeftovers
+2: // loop copying doublewords
+ movl (%esi),%eax
+ addl $4,%esi
+ movl %eax,(%edi)
+ addl $4,%edi
+ dec %ecx
+ jnz 2b
+LLeftovers: // handle leftover bytes (0..3) in last word
+ andl $3,%edx // any leftover bytes?
+ jz 5f
+4: // loop copying bytes
+ movb (%esi),%al
+ inc %esi
+movb %al,(%edi)
+ inc %edi
+ dec %edx
+ jnz 4b
+5:
+ movl 8(%ebp),%eax // get return value (dst ptr) for memcpy/memmove
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+
+
+LReverseIsland: // keep the "jb" above a short branch...
+ jmp LReverse // ...because reverse moves are uncommon
+
+
+// Handle forward moves that are long enough to justify use of SSE3.
+// First, 16-byte align the destination.
+// ecx = length (> kShort)
+// esi = source ptr
+// edi = dest ptr
+
+LNotShort:
+ cmpl $(kVeryLong),%ecx // long enough to justify heavyweight loops?
+ movl %edi,%edx // copy destination
+ jae LVeryLong // use very-long-operand path
+ negl %edx
+ andl $15,%edx // get #bytes to align destination
+ jz LDestAligned // already aligned
+ subl %edx,%ecx // decrement length
+1: // loop copying 1..15 bytes
+ movb (%esi),%al
+ inc %esi
+ movb %al,(%edi)
+ inc %edi
+ dec %edx
+ jnz 1b
+
+// Destination is now aligned. Prepare for forward loops over 64-byte chunks.
+// Since kShort>=80 and we've moved at most 15 bytes already, there is at least one chunk.
+
+LDestAligned:
+ movl %ecx,%edx // copy length
+ movl %ecx,%eax // twice
+ andl $63,%ecx // get remaining bytes for Lshort
+ andl $-64,%edx // get number of bytes we will copy in inner loop
+ addl %edx,%esi // point to 1st byte not copied
+ addl %edx,%edi
+ negl %edx // now generate offset to 1st byte to be copied
+ testl $15,%esi // is source aligned too?
+ jnz LUnalignedLoop // no
+
+ cmpl $(kFastUCode),%eax // long enough for the fastpath in microcode?
+ jb LAlignedLoop // no, use SSE
+ cld // we'll move forward
+ movl %eax,%ecx // copy length again
+ shrl $2,%ecx // compute #words to move
+ addl %edx,%esi // restore ptrs to 1st byte of source and dest
+ addl %edx,%edi
+ rep // the u-code will optimize this
+ movsl
+ movl %eax,%edx // original length
+ jmp LLeftovers // handle 0..3 leftover bytes
+
+
+// Forward aligned loop for medium length operands (kShort < n < kVeryLong).
+
+ .align 4,0x90 // 16-byte align inner loops
+LAlignedLoop: // loop over 64-byte chunks
+ movdqa (%esi,%edx),%xmm0
+ movdqa 16(%esi,%edx),%xmm1
+ movdqa 32(%esi,%edx),%xmm2
+ movdqa 48(%esi,%edx),%xmm3
+
+ movdqa %xmm0,(%edi,%edx)
+ movdqa %xmm1,16(%edi,%edx)
+ movdqa %xmm2,32(%edi,%edx)
+ movdqa %xmm3,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz LAlignedLoop
+
+ jmp Lshort // copy remaining 0..15 bytes and done
+
+
+// Forward unaligned loop for medium length operands (kShort < n < kVeryLong).
+// Note that LDDQU==MOVDQU on these machines, ie we don't care when we cross
+// source cache lines.
+
+ .align 4,0x90 // 16-byte align inner loops
+LUnalignedLoop: // loop over 64-byte chunks
+ movdqu (%esi,%edx),%xmm0 // the loads are unaligned
+ movdqu 16(%esi,%edx),%xmm1
+ movdqu 32(%esi,%edx),%xmm2
+ movdqu 48(%esi,%edx),%xmm3
+
+ movdqa %xmm0,(%edi,%edx) // we can use aligned stores
+ movdqa %xmm1,16(%edi,%edx)
+ movdqa %xmm2,32(%edi,%edx)
+ movdqa %xmm3,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz LUnalignedLoop
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Very long forward moves. These are at least several pages, so we loop over big
+// chunks of memory (kBigChunk in size.) We first prefetch the chunk, and then copy
+// it using non-temporal stores. Hopefully all the reads occur in the prefetch loop,
+// so the copy loop reads from L2 and writes directly to memory (with write combining.)
+// This minimizes bus turnaround and maintains good DRAM page locality.
+// Note that for this scheme to work, kVeryLong must be a large fraction of L2 cache
+// size. Otherwise, it is counter-productive to bypass L2 on the stores.
+// ecx = length (>= kVeryLong bytes)
+// edi = dest (aligned)
+// esi = source
+
+LVeryLong:
+ pushl %ebx // we'll need to use this
+ movl %edi,%ebx // copy dest ptr
+ negl %ebx
+ andl $63,%ebx // get #bytes to cache line align destination
+ jz LBigChunkLoop // already aligned
+
+// Cache line align destination, so temporal stores in copy loops work right.
+
+ pushl %ecx // save total length remaining
+ pushl %ebx // arg3 - #bytes to align destination (1..63)
+ pushl %esi // arg2 - source
+ pushl %edi // arg1 - dest
+ call Lmemcpy_sse2 // align the destination
+ movl 12(%esp),%ecx // recover total length
+ addl $16,%esp
+ addl %ebx,%esi // adjust ptrs and lengths past copy
+ addl %ebx,%edi
+ subl %ebx,%ecx
+
+// Loop over big chunks.
+// ecx = length remaining (>= 4096)
+// edi = dest (64-byte aligned)
+// esi = source (may be unaligned)
+
+LBigChunkLoop:
+ movl $(kBigChunk),%edx // assume we can do a full chunk
+ cmpl %edx,%ecx // do we have a full chunk left to do?
+ cmovbl %ecx,%edx // if not, only move what we have left
+ andl $-4096,%edx // we work in page multiples
+ xor %eax,%eax // initialize chunk offset
+ jmp LTouchLoop
+
+// Because the source may be unaligned, we use byte loads to touch.
+// ecx = length remaining (including this chunk)
+// edi = ptr to start of dest chunk
+// esi = ptr to start of source chunk
+// edx = chunk length (multiples of pages)
+// ebx = scratch reg used to read a byte of each cache line
+// eax = chunk offset
+
+ .align 4,0x90 // 16-byte align inner loops
+LTouchLoop:
+ movzb (%esi,%eax),%ebx // touch line 0, 2, 4, or 6 of page
+ movzb 1*64(%esi,%eax),%ebx // touch line 1, 3, 5, or 7
+ movzb 8*64(%esi,%eax),%ebx // touch line 8, 10, 12, or 14
+ movzb 9*64(%esi,%eax),%ebx // etc
+
+ movzb 16*64(%esi,%eax),%ebx
+ movzb 17*64(%esi,%eax),%ebx
+ movzb 24*64(%esi,%eax),%ebx
+ movzb 25*64(%esi,%eax),%ebx
+
+ movzb 32*64(%esi,%eax),%ebx
+ movzb 33*64(%esi,%eax),%ebx
+ movzb 40*64(%esi,%eax),%ebx
+ movzb 41*64(%esi,%eax),%ebx
+
+ movzb 48*64(%esi,%eax),%ebx
+ movzb 49*64(%esi,%eax),%ebx
+ movzb 56*64(%esi,%eax),%ebx
+ movzb 57*64(%esi,%eax),%ebx
+
+ subl $-128,%eax // next slice of page (adding 128 w 8-bit immediate)
+ testl $512,%eax // done with this page?
+ jz LTouchLoop // no, next of four slices
+ addl $(4096-512),%eax // move on to next page
+ cmpl %eax,%edx // done with this chunk?
+ jnz LTouchLoop // no, do next page
+
+// The chunk has been pre-fetched, now copy it using non-temporal stores.
+// There are two copy loops, depending on whether the source is 16-byte aligned
+// or not.
+
+ addl %edx,%esi // increment ptrs by chunk length
+ addl %edx,%edi
+ subl %edx,%ecx // adjust remaining length
+ negl %edx // prepare loop index (counts up to 0)
+ testl $15,%esi // is source 16-byte aligned?
+ jnz LVeryLongUnaligned // source is not aligned
+ jmp LVeryLongAligned
+
+ .align 4,0x90 // 16-byte align inner loops
+LVeryLongAligned: // aligned loop over 128-bytes
+ movdqa (%esi,%edx),%xmm0
+ movdqa 16(%esi,%edx),%xmm1
+ movdqa 32(%esi,%edx),%xmm2
+ movdqa 48(%esi,%edx),%xmm3
+ movdqa 64(%esi,%edx),%xmm4
+ movdqa 80(%esi,%edx),%xmm5
+ movdqa 96(%esi,%edx),%xmm6
+ movdqa 112(%esi,%edx),%xmm7
+
+ movntdq %xmm0,(%edi,%edx)
+ movntdq %xmm1,16(%edi,%edx)
+ movntdq %xmm2,32(%edi,%edx)
+ movntdq %xmm3,48(%edi,%edx)
+ movntdq %xmm4,64(%edi,%edx)
+ movntdq %xmm5,80(%edi,%edx)
+ movntdq %xmm6,96(%edi,%edx)
+ movntdq %xmm7,112(%edi,%edx)
+
+ subl $-128,%edx // add 128 with an 8-bit immediate
+ jnz LVeryLongAligned
+ jmp LVeryLongChunkEnd
+
+ .align 4,0x90 // 16-byte align inner loops
+LVeryLongUnaligned: // unaligned loop over 128-bytes
+ movdqu (%esi,%edx),%xmm0
+ movdqu 16(%esi,%edx),%xmm1
+ movdqu 32(%esi,%edx),%xmm2
+ movdqu 48(%esi,%edx),%xmm3
+ movdqu 64(%esi,%edx),%xmm4
+ movdqu 80(%esi,%edx),%xmm5
+ movdqu 96(%esi,%edx),%xmm6
+ movdqu 112(%esi,%edx),%xmm7
+
+ movntdq %xmm0,(%edi,%edx)
+ movntdq %xmm1,16(%edi,%edx)
+ movntdq %xmm2,32(%edi,%edx)
+ movntdq %xmm3,48(%edi,%edx)
+ movntdq %xmm4,64(%edi,%edx)
+ movntdq %xmm5,80(%edi,%edx)
+ movntdq %xmm6,96(%edi,%edx)
+ movntdq %xmm7,112(%edi,%edx)
+
+ subl $-128,%edx // add 128 with an 8-bit immediate
+ jnz LVeryLongUnaligned
+
+LVeryLongChunkEnd:
+ cmpl $4096,%ecx // at least another page to go?
+ jae LBigChunkLoop // yes
+
+ sfence // required by non-temporal stores
+ popl %ebx
+ jmp Lrejoin // handle remaining (0..4095) bytes
+
+
+// Reverse moves.
+// ecx = length
+// esi = source ptr
+// edi = dest ptr
+
+LReverse:
+ addl %ecx,%esi // point to end of strings
+ addl %ecx,%edi
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ ja LReverseNotShort // yes
+
+// Handle reverse short copies.
+// ecx = length
+// esi = one byte past end of source
+// edi = one byte past end of dest
+
+LReverseShort:
+ movl %ecx,%edx // copy length
+ shrl $2,%ecx // #words
+ jz 3f
+1:
+ subl $4,%esi
+ movl (%esi),%eax
+ subl $4,%edi
+ movl %eax,(%edi)
+ dec %ecx
+ jnz 1b
+3:
+ andl $3,%edx // bytes?
+ jz 5f
+4:
+ dec %esi
+ movb (%esi),%al
+ dec %edi
+ movb %al,(%edi)
+ dec %edx
+ jnz 4b
+5:
+ movl 8(%ebp),%eax // get return value (dst ptr) for memcpy/memmove
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+
+// Handle a reverse move long enough to justify using SSE.
+// ecx = length
+// esi = one byte past end of source
+// edi = one byte past end of dest
+
+LReverseNotShort:
+ movl %edi,%edx // copy destination
+ andl $15,%edx // get #bytes to align destination
+ je LReverseDestAligned // already aligned
+ subl %edx,%ecx // adjust length
+1: // loop copying 1..15 bytes
+ dec %esi
+ movb (%esi),%al
+ dec %edi
+ movb %al,(%edi)
+ dec %edx
+ jnz 1b
+
+// Destination is now aligned. Prepare for reverse loops.
+
+LReverseDestAligned:
+ movl %ecx,%edx // copy length
+ andl $63,%ecx // get remaining bytes for Lshort
+ andl $-64,%edx // get number of bytes we will copy in inner loop
+ subl %edx,%esi // point to endpoint of copy
+ subl %edx,%edi
+ testl $15,%esi // is source aligned too?
+ jnz LReverseUnalignedLoop // no
+ jmp LReverseAlignedLoop // use aligned loop
+
+ .align 4,0x90 // 16-byte align inner loops
+LReverseAlignedLoop: // loop over 64-byte chunks
+ movdqa -16(%esi,%edx),%xmm0
+ movdqa -32(%esi,%edx),%xmm1
+ movdqa -48(%esi,%edx),%xmm2
+ movdqa -64(%esi,%edx),%xmm3
+
+ movdqa %xmm0,-16(%edi,%edx)
+ movdqa %xmm1,-32(%edi,%edx)
+ movdqa %xmm2,-48(%edi,%edx)
+ movdqa %xmm3,-64(%edi,%edx)
+
+ subl $64,%edx
+ jne LReverseAlignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+
+// Reverse, unaligned loop. LDDQU==MOVDQU on these machines.
+
+ .align 4,0x90 // 16-byte align inner loops
+LReverseUnalignedLoop: // loop over 64-byte chunks
+ movdqu -16(%esi,%edx),%xmm0
+ movdqu -32(%esi,%edx),%xmm1
+ movdqu -48(%esi,%edx),%xmm2
+ movdqu -64(%esi,%edx),%xmm3
+
+ movdqa %xmm0,-16(%edi,%edx)
+ movdqa %xmm1,-32(%edi,%edx)
+ movdqa %xmm2,-48(%edi,%edx)
+ movdqa %xmm3,-64(%edi,%edx)
+
+ subl $64,%edx
+ jne LReverseUnalignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+PLATFUNC_DESCRIPTOR(bcopy,sse2,kHasSSE2|kCache64,kHasSupplementalSSE3)
+PLATFUNC_DESCRIPTOR(memcpy,sse2,kHasSSE2|kCache64,kHasSupplementalSSE3)
+PLATFUNC_DESCRIPTOR(memmove,sse2,kHasSSE2|kCache64,kHasSupplementalSSE3)
--- /dev/null
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * The bcopy/memcpy loops, tuned for Pentium-M class processors with
+ * Supplemental SSE3 and 64-byte cache lines.
+ *
+ * The following #defines are tightly coupled to the u-architecture:
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+#define kVeryLong (500*1024) // large enough for non-temporal stores (must be >= 8192)
+#define kFastUCode ((16*1024)-15) // cutoff for microcode fastpath for "rep/movsl"
+
+// void bcopy(const void *src, void *dst, size_t len);
+
+PLATFUNC_FUNCTION_START(bcopy, sse3x, 32, 5)
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ movl 8(%ebp),%esi // get source ptr
+ movl 12(%ebp),%edi // get dest ptr
+ movl 16(%ebp),%ecx // get length
+ movl %edi,%edx
+ subl %esi,%edx // (dest - source)
+ cmpl %ecx,%edx // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ jbe Lshort // no
+ jmp LNotShort
+
+//
+// void *memcpy(void *dst, const void *src, size_t len);
+// void *memmove(void *dst, const void *src, size_t len);
+//
+
+PLATFUNC_FUNCTION_START(memcpy, sse3x, 32, 0) // void *memcpy(void *dst, const void *src, size_t len)
+PLATFUNC_FUNCTION_START(memmove, sse3x, 32, 0) // void *memmove(void *dst, const void *src, size_t len)
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ movl 8(%ebp),%edi // get dest ptr
+ movl 12(%ebp),%esi // get source ptr
+ movl 16(%ebp),%ecx // get length
+ movl %edi,%edx
+ subl %esi,%edx // (dest - source)
+ cmpl %ecx,%edx // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ ja LNotShort // yes
+
+// Handle short forward copies. As the most common case, this is the fall-through path.
+// ecx = length (<= kShort)
+// esi = source ptr
+// edi = dest ptr
+
+Lshort:
+ movl %ecx,%edx // copy length
+ shrl $2,%ecx // get #doublewords
+ jz LLeftovers
+2: // loop copying doublewords
+ movl (%esi),%eax
+ addl $4,%esi
+ movl %eax,(%edi)
+ addl $4,%edi
+ dec %ecx
+ jnz 2b
+LLeftovers: // handle leftover bytes (0..3) in last word
+ andl $3,%edx // any leftover bytes?
+ jz Lexit
+4: // loop copying bytes
+ movb (%esi),%al
+ inc %esi
+ movb %al,(%edi)
+ inc %edi
+ dec %edx
+ jnz 4b
+Lexit:
+ movl 8(%ebp),%eax // get return value (dst ptr) for memcpy/memmove
+ popl %ebx
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+
+
+LReverseIsland: // keep the "jb" above a short branch...
+ jmp LReverse // ...because reverse moves are uncommon
+
+
+// Handle forward moves that are long enough to justify use of SSE3.
+// First, 16-byte align the destination.
+// ecx = length (> kShort)
+// esi = source ptr
+// edi = dest ptr
+
+LNotShort:
+ cmpl $(kVeryLong),%ecx // long enough to justify heavyweight loops?
+ movl %edi,%edx // copy destination
+ jae LVeryLong // use very-long-operand path
+ negl %edx
+ andl $15,%edx // get #bytes to align destination
+ jz LDestAligned // already aligned
+ subl %edx,%ecx // decrement length
+1: // loop copying 1..15 bytes
+ movb (%esi),%al
+ inc %esi
+ movb %al,(%edi)
+ inc %edi
+ dec %edx
+ jnz 1b
+
+// Destination is now aligned. Dispatch to one of sixteen loops over 64-byte chunks,
+// based on the alignment of the source. All vector loads and stores are aligned.
+// Even though this means we have to shift and repack vectors, doing so is much faster
+// than unaligned loads. Since kShort>=80 and we've moved at most 15 bytes already,
+// there is at least one chunk. When we enter the copy loops, the following registers
+// are set up:
+// ecx = residual length (0..63)
+// edx = -(length to move), a multiple of 64
+// esi = ptr to 1st source byte not to move (unaligned)
+// edi = ptr to 1st dest byte not to move (aligned)
+
+LDestAligned:
+ movl %ecx,%edx // copy length
+ movl %esi,%eax // copy source address
+ andl $63,%ecx // get remaining bytes for Lshort
+ andl $-64,%edx // get number of bytes we will copy in inner loop
+ andl $15,%eax // mask to low 4 bits of source address
+ addl %edx,%esi // point to 1st byte not copied
+ addl %edx,%edi
+ negl %edx // now generate offset to 1st byte to be copied
+ call 1f
+1:
+ popl %ebx
+ movl (LTable-1b)(%ebx,%eax,4), %eax // load jump table entry address, relative to LZero
+ leal (LTable-1b)(%ebx,%eax,1), %eax
+ jmp *%eax
+
+ .align 2
+LTable: // table of copy loop addresses
+ .long LMod0 -LTable
+ .long LMod1 -LTable
+ .long LMod2 -LTable
+ .long LMod3 -LTable
+ .long LMod4 -LTable
+ .long LMod5 -LTable
+ .long LMod6 -LTable
+ .long LMod7 -LTable
+ .long LMod8 -LTable
+ .long LMod9 -LTable
+ .long LMod10 -LTable
+ .long LMod11 -LTable
+ .long LMod12 -LTable
+ .long LMod13 -LTable
+ .long LMod14 -LTable
+ .long LMod15 -LTable
+
+
+// Very long forward moves. These are at least several pages. They are special cased
+// and aggressively optimized, not so much because they are common or useful, but
+// because they are subject to benchmark. There isn't enough room for them in the
+// area reserved on the platfunc for bcopy, so we put them elsewhere. We call
+// the longcopy routine using the normal ABI.
+
+LVeryLong:
+ pushl %ecx // length (>= kVeryLong)
+ pushl %esi // source ptr
+ pushl %edi // dest ptr
+ call _longcopy
+ addl $12,%esp // pop off our parameters
+ jmp Lexit
+
+
+// On Pentium-M, the microcode for "rep/movsl" is faster than SSE for 8-byte
+// aligned operands from about 32KB up to kVeryLong for the hot cache case, and from
+// about 256 bytes up to kVeryLong for cold caches. This is because the microcode
+// avoids having to read destination cache lines that will be completely overwritten.
+// The cutoff we use (ie, kFastUCode) must somehow balance the two cases, since
+// we do not know if the destination is in cache or not.
+
+Lfastpath:
+ addl %edx,%esi // restore ptrs to 1st byte of source and dest
+ addl %edx,%edi
+ negl %edx // make length positive
+ orl %edx,%ecx // restore total #bytes remaining to move
+ cld // we'll move forward
+ movl %ecx,%edx // copy total length to move
+ shrl $2,%ecx // compute #words to move
+ rep // the u-code will optimize this
+ movsl
+ jmp LLeftovers // handle 0..3 leftover bytes
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0000
+
+LMod0:
+ cmpl $(-kFastUCode),%edx // %edx == -length, where (length < kVeryLong)
+ jle Lfastpath // long enough for fastpath in microcode
+ jmp 1f
+ .align 4,0x90 // 16-byte align inner loops
+1: // loop over 64-byte chunks
+ movdqa (%esi,%edx),%xmm0
+ movdqa 16(%esi,%edx),%xmm1
+ movdqa 32(%esi,%edx),%xmm2
+ movdqa 48(%esi,%edx),%xmm3
+
+ movdqa %xmm0,(%edi,%edx)
+ movdqa %xmm1,16(%edi,%edx)
+ movdqa %xmm2,32(%edi,%edx)
+ movdqa %xmm3,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0001
+
+LMod1:
+ movdqa -1(%esi,%edx),%xmm0 // prime the loop by loading 1st quadword
+1: // loop over 64-byte chunks
+ movdqa 15(%esi,%edx),%xmm1
+ movdqa 31(%esi,%edx),%xmm2
+ movdqa 47(%esi,%edx),%xmm3
+ movdqa 63(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $1,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $1,%xmm2,%xmm3
+ palignr $1,%xmm1,%xmm2
+ palignr $1,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0010
+
+LMod2:
+ movdqa -2(%esi,%edx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 14(%esi,%edx),%xmm1
+ movdqa 30(%esi,%edx),%xmm2
+ movdqa 46(%esi,%edx),%xmm3
+ movdqa 62(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $2,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $2,%xmm2,%xmm3
+ palignr $2,%xmm1,%xmm2
+ palignr $2,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0011
+
+LMod3:
+ movdqa -3(%esi,%edx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 13(%esi,%edx),%xmm1
+ movdqa 29(%esi,%edx),%xmm2
+ movdqa 45(%esi,%edx),%xmm3
+ movdqa 61(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $3,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $3,%xmm2,%xmm3
+ palignr $3,%xmm1,%xmm2
+ palignr $3,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0100
+// We use the float single data type in order to use "movss" to merge vectors.
+
+LMod4:
+ movaps -4(%esi,%edx),%xmm0 // 4-byte aligned: prime the loop
+ jmp 1f
+ .align 4,0x90
+1: // loop over 64-byte chunks
+ movaps 12(%esi,%edx),%xmm1
+ movaps 28(%esi,%edx),%xmm2
+ movss %xmm1,%xmm0 // copy low 4 bytes of source into destination
+ pshufd $(0x39),%xmm0,%xmm0 // rotate right 4 bytes (mask -- 00 11 10 01)
+ movaps 44(%esi,%edx),%xmm3
+ movss %xmm2,%xmm1
+ pshufd $(0x39),%xmm1,%xmm1
+ movaps 60(%esi,%edx),%xmm4
+ movss %xmm3,%xmm2
+ pshufd $(0x39),%xmm2,%xmm2
+
+ movaps %xmm0,(%edi,%edx)
+ movss %xmm4,%xmm3
+ pshufd $(0x39),%xmm3,%xmm3
+ movaps %xmm1,16(%edi,%edx)
+ movaps %xmm2,32(%edi,%edx)
+ movaps %xmm4,%xmm0
+ movaps %xmm3,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0101
+
+LMod5:
+ movdqa -5(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 11(%esi,%edx),%xmm1
+ movdqa 27(%esi,%edx),%xmm2
+ movdqa 43(%esi,%edx),%xmm3
+ movdqa 59(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $5,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $5,%xmm2,%xmm3
+ palignr $5,%xmm1,%xmm2
+ palignr $5,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0110
+
+LMod6:
+ movdqa -6(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 10(%esi,%edx),%xmm1
+ movdqa 26(%esi,%edx),%xmm2
+ movdqa 42(%esi,%edx),%xmm3
+ movdqa 58(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $6,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $6,%xmm2,%xmm3
+ palignr $6,%xmm1,%xmm2
+ palignr $6,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 0111
+
+LMod7:
+ movdqa -7(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 9(%esi,%edx),%xmm1
+ movdqa 25(%esi,%edx),%xmm2
+ movdqa 41(%esi,%edx),%xmm3
+ movdqa 57(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $7,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $7,%xmm2,%xmm3
+ palignr $7,%xmm1,%xmm2
+ palignr $7,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1000
+// We use the float double data type in order to use "shufpd" to shift by 8 bytes.
+
+LMod8:
+ cmpl $(-kFastUCode),%edx// %edx == -length, where (length < kVeryLong)
+ jle Lfastpath // long enough for fastpath in microcode
+ movapd -8(%esi,%edx),%xmm0// 8-byte aligned: prime the loop
+ jmp 1f
+ .align 4,0x90
+1: // loop over 64-byte chunks
+ movapd 8(%esi,%edx),%xmm1
+ movapd 24(%esi,%edx),%xmm2
+ shufpd $01,%xmm1,%xmm0 // %xmm0 <- shr( %xmm0 || %xmm1, 8 bytes)
+ movapd 40(%esi,%edx),%xmm3
+ shufpd $01,%xmm2,%xmm1
+ movapd 56(%esi,%edx),%xmm4
+ shufpd $01,%xmm3,%xmm2
+
+ movapd %xmm0,(%edi,%edx)
+ shufpd $01,%xmm4,%xmm3
+ movapd %xmm1,16(%edi,%edx)
+ movapd %xmm2,32(%edi,%edx)
+ movapd %xmm4,%xmm0
+ movapd %xmm3,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1001
+
+LMod9:
+ movdqa -9(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 7(%esi,%edx),%xmm1
+ movdqa 23(%esi,%edx),%xmm2
+ movdqa 39(%esi,%edx),%xmm3
+ movdqa 55(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $9,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $9,%xmm2,%xmm3
+ palignr $9,%xmm1,%xmm2
+ palignr $9,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1010
+
+LMod10:
+ movdqa -10(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 6(%esi,%edx),%xmm1
+ movdqa 22(%esi,%edx),%xmm2
+ movdqa 38(%esi,%edx),%xmm3
+ movdqa 54(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $10,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $10,%xmm2,%xmm3
+ palignr $10,%xmm1,%xmm2
+ palignr $10,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1011
+
+LMod11:
+ movdqa -11(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 5(%esi,%edx),%xmm1
+ movdqa 21(%esi,%edx),%xmm2
+ movdqa 37(%esi,%edx),%xmm3
+ movdqa 53(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $11,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $11,%xmm2,%xmm3
+ palignr $11,%xmm1,%xmm2
+ palignr $11,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1100
+// We use the float single data type in order to use "movss" to merge vectors.
+
+LMod12:
+ movss (%esi,%edx),%xmm0// prefetch 1st four bytes of source, right justified
+ jmp 1f
+ .align 4,0x90
+1: // loop over 64-byte chunks
+ pshufd $(0x93),4(%esi,%edx),%xmm1 // load and rotate right 12 bytes (mask -- 10 01 00 11)
+ pshufd $(0x93),20(%esi,%edx),%xmm2
+ pshufd $(0x93),36(%esi,%edx),%xmm3
+ pshufd $(0x93),52(%esi,%edx),%xmm4
+
+ movaps %xmm4,%xmm5
+ movss %xmm3,%xmm4 // copy low 4 bytes of source into destination
+ movss %xmm2,%xmm3
+ movss %xmm1,%xmm2
+ movss %xmm0,%xmm1
+
+ movaps %xmm1,(%edi,%edx)
+ movaps %xmm2,16(%edi,%edx)
+ movaps %xmm5,%xmm0
+ movaps %xmm3,32(%edi,%edx)
+ movaps %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1101
+
+LMod13:
+ movdqa -13(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 3(%esi,%edx),%xmm1
+ movdqa 19(%esi,%edx),%xmm2
+ movdqa 35(%esi,%edx),%xmm3
+ movdqa 51(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $13,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $13,%xmm2,%xmm3
+ palignr $13,%xmm1,%xmm2
+ palignr $13,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1110
+
+LMod14:
+ movdqa -14(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 2(%esi,%edx),%xmm1
+ movdqa 18(%esi,%edx),%xmm2
+ movdqa 34(%esi,%edx),%xmm3
+ movdqa 50(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $14,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $14,%xmm2,%xmm3
+ palignr $14,%xmm1,%xmm2
+ palignr $14,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %esi == 1111
+
+LMod15:
+ movdqa -15(%esi,%edx),%xmm0// prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 1(%esi,%edx),%xmm1
+ movdqa 17(%esi,%edx),%xmm2
+ movdqa 33(%esi,%edx),%xmm3
+ movdqa 49(%esi,%edx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $15,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $15,%xmm2,%xmm3
+ palignr $15,%xmm1,%xmm2
+ palignr $15,%xmm5,%xmm1
+
+ movdqa %xmm1,(%edi,%edx)
+ movdqa %xmm2,16(%edi,%edx)
+ movdqa %xmm3,32(%edi,%edx)
+ movdqa %xmm4,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz 1b
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Reverse moves. These are not optimized as aggressively as their forward
+// counterparts, as they are only used with destructive overlap.
+// ecx = length
+// esi = source ptr
+// edi = dest ptr
+
+LReverse:
+ addl %ecx,%esi // point to end of strings
+ addl %ecx,%edi
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ ja LReverseNotShort // yes
+
+// Handle reverse short copies.
+// ecx = length
+// esi = one byte past end of source
+// edi = one byte past end of dest
+
+LReverseShort:
+ movl %ecx,%edx // copy length
+ shrl $2,%ecx // #words
+ jz 3f
+1:
+ subl $4,%esi
+ movl (%esi),%eax
+ subl $4,%edi
+ movl %eax,(%edi)
+ dec %ecx
+ jnz 1b
+3:
+ andl $3,%edx // bytes?
+ jz 5f
+4:
+ dec %esi
+ movb (%esi),%al
+ dec %edi
+ movb %al,(%edi)
+ dec %edx
+ jnz 4b
+5:
+ movl 8(%ebp),%eax // get return value (dst ptr) for memcpy/memmove
+ popl %ebx
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+
+// Handle a reverse move long enough to justify using SSE.
+// ecx = length
+// esi = one byte past end of source
+// edi = one byte past end of dest
+
+LReverseNotShort:
+ movl %edi,%edx // copy destination
+ andl $15,%edx // get #bytes to align destination
+ je LReverseDestAligned // already aligned
+ subl %edx,%ecx // adjust length
+1: // loop copying 1..15 bytes
+ dec %esi
+ movb (%esi),%al
+ dec %edi
+ movb %al,(%edi)
+ dec %edx
+ jnz 1b
+
+// Destination is now aligned. Prepare for reverse loops.
+
+LReverseDestAligned:
+ movl %ecx,%edx // copy length
+ andl $63,%ecx // get remaining bytes for Lshort
+ andl $-64,%edx // get number of bytes we will copy in inner loop
+ subl %edx,%esi // point to endpoint of copy
+ subl %edx,%edi
+ testl $15,%esi // is source aligned too?
+ jnz LReverseUnalignedLoop // no
+
+LReverseAlignedLoop: // loop over 64-byte chunks
+ movdqa -16(%esi,%edx),%xmm0
+ movdqa -32(%esi,%edx),%xmm1
+ movdqa -48(%esi,%edx),%xmm2
+ movdqa -64(%esi,%edx),%xmm3
+
+ movdqa %xmm0,-16(%edi,%edx)
+ movdqa %xmm1,-32(%edi,%edx)
+ movdqa %xmm2,-48(%edi,%edx)
+ movdqa %xmm3,-64(%edi,%edx)
+
+ subl $64,%edx
+ jne LReverseAlignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+
+// Reverse, unaligned loop. LDDQU==MOVDQU on these machines.
+
+LReverseUnalignedLoop: // loop over 64-byte chunks
+ movdqu -16(%esi,%edx),%xmm0
+ movdqu -32(%esi,%edx),%xmm1
+ movdqu -48(%esi,%edx),%xmm2
+ movdqu -64(%esi,%edx),%xmm3
+
+ movdqa %xmm0,-16(%edi,%edx)
+ movdqa %xmm1,-32(%edi,%edx)
+ movdqa %xmm2,-48(%edi,%edx)
+ movdqa %xmm3,-64(%edi,%edx)
+
+ subl $64,%edx
+ jne LReverseUnalignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+PLATFUNC_DESCRIPTOR(bcopy,sse3x,kHasSSE2|kHasSupplementalSSE3|kCache64,kHasSSE4_2)
+PLATFUNC_DESCRIPTOR(memcpy,sse3x,kHasSSE2|kHasSupplementalSSE3|kCache64,kHasSSE4_2)
+PLATFUNC_DESCRIPTOR(memmove,sse3x,kHasSSE2|kHasSupplementalSSE3|kCache64,kHasSSE4_2)
--- /dev/null
+/*
+ * Copyright (c) 2008 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * The bcopy/memcpy loops, tuned for Nehalem.
+ *
+ * The following #defines are tightly coupled to the u-architecture:
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+
+
+// void bcopy(const void *src, void *dst, size_t len);
+
+PLATFUNC_FUNCTION_START(bcopy, sse42, 32, 5)
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ movl 8(%ebp),%esi // get source ptr
+ movl 12(%ebp),%edi // get dest ptr
+ movl 16(%ebp),%ecx // get length
+ movl %edi,%edx
+ subl %esi,%edx // (dest - source)
+ cmpl %ecx,%edx // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ jbe Lshort // no
+ jmp LNotShort
+
+//
+// void *memcpy(void *dst, const void *src, size_t len);
+// void *memmove(void *dst, const void *src, size_t len);
+//
+
+PLATFUNC_FUNCTION_START(memcpy, sse42, 32, 0) // void *memcpy(void *dst, const void *src, size_t len)
+PLATFUNC_FUNCTION_START(memmove, sse42, 32, 0) // void *memmove(void *dst, const void *src, size_t len)
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ movl 8(%ebp),%edi // get dest ptr
+ movl 12(%ebp),%esi // get source ptr
+ movl 16(%ebp),%ecx // get length
+ movl %edi,%edx
+ subl %esi,%edx // (dest - source)
+ cmpl %ecx,%edx // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ ja LNotShort // yes
+
+// Handle short forward copies. As the most common case, this is the fall-through path.
+// ecx = length (<= kShort)
+// esi = source ptr
+// edi = dest ptr
+
+Lshort:
+ movl %ecx,%edx // copy length
+ shrl $2,%ecx // get #doublewords
+ jz 3f
+2: // loop copying doublewords
+ movl (%esi),%eax
+ addl $4,%esi
+ movl %eax,(%edi)
+ addl $4,%edi
+ dec %ecx
+ jnz 2b
+3: // handle leftover bytes (0..3) in last word
+ andl $3,%edx // any leftover bytes?
+ jz Lexit
+4: // loop copying bytes
+ movb (%esi),%al
+ inc %esi
+ movb %al,(%edi)
+ inc %edi
+ dec %edx
+ jnz 4b
+Lexit:
+ movl 8(%ebp),%eax // get return value (dst ptr) for memcpy/memmove
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+
+
+LReverseIsland: // keep the "jb" above a short branch...
+ jmp LReverse // ...because reverse moves are uncommon
+
+
+// Handle forward moves that are long enough to justify use of SSE.
+// First, 16-byte align the destination.
+// ecx = length (> kShort)
+// esi = source ptr
+// edi = dest ptr
+
+LNotShort:
+ movl %edi,%edx // copy destination
+ negl %edx
+ andl $15,%edx // get #bytes to align destination
+ jz LDestAligned // already aligned
+ subl %edx,%ecx // decrement length
+1: // loop copying 1..15 bytes
+ movb (%esi),%al
+ inc %esi
+ movb %al,(%edi)
+ inc %edi
+ dec %edx
+ jnz 1b
+
+// Destination is now aligned. Nehalem does a great job with unaligned SSE loads,
+// so we use MOVDQU rather than aligned loads and shifts. Since kShort>=80, we
+// know there is at least one 64-byte chunk to move.
+// When we enter the copy loops, the following registers are set up:
+// ecx = residual length (0..63)
+// edx = -(length to move), a multiple of 64
+// esi = ptr to 1st source byte not to move (unaligned)
+// edi = ptr to 1st dest byte not to move (aligned)
+
+LDestAligned:
+ movl %ecx,%edx // copy length
+ andl $63,%ecx // get remaining bytes for Lshort
+ andl $-64,%edx // get number of bytes we will copy in inner loop
+ addl %edx,%esi // point to 1st byte not copied
+ addl %edx,%edi
+ negl %edx // now generate offset to 1st byte to be copied
+ testl $15,%esi // source also aligned?
+ jnz LUnalignedLoop
+ jmp LAlignedLoop
+
+
+// Forward loop for aligned operands.
+
+ .align 4,0x90 // 16-byte align inner loops
+LAlignedLoop: // loop over 64-byte chunks
+ movdqa (%esi,%edx),%xmm0
+ movdqa 16(%esi,%edx),%xmm1
+ movdqa 32(%esi,%edx),%xmm2
+ movdqa 48(%esi,%edx),%xmm3
+
+ movdqa %xmm0,(%edi,%edx)
+ movdqa %xmm1,16(%edi,%edx)
+ movdqa %xmm2,32(%edi,%edx)
+ movdqa %xmm3,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz LAlignedLoop
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for unaligned operands.
+
+ .align 4,0x90 // 16-byte align inner loops
+LUnalignedLoop: // loop over 64-byte chunks
+ movdqu (%esi,%edx),%xmm0
+ movdqu 16(%esi,%edx),%xmm1
+ movdqu 32(%esi,%edx),%xmm2
+ movdqu 48(%esi,%edx),%xmm3
+
+ movdqa %xmm0,(%edi,%edx)
+ movdqa %xmm1,16(%edi,%edx)
+ movdqa %xmm2,32(%edi,%edx)
+ movdqa %xmm3,48(%edi,%edx)
+
+ addl $64,%edx
+ jnz LUnalignedLoop
+
+ jmp Lshort // copy remaining 0..63 bytes and done
+
+
+// Reverse moves. They are only used with destructive overlap.
+// ecx = length
+// esi = source ptr
+// edi = dest ptr
+
+LReverse:
+ addl %ecx,%esi // point to end of strings
+ addl %ecx,%edi
+ cmpl $(kShort),%ecx // long enough to bother with SSE?
+ ja LReverseNotShort // yes
+
+// Handle reverse short copies.
+// ecx = length
+// esi = one byte past end of source
+// edi = one byte past end of dest
+
+LReverseShort:
+ movl %ecx,%edx // copy length
+ shrl $2,%ecx // #words
+ jz 3f
+1:
+ subl $4,%esi
+ movl (%esi),%eax
+ subl $4,%edi
+ movl %eax,(%edi)
+ dec %ecx
+ jnz 1b
+3:
+ andl $3,%edx // bytes?
+ jz 5f
+4:
+ dec %esi
+ movb (%esi),%al
+ dec %edi
+ movb %al,(%edi)
+ dec %edx
+ jnz 4b
+5:
+ movl 8(%ebp),%eax // get return value (dst ptr) for memcpy/memmove
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
+
+// Handle a reverse move long enough to justify using SSE.
+// ecx = length
+// esi = one byte past end of source
+// edi = one byte past end of dest
+
+LReverseNotShort:
+ movl %edi,%edx // copy destination
+ andl $15,%edx // get #bytes to align destination
+ je LReverseDestAligned // already aligned
+ subl %edx,%ecx // adjust length
+1: // loop copying 1..15 bytes
+ dec %esi
+ movb (%esi),%al
+ dec %edi
+ movb %al,(%edi)
+ dec %edx
+ jnz 1b
+
+// Destination is now aligned. Prepare for reverse loops.
+
+LReverseDestAligned:
+ movl %ecx,%edx // copy length
+ andl $63,%ecx // get remaining bytes for Lshort
+ andl $-64,%edx // get number of bytes we will copy in inner loop
+ subl %edx,%esi // point to endpoint of copy
+ subl %edx,%edi
+ testl $15,%esi // is source aligned too?
+ jnz LReverseUnalignedLoop // no
+
+LReverseAlignedLoop: // loop over 64-byte chunks
+ movdqa -16(%esi,%edx),%xmm0
+ movdqa -32(%esi,%edx),%xmm1
+ movdqa -48(%esi,%edx),%xmm2
+ movdqa -64(%esi,%edx),%xmm3
+
+ movdqa %xmm0,-16(%edi,%edx)
+ movdqa %xmm1,-32(%edi,%edx)
+ movdqa %xmm2,-48(%edi,%edx)
+ movdqa %xmm3,-64(%edi,%edx)
+
+ subl $64,%edx
+ jne LReverseAlignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+
+// Reverse, unaligned loop. LDDQU==MOVDQU on these machines.
+
+LReverseUnalignedLoop: // loop over 64-byte chunks
+ movdqu -16(%esi,%edx),%xmm0
+ movdqu -32(%esi,%edx),%xmm1
+ movdqu -48(%esi,%edx),%xmm2
+ movdqu -64(%esi,%edx),%xmm3
+
+ movdqa %xmm0,-16(%edi,%edx)
+ movdqa %xmm1,-32(%edi,%edx)
+ movdqa %xmm2,-48(%edi,%edx)
+ movdqa %xmm3,-64(%edi,%edx)
+
+ subl $64,%edx
+ jne LReverseUnalignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+
+PLATFUNC_DESCRIPTOR(bcopy,sse42,kHasSSE4_2,0)
+PLATFUNC_DESCRIPTOR(memcpy,sse42,kHasSSE4_2,0)
+PLATFUNC_DESCRIPTOR(memmove,sse42,kHasSSE4_2,0)
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bzero, sse42)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bzero, sse2)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bzero, scalar)
+
+static const platfunc_descriptor *bzero_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(bzero, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(bzero, sse2),
+ PLATFUNC_DESCRIPTOR_REFERENCE(bzero, scalar),
+ 0
+};
+
+void *bzero_chooser() __asm__("_bzero");
+void *bzero_chooser() {
+ __asm__(".desc _bzero, 0x100");
+ return find_platform_function((const platfunc_descriptor **) bzero_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 2002-2003 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@
- */
-
-/*
- * Call the comm page routine
- */
-
-#define __APPLE_API_PRIVATE
-#include <machine/cpu_capabilities.h>
-
-#include <architecture/i386/asm_help.h>
-
- TEXT
- ALIGN
-
-LEAF(_bzero,0)
- movl $(_COMM_PAGE_BZERO), %eax
- jmpl *%eax
-
-X_LEAF(___bzero, _bzero)
--- /dev/null
+/*
+ * Copyright (c) 2003-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * 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 Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * bzero (void *b, size_t len)
+ * write len zero bytes to the string b.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+PLATFUNC_FUNCTION_START_GENERIC(bzero, scalar, 32, 4)
+ pushl %ebp /* set up a frame for backtraces */
+ movl %esp,%ebp
+ pushl %edi
+ pushl %ebx
+ movl 8(%ebp),%edi
+ movl 12(%ebp),%ecx
+
+ cld /* set fill direction forward */
+ xorl %eax,%eax /* set fill data to 0 */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpl $0x0f,%ecx
+ jbe L1
+
+ movl %edi,%edx /* compute misalignment */
+ negl %edx
+ andl $3,%edx
+ movl %ecx,%ebx
+ subl %edx,%ebx
+
+ movl %edx,%ecx /* zero until word aligned */
+ rep
+ stosb
+
+ movl %ebx,%ecx /* zero by words */
+ shrl $2,%ecx
+ rep
+ stosl
+
+ movl %ebx,%ecx
+ andl $3,%ecx /* zero remainder by bytes */
+L1: rep
+ stosb
+
+ popl %ebx
+ popl %edi
+ popl %ebp
+ ret
+
+PLATFUNC_DESCRIPTOR(bzero,scalar,0,0)
--- /dev/null
+/*
+ * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * Bzero, tuned for Pentium-M class processors with SSE2
+ * and 64-byte cache lines.
+ *
+ * This routine is also used for memset(p,0,n), which is a common case
+ * since gcc sometimes silently maps bzero() into memset(). As a result,
+ * we always load the original ptr into %eax before returning.
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+#define kVeryLong (1024*1024)
+
+// void bzero(void *b, size_t len);
+
+PLATFUNC_FUNCTION_START(bzero, sse2, 32, 5)
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %edi
+ movl 8(%ebp),%edi // get ptr
+ movl 12(%ebp),%edx // get length
+
+ xorl %eax,%eax // set fill data to 0
+ cmpl $(kShort),%edx // long enough for SSE?
+ jg LNotShort // yes
+
+// Here for short operands or the end of long ones.
+// %edx = length
+// %edi = ptr
+// %eax = zero
+
+Lshort:
+ cmpl $16,%edx // long enough to word align?
+ jge 3f // yes
+ test %edx,%edx // length==0?
+ jz 6f
+1:
+ movb %al,(%edi) // zero a byte
+ inc %edi
+ dec %edx
+ jnz 1b
+ jmp 6f
+2:
+ movb %al,(%edi) // zero a byte
+ inc %edi
+ dec %edx
+3:
+ test $3,%edi // is ptr doubleword aligned?
+ jnz 2b // no
+ movl %edx,%ecx // copy length
+ shrl $2,%edx // #doublewords to store
+4:
+ movl %eax,(%edi) // zero an aligned doubleword
+ addl $4,%edi
+ dec %edx
+ jnz 4b
+ andl $3,%ecx // mask down to #bytes at end (0..3)
+ jz 6f // none
+5:
+ movb %al,(%edi) // zero a byte
+ inc %edi
+ dec %ecx
+ jnz 5b
+6:
+ movl 8(%ebp),%eax // get return value in case this was a call of memset()
+ popl %edi
+ popl %ebp
+ ret
+
+
+// We will be using SSE, so align ptr.
+
+LNotShort:
+ movl %edi,%ecx
+ negl %ecx
+ andl $15,%ecx // mask down to #bytes to 16-byte align
+ jz LDestAligned // already aligned
+ subl %ecx,%edx // decrement length
+0: // loop storing bytes to align the ptr
+ movb %al,(%edi) // pack in a byte
+ inc %edi
+ dec %ecx
+ jnz 0b
+
+// Destination is now 16-byte aligned. Prepare to loop over 64-byte chunks.
+// %edx = length
+// %edi = ptr
+// %eax = zero
+
+LDestAligned:
+ movl %edx,%ecx
+ andl $63,%edx // mask down to residual length (0..63)
+ andl $-64,%ecx // get #bytes we will zero in this loop
+ pxor %xmm0,%xmm0 // zero an SSE register
+ addl %ecx,%edi // increment ptr by length to move
+ cmpl $(kVeryLong),%ecx // long enough to justify non-temporal stores?
+ jae LVeryLong // yes
+ negl %ecx // negate length to move
+ jmp 1f
+
+// Loop over 64-byte chunks, storing into cache.
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movdqa %xmm0,(%edi,%ecx)
+ movdqa %xmm0,16(%edi,%ecx)
+ movdqa %xmm0,32(%edi,%ecx)
+ movdqa %xmm0,48(%edi,%ecx)
+ addl $64,%ecx
+ jne 1b
+
+ jmp Lshort
+
+// Very long operands: use non-temporal stores to bypass cache.
+
+LVeryLong:
+ negl %ecx // negate length to move
+ jmp 1f
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movntdq %xmm0,(%edi,%ecx)
+ movntdq %xmm0,16(%edi,%ecx)
+ movntdq %xmm0,32(%edi,%ecx)
+ movntdq %xmm0,48(%edi,%ecx)
+ addl $64,%ecx
+ jne 1b
+
+ sfence // required by non-temporal stores
+ jmp Lshort
+
+PLATFUNC_DESCRIPTOR(bzero,sse2,kHasSSE2,kHasSSE4_2)
--- /dev/null
+/*
+ * Copyright (c) 2008 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * Bzero, tuned for processors with SSE4.2 and 64-byte cache lines, ie Nehalem.
+ * We don't actually use SSE4.2, but rather use it to identify Nehalem.
+ *
+ * We do not use nontemporal operations, but use MOVDQA in preference to REP/STOS.
+ *
+ * This routine is also used for memset(p,0,n), which is a common case
+ * since gcc sometimes silently maps bzero() into memset(). As a result,
+ * we always load the original ptr into %eax before returning.
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+
+
+PLATFUNC_FUNCTION_START(bzero, sse42, 32, 5)
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %edi
+ movl 8(%ebp),%edi // get ptr
+ movl 12(%ebp),%edx // get length
+
+ xorl %eax,%eax // set fill data to 0
+ cmpl $(kShort),%edx // long enough for SSE?
+ jg LNotShort // yes
+
+// Here for short operands or the end of long ones.
+// %edx = length
+// %edi = ptr
+// %eax = zero
+
+Lshort:
+ cmpl $12,%edx // long enough to word align?
+ jge 3f // yes
+ test %edx,%edx // length==0?
+ jz 6f
+1:
+ movb %al,(%edi) // zero a byte
+ inc %edi
+ dec %edx
+ jnz 1b
+ jmp 6f
+2:
+ movb %al,(%edi) // zero a byte
+ inc %edi
+ dec %edx
+3:
+ test $3,%edi // is ptr doubleword aligned?
+ jnz 2b // no
+ movl %edx,%ecx // copy length
+ shrl $2,%edx // #doublewords to store
+4:
+ movl %eax,(%edi) // zero an aligned doubleword
+ addl $4,%edi
+ dec %edx
+ jnz 4b
+ andl $3,%ecx // mask down to #bytes at end (0..3)
+ jz 6f // none
+5:
+ movb %al,(%edi) // zero a byte
+ inc %edi
+ dec %ecx
+ jnz 5b
+6:
+ movl 8(%ebp),%eax // get return value in case this was a call of memset()
+ popl %edi
+ popl %ebp
+ ret
+
+
+// We will be using SSE, so align ptr.
+// %edx = length
+// %edi = ptr
+// %eax = zero
+
+LNotShort:
+ testl $3,%edi // 4-byte aligned?
+ jz 2f // yes
+ movb %al,(%edi) // zero another byte
+ incl %edi
+ decl %edx
+ jmp LNotShort
+1: // zero doublewords until 16-byte aligned
+ movl %eax,(%edi)
+ addl $4,%edi
+ subl $4,%edx
+2:
+ testl $15,%edi // 16-byte aligned?
+ jnz 1b // no
+
+
+// Destination is now 16-byte aligned. Prepare to loop over 64-byte chunks.
+// %edx = length
+// %edi = ptr
+// %eax = zero
+
+LDestAligned:
+ movl %edx,%ecx
+ andl $63,%edx // mask down to residual length (0..63)
+ andl $-64,%ecx // get #bytes we will zero in this loop
+ pxor %xmm0,%xmm0 // zero an SSE register
+ addl %ecx,%edi // increment ptr by length to move
+ negl %ecx // negate length to move
+ jmp 1f
+
+// Loop over 64-byte chunks, storing into cache.
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movdqa %xmm0,(%edi,%ecx)
+ movdqa %xmm0,16(%edi,%ecx)
+ movdqa %xmm0,32(%edi,%ecx)
+ movdqa %xmm0,48(%edi,%ecx)
+ addl $64,%ecx
+ jne 1b
+
+ jmp Lshort
+
+
+
+PLATFUNC_DESCRIPTOR(bzero,sse42,kHasSSE4_2,0)
--- /dev/null
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+
+/*
+ * The bcopy/memcpy loops for very long operands, tuned for Pentium-M
+ * class processors with Supplemental SSE3 and 64-byte cache lines.
+ *
+ * The following #defines are tightly coupled to the u-architecture:
+ */
+
+#define kBigChunk (256*1024) // outer loop chunk size for kVeryLong sized operands
+
+
+// Very long forward moves. These are at least several pages, so we loop over big
+// chunks of memory (kBigChunk in size.) We first prefetch the chunk, and then copy
+// it using non-temporal stores. Hopefully all the reads occur in the prefetch loop,
+// so the copy loop reads from L2 and writes directly to memory (with write combining.)
+// This minimizes bus turnaround and maintains good DRAM page locality.
+// Note that for this scheme to work, kVeryLong must be a large fraction of L2 cache
+// size. Otherwise, it is counter-productive to bypass L2 on the stores.
+//
+// We are called from the platfunc bcopy loops when they encounter very long
+// operands, with the standard ABI.
+//
+// void longcopy(const void *dest, void *sou, size_t len)
+
+// void longcopy(const void *dest, void *sou, size_t len)
+
+ .text
+ .private_extern _longcopy
+
+ .align 5
+_longcopy:
+ pushl %ebp // set up a frame for backtraces
+ movl %esp,%ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx // we'll need to use this too
+ movl 8(%ebp),%edi // get dest ptr
+ movl 12(%ebp),%esi // get source ptr
+ movl 16(%ebp),%ecx // get length
+ movl %edi,%ebx // copy dest ptr
+ negl %ebx
+ andl $63,%ebx // get #bytes to cache line align destination
+ jz LBigChunkLoop // already aligned
+
+// Cache line align destination, so temporal stores in copy loops work right.
+
+ pushl %ebx // arg3 - #bytes to align destination (1..63)
+ pushl %esi // arg2 - source
+ pushl %edi // arg1 - dest
+ call _memcpy // align the destination
+ addl $12,%esp
+ movl 8(%ebp),%edi // recover dest ptr
+ movl 12(%ebp),%esi // recover source ptr
+ movl 16(%ebp),%ecx // recover length
+ addl %ebx,%esi // adjust ptrs and lengths past copy
+ addl %ebx,%edi
+ subl %ebx,%ecx
+
+// Loop over big chunks.
+// ecx = length remaining (>= 4096)
+// edi = dest (64-byte aligned)
+// esi = source (may be unaligned)
+
+LBigChunkLoop:
+ movl $(kBigChunk),%edx // assume we can do a full chunk
+ cmpl %edx,%ecx // do we have a full chunk left to do?
+ cmovbl %ecx,%edx // if not, only move what we have left
+ andl $-4096,%edx // we work in page multiples
+ xor %eax,%eax // initialize chunk offset
+ jmp LTouchLoop
+
+// Touch in the next chunk. We try to keep the prefetch unit in "kick-start" mode,
+// by touching two adjacent cache lines every 8 lines of each page, in four slices.
+// Because the source may be unaligned, we use byte loads to touch.
+// ecx = length remaining (including this chunk)
+// edi = ptr to start of dest chunk
+// esi = ptr to start of source chunk
+// edx = chunk length (multiples of pages)
+// ebx = scratch reg used to read a byte of each cache line
+// eax = chunk offset
+
+ .align 4,0x90 // 16-byte align inner loops
+LTouchLoop:
+ movzb (%esi,%eax),%ebx // touch line 0, 2, 4, or 6 of page
+ movzb 1*64(%esi,%eax),%ebx // touch line 1, 3, 5, or 7
+ movzb 8*64(%esi,%eax),%ebx // touch line 8, 10, 12, or 14
+ movzb 9*64(%esi,%eax),%ebx // etc
+
+ movzb 16*64(%esi,%eax),%ebx
+ movzb 17*64(%esi,%eax),%ebx
+ movzb 24*64(%esi,%eax),%ebx
+ movzb 25*64(%esi,%eax),%ebx
+
+ movzb 32*64(%esi,%eax),%ebx
+ movzb 33*64(%esi,%eax),%ebx
+ movzb 40*64(%esi,%eax),%ebx
+ movzb 41*64(%esi,%eax),%ebx
+
+ movzb 48*64(%esi,%eax),%ebx
+ movzb 49*64(%esi,%eax),%ebx
+ movzb 56*64(%esi,%eax),%ebx
+ movzb 57*64(%esi,%eax),%ebx
+
+ subl $-128,%eax // next slice of page (adding 128 w 8-bit immediate)
+ testl $512,%eax // done with this page?
+ jz LTouchLoop // no, next of four slices
+ addl $(4096-512),%eax // move on to next page
+ cmpl %eax,%edx // done with this chunk?
+ jnz LTouchLoop // no, do next page
+
+// The chunk has been pre-fetched, now copy it using non-temporal stores.
+// There are two copy loops, depending on whether the source is 16-byte aligned
+// or not.
+
+ addl %edx,%esi // increment ptrs by chunk length
+ addl %edx,%edi
+ subl %edx,%ecx // adjust remaining length
+ negl %edx // prepare loop index (counts up to 0)
+ testl $15,%esi // is source 16-byte aligned?
+ jnz LVeryLongUnaligned // source is not aligned
+ jmp LVeryLongAligned
+
+ .align 4,0x90 // 16-byte align inner loops
+LVeryLongAligned: // aligned loop over 128-bytes
+ movdqa (%esi,%edx),%xmm0
+ movdqa 16(%esi,%edx),%xmm1
+ movdqa 32(%esi,%edx),%xmm2
+ movdqa 48(%esi,%edx),%xmm3
+ movdqa 64(%esi,%edx),%xmm4
+ movdqa 80(%esi,%edx),%xmm5
+ movdqa 96(%esi,%edx),%xmm6
+ movdqa 112(%esi,%edx),%xmm7
+
+ movntdq %xmm0,(%edi,%edx)
+ movntdq %xmm1,16(%edi,%edx)
+ movntdq %xmm2,32(%edi,%edx)
+ movntdq %xmm3,48(%edi,%edx)
+ movntdq %xmm4,64(%edi,%edx)
+ movntdq %xmm5,80(%edi,%edx)
+ movntdq %xmm6,96(%edi,%edx)
+ movntdq %xmm7,112(%edi,%edx)
+
+ subl $-128,%edx // add 128 with an 8-bit immediate
+ jnz LVeryLongAligned
+ jmp LVeryLongChunkEnd
+
+ .align 4,0x90 // 16-byte align inner loops
+LVeryLongUnaligned: // unaligned loop over 128-bytes
+ movdqu (%esi,%edx),%xmm0
+ movdqu 16(%esi,%edx),%xmm1
+ movdqu 32(%esi,%edx),%xmm2
+ movdqu 48(%esi,%edx),%xmm3
+ movdqu 64(%esi,%edx),%xmm4
+ movdqu 80(%esi,%edx),%xmm5
+ movdqu 96(%esi,%edx),%xmm6
+ movdqu 112(%esi,%edx),%xmm7
+
+ movntdq %xmm0,(%edi,%edx)
+ movntdq %xmm1,16(%edi,%edx)
+ movntdq %xmm2,32(%edi,%edx)
+ movntdq %xmm3,48(%edi,%edx)
+ movntdq %xmm4,64(%edi,%edx)
+ movntdq %xmm5,80(%edi,%edx)
+ movntdq %xmm6,96(%edi,%edx)
+ movntdq %xmm7,112(%edi,%edx)
+
+ subl $-128,%edx // add 128 with an 8-bit immediate
+ jnz LVeryLongUnaligned
+
+LVeryLongChunkEnd:
+ cmpl $4096,%ecx // at least another page to go?
+ jae LBigChunkLoop // yes
+
+// Done. Call memcpy() again to handle the 0-4095 bytes at the end.
+
+ sfence // required by non-temporal stores
+ testl %ecx,%ecx // anything left to copy?
+ jz 1f
+ pushl %ecx // arg3 - #bytes to align destination (1..63)
+ pushl %esi // arg2 - source
+ pushl %edi // arg1 - dest
+ call _memcpy // align the destination
+ addl $12,%esp // pop off arguments
+1:
+ popl %ebx
+ popl %edi
+ popl %esi
+ popl %ebp
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memcpy, sse42)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memcpy, sse3x)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memcpy, sse2)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memcpy, scalar)
+
+static const platfunc_descriptor *memcpy_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(memcpy, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memcpy, sse3x),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memcpy, sse2),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memcpy, scalar),
+ 0
+};
+
+void *memcpy_chooser() __asm__("_memcpy");
+void *memcpy_chooser() {
+ __asm__(".desc _memcpy, 0x100");
+ return find_platform_function((const platfunc_descriptor **) memcpy_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
- *
- * File: libc/i386/ansi/memcpy.c
- * Author: Bruce Martin, NeXT Computer, Inc.
- *
- * HISTORY
- * 24-Nov-92 Derek B Clegg (dclegg@next.com)
- * Created for m98k.
- */
-#define MEMCOPY
-#include "bcopy.s"
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memmove, sse42)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memmove, sse3x)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memmove, sse2)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memmove, scalar)
+
+static const platfunc_descriptor *memmove_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(memmove, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memmove, sse3x),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memmove, sse2),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memmove, scalar),
+ 0
+};
+
+void *memmove_chooser() __asm__("_memmove");
+void *memmove_chooser() {
+ __asm__(".desc _memmove, 0x100");
+ return find_platform_function((const platfunc_descriptor **) memmove_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
- *
- * File: libc/i386/ansi/memmove.c
- * Author: Bruce Martin, NeXT Computer, Inc.
- *
- * HISTORY
- * 24-Nov-92 Derek B Clegg (dclegg@next.com)
- * Created for m98k.
- */
-#define MEMMOVE
-#include "bcopy.s"
* void memset_pattern16(void *b, const void *c16, size_t len);
*
* Calls of memset() with c==0 are routed to the bzero() routine. Most of the
- * others go to _COMM_PAGE_MEMSET_PATTERN, which is entered as follows:
+ * others go to _memset_pattern, which is entered as follows:
* %edi = ptr to memory to set (aligned)
* %edx = length (which can be short, though we bias in favor of long operands)
* %xmm0 = the pattern to store
andl $0xFF,%eax // (c==0) ?
jnz LNonzero // not a bzero
- movl $(_COMM_PAGE_BZERO),%eax// map memset(p,0,n) into bzero(p,n)
movl %edx,8(%esp) // put count where bzero() expects it
- jmp *%eax // enter commpage
+ jmp _bzero // enter _bzero
// Handle memset of a nonzero value.
dec %ecx
jnz 1b
2: // ptr aligned, length long enough to justify
- movl $(_COMM_PAGE_MEMSET_PATTERN),%eax
- call *%eax // call commpage to do the heavy lifting
+ call _memset_pattern // call commpage to do the heavy lifting
movl 12(%esp),%eax // get return value (ie, original ptr)
popl %esi
popl %edi
// Ptr is aligned if practical, we're ready to call commpage to do the heavy lifting.
LReady:
- movl $(_COMM_PAGE_MEMSET_PATTERN),%eax
- call *%eax // call commpage to do the heavy lifting
+ call _memset_pattern // call commpage to do the heavy lifting
popl %esi
popl %edi
ret
--- /dev/null
+/*
+ * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/* The common path for nonzero memset and the memset_pattern routines,
+ * tuned for Pentium-M class processors with SSE2 and 64-byte cache lines.
+ * This is used by the following functions:
+ *
+ * void *memset(void *b, int c, size_t len); // when c!=0
+ * void memset_pattern4(void *b, const void *c4, size_t len);
+ * void memset_pattern8(void *b, const void *c8, size_t len);
+ * void memset_pattern16(void *b, const void *c16, size_t len);
+ *
+ * Note bzero() and memset() of 0 are handled separately.
+ */
+
+#define kShort 63
+#define kVeryLong (1024*1024)
+
+// Initial entry from Libc with parameters passed in registers. Although we
+// correctly handle misaligned ptrs and short operands, they are inefficient.
+// Therefore our caller should filter out short operands and exploit local
+// knowledge (ie, original pattern length) to align the ptr if possible.
+// When called, we expect:
+// %edi = ptr to memory to set (not necessarily aligned)
+// %edx = length (may be short or even 0)
+// %xmm0 = the pattern to store
+// Return conditions:
+// %eax, %edi, %esi, %ecx, and %edx all trashed
+
+ .align 5
+ .private_extern _memset_pattern
+_memset_pattern:
+ cmpl $(kShort),%edx // long enough to bother aligning?
+ ja LNotShort // yes
+ jmp LShort // no
+
+// Here for short operands or the end of long ones.
+// %edx = length
+// %edi = ptr (may not be not aligned)
+// %xmm0 = pattern
+
+LUnalignedStore16:
+ movdqu %xmm0,(%edi) // stuff in another 16 bytes
+ subl $16,%edx
+ addl $16,%edi
+LShort:
+ cmpl $16,%edx // room for another vector?
+ jge LUnalignedStore16 // yes
+LLessThan16: // here at end of copy with < 16 bytes remaining
+ test $8,%dl // 8-byte store required?
+ jz 2f // no
+ movq %xmm0,(%edi) // pack in 8 low bytes
+ psrldq $8,%xmm0 // then shift vector down 8 bytes
+ addl $8,%edi
+2:
+ test $4,%dl // 4-byte store required?
+ jz 3f // no
+ movd %xmm0,(%edi) // pack in 4 low bytes
+ psrldq $4,%xmm0 // then shift vector down 4 bytes
+ addl $4,%edi
+3:
+ andl $3,%edx // more to go?
+ jz 5f // no
+ movd %xmm0,%eax // move remainders out into %eax
+4: // loop on up to three bytes
+ movb %al,(%edi) // pack in next byte
+ shrl $8,%eax // shift next byte into position
+ inc %edi
+ dec %edx
+ jnz 4b
+5: ret
+
+// Long enough to justify aligning ptr. Note that we have to rotate the
+// pattern to account for any alignment. We do this by doing two unaligned
+// stores, and then an aligned load from the middle of the two stores.
+// This will stall on store forwarding alignment mismatch, and the unaligned
+// stores can be pretty slow too, but the alternatives aren't any better.
+// Fortunately, in most cases our caller has already aligned the ptr.
+// %edx = length (> kShort)
+// %edi = ptr (may not be aligned)
+// %xmm0 = pattern
+
+LNotShort:
+ movl %edi,%ecx // copy dest ptr
+ negl %ecx
+ andl $15,%ecx // mask down to #bytes to 16-byte align
+ jz LAligned // skip if already aligned
+ movdqu %xmm0,(%edi) // store 16 unaligned bytes
+ movdqu %xmm0,16(%edi) // and 16 more, to be sure we have an aligned chunk
+ addl %ecx,%edi // now point to the aligned chunk
+ subl %ecx,%edx // adjust remaining count
+ movdqa (%edi),%xmm0 // get the rotated pattern (probably stalling)
+ addl $16,%edi // skip past the aligned chunk
+ subl $16,%edx
+
+// Set up for 64-byte loops.
+// %edx = length remaining
+// %edi = ptr (aligned)
+// %xmm0 = rotated pattern
+
+LAligned:
+ movl %edx,%ecx // copy length remaining
+ andl $63,%edx // mask down to residual length (0..63)
+ andl $-64,%ecx // %ecx <- #bytes we will zero in by-64 loop
+ jz LNoMoreChunks // no 64-byte chunks
+ addl %ecx,%edi // increment ptr by length to move
+ cmpl $(kVeryLong),%ecx // long enough to justify non-temporal stores?
+ jge LVeryLong // yes
+ negl %ecx // negate length to move
+ jmp 1f
+
+// Loop over 64-byte chunks, storing into cache.
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movdqa %xmm0,(%edi,%ecx)
+ movdqa %xmm0,16(%edi,%ecx)
+ movdqa %xmm0,32(%edi,%ecx)
+ movdqa %xmm0,48(%edi,%ecx)
+ addl $64,%ecx
+ jne 1b
+
+ jmp LNoMoreChunks
+
+// Very long operands: use non-temporal stores to bypass cache.
+
+LVeryLong:
+ negl %ecx // negate length to move
+ jmp 1f
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movntdq %xmm0,(%edi,%ecx)
+ movntdq %xmm0,16(%edi,%ecx)
+ movntdq %xmm0,32(%edi,%ecx)
+ movntdq %xmm0,48(%edi,%ecx)
+ addl $64,%ecx
+ jne 1b
+
+ sfence // required by non-temporal stores
+ jmp LNoMoreChunks
+
+// Handle leftovers: loop by 16.
+// %edx = length remaining (<64)
+// %edi = ptr (aligned)
+// %xmm0 = rotated pattern
+
+LLoopBy16:
+ movdqa %xmm0,(%edi) // pack in 16 more bytes
+ subl $16,%edx // decrement count
+ addl $16,%edi // increment ptr
+LNoMoreChunks:
+ cmpl $16,%edx // more to go?
+ jge LLoopBy16 // yes
+ jmp LLessThan16 // handle up to 15 remaining bytes
LZeroBuffer:
pushl %ecx // remaining buffer size
pushl %edi // ptr to 1st unstored byte
- movl $(_COMM_PAGE_BZERO),%eax
- call *%eax
+ call _bzero
addl $8,%esp // pop off the arguments
LDone:
AINC+= -I${.CURDIR}/i386/sys
MDSRCS+= OSAtomic.s \
- i386_gettimeofday.s \
+ atomic.c \
+ i386_gettimeofday_asm.s \
+ mach_absolute_time.c \
+ mach_absolute_time_asm.s \
_setjmp.s \
setjmp.s \
- _sigtramp.s
+ _sigtramp.s \
+ spinlocks_asm.s \
+ spinlocks.s
-MDCOPYFILES+= ${.CURDIR}/Platforms/${RC_TARGET_CONFIG}/i386/libc.syscall.i386
+DYLDSRCS += \
+ OSAtomic.s \
+ i386_gettimeofday_asm.s \
+ mach_absolute_time_asm.s \
+ spinlocks_asm.s
*/
#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
-#define DECLARE(x) \
-.align 2, 0x90 ; \
-.globl x ; \
-.globl x ## Barrier ; \
-x: ; \
-x ## Barrier:
-
-.text
-
-DECLARE(_OSAtomicAnd32)
- movl 8(%esp), %ecx
- movl (%ecx), %eax
-1:
- movl 4(%esp), %edx
- andl %eax, %edx
- call *_COMM_PAGE_COMPARE_AND_SWAP32
- jnz 1b
- movl %edx, %eax
+#define ATOMIC_UP 0
+#define ATOMIC_MP 1
+#define ATOMIC_RET_ORIG 0
+#define ATOMIC_RET_NEW 1
+
+// compare and exchange 32-bit
+// xchg32 <new> <dst> <mp>
+.macro xchg32
+ .if $2 == ATOMIC_MP
+ lock
+ .endif
+ cmpxchgl $0, ($1)
+.endm
+
+// compare and exchange 64-bit
+// xchg64 <dst> <mp>
+.macro xchg64
+ .if $1 == ATOMIC_MP
+ lock
+ .endif
+ cmpxchg8b ($0)
+.endm
+
+
+// int32_t OSAtomicAdd32(int32_t theAmount, volatile int32_t *theValue);
+#define ATOMIC_ARITHMETIC(instr, orig, mp) \
+ movl 8(%esp), %ecx /* load 2nd arg ptr into ecx */ ;\
+ movl (%ecx), %eax /* load contents of ecx into eax */ ;\
+1: movl 4(%esp), %edx /* load 1st arg into edx */ ;\
+ instr %eax, %edx /* do the operation */ ;\
+ xchg32 %edx, %ecx, mp /* old in %eax, new in %edx, exchange into %ecx */ ;\
+ jnz 1b /* go back if we failed to exchange */ ;\
+ .if orig == ATOMIC_RET_NEW ;\
+ movl %edx, %eax /* return new value */ ;\
+ .endif
+
+// bool OSAtomicTestAndSet(uint32_t n, volatile void *theAddress);
+#define ATOMIC_BIT_OP(instr, mp) \
+ movl 4(%esp), %eax ;\
+ movl 8(%esp), %edx ;\
+ shldl $3,%edx,%ecx /* save top 3 bits of address in %ecx */ ;\
+ shll $3,%edx ;\
+ xorl $7,%eax /* bit position is numbered big endian so convert to little endian */ ;\
+ addl %eax,%edx /* generate bit address */ ;\
+ adcl $0,%ecx /* handle carry out of lower half of address */ ;\
+ movl %edx,%eax /* copy lower half of bit address */ ;\
+ andl $31,%eax /* keep bit offset in range 0..31 */ ;\
+ xorl %eax,%edx /* 4-byte align address */ ;\
+ shrdl $3,%ecx,%edx /* restore 32-bit byte address in %edx */ ;\
+ .if mp == ATOMIC_MP ;\
+ lock ;\
+ .endif ;\
+ instr %eax, (%edx) ;\
+ setc %al ;\
+ movzbl %al,%eax // widen in case caller assumes we return an int
+
+// int64_t OSAtomicAdd64(int64_t theAmount, volatile int64_t *theValue);
+#define ATOMIC_ADD64(mp) \
+ pushl %ebx ;\
+ pushl %esi ;\
+ movl 20(%esp), %esi ;\
+ movl 0(%esi), %eax ;\
+ movl 4(%esi), %edx ;\
+1: movl 12(%esp), %ebx ;\
+ movl 16(%esp), %ecx ;\
+ addl %eax, %ebx ;\
+ adcl %edx, %ecx ;\
+ xchg64 %esi, mp ;\
+ jnz 1b ;\
+ movl %ebx, %eax ;\
+ movl %ecx, %edx ;\
+ popl %esi ;\
+ popl %ebx
+
+ .text
+
+PLATFUNC_FUNCTION_START(OSAtomicAnd32, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAnd32Barrier, up, 32, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_NEW, ATOMIC_UP)
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32Barrier, mp, 32, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_NEW, ATOMIC_MP)
+ ret
+
+PLATFUNC_FUNCTION_START(OSAtomicOr32, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicOr32Barrier, up, 32, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_NEW, ATOMIC_UP)
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32Barrier, mp, 32, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_NEW, ATOMIC_MP)
ret
-DECLARE(_OSAtomicOr32)
- movl 8(%esp), %ecx
- movl (%ecx), %eax
-1:
- movl 4(%esp), %edx
- orl %eax, %edx
- call *_COMM_PAGE_COMPARE_AND_SWAP32
- jnz 1b
- movl %edx, %eax
+PLATFUNC_FUNCTION_START(OSAtomicXor32, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicXor32Barrier, up, 32, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_NEW, ATOMIC_UP)
ret
-DECLARE(_OSAtomicXor32)
- movl 8(%esp), %ecx
- movl (%ecx), %eax
-1:
- movl 4(%esp), %edx
- xorl %eax, %edx
- call *_COMM_PAGE_COMPARE_AND_SWAP32
- jnz 1b
- movl %edx, %eax
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32Barrier, mp, 32, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_NEW, ATOMIC_MP)
ret
-DECLARE(_OSAtomicAnd32Orig)
- movl 8(%esp), %ecx
- movl (%ecx), %eax
-1:
- movl 4(%esp), %edx
- andl %eax, %edx
- call *_COMM_PAGE_COMPARE_AND_SWAP32
- jnz 1b
+PLATFUNC_FUNCTION_START(OSAtomicAnd32Orig, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAnd32OrigBarrier, up, 32, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_ORIG, ATOMIC_UP)
ret
-DECLARE(_OSAtomicOr32Orig)
- movl 8(%esp), %ecx
- movl (%ecx), %eax
-1:
- movl 4(%esp), %edx
- orl %eax, %edx
- call *_COMM_PAGE_COMPARE_AND_SWAP32
- jnz 1b
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32Orig, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32OrigBarrier, mp, 32, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_ORIG, ATOMIC_MP)
ret
-DECLARE(_OSAtomicXor32Orig)
- movl 8(%esp), %ecx
- movl (%ecx), %eax
-1:
- movl 4(%esp), %edx
- xorl %eax, %edx
- call *_COMM_PAGE_COMPARE_AND_SWAP32
- jnz 1b
+PLATFUNC_FUNCTION_START(OSAtomicOr32Orig, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicOr32OrigBarrier, up, 32, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_ORIG, ATOMIC_UP)
ret
-DECLARE(_OSAtomicCompareAndSwapPtr)
-DECLARE(_OSAtomicCompareAndSwapInt)
-DECLARE(_OSAtomicCompareAndSwapLong)
-DECLARE(_OSAtomicCompareAndSwap32)
- movl 4(%esp), %eax
- movl 8(%esp), %edx
- movl 12(%esp), %ecx
- call *_COMM_PAGE_COMPARE_AND_SWAP32
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32Orig, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32OrigBarrier, mp, 32, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_ORIG, ATOMIC_MP)
+ ret
+
+PLATFUNC_FUNCTION_START(OSAtomicXor32Orig, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicXor32OrigBarrier, up, 32, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_ORIG, ATOMIC_UP)
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32Orig, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32OrigBarrier, mp, 32, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_ORIG, ATOMIC_MP)
+ ret
+
+// bool OSAtomicCompareAndSwapInt(int oldValue, int newValue, volatile int *theValue);
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapPtr, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapPtrBarrier, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapInt, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapIntBarrier, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapLong, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapLongBarrier, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap32, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap32Barrier, up, 32, 2)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+ movl 12(%esp), %ecx
+ xchg32 %edx, %ecx, ATOMIC_UP
sete %al
movzbl %al,%eax // widen in case caller assumes we return an int
ret
-DECLARE(_OSAtomicCompareAndSwap64)
- pushl %ebx
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapPtr, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapPtrBarrier, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapInt, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapIntBarrier, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapLong, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapLongBarrier, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap32, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap32Barrier, mp, 32, 2)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+ movl 12(%esp), %ecx
+ xchg32 %edx, %ecx, ATOMIC_MP
+ sete %al
+ movzbl %al,%eax // widen in case caller assumes we return an int
+ ret
+
+// bool OSAtomicCompareAndSwap64(int64_t oldValue, int64_t newValue, volatile int64_t *theValue);
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap64, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap64Barrier, up, 32, 2)
+ pushl %ebx // push out spare stuff for space
pushl %esi
- movl 12(%esp), %eax
+ movl 12(%esp), %eax // load in 1st 64-bit parameter
movl 16(%esp), %edx
- movl 20(%esp), %ebx
+ movl 20(%esp), %ebx // load in 2nd 64-bit parameter
movl 24(%esp), %ecx
- movl 28(%esp), %esi
- call *_COMM_PAGE_COMPARE_AND_SWAP64
+ movl 28(%esp), %esi // laod in destination address
+ xchg64 %esi, ATOMIC_UP // compare and swap 64-bit
sete %al
movzbl %al,%eax // widen in case caller assumes we return an int
popl %esi
popl %ebx
ret
-DECLARE(_OSAtomicAdd32)
- movl 4(%esp), %eax
- movl 8(%esp), %edx
- movl %eax, %ecx
- call *_COMM_PAGE_ATOMIC_ADD32
- addl %ecx, %eax
- ret
-
-DECLARE(_OSAtomicAdd64)
- pushl %ebx
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap64, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap64Barrier, mp, 32, 2)
+ pushl %ebx // push out spare stuff for space
pushl %esi
- movl 20(%esp), %esi
- movl 0(%esi), %eax
- movl 4(%esi), %edx
-1: movl 12(%esp), %ebx
- movl 16(%esp), %ecx
- addl %eax, %ebx
- adcl %edx, %ecx
- call *_COMM_PAGE_COMPARE_AND_SWAP64
- jnz 1b
- movl %ebx, %eax
- movl %ecx, %edx
+ movl 12(%esp), %eax // load in 1st 64-bit parameter
+ movl 16(%esp), %edx
+ movl 20(%esp), %ebx // load in 2nd 64-bit parameter
+ movl 24(%esp), %ecx
+ movl 28(%esp), %esi // laod in destination address
+ xchg64 %esi, ATOMIC_MP // compare and swap 64-bit
+ sete %al
+ movzbl %al,%eax // widen in case caller assumes we return an int
popl %esi
- popl %ebx
+ popl %ebx
ret
-DECLARE(_OSAtomicTestAndSet)
+PLATFUNC_FUNCTION_START(OSAtomicAdd32, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAdd32Barrier, up, 32, 2)
movl 4(%esp), %eax
movl 8(%esp), %edx
movl %eax, %ecx
- andl $-8, %ecx
- notl %eax
- andl $7, %eax
- orl %ecx, %eax
- call *_COMM_PAGE_BTS
- setc %al
- movzbl %al,%eax // widen in case caller assumes we return an int
+ xaddl %eax, (%edx)
+ addl %ecx, %eax
ret
-DECLARE(_OSAtomicTestAndClear)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd32, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd32Barrier, mp, 32, 2)
movl 4(%esp), %eax
movl 8(%esp), %edx
movl %eax, %ecx
- andl $-8, %ecx
- notl %eax
- andl $7, %eax
- orl %ecx, %eax
- call *_COMM_PAGE_BTC
- setc %al
- movzbl %al,%eax // widen in case caller assumes we return an int
+ lock
+ xaddl %eax, (%edx)
+ addl %ecx, %eax
ret
- .align 2, 0x90
- .globl _OSSpinLockTry
- .globl __spin_lock_try
-_OSSpinLockTry:
-__spin_lock_try:
- movl $(_COMM_PAGE_SPINLOCK_TRY), %eax
- jmpl *%eax
-
- .align 2, 0x90
- .globl _OSSpinLockLock
- .globl _spin_lock
- .globl __spin_lock
-_OSSpinLockLock:
-_spin_lock:
-__spin_lock:
- movl $(_COMM_PAGE_SPINLOCK_LOCK), %eax
- jmpl *%eax
-
- .align 2, 0x90
- .globl _OSSpinLockUnlock
- .globl _spin_unlock
- .globl __spin_unlock
-_OSSpinLockUnlock:
-_spin_unlock:
-__spin_unlock:
- movl 4(%esp), %eax
- movl $0, (%eax)
+PLATFUNC_FUNCTION_START(OSAtomicAdd64, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAdd64Barrier, up, 32, 2)
+ ATOMIC_ADD64(ATOMIC_UP)
ret
- .align 2, 0x90
- .globl _OSMemoryBarrier
-_OSMemoryBarrier:
- movl $(_COMM_PAGE_MEMORY_BARRIER), %eax
- jmpl *%eax
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd64, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd64Barrier, mp, 32, 2)
+ ATOMIC_ADD64(ATOMIC_MP)
+ ret
-/*
- * typedef volatile struct {
- * void *opaque1; <-- ptr to 1st queue element or null
- * long opaque2; <-- generation count
- * } OSQueueHead;
- *
- * void OSAtomicEnqueue( OSQueueHead *list, void *new, size_t offset);
- */
- .align 2
- .globl _OSAtomicEnqueue
-_OSAtomicEnqueue:
+PLATFUNC_FUNCTION_START(OSAtomicTestAndSet, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicTestAndSetBarrier, up, 32, 2)
+ ATOMIC_BIT_OP(btsl, ATOMIC_UP)
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndSet, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndSetBarrier, mp, 32, 2)
+ ATOMIC_BIT_OP(btsl, ATOMIC_MP)
+ ret
+
+PLATFUNC_FUNCTION_START(OSAtomicTestAndClear, up, 32, 2)
+PLATFUNC_FUNCTION_START(OSAtomicTestAndClearBarrier, up, 32, 2)
+ ATOMIC_BIT_OP(btrl, ATOMIC_UP)
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndClear, mp, 32, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndClearBarrier, mp, 32, 2)
+ ATOMIC_BIT_OP(btrl, ATOMIC_MP)
+ ret
+
+// OSMemoryBarrier()
+// These are used both in 32 and 64-bit mode. We use a fence even on UP
+// machines, so this function can be used with nontemporal stores.
+
+PLATFUNC_FUNCTION_START_GENERIC(OSMemoryBarrier, all, 32, 4)
+ lock
+ addl $0,(%esp)
+ ret
+PLATFUNC_DESCRIPTOR(OSMemoryBarrier,all,0,kHasSSE2);
+
+PLATFUNC_FUNCTION_START(OSMemoryBarrier, sse2, 32, 4)
+ mfence
+ ret
+PLATFUNC_DESCRIPTOR(OSMemoryBarrier,sse2,kHasSSE2,0);
+
+ /*
+ * typedef volatile struct {
+ * void *opaque1; <-- ptr to 1st queue element or null
+ * long opaque2; <-- generation count
+ * } OSQueueHead;
+ *
+ * void OSAtomicEnqueue( OSQueueHead *list, void *new, size_t offset);
+ */
+PLATFUNC_FUNCTION_START(OSAtomicEnqueue, up, 32, 2)
pushl %edi
pushl %esi
pushl %ebx
movl 24(%esp),%esi // %esi == offset
movl (%edi),%eax // %eax == ptr to 1st element in Q
movl 4(%edi),%edx // %edx == current generation count
-1:
- movl %eax,(%ebx,%esi)// link to old list head from new element
+1: movl %eax,(%ebx,%esi)// link to old list head from new element
movl %edx,%ecx
incl %ecx // increment generation count
- lock // always lock for now...
- cmpxchg8b (%edi) // ...push on new element
+ xchg64 %edi, ATOMIC_UP // ...push on new element
jnz 1b
popl %ebx
popl %esi
popl %edi
ret
-
-
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicEnqueue, mp, 32, 2)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ movl 16(%esp),%edi // %edi == ptr to list head
+ movl 20(%esp),%ebx // %ebx == new
+ movl 24(%esp),%esi // %esi == offset
+ movl (%edi),%eax // %eax == ptr to 1st element in Q
+ movl 4(%edi),%edx // %edx == current generation count
+1: movl %eax,(%ebx,%esi)// link to old list head from new element
+ movl %edx,%ecx
+ incl %ecx // increment generation count
+ xchg64 %edi, ATOMIC_MP // ...push on new element
+ jnz 1b
+ popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
/* void* OSAtomicDequeue( OSQueueHead *list, size_t offset); */
- .align 2
- .globl _OSAtomicDequeue
-_OSAtomicDequeue:
+PLATFUNC_FUNCTION_START(OSAtomicDequeue, up, 32, 2)
pushl %edi
pushl %esi
pushl %ebx
movl 20(%esp),%esi // %esi == offset
movl (%edi),%eax // %eax == ptr to 1st element in Q
movl 4(%edi),%edx // %edx == current generation count
-1:
- testl %eax,%eax // list empty?
+1: testl %eax,%eax // list empty?
jz 2f // yes
movl (%eax,%esi),%ebx // point to 2nd in Q
movl %edx,%ecx
incl %ecx // increment generation count
- lock // always lock for now...
- cmpxchg8b (%edi) // ...pop off 1st element
+ xchg64 %edi, ATOMIC_UP // ...pop off 1st element
jnz 1b
-2:
- popl %ebx
+2: popl %ebx
+ popl %esi
+ popl %edi
+ ret // ptr to 1st element in Q still in %eax
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicDequeue, mp, 32, 2)
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ movl 16(%esp),%edi // %edi == ptr to list head
+ movl 20(%esp),%esi // %esi == offset
+ movl (%edi),%eax // %eax == ptr to 1st element in Q
+ movl 4(%edi),%edx // %edx == current generation count
+1: testl %eax,%eax // list empty?
+ jz 2f // yes
+ movl (%eax,%esi),%ebx // point to 2nd in Q
+ movl %edx,%ecx
+ incl %ecx // increment generation count
+ xchg64 %edi, ATOMIC_MP // ...pop off 1st element
+ jnz 1b
+2: popl %ebx
+ popl %esi
+ popl %edi
+ ret // ptr to 1st element in Q still in %eax
+
+/*
+ * typedef volatile struct {
+ * void *opaque1; <-- ptr to first queue element or null
+ * void *opaque2; <-- ptr to last queue element or null
+ * int opaque3; <-- spinlock
+ * } OSFifoQueueHead;
+ *
+ * void OSAtomicFifoEnqueue( OSFifoQueueHead *list, void *new, size_t offset);
+ */
+ .align 2
+ .globl _OSAtomicFifoEnqueue
+_OSAtomicFifoEnqueue:
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ xorl %ebx,%ebx // clear "preemption pending" flag
+ movl 16(%esp),%edi // %edi == ptr to list head
+ movl 20(%esp),%esi // %esi == new
+ movl 24(%esp),%edx // %edx == offset
+ movl $(_COMM_PAGE_PFZ_ENQUEUE), %ecx
+ call *%ecx
+ testl %ebx,%ebx // pending preemption?
+ jz 1f
+ call _preempt
+1: popl %ebx
+ popl %esi
+ popl %edi
+ ret
+
+/* void* OSAtomicFifoDequeue( OSFifoQueueHead *list, size_t offset); */
+ .align 2
+ .globl _OSAtomicFifoDequeue
+_OSAtomicFifoDequeue:
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ xorl %ebx,%ebx // clear "preemption pending" flag
+ movl 16(%esp),%edi // %edi == ptr to list head
+ movl 20(%esp),%edx // %edx == offset
+ movl $(_COMM_PAGE_PFZ_DEQUEUE), %ecx
+ call *%ecx
+ testl %ebx,%ebx // pending preemption?
+ jz 1f
+ pushl %eax // save return value across sysenter
+ call _preempt
+ popl %eax
+1: popl %ebx
popl %esi
popl %edi
ret // ptr to 1st element in Q still in %eax
+// Local Variables:
+// tab-width: 8
+// End:
#define JB_FS 64
#define JB_GS 68
-#define SAVE_SEG_REGS 1
-
LEAF(__setjmp, 0)
movl 4(%esp), %ecx // jmp_buf (struct sigcontext *)
movl (%esp), %eax
movl %eax, JB_EIP(%ecx)
// ESP is set to the frame return address plus 4
- movl %esp, %eax
- addl $4, %eax
+ leal 4(%esp), %eax
movl %eax, JB_ESP(%ecx)
-#if SAVE_SEG_REGS
- // segment registers
- mov %ss, JB_SS(%ecx)
- mov %cs, JB_CS(%ecx)
- mov %ds, JB_DS(%ecx)
- mov %es, JB_ES(%ecx)
- mov %fs, JB_FS(%ecx)
- mov %gs, JB_GS(%ecx)
-#endif
-
- // save eflags - you can't use movl
- pushf
- popl %eax
- movl %eax, JB_EFLAGS(%ecx)
-
// return 0
xorl %eax, %eax
ret
LEAF(__longjmp, 0)
- fninit // reset FP coprocessor
-
+ fninit // Clear all FP exceptions
movl 4(%esp), %ecx // jmp_buf (struct sigcontext *)
movl 8(%esp), %eax // return value
testl %eax, %eax
jnz 1f
- incl %eax
+ incl %eax
// general registers
1: movl JB_EBX(%ecx), %ebx
movl JB_EDI(%ecx), %edi
movl JB_EBP(%ecx), %ebp
movl JB_ESP(%ecx), %esp
+
fldcw JB_FPCW(%ecx) // Restore FP control word
ldmxcsr JB_MXCSR(%ecx) // Restore the MXCSR
-#if SAVE_SEG_REGS
- // segment registers
- mov JB_SS(%ecx), %ss
- // mov JB_CS(%ecx), %cs // can't set cs?
- mov JB_DS(%ecx), %ds
- mov JB_ES(%ecx), %es
- mov JB_FS(%ecx), %fs
- mov JB_GS(%ecx), %gs
-#endif
-
- // eflags
- pushl JB_EFLAGS(%ecx)
- popf
-
+ cld // Make sure DF is reset
jmp *JB_EIP(%ecx)
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
.text
.align 4,0x90
__sigtramp:
+Lstart:
/* Although this routine does not need any stack frame, various parts
of the OS can't analyse the stack without them. */
pushl %ebp
movl %esi, 8(%esp)
movl %eax, 4(%esp)
movl %edx, (%esp)
-Lcall_start:
call *%ecx
-Lcall_end:
#if defined(__DYNAMIC__)
decl ___in_sigtramp-"L00000000001$pb"(%ebx)
#endif
movl $ UC_FLAVOR, 8(%esp)
movl $ SYS_sigreturn, %eax
int $0x80
+Lend:
/* DWARF unwind table #defines. */
#define DW_CFA_advance_loc_4 0x44
.long L$set$0 # Length of Common Information Entry
LSCIE1:
.long 0 # CIE Identifier Tag
- .byte 0x3 # CIE Version
- .ascii "zR\0" # CIE Augmentation
+ .byte 0x1 # CIE Version
+ .ascii "zRS\0" # CIE Augmentation
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
.byte 0x7c # sleb128 -4; CIE Data Alignment Factor
.byte 0x8 # CIE RA Column
.byte 0x4 # uleb128 0x4
.byte DW_CFA_offset(8)
.byte 0x1 # uleb128 0x1
+ .byte DW_CFA_offset(8) // double DW_CFA_offset (eip, -4) tells linker to not make compact unwind
+ .byte 0x1 # uleb128 0x1
.align 2
LECIE1:
.globl _sigtramp.eh
.long L$set$1 # FDE Length
LASFDE1:
.long LASFDE1-EH_frame1 # FDE CIE offset
- .long Lcall_start-. # FDE initial location
- .set L$set$2,Lcall_end-Lcall_start
+ .long Lstart-. # FDE initial location
+ .set L$set$2,Lend-Lstart
.long L$set$2 # FDE address range
.byte 0x0 # uleb128 0x0; Augmentation size
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+#define RESOLVER_UP_MP(symbol) \
+ PLATFUNC_DESCRIPTOR(symbol, up, kUP, 0); \
+ PLATFUNC_DESCRIPTOR(symbol, mp, 0, kUP); \
+ static const platfunc_descriptor* symbol ## _platfunc_descriptors[] = { \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, mp), \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, up), \
+ 0 \
+ }; \
+ void* symbol ## _chooser() __asm__("_" #symbol); \
+ void* symbol ## _chooser() { \
+ __asm__(".symbol_resolver _" #symbol); \
+ return find_platform_function((const platfunc_descriptor**) symbol ## _platfunc_descriptors); \
+ }
+
+RESOLVER_UP_MP(OSAtomicAnd32)
+RESOLVER_UP_MP(OSAtomicAnd32Barrier)
+RESOLVER_UP_MP(OSAtomicOr32)
+RESOLVER_UP_MP(OSAtomicOr32Barrier)
+RESOLVER_UP_MP(OSAtomicXor32)
+RESOLVER_UP_MP(OSAtomicXor32Barrier)
+RESOLVER_UP_MP(OSAtomicAnd32Orig)
+RESOLVER_UP_MP(OSAtomicAnd32OrigBarrier)
+RESOLVER_UP_MP(OSAtomicOr32Orig)
+RESOLVER_UP_MP(OSAtomicOr32OrigBarrier)
+RESOLVER_UP_MP(OSAtomicXor32Orig)
+RESOLVER_UP_MP(OSAtomicXor32OrigBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapPtr)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapPtrBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapInt)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapIntBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapLong)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapLongBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap32)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap32Barrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap64)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap64Barrier)
+RESOLVER_UP_MP(OSAtomicAdd32)
+RESOLVER_UP_MP(OSAtomicAdd32Barrier)
+RESOLVER_UP_MP(OSAtomicAdd64)
+RESOLVER_UP_MP(OSAtomicAdd64Barrier)
+RESOLVER_UP_MP(OSAtomicTestAndSet)
+RESOLVER_UP_MP(OSAtomicTestAndSetBarrier)
+RESOLVER_UP_MP(OSAtomicTestAndClear)
+RESOLVER_UP_MP(OSAtomicTestAndClearBarrier)
+RESOLVER_UP_MP(OSAtomicEnqueue)
+RESOLVER_UP_MP(OSAtomicDequeue)
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(OSMemoryBarrier, all)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(OSMemoryBarrier, sse2)
+
+static const platfunc_descriptor *OSMemoryBarrier_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(OSMemoryBarrier, sse2),
+ PLATFUNC_DESCRIPTOR_REFERENCE(OSMemoryBarrier, all),
+ 0
+};
+
+void *OSMemoryBarrier_chooser() __asm__("_OSMemoryBarrier");
+void *OSMemoryBarrier_chooser() {
+ __asm__(".symbol_resolver _OSMemoryBarrier");
+ return find_platform_function((const platfunc_descriptor **) OSMemoryBarrier_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/* Copyright 1998 Apple Computer, Inc. */
-
-#include <architecture/i386/asm_help.h>
-
-#define __APPLE_API_PRIVATE
-#include <machine/cpu_capabilities.h>
-#undef __APPLE_API_PRIVATE
-
-LABEL(___commpage_gettimeofday)
- mov $ _COMM_PAGE_GETTIMEOFDAY,%eax
- jmp *%eax
--- /dev/null
+/*
+ * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+#define NSEC_PER_SEC 1000*1000*1000
+#define NSEC_PER_USEC 1000
+
+ .align 4
+ .private_extern ___commpage_gettimeofday
+___commpage_gettimeofday:
+ push %ebp
+ mov %esp,%ebp
+ push %esi
+ push %ebx
+
+0:
+ movl _COMM_PAGE_GTOD_GENERATION,%esi /* get generation (0 if disabled) */
+ testl %esi,%esi /* disabled? */
+ jz 4f
+
+ call _mach_absolute_time_direct
+
+ sub _COMM_PAGE_GTOD_NS_BASE,%eax
+ sbb _COMM_PAGE_GTOD_NS_BASE+4,%edx
+ mov _COMM_PAGE_GTOD_SEC_BASE,%ebx /* load all the data before checking generation */
+ mov $ NSEC_PER_SEC,%ecx
+
+ cmpl _COMM_PAGE_GTOD_GENERATION,%esi /* has time data changed out from under us? */
+ jne 0b
+
+ div %ecx
+ add %eax,%ebx
+
+ mov $ NSEC_PER_USEC,%ecx
+ mov %edx,%eax
+ xor %edx,%edx
+ div %ecx
+
+ mov 8(%ebp),%ecx
+ mov %ebx,(%ecx)
+ mov %eax,4(%ecx)
+ xor %eax,%eax
+
+3:
+ pop %ebx
+ pop %esi
+ pop %ebp
+ ret
+4: /* fail */
+ movl $1,%eax
+ jmp 3b
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(mach_absolute_time,fast)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(mach_absolute_time,slow)
+
+static const platfunc_descriptor *mach_absolute_time_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(mach_absolute_time,fast),
+ PLATFUNC_DESCRIPTOR_REFERENCE(mach_absolute_time,slow),
+ 0
+};
+
+void *mach_absolute_time_chooser() __asm__("_mach_absolute_time");
+void *mach_absolute_time_chooser() {
+ __asm__(".desc _mach_absolute_time, 0x100");
+ return find_platform_function((const platfunc_descriptor **) mach_absolute_time_platfunc_descriptors);
+}
--- /dev/null
+/*
+ * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+#if defined(VARIANT_DYLD)
+/* For dyld, we need to decide upon call whether to jump to fast or slow */
+ .globl _mach_absolute_time
+ .align 2, 0x90
+_mach_absolute_time:
+ movl _COMM_PAGE_CPU_CAPABILITIES, %eax
+ andl $(kSlow), %eax
+ jnz PLATFUNC_VARIANT_NAME(mach_absolute_time, slow)
+ jmp PLATFUNC_VARIANT_NAME(mach_absolute_time, fast)
+#endif
+
+/* return mach_absolute_time in %edx:%eax */
+
+PLATFUNC_FUNCTION_START(mach_absolute_time, fast, 32, 4)
+ .private_extern _mach_absolute_time_direct
+_mach_absolute_time_direct:
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %esi
+ pushl %ebx
+
+0:
+ movl _COMM_PAGE_NT_GENERATION,%esi /* get generation (0 if being changed) */
+ testl %esi,%esi /* if being updated, loop until stable */
+ jz 0b
+
+ lfence
+ rdtsc /* get TSC in %edx:%eax */
+ lfence
+
+ subl _COMM_PAGE_NT_TSC_BASE,%eax
+ sbbl _COMM_PAGE_NT_TSC_BASE+4,%edx
+
+ movl _COMM_PAGE_NT_SCALE,%ecx
+
+ movl %edx,%ebx
+ mull %ecx
+ movl %ebx,%eax
+ movl %edx,%ebx
+ mull %ecx
+ addl %ebx,%eax
+ adcl $0,%edx
+
+ addl _COMM_PAGE_NT_NS_BASE,%eax
+ adcl _COMM_PAGE_NT_NS_BASE+4,%edx
+
+ cmpl _COMM_PAGE_NT_GENERATION,%esi /* have the parameters changed? */
+ jne 0b /* yes, loop until stable */
+
+ popl %ebx
+ popl %esi
+ popl %ebp
+ ret
+PLATFUNC_DESCRIPTOR(mach_absolute_time,fast,0,kSlow)
+
+
+/* mach_absolute_time routine for machines slower than ~1Gz (SLOW_TSC_THRESHOLD) */
+PLATFUNC_FUNCTION_START(mach_absolute_time, slow, 32, 4)
+ push %ebp
+ mov %esp,%ebp
+ push %esi
+ push %edi
+ push %ebx
+
+0:
+ movl _COMM_PAGE_NT_GENERATION,%esi
+ testl %esi,%esi /* if generation is 0, data being changed */
+ jz 0b /* so loop until stable */
+
+ lfence
+ rdtsc /* get TSC in %edx:%eax */
+ lfence
+ subl _COMM_PAGE_NT_TSC_BASE,%eax
+ sbbl _COMM_PAGE_NT_TSC_BASE+4,%edx
+
+ pushl %esi /* save generation */
+ /*
+ * Do the math to convert tsc ticks to nanoseconds. We first
+ * do long multiply of 1 billion times the tsc. Then we do
+ * long division by the tsc frequency
+ */
+ mov $1000000000, %ecx /* number of nanoseconds in a second */
+ mov %edx, %ebx
+ mul %ecx
+ mov %edx, %edi
+ mov %eax, %esi
+ mov %ebx, %eax
+ mul %ecx
+ add %edi, %eax
+ adc $0, %edx /* result in edx:eax:esi */
+ mov %eax, %edi
+ mov _COMM_PAGE_NT_SHIFT,%ecx /* overloaded as the low 32 tscFreq */
+ xor %eax, %eax
+ xchg %edx, %eax
+ div %ecx
+ xor %eax, %eax
+ mov %edi, %eax
+ div %ecx
+ mov %eax, %ebx
+ mov %esi, %eax
+ div %ecx
+ mov %ebx, %edx /* result in edx:eax */
+ popl %esi /* recover generation */
+
+ add _COMM_PAGE_NT_NS_BASE,%eax
+ adc _COMM_PAGE_NT_NS_BASE+4,%edx
+
+ cmpl _COMM_PAGE_NT_GENERATION,%esi /* have the parameters changed? */
+ jne 0b /* yes, loop until stable */
+
+ pop %ebx
+ pop %edi
+ pop %esi
+ pop %ebp
+ ret /* result in edx:eax */
+PLATFUNC_DESCRIPTOR(mach_absolute_time,slow,kSlow,0)
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+#define RESOLVER_UP_MP(symbol) \
+ PLATFUNC_DESCRIPTOR_PROTOTYPE(symbol, up); \
+ PLATFUNC_DESCRIPTOR_PROTOTYPE(symbol, mp); \
+ static const platfunc_descriptor* symbol ## _platfunc_descriptors[] = { \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, mp), \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, up), \
+ 0 \
+ }; \
+ void* symbol ## _chooser() __asm__("_" #symbol); \
+ void* symbol ## _chooser() { \
+ __asm__(".symbol_resolver _" #symbol); \
+ return find_platform_function((const platfunc_descriptor**) symbol ## _platfunc_descriptors); \
+ }
+
+RESOLVER_UP_MP(OSSpinLockTry)
+RESOLVER_UP_MP(_spin_lock_try)
+RESOLVER_UP_MP(OSSpinLockLock)
+RESOLVER_UP_MP(_spin_lock)
+RESOLVER_UP_MP(spin_lock)
--- /dev/null
+/*
+ * Copyright (c) 2003-2009 Apple, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+#include <mach/i386/syscall_sw.h>
+
+
+PLATFUNC_FUNCTION_START(OSSpinLockTry, up, 32, 4)
+PLATFUNC_FUNCTION_START(_spin_lock_try, up, 32, 4)
+ movl 4(%esp), %ecx
+ xorl %eax, %eax
+ orl $-1, %edx
+ cmpxchgl %edx, (%ecx)
+ setz %dl
+ movzbl %dl, %eax
+ ret
+PLATFUNC_DESCRIPTOR(OSSpinLockTry,up,kUP,0)
+PLATFUNC_DESCRIPTOR(_spin_lock_try,up,kUP,0)
+
+PLATFUNC_FUNCTION_START_GENERIC(OSSpinLockTry, mp, 32, 4)
+PLATFUNC_FUNCTION_START_GENERIC(_spin_lock_try, mp, 32, 4)
+ movl 4(%esp), %ecx
+ xorl %eax, %eax
+ orl $-1, %edx
+ lock
+ cmpxchgl %edx, (%ecx)
+ setz %dl
+ movzbl %dl, %eax
+ ret
+PLATFUNC_DESCRIPTOR(OSSpinLockTry,mp,0,kUP)
+PLATFUNC_DESCRIPTOR(_spin_lock_try,mp,0,kUP)
+
+
+PLATFUNC_FUNCTION_START(spin_lock, up, 32, 4)
+PLATFUNC_FUNCTION_START(OSSpinLockLock, up, 32, 4)
+PLATFUNC_FUNCTION_START(_spin_lock, up, 32, 4)
+Lspin_lock_up:
+ movl 4(%esp), %ecx
+ xorl %eax, %eax
+ orl $-1, %edx
+ cmpxchgl %edx, (%ecx)
+ jnz 1f
+ ret
+1:
+ /* failed to get lock so relinquish the processor immediately on UP */
+ pushl $1 /* 1 ms */
+ pushl $1 /* SWITCH_OPTION_DEPRESS */
+ pushl $0 /* THREAD_NULL */
+ pushl $0 /* push dummy stack ret addr */
+ movl $-61,%eax /* SYSCALL_THREAD_SWITCH */
+ int $(MACH_INT)
+ addl $16, %esp /* adjust stack*/
+ jmp Lspin_lock_up
+PLATFUNC_DESCRIPTOR(spin_lock,up,kUP,0)
+PLATFUNC_DESCRIPTOR(OSSpinLockLock,up,kUP,0)
+PLATFUNC_DESCRIPTOR(_spin_lock,up,kUP,0)
+
+PLATFUNC_FUNCTION_START_GENERIC(spin_lock, mp, 32, 4)
+PLATFUNC_FUNCTION_START_GENERIC(OSSpinLockLock, mp, 32, 4)
+PLATFUNC_FUNCTION_START_GENERIC(_spin_lock, mp, 32, 4)
+Lspin_lock_mp:
+ movl 4(%esp), %ecx
+ xorl %eax, %eax
+0:
+ orl $-1, %edx
+ lock
+ cmpxchgl %edx, (%ecx)
+ jnz 1f
+ ret
+1:
+ xorl %eax, %eax
+ movl $(MP_SPIN_TRIES), %edx
+2:
+ pause
+ cmpl %eax, (%ecx)
+ jz 0b /* favor success and slow down spin loop */
+ decl %edx
+ jnz 2b
+ /* failed to get lock after spinning so relinquish */
+ pushl $1 /* 1 ms */
+ pushl $1 /* SWITCH_OPTION_DEPRESS */
+ pushl $0 /* THREAD_NULL */
+ pushl $0 /* push dummy stack ret addr */
+ movl $-61,%eax /* SYSCALL_THREAD_SWITCH */
+ int $(MACH_INT)
+ addl $16, %esp /* adjust stack*/
+ jmp Lspin_lock_mp
+PLATFUNC_DESCRIPTOR(spin_lock,mp,0,kUP)
+PLATFUNC_DESCRIPTOR(OSSpinLockLock,mp,0,kUP)
+PLATFUNC_DESCRIPTOR(_spin_lock,mp,0,kUP)
+
+ .align 2, 0x90
+ .globl _OSSpinLockUnlock
+ .globl _spin_unlock
+ .globl __spin_unlock
+_OSSpinLockUnlock:
+_spin_unlock:
+__spin_unlock:
+ movl 4(%esp), %eax
+ movl $0, (%eax)
+ ret
+
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/***********************************************************************
+ * Not to be installed in /usr/local/include
+ ***********************************************************************/
+
+#ifndef _LIBC_CRASHREPORTERCLIENT_H
+#define _LIBC_CRASHREPORTERCLIENT_H
+
+#ifdef LIBC_NO_LIBCRASHREPORTERCLIENT
+
+/* Fake the CrashReporterClient API */
+#define CRGetCrashLogMessage() 0
+#define CRSetCrashLogMessage(x) /* nothing */
+
+#else /* !LIBC_NO_LIBCRASHREPORTERCLIENT */
+
+/* Include the real CrashReporterClient.h */
+#include_next <CrashReporterClient.h>
+
+#endif /* !LIBC_NO_LIBCRASHREPORTERCLIENT */
+
+#endif /* _LIBC_CRASHREPORTERCLIENT_H */
--- /dev/null
+/* $NetBSD: nl_types.h,v 1.9 2000/10/03 19:53:32 sommerfeld Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * 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.
+ *
+ * $FreeBSD: src/include/nl_types.h,v 1.11 2005/02/27 16:20:53 phantom Exp $
+ */
+
+#ifndef _NL_TYPES_H_
+#define _NL_TYPES_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#ifdef _NLS_PRIVATE
+/*
+ * MESSAGE CATALOG FILE FORMAT.
+ *
+ * The NetBSD/FreeBSD message catalog format is similar to the format used by
+ * Svr4 systems. The differences are:
+ * * fixed byte order (big endian)
+ * * fixed data field sizes
+ *
+ * A message catalog contains four data types: a catalog header, one
+ * or more set headers, one or more message headers, and one or more
+ * text strings.
+ */
+
+#define _NLS_MAGIC 0xff88ff89
+
+struct _nls_cat_hdr {
+ int32_t __magic;
+ int32_t __nsets;
+ int32_t __mem;
+ int32_t __msg_hdr_offset;
+ int32_t __msg_txt_offset;
+} ;
+
+struct _nls_set_hdr {
+ int32_t __setno; /* set number: 0 < x <= NL_SETMAX */
+ int32_t __nmsgs; /* number of messages in the set */
+ int32_t __index; /* index of first msg_hdr in msg_hdr table */
+} ;
+
+struct _nls_msg_hdr {
+ int32_t __msgno; /* msg number: 0 < x <= NL_MSGMAX */
+ int32_t __msglen;
+ int32_t __offset;
+} ;
+
+#endif /* _NLS_PRIVATE */
+
+#define NL_SETD 0
+#define NL_CAT_LOCALE 1
+
+typedef struct __nl_cat_d {
+ void *__data;
+ int __size;
+} *nl_catd;
+
+#ifndef _NL_ITEM_DECLARED
+typedef __nl_item nl_item;
+#define _NL_ITEM_DECLARED
+#endif
+
+__BEGIN_DECLS
+nl_catd catopen(const char *, int);
+char *catgets(nl_catd, int, int, const char *)
+ __attribute__((__format_arg__(4)));
+int catclose(nl_catd);
+__END_DECLS
+
+#endif /* _NL_TYPES_H_ */
--- /dev/null
+--- nl_types.h.orig 2010-10-29 00:51:39.000000000 -0700
++++ nl_types.h 2010-10-29 00:53:25.000000000 -0700
+@@ -43,6 +43,7 @@
+
+ #include <sys/cdefs.h>
+ #include <sys/types.h>
++#include <_types.h>
+
+ #ifdef _NLS_PRIVATE
+ /*
+@@ -82,7 +83,7 @@
+
+ #endif /* _NLS_PRIVATE */
+
+-#define NL_SETD 0
++#define NL_SETD 1
+ #define NL_CAT_LOCALE 1
+
+ typedef struct __nl_cat_d {
+@@ -90,9 +91,9 @@
+ int __size;
+ } *nl_catd;
+
+-#ifndef _NL_ITEM_DECLARED
+-typedef __nl_item nl_item;
+-#define _NL_ITEM_DECLARED
++#ifndef _NL_ITEM
++typedef __darwin_nl_item nl_item;
++#define _NL_ITEM
+ #endif
+
+ __BEGIN_DECLS
err.h \
errno.h \
fcntl.h \
- float.h \
fmtmsg.h \
fnmatch.h \
fsproperties.h \
spawn.h \
stab.h \
standards.h \
- stdarg.h \
stdbool.h \
stddef.h \
stdio.h \
+ stdint.h \
stdlib.h \
strhash.h \
string.h \
util.h \
utime.h \
utmpx.h \
- varargs.h \
vis.h \
wchar.h \
wctype.h \
.include "Makefile.nbsd_begin"
NBSDHDRS = utmpx.h
.include "Makefile.nbsd_end"
+
+.include "Makefile.fbsd_begin"
+FBSDHDRS= nl_types.h
+.include "Makefile.fbsd_end"
+
NSDocumentationDirectory = 8, // documentation (Library/Documentation)
NSDocumentDirectory = 9, // documents (Documents)
NSCoreServiceDirectory = 10, // location of core services (System/Library/CoreServices)
- NSAutosavedInformationDirectory = 11, // location of user's directory for use with autosaving (~/Documents/Autosaved)
+ NSAutosavedInformationDirectory = 11, // location of user's directory for use with autosaving (Library/Autosave Information)
NSDesktopDirectory = 12, // location of user's Desktop (Desktop)
NSCachesDirectory = 13, // location of discardable cache files (Library/Caches)
NSApplicationSupportDirectory = 14, // location of application support files (plug-ins, etc) (Library/Application Support)
---- utmpx.h.orig 2008-07-17 11:34:24.000000000 -0700
-+++ utmpx.h 2008-07-17 11:57:27.000000000 -0700
+Index: utmpx.h
+===================================================================
+--- utmpx.h (revision 59377)
++++ utmpx.h (working copy)
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
/* $NetBSD: utmpx.h,v 1.11 2003/08/26 16:48:32 wiz Exp $ */
/*-
-@@ -38,28 +60,32 @@
+@@ -38,28 +60,34 @@
#ifndef _UTMPX_H_
#define _UTMPX_H_
--#include <sys/cdefs.h>
++#include <_types.h>
++#include <sys/time.h>
+ #include <sys/cdefs.h>
-#include <sys/featuretest.h>
-#include <sys/socket.h>
-+#include <_types.h>
- #include <sys/time.h>
+-#include <sys/time.h>
++#include <Availability.h>
+#ifndef _PID_T
+#define _PID_T
#define EMPTY 0
#define RUN_LVL 1
#define BOOT_TIME 2
-@@ -70,74 +96,87 @@
+@@ -70,75 +98,88 @@
#define USER_PROCESS 7
#define DEAD_PROCESS 8
#define SIGNATURE 10
-#endif
+#define SHUTDOWN_TIME 11
-+
+
+#define UTMPX_AUTOFILL_MASK 0x8000
+#define UTMPX_DEAD_IF_CORRESPONDING_MASK 0x4000
+
+/* notify(3) change notification name */
+#define UTMPX_CHANGE_NOTIFICATION "com.apple.system.utmpx"
+#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
-
++
/*
* The following structure describes the fields of the utmpx entries
- * stored in _PATH_UTMPX or _PATH_WTMPX. This is not the format the
-struct utmpx *getutxid __P((const struct utmpx *));
-struct utmpx *getutxline __P((const struct utmpx *));
-struct utmpx *pututxline __P((const struct utmpx *));
--
++void endutxent(void);
+
-#if defined(_NETBSD_SOURCE)
-int updwtmpx __P((const char *, const struct utmpx *));
-int lastlogxname __P((const char *));
-struct utmp;
-void getutmp __P((const struct utmpx *, struct utmp *));
-void getutmpx __P((const struct utmp *, struct utmpx *));
--
--int utmpxname __P((const char *));
-+void endutxent(void);
-
--#endif /* _NETBSD_SOURCE */
+#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-+void endutxent_wtmp(void);
++void endutxent_wtmp(void) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+struct lastlogx *
-+ getlastlogx(uid_t, struct lastlogx *);
++ getlastlogx(uid_t, struct lastlogx *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+struct lastlogx *
-+ getlastlogxbyname(const char*, struct lastlogx *);
++ getlastlogxbyname(const char*, struct lastlogx *)__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+#ifdef UNIFDEF_LEGACY_UTMP_APIS
+struct utmp; /* forward reference */
-+void getutmp(const struct utmpx *, struct utmp *);
-+void getutmpx(const struct utmp *, struct utmpx *);
++void getutmp(const struct utmpx *, struct utmp *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
++void getutmpx(const struct utmp *, struct utmpx *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+#endif /* UNIFDEF_LEGACY_UTMP_APIS */
+#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
-+
+
+-int utmpxname __P((const char *));
+struct utmpx *
+ getutxent(void);
-+
+
+-#endif /* _NETBSD_SOURCE */
+#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+struct utmpx *
-+ getutxent_wtmp(void);
++ getutxent_wtmp(void) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
-+
+
+struct utmpx *
+ getutxid(const struct utmpx *);
+struct utmpx *
+void setutxent(void);
+
+#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-+void setutxent_wtmp(int);
-+int utmpxname(const char *);
-+int wtmpxname(const char *);
++void setutxent_wtmp(int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
++int utmpxname(const char *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
++int wtmpxname(const char *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
-
++
__END_DECLS
+ #endif /* !_UTMPX_H_ */
/*
- * Copyright (c) 2004 - 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
- * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.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.apple.com/publicsource and read it before using
- * this file.
+ *
+ * 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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 <stdint.h>
#include <stdarg.h>
#include <sys/cdefs.h>
+#include <Availability.h>
typedef struct __aslclient *aslclient;
typedef struct __aslmsg *aslmsg;
#define ASL_KEY_GID "GID" /* GID that sent the log message (set by the server). */
#define ASL_KEY_LEVEL "Level" /* Log level number encoded as a string. See levels above. */
#define ASL_KEY_MSG "Message" /* Message text. */
-#define ASL_KEY_READ_UID "ReadUID" /* User read access (-1 is any group). */
+#define ASL_KEY_READ_UID "ReadUID" /* User read access (-1 is any user). */
#define ASL_KEY_READ_GID "ReadGID" /* Group read access (-1 is any group). */
#define ASL_KEY_EXPIRE_TIME "ASLExpireTime" /* Expiration time for messages with long TTL. */
#define ASL_KEY_MSG_ID "ASLMessageID" /* 64-bit message ID number (set by the server). */
#define ASL_KEY_SESSION "Session" /* Session (set by the launchd). */
#define ASL_KEY_REF_PID "RefPID" /* Reference PID for messages proxied by launchd */
#define ASL_KEY_REF_PROC "RefProc" /* Reference process for messages proxied by launchd */
+#define ASL_KEY_AUX_TITLE "ASLAuxTitle" /* Auxiliary title string */
+#define ASL_KEY_AUX_UTI "ASLAuxUTI" /* Auxiliary Uniform Type ID */
+#define ASL_KEY_AUX_URL "ASLAuxURL" /* Auxiliary Uniform Resource Locator */
+#define ASL_KEY_AUX_DATA "ASLAuxData" /* Auxiliary in-line data */
+#define ASL_KEY_OPTION "ASLOption" /* Internal */
+#define ASL_KEY_SENDER_INSTANCE "SenderInstance" /* Sender instance UUID. */
/*! @/defineblock */
/*! @defineblock aslmsg Types
*/
void aslresponse_free(aslresponse r);
+/*!
+ * Creates an auxiliary file that may be used to save arbitrary data. The ASL message msg
+ * will be saved at the time that the auxiliary file is closed with asl_close_auxiliary_file().
+ * The log entry will include any keys and values found in msg, and it will include the title
+ * and Uniform Type Identifier specified. If NULL is supplied as a value for the uti parameter,
+ * the type "public.data" is used. Console.app will display a hyperlink to the file.
+ * Output parameter out_fd will contain a readable and writable file descriptor for the new
+ * auxiliary file.
+ *
+ * By default, the file will be world-readable. If the message contains a ReadUID and/or a
+ * ReadGID key, then the values for those keys will determine read access to the file.
+ *
+ * The file will be deleted at the same time that the message expires from the ASL data store.
+ * The aslmanager utility manages message expiry. If msg contains a value for ASLExpireTime,
+ * then the message and the file will not be deleted before that time. The value may be in
+ * seconds after the Epoch, or it may be ctime() format, e.g "Thu Jun 24 18:22:48 2010".
+ *
+ * @param msg
+ * (input) An aslmsg
+ * @param tite
+ * (input) A title string for the file
+ * @param uti
+ * (input) Uniform Type Identifier for the file
+ * @param out_fd
+ * (output) A writable file descriptor
+ * @result Returns 0 for success, non-zero for failure
+ */
+int asl_create_auxiliary_file(aslmsg msg, const char *title, const char *uti, int *out_fd)
+__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0);
+
+/*!
+ * Close an auxiliary file opened by asl_create_auxiliary_file() when writing is complete.
+ * syslogd will log the message provided to asl_create_auxiliary_file() when this routine
+ * is called.
+ *
+ * @param fd
+ * (input) The file descriptor
+ * @result Returns 0 for success, non-zero for failure
+ */
+int asl_close_auxiliary_file(int fd)
+__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0);
+
+/*!
+ * Sends an ASL message to syslogd along with a title string, Uniform Resource Locator,
+ * and Uniform Type Identifier specified. Console.app will hyperlink the title string to
+ * the specified URL. If NULL is supplied as a value for the uti parameter, the default
+ * type "public.data" is used.
+ *
+ * @param msg
+ * (input) An aslmsg
+ * @param title
+ * (input) A title string for the file
+ * @param uti
+ * (input) Uniform Type Identifier for the file
+ * @param url
+ * (input) Uniform Type Locator
+ * @result Returns 0 for success, non-zero for failure
+ */
+int asl_log_auxiliary_location(aslmsg msg, const char *title, const char *uti, const char *url)
+__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0);
+
+/*!
+ * Creates an aslclient for logging to a file descriptor. The file must be opened for read and
+ * write access. This routine may be used in conjunction with asl_create_auxiliary_file() to
+ * save ASL format log messages to an auxiliary file.
+ *
+ * The file will be truncated if it is not empty. When logging to the auxiliary file is complete,
+ * aslclient should be closed using asl_close(). The file should be closed using
+ * asl_close_auxiliary_file() if it was returned by asl_create_auxiliary_file(), or close()
+ * otherwise.
+ *
+ * The returned aslclient is thread-safe.
+ *
+ * Note that per-message read access controls (ReadUID and ReadGID) and message expire
+ * times (ASLExpireTime) keys have no effect for messages written to this file.
+ *
+ * @param fd
+ * (input) A file descriptor
+ * @param ident
+ * (input) Sender name
+ * @param facility
+ * (input) Facility name
+ * @result An aslclient
+ */
+aslclient asl_open_from_file(int fd, const char *ident, const char *facility)
+__OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_5_0);
+
__END_DECLS
#endif /* __ASL_H__ */
__BEGIN_DECLS
void __assert_rtn(const char *, const char *, int, const char *) __dead2;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1070)
void __eprintf(const char *, const char *, unsigned, const char *) __dead2;
+#endif
__END_DECLS
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1070)
#define __assert(e, file, line) \
__eprintf ("%s:%u: failed assertion `%s'\n", file, line, e)
+#else
+/* 8462256: modified __assert_rtn() replaces deprecated __eprintf() */
+#define __assert(e, file, line) \
+ __assert_rtn ((const char *)-1L, file, line, e)
+#endif
#if __DARWIN_UNIX03
#define assert(e) \
*/
__asm("_getdirentries_is_not_available_when_64_bit_inodes_are_in_effect")
#else /* !__DARWIN_64_BIT_INO_T */
- __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_6,__IPHONE_2_0,__IPHONE_2_0)
+ __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_6, __IPHONE_2_0,__IPHONE_2_0)
#endif /* __DARWIN_64_BIT_INO_T */
//Begin-Libc
#endif /* !__LIBC__ */
int (*)(struct dirent *), int (*)(const void *, const void *)) __DARWIN_INODE64(scandir);
#ifdef __BLOCKS__
int scandir_b(const char *, struct dirent ***,
- int (^)(struct dirent *), int (^)(const void *, const void *)) __DARWIN_INODE64(scandir_b);
+ int (^)(struct dirent *), int (^)(const void *, const void *)) __DARWIN_INODE64(scandir_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* __BLOCKS__ */
#endif /* not POSIX */
//Begin-Libc
*/
#include <sys/cdefs.h>
#include <_types.h>
+#include <Availability.h>
__BEGIN_DECLS
-void err(int, const char *, ...) __DARWIN_LDBL_COMPAT(err) __dead2;
-void verr(int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(verr) __dead2;
-void errc(int, int, const char *, ...) __DARWIN_LDBL_COMPAT(errc) __dead2;
-void verrc(int, int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(verrc) __dead2;
-void errx(int, const char *, ...) __DARWIN_LDBL_COMPAT(errx) __dead2;
-void verrx(int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(verrx) __dead2;
-void warn(const char *, ...) __DARWIN_LDBL_COMPAT(warn);
-void vwarn(const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(vwarn);
-void warnc(int, const char *, ...) __DARWIN_LDBL_COMPAT(warnc);
-void vwarnc(int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(vwarnc);
-void warnx(const char *, ...) __DARWIN_LDBL_COMPAT(warnx);
-void vwarnx(const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(vwarnx);
+void err(int, const char *, ...) __DARWIN_LDBL_COMPAT(err) __dead2 __printflike(2, 3);
+void verr(int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(verr) __dead2 __printflike(2, 0);
+void errc(int, int, const char *, ...) __DARWIN_LDBL_COMPAT(errc) __dead2 __printflike(3, 4);
+void verrc(int, int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(verrc) __dead2 __printflike(3, 0);
+void errx(int, const char *, ...) __DARWIN_LDBL_COMPAT(errx) __dead2 __printflike(2, 3);
+void verrx(int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(verrx) __dead2 __printflike(2, 0);
+void warn(const char *, ...) __DARWIN_LDBL_COMPAT(warn) __printflike(1, 2);
+void vwarn(const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(vwarn) __printflike(1, 0);
+void warnc(int, const char *, ...) __DARWIN_LDBL_COMPAT(warnc) __printflike(2, 3);
+void vwarnc(int, const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(vwarnc) __printflike(2, 0);
+void warnx(const char *, ...) __DARWIN_LDBL_COMPAT(warnx) __printflike(1, 2);
+void vwarnx(const char *, __darwin_va_list) __DARWIN_LDBL_COMPAT(vwarnx) __printflike(1, 0);
void err_set_file(void *);
void err_set_exit(void (*)(int));
#ifdef __BLOCKS__
-void err_set_exit_b(void (^)(int));
+void err_set_exit_b(void (^)(int)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* __BLOCKS__ */
__END_DECLS
+++ /dev/null
-/* This file exists soley to keep Metrowerks' compilers happy. The version
- used by GCC can be found in /usr/lib/gcc, although it's
- not very informative. */
-
-#ifndef _FLOAT_H_
-
-#if defined(__GNUC__)
-#include_next <float.h>
-
-#elif defined(__MWERKS__)
-#define _FLOAT_H_
-
-/* APPLE LOCAL begin MW compatibility */
-/* Define various characteristics of floating-point types, if needed. */
-#ifndef __FLT_RADIX__
-#define __FLT_RADIX__ 2
-#endif
-#ifndef __FLT_MANT_DIG__
-#define __FLT_MANT_DIG__ 24
-#endif
-#ifndef __FLT_DIG__
-#define __FLT_DIG__ 6
-#endif
-#ifndef __FLT_EPSILON__
-#define __FLT_EPSILON__ 1.19209290e-07F
-#endif
-#ifndef __FLT_MIN__
-#define __FLT_MIN__ 1.17549435e-38F
-#endif
-#ifndef __FLT_MAX__
-#define __FLT_MAX__ 3.40282347e+38F
-#endif
-#ifndef __FLT_MIN_EXP__
-#define __FLT_MIN_EXP__ (-125)
-#endif
-#ifndef __FLT_MIN_10_EXP__
-#define __FLT_MIN_10_EXP__ (-37)
-#endif
-#ifndef __FLT_MAX_EXP__
-#define __FLT_MAX_EXP__ 128
-#endif
-#ifndef __FLT_MAX_10_EXP__
-#define __FLT_MAX_10_EXP__ 38
-#endif
-#ifndef __DBL_MANT_DIG__
-#define __DBL_MANT_DIG__ 53
-#endif
-#ifndef __DBL_DIG__
-#define __DBL_DIG__ 15
-#endif
-#ifndef __DBL_EPSILON__
-#define __DBL_EPSILON__ 2.2204460492503131e-16
-#endif
-#ifndef __DBL_MIN__
-#define __DBL_MIN__ 2.2250738585072014e-308
-#endif
-#ifndef __DBL_MAX__
-#define __DBL_MAX__ 1.7976931348623157e+308
-#endif
-#ifndef __DBL_MIN_EXP__
-#define __DBL_MIN_EXP__ (-1021)
-#endif
-#ifndef __DBL_MIN_10_EXP__
-#define __DBL_MIN_10_EXP__ (-307)
-#endif
-#ifndef __DBL_MAX_EXP__
-#define __DBL_MAX_EXP__ 1024
-#endif
-#ifndef __DBL_MAX_10_EXP__
-#define __DBL_MAX_10_EXP__ 308
-#endif
-#ifndef __LDBL_MANT_DIG__
-#define __LDBL_MANT_DIG__ 53
-#endif
-#ifndef __LDBL_DIG__
-#define __LDBL_DIG__ 15
-#endif
-#ifndef __LDBL_EPSILON__
-#define __LDBL_EPSILON__ 2.2204460492503131e-16
-#endif
-#ifndef __LDBL_MIN__
-#define __LDBL_MIN__ 2.2250738585072014e-308
-#endif
-#ifndef __LDBL_MAX__
-#define __LDBL_MAX__ 1.7976931348623157e+308
-#endif
-#ifndef __LDBL_MIN_EXP__
-#define __LDBL_MIN_EXP__ (-1021)
-#endif
-#ifndef __LDBL_MIN_10_EXP__
-#define __LDBL_MIN_10_EXP__ (-307)
-#endif
-#ifndef __LDBL_MAX_EXP__
-#define __LDBL_MAX_EXP__ 1024
-#endif
-#ifndef __LDBL_MAX_10_EXP__
-#define __LDBL_MAX_10_EXP__ 308
-#endif
-/* APPLE LOCAl end MW compatibility */
-
-/* Copyright (C) 2002 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* As a special exception, if you include this header file into source
- files compiled by GCC, this header file does not by itself cause
- the resulting executable to be covered by the GNU General Public
- License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General
- Public License. */
-
-/*
- * ISO C Standard: 5.2.4.2.2 Characteristics of floating types <float.h>
- */
-
-
-/* Radix of exponent representation, b. */
-#undef FLT_RADIX
-#define FLT_RADIX __FLT_RADIX__
-
-/* Number of base-FLT_RADIX digits in the significand, p. */
-#undef FLT_MANT_DIG
-#undef DBL_MANT_DIG
-#undef LDBL_MANT_DIG
-#define FLT_MANT_DIG __FLT_MANT_DIG__
-#define DBL_MANT_DIG __DBL_MANT_DIG__
-#define LDBL_MANT_DIG __LDBL_MANT_DIG__
-
-/* Number of decimal digits, q, such that any floating-point number with q
- decimal digits can be rounded into a floating-point number with p radix b
- digits and back again without change to the q decimal digits,
-
- p * log10(b) if b is a power of 10
- floor((p - 1) * log10(b)) otherwise
-*/
-#undef FLT_DIG
-#undef DBL_DIG
-#undef LDBL_DIG
-#define FLT_DIG __FLT_DIG__
-#define DBL_DIG __DBL_DIG__
-#define LDBL_DIG __LDBL_DIG__
-
-/* Minimum int x such that FLT_RADIX**(x-1) is a normalized float, emin */
-#undef FLT_MIN_EXP
-#undef DBL_MIN_EXP
-#undef LDBL_MIN_EXP
-#define FLT_MIN_EXP __FLT_MIN_EXP__
-#define DBL_MIN_EXP __DBL_MIN_EXP__
-#define LDBL_MIN_EXP __LDBL_MIN_EXP__
-
-/* Minimum negative integer such that 10 raised to that power is in the
- range of normalized floating-point numbers,
-
- ceil(log10(b) * (emin - 1))
-*/
-#undef FLT_MIN_10_EXP
-#undef DBL_MIN_10_EXP
-#undef LDBL_MIN_10_EXP
-#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
-#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
-#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
-
-/* Maximum int x such that FLT_RADIX**(x-1) is a representable float, emax. */
-#undef FLT_MAX_EXP
-#undef DBL_MAX_EXP
-#undef LDBL_MAX_EXP
-#define FLT_MAX_EXP __FLT_MAX_EXP__
-#define DBL_MAX_EXP __DBL_MAX_EXP__
-#define LDBL_MAX_EXP __LDBL_MAX_EXP__
-
-/* Maximum integer such that 10 raised to that power is in the range of
- representable finite floating-point numbers,
-
- floor(log10((1 - b**-p) * b**emax))
-*/
-#undef FLT_MAX_10_EXP
-#undef DBL_MAX_10_EXP
-#undef LDBL_MAX_10_EXP
-#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
-#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
-#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
-
-/* Maximum representable finite floating-point number,
-
- (1 - b**-p) * b**emax
-*/
-#undef FLT_MAX
-#undef DBL_MAX
-#undef LDBL_MAX
-#define FLT_MAX __FLT_MAX__
-#define DBL_MAX __DBL_MAX__
-#define LDBL_MAX __LDBL_MAX__
-
-/* The difference between 1 and the least value greater than 1 that is
- representable in the given floating point type, b**1-p. */
-#undef FLT_EPSILON
-#undef DBL_EPSILON
-#undef LDBL_EPSILON
-#define FLT_EPSILON __FLT_EPSILON__
-#define DBL_EPSILON __DBL_EPSILON__
-#define LDBL_EPSILON __LDBL_EPSILON__
-
-/* Minimum normalized positive floating-point number, b**(emin - 1). */
-#undef FLT_MIN
-#undef DBL_MIN
-#undef LDBL_MIN
-#define FLT_MIN __FLT_MIN__
-#define DBL_MIN __DBL_MIN__
-#define LDBL_MIN __LDBL_MIN__
-
-/* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown. */
-/* ??? This is supposed to change with calls to fesetround in <fenv.h>. */
-#undef FLT_ROUNDS
-#define FLT_ROUNDS 1
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-/* The floating-point expression evaluation method.
- -1 indeterminate
- 0 evaluate all operations and constants just to the range and
- precision of the type
- 1 evaluate operations and constants of type float and double
- to the range and precision of the double type, evaluate
- long double operations and constants to the range and
- precision of the long double type
- 2 evaluate all operations and constants to the range and
- precision of the long double type
-
- ??? This ought to change with the setting of the fp control word;
- the value provided by the compiler assumes the widest setting. */
-#undef FLT_EVAL_METHOD
-#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
-
-/* Number of decimal digits, n, such that any floating-point number in the
- widest supported floating type with pmax radix b digits can be rounded
- to a floating-point number with n decimal digits and back again without
- change to the value,
-
- pmax * log10(b) if b is a power of 10
- ceil(1 + pmax * log10(b)) otherwise
-*/
-#undef DECIMAL_DIG
-#define DECIMAL_DIG __DECIMAL_DIG__
-
-#endif /* C99 */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int __fegetfltrounds( void );
-#ifdef __cplusplus
-}
-#endif
-#undef FLT_ROUNDS
-#define FLT_ROUNDS (__fegetfltrounds ())
-/* End of GNU CC file */
-
-/* APPLE LOCAL begin CW compatibility */
-/* CodeWarrior defines the following on its own. */
-#undef DECIMAL_DIG
-/* APPLE LOCAL end CW compatibility */
-
-#else
-#error This file is only for Metrowerks compatibilty.
-#endif
-
-#endif /* _FLOAT_H_ */
#define kFSVerificationArgumentsKey "FSVerificationArguments"
#define kFSVerificationExecutableKey "FSVerificationExecutable"
#define kFSSubTypeKey "FSSubType"
+#define kFSXMLOutputArgumentKey "FSXMLOutputArgument"
+
+#define kFSCoreStorageEncryptNameKey "FSCoreStorageEncryptionName"
#endif /* _FSPROPERTIES_H_ */
} FTSENT;
#include <sys/cdefs.h>
+#include <Availability.h>
__BEGIN_DECLS
//Begin-Libc
#ifndef LIBC_ALIAS_FTS_OPEN_B
//End-Libc
FTS *fts_open_b(char * const *, int,
- int (^)(const FTSENT **, const FTSENT **)) __DARWIN_INODE64(fts_open_b);
+ int (^)(const FTSENT **, const FTSENT **)) __DARWIN_INODE64(fts_open_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
//Begin-Libc
#else /* LIBC_ALIAS_FTS_OPEN */
FTS *fts_open_b(char * const *, int,
#define _GLOB_H_
#include <_types.h>
+#include <sys/cdefs.h>
+#include <Availability.h>
#ifndef _SIZE_T
#define _SIZE_T
#ifndef LIBC_ALIAS_GLOB_B
//End-Libc
int glob_b(const char * __restrict, int, int (^)(const char *, int),
- glob_t * __restrict) __DARWIN_INODE64(glob_b);
+ glob_t * __restrict) __DARWIN_INODE64(glob_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
//Begin-Libc
#else /* LIBC_ALIAS_GLOB_B */
int glob_b(const char * __restrict, int, int (^)(const char *, int),
* and their ilk.
*/
-/* "C++ implementations should define these macros only when
- * __STDC_FORMAT_MACROS is defined before <inttypes.h> is included."
- */
-#if (!defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)) && !defined(__STDC_FORMAT_MACROS_DEFINED)
-#define __STDC_FORMAT_MACROS_DEFINED
+#if !defined(_INTTYPES_H_)
+#define _INTTYPES_H_
# undef __PRI_8_LENGTH_MODIFIER__
# undef __PRI_64_LENGTH_MODIFIER__
# define SCNuMAX __SCN_MAX_LENGTH_MODIFIER__ "u"
# define SCNxMAX __SCN_MAX_LENGTH_MODIFIER__ "x"
-#endif /* if C++, then __STDC_FORMAT_MACROS enables the above macros */
-
-#if !defined(_INTTYPES_H_)
-#define _INTTYPES_H_
-
#include <sys/cdefs.h> /* For __BEGIN_DECLS and __END_DECLS */
#include <_types.h> /* For __darwin_wchar_t */
#include <stdint.h>
#define YESEXPR 52 /* affirmative response expression */
#define NOEXPR 53 /* negative response expression */
-#if !defined(_ANSI_SOURCE)
+#if (__DARWIN_C_LEVEL > __DARWIN_C_ANSI && __DARWIN_C_LEVEL < 200112L) || __DARWIN_C_LEVEL == __DARWIN_C_FULL
#define YESSTR 54 /* affirmative response for yes/no queries */
#define NOSTR 55 /* negative response for yes/no queries */
#endif
#define _LIBC_H
#include <stdio.h>
-#include <standards.h>
#include <unistd.h>
#ifdef __STRICT_BSD__
#include <stdint.h>
#include <stdbool.h>
-/* These are the preferred versions of the atomic and synchronization operations.
+#include <Availability.h>
+
+/*! @header
+ * These are the preferred versions of the atomic and synchronization operations.
* Their implementation is customized at boot time for the platform, including
* late-breaking errata fixes as necessary. They are thread safe.
*
- * WARNING: all addresses passed to these functions must be "naturally aligned", ie
- * int32_t's must be 32-bit aligned (low 2 bits of address zero), and int64_t's
- * must be 64-bit aligned (low 3 bits of address zero.)
+ * WARNING: all addresses passed to these functions must be "naturally aligned",
+ * i.e. * <code>int32_t</code> pointers must be 32-bit aligned (low 2 bits of
+ * address are zeroes), and <code>int64_t</code> pointers must be 64-bit aligned
+ * (low 3 bits of address are zeroes.)
+ *
+ * Note that some versions of the atomic functions incorporate memory barriers
+ * and some do not. Barriers strictly order memory access on weakly-ordered
+ * architectures such as PPC. All loads and stores that appear (in sequential
+ * program order) before the barrier are guaranteed to complete before any
+ * load or store that appears after the barrier.
*
- * Note that some versions of the atomic functions incorporate memory barriers,
- * and some do not. Barriers strictly order memory access on a weakly-ordered
- * architecture such as PPC. All loads and stores executed in sequential program
- * order before the barrier will complete before any load or store executed after
- * the barrier. On a uniprocessor, the barrier operation is typically a nop.
- * On a multiprocessor, the barrier can be quite expensive on some platforms,
- * eg PPC.
+ * On a uniprocessor system, the barrier operation is typically a no-op. On a
+ * multiprocessor system, the barrier can be quite expensive on some platforms,
+ * such as PPC.
*
- * Most code will want to use the barrier functions to insure that memory shared
- * between threads is properly synchronized. For example, if you want to initialize
+ * Most code should use the barrier functions to ensure that memory shared between
+ * threads is properly synchronized. For example, if you want to initialize
* a shared data structure and then atomically increment a variable to indicate
- * that the initialization is complete, then you must use OSAtomicIncrement32Barrier()
- * to ensure that the stores to your data structure complete before the atomic add.
- * Likewise, the consumer of that data structure must use OSAtomicDecrement32Barrier(),
+ * that the initialization is complete, you must use {@link OSAtomicIncrement32Barrier}
+ * to ensure that the stores to your data structure complete before the atomic
+ * increment.
+ *
+ * Likewise, the consumer of that data structure must use {@link OSAtomicDecrement32Barrier},
* in order to ensure that their loads of the structure are not executed before
* the atomic decrement. On the other hand, if you are simply incrementing a global
- * counter, then it is safe and potentially faster to use OSAtomicIncrement32().
+ * counter, then it is safe and potentially faster to use {@link OSAtomicIncrement32}.
*
* If you are unsure which version to use, prefer the barrier variants as they are
* safer.
*
* The spinlock and queue operations always incorporate a barrier.
+ *
+ * For the kernel-space version of this header, see
+ * {@link //apple_ref/doc/header/OSAtomic.h OSAtomic.h (Kernel Framework)}
+ *
+ * @apiuid //apple_ref/doc/header/user_space_OSAtomic.h
*/
__BEGIN_DECLS
-/* Arithmetic functions. They return the new value.
+/*! @group Arithmetic functions
+ All functions in this group return the new value.
+ */
+
+/*! @abstract Atomically adds two 32-bit values.
+ @discussion
+ This function adds the value given by <code>__theAmount</code> to the
+ value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ @result Returns the new value.
*/
int32_t OSAtomicAdd32( int32_t __theAmount, volatile int32_t *__theValue );
+
+
+/*! @abstract Atomically adds two 32-bit values.
+ @discussion
+ This function adds the value given by <code>__theAmount</code> to the
+ value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicAdd32}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
int32_t OSAtomicAdd32Barrier( int32_t __theAmount, volatile int32_t *__theValue );
+
+/*! @abstract Atomically increments a 32-bit value.
+ */
__inline static
int32_t OSAtomicIncrement32( volatile int32_t *__theValue )
{ return OSAtomicAdd32( 1, __theValue); }
+
+
+/*! @abstract Atomically increments a 32-bit value with a barrier.
+ @discussion
+ This function is equivalent to {@link OSAtomicIncrement32}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
__inline static
int32_t OSAtomicIncrement32Barrier( volatile int32_t *__theValue )
{ return OSAtomicAdd32Barrier( 1, __theValue); }
+/*! @abstract Atomically decrements a 32-bit value. */
__inline static
int32_t OSAtomicDecrement32( volatile int32_t *__theValue )
{ return OSAtomicAdd32( -1, __theValue); }
+
+/*! @abstract Atomically increments a 32-bit value with a barrier.
+ @discussion
+ This function is equivalent to {@link OSAtomicDecrement32}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
__inline static
int32_t OSAtomicDecrement32Barrier( volatile int32_t *__theValue )
{ return OSAtomicAdd32Barrier( -1, __theValue); }
+
#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+/*! @abstract Atomically adds two 64-bit values.
+ @discussion
+ This function adds the value given by <code>__theAmount</code> to the
+ value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ */
int64_t OSAtomicAdd64( int64_t __theAmount, volatile int64_t *__theValue );
-int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *__theValue );
+
+/*! @abstract Atomically adds two 64-bit values with a barrier.
+ @discussion
+ This function adds the value given by <code>__theAmount</code> to the
+ value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicAdd64}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
+int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2);
+
+
+/*! @abstract Atomically increments a 64-bit value. */
__inline static
int64_t OSAtomicIncrement64( volatile int64_t *__theValue )
{ return OSAtomicAdd64( 1, __theValue); }
+
+/*! @abstract Atomically increments a 64-bit value with a barrier.
+ @discussion
+ This function is equivalent to {@link OSAtomicIncrement64}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
__inline static
int64_t OSAtomicIncrement64Barrier( volatile int64_t *__theValue )
{ return OSAtomicAdd64Barrier( 1, __theValue); }
+
+/*! @abstract Atomically decrements a 64-bit value.
+ @discussion
+ This function is equivalent to {@link OSAtomicIncrement64}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
__inline static
int64_t OSAtomicDecrement64( volatile int64_t *__theValue )
{ return OSAtomicAdd64( -1, __theValue); }
+
+
+/*! @abstract Atomically decrements a 64-bit value with a barrier.
+ @discussion
+ This function is equivalent to {@link OSAtomicDecrement64}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
__inline static
int64_t OSAtomicDecrement64Barrier( volatile int64_t *__theValue )
{ return OSAtomicAdd64Barrier( -1, __theValue); }
+
#endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) */
-/* Boolean functions (and, or, xor.) These come in four versions for each operation:
- * with and without barriers, and returning the old or new value of the operation.
- * The "Orig" versions return the original value, ie before the operation, the non-Orig
+/*! @group Boolean functions (AND, OR, XOR)
+ *
+ * @discussion Functions in this group come in four variants for each operation:
+ * with and without barriers, and functions that return the original value or
+ * the result value of the operation.
+ *
+ * The "Orig" versions return the original value, (before the operation); the non-Orig
* versions return the value after the operation. All are layered on top of
- * compare-and-swap.
+ * {@link OSAtomicCompareAndSwap32} and similar.
+ */
+
+/*! @abstract Atomic bitwise OR of two 32-bit values.
+ @discussion
+ This function performs the bitwise OR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ @result Returns the new value.
*/
int32_t OSAtomicOr32( uint32_t __theMask, volatile uint32_t *__theValue );
+
+
+/*! @abstract Atomic bitwise OR of two 32-bit values with barrier.
+ @discussion
+ This function performs the bitwise OR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicOr32}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
int32_t OSAtomicOr32Barrier( uint32_t __theMask, volatile uint32_t *__theValue );
-int32_t OSAtomicOr32Orig( uint32_t __theMask, volatile uint32_t *__theValue );
-int32_t OSAtomicOr32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue );
+
+/*! @abstract Atomic bitwise OR of two 32-bit values returning original.
+ @discussion
+ This function performs the bitwise OR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ @result Returns the original value referenced by <code>__theValue</code>.
+ */
+int32_t OSAtomicOr32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
+
+
+/*! @abstract Atomic bitwise OR of two 32-bit values returning original with barrier.
+ @discussion
+ This function performs the bitwise OR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicOr32Orig}
+ except that it also introduces a barrier.
+ @result Returns the original value referenced by <code>__theValue</code>.
+ */
+int32_t OSAtomicOr32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
+
+
+
+
+/*! @abstract Atomic bitwise AND of two 32-bit values.
+ @discussion
+ This function performs the bitwise AND of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ @result Returns the new value.
+ */
int32_t OSAtomicAnd32( uint32_t __theMask, volatile uint32_t *__theValue );
+
+
+/*! @abstract Atomic bitwise AND of two 32-bit values with barrier.
+ @discussion
+ This function performs the bitwise AND of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicAnd32}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
int32_t OSAtomicAnd32Barrier( uint32_t __theMask, volatile uint32_t *__theValue );
-int32_t OSAtomicAnd32Orig( uint32_t __theMask, volatile uint32_t *__theValue );
-int32_t OSAtomicAnd32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue );
+
+/*! @abstract Atomic bitwise AND of two 32-bit values returning original.
+ @discussion
+ This function performs the bitwise AND of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ @result Returns the original value referenced by <code>__theValue</code>.
+ */
+int32_t OSAtomicAnd32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
+
+
+/*! @abstract Atomic bitwise AND of two 32-bit values returning original with barrier.
+ @discussion
+ This function performs the bitwise AND of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicAnd32Orig}
+ except that it also introduces a barrier.
+ @result Returns the original value referenced by <code>__theValue</code>.
+ */
+int32_t OSAtomicAnd32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
+
+
+
+
+/*! @abstract Atomic bitwise XOR of two 32-bit values.
+ @discussion
+ This function performs the bitwise XOR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ @result Returns the new value.
+ */
int32_t OSAtomicXor32( uint32_t __theMask, volatile uint32_t *__theValue );
+
+
+/*! @abstract Atomic bitwise XOR of two 32-bit values with barrier.
+ @discussion
+ This function performs the bitwise XOR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicXor32}
+ except that it also introduces a barrier.
+ @result Returns the new value.
+ */
int32_t OSAtomicXor32Barrier( uint32_t __theMask, volatile uint32_t *__theValue );
-int32_t OSAtomicXor32Orig( uint32_t __theMask, volatile uint32_t *__theValue );
-int32_t OSAtomicXor32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue );
+
+
+/*! @abstract Atomic bitwise XOR of two 32-bit values returning original.
+ @discussion
+ This function performs the bitwise XOR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+ @result Returns the original value referenced by <code>__theValue</code>.
+ */
+int32_t OSAtomicXor32Orig( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
+
+
+/*! @abstract Atomic bitwise XOR of two 32-bit values returning original with barrier.
+ @discussion
+ This function performs the bitwise XOR of the value given by <code>__theMask</code>
+ with the value in the memory location referenced by <code>__theValue</code>,
+ storing the result back to that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicXor32Orig}
+ except that it also introduces a barrier.
+ @result Returns the original value referenced by <code>__theValue</code>.
+ */
+int32_t OSAtomicXor32OrigBarrier( uint32_t __theMask, volatile uint32_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_2);
-/* Compare and swap. They return true if the swap occured. There are several versions,
- * depending on data type and whether or not a barrier is used.
+/*! @group Compare and swap
+ * Functions in this group return true if the swap occured. There are several versions,
+ * depending on data type and on whether or not a barrier is used.
+ */
+
+
+/*! @abstract Compare and swap for 32-bit values.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+ @result Returns TRUE on a match, FALSE otherwise.
*/
bool OSAtomicCompareAndSwap32( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
+
+
+/*! @abstract Compare and swap for 32-bit values with barrier.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwap32}
+ except that it also introduces a barrier.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );
-bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );
-bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue, void *__newValue, void * volatile *__theValue );
-bool OSAtomicCompareAndSwapInt( int __oldValue, int __newValue, volatile int *__theValue );
-bool OSAtomicCompareAndSwapIntBarrier( int __oldValue, int __newValue, volatile int *__theValue );
-bool OSAtomicCompareAndSwapLong( long __oldValue, long __newValue, volatile long *__theValue );
-bool OSAtomicCompareAndSwapLongBarrier( long __oldValue, long __newValue, volatile long *__theValue );
+
+
+/*! @abstract Compare and swap pointers.
+ @discussion
+ This function compares the pointer stored in <code>__oldValue</code> to the pointer
+ in the memory location referenced by <code>__theValue</code>. If the pointers
+ match, this function stores the pointer from <code>__newValue</code> into
+ that memory location atomically.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
+bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+
+
+/*! @abstract Compare and swap pointers with barrier.
+ @discussion
+ This function compares the pointer stored in <code>__oldValue</code> to the pointer
+ in the memory location referenced by <code>__theValue</code>. If the pointers
+ match, this function stores the pointer from <code>__newValue</code> into
+ that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwapPtr}
+ except that it also introduces a barrier.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
+bool OSAtomicCompareAndSwapPtrBarrier( void *__oldValue, void *__newValue, void * volatile *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+
+
+/*! @abstract Compare and swap for <code>int</code> values.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwap32}.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
+bool OSAtomicCompareAndSwapInt( int __oldValue, int __newValue, volatile int *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+
+
+/*! @abstract Compare and swap for <code>int</code> values.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwapInt}
+ except that it also introduces a barrier.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwap32Barrier}.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
+bool OSAtomicCompareAndSwapIntBarrier( int __oldValue, int __newValue, volatile int *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+
+
+/*! @abstract Compare and swap for <code>long</code> values.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures,
+ or {@link OSAtomicCompareAndSwap64} on 64-bit architectures.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
+bool OSAtomicCompareAndSwapLong( long __oldValue, long __newValue, volatile long *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+
+
+/*! @abstract Compare and swap for <code>long</code> values.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwapLong}
+ except that it also introduces a barrier.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwap32} on 32-bit architectures,
+ or {@link OSAtomicCompareAndSwap64} on 64-bit architectures.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
+bool OSAtomicCompareAndSwapLongBarrier( long __oldValue, long __newValue, volatile long *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+
#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+/*! @abstract Compare and swap for <code>uint64_t</code> values.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
bool OSAtomicCompareAndSwap64( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
-bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
+
+
+/*! @abstract Compare and swap for <code>uint64_t</code> values.
+ @discussion
+ This function compares the value in <code>__oldValue</code> to the value
+ in the memory location referenced by <code>__theValue</code>. If the values
+ match, this function stores the value from <code>__newValue</code> into
+ that memory location atomically.
+
+ This function is equivalent to {@link OSAtomicCompareAndSwap64}
+ except that it also introduces a barrier.
+ @result Returns TRUE on a match, FALSE otherwise.
+ */
+bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_3_2);
#endif /* defined(__ppc64__) || defined(__i386__) || defined(__x86_64__) || defined(__arm__) */
/* Test and set. They return the original value of the bit, and operate on bit (0x80>>(n&7))
* in byte ((char*)theAddress + (n>>3)).
*/
+/*! @abstract Atomic test and set
+ @discussion
+ This function tests a bit in the value referenced by <code>__theAddress</code>
+ and if it is not set, sets it. The bit is chosen by the value of <code>__n</code>.
+ The bits are numbered in order beginning with bit 1 as the lowest order bit.
+
+ For example, if <code>__theAddress</code> points to a 64-bit value,
+ to compare the value of the highest bit, you would specify <code>64</code> for
+ <code>__n</code>.
+ @result
+ Returns the original value of the bit being tested.
+ */
bool OSAtomicTestAndSet( uint32_t __n, volatile void *__theAddress );
+
+
+/*! @abstract Atomic test and set with barrier
+ @discussion
+ This function tests a bit in the value referenced by <code>__theAddress</code>
+ and if it is not set, sets it. The bit is chosen by the value of <code>__n</code>.
+ The bits are numbered in order beginning with bit 1 as the lowest order bit.
+
+ For example, if <code>__theAddress</code> points to a 64-bit value,
+ to compare the value of the highest bit, you would specify <code>64</code> for
+ <code>__n</code>.
+
+ This function is equivalent to {@link OSAtomicTestAndSet}
+ except that it also introduces a barrier.
+ @result
+ Returns the original value of the bit being tested.
+ */
+
bool OSAtomicTestAndSetBarrier( uint32_t __n, volatile void *__theAddress );
+
+
+
+/*! @abstract Atomic test and clear
+ @discussion
+ This function tests a bit in the value referenced by <code>__theAddress</code>
+ and if it is not cleared, clears it. The bit is chosen by the value of <code>__n</code>.
+ The bits are numbered in order beginning with bit 1 as the lowest order bit.
+
+ For example, if <code>__theAddress</code> points to a 64-bit value,
+ to compare the value of the highest bit, you would specify <code>64</code> for
+ <code>__n</code>.
+ @result
+ Returns the original value of the bit being tested.
+ */
bool OSAtomicTestAndClear( uint32_t __n, volatile void *__theAddress );
+
+
+/*! @abstract Atomic test and clear
+ @discussion
+ This function tests a bit in the value referenced by <code>__theAddress</code>
+ and if it is not cleared, clears it. The bit is chosen by the value of <code>__n</code>.
+ The bits are numbered in order beginning with bit 1 as the lowest order bit.
+
+ For example, if <code>__theAddress</code> points to a 64-bit value,
+ to compare the value of the highest bit, you would specify <code>64</code> for
+ <code>__n</code>.
+
+ This function is equivalent to {@link OSAtomicTestAndSet}
+ except that it also introduces a barrier.
+ @result
+ Returns the original value of the bit being tested.
+ */
bool OSAtomicTestAndClearBarrier( uint32_t __n, volatile void *__theAddress );
-/* Spinlocks. These use memory barriers as required to synchronize access to shared
- * memory protected by the lock. The lock operation spins, but employs various strategies
- * to back off if the lock is held, making it immune to most priority-inversion livelocks.
- * The try operation immediately returns false if the lock was held, true if it took the
- * lock. The convention is that unlocked is zero, locked is nonzero.
+/*! @group Spinlocks
+ * These spinlocks use memory barriers as required to synchronize access to shared
+ * memory protected by the lock.
+ */
+
+/*! @abstract The default value for an <code>OSSpinLock</code>.
+ @discussion
+ The convention is that unlocked is zero, locked is nonzero.
*/
#define OS_SPINLOCK_INIT 0
+
+/*! @abstract Data type for a spinlock.
+ @discussion
+ You should always initialize a spinlock to {@link OS_SPINLOCK_INIT} before
+ using it.
+ */
typedef int32_t OSSpinLock;
+
+/*! @abstract Locks a spinlock if it would not block
+ @result
+ Returns <code>false</code> if the lock was already held by another thread,
+ <code>true</code> if it took the lock successfully.
+ */
bool OSSpinLockTry( volatile OSSpinLock *__lock );
+
+
+/*! @abstract Locks a spinlock
+ @discussion
+ Although the lock operation spins, it employs various strategies
+ to back off if the lock is held, making it immune to most priority-inversion
+ livelocks.
+ */
void OSSpinLockLock( volatile OSSpinLock *__lock );
+
+
+/*! @abstract Unlocks a spinlock */
void OSSpinLockUnlock( volatile OSSpinLock *__lock );
-/* Lockless atomic enqueue and dequeue. These routines manipulate singly
- * linked LIFO lists. Ie, a dequeue will return the most recently enqueued
- * element, or NULL if the list is empty. The "offset" parameter is the offset
- * in bytes of the link field within the data structure being queued. The
- * link field should be a pointer type. Memory barriers are incorporated as
- * needed to permit thread-safe access to the queue element.
+/*! @group Lockless atomic enqueue and dequeue
+ * These routines manipulate singly-linked LIFO lists.
+ */
+
+/*! @abstract The data structure for a queue head.
+ @discussion
+ You should always initialize a queue head structure with the
+ initialization vector {@link OS_ATOMIC_QUEUE_INIT} before use.
*/
#if defined(__x86_64__)
typedef volatile struct {
void *opaque1;
long opaque2;
-} OSQueueHead __attribute__ ((aligned (16)));
+} __attribute__ ((aligned (16))) OSQueueHead;
#else
#endif
+/*! @abstract The initialization vector for a queue head. */
#define OS_ATOMIC_QUEUE_INIT { NULL, 0 }
-void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset);
-void* OSAtomicDequeue( OSQueueHead *__list, size_t __offset);
+/*! @abstract Enqueue an item onto a list.
+ @discussion
+ Memory barriers are incorporated as needed to permit thread-safe access
+ to the queue element.
+ @param __list
+ The list on which you want to enqueue the item.
+ @param __new
+ The item to add.
+ @param __offset
+ The "offset" parameter is the offset (in bytes) of the link field
+ from the beginning of the data structure being queued (<code>__new</code>).
+ The link field should be a pointer type.
+ The <code>__offset</code> value needs to be same for all enqueuing and
+ dequeuing operations on the same queue, even if different structure types
+ are enqueued on that queue. The use of <code>offsetset()</code>, defined in
+ <code>stddef.h</code> is the common way to specify the <code>__offset</code>
+ value.
+ */
+void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_4_0);
+
+
+/*! @abstract Dequeue an item from a list.
+ @discussion
+ Memory barriers are incorporated as needed to permit thread-safe access
+ to the queue element.
+ @param __list
+ The list on which you want to enqueue the item.
+ @param __offset
+ The "offset" parameter is the offset (in bytes) of the link field
+ from the beginning of the data structure being queued (<code>__new</code>).
+ The link field should be a pointer type.
+ The <code>__offset</code> value needs to be same for all enqueuing and
+ dequeuing operations on the same queue, even if different structure types
+ are enqueued on that queue. The use of <code>offsetset()</code>, defined in
+ <code>stddef.h</code> is the common way to specify the <code>__offset</code>
+ value.
+ @result
+ Returns the most recently enqueued element, or <code>NULL</code> if the
+ list is empty.
+ */
+void* OSAtomicDequeue( OSQueueHead *__list, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_4_0);
+#if defined(__x86_64__) || defined(__i386__)
-/* Memory barrier. It is both a read and write barrier.
+/*! @group Lockless atomic fifo enqueue and dequeue
+ * These routines manipulate singly-linked FIFO lists.
*/
-void OSMemoryBarrier( void );
+/*! @abstract The data structure for a fifo queue head.
+ @discussion
+ You should always initialize a fifo queue head structure with the
+ initialization vector {@link OS_ATOMIC_FIFO_QUEUE_INIT} before use.
+ */
+#if defined(__x86_64__)
+
+typedef volatile struct {
+ void *opaque1;
+ void *opaque2;
+ int opaque3;
+} __attribute__ ((aligned (16))) OSFifoQueueHead;
+
+#else
+
+typedef volatile struct {
+ void *opaque1;
+ void *opaque2;
+ int opaque3;
+} OSFifoQueueHead;
+
+#endif
+
+/*! @abstract The initialization vector for a fifo queue head. */
+#define OS_ATOMIC_FIFO_QUEUE_INIT { NULL, NULL, 0 }
+
+/*! @abstract Enqueue an item onto a list.
+ @discussion
+ Memory barriers are incorporated as needed to permit thread-safe access
+ to the queue element.
+ @param __list
+ The list on which you want to enqueue the item.
+ @param __new
+ The item to add.
+ @param __offset
+ The "offset" parameter is the offset (in bytes) of the link field
+ from the beginning of the data structure being queued (<code>__new</code>).
+ The link field should be a pointer type.
+ The <code>__offset</code> value needs to be same for all enqueuing and
+ dequeuing operations on the same queue, even if different structure types
+ are enqueued on that queue. The use of <code>offsetset()</code>, defined in
+ <code>stddef.h</code> is the common way to specify the <code>__offset</code>
+ value.
+ */
+void OSAtomicFifoEnqueue( OSFifoQueueHead *__list, void *__new, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+
+/*! @abstract Dequeue an item from a list.
+ @discussion
+ Memory barriers are incorporated as needed to permit thread-safe access
+ to the queue element.
+ @param __list
+ The list on which you want to enqueue the item.
+ @param __offset
+ The "offset" parameter is the offset (in bytes) of the link field
+ from the beginning of the data structure being queued (<code>__new</code>).
+ The link field should be a pointer type.
+ The <code>__offset</code> value needs to be same for all enqueuing and
+ dequeuing operations on the same queue, even if different structure types
+ are enqueued on that queue. The use of <code>offsetset()</code>, defined in
+ <code>stddef.h</code> is the common way to specify the <code>__offset</code>
+ value.
+ @result
+ Returns the oldest enqueued element, or <code>NULL</code> if the
+ list is empty.
+ */
+void* OSAtomicFifoDequeue( OSFifoQueueHead *__list, size_t __offset) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+
+#endif /* __i386__ || __x86_64__ */
+
+/*! @group Memory barriers */
+
+/*! @abstract Memory barrier.
+ @discussion
+ This function serves as both a read and write barrier.
+ */
+void OSMemoryBarrier( void );
__END_DECLS
#include <stddef.h>
#include <sys/cdefs.h>
#include <stdint.h>
+#include <Availability.h>
__BEGIN_DECLS
void sys_icache_invalidate( void *start, size_t len);
/* equivalent to sys_cache_control(kCacheFunctionFlushDcache): */
-void sys_dcache_flush( void *start, size_t len);
+void sys_dcache_flush( void *start, size_t len) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
__END_DECLS
#define _OSTHERMALNOTIFICATION_H_
#include <sys/cdefs.h>
+#include <Availability.h>
/*
** OSThermalNotification.h
typedef enum {
OSThermalNotificationLevelAny = -1,
OSThermalNotificationLevelNormal = 0,
- OSThermalNotificationLevel70PercentTorch = 1,
- OSThermalNotificationLevel70PercentBacklight = 3,
- OSThermalNotificationLevel50PercentTorch = 3,
- OSThermalNotificationLevel50PercentBacklight = 5,
- OSThermalNotificationLevelDisableTorch = 5,
- OSThermalNotificationLevel25PercentBacklight = 7,
- OSThermalNotificationLevelAppTerminate = 12,
- OSThermalNotificationLevelDeviceRestart = 16
} OSThermalNotificationLevel;
+extern OSThermalNotificationLevel _OSThermalNotificationLevelForBehavior(int) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_4_2);
+extern void _OSThermalNotificationSetLevelForBehavior(int, int) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_4_2);
+
+enum {
+ kOSThermalMitigationNone,
+ kOSThermalMitigation70PercentTorch,
+ kOSThermalMitigation70PercentBacklight,
+ kOSThermalMitigation50PercentTorch,
+ kOSThermalMitigation50PercentBacklight,
+ kOSThermalMitigationDisableTorch,
+ kOSThermalMitigation25PercentBacklight,
+ kOSThermalMitigationDisableMapsHalo,
+ kOSThermalMitigationAppTerminate,
+ kOSThermalMitigationDeviceRestart,
+ kOSThermalMitigationCount
+};
+
+#define OSThermalNotificationLevel70PercentTorch _OSThermalNotificationLevelForBehavior(kOSThermalMitigation70PercentTorch)
+#define OSThermalNotificationLevel70PercentBacklight _OSThermalNotificationLevelForBehavior(kOSThermalMitigation70PercentBacklight)
+#define OSThermalNotificationLevel50PercentTorch _OSThermalNotificationLevelForBehavior(kOSThermalMitigation50PercentTorch)
+#define OSThermalNotificationLevel50PercentBacklight _OSThermalNotificationLevelForBehavior(kOSThermalMitigation50PercentBacklight)
+#define OSThermalNotificationLevelDisableTorch _OSThermalNotificationLevelForBehavior(kOSThermalMitigationDisableTorch)
+#define OSThermalNotificationLevel25PercentBacklight _OSThermalNotificationLevelForBehavior(kOSThermalMitigation25PercentBacklight)
+#define OSThermalNotificationLevelDisableMapsHalo _OSThermalNotificationLevelForBehavior(kOSThermalMitigationDisableMapsHalo)
+#define OSThermalNotificationLevelAppTerminate _OSThermalNotificationLevelForBehavior(kOSThermalMitigationAppTerminate)
+#define OSThermalNotificationLevelDeviceRestart _OSThermalNotificationLevelForBehavior(kOSThermalMitigationDeviceRestart)
+
/* Backwards compatibility */
#define OSThermalNotificationLevelWarning OSThermalNotificationLevel70PercentBacklight
#define OSThermalNotificationLevelUrgent OSThermalNotificationLevelAppTerminate
** Simple polling interface to detect current thermal level
*/
-OSThermalNotificationLevel OSThermalNotificationCurrentLevel(void);
+extern OSThermalNotificationLevel OSThermalNotificationCurrentLevel(void) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_2_0);
/*
** External notify(3) string for manual notification setup
*/
-extern const char *kOSThermalNotificationName;
+extern const char * const kOSThermalNotificationName __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_2_0);
__END_DECLS
/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000, 2004-2007, 2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <machine/limits.h>
#include <sys/syslimits.h>
-#if !defined(_ANSI_SOURCE)
-#define _POSIX_AIO_LISTIO_MAX 2
-#define _POSIX_AIO_MAX 1
-#define _POSIX_DELAYTIMER_MAX 32
-#define _POSIX_HOST_NAME_MAX 255
-#define _POSIX_LOGIN_NAME_MAX 9
-#define _POSIX_MQ_OPEN_MAX 8
-#define _POSIX_MQ_PRIO_MAX 32
-
+#if __DARWIN_C_LEVEL > __DARWIN_C_ANSI
#define _POSIX_ARG_MAX 4096
#define _POSIX_CHILD_MAX 25
#define _POSIX_LINK_MAX 8
#define _POSIX_STREAM_MAX 8
#define _POSIX_TZNAME_MAX 6
-#define _POSIX_RE_DUP_MAX 255
+#define _POSIX2_BC_BASE_MAX 99
+#define _POSIX2_BC_DIM_MAX 2048
+#define _POSIX2_BC_SCALE_MAX 99
+#define _POSIX2_BC_STRING_MAX 1000
+#define _POSIX2_EQUIV_CLASS_MAX 2
+#define _POSIX2_EXPR_NEST_MAX 32
+#define _POSIX2_LINE_MAX 2048
+#define _POSIX2_RE_DUP_MAX 255
+#endif /* __DARWIN_C_LEVEL > __DARWIN_C_ANSI */
+
+#if __DARWIN_C_LEVEL >= 199309L
+#define _POSIX_AIO_LISTIO_MAX 2
+#define _POSIX_AIO_MAX 1
+#define _POSIX_DELAYTIMER_MAX 32
+#define _POSIX_MQ_OPEN_MAX 8
+#define _POSIX_MQ_PRIO_MAX 32
#define _POSIX_RTSIG_MAX 8
#define _POSIX_SEM_NSEMS_MAX 256
#define _POSIX_SEM_VALUE_MAX 32767
#define _POSIX_SIGQUEUE_MAX 32
-#define _POSIX_SS_REPL_MAX 4
-#define _POSIX_SYMLINK_MAX 255
-#define _POSIX_SYMLOOP_MAX 8
+#define _POSIX_TIMER_MAX 32
+#endif /* __DARWIN_C_LEVEL >= 199309L */
+
+#if __DARWIN_C_LEVEL >= 199506L
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
#define _POSIX_THREAD_KEYS_MAX 128
#define _POSIX_THREAD_THREADS_MAX 64
-#define _POSIX_TIMER_MAX 32
+#endif /* __DARWIN_C_LEVEL >= 199506L */
+
+#if __DARWIN_C_LEVEL >= 200112
+#define _POSIX_HOST_NAME_MAX 255
+#define _POSIX_LOGIN_NAME_MAX 9
+#define _POSIX_SS_REPL_MAX 4
+#define _POSIX_SYMLINK_MAX 255
+#define _POSIX_SYMLOOP_MAX 8
#define _POSIX_TRACE_EVENT_NAME_MAX 30
#define _POSIX_TRACE_NAME_MAX 8
#define _POSIX_TRACE_SYS_MAX 8
#define _POSIX_TRACE_USER_EVENT_MAX 32
#define _POSIX_TTY_NAME_MAX 9
-
-#define _POSIX2_BC_BASE_MAX 99
-#define _POSIX2_BC_DIM_MAX 2048
-#define _POSIX2_BC_SCALE_MAX 99
-#define _POSIX2_BC_STRING_MAX 1000
#define _POSIX2_CHARCLASS_NAME_MAX 14
#define _POSIX2_COLL_WEIGHTS_MAX 2
-#define _POSIX2_EQUIV_CLASS_MAX 2
-#define _POSIX2_EXPR_NEST_MAX 32
-#define _POSIX2_LINE_MAX 2048
-#define _POSIX2_RE_DUP_MAX 255
-#define PTHREAD_STACK_MIN 8192
+#define _POSIX_RE_DUP_MAX _POSIX2_RE_DUP_MAX
+#endif /* __DARWIN_C_LEVEL >= 200112 */
+
+#if __DARWIN_C_LEVEL >= 200809L
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
#define PTHREAD_KEYS_MAX 512
+#define PTHREAD_STACK_MIN 8192
+#endif /* __DARWIN_C_LEVEL >= 200809L */
-#if (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+#define OFF_MIN LLONG_MIN /* min value for an off_t */
+#define OFF_MAX LLONG_MAX /* max value for an off_t */
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
+
+/* Actually for XSI Visible */
+#if __DARWIN_C_LEVEL > __DARWIN_C_ANSI
+
+/* Removed in Issue 6 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
#define PASS_MAX 128
-#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
+#endif
#define NL_ARGMAX 9
#define NL_LANGMAX 14
#define _XOPEN_NAME_MAX 255
#define _XOPEN_PATH_MAX 1024
-#endif /* _ANSI_SOURCE */
+#endif /* __DARWIN_C_LEVEL > __DARWIN_C_ANSI */
/* NZERO to be defined here. TBD. See also sys/param.h */
#endif /* !_LIMITS_H_ */
-
#include <stddef.h>
#include <mach/mach_types.h>
#include <sys/cdefs.h>
+#include <Availability.h>
__BEGIN_DECLS
/********* Type definitions ************/
struct malloc_introspection_t *introspect;
unsigned version;
- /* aligned memory allocation. The callback may be NULL. */
- void *(*memalign)(struct _malloc_zone_t *zone, size_t alignment, size_t size);
+ /* aligned memory allocation. The callback may be NULL. Present in version >= 5. */
+ void *(*memalign)(struct _malloc_zone_t *zone, size_t alignment, size_t size);
- /* free a pointer known to be in zone and known to have the given size. The callback may be NULL. */
+ /* free a pointer known to be in zone and known to have the given size. The callback may be NULL. Present in version >= 6.*/
void (*free_definite_size)(struct _malloc_zone_t *zone, void *ptr, size_t size);
+
+ /* Empty out caches in the face of memory pressure. The callback may be NULL. Present in version >= 8. */
+ size_t (*pressure_relief)(struct _malloc_zone_t *zone, size_t goal);
} malloc_zone_t;
/********* Creation and destruction ************/
extern size_t malloc_good_size(size_t size);
/* Returns number of bytes greater than or equal to size that can be allocated without padding */
-extern void *malloc_zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size);
+extern void *malloc_zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
/*
* Allocates a new pointer of size size whose address is an exact multiple of alignment.
- * alignment must be a power of two and at least as large as sizeof(void *).
- * zone must be non-NULL.
- */
+ * alignment must be a power of two and at least as large as sizeof(void *).
+ * zone must be non-NULL.
+ */
/********* Batch methods ************/
/********* Functions for libcache ************/
-extern malloc_zone_t *malloc_default_purgeable_zone(void);
+extern malloc_zone_t *malloc_default_purgeable_zone(void) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
/* Returns a pointer to the default purgeable_zone. */
-extern void malloc_make_purgeable(void *ptr);
+extern void malloc_make_purgeable(void *ptr) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
/* Make an allocation from the purgeable zone purgeable if possible. */
-extern int malloc_make_nonpurgeable(void *ptr);
+extern int malloc_make_nonpurgeable(void *ptr) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
/* Makes an allocation from the purgeable zone nonpurgeable.
* Returns zero if the contents were not purged since the last
* call to malloc_make_purgeable, else returns non-zero. */
extern const char *malloc_get_zone_name(malloc_zone_t *zone);
/* Returns the name of a zone */
+size_t malloc_zone_pressure_relief(malloc_zone_t *zone, size_t goal) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+ /* malloc_zone_pressure_relief() advises the malloc subsystem that the process is under memory pressure and
+ * that the subsystem should make its best effort towards releasing (i.e. munmap()-ing) "goal" bytes from "zone".
+ * If "goal" is passed as zero, the malloc subsystem will attempt to achieve maximal pressure relief in "zone".
+ * If "zone" is passed as NULL, all zones are examined for pressure relief opportunities.
+ * malloc_zone_pressure_relief() returns the number of bytes released.
+ */
+
typedef struct {
vm_address_t address;
vm_size_t size;
void (*force_lock)(malloc_zone_t *zone); /* Forces locking zone */
void (*force_unlock)(malloc_zone_t *zone); /* Forces unlocking zone */
void (*statistics)(malloc_zone_t *zone, malloc_statistics_t *stats); /* Fills statistics */
- boolean_t (*zone_locked)(malloc_zone_t *zone); /* Are any zone locks held */
+ boolean_t (*zone_locked)(malloc_zone_t *zone); /* Are any zone locks held */
+
+ /* Discharge checking. Present in version >= 7. */
+ boolean_t (*enable_discharge_checking)(malloc_zone_t *zone);
+ void (*disable_discharge_checking)(malloc_zone_t *zone);
+ void (*discharge)(malloc_zone_t *zone, void *memory);
+#ifdef __BLOCKS__
+ void (*enumerate_discharged_pointers)(malloc_zone_t *zone, void (^report_discharged)(void *memory, void *info));
+#else
+ void *enumerate_unavailable_without_blocks;
+#endif /* __BLOCKS__ */
} malloc_introspection_t;
extern void malloc_printf(const char *format, ...);
extern struct mstats mstats(void);
+extern boolean_t malloc_zone_enable_discharge_checking(malloc_zone_t *zone) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+/* Increment the discharge checking enabled counter for a zone. Returns true if the zone supports checking, false if it does not. */
+
+extern void malloc_zone_disable_discharge_checking(malloc_zone_t *zone) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+/* Decrement the discharge checking enabled counter for a zone. */
+
+extern void malloc_zone_discharge(malloc_zone_t *zone, void *memory) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+/* Register memory that the programmer expects to be freed soon.
+ zone may be NULL in which case the zone is determined using malloc_zone_from_ptr().
+ If discharge checking is off for the zone this function is a no-op. */
+
+#ifdef __BLOCKS__
+extern void malloc_zone_enumerate_discharged_pointers(malloc_zone_t *zone, void (^report_discharged)(void *memory, void *info)) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+/* Calls report_discharged for each block that was registered using malloc_zone_discharge() but has not yet been freed.
+ info is used to provide zone defined information about the memory block.
+ If zone is NULL then the enumeration covers all zones. */
+#else
+extern void malloc_zone_enumerate_discharged_pointers(malloc_zone_t *zone, void *) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+#endif /* __BLOCKS__ */
+
__END_DECLS
#endif /* _MALLOC_MALLOC_H_ */
-/* $FreeBSD: src/include/nl_types.h,v 1.7 1999/08/27 23:44:51 peter Exp $ */
-
-/***********************************************************
-Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that Alfalfa's name not be used in
-advertising or publicity pertaining to distribution of the software
-without specific, written prior permission.
-
-ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-If you make any modifications, bugfixes or other changes to this software
-we'd appreciate it if you could send a copy to us so we can keep things
-up-to-date. Many thanks.
- Kee Hinckley
- Alfalfa Software, Inc.
- 267 Allston St., #3
- Cambridge, MA 02139 USA
- nazgul@alfalfa.com
-
-******************************************************************/
+/* $NetBSD: nl_types.h,v 1.9 2000/10/03 19:53:32 sommerfeld Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * 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.
+ *
+ * $FreeBSD: src/include/nl_types.h,v 1.11 2005/02/27 16:20:53 phantom Exp $
+ */
#ifndef _NL_TYPES_H_
#define _NL_TYPES_H_
+
#include <sys/cdefs.h>
+#include <sys/types.h>
#include <_types.h>
+#ifdef _NLS_PRIVATE
+/*
+ * MESSAGE CATALOG FILE FORMAT.
+ *
+ * The NetBSD/FreeBSD message catalog format is similar to the format used by
+ * Svr4 systems. The differences are:
+ * * fixed byte order (big endian)
+ * * fixed data field sizes
+ *
+ * A message catalog contains four data types: a catalog header, one
+ * or more set headers, one or more message headers, and one or more
+ * text strings.
+ */
+
+#define _NLS_MAGIC 0xff88ff89
+
+struct _nls_cat_hdr {
+ int32_t __magic;
+ int32_t __nsets;
+ int32_t __mem;
+ int32_t __msg_hdr_offset;
+ int32_t __msg_txt_offset;
+} ;
+
+struct _nls_set_hdr {
+ int32_t __setno; /* set number: 0 < x <= NL_SETMAX */
+ int32_t __nmsgs; /* number of messages in the set */
+ int32_t __index; /* index of first msg_hdr in msg_hdr table */
+} ;
+
+struct _nls_msg_hdr {
+ int32_t __msgno; /* msg number: 0 < x <= NL_MSGMAX */
+ int32_t __msglen;
+ int32_t __offset;
+} ;
+
+#endif /* _NLS_PRIVATE */
+
#define NL_SETD 1
#define NL_CAT_LOCALE 1
+typedef struct __nl_cat_d {
+ void *__data;
+ int __size;
+} *nl_catd;
+
#ifndef _NL_ITEM
-typedef __darwin_nl_item nl_item;
+typedef __darwin_nl_item nl_item;
#define _NL_ITEM
#endif
-typedef void *nl_catd;
-
__BEGIN_DECLS
-extern nl_catd catopen(const char *, int);
-extern char *catgets(nl_catd, int, int, const char *);
-extern int catclose(nl_catd);
+nl_catd catopen(const char *, int);
+char *catgets(nl_catd, int, int, const char *)
+ __attribute__((__format_arg__(4)));
+int catclose(nl_catd);
__END_DECLS
#endif /* _NL_TYPES_H_ */
-PROTO_INSTHDRS += dumprestore.h \
- routed.h \
+PROTO_INSTHDRS += routed.h \
rwhod.h \
talkd.h \
timed.h
+++ /dev/null
-/*
- * Copyright (c) 2000, 2006, 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@
- */
-/*
- * Copyright (c) 1980, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * 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.
- *
- * @(#)dumprestore.h 8.2 (Berkeley) 1/21/94
- */
-
-#ifndef _DUMPRESTORE_H_
-#define _DUMPRESTORE_H_
-
-/*
- * TP_BSIZE is the size of file blocks on the dump tapes.
- * Note that TP_BSIZE must be a multiple of DEV_BSIZE.
- *
- * NTREC is the number of TP_BSIZE blocks that are written
- * in each tape record. HIGHDENSITYTREC is the number of
- * TP_BSIZE blocks that are written in each tape record on
- * 6250 BPI or higher density tapes.
- *
- * TP_NINDIR is the number of indirect pointers in a TS_INODE
- * or TS_ADDR record. Note that it must be a power of two.
- */
-#define TP_BSIZE 1024
-#define NTREC 10
-#define HIGHDENSITYTREC 32
-#define TP_NINDIR (TP_BSIZE/2)
-#define LBLSIZE 16
-#define NAMELEN 64
-
-#define OFS_MAGIC (int)60011
-#define NFS_MAGIC (int)60012
-#define CHECKSUM (int)84446
-
-union u_spcl {
- char dummy[TP_BSIZE];
- struct s_spcl {
-#ifdef __LP64__
- int c_type; /* record type (see below) */
- int c_date; /* date of this dump */
- int c_ddate; /* date of previous dump */
- int c_volume; /* dump volume number */
-#else /* !__LP64__ */
- long c_type; /* record type (see below) */
- time_t c_date; /* date of this dump */
- time_t c_ddate; /* date of previous dump */
- long c_volume; /* dump volume number */
-#endif /* __LP64__ */
- daddr_t c_tapea; /* logical block of this record */
- unsigned int c_inumber; /* number of inode; truncation can occur for 64-bit ino_t */
-#ifdef __LP64__
- int c_magic; /* magic number (see above) */
- int c_checksum; /* record checksum */
-#else /* !__LP64__ */
- long c_magic; /* magic number (see above) */
- long c_checksum; /* record checksum */
-#endif /* __LP64__ */
- struct dinode c_dinode; /* ownership and mode of inode */
-#ifdef __LP64__
- int c_count; /* number of valid c_addr entries */
-#else /* !__LP64__ */
- long c_count; /* number of valid c_addr entries */
-#endif /* __LP64__ */
- char c_addr[TP_NINDIR]; /* 1 => data; 0 => hole in inode */
- char c_label[LBLSIZE]; /* dump label */
-#ifdef __LP64__
- int c_level; /* level of this dump */
-#else /* !__LP64__ */
- long c_level; /* level of this dump */
-#endif /* __LP64__ */
- char c_filesys[NAMELEN]; /* name of dumpped file system */
- char c_dev[NAMELEN]; /* name of dumpped device */
- char c_host[NAMELEN]; /* name of dumpped host */
-#ifdef __LP64__
- int c_flags; /* additional information */
- int c_firstrec; /* first record on volume */
- int c_spare[32]; /* reserved for future uses */
-#else /* !__LP64__ */
- long c_flags; /* additional information */
- long c_firstrec; /* first record on volume */
- long c_spare[32]; /* reserved for future uses */
-#endif /* __LP64__ */
- } s_spcl;
-};
-
-/*
- * special record types
- */
-#define TS_TAPE 1 /* dump tape header */
-#define TS_INODE 2 /* beginning of file record */
-#define TS_ADDR 4 /* continuation of file record */
-#define TS_BITS 3 /* map of inodes on tape */
-#define TS_CLRI 6 /* map of inodes deleted since last dump */
-#define TS_END 5 /* end of volume marker */
-
-/*
- * flag values
- */
-#define DR_NEWHEADER 0x0001 /* new format tape header */
-#define DR_NEWINODEFMT 0x0002 /* new format inodes on tape */
-
-#define DUMPOUTFMT "%-16s %c %s" /* for printf */
- /* name, level, ctime(date) */
-#define DUMPINFMT "%16s %c %[^\n]\n" /* inverse for scanf */
-
-#endif /* !_DUMPRESTORE_H_ */
#include <runetype.h>
#include <stdio.h>
-#include <AvailabilityMacros.h>
+#include <Availability.h>
/*--------------------------- DEPRECIATED -------------------------------
* This interface is depreciated and will eventually be removed. The ISO C99
#define sputrune(c, s, n, r) (*__sputrune)((c), (s), (n), (r))
__BEGIN_DECLS
-char *mbrune(const char *, rune_t) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
-char *mbrrune(const char *, rune_t) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
-char *mbmb(const char *, char *) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
-long fgetrune(FILE *) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
-int fputrune(rune_t, FILE *) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
-int fungetrune(rune_t, FILE *) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
-int setrunelocale(char *) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
-void setinvalidrune(rune_t) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+char *mbrune(const char *, rune_t) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
+char *mbrrune(const char *, rune_t) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
+char *mbmb(const char *, char *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
+long fgetrune(FILE *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
+int fputrune(rune_t, FILE *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
+int fungetrune(rune_t, FILE *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
+int setrunelocale(char *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
+void setinvalidrune(rune_t) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_4, __IPHONE_NA, __IPHONE_NA);
__END_DECLS
#endif /*! _RUNE_H_ */
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#undef sprintf
#undef vsprintf
+
+#if __DARWIN_C_LEVEL >= 200112L
#undef snprintf
#undef vsnprintf
+#endif
/* sprintf, vsprintf, snprintf, vsnprintf */
const char * __restrict, ...)
__DARWIN_LDBL_COMPAT (__snprintf_chk);
+#if __DARWIN_C_LEVEL >= 200112L
#define snprintf(str, len, ...) \
__builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
#define vsnprintf(str, len, format, ap) \
__builtin___vsnprintf_chk (str, len, 0, __darwin_obsz(str), format, ap)
-
+#endif
#endif
#if _USE_FORTIFY_LEVEL > 0
-/* memcpy, mempcpy, memmove, memset, strcpy, stpcpy, strncpy, strcat
- and strncat */
+/* memcpy, mempcpy, memmove, memset, strcpy, stpcpy, strncpy, stpncpy,
+ strcat, and strncat */
#undef memcpy
#undef memmove
#undef memset
#undef strcpy
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+#if __DARWIN_C_LEVEL >= 200809L
#undef stpcpy
-#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
+#undef stpncpy
+#endif
#undef strncpy
#undef strcat
+#if ! (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 32000)
#undef strncat
+#endif
#define memcpy(dest, src, len) \
((__darwin_obsz0 (dest) != (size_t) -1) \
return __builtin___strcpy_chk (__dest, __src, __darwin_obsz(__dest));
}
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+#if __DARWIN_C_LEVEL >= 200809L
#define stpcpy(dest, src) \
((__darwin_obsz0 (dest) != (size_t) -1) \
? __builtin___stpcpy_chk (dest, src, __darwin_obsz (dest)) \
{
return __builtin___stpcpy_chk (__dest, __src, __darwin_obsz(__dest));
}
-#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
+
+#define stpncpy(dest, src, len) \
+ ((__darwin_obsz0 (dest) != (size_t) -1) \
+ ? __builtin___stpncpy_chk (dest, src, len, __darwin_obsz (dest)) \
+ : __inline_stpncpy_chk (dest, src, len))
+
+static __inline char *
+__inline_stpncpy_chk (char *__restrict __dest, const char *__restrict __src,
+ size_t __len)
+{
+ return __builtin___stpncpy_chk (__dest, __src, __len, __darwin_obsz(__dest));
+}
+#endif
#define strncpy(dest, src, len) \
((__darwin_obsz0 (dest) != (size_t) -1) \
return __builtin___strcat_chk (__dest, __src, __darwin_obsz(__dest));
}
+#if ! (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 32000)
#define strncat(dest, src, len) \
((__darwin_obsz0 (dest) != (size_t) -1) \
? __builtin___strncat_chk (dest, src, len, __darwin_obsz (dest)) \
{
return __builtin___strncat_chk (__dest, __src, __len, __darwin_obsz(__dest));
}
+#endif
#endif
#endif
/*
- * Copyright (c) 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2006, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <_types.h>
#include <sys/spawn.h> /* shared types */
+#include <Availability.h>
+
/*
* [SPN] Inclusion of the <spawn.h> header may make visible symbols defined
* in the <sched.h>, <signal.h>, and <sys/types.h> headers.
const posix_spawn_file_actions_t *,
const posix_spawnattr_t * __restrict,
char *const __argv[ __restrict],
- char *const __envp[ __restrict]);
+ char *const __envp[ __restrict]) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnp(pid_t * __restrict, const char * __restrict,
const posix_spawn_file_actions_t *,
const posix_spawnattr_t * __restrict,
char *const __argv[ __restrict],
- char *const __envp[ __restrict]);
-int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int);
+ char *const __envp[ __restrict]) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int,
- int);
+ int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawn_file_actions_addopen(
posix_spawn_file_actions_t * __restrict, int,
- const char * __restrict, int, mode_t);
-int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *);
-int posix_spawn_file_actions_init(posix_spawn_file_actions_t *);
-int posix_spawnattr_destroy(posix_spawnattr_t *);
+ const char * __restrict, int, mode_t) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawn_file_actions_init(posix_spawn_file_actions_t *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawnattr_destroy(posix_spawnattr_t *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict,
- sigset_t * __restrict);
+ sigset_t * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_getflags(const posix_spawnattr_t * __restrict,
- short * __restrict);
+ short * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict,
- pid_t * __restrict);
+ pid_t * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict,
- sigset_t * __restrict);
-int posix_spawnattr_init(posix_spawnattr_t *);
+ sigset_t * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawnattr_init(posix_spawnattr_t *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict,
- const sigset_t * __restrict);
-int posix_spawnattr_setflags(posix_spawnattr_t *, short);
-int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t);
+ const sigset_t * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawnattr_setflags(posix_spawnattr_t *, short) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict,
- const sigset_t * __restrict);
+ const sigset_t * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
#if 0 /* _POSIX_PRIORITY_SCHEDULING [PS] : not supported */
int posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict,
__BEGIN_DECLS
int posix_spawnattr_getbinpref_np(const posix_spawnattr_t * __restrict,
- size_t, cpu_type_t *__restrict, size_t *__restrict);
+ size_t, cpu_type_t *__restrict, size_t *__restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_setauditsessionport_np(posix_spawnattr_t *__restrict,
- mach_port_t);
+ mach_port_t) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
int posix_spawnattr_setbinpref_np(posix_spawnattr_t * __restrict,
- size_t, cpu_type_t *__restrict, size_t *__restrict);
+ size_t, cpu_type_t *__restrict, size_t *__restrict) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_setexceptionports_np(posix_spawnattr_t *__restrict,
exception_mask_t, mach_port_t,
- exception_behavior_t, thread_state_flavor_t);
+ exception_behavior_t, thread_state_flavor_t) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
int posix_spawnattr_setspecialport_np(posix_spawnattr_t *__restrict,
- mach_port_t, int);
+ mach_port_t, int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t *,
+ int) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+
__END_DECLS
#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
#define _SPAWN_PRIVATE_H_
#include <spawn.h>
+#include <sys/cdefs.h>
+#include <Availability.h>
-int posix_spawnattr_getpcontrol_np(const posix_spawnattr_t * __restrict, int * __restrict);
-int posix_spawnattr_setpcontrol_np(posix_spawnattr_t *, const int);
+int posix_spawnattr_getpcontrol_np(const posix_spawnattr_t * __restrict, int * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
+int posix_spawnattr_setpcontrol_np(posix_spawnattr_t *, const int) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* !defined _SPAWN_PRIVATE_H_*/
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/cdefs.h>
-#if defined(_POSIX_C_SOURCE) && !defined(_DARWIN_C_SOURCE)
-# ifndef __STRICT_ANSI__
-# define __STRICT_ANSI__
-# endif
-# undef __STRICT_BSD__
-#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
+#warning "The use of <standards.h> is deprecated, and it will be removed in a future release."
#endif /* _STANDARDS_H */
+++ /dev/null
-/* This file is public domain. */
-/* GCC uses its own copy of this header */
-#if defined(__GNUC__)
-#include_next <stdarg.h>
-#elif defined(__MWERKS__)
-#include "mw_stdarg.h"
-#else
-#error "This header only supports __MWERKS__."
-#endif
typedef int _Bool;
#endif
-#define false (bool)0
-#define true (bool)1
+#define false 0
+#define true 1
#endif /* !__cplusplus */
#ifdef __STDDEF_H__
#if defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 5 || __GNUC__ > 3)
-#ifndef __offsetof /* Deprecated: for source compatability only */
+#ifndef __offsetof /* Deprecated: for source compatibility only */
#define __offsetof(type, field) __builtin_offsetof(type, field)
#endif
#define offsetof(type, field) __builtin_offsetof(type, field)
#else /* ! (gcc >= 3.5) */
-#ifndef __offsetof /* Deprecated: for source compatability only */
+#ifndef __offsetof /* Deprecated: for source compatibility only */
#define __offsetof(type, field) ((size_t)(&((type *)0)->field))
#endif
#define offsetof(type, field) ((size_t)(&((type *)0)->field))
--- /dev/null
+/*
+ * Copyright (c) 2000-2010 Apple Inc.
+ * All rights reserved.
+ */
+
+#ifndef _STDINT_H_
+#define _STDINT_H_
+
+#if __LP64__
+#define __WORDSIZE 64
+#else
+#define __WORDSIZE 32
+#endif
+
+/* from ISO/IEC 988:1999 spec */
+
+/* 7.18.1.1 Exact-width integer types */
+#ifndef _INT8_T
+#define _INT8_T
+typedef signed char int8_t;
+#endif /*_INT8_T */
+
+#ifndef _INT16_T
+#define _INT16_T
+typedef short int16_t;
+#endif /* _INT16_T */
+
+#ifndef _INT32_T
+#define _INT32_T
+typedef int int32_t;
+#endif /* _INT32_T */
+
+#ifndef _INT64_T
+#define _INT64_T
+typedef long long int64_t;
+#endif /* _INT64_T */
+
+#ifndef _UINT8_T
+#define _UINT8_T
+typedef unsigned char uint8_t;
+#endif /*_UINT8_T */
+
+#ifndef _UINT16_T
+#define _UINT16_T
+typedef unsigned short uint16_t;
+#endif /* _UINT16_T */
+
+#ifndef _UINT32_T
+#define _UINT32_T
+typedef unsigned int uint32_t;
+#endif /* _UINT32_T */
+
+#ifndef _UINT64_T
+#define _UINT64_T
+typedef unsigned long long uint64_t;
+#endif /* _UINT64_T */
+
+/* 7.18.1.2 Minimum-width integer types */
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+
+/* 7.18.1.3 Fastest-width integer types */
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+
+/* 7.18.1.4 Integer types capable of holding object pointers */
+
+#ifndef _INTPTR_T
+#define _INTPTR_T
+typedef long intptr_t;
+#endif /* _INTPTR_T */
+
+#ifndef _UINTPTR_T
+#define _UINTPTR_T
+typedef unsigned long uintptr_t;
+#endif /* _UINTPTR_T */
+
+
+/* 7.18.1.5 Greatest-width integer types */
+#ifndef _INTMAX_T
+#define _INTMAX_T
+#ifdef __INTMAX_TYPE__
+typedef __INTMAX_TYPE__ intmax_t;
+#else /* __INTMAX_TYPE__ */
+typedef long long intmax_t;
+#endif /* __INTMAX_TYPE__ */
+#endif /* _INTMAX_T */
+
+#ifndef _UINTMAX_T
+#define _UINTMAX_T
+#ifdef __UINTMAX_TYPE__
+typedef __UINTMAX_TYPE__ uintmax_t;
+#else /* __UINTMAX_TYPE__ */
+typedef unsigned long long uintmax_t;
+#endif /* __UINTMAX_TYPE__ */
+#endif /* _UINTMAX_T */
+
+/* 7.18.2 Limits of specified-width integer types:
+ * These #defines specify the minimum and maximum limits
+ * of each of the types declared above.
+ */
+
+
+/* 7.18.2.1 Limits of exact-width integer types */
+#define INT8_MAX 127
+#define INT16_MAX 32767
+#define INT32_MAX 2147483647
+#define INT64_MAX 9223372036854775807LL
+
+#define INT8_MIN -128
+#define INT16_MIN -32768
+ /*
+ Note: the literal "most negative int" cannot be written in C --
+ the rules in the standard (section 6.4.4.1 in C99) will give it
+ an unsigned type, so INT32_MIN (and the most negative member of
+ any larger signed type) must be written via a constant expression.
+ */
+#define INT32_MIN (-INT32_MAX-1)
+#define INT64_MIN (-INT64_MAX-1)
+
+#define UINT8_MAX 255
+#define UINT16_MAX 65535
+#define UINT32_MAX 4294967295U
+#define UINT64_MAX 18446744073709551615ULL
+
+/* 7.18.2.2 Limits of minimum-width integer types */
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST64_MIN INT64_MIN
+
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MAX INT64_MAX
+
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+/* 7.18.2.3 Limits of fastest minimum-width integer types */
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST64_MIN INT64_MIN
+
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MAX INT64_MAX
+
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+/* 7.18.2.4 Limits of integer types capable of holding object pointers */
+
+#if __WORDSIZE == 64
+#define INTPTR_MIN INT64_MIN
+#define INTPTR_MAX INT64_MAX
+#else
+#define INTPTR_MIN INT32_MIN
+#define INTPTR_MAX INT32_MAX
+#endif
+
+#if __WORDSIZE == 64
+#define UINTPTR_MAX UINT64_MAX
+#else
+#define UINTPTR_MAX UINT32_MAX
+#endif
+
+/* 7.18.2.5 Limits of greatest-width integer types */
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+
+#define UINTMAX_MAX UINT64_MAX
+
+/* 7.18.3 "Other" */
+#if __WORDSIZE == 64
+#define PTRDIFF_MIN INT64_MIN
+#define PTRDIFF_MAX INT64_MAX
+#else
+#define PTRDIFF_MIN INT32_MIN
+#define PTRDIFF_MAX INT32_MAX
+#endif
+
+/* We have no sig_atomic_t yet, so no SIG_ATOMIC_{MIN,MAX}.
+ Should end up being {-127,127} or {0,255} ... or bigger.
+ My bet would be on one of {U}INT32_{MIN,MAX}. */
+
+#if __WORDSIZE == 64
+#define SIZE_MAX UINT64_MAX
+#else
+#define SIZE_MAX UINT32_MAX
+#endif
+
+#ifndef WCHAR_MAX
+# ifdef __WCHAR_MAX__
+# define WCHAR_MAX __WCHAR_MAX__
+# else
+# define WCHAR_MAX 0x7fffffff
+# endif
+#endif
+
+/* WCHAR_MIN should be 0 if wchar_t is an unsigned type and
+ (-WCHAR_MAX-1) if wchar_t is a signed type. Unfortunately,
+ it turns out that -fshort-wchar changes the signedness of
+ the type. */
+#ifndef WCHAR_MIN
+# if WCHAR_MAX == 0xffff
+# define WCHAR_MIN 0
+# else
+# define WCHAR_MIN (-WCHAR_MAX-1)
+# endif
+#endif
+
+#define WINT_MIN INT32_MIN
+#define WINT_MAX INT32_MAX
+
+#define SIG_ATOMIC_MIN INT32_MIN
+#define SIG_ATOMIC_MAX INT32_MAX
+
+/* 7.18.4 Macros for integer constants */
+#define INT8_C(v) (v)
+#define INT16_C(v) (v)
+#define INT32_C(v) (v)
+#define INT64_C(v) (v ## LL)
+
+#define UINT8_C(v) (v ## U)
+#define UINT16_C(v) (v ## U)
+#define UINT32_C(v) (v ## U)
+#define UINT64_C(v) (v ## ULL)
+
+#define INTMAX_C(v) (v ## LL)
+#define UINTMAX_C(v) (v ## ULL)
+
+#endif /* _STDINT_H_ */
/*
- * Copyright (c) 2000, 2005, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2005, 2007, 2009, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#ifndef _STDIO_H_
#define _STDIO_H_
+#include <sys/cdefs.h>
+#include <Availability.h>
+
#include <_types.h>
#ifndef _VA_LIST
typedef __darwin_va_list va_list;
#endif
-#ifndef _OFF_T
-#define _OFF_T
-typedef __darwin_off_t off_t;
-#endif
-
#ifndef _SIZE_T
#define _SIZE_T
typedef __darwin_size_t size_t;
} FILE;
__BEGIN_DECLS
-#if __DARWIN_UNIX03
extern FILE *__stdinp;
extern FILE *__stdoutp;
extern FILE *__stderrp;
-#else /* !__DARWIN_UNIX03 */
-extern FILE __sF[];
-#endif /* __DARWIN_UNIX03 */
__END_DECLS
#define __SLBF 0x0001 /* line buffered */
#define BUFSIZ 1024 /* size of buffer used by setbuf */
#define EOF (-1)
-/*
- * FOPEN_MAX is a minimum maximum, and is the number of streams that
- * stdio can provide without attempting to allocate further resources
- * (which could fail). Do not use this for anything.
- */
/* must be == _POSIX_STREAM_MAX <limits.h> */
#define FOPEN_MAX 20 /* must be <= OPEN_MAX <sys/syslimits.h> */
#define FILENAME_MAX 1024 /* must be <= PATH_MAX <sys/syslimits.h> */
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
-#if __DARWIN_UNIX03
#define stdin __stdinp
#define stdout __stdoutp
#define stderr __stderrp
-#else /* !__DARWIN_UNIX03 */
-#define stdin (&__sF[0])
-#define stdout (&__sF[1])
-#define stderr (&__sF[2])
-#endif /* __DARWIN_UNIX03 */
-/*
- * Functions defined in ANSI C standard.
- */
+#ifdef _DARWIN_UNLIMITED_STREAMS
+#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2
+#error "_DARWIN_UNLIMITED_STREAMS specified, but -miphoneos-version-min version does not support it."
+#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6
+#error "_DARWIN_UNLIMITED_STREAMS specified, but -mmacosx-version-min version does not support it."
+#endif
+#endif
+
+/* ANSI-C */
+
__BEGIN_DECLS
void clearerr(FILE *);
int fclose(FILE *);
int fgetc(FILE *);
int fgetpos(FILE * __restrict, fpos_t *);
char *fgets(char * __restrict, int, FILE *);
-#if defined(__DARWIN_10_6_AND_LATER) && (defined(_DARWIN_UNLIMITED_STREAMS) || defined(_DARWIN_C_SOURCE))
-FILE *fopen(const char * __restrict, const char * __restrict) __DARWIN_EXTSN(fopen);
-#else /* < 10.6 || !_DARWIN_UNLIMITED_STREAMS && !_DARWIN_C_SOURCE */
+#if defined(_DARWIN_UNLIMITED_STREAMS) || defined(_DARWIN_C_SOURCE)
+FILE *fopen(const char * __restrict, const char * __restrict) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_3_2, __DARWIN_EXTSN(fopen));
+#else /* !_DARWIN_UNLIMITED_STREAMS && !_DARWIN_C_SOURCE */
//Begin-Libc
#ifndef LIBC_ALIAS_FOPEN
//End-Libc
-FILE *fopen(const char * __restrict, const char * __restrict) __DARWIN_10_6_AND_LATER_ALIAS(__DARWIN_ALIAS(fopen));
+FILE *fopen(const char * __restrict, const char * __restrict) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_2_0, __DARWIN_ALIAS(fopen));
//Begin-Libc
#else /* LIBC_ALIAS_FOPEN */
FILE *fopen(const char * __restrict, const char * __restrict) LIBC_ALIAS(fopen);
#endif /* !LIBC_ALIAS_FOPEN */
//End-Libc
-#endif /* >= 10.6 &&_(DARWIN_UNLIMITED_STREAMS || _DARWIN_C_SOURCE) */
-int fprintf(FILE * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(fprintf);
+#endif /* (DARWIN_UNLIMITED_STREAMS || _DARWIN_C_SOURCE) */
+int fprintf(FILE * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(fprintf) __printflike(2, 3);
int fputc(int, FILE *);
//Begin-Libc
#ifndef LIBC_ALIAS_FPUTS
#ifndef LIBC_ALIAS_FREOPEN
//End-Libc
FILE *freopen(const char * __restrict, const char * __restrict,
- FILE * __restrict) __DARWIN_ALIAS(freopen);
+ FILE * __restrict) __DARWIN_ALIAS(freopen);
//Begin-Libc
#else /* LIBC_ALIAS_FREOPEN */
FILE *freopen(const char * __restrict, const char * __restrict,
- FILE * __restrict) LIBC_ALIAS(freopen);
+ FILE * __restrict) LIBC_ALIAS(freopen);
#endif /* !LIBC_ALIAS_FREOPEN */
//End-Libc
-int fscanf(FILE * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(fscanf);
+int fscanf(FILE * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(fscanf) __scanflike(2, 3);
int fseek(FILE *, long, int);
int fsetpos(FILE *, const fpos_t *);
long ftell(FILE *);
int getc(FILE *);
int getchar(void);
char *gets(char *);
-#if !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
-extern __const int sys_nerr; /* perror(3) external variables */
-extern __const char *__const sys_errlist[];
-#endif
void perror(const char *);
-int printf(const char * __restrict, ...) __DARWIN_LDBL_COMPAT(printf);
+int printf(const char * __restrict, ...) __DARWIN_LDBL_COMPAT(printf) __printflike(1, 2);
int putc(int, FILE *);
int putchar(int);
int puts(const char *);
int remove(const char *);
int rename (const char *, const char *);
void rewind(FILE *);
-int scanf(const char * __restrict, ...) __DARWIN_LDBL_COMPAT(scanf);
+int scanf(const char * __restrict, ...) __DARWIN_LDBL_COMPAT(scanf) __scanflike(1, 2);
void setbuf(FILE * __restrict, char * __restrict);
int setvbuf(FILE * __restrict, char * __restrict, int, size_t);
-int sprintf(char * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(sprintf);
-int sscanf(const char * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(sscanf);
+int sprintf(char * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(sprintf) __printflike(2, 3);
+int sscanf(const char * __restrict, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(sscanf) __scanflike(2, 3);
FILE *tmpfile(void);
char *tmpnam(char *);
int ungetc(int, FILE *);
-int vfprintf(FILE * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vfprintf);
-int vprintf(const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vprintf);
-int vsprintf(char * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vsprintf);
-#if !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
-int asprintf(char **, const char *, ...) __DARWIN_LDBL_COMPAT(asprintf);
-int vasprintf(char **, const char *, va_list) __DARWIN_LDBL_COMPAT(vasprintf);
-#endif
+int vfprintf(FILE * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vfprintf) __printflike(2, 0);
+int vprintf(const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vprintf) __printflike(1, 0);
+int vsprintf(char * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vsprintf) __printflike(2, 0);
__END_DECLS
-/*
- * Functions defined in POSIX 1003.1.
+
+
+/* Additional functionality provided by:
+ * POSIX.1-1988
*/
-#ifndef _ANSI_SOURCE
+
+#if __DARWIN_C_LEVEL >= 198808L
#define L_ctermid 1024 /* size for ctermid(); PATH_MAX */
__BEGIN_DECLS
+#ifndef __CTERMID_DEFINED
+/* Multiply defined in stdio.h and unistd.h by SUS */
+#define __CTERMID_DEFINED 1
char *ctermid(char *);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-char *ctermid_r(char *);
-#endif /* not POSIX */
-#if defined(__DARWIN_10_6_AND_LATER) && (defined(_DARWIN_UNLIMITED_STREAMS) || defined(_DARWIN_C_SOURCE))
-FILE *fdopen(int, const char *) __DARWIN_EXTSN(fdopen);
-#else /* < 10.6 || !_DARWIN_UNLIMITED_STREAMS && !_DARWIN_C_SOURCE */
+#endif
+
+#if defined(_DARWIN_UNLIMITED_STREAMS) || defined(_DARWIN_C_SOURCE)
+FILE *fdopen(int, const char *) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_3_2, __DARWIN_EXTSN(fdopen));
+#else /* !_DARWIN_UNLIMITED_STREAMS && !_DARWIN_C_SOURCE */
//Begin-Libc
#ifndef LIBC_ALIAS_FDOPEN
//End-Libc
-FILE *fdopen(int, const char *) __DARWIN_10_6_AND_LATER_ALIAS(__DARWIN_ALIAS(fdopen));
+FILE *fdopen(int, const char *) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_2_0, __DARWIN_ALIAS(fdopen));
//Begin-Libc
#else /* LIBC_ALIAS_FDOPEN */
FILE *fdopen(int, const char *) LIBC_ALIAS(fdopen);
#endif /* !LIBC_ALIAS_FDOPEN */
//End-Libc
-#endif /* >= 10.6 &&_(DARWIN_UNLIMITED_STREAMS || _DARWIN_C_SOURCE) */
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-char *fgetln(FILE *, size_t *);
-#endif /* not POSIX */
+#endif /* (DARWIN_UNLIMITED_STREAMS || _DARWIN_C_SOURCE) */
int fileno(FILE *);
-void flockfile(FILE *);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-__const char
- *fmtcheck(const char *, const char *);
-int fpurge(FILE *);
-#endif /* not POSIX */
-int fseeko(FILE *, off_t, int);
-off_t ftello(FILE *);
-int ftrylockfile(FILE *);
-void funlockfile(FILE *);
-int getc_unlocked(FILE *);
-int getchar_unlocked(void);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-int getw(FILE *);
-#endif /* not POSIX */
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 198808L */
+
+
+/* Additional functionality provided by:
+ * POSIX.2-1992 C Language Binding Option
+ */
+
+#if __DARWIN_C_LEVEL >= 199209L
+__BEGIN_DECLS
int pclose(FILE *);
-#if defined(__DARWIN_10_6_AND_LATER) && (defined(_DARWIN_UNLIMITED_STREAMS) || defined(_DARWIN_C_SOURCE))
-FILE *popen(const char *, const char *) __DARWIN_EXTSN(popen);
-#else /* < 10.6 || !_DARWIN_UNLIMITED_STREAMS && !_DARWIN_C_SOURCE */
+#if defined(_DARWIN_UNLIMITED_STREAMS) || defined(_DARWIN_C_SOURCE)
+FILE *popen(const char *, const char *) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_3_2, __DARWIN_EXTSN(popen));
+#else /* !_DARWIN_UNLIMITED_STREAMS && !_DARWIN_C_SOURCE */
//Begin-Libc
#ifndef LIBC_ALIAS_POPEN
//End-Libc
-FILE *popen(const char *, const char *) __DARWIN_10_6_AND_LATER_ALIAS(__DARWIN_ALIAS(popen));
+FILE *popen(const char *, const char *) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_2_0, __DARWIN_ALIAS(popen));
//Begin-Libc
#else /* LIBC_ALIAS_POPEN */
FILE *popen(const char *, const char *) LIBC_ALIAS(popen);
#endif /* !LIBC_ALIAS_POPEN */
//End-Libc
-#endif /* >= 10.6 &&_(DARWIN_UNLIMITED_STREAMS || _DARWIN_C_SOURCE) */
-int putc_unlocked(int, FILE *);
-int putchar_unlocked(int);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-int putw(int, FILE *);
-void setbuffer(FILE *, char *, int);
-int setlinebuf(FILE *);
-#endif /* not POSIX */
-int snprintf(char * __restrict, size_t, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(snprintf);
-//Begin-Libc
-#ifndef LIBC_ALIAS_TEMPNAM
-//End-Libc
-char *tempnam(const char *, const char *) __DARWIN_ALIAS(tempnam);
-//Begin-Libc
-#else /* LIBC_ALIAS_TEMPNAM */
-char *tempnam(const char *, const char *) LIBC_ALIAS(tempnam);
-#endif /* !LIBC_ALIAS_TEMPNAM */
-//End-Libc
-int vfscanf(FILE * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vfscanf);
-int vscanf(const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vscanf);
-int vsnprintf(char * __restrict, size_t, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vsnprintf);
-int vsscanf(const char * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vsscanf);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-FILE *zopen(const char *, const char *, int);
-#endif /* not POSIX */
+#endif /* (DARWIN_UNLIMITED_STREAMS || _DARWIN_C_SOURCE) */
__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 199209L */
-/*
- * Stdio function-access interface.
- */
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-__BEGIN_DECLS
-FILE *funopen(const void *,
- int (*)(void *, char *, int),
- int (*)(void *, const char *, int),
- fpos_t (*)(void *, fpos_t, int),
- int (*)(void *));
-__END_DECLS
-#define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0)
-#define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0)
-#endif /* not POSIX */
-#endif /* not ANSI */
-/*
- * Functions internal to the implementation.
+
+
+/* Additional functionality provided by:
+ * POSIX.1c-1995,
+ * POSIX.1i-1995,
+ * and the omnibus ISO/IEC 9945-1: 1996
*/
+
+#if __DARWIN_C_LEVEL >= 199506L
+
+/* Functions internal to the implementation. */
__BEGIN_DECLS
int __srget(FILE *);
-int __svfscanf(FILE *, const char *, va_list) __DARWIN_LDBL_COMPAT(__svfscanf);
+int __svfscanf(FILE *, const char *, va_list) __DARWIN_LDBL_COMPAT(__svfscanf) __scanflike(2, 0);
int __swbuf(int, FILE *);
__END_DECLS
#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
#define __sfileno(p) ((p)->_file)
-#ifndef _ANSI_SOURCE
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-#define feof_unlocked(p) __sfeof(p)
-#define ferror_unlocked(p) __sferror(p)
-#define clearerr_unlocked(p) __sclearerr(p)
-#define fileno_unlocked(p) __sfileno(p)
-#endif /* not POSIX */
+__BEGIN_DECLS
+void flockfile(FILE *);
+int ftrylockfile(FILE *);
+void funlockfile(FILE *);
+int getc_unlocked(FILE *);
+int getchar_unlocked(void);
+int putc_unlocked(int, FILE *);
+int putchar_unlocked(int);
+
+/* Removed in Issue 6 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
+int getw(FILE *);
+int putw(int, FILE *);
+#endif
+
+//Begin-Libc
+#ifndef LIBC_ALIAS_TEMPNAM
+//End-Libc
+char *tempnam(const char *, const char *) __DARWIN_ALIAS(tempnam);
+//Begin-Libc
+#else /* LIBC_ALIAS_TEMPNAM */
+char *tempnam(const char *, const char *) LIBC_ALIAS(tempnam);
+#endif /* !LIBC_ALIAS_TEMPNAM */
+//End-Libc
+__END_DECLS
#ifndef lint
#define getc_unlocked(fp) __sgetc(fp)
#define getchar_unlocked() getc_unlocked(stdin)
#define putchar_unlocked(x) putc_unlocked(x, stdout)
-#endif /* not ANSI */
+#endif /* __DARWIN_C_LEVEL >= 199506L */
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2001
+ * ISO C99
+ */
+
+#if __DARWIN_C_LEVEL >= 200112L
+#ifndef _OFF_T
+#define _OFF_T
+typedef __darwin_off_t off_t;
+#endif
+
+__BEGIN_DECLS
+int fseeko(FILE *, off_t, int);
+off_t ftello(FILE *);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200112L */
+
+#if __DARWIN_C_LEVEL >= 200112L || defined(_C99_SOURCE) || defined(__cplusplus)
+__BEGIN_DECLS
+int snprintf(char * __restrict, size_t, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(snprintf) __printflike(3, 4);
+int vfscanf(FILE * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vfscanf) __scanflike(2, 0);
+int vscanf(const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vscanf) __scanflike(1, 0);
+int vsnprintf(char * __restrict, size_t, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vsnprintf) __printflike(3, 0);
+int vsscanf(const char * __restrict, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vsscanf) __scanflike(2, 0);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200112L || defined(_C99_SOURCE) || defined(__cplusplus) */
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2008
+ */
+
+#if __DARWIN_C_LEVEL >= 200809L
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef __darwin_ssize_t ssize_t;
+#endif
+
+__BEGIN_DECLS
+int dprintf(int, const char * __restrict, ...) __DARWIN_LDBL_COMPAT(dprintf) __printflike(2, 3) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int vdprintf(int, const char * __restrict, va_list) __DARWIN_LDBL_COMPAT(vdprintf) __printflike(2, 0) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+ssize_t getdelim(char ** __restrict, size_t * __restrict, int, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200809L */
+
+
+
+/* Darwin extensions */
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+__BEGIN_DECLS
+extern __const int sys_nerr; /* perror(3) external variables */
+extern __const char *__const sys_errlist[];
+
+int asprintf(char **, const char *, ...) __DARWIN_LDBL_COMPAT(asprintf) __printflike(2, 3);
+char *ctermid_r(char *);
+char *fgetln(FILE *, size_t *);
+__const char *fmtcheck(const char *, const char *);
+int fpurge(FILE *);
+void setbuffer(FILE *, char *, int);
+int setlinebuf(FILE *);
+int vasprintf(char **, const char *, va_list) __DARWIN_LDBL_COMPAT(vasprintf) __printflike(2, 0);
+FILE *zopen(const char *, const char *, int);
+
+
+/*
+ * Stdio function-access interface.
+ */
+FILE *funopen(const void *,
+ int (*)(void *, char *, int),
+ int (*)(void *, const char *, int),
+ fpos_t (*)(void *, fpos_t, int),
+ int (*)(void *));
+__END_DECLS
+#define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0)
+#define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0)
+
+#define feof_unlocked(p) __sfeof(p)
+#define ferror_unlocked(p) __sferror(p)
+#define clearerr_unlocked(p) __sclearerr(p)
+#define fileno_unlocked(p) __sfileno(p)
+
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
+
#ifdef _USE_EXTENDED_LOCALES_
#include <xlocale/_stdio.h>
int mblen(const char *, size_t);
size_t mbstowcs(wchar_t * __restrict , const char * __restrict, size_t);
int mbtowc(wchar_t * __restrict, const char * __restrict, size_t);
-int posix_memalign(void **, size_t, size_t);
+int posix_memalign(void **, size_t, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
void qsort(void *, size_t, size_t,
int (*)(const void *, const void *));
int rand(void);
u_int32_t
arc4random(void);
-void arc4random_addrandom(unsigned char *dat, int datlen);
+void arc4random_addrandom(unsigned char * /*dat*/, int /*datlen*/);
+void arc4random_buf(void * /*buf*/, size_t /*nbytes*/) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
void arc4random_stir(void);
+u_int32_t
+ arc4random_uniform(u_int32_t /*upper_bound*/) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
#ifdef __BLOCKS__
-int atexit_b(void (^)(void));
+int atexit_b(void (^)(void)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
void *bsearch_b(const void *, const void *, size_t,
- size_t, int (^)(const void *, const void *));
+ size_t, int (^)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* __BLOCKS__ */
/* getcap(3) functions */
int cgetstr(char *, const char *, char **);
int cgetustr(char *, const char *, char **);
-int daemon(int, int) __DARWIN_1050(daemon) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5,__IPHONE_2_0,__IPHONE_2_0);
+int daemon(int, int) __DARWIN_1050(daemon) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_5, __IPHONE_2_0, __IPHONE_2_0);
char *devname(dev_t, mode_t);
char *devname_r(dev_t, mode_t, char *buf, int len);
char *getbsize(int *, long *);
int (*)(const void *, const void *));
#ifdef __BLOCKS__
int heapsort_b(void *, size_t, size_t,
- int (^)(const void *, const void *));
+ int (^)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* __BLOCKS__ */
int mergesort(void *, size_t, size_t,
int (*)(const void *, const void *));
#ifdef __BLOCKS__
int mergesort_b(void *, size_t, size_t,
- int (^)(const void *, const void *));
+ int (^)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* __BLOCKS__ */
void psort(void *, size_t, size_t,
- int (*)(const void *, const void *));
+ int (*)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#ifdef __BLOCKS__
void psort_b(void *, size_t, size_t,
- int (^)(const void *, const void *));
+ int (^)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* __BLOCKS__ */
void psort_r(void *, size_t, size_t, void *,
- int (*)(void *, const void *, const void *));
+ int (*)(void *, const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#ifdef __BLOCKS__
void qsort_b(void *, size_t, size_t,
- int (^)(const void *, const void *));
+ int (^)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
#endif /* __BLOCKS__ */
void qsort_r(void *, size_t, size_t, void *,
int (*)(void *, const void *, const void *));
/*
- * Copyright (c) 2000, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2007, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#ifndef _STRING_H_
#define _STRING_H_
+
#include <_types.h>
+#include <sys/cdefs.h>
+#include <Availability.h>
+
#ifndef _SIZE_T
#define _SIZE_T
typedef __darwin_size_t size_t;
#endif
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) /* For swab */
-#ifndef _SSIZE_T
-#define _SSIZE_T
-typedef __darwin_ssize_t ssize_t;
-#endif
-#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
-
#ifndef NULL
#define NULL __DARWIN_NULL
#endif /* ! NULL */
-#include <sys/cdefs.h>
+
+
+/* ANSI-C */
__BEGIN_DECLS
void *memchr(const void *, int, size_t);
void *memcpy(void *, const void *, size_t);
void *memmove(void *, const void *, size_t);
void *memset(void *, int, size_t);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-char *stpcpy(char *, const char *);
-char *strcasestr(const char *, const char *);
-#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
char *strcat(char *, const char *);
char *strchr(const char *, int);
int strcmp(const char *, const char *);
char *strerror(int) LIBC_ALIAS(strerror);
#endif /* !LIBC_ALIAS_STRERROR */
//End-Libc
-int strerror_r(int, char *, size_t);
size_t strlen(const char *);
char *strncat(char *, const char *, size_t);
int strncmp(const char *, const char *, size_t);
char *strncpy(char *, const char *, size_t);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-char *strnstr(const char *, const char *, size_t);
-#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
char *strpbrk(const char *, const char *);
char *strrchr(const char *, int);
size_t strspn(const char *, const char *);
char *strstr(const char *, const char *);
char *strtok(char *, const char *);
size_t strxfrm(char *, const char *, size_t);
+__END_DECLS
-/* Nonstandard routines */
-#ifndef _ANSI_SOURCE
-void *memccpy(void *, const void *, int, size_t);
+
+
+/* Additional functionality provided by:
+ * POSIX.1c-1995,
+ * POSIX.1i-1995,
+ * and the omnibus ISO/IEC 9945-1: 1996
+ */
+
+#if __DARWIN_C_LEVEL >= 199506L
+__BEGIN_DECLS
char *strtok_r(char *, const char *, char **);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 199506L */
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2001
+ */
+
+#if __DARWIN_C_LEVEL >= 200112L
+__BEGIN_DECLS
+int strerror_r(int, char *, size_t);
char *strdup(const char *);
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-int bcmp(const void *, const void *, size_t);
-void bcopy(const void *, void *, size_t);
-void bzero(void *, size_t);
-int ffs(int);
-int ffsl(long);
-int fls(int);
-int flsl(long);
-char *index(const char *, int);
-void memset_pattern4(void *, const void *, size_t);
-void memset_pattern8(void *, const void *, size_t);
-void memset_pattern16(void *, const void *, size_t);
-char *rindex(const char *, int);
-int strcasecmp(const char *, const char *);
+void *memccpy(void *, const void *, int, size_t);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200112L */
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2008
+ */
+
+#if __DARWIN_C_LEVEL >= 200809L
+__BEGIN_DECLS
+char *stpcpy(char *, const char *);
+char *stpncpy(char *, const char *, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+char *strndup(const char *, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+size_t strnlen(const char *, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+char *strsignal(int sig);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200809L */
+
+
+
+/* Darwin extensions */
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef __darwin_ssize_t ssize_t;
+#endif
+
+__BEGIN_DECLS
+void *memmem(const void *, size_t, const void *, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+void memset_pattern4(void *, const void *, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0);
+void memset_pattern8(void *, const void *, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0);
+void memset_pattern16(void *, const void *, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0);
+
+char *strcasestr(const char *, const char *);
+char *strnstr(const char *, const char *, size_t);
size_t strlcat(char *, const char *, size_t);
size_t strlcpy(char *, const char *, size_t);
void strmode(int, char *);
-int strncasecmp(const char *, const char *, size_t);
char *strsep(char **, const char *);
-char *strsignal(int sig);
+
+/* SUS places swab() in unistd.h. It is listed here for source compatibility */
void swab(const void * __restrict, void * __restrict, ssize_t);
-#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
-#endif /* !_ANSI_SOURCE */
__END_DECLS
+/* Some functions historically defined in string.h were placed in strings.h
+ * by SUS. We are using "strings.h" instead of <strings.h> to avoid an issue
+ * where /Developer/Headers/FlatCarbon/Strings.h could be included instead on
+ * case-insensitive file systems.
+ */
+#include "strings.h"
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
+
+
#ifdef _USE_EXTENDED_LOCALES_
#include <xlocale/_string.h>
#endif /* _USE_EXTENDED_LOCALES_ */
/*
- * Copyright (c) 2000, 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2007, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* @(#)strings.h 8.1 (Berkeley) 6/2/93
*/
-#include <sys/cdefs.h>
-
-#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
-
-#include <string.h>
-
-#else
+#ifndef _STRINGS_H_
+#define _STRINGS_H_
#include <_types.h>
+#include <sys/cdefs.h>
+#include <Availability.h>
+
#ifndef _SIZE_T
#define _SIZE_T
typedef __darwin_size_t size_t;
#endif
__BEGIN_DECLS
-int bcmp(const void *, const void *, size_t);
-void bcopy(const void *, void *, size_t);
-void bzero(void *, size_t);
-int ffs(int);
-char *index(const char *, int);
-char *rindex(const char *, int);
-int strcasecmp(const char *, const char *);
-int strncasecmp(const char *, const char *, size_t);
+/* Removed in Issue 7 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L
+int bcmp(const void *, const void *, size_t) __POSIX_C_DEPRECATED(200112L);
+void bcopy(const void *, void *, size_t) __POSIX_C_DEPRECATED(200112L);
+void bzero(void *, size_t) __POSIX_C_DEPRECATED(200112L);
+char *index(const char *, int) __POSIX_C_DEPRECATED(200112L);
+char *rindex(const char *, int) __POSIX_C_DEPRECATED(200112L);
+#endif
+
+int ffs(int);
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size_t);
+__END_DECLS
+
+/* Darwin extensions */
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+__BEGIN_DECLS
+int ffsl(long) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int fls(int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int flsl(long) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
__END_DECLS
-#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
+#include <string.h>
+#endif
+
+#endif /* _STRINGS_H_ */
/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#ifndef _SYS_ACL_H
#define _SYS_ACL_H
+#include <Availability.h>
#include <sys/kauth.h>
+#define __DARWIN_ACL_READ_DATA (1<<1)
+#define __DARWIN_ACL_LIST_DIRECTORY __DARWIN_ACL_READ_DATA
+#define __DARWIN_ACL_WRITE_DATA (1<<2)
+#define __DARWIN_ACL_ADD_FILE __DARWIN_ACL_WRITE_DATA
+#define __DARWIN_ACL_EXECUTE (1<<3)
+#define __DARWIN_ACL_SEARCH __DARWIN_ACL_EXECUTE
+#define __DARWIN_ACL_DELETE (1<<4)
+#define __DARWIN_ACL_APPEND_DATA (1<<5)
+#define __DARWIN_ACL_ADD_SUBDIRECTORY __DARWIN_ACL_APPEND_DATA
+#define __DARWIN_ACL_DELETE_CHILD (1<<6)
+#define __DARWIN_ACL_READ_ATTRIBUTES (1<<7)
+#define __DARWIN_ACL_WRITE_ATTRIBUTES (1<<8)
+#define __DARWIN_ACL_READ_EXTATTRIBUTES (1<<9)
+#define __DARWIN_ACL_WRITE_EXTATTRIBUTES (1<<10)
+#define __DARWIN_ACL_READ_SECURITY (1<<11)
+#define __DARWIN_ACL_WRITE_SECURITY (1<<12)
+#define __DARWIN_ACL_CHANGE_OWNER (1<<13)
+
+#define __DARWIN_ACL_EXTENDED_ALLOW 1
+#define __DARWIN_ACL_EXTENDED_DENY 2
+
+#define __DARWIN_ACL_ENTRY_INHERITED (1<<4)
+#define __DARWIN_ACL_ENTRY_FILE_INHERIT (1<<5)
+#define __DARWIN_ACL_ENTRY_DIRECTORY_INHERIT (1<<6)
+#define __DARWIN_ACL_ENTRY_LIMIT_INHERIT (1<<7)
+#define __DARWIN_ACL_ENTRY_ONLY_INHERIT (1<<8)
+#define __DARWIN_ACL_FLAG_NO_INHERIT (1<<17)
+
/*
* Implementation constants.
*
/* 23.2.2 Individual object access permissions - nonstandard */
typedef enum {
- ACL_READ_DATA = KAUTH_VNODE_READ_DATA,
- ACL_LIST_DIRECTORY = KAUTH_VNODE_LIST_DIRECTORY,
- ACL_WRITE_DATA = KAUTH_VNODE_WRITE_DATA,
- ACL_ADD_FILE = KAUTH_VNODE_ADD_FILE,
- ACL_EXECUTE = KAUTH_VNODE_EXECUTE,
- ACL_SEARCH = KAUTH_VNODE_SEARCH,
- ACL_DELETE = KAUTH_VNODE_DELETE,
- ACL_APPEND_DATA = KAUTH_VNODE_APPEND_DATA,
- ACL_ADD_SUBDIRECTORY = KAUTH_VNODE_ADD_SUBDIRECTORY,
- ACL_DELETE_CHILD = KAUTH_VNODE_DELETE_CHILD,
- ACL_READ_ATTRIBUTES = KAUTH_VNODE_READ_ATTRIBUTES,
- ACL_WRITE_ATTRIBUTES = KAUTH_VNODE_WRITE_ATTRIBUTES,
- ACL_READ_EXTATTRIBUTES = KAUTH_VNODE_READ_EXTATTRIBUTES,
- ACL_WRITE_EXTATTRIBUTES = KAUTH_VNODE_WRITE_EXTATTRIBUTES,
- ACL_READ_SECURITY = KAUTH_VNODE_READ_SECURITY,
- ACL_WRITE_SECURITY = KAUTH_VNODE_WRITE_SECURITY,
- ACL_CHANGE_OWNER = KAUTH_VNODE_CHANGE_OWNER
+ ACL_READ_DATA = __DARWIN_ACL_READ_DATA,
+ ACL_LIST_DIRECTORY = __DARWIN_ACL_LIST_DIRECTORY,
+ ACL_WRITE_DATA = __DARWIN_ACL_WRITE_DATA,
+ ACL_ADD_FILE = __DARWIN_ACL_ADD_FILE,
+ ACL_EXECUTE = __DARWIN_ACL_EXECUTE,
+ ACL_SEARCH = __DARWIN_ACL_SEARCH,
+ ACL_DELETE = __DARWIN_ACL_DELETE,
+ ACL_APPEND_DATA = __DARWIN_ACL_APPEND_DATA,
+ ACL_ADD_SUBDIRECTORY = __DARWIN_ACL_ADD_SUBDIRECTORY,
+ ACL_DELETE_CHILD = __DARWIN_ACL_DELETE_CHILD,
+ ACL_READ_ATTRIBUTES = __DARWIN_ACL_READ_ATTRIBUTES,
+ ACL_WRITE_ATTRIBUTES = __DARWIN_ACL_WRITE_ATTRIBUTES,
+ ACL_READ_EXTATTRIBUTES = __DARWIN_ACL_READ_EXTATTRIBUTES,
+ ACL_WRITE_EXTATTRIBUTES = __DARWIN_ACL_WRITE_EXTATTRIBUTES,
+ ACL_READ_SECURITY = __DARWIN_ACL_READ_SECURITY,
+ ACL_WRITE_SECURITY = __DARWIN_ACL_WRITE_SECURITY,
+ ACL_CHANGE_OWNER = __DARWIN_ACL_CHANGE_OWNER,
} acl_perm_t;
/* 23.2.5 ACL entry tag type bits - nonstandard */
typedef enum {
ACL_UNDEFINED_TAG = 0,
- ACL_EXTENDED_ALLOW = KAUTH_ACE_PERMIT,
- ACL_EXTENDED_DENY = KAUTH_ACE_DENY
+ ACL_EXTENDED_ALLOW = __DARWIN_ACL_EXTENDED_ALLOW,
+ ACL_EXTENDED_DENY = __DARWIN_ACL_EXTENDED_DENY
} acl_tag_t;
/* 23.2.6 Individual ACL types */
/* nonstandard ACL / entry flags */
typedef enum {
ACL_FLAG_DEFER_INHERIT = (1 << 0), /* tentative */
- ACL_ENTRY_INHERITED = KAUTH_ACE_INHERITED,
- ACL_ENTRY_FILE_INHERIT = KAUTH_ACE_FILE_INHERIT,
- ACL_ENTRY_DIRECTORY_INHERIT = KAUTH_ACE_DIRECTORY_INHERIT,
- ACL_ENTRY_LIMIT_INHERIT = KAUTH_ACE_LIMIT_INHERIT,
- ACL_ENTRY_ONLY_INHERIT = KAUTH_ACE_ONLY_INHERIT
+ ACL_FLAG_NO_INHERIT = __DARWIN_ACL_FLAG_NO_INHERIT,
+ ACL_ENTRY_INHERITED = __DARWIN_ACL_ENTRY_INHERITED,
+ ACL_ENTRY_FILE_INHERIT = __DARWIN_ACL_ENTRY_FILE_INHERIT,
+ ACL_ENTRY_DIRECTORY_INHERIT = __DARWIN_ACL_ENTRY_DIRECTORY_INHERIT,
+ ACL_ENTRY_LIMIT_INHERIT = __DARWIN_ACL_ENTRY_LIMIT_INHERIT,
+ ACL_ENTRY_ONLY_INHERIT = __DARWIN_ACL_ENTRY_ONLY_INHERIT
} acl_flag_t;
/* "External" ACL types */
typedef struct _acl_permset *acl_permset_t;
typedef struct _acl_flagset *acl_flagset_t;
+typedef u_int64_t acl_permset_mask_t;
+
__BEGIN_DECLS
/* 23.1.6.1 ACL Storage Management */
extern acl_t acl_dup(acl_t acl);
extern int acl_get_permset(acl_entry_t entry_d, acl_permset_t *permset_p);
extern int acl_set_permset(acl_entry_t entry_d, acl_permset_t permset_d);
+/* nonstandard - manipulate permissions within an ACL entry using bitmasks */
+extern int acl_maximal_permset_mask_np(acl_permset_mask_t * mask_p) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+extern int acl_get_permset_mask_np(acl_entry_t entry_d, acl_permset_mask_t * mask_p) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+extern int acl_set_permset_mask_np(acl_entry_t entry_d, acl_permset_mask_t mask) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+
/* nonstandard - manipulate flags on ACLs and entries */
extern int acl_add_flag_np(acl_flagset_t flagset_d, acl_flag_t flag);
extern int acl_clear_flags_np(acl_flagset_t flagset_d);
//End-Libc
#ifdef _XOPEN_SOURCE
#include <sys/ucontext.h>
+#include <Availability.h>
__BEGIN_DECLS
-int getcontext(ucontext_t *);
-void makecontext(ucontext_t *, void (*)(), int, ...);
-int setcontext(const ucontext_t *);
-int swapcontext(ucontext_t * __restrict, const ucontext_t * __restrict);
+int getcontext(ucontext_t *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_6, __IPHONE_2_0, __IPHONE_2_0);
+void makecontext(ucontext_t *, void (*)(), int, ...) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_6, __IPHONE_2_0, __IPHONE_2_0);
+int setcontext(const ucontext_t *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_6, __IPHONE_2_0, __IPHONE_2_0);
+int swapcontext(ucontext_t * __restrict, const ucontext_t * __restrict) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_6, __IPHONE_2_0, __IPHONE_2_0);
__END_DECLS
#else /* !_XOPEN_SOURCE */
-#error ucontext routines are deprecated, and require _XOPEN_SOURCE to be defined
+#error The deprecated ucontext routines require _XOPEN_SOURCE to be defined
#endif /* _XOPEN_SOURCE */
//Begin-Libc
#endif /* __LIBC__ */
/*
- * Copyright (c) 2000, 2002-2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2000, 2002-2006, 2008-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <_types.h>
#include <sys/unistd.h>
-
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-#ifndef _DEV_T
-#define _DEV_T
-typedef __darwin_dev_t dev_t;
-#endif
-#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
+#include <Availability.h>
#ifndef _GID_T
#define _GID_T
typedef __darwin_intptr_t intptr_t;
#endif
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-#ifndef _MODE_T
-#define _MODE_T
-typedef __darwin_mode_t mode_t;
-#endif
-#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
-
#ifndef _OFF_T
#define _OFF_T
typedef __darwin_off_t off_t;
typedef __darwin_useconds_t useconds_t;
#endif
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-#ifndef _UUID_T
-#define _UUID_T
-typedef __darwin_uuid_t uuid_t;
-#endif /* _UUID_T */
-#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
+#ifndef NULL
+#define NULL __DARWIN_NULL
+#endif /* ! NULL */
#define STDIN_FILENO 0 /* standard input file descriptor */
#define STDOUT_FILENO 1 /* standard output file descriptor */
#define STDERR_FILENO 2 /* standard error file descriptor */
-#ifndef NULL
-#define NULL __DARWIN_NULL
-#endif /* ! NULL */
/* Version test macros */
/* _POSIX_VERSION and _POSIX2_VERSION from sys/unistd.h */
#define _POSIX_VDISABLE 0xff /* same as sys/termios.h */
#endif /* _POSIX_VDISABLE */
+#if __DARWIN_C_LEVEL >= 199209L
#define _POSIX2_C_BIND 200112L
#define _POSIX2_C_DEV 200112L /* c99 command */
#define _POSIX2_CHAR_TERM 200112L
#define _POSIX2_PBS_TRACK (-1)
#define _POSIX2_SW_DEV 200112L
#define _POSIX2_UPE 200112L /* XXXX no fc, newgrp, tabs */
+#endif /* __DARWIN_C_LEVEL */
-#define _V6_ILP32_OFF32 (-1)
-#define _V6_ILP32_OFFBIG (1)
-#define _V6_LP64_OFF64 (-1)
-#define _V6_LPBIG_OFFBIG (-1)
+#define __ILP32_OFF32 (-1)
+#define __ILP32_OFFBIG (-1)
+#define __LP64_OFF64 (-1)
+#define __LPBIG_OFFBIG (-1)
-#define _XBS5_ILP32_OFF32 _V6_ILP32_OFF32 /* legacy */
-#define _XBS5_ILP32_OFFBIG _V6_ILP32_OFFBIG /* legacy */
-#define _XBS5_LP64_OFF64 _V6_LP64_OFF64 /* legacy */
-#define _XBS5_LPBIG_OFFBIG _V6_LPBIG_OFFBIG /* legacy */
+#ifdef __LP64__
+#undef __LP64_OFF64
+#define __LP64_OFF64 (1)
+#undef __LPBIG_OFFBIG
+#define __LPBIG_OFFBIG (1)
+#else
+#undef __ILP32_OFFBIG
+#define __ILP32_OFFBIG (1)
+#endif
+#if __DARWIN_C_LEVEL >= 200112L
+#define _POSIX_V6_ILP32_OFF32 __ILP32_OFF32
+#define _POSIX_V6_ILP32_OFFBIG __ILP32_OFFBIG
+#define _POSIX_V6_LP64_OFF64 __LP64_OFF64
+#define _POSIX_V6_LPBIG_OFFBIG __LPBIG_OFFBIG
+#endif /* __DARWIN_C_LEVEL >= 200112L */
+
+#if __DARWIN_C_LEVEL >= 200809L
+#define _POSIX_V7_ILP32_OFF32 __ILP32_OFF32
+#define _POSIX_V7_ILP32_OFFBIG __ILP32_OFFBIG
+#define _POSIX_V7_LP64_OFF64 __LP64_OFF64
+#define _POSIX_V7_LPBIG_OFFBIG __LPBIG_OFFBIG
+#endif /* __DARWIN_C_LEVEL >= 200809L */
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+#define _V6_ILP32_OFF32 __ILP32_OFF32
+#define _V6_ILP32_OFFBIG __ILP32_OFFBIG
+#define _V6_LP64_OFF64 __LP64_OFF64
+#define _V6_LPBIG_OFFBIG __LPBIG_OFFBIG
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
+
+#if (__DARWIN_C_LEVEL >= 199506L && __DARWIN_C_LEVEL < 200809L) || __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+/* Removed in Issue 7 */
+#define _XBS5_ILP32_OFF32 __ILP32_OFF32
+#define _XBS5_ILP32_OFFBIG __ILP32_OFFBIG
+#define _XBS5_LP64_OFF64 __LP64_OFF64
+#define _XBS5_LPBIG_OFFBIG __LPBIG_OFFBIG
+#endif /* __DARWIN_C_LEVEL < 200809L */
+
+#if __DARWIN_C_LEVEL >= 199506L /* This really should be XSI */
#define _XOPEN_CRYPT (1)
#define _XOPEN_ENH_I18N (1) /* XXX required */
#define _XOPEN_LEGACY (-1) /* no ftime gcvt, wcswcs */
#define _XOPEN_REALTIME (-1) /* no q'ed signals, mq_* */
#define _XOPEN_REALTIME_THREADS (-1) /* no posix_spawn, et. al. */
#define _XOPEN_SHM (1)
-#define _XOPEN_STREAMS (-1)
+#define _XOPEN_STREAMS (-1) /* Issue 6 */
#define _XOPEN_UNIX (1)
-
-
-#define F_ULOCK 0 /* unlock locked section */
-#define F_LOCK 1 /* lock a section for exclusive use */
-#define F_TLOCK 2 /* test and lock a section for exclusive use */
-#define F_TEST 3 /* test a section for locks by other procs */
+#endif /* XSI */
/* configurable system variables */
#define _SC_ARG_MAX 1
#define _SC_2_UPE 25
#define _SC_STREAM_MAX 26
#define _SC_TZNAME_MAX 27
+
+#if __DARWIN_C_LEVEL >= 199309L
#define _SC_ASYNCHRONOUS_IO 28
#define _SC_PAGESIZE 29
#define _SC_MEMLOCK 30
#define _SC_SEM_VALUE_MAX 50
#define _SC_SIGQUEUE_MAX 51
#define _SC_TIMER_MAX 52
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+#endif /* __DARWIN_C_LEVEL >= 199309L */
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
#define _SC_NPROCESSORS_CONF 57
#define _SC_NPROCESSORS_ONLN 58
-#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
+
+#if __DARWIN_C_LEVEL >= 200112L
#define _SC_2_PBS 59
#define _SC_2_PBS_ACCOUNTING 60
#define _SC_2_PBS_CHECKPOINT 61
#define _SC_IPV6 118
#define _SC_RAW_SOCKETS 119
#define _SC_SYMLOOP_MAX 120
+#endif /* __DARWIN_C_LEVEL >= 200112L */
+
+#if __DARWIN_C_LEVEL >= 199506L /* Really XSI */
#define _SC_ATEXIT_MAX 107
#define _SC_IOV_MAX 56
#define _SC_PAGE_SIZE _SC_PAGESIZE
#define _SC_XOPEN_CRYPT 108
#define _SC_XOPEN_ENH_I18N 109
-#define _SC_XOPEN_LEGACY 110
-#define _SC_XOPEN_REALTIME 111
-#define _SC_XOPEN_REALTIME_THREADS 112
+#define _SC_XOPEN_LEGACY 110 /* Issue 6 */
+#define _SC_XOPEN_REALTIME 111 /* Issue 6 */
+#define _SC_XOPEN_REALTIME_THREADS 112 /* Issue 6 */
#define _SC_XOPEN_SHM 113
-#define _SC_XOPEN_STREAMS 114
+#define _SC_XOPEN_STREAMS 114 /* Issue 6 */
#define _SC_XOPEN_UNIX 115
#define _SC_XOPEN_VERSION 116
#define _SC_XOPEN_XCU_VERSION 121
+#endif /* XSI */
+
+#if (__DARWIN_C_LEVEL >= 199506L && __DARWIN_C_LEVEL < 200809L) || __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+/* Removed in Issue 7 */
#define _SC_XBS5_ILP32_OFF32 122
#define _SC_XBS5_ILP32_OFFBIG 123
#define _SC_XBS5_LP64_OFF64 124
#define _SC_XBS5_LPBIG_OFFBIG 125
+#endif /* __DARWIN_C_LEVEL <= 200809L */
+
+#if __DARWIN_C_LEVEL >= 200112L
#define _SC_SS_REPL_MAX 126
#define _SC_TRACE_EVENT_NAME_MAX 127
#define _SC_TRACE_NAME_MAX 128
#define _SC_TRACE_SYS_MAX 129
#define _SC_TRACE_USER_EVENT_MAX 130
+#endif
+
+#if __DARWIN_C_LEVEL < 200112L || __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+/* Removed in Issue 6 */
#define _SC_PASS_MAX 131
+#endif
-#ifndef _CS_PATH /* XXX temporary #ifdef'ed for <sys/unistd.h> */
+#if __DARWIN_C_LEVEL >= 199209L
+#ifndef _CS_PATH /* Defined in <sys/unistd.h> */
#define _CS_PATH 1
#endif
+#endif
+
+#if __DARWIN_C_LEVEL >= 200112
#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS 2
#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS 3
#define _CS_POSIX_V6_ILP32_OFF32_LIBS 4
#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS 12
#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS 13
#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 14
+#endif
-/* reserved for compatibility with Issue 5 */
+#if (__DARWIN_C_LEVEL >= 199506L && __DARWIN_C_LEVEL < 200809L) || __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+/* Removed in Issue 7 */
#define _CS_XBS5_ILP32_OFF32_CFLAGS 20
#define _CS_XBS5_ILP32_OFF32_LDFLAGS 21
#define _CS_XBS5_ILP32_OFF32_LIBS 22
#define _CS_XBS5_LPBIG_OFFBIG_LDFLAGS 33
#define _CS_XBS5_LPBIG_OFFBIG_LIBS 34
#define _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS 35
+#endif
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
#define _CS_DARWIN_USER_DIR 65536
#define _CS_DARWIN_USER_TEMP_DIR 65537
#define _CS_DARWIN_USER_CACHE_DIR 65538
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
-__BEGIN_DECLS
+#ifdef _DARWIN_UNLIMITED_GETGROUPS
+#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2
+#error "_DARWIN_UNLIMITED_GETGROUPS specified, but -miphoneos-version-min version does not support it."
+#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6
+#error "_DARWIN_UNLIMITED_GETGROUPS specified, but -mmacosx-version-min version does not support it."
+#endif
+#endif
+
+/* POSIX.1-1990 */
+
+__BEGIN_DECLS
void _exit(int) __dead2;
int access(const char *, int);
unsigned int
alarm(unsigned int);
int chdir(const char *);
int chown(const char *, uid_t, gid_t);
+
//Begin-Libc
#ifndef LIBC_ALIAS_CLOSE
//End-Libc
int close(int) LIBC_ALIAS_C(close);
#endif /* !LIBC_ALIAS_CLOSE */
//End-Libc
-//Begin-Libc
-#ifndef LIBC_ALIAS_CONFSTR
-//End-Libc
-size_t confstr(int, char *, size_t) __DARWIN_ALIAS(confstr);
-//Begin-Libc
-#else /* LIBC_ALIAS_CONFSTR */
-size_t confstr(int, char *, size_t) LIBC_ALIAS(confstr);
-#endif /* !LIBC_ALIAS_CONFSTR */
-//End-Libc
-char *crypt(const char *, const char *);
-char *ctermid(char *);
+
int dup(int);
int dup2(int, int);
-#if __DARWIN_UNIX03
-//Begin-Libc
-#ifndef LIBC_ALIAS_ENCRYPT
-//End-Libc
-void encrypt(char *, int) __DARWIN_ALIAS(encrypt);
-//Begin-Libc
-#else /* LIBC_ALIAS_ENCRYPT */
-void encrypt(char *, int) LIBC_ALIAS(encrypt);
-#endif /* !LIBC_ALIAS_ENCRYPT */
-//End-Libc
-#else /* !__DARWIN_UNIX03 */
-int encrypt(char *, int);
-#endif /* __DARWIN_UNIX03 */
int execl(const char *, const char *, ...);
int execle(const char *, const char *, ...);
int execlp(const char *, const char *, ...);
int execv(const char *, char * const *);
int execve(const char *, char * const *, char * const *);
int execvp(const char *, char * const *);
-int fchown(int, uid_t, gid_t);
-int fchdir(int);
pid_t fork(void);
long fpathconf(int, int);
-//Begin-Libc
-#ifndef LIBC_ALIAS_FSYNC
-//End-Libc
-int fsync(int) __DARWIN_ALIAS_C(fsync);
-//Begin-Libc
-#else /* LIBC_ALIAS_FSYNC */
-int fsync(int) LIBC_ALIAS_C(fsync);
-#endif /* !LIBC_ALIAS_FSYNC */
-//End-Libc
-int ftruncate(int, off_t);
char *getcwd(char *, size_t);
gid_t getegid(void);
uid_t geteuid(void);
gid_t getgid(void);
#if defined(_DARWIN_UNLIMITED_GETGROUPS) || defined(_DARWIN_C_SOURCE)
-int getgroups(int, gid_t []) __DARWIN_EXTSN(getgroups);
+int getgroups(int, gid_t []) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_3_2, __DARWIN_EXTSN(getgroups));
#else /* !_DARWIN_UNLIMITED_GETGROUPS && !_DARWIN_C_SOURCE */
int getgroups(int, gid_t []);
#endif /* _DARWIN_UNLIMITED_GETGROUPS || _DARWIN_C_SOURCE */
-long gethostid(void);
-int gethostname(char *, size_t);
char *getlogin(void);
-int getlogin_r(char *, size_t);
+pid_t getpgrp(void);
+pid_t getpid(void);
+pid_t getppid(void);
+uid_t getuid(void);
+int isatty(int);
+int link(const char *, const char *);
+off_t lseek(int, off_t, int);
+long pathconf(const char *, int);
+
+//Begin-Libc
+#ifndef LIBC_ALIAS_PAUSE
+//End-Libc
+int pause(void) __DARWIN_ALIAS_C(pause);
+//Begin-Libc
+#else /* LIBC_ALIAS_PAUSE */
+int pause(void) LIBC_ALIAS_C(pause);
+#endif /* !LIBC_ALIAS_PAUSE */
+//End-Libc
+
+int pipe(int [2]);
+
+//Begin-Libc
+#ifndef LIBC_ALIAS_READ
+//End-Libc
+ssize_t read(int, void *, size_t) __DARWIN_ALIAS_C(read);
+//Begin-Libc
+#else /* LIBC_ALIAS_READ */
+ssize_t read(int, void *, size_t) LIBC_ALIAS_C(read);
+#endif /* !LIBC_ALIAS_READ */
+//End-Libc
+
+int rmdir(const char *);
+int setgid(gid_t);
+int setpgid(pid_t, pid_t);
+pid_t setsid(void);
+int setuid(uid_t);
+
+//Begin-Libc
+#ifndef LIBC_ALIAS_SLEEP
+//End-Libc
+unsigned int
+ sleep(unsigned int) __DARWIN_ALIAS_C(sleep);
+//Begin-Libc
+#else /* LIBC_ALIAS_SLEEP */
+unsigned int
+ sleep(unsigned int) LIBC_ALIAS_C(sleep);
+#endif /* !LIBC_ALIAS_SLEEP */
+//End-Libc
+
+long sysconf(int);
+pid_t tcgetpgrp(int);
+int tcsetpgrp(int, pid_t);
+char *ttyname(int);
+
+#if __DARWIN_UNIX03
+//Begin-Libc
+#ifndef LIBC_ALIAS_TTYNAME_R
+//End-Libc
+int ttyname_r(int, char *, size_t) __DARWIN_ALIAS(ttyname_r);
+//Begin-Libc
+#else /* LIBC_ALIAS_TTYNAME_R */
+int ttyname_r(int, char *, size_t) LIBC_ALIAS(ttyname_r);
+#endif /* !LIBC_ALIAS_TTYNAME_R */
+//End-Libc
+#else /* !__DARWIN_UNIX03 */
+char *ttyname_r(int, char *, size_t);
+#endif /* __DARWIN_UNIX03 */
+
+int unlink(const char *);
+
+//Begin-Libc
+#ifndef LIBC_ALIAS_WRITE
+//End-Libc
+ssize_t write(int, const void *, size_t) __DARWIN_ALIAS_C(write);
+//Begin-Libc
+#else /* LIBC_ALIAS_WRITE */
+ssize_t write(int, const void *, size_t) LIBC_ALIAS_C(write);
+#endif /* !LIBC_ALIAS_WRITE */
+//End-Libc
+__END_DECLS
+
+
+
+/* Additional functionality provided by:
+ * POSIX.2-1992 C Language Binding Option
+ */
+
+#if __DARWIN_C_LEVEL >= 199209L
+__BEGIN_DECLS
+//Begin-Libc
+#ifndef LIBC_ALIAS_CONFSTR
+//End-Libc
+size_t confstr(int, char *, size_t) __DARWIN_ALIAS(confstr);
+//Begin-Libc
+#else /* LIBC_ALIAS_CONFSTR */
+size_t confstr(int, char *, size_t) LIBC_ALIAS(confstr);
+#endif /* !LIBC_ALIAS_CONFSTR */
+//End-Libc
+
//Begin-Libc
#ifndef LIBC_ALIAS_GETOPT
//End-Libc
int getopt(int, char * const [], const char *) LIBC_ALIAS(getopt);
#endif /* !LIBC_ALIAS_GETOPT */
//End-Libc
+
+extern char *optarg; /* getopt(3) external variables */
+extern int optind, opterr, optopt;
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 199209L */
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1c-1995,
+ * POSIX.1i-1995,
+ * and the omnibus ISO/IEC 9945-1: 1996
+ */
+
+#if __DARWIN_C_LEVEL >= 199506L
+ /* These F_* are really XSI or Issue 6 */
+#define F_ULOCK 0 /* unlock locked section */
+#define F_LOCK 1 /* lock a section for exclusive use */
+#define F_TLOCK 2 /* test and lock a section for exclusive use */
+#define F_TEST 3 /* test a section for locks by other procs */
+
+ __BEGIN_DECLS
+
+/* Begin XSI */
+/* Removed in Issue 6 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
+void *brk(const void *);
+int chroot(const char *) __POSIX_C_DEPRECATED(199506L);
+#endif
+
+char *crypt(const char *, const char *);
+#ifndef __CTERMID_DEFINED
+/* Multiply defined in stdio.h and unistd.h by SUS */
+#define __CTERMID_DEFINED 1
+char *ctermid(char *);
+#endif
+#if __DARWIN_UNIX03
+//Begin-Libc
+#ifndef LIBC_ALIAS_ENCRYPT
+//End-Libc
+void encrypt(char *, int) __DARWIN_ALIAS(encrypt);
+//Begin-Libc
+#else /* LIBC_ALIAS_ENCRYPT */
+void encrypt(char *, int) LIBC_ALIAS(encrypt);
+#endif /* !LIBC_ALIAS_ENCRYPT */
+//End-Libc
+#else /* !__DARWIN_UNIX03 */
+int encrypt(char *, int);
+#endif /* __DARWIN_UNIX03 */
+int fchdir(int);
+long gethostid(void);
pid_t getpgid(pid_t);
-pid_t getpgrp(void);
-pid_t getpid(void);
-pid_t getppid(void);
pid_t getsid(pid_t);
-uid_t getuid(void);
-char *getwd(char *); /* obsoleted by getcwd() */
-int isatty(int);
+
+/* Removed in Issue 6 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
+int getdtablesize(void) __POSIX_C_DEPRECATED(199506L);
+int getpagesize(void) __pure2 __POSIX_C_DEPRECATED(199506L);
+char *getpass(const char *) __POSIX_C_DEPRECATED(199506L);
+#endif
+
+/* Removed in Issue 7 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L
+char *getwd(char *) __POSIX_C_DEPRECATED(200112L); /* obsoleted by getcwd() */
+#endif
+
//Begin-Libc
#ifndef LIBC_ALIAS_LCHOWN
//End-Libc
int lchown(const char *, uid_t, gid_t) LIBC_ALIAS(lchown);
#endif /* !LIBC_ALIAS_LCHOWN */
//End-Libc
-int link(const char *, const char *);
+
//Begin-Libc
#ifndef LIBC_ALIAS_LOCKF
//End-Libc
int lockf(int, int, off_t) LIBC_ALIAS_C(lockf);
#endif /* !LIBC_ALIAS_LOCKF */
//End-Libc
-off_t lseek(int, off_t, int);
+
//Begin-Libc
#ifndef LIBC_ALIAS_NICE
//End-Libc
int nice(int) LIBC_ALIAS(nice);
#endif /* !LIBC_ALIAS_NICE */
//End-Libc
-long pathconf(const char *, int);
-//Begin-Libc
-#ifndef LIBC_ALIAS_PAUSE
-//End-Libc
-int pause(void) __DARWIN_ALIAS_C(pause);
-//Begin-Libc
-#else /* LIBC_ALIAS_PAUSE */
-int pause(void) LIBC_ALIAS_C(pause);
-#endif /* !LIBC_ALIAS_PAUSE */
-//End-Libc
-int pipe(int [2]);
+
//Begin-Libc
#ifndef LIBC_ALIAS_PREAD
//End-Libc
ssize_t pread(int, void *, size_t, off_t) LIBC_ALIAS_C(pread);
#endif /* !LIBC_ALIAS_PREAD */
//End-Libc
+
//Begin-Libc
#ifndef LIBC_ALIAS_PWRITE
//End-Libc
ssize_t pwrite(int, const void *, size_t, off_t) LIBC_ALIAS_C(pwrite);
#endif /* !LIBC_ALIAS_PWRITE */
//End-Libc
-//Begin-Libc
-#ifndef LIBC_ALIAS_READ
-//End-Libc
-ssize_t read(int, void *, size_t) __DARWIN_ALIAS_C(read);
-//Begin-Libc
-#else /* LIBC_ALIAS_READ */
-ssize_t read(int, void *, size_t) LIBC_ALIAS_C(read);
-#endif /* !LIBC_ALIAS_READ */
-//End-Libc
-ssize_t readlink(const char * __restrict, char * __restrict, size_t);
-int rmdir(const char *);
-int setegid(gid_t);
-int seteuid(uid_t);
-int setgid(gid_t);
-int setpgid(pid_t, pid_t);
+
+/* Removed in Issue 6 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
+/* Note that Issue 5 changed the argument as intprt_t,
+ * but we keep it as int for binary compatability. */
+void *sbrk(int);
+#endif
+
#if __DARWIN_UNIX03
//Begin-Libc
#ifndef LIBC_ALIAS_SETPGRP
#else /* !__DARWIN_UNIX03 */
int setpgrp(pid_t pid, pid_t pgrp); /* obsoleted by setpgid() */
#endif /* __DARWIN_UNIX03 */
+
//Begin-Libc
#ifndef LIBC_ALIAS_SETREGID
//End-Libc
int setregid(gid_t, gid_t) LIBC_ALIAS(setregid);
#endif /* !LIBC_ALIAS_SETREGID */
//End-Libc
+
//Begin-Libc
#ifndef LIBC_ALIAS_SETREUID
//End-Libc
int setreuid(uid_t, uid_t) LIBC_ALIAS(setreuid);
#endif /* !LIBC_ALIAS_SETREUID */
//End-Libc
-pid_t setsid(void);
-int setuid(uid_t);
-//Begin-Libc
-#ifndef LIBC_ALIAS_SLEEP
-//End-Libc
-unsigned int
- sleep(unsigned int) __DARWIN_ALIAS_C(sleep);
-//Begin-Libc
-#else /* LIBC_ALIAS_SLEEP */
-unsigned int
- sleep(unsigned int) LIBC_ALIAS_C(sleep);
-#endif /* !LIBC_ALIAS_SLEEP */
-//End-Libc
+
void swab(const void * __restrict, void * __restrict, ssize_t);
-int symlink(const char *, const char *);
void sync(void);
-long sysconf(int);
-pid_t tcgetpgrp(int);
-int tcsetpgrp(int, pid_t);
int truncate(const char *, off_t);
-char *ttyname(int);
-#if __DARWIN_UNIX03
-//Begin-Libc
-#ifndef LIBC_ALIAS_TTYNAME_R
-//End-Libc
-int ttyname_r(int, char *, size_t) __DARWIN_ALIAS(ttyname_r);
-//Begin-Libc
-#else /* LIBC_ALIAS_TTYNAME_R */
-int ttyname_r(int, char *, size_t) LIBC_ALIAS(ttyname_r);
-#endif /* !LIBC_ALIAS_TTYNAME_R */
-//End-Libc
-#else /* !__DARWIN_UNIX03 */
-char *ttyname_r(int, char *, size_t);
-#endif /* __DARWIN_UNIX03 */
-useconds_t
- ualarm(useconds_t, useconds_t);
-int unlink(const char *);
+useconds_t ualarm(useconds_t, useconds_t);
//Begin-Libc
#ifndef LIBC_ALIAS_USLEEP
//End-Libc
#endif /* !LIBC_ALIAS_USLEEP */
//End-Libc
pid_t vfork(void);
+/* End XSI */
+
//Begin-Libc
-#ifndef LIBC_ALIAS_WRITE
+#ifndef LIBC_ALIAS_FSYNC
//End-Libc
-ssize_t write(int, const void *, size_t) __DARWIN_ALIAS_C(write);
+int fsync(int) __DARWIN_ALIAS_C(fsync);
//Begin-Libc
-#else /* LIBC_ALIAS_WRITE */
-ssize_t write(int, const void *, size_t) LIBC_ALIAS_C(write);
-#endif /* !LIBC_ALIAS_WRITE */
+#else /* LIBC_ALIAS_FSYNC */
+int fsync(int) LIBC_ALIAS_C(fsync);
+#endif /* !LIBC_ALIAS_FSYNC */
//End-Libc
-extern char *optarg; /* getopt(3) external variables */
-extern int optind, opterr, optopt;
+int ftruncate(int, off_t);
+int getlogin_r(char *, size_t);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 199506L */
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2001
+ * ISO C99
+ */
+
+#if __DARWIN_C_LEVEL >= 200112L
+__BEGIN_DECLS
+int fchown(int, uid_t, gid_t);
+int gethostname(char *, size_t);
+ssize_t readlink(const char * __restrict, char * __restrict, size_t);
+int setegid(gid_t);
+int seteuid(uid_t);
+int symlink(const char *, const char *);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200112L */
-#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+
+
+/* Darwin extensions */
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
#include <sys/select.h>
+#ifndef _DEV_T
+#define _DEV_T
+typedef __darwin_dev_t dev_t;
+#endif
+
+#ifndef _MODE_T
+#define _MODE_T
+typedef __darwin_mode_t mode_t;
+#endif
+
+#ifndef _UUID_T
+#define _UUID_T
+typedef __darwin_uuid_t uuid_t;
+#endif /* _UUID_T */
+
+__BEGIN_DECLS
void _Exit(int) __dead2;
int accessx_np(const struct accessx_descriptor *, size_t, int *, uid_t);
int acct(const char *);
int add_profil(char *, size_t, unsigned long, unsigned int);
-void *brk(const void *);
-int chroot(const char *);
void endusershell(void);
int execvP(const char *, const char *, char * const *);
char *fflagstostr(unsigned long);
-int getdtablesize(void);
int getdomainname(char *, int);
int getgrouplist(const char *, int, int *, int *);
-int gethostuuid(uuid_t, const struct timespec *);
+int gethostuuid(uuid_t, const struct timespec *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
mode_t getmode(const void *, mode_t);
-int getpagesize(void) __pure2;
-char *getpass(const char *);
int getpeereid(int, uid_t *, gid_t *);
-int getpgid(pid_t _pid);
int getsgroups_np(int *, uuid_t);
-int getsid(pid_t _pid);
char *getusershell(void);
int getwgroups_np(int *, uuid_t);
int initgroups(const char *, int);
int rresvport(int *);
int rresvport_af(int *, int);
int ruserok(const char *, int, const char *, const char *);
-void *sbrk(int);
int setdomainname(const char *, int);
int setgroups(int, const gid_t *);
void sethostid(long);
//Begin-Libc
#ifndef LIBC_ALIAS_SETMODE
//End-Libc
-void *setmode(const char *) __DARWIN_ALIAS(setmode);
+void *setmode(const char *) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_2_0, __DARWIN_ALIAS(setmode));
//Begin-Libc
#else /* LIBC_ALIAS_SETMODE */
void *setmode(const char *) LIBC_ALIAS(setmode);
/* HFS & HFS Plus semantics system calls go here */
#ifdef __LP64__
-int fgetattrlist(int,void*,void*,size_t,unsigned int);
-int fsetattrlist(int,void*,void*,size_t,unsigned int);
+int fgetattrlist(int,void*,void*,size_t,unsigned int) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
+int fsetattrlist(int,void*,void*,size_t,unsigned int) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
//Begin-Libc
#ifndef LIBC_ALIAS_GETATTRLIST
//End-Libc
int getdirentriesattr(int,void*,void*,size_t,unsigned int*,unsigned int*,unsigned int*,unsigned int);
#else /* __LP64__ */
-int fgetattrlist(int,void*,void*,size_t,unsigned long);
-int fsetattrlist(int,void*,void*,size_t,unsigned long);
+int fgetattrlist(int,void*,void*,size_t,unsigned long) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
+int fsetattrlist(int,void*,void*,size_t,unsigned long) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
//Begin-Libc
#ifndef LIBC_ALIAS_GETATTRLIST
//End-Libc
int searchfs(const char *, struct fssearchblock *, unsigned long *, unsigned int, unsigned int, struct searchstate *);
int fsctl(const char *,unsigned long,void*,unsigned int);
-int ffsctl(int,unsigned long,void*,unsigned int);
+int ffsctl(int,unsigned long,void*,unsigned int) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0);
extern int optreset;
-#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
-#endif /* !_UNISTD_H_ */
+#endif /* _UNISTD_H_ */
#include <_types.h>
#include <sys/time.h>
+#include <sys/cdefs.h>
+#include <Availability.h>
#ifndef _PID_T
#define _PID_T
void endutxent(void);
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-void endutxent_wtmp(void);
+void endutxent_wtmp(void) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
struct lastlogx *
- getlastlogx(uid_t, struct lastlogx *);
+ getlastlogx(uid_t, struct lastlogx *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
struct lastlogx *
- getlastlogxbyname(const char*, struct lastlogx *);
+ getlastlogxbyname(const char*, struct lastlogx *)__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
#ifdef UNIFDEF_LEGACY_UTMP_APIS
struct utmp; /* forward reference */
-void getutmp(const struct utmpx *, struct utmp *);
-void getutmpx(const struct utmp *, struct utmpx *);
+void getutmp(const struct utmpx *, struct utmp *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+void getutmpx(const struct utmp *, struct utmpx *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
#endif /* UNIFDEF_LEGACY_UTMP_APIS */
#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
struct utmpx *
- getutxent_wtmp(void);
+ getutxent_wtmp(void) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
struct utmpx *
void setutxent(void);
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
-void setutxent_wtmp(int);
-int utmpxname(const char *);
-int wtmpxname(const char *);
+void setutxent_wtmp(int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int utmpxname(const char *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int wtmpxname(const char *) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */
__END_DECLS
+++ /dev/null
-/* This file is public domain. */
-/* GCC uses its own copy of this header */
-#if defined(__GNUC__)
-#include_next <varargs.h>
-#elif defined(__MWERKS__)
-#include "mw_varargs.h"
-#else
-#error "This header only supports __MWERKS__."
-#endif
#define _WCHAR_H_
#include <_types.h>
+#include <sys/cdefs.h>
+#include <Availability.h>
#ifndef NULL
#define NULL __DARWIN_NULL
#include <time.h>
#include <_wctype.h>
+
+/* Initially added in Issue 4 */
__BEGIN_DECLS
wint_t btowc(int);
wint_t fgetwc(FILE *);
wchar_t *wmemset(wchar_t *, wchar_t, size_t);
int wprintf(const wchar_t * __restrict, ...) __DARWIN_LDBL_COMPAT(wprintf);
int wscanf(const wchar_t * __restrict, ...) __DARWIN_LDBL_COMPAT(wscanf);
+int wcswidth(const wchar_t *, size_t);
+int wcwidth(wchar_t);
+__END_DECLS
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2001
+ * ISO C99
+ */
-#if !defined(_ANSI_SOURCE)
+#if __DARWIN_C_LEVEL >= 200112L || defined(_C99_SOURCE) || defined(__cplusplus)
+__BEGIN_DECLS
int vfwscanf(FILE * __restrict, const wchar_t * __restrict,
__darwin_va_list) __DARWIN_LDBL_COMPAT(vfwscanf);
int vswscanf(const wchar_t * __restrict, const wchar_t * __restrict,
unsigned long long
wcstoull(const wchar_t * __restrict, wchar_t ** __restrict, int);
#endif /* !__DARWIN_NO_LONG_LONG */
-int wcswidth(const wchar_t *, size_t);
-int wcwidth(wchar_t);
-#endif /* !defined(_ANSI_SOURCE) */
+__END_DECLS
+#endif
+
-#if !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
-size_t mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t,
- size_t, mbstate_t * __restrict);
+
+/* Additional functionality provided by:
+ * POSIX.1-2008
+ */
+
+#if __DARWIN_C_LEVEL >= 200809L
+__BEGIN_DECLS
+size_t mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t,
+ size_t, mbstate_t * __restrict);
+wchar_t *wcpcpy(wchar_t * __restrict, const wchar_t * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+wchar_t *wcpncpy(wchar_t * __restrict, const wchar_t * __restrict, size_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+wchar_t *wcsdup(const wchar_t *) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int wcscasecmp(const wchar_t *, const wchar_t *) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int wcsncasecmp(const wchar_t *, const wchar_t *, size_t n) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+size_t wcsnlen(const wchar_t *, size_t) __pure __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+size_t wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t,
+ size_t, mbstate_t * __restrict);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200809L */
+
+
+
+/* Darwin extensions */
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+__BEGIN_DECLS
+wchar_t *fgetwln(FILE * __restrict, size_t *) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
size_t wcslcat(wchar_t *, const wchar_t *, size_t);
size_t wcslcpy(wchar_t *, const wchar_t *, size_t);
-size_t wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t,
- size_t, mbstate_t * __restrict);
-#endif /* !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) */
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
+
/* Poison the following routines if -fshort-wchar is set */
#if !defined(__cplusplus) && defined(__WCHAR_MAX__) && __WCHAR_MAX__ <= 0xffffU
-#pragma GCC poison fgetws fputwc fputws fwprintf fwscanf mbrtowc mbsnrtowcs mbsrtowcs putwc putwchar swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf vwprintf vwscanf wcrtomb wcscat wcschr wcscmp wcscoll wcscpy wcscspn wcsftime wcsftime wcslcat wcslcpy wcslen wcsncat wcsncmp wcsncpy wcsnrtombs wcspbrk wcsrchr wcsrtombs wcsspn wcsstr wcstod wcstof wcstok wcstol wcstold wcstoll wcstoul wcstoull wcswidth wcsxfrm wcwidth wmemchr wmemcmp wmemcpy wmemmove wmemset wprintf wscanf
+#pragma GCC poison fgetwln fgetws fputwc fputws fwprintf fwscanf mbrtowc mbsnrtowcs mbsrtowcs putwc putwchar swprintf swscanf vfwprintf vfwscanf vswprintf vswscanf vwprintf vwscanf wcrtomb wcscat wcschr wcscmp wcscoll wcscpy wcscspn wcsftime wcsftime wcslcat wcslcpy wcslen wcsncat wcsncmp wcsncpy wcsnrtombs wcspbrk wcsrchr wcsrtombs wcsspn wcsstr wcstod wcstof wcstok wcstol wcstold wcstoll wcstoul wcstoull wcswidth wcsxfrm wcwidth wmemchr wmemcmp wmemcpy wmemmove wmemset wprintf wscanf
#endif
-__END_DECLS
#ifdef _USE_EXTENDED_LOCALES_
#include <xlocale/_wchar.h>
/*
- * Copyright (c) 2005, 2009 Apple Inc. All rights reserved.
+ * Copyright (c) 2005, 2009, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define _XLOCALE__STDIO_H_
__BEGIN_DECLS
-int asprintf_l(char **, locale_t, const char *, ...)
- __DARWIN_LDBL_COMPAT2(asprintf_l) __printflike(3, 4);
+
int fprintf_l(FILE * __restrict, locale_t, const char * __restrict, ...)
- __DARWIN_LDBL_COMPAT2(fprintf_l) __printflike(3, 4);
+ __DARWIN_LDBL_COMPAT2(fprintf_l) __printflike(3, 4);
int fscanf_l(FILE * __restrict, locale_t, const char * __restrict, ...)
- __DARWIN_LDBL_COMPAT2(fscanf_l) __scanflike(3, 4);
+ __DARWIN_LDBL_COMPAT2(fscanf_l) __scanflike(3, 4);
int printf_l(locale_t, const char * __restrict, ...)
- __DARWIN_LDBL_COMPAT2(printf_l) __printflike(2, 3);
+ __DARWIN_LDBL_COMPAT2(printf_l) __printflike(2, 3);
int scanf_l(locale_t, const char * __restrict, ...)
- __DARWIN_LDBL_COMPAT2(scanf_l) __scanflike(2, 3);
-int snprintf_l(char * __restrict, size_t, locale_t,
- const char * __restrict, ...)
- __DARWIN_LDBL_COMPAT2(snprintf_l) __printflike(4, 5);
+ __DARWIN_LDBL_COMPAT2(scanf_l) __scanflike(2, 3);
int sprintf_l(char * __restrict, locale_t, const char * __restrict, ...)
- __DARWIN_LDBL_COMPAT2(sprintf_l) __printflike(3, 4);
-int sscanf_l(const char * __restrict, locale_t, const char * __restrict,
- ...) __DARWIN_LDBL_COMPAT2(sscanf_l) __scanflike(3, 4);
-int vasprintf_l(char **, locale_t, const char *, va_list)
- __DARWIN_LDBL_COMPAT2(vasprintf_l) __printflike(3, 0);
-int vfprintf_l(FILE * __restrict, locale_t, const char * __restrict,
- va_list) __DARWIN_LDBL_COMPAT2(vfprintf_l) __printflike(3, 0);
-int vfscanf_l(FILE * __restrict, locale_t, const char * __restrict,
- va_list) __DARWIN_LDBL_COMPAT2(vfscanf_l) __scanflike(3, 0);
+ __DARWIN_LDBL_COMPAT2(sprintf_l) __printflike(3, 4);
+int sscanf_l(const char * __restrict, locale_t, const char * __restrict, ...)
+ __DARWIN_LDBL_COMPAT2(sscanf_l) __scanflike(3, 4);
+int vfprintf_l(FILE * __restrict, locale_t, const char * __restrict, va_list)
+ __DARWIN_LDBL_COMPAT2(vfprintf_l) __printflike(3, 0);
int vprintf_l(locale_t, const char * __restrict, va_list)
- __DARWIN_LDBL_COMPAT2(vprintf_l) __printflike(2, 0);
+ __DARWIN_LDBL_COMPAT2(vprintf_l) __printflike(2, 0);
+int vsprintf_l(char * __restrict, locale_t, const char * __restrict, va_list)
+ __DARWIN_LDBL_COMPAT2(vsprintf_l) __printflike(3, 0);
+
+#if __DARWIN_C_LEVEL >= 200112L
+int snprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, ...)
+ __DARWIN_LDBL_COMPAT2(snprintf_l) __printflike(4, 5);
+int vfscanf_l(FILE * __restrict, locale_t, const char * __restrict, va_list)
+ __DARWIN_LDBL_COMPAT2(vfscanf_l) __scanflike(3, 0);
int vscanf_l(locale_t, const char * __restrict, va_list)
- __DARWIN_LDBL_COMPAT2(vscanf_l) __scanflike(2, 0);
-int vsnprintf_l(char * __restrict, size_t, locale_t,
- const char * __restrict, va_list)
- __DARWIN_LDBL_COMPAT2(vsnprintf_l) __printflike(4, 0);
-int vsprintf_l(char * __restrict, locale_t, const char * __restrict,
- va_list) __DARWIN_LDBL_COMPAT2(vsprintf_l) __printflike(3, 0);
-int vsscanf_l(const char * __restrict, locale_t, const char * __restrict,
- va_list) __DARWIN_LDBL_COMPAT2(vsscanf_l) __scanflike(3, 0);
+ __DARWIN_LDBL_COMPAT2(vscanf_l) __scanflike(2, 0);
+int vsnprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, va_list)
+ __DARWIN_LDBL_COMPAT2(vsnprintf_l) __printflike(4, 0);
+int vsscanf_l(const char * __restrict, locale_t, const char * __restrict, va_list)
+ __DARWIN_LDBL_COMPAT2(vsscanf_l) __scanflike(3, 0);
+#endif
+
+#if __DARWIN_C_LEVEL >= 200809L
+int dprintf_l(int, locale_t, const char * __restrict, ...)
+ __DARWIN_LDBL_COMPAT2(dprintf_l) __printflike(3, 4) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int vdprintf_l(int, locale_t, const char * __restrict, va_list)
+ __DARWIN_LDBL_COMPAT2(vdprintf_l) __printflike(3, 0) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+#endif
+
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+int asprintf_l(char **, locale_t, const char *, ...)
+ __DARWIN_LDBL_COMPAT2(asprintf_l) __printflike(3, 4);
+int vasprintf_l(char **, locale_t, const char *, va_list)
+ __DARWIN_LDBL_COMPAT2(vasprintf_l) __printflike(3, 0);
+#endif
+
__END_DECLS
+
#endif /* _XLOCALE__STDIO_H_ */
#ifndef _XLOCALE__WCHAR_H_
#define _XLOCALE__WCHAR_H_
+/* Initially added in Issue 4 */
__BEGIN_DECLS
wint_t btowc_l(int, locale_t);
wint_t fgetwc_l(FILE *, locale_t);
size_t mbrtowc_l(wchar_t * __restrict, const char * __restrict, size_t,
mbstate_t * __restrict, locale_t);
int mbsinit_l(const mbstate_t *, locale_t);
-size_t mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t,
- size_t, mbstate_t * __restrict, locale_t);
size_t mbsrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t,
mbstate_t * __restrict, locale_t);
wint_t putwc_l(wchar_t, FILE *, locale_t);
wint_t ungetwc_l(wint_t, FILE *, locale_t);
int vfwprintf_l(FILE * __restrict, locale_t, const wchar_t * __restrict,
__darwin_va_list) __DARWIN_LDBL_COMPAT2(vfwprintf_l);
-int vfwscanf_l(FILE * __restrict, locale_t, const wchar_t * __restrict,
- __darwin_va_list) __DARWIN_LDBL_COMPAT2(vfwscanf_l);
int vswprintf_l(wchar_t * __restrict, size_t n, locale_t,
const wchar_t * __restrict, __darwin_va_list)
__DARWIN_LDBL_COMPAT2(vswprintf_l);
-int vswscanf_l(const wchar_t * __restrict, locale_t,
- const wchar_t * __restrict, __darwin_va_list)
- __DARWIN_LDBL_COMPAT2(vswscanf_l);
int vwprintf_l(locale_t, const wchar_t * __restrict, __darwin_va_list)
__DARWIN_LDBL_COMPAT2(vwprintf_l);
-int vwscanf_l(locale_t, const wchar_t * __restrict, __darwin_va_list)
- __DARWIN_LDBL_COMPAT2(vwscanf_l);
size_t wcrtomb_l(char * __restrict, wchar_t, mbstate_t * __restrict,
locale_t);
int wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
LIBC_ALIAS(wcsftime_l);
#endif /* !LIBC_ALIAS_WCSFTIME_L */
//End-Libc
-size_t wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t,
- size_t, mbstate_t * __restrict, locale_t);
size_t wcsrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t,
mbstate_t * __restrict, locale_t);
double wcstod_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t);
-float wcstof_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t);
long wcstol_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
locale_t);
-long double
- wcstold_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t)
- __DARWIN_LDBL_COMPAT2(wcstold_l);
-long long
- wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
- locale_t);
unsigned long
wcstoul_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
locale_t);
-unsigned long long
- wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
- locale_t);
int wcswidth_l(const wchar_t *, size_t, locale_t);
size_t wcsxfrm_l(wchar_t * __restrict, const wchar_t * __restrict, size_t,
locale_t);
__DARWIN_LDBL_COMPAT2(wprintf_l);
int wscanf_l(locale_t, const wchar_t * __restrict, ...)
__DARWIN_LDBL_COMPAT2(wscanf_l);
+__END_DECLS
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2001
+ */
+
+#if __DARWIN_C_LEVEL >= 200112L
+__BEGIN_DECLS
+int vfwscanf_l(FILE * __restrict, locale_t, const wchar_t * __restrict,
+ __darwin_va_list) __DARWIN_LDBL_COMPAT2(vfwscanf_l);
+int vswscanf_l(const wchar_t * __restrict, locale_t,
+ const wchar_t * __restrict, __darwin_va_list)
+ __DARWIN_LDBL_COMPAT2(vswscanf_l);
+int vwscanf_l(locale_t, const wchar_t * __restrict, __darwin_va_list)
+ __DARWIN_LDBL_COMPAT2(vwscanf_l);
+float wcstof_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t);
+long double
+ wcstold_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t)
+ __DARWIN_LDBL_COMPAT2(wcstold_l);
+#if !__DARWIN_NO_LONG_LONG
+long long
+ wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
+ locale_t);
+unsigned long long
+ wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
+ locale_t);
+#endif /* !__DARWIN_NO_LONG_LONG */
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200112L */
+
+
+
+/* Additional functionality provided by:
+ * POSIX.1-2008
+ */
+
+#if __DARWIN_C_LEVEL >= 200809L
+__BEGIN_DECLS
+size_t mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t,
+ size_t, mbstate_t * __restrict, locale_t);
+int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t n, locale_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+size_t wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t,
+ size_t, mbstate_t * __restrict, locale_t);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= 200809L */
+
+
+
+/* Darwin extensions */
+
+#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL
+__BEGIN_DECLS
+wchar_t *fgetwln_l(FILE * __restrict, size_t *, locale_t) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+__END_DECLS
+#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
+
+
/* Poison the following routines if -fshort-wchar is set */
#if !defined(__cplusplus) && defined(__WCHAR_MAX__) && __WCHAR_MAX__ <= 0xffffU
-#pragma GCC poison fgetws_l fputwc_l fputws_l fwprintf_l fwscanf_l mbrtowc_l mbsnrtowcs_l mbsrtowcs_l putwc_l putwchar_l swprintf_l swscanf_l vfwprintf_l vfwscanf_l vswprintf_l vswscanf_l vwprintf_l vwscanf_l wcrtomb_l wcscoll_l wcsftime_l wcsftime_l wcsnrtombs_l wcsrtombs_l wcstod_l wcstof_l wcstol_l wcstold_l wcstoll_l wcstoul_l wcstoull_l wcswidth_l wcsxfrm_l wcwidth_l wprintf_l wscanf_l
+#pragma GCC poison fgetwln_l fgetws_l fputwc_l fputws_l fwprintf_l fwscanf_l mbrtowc_l mbsnrtowcs_l mbsrtowcs_l putwc_l putwchar_l swprintf_l swscanf_l vfwprintf_l vfwscanf_l vswprintf_l vswscanf_l vwprintf_l vwscanf_l wcrtomb_l wcscoll_l wcsftime_l wcsftime_l wcsnrtombs_l wcsrtombs_l wcstod_l wcstof_l wcstol_l wcstold_l wcstoll_l wcstoul_l wcstoull_l wcswidth_l wcsxfrm_l wcwidth_l wprintf_l wscanf_l
#endif
-__END_DECLS
#endif /* _XLOCALE__WCHAR_H_ */
--- /dev/null
+_malloc_printf
+__malloc_fork_prepare
+__malloc_fork_parent
+__malloc_fork_child
+_vfree
+_malloc
+_free
+_realloc
+_calloc
+_malloc_size
+_malloc_good_size
+_malloc_zone_valloc
+_valloc
+_malloc_create_zone
+_malloc_default_zone
+_malloc_destroy_zone
+_malloc_get_all_zones
+_malloc_get_zone_name
+_malloc_zone_calloc
+_malloc_zone_check
+_malloc_zone_free
+_malloc_zone_from_ptr
+_malloc_zone_log
+_malloc_zone_malloc
+_malloc_zone_memalign
+_posix_memalign
+_malloc_zone_print
+_malloc_zone_print_ptr_info
+_malloc_zone_realloc
+_malloc_zone_register
+_malloc_zone_unregister
+_malloc_zone_batch_malloc
+_malloc_zone_batch_free
--- /dev/null
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/ascii.c,v 1.1 2008/01/21 23:48:12 ache Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <runetype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+static size_t _ascii_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _ascii_mbsinit(const mbstate_t *);
+static size_t _ascii_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps __unused);
+static size_t _ascii_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+
+int
+_ascii_init(_RuneLocale *rl)
+{
+
+ __mbrtowc = _ascii_mbrtowc;
+ __mbsinit = _ascii_mbsinit;
+ __mbsnrtowcs = _ascii_mbsnrtowcs;
+ __wcrtomb = _ascii_wcrtomb;
+ __wcsnrtombs = _ascii_wcsnrtombs;
+ _CurrentRuneLocale = rl;
+ __mb_cur_max = 1;
+ __mb_sb_limit = 128;
+ return(0);
+}
+
+static int
+_ascii_mbsinit(const mbstate_t *ps __unused)
+{
+
+ /*
+ * Encoding is not state dependent - we are always in the
+ * initial state.
+ */
+ return (1);
+}
+
+static size_t
+_ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (0);
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if (pwc != NULL)
+ *pwc = (unsigned char)*s;
+ return (*s == '\0' ? 0 : 1);
+}
+
+static size_t
+_ascii_wcrtomb(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if (wc < 0 || wc > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ *s = (unsigned char)wc;
+ return (1);
+}
+
+static size_t
+_ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps __unused)
+{
+ const char *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ for (s = *src; nms > 0 && *s != '\0'; s++, nms--) {
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ return (s - *src);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nms-- > 0) {
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if ((*dst++ = (unsigned char)*s++) == L'\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
+static size_t
+_ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
+{
+ const wchar_t *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
+ if (*s < 0 || *s > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ return (s - *src);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nwc-- > 0) {
+ if (*s < 0 || *s > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if ((*dst++ = *s++) == '\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
--- /dev/null
+Index: ascii.c
+===================================================================
+--- ascii.c (revision 47445)
++++ ascii.c (working copy)
+@@ -45,33 +45,32 @@
+ #include "mblocal.h"
+
+ static size_t _ascii_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _ascii_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
++static int _ascii_mbsinit(const mbstate_t *, locale_t);
+ static size_t _ascii_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+- mbstate_t * __restrict ps __unused);
++ mbstate_t * __restrict ps __unused, locale_t);
+ static size_t _ascii_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
+ static size_t _ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+- size_t, size_t, mbstate_t * __restrict);
++ size_t, size_t, mbstate_t * __restrict, locale_t);
+
+-int
+-_ascii_init(_RuneLocale *rl)
++__private_extern__ int
++_ascii_init(struct __xlocale_st_runelocale *xrl)
+ {
+
+- __mbrtowc = _ascii_mbrtowc;
+- __mbsinit = _ascii_mbsinit;
+- __mbsnrtowcs = _ascii_mbsnrtowcs;
+- __wcrtomb = _ascii_wcrtomb;
+- __wcsnrtombs = _ascii_wcsnrtombs;
+- _CurrentRuneLocale = rl;
+- __mb_cur_max = 1;
+- __mb_sb_limit = 128;
++ xrl->__mbrtowc = _ascii_mbrtowc;
++ xrl->__mbsinit = _ascii_mbsinit;
++ xrl->__mbsnrtowcs = _ascii_mbsnrtowcs;
++ xrl->__wcrtomb = _ascii_wcrtomb;
++ xrl->__wcsnrtombs = _ascii_wcsnrtombs;
++ xrl->__mb_cur_max = 1;
++ xrl->__mb_sb_limit = 128;
+ return(0);
+ }
+
+ static int
+-_ascii_mbsinit(const mbstate_t *ps __unused)
++_ascii_mbsinit(const mbstate_t *ps __unused, locale_t loc __unused)
+ {
+
+ /*
+@@ -83,7 +82,7 @@
+
+ static size_t
+ _ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+- mbstate_t * __restrict ps __unused)
++ mbstate_t * __restrict ps __unused, locale_t loc __unused)
+ {
+
+ if (s == NULL)
+@@ -103,7 +102,7 @@
+
+ static size_t
+ _ascii_wcrtomb(char * __restrict s, wchar_t wc,
+- mbstate_t * __restrict ps __unused)
++ mbstate_t * __restrict ps __unused, locale_t loc __unused)
+ {
+
+ if (s == NULL)
+@@ -119,7 +118,7 @@
+
+ static size_t
+ _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+- size_t nms, size_t len, mbstate_t * __restrict ps __unused)
++ size_t nms, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
+ {
+ const char *s;
+ size_t nchr;
+@@ -153,7 +152,7 @@
+
+ static size_t
+ _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+- size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
++ size_t nwc, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
+ {
+ const wchar_t *s;
+ size_t nchr;
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)big5.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/big5.c,v 1.16 2004/05/17 11:16:14 tjr Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/big5.c,v 1.18 2007/10/13 16:28:21 ache Exp $");
+#include <sys/types.h>
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
-int _BIG5_init(_RuneLocale *);
-size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _BIG5_mbsinit(const mbstate_t *);
-size_t _BIG5_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+extern int __mb_sb_limit;
+
+static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _BIG5_mbsinit(const mbstate_t *);
+static size_t _BIG5_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
typedef struct {
wchar_t ch;
__mbsinit = _BIG5_mbsinit;
_CurrentRuneLocale = rl;
__mb_cur_max = 2;
+ __mb_sb_limit = 128;
return (0);
}
-int
+static int
_BIG5_mbsinit(const mbstate_t *ps)
{
return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1);
}
-size_t
+static size_t
_BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps)
{
}
}
-size_t
+static size_t
_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
_BIG5State *bs;
---- big5.c.orig Thu Nov 25 11:38:16 2004
-+++ big5.c Fri Feb 18 15:48:14 2005
-@@ -41,6 +41,8 @@
- #include <sys/param.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/big5.c,v 1.16 2004/05/17 11:16:14 tjr Exp $");
+--- big5.c.orig 2009-11-09 15:24:27.000000000 -0800
++++ big5.c 2009-11-09 18:41:35.000000000 -0800
+@@ -41,6 +41,8 @@ static char sccsid[] = "@(#)big5.c 8.1 (
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/locale/big5.c,v 1.18 2007/10/13 16:28:21 ache Exp $");
+#include "xlocale_private.h"
+
+ #include <sys/types.h>
#include <errno.h>
#include <runetype.h>
- #include <stdlib.h>
-@@ -48,30 +50,29 @@
+@@ -49,33 +51,30 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--int _BIG5_init(_RuneLocale *);
--size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _BIG5_mbsinit(const mbstate_t *);
--size_t _BIG5_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
-+__private_extern__ int _BIG5_init(struct __xlocale_st_runelocale *);
-+static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
+-extern int __mb_sb_limit;
+-
+ static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _BIG5_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
+static int _BIG5_mbsinit(const mbstate_t *, locale_t);
-+static size_t _BIG5_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+ static size_t _BIG5_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
- __mbsinit = _BIG5_mbsinit;
- _CurrentRuneLocale = rl;
- __mb_cur_max = 2;
+- __mb_sb_limit = 128;
+ xrl->__mbrtowc = _BIG5_mbrtowc;
+ xrl->__wcrtomb = _BIG5_wcrtomb;
+ xrl->__mbsinit = _BIG5_mbsinit;
+ xrl->__mb_cur_max = 2;
++ xrl->__mb_sb_limit = 128;
return (0);
}
--int
+ static int
-_BIG5_mbsinit(const mbstate_t *ps)
-+static int
-+_BIG5_mbsinit(const mbstate_t *ps, locale_t loc)
++_BIG5_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _BIG5State *)ps)->ch == 0);
-@@ -85,9 +86,9 @@
- return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1);
- }
+@@ -91,7 +90,7 @@ _big5_check(u_int c)
--size_t
-+static size_t
+ static size_t
_BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps)
-+ mbstate_t * __restrict ps, locale_t loc)
++ mbstate_t * __restrict ps, locale_t loc __unused)
{
_BIG5State *bs;
wchar_t wc;
-@@ -146,8 +147,8 @@
- }
+@@ -151,7 +150,7 @@ _BIG5_mbrtowc(wchar_t * __restrict pwc,
}
--size_t
+ static size_t
-_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
-+_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
++_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_BIG5State *bs;
---- btowc.3 2003-05-20 15:21:44.000000000 -0700
-+++ btowc.3.edit 2006-07-12 11:14:18.000000000 -0700
+--- btowc.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ btowc.3 2009-11-09 15:05:25.000000000 -0800
@@ -29,16 +29,35 @@
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn btowc
-@@ -59,10 +78,29 @@
+@@ -59,10 +78,29 @@ or not able to be represented as a singl
.Fn wctob
returns
.Dv WEOF .
---- btowc.c.orig Thu Nov 25 11:38:16 2004
-+++ btowc.c Fri Feb 18 15:58:50 2005
+--- btowc.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ btowc.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,18 +27,21 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/btowc.c,v 1.4 2004/05/12 14:26:54 tjr Exp $");
if (c == EOF)
return (WEOF);
/*
-@@ -47,7 +50,13 @@
+@@ -47,7 +50,13 @@ btowc(int c)
* counts.
*/
cc = (char)c;
+ if (loc->__lc_ctype->__mbrtowc(&wc, &cc, 1, &mbs, loc) > 1)
return (WEOF);
return (wc);
-+}
+ }
+
+wint_t
+btowc(int c)
+{
+ return btowc_l(c, __current_locale());
- }
++}
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.33 2004/09/22 16:56:48 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.35 2005/02/27 20:31:13 ru Exp $");
#include "namespace.h"
#include <arpa/inet.h>
chains = -1;
if (strcmp(strbuf, COLLATE_VERSION) == 0)
chains = 0;
- else if (strcmp(strbuf, COLLATE_VERSION1_1) == 0)
+ else if (strcmp(strbuf, COLLATE_VERSION1_2) == 0)
chains = 1;
if (chains < 0) {
(void)fclose(fp);
if (__collate_char_pri_table_ptr != NULL)
free(__collate_char_pri_table_ptr);
__collate_char_pri_table_ptr = TMP_char_pri_table;
+ for (i = 0; i < UCHAR_MAX + 1; i++) {
+ __collate_char_pri_table[i].prim =
+ ntohl(__collate_char_pri_table[i].prim);
+ __collate_char_pri_table[i].sec =
+ ntohl(__collate_char_pri_table[i].sec);
+ }
if (__collate_chain_pri_table != NULL)
free(__collate_chain_pri_table);
__collate_chain_pri_table = TMP_chain_pri_table;
-
+ for (i = 0; i < chains; i++) {
+ __collate_chain_pri_table[i].prim =
+ ntohl(__collate_chain_pri_table[i].prim);
+ __collate_chain_pri_table[i].sec =
+ ntohl(__collate_chain_pri_table[i].sec);
+ }
__collate_substitute_nontrivial = 0;
for (i = 0; i < UCHAR_MAX + 1; i++) {
if (__collate_substitute_table[i][0] != i ||
}
u_char *
-__collate_substitute(s)
- const u_char *s;
+__collate_substitute(const u_char *s)
{
int dest_len, len, nlen;
int delta = strlen(s);
}
void
-__collate_lookup(t, len, prim, sec)
- const u_char *t;
- int *len, *prim, *sec;
+__collate_lookup(const u_char *t, int *len, int *prim, int *sec)
{
struct __collate_st_chain_pri *p2;
}
u_char *
-__collate_strdup(s)
- u_char *s;
+__collate_strdup(u_char *s)
{
u_char *t = strdup(s);
---- collate.c.orig 2004-11-25 11:38:16.000000000 -0800
-+++ collate.c 2005-10-20 01:00:19.000000000 -0700
+--- collate.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ collate.c 2009-11-09 15:20:20.000000000 -0800
@@ -28,14 +28,26 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.33 2004/09/22 16:56:48 stefanf Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.35 2005/02/27 20:31:13 ru Exp $");
+#include "xlocale_private.h"
+/* assumes the locale_t variable is named loc */
#include "un-namespace.h"
#include "collate.h"
-@@ -44,36 +56,50 @@
+@@ -44,36 +56,50 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "libc_private.h"
return (_LDP_CACHE);
}
-@@ -97,9 +123,7 @@
+@@ -97,9 +123,7 @@ __collate_load_tables(const char *encodi
return (_LDP_ERROR);
}
chains = -1;
- if (strcmp(strbuf, COLLATE_VERSION) == 0)
- chains = 0;
-- else if (strcmp(strbuf, COLLATE_VERSION1_1) == 0)
+- else if (strcmp(strbuf, COLLATE_VERSION1_2) == 0)
+ if (strcmp(strbuf, COLLATE_VERSION1_1A) == 0)
chains = 1;
if (chains < 0) {
(void)fclose(fp);
-@@ -107,13 +131,21 @@
+@@ -107,13 +131,21 @@ __collate_load_tables(const char *encodi
return (_LDP_ERROR);
}
if (chains) {
(void)fclose(fp);
errno = EFTYPE;
return (_LDP_ERROR);
-@@ -121,136 +153,446 @@
+@@ -121,143 +153,446 @@ __collate_load_tables(const char *encodi
} else
chains = TABLE_SIZE;
- if ((TMP_substitute_table =
- malloc(sizeof(__collate_substitute_table))) == NULL) {
-- saverr = errno;
-- (void)fclose(fp);
-- errno = saverr;
-- return (_LDP_ERROR);
-- }
++ i = sizeof(struct __xlocale_st_collate)
++ + sizeof(struct __collate_st_chain_pri) * chains
++ + sizeof(struct __collate_st_large_char_pri) * info.large_pri_count;
++ for(z = 0; z < info.directive_count; z++)
++ i += sizeof(struct __collate_st_subst) * info.subst_count[z];
++ if ((TMP = (struct __xlocale_st_collate *)malloc(i)) == NULL) {
+ saverr = errno;
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
- if ((TMP_char_pri_table =
- malloc(sizeof(__collate_char_pri_table))) == NULL) {
- saverr = errno;
- }
- if ((TMP_chain_pri_table =
- malloc(sizeof(*__collate_chain_pri_table) * chains)) == NULL) {
-+ i = sizeof(struct __xlocale_st_collate)
-+ + sizeof(struct __collate_st_chain_pri) * chains
-+ + sizeof(struct __collate_st_large_char_pri) * info.large_pri_count;
-+ for(z = 0; z < info.directive_count; z++)
-+ i += sizeof(struct __collate_st_subst) * info.subst_count[z];
-+ if ((TMP = (struct __xlocale_st_collate *)malloc(i)) == NULL) {
- saverr = errno;
+- saverr = errno;
- free(TMP_substitute_table);
- free(TMP_char_pri_table);
- (void)fclose(fp);
- errno = saverr;
- return (_LDP_ERROR);
- }
+- (void)fclose(fp);
+- errno = saverr;
+- return (_LDP_ERROR);
+- }
+ TMP->__refcount = 2; /* one for the locale, one for the cache */
+ TMP->__free_extra = NULL;
- if (__collate_char_pri_table_ptr != NULL)
- free(__collate_char_pri_table_ptr);
- __collate_char_pri_table_ptr = TMP_char_pri_table;
+- for (i = 0; i < UCHAR_MAX + 1; i++) {
+- __collate_char_pri_table[i].prim =
+- ntohl(__collate_char_pri_table[i].prim);
+- __collate_char_pri_table[i].sec =
+- ntohl(__collate_char_pri_table[i].sec);
+- }
- if (__collate_chain_pri_table != NULL)
- free(__collate_chain_pri_table);
- __collate_chain_pri_table = TMP_chain_pri_table;
--
+- for (i = 0; i < chains; i++) {
+- __collate_chain_pri_table[i].prim =
+- ntohl(__collate_chain_pri_table[i].prim);
+- __collate_chain_pri_table[i].sec =
+- ntohl(__collate_chain_pri_table[i].sec);
+- }
- __collate_substitute_nontrivial = 0;
- for (i = 0; i < UCHAR_MAX + 1; i++) {
- if (__collate_substitute_table[i][0] != i ||
}
-u_char *
--__collate_substitute(s)
-- const u_char *s;
+-__collate_substitute(const u_char *s)
+static int
+__collate_wcsnlen(const wchar_t *s, int len)
+{
}
-void
--__collate_lookup(t, len, prim, sec)
-- const u_char *t;
-- int *len, *prim, *sec;
+-__collate_lookup(const u_char *t, int *len, int *prim, int *sec)
+static struct __collate_st_chain_pri *
+chainsearch(const wchar_t *key, int *len, locale_t loc)
+{
+ if (p >= 0) {
+ *len = l;
+ *pri = p;
-+ return;
-+ }
-+ }
+ return;
+ }
+ }
+- *prim = __collate_char_pri_table[*t].prim;
+- *sec = __collate_char_pri_table[*t].sec;
+ if (*t <= UCHAR_MAX) {
+ *pri = __collate_char_pri_table[*t].pri[which];
+ return;
+ match = largesearch(*t, loc);
+ if (match) {
+ *pri = match->pri.pri[which];
- return;
- }
- }
-- *prim = __collate_char_pri_table[*t].prim;
-- *sec = __collate_char_pri_table[*t].sec;
++ return;
++ }
++ }
+ *pri = (l = __collate_info->undef_pri[which]) >= 0 ? l : *t - l;
- }
-
--u_char *
--__collate_strdup(s)
-- u_char *s;
++}
++
+__private_extern__ wchar_t *
+__collate_mbstowcs(const char *s, locale_t loc)
- {
-- u_char *t = strdup(s);
++{
+ static const mbstate_t initial;
+ mbstate_t st;
+ size_t len;
+ st = initial;
+ mbsrtowcs_l(wcs, &s, len, &st, loc);
+ wcs[len] = 0;
-
-- if (t == NULL)
-+ return (wcs);
-+}
+
++ return (wcs);
+ }
+
+-u_char *
+-__collate_strdup(u_char *s)
+__private_extern__ wchar_t *
+__collate_wcsdup(const wchar_t *s)
-+{
+ {
+- u_char *t = strdup(s);
+ size_t len = wcslen(s) + 1;
+ wchar_t *wcs;
-+
+
+- if (t == NULL)
+ if ((wcs = (wchar_t *)malloc(len * sizeof(wchar_t))) == NULL)
__collate_err(EX_OSERR, __func__);
- return (t);
__collate_err(int ex, const char *f)
{
const char *s;
-@@ -268,24 +610,345 @@
+@@ -275,24 +610,345 @@ __collate_err(int ex, const char *f)
exit(ex);
}
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/lib/libc/locale/collate.h,v 1.14 2002/08/30 20:26:02 ache Exp $
+ * $FreeBSD: src/lib/libc/locale/collate.h,v 1.15 2005/02/27 20:31:13 ru Exp $
*/
#ifndef _COLLATE_H_
#define STR_LEN 10
#define TABLE_SIZE 100
#define COLLATE_VERSION "1.0\n"
-#define COLLATE_VERSION1_1 "1.1\n"
+#define COLLATE_VERSION1_2 "1.2\n"
struct __collate_st_char_pri {
int prim, sec;
---- collate.h.orig 2003-05-20 15:21:44.000000000 -0700
-+++ collate.h 2005-10-20 00:05:25.000000000 -0700
-@@ -31,36 +31,88 @@
+--- collate.h.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ collate.h 2009-11-09 15:21:14.000000000 -0800
+@@ -31,36 +31,90 @@
#define _COLLATE_H_
#include <sys/cdefs.h>
#define STR_LEN 10
#define TABLE_SIZE 100
#define COLLATE_VERSION "1.0\n"
- #define COLLATE_VERSION1_1 "1.1\n"
++#define COLLATE_VERSION1_1 "1.1\n"
+#define COLLATE_VERSION1_1A "1.1A\n"
+ #define COLLATE_VERSION1_2 "1.2\n"
+
+/* see discussion in string/FreeBSD/strxfrm for this value */
+#define COLLATE_MAX_PRIORITY ((1 << 24) - 1)
+
+ __int32_t chain_count;
+ __int32_t large_pri_count;
+};
-
++
struct __collate_st_char_pri {
- int prim, sec;
+ __int32_t pri[COLL_WEIGHTS_MAX];
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.17 2003/08/03 19:28:23 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.18 2005/02/27 14:54:23 phantom Exp $");
#include <string.h>
#include "collate.h"
* Compare two characters using collate
*/
-int __collate_range_cmp(c1, c2)
- int c1, c2;
+int __collate_range_cmp(int c1, int c2)
{
static char s1[2], s2[2];
---- collcmp.c.orig 2004-11-25 11:38:16.000000000 -0800
-+++ collcmp.c 2005-03-30 08:36:37.000000000 -0800
-@@ -27,19 +27,22 @@
+--- collcmp.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ collcmp.c 2009-11-09 15:23:31.000000000 -0800
+@@ -27,18 +27,20 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.17 2003/08/03 19:28:23 ache Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.18 2005/02/27 14:54:23 phantom Exp $");
-#include <string.h>
+#include <xlocale.h>
* Compare two characters using collate
*/
--int __collate_range_cmp(c1, c2)
-- int c1, c2;
+-int __collate_range_cmp(int c1, int c2)
+__private_extern__ int
-+__collate_range_cmp(c1, c2, loc)
-+ wchar_t c1, c2;
-+ locale_t loc;
++__collate_range_cmp(wchar_t c1, wchar_t c2, locale_t loc)
{
- static char s1[2], s2[2];
+ static wchar_t s1[2], s2[2];
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/ctype.3,v 1.15 2004/06/30 20:09:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/ctype.3,v 1.18 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt CTYPE 3
---- ctype.3.orig Fri Mar 11 18:02:47 2005
-+++ ctype.3 Fri Mar 11 18:03:52 2005
-@@ -115,6 +115,12 @@
+--- ctype.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ ctype.3 2009-11-09 15:05:26.000000000 -0800
+@@ -111,6 +111,12 @@ They are available as macros, defined in
.In ctype.h ,
or as true functions in the C library.
See the specific manual pages for more information.
.Sh SEE ALSO
.Xr digittoint 3 ,
.Xr isalnum 3 ,
-@@ -138,7 +144,8 @@
+@@ -134,7 +140,8 @@ See the specific manual pages for more i
.Xr tolower 3 ,
.Xr toupper 3 ,
.Xr wctype 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)digittoint.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/digittoint.3,v 1.3 2004/03/30 07:19:35 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/digittoint.3,v 1.6 2009/09/04 07:44:58 des Exp $
.\"
.Dd April 6, 2001
.Dt DIGITTOINT 3
---- digittoint.3 2004-11-25 11:38:16.000000000 -0800
-+++ digittoint.3.edit 2006-08-11 15:23:25.000000000 -0700
-@@ -36,20 +36,38 @@
+--- digittoint.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ digittoint.3 2009-11-09 15:05:26.000000000 -0800
+@@ -32,20 +32,38 @@
.Dt DIGITTOINT 3
.Os
.Sh NAME
.Sh RETURN VALUES
The
.Fn digittoint
-@@ -60,4 +78,5 @@
+@@ -56,4 +74,5 @@ the function will return 0.
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr isdigit 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)euc.4 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/euc.5,v 1.12 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/euc.5,v 1.13 2007/01/09 00:28:00 imp Exp $
.\"
.Dd November 8, 2003
.Dt EUC 5
static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.20 2004/06/23 07:01:43 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.22 2007/10/13 16:28:21 ache Exp $");
#include <errno.h>
#include <limits.h>
#include <wchar.h>
#include "mblocal.h"
-int _EUC_init(_RuneLocale *);
-size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _EUC_mbsinit(const mbstate_t *);
-size_t _EUC_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+extern int __mb_sb_limit;
+
+static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _EUC_mbsinit(const mbstate_t *);
+static size_t _EUC_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
typedef struct {
int count[4];
__mbrtowc = _EUC_mbrtowc;
__wcrtomb = _EUC_wcrtomb;
__mbsinit = _EUC_mbsinit;
+ __mb_sb_limit = 256;
return (0);
}
-int
+static int
_EUC_mbsinit(const mbstate_t *ps)
{
static __inline int
_euc_set(u_int c)
{
+
c &= 0xff;
return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
}
-size_t
+static size_t
_EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps)
{
return (wc == L'\0' ? 0 : s - os);
}
-size_t
+static size_t
_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
_EucState *es;
---- euc.c.orig Thu Nov 25 11:38:16 2004
-+++ euc.c Fri Feb 18 15:30:38 2005
-@@ -41,6 +41,8 @@
+--- euc.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ euc.c 2009-11-09 15:44:21.000000000 -0800
+@@ -41,6 +41,8 @@ static char sccsid[] = "@(#)euc.c 8.1 (B
#include <sys/param.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.20 2004/06/23 07:01:43 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.22 2007/10/13 16:28:21 ache Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <limits.h>
#include <runetype.h>
-@@ -49,11 +51,12 @@
+@@ -49,13 +51,11 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--int _EUC_init(_RuneLocale *);
--size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _EUC_mbsinit(const mbstate_t *);
--size_t _EUC_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
-+__private_extern__ int _EUC_init(struct __xlocale_st_runelocale *);
-+static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
+-extern int __mb_sb_limit;
+-
+ static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _EUC_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
+static int _EUC_mbsinit(const mbstate_t *, locale_t);
-+static size_t _EUC_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict,
-+ locale_t);
+ static size_t _EUC_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
typedef struct {
int count[4];
-@@ -67,12 +70,20 @@
+@@ -69,12 +69,20 @@ typedef struct {
int want;
} _EucState;
if (rl->__variable == NULL)
return (EFTYPE);
-@@ -111,23 +122,21 @@
+@@ -113,24 +121,22 @@ _EUC_init(_RuneLocale *rl)
}
rl->__variable = ei;
rl->__variable_len = sizeof(_EucInfo);
- __mbrtowc = _EUC_mbrtowc;
- __wcrtomb = _EUC_wcrtomb;
- __mbsinit = _EUC_mbsinit;
-+ xrl->__mb_cur_max = new__mb_cur_max;
-+ xrl->__mbrtowc = _EUC_mbrtowc;
-+ xrl->__wcrtomb = _EUC_wcrtomb;
-+ xrl->__mbsinit = _EUC_mbsinit;
-+ xrl->__free_extra = (__free_extra_t)_EUC_free_extra;
+- __mb_sb_limit = 256;
++ xrl->__mb_cur_max = new__mb_cur_max;
++ xrl->__mbrtowc = _EUC_mbrtowc;
++ xrl->__wcrtomb = _EUC_wcrtomb;
++ xrl->__mbsinit = _EUC_mbsinit;
++ xrl->__mb_sb_limit = 256;
++ xrl->__free_extra = (__free_extra_t)_EUC_free_extra;
return (0);
}
--int
+ static int
-_EUC_mbsinit(const mbstate_t *ps)
-+static int
-+_EUC_mbsinit(const mbstate_t *ps, locale_t loc)
++_EUC_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _EucState *)ps)->want == 0);
#define _SS2 0x008e
#define _SS3 0x008f
-@@ -140,18 +149,20 @@
- return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
- }
+@@ -146,16 +152,18 @@ _euc_set(u_int c)
--size_t
-+static size_t
+ static size_t
_EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps)
+ mbstate_t * __restrict ps, locale_t loc)
es->set > 3) {
errno = EINVAL;
return ((size_t)-1);
-@@ -213,12 +224,14 @@
- return (wc == L'\0' ? 0 : s - os);
+@@ -218,11 +226,12 @@ _EUC_mbrtowc(wchar_t * __restrict pwc, c
}
--size_t
+ static size_t
-_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
-+_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps,
-+ locale_t loc)
++_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
{
_EucState *es;
wchar_t m, nm;
---- fix_grouping.c.orig 2004-11-25 11:38:16.000000000 -0800
-+++ fix_grouping.c 2004-12-07 18:11:15.000000000 -0800
-@@ -31,7 +31,8 @@
+--- fix_grouping.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ fix_grouping.c 2009-11-09 15:05:25.000000000 -0800
+@@ -31,7 +31,8 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <limits.h>
#include <stddef.h>
/*
* Internal helper used to convert grouping sequences from string
-@@ -84,3 +85,14 @@
+@@ -84,3 +85,14 @@ __fix_locale_grouping_str(const char *st
*dst = '\0';
return str;
}
*/
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/gb18030.c,v 1.6 2004/05/12 14:09:04 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/gb18030.c,v 1.8 2007/10/13 16:28:21 ache Exp $");
#include <errno.h>
#include <runetype.h>
#include <wchar.h>
#include "mblocal.h"
-int _GB18030_init(_RuneLocale *);
-size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _GB18030_mbsinit(const mbstate_t *);
-size_t _GB18030_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+extern int __mb_sb_limit;
+
+static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _GB18030_mbsinit(const mbstate_t *);
+static size_t _GB18030_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
typedef struct {
int count;
__mbsinit = _GB18030_mbsinit;
_CurrentRuneLocale = rl;
__mb_cur_max = 4;
+ __mb_sb_limit = 128;
return (0);
}
-int
+static int
_GB18030_mbsinit(const mbstate_t *ps)
{
return (ps == NULL || ((const _GB18030State *)ps)->count == 0);
}
-size_t
+static size_t
_GB18030_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
size_t n, mbstate_t * __restrict ps)
{
return ((size_t)-1);
}
-size_t
+static size_t
_GB18030_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
_GB18030State *gs;
---- gb18030.c.orig Thu Nov 25 11:38:16 2004
-+++ gb18030.c Fri Feb 18 15:43:22 2005
+--- gb18030.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ gb18030.c 2009-11-09 15:50:31.000000000 -0800
@@ -32,6 +32,8 @@
#include <sys/param.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/gb18030.c,v 1.6 2004/05/12 14:09:04 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/gb18030.c,v 1.8 2007/10/13 16:28:21 ache Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
-@@ -39,40 +41,41 @@
+@@ -39,35 +41,34 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--int _GB18030_init(_RuneLocale *);
--size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _GB18030_mbsinit(const mbstate_t *);
--size_t _GB18030_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+-extern int __mb_sb_limit;
+#define GB18030_MB_CUR_MAX 4
-+
-+__private_extern__ int _GB18030_init(struct __xlocale_st_runelocale *);
-+static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
+
+ static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _GB18030_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
+static int _GB18030_mbsinit(const mbstate_t *, locale_t);
-+static size_t _GB18030_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+ static size_t _GB18030_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
typedef struct {
int count;
- __mbsinit = _GB18030_mbsinit;
- _CurrentRuneLocale = rl;
- __mb_cur_max = 4;
+- __mb_sb_limit = 128;
+ xrl->__mbrtowc = _GB18030_mbrtowc;
+ xrl->__wcrtomb = _GB18030_wcrtomb;
+ xrl->__mbsinit = _GB18030_mbsinit;
+ xrl->__mb_cur_max = GB18030_MB_CUR_MAX;
++ xrl->__mb_sb_limit = 128;
return (0);
}
--int
+ static int
-_GB18030_mbsinit(const mbstate_t *ps)
-+static int
-+_GB18030_mbsinit(const mbstate_t *ps, locale_t loc)
++_GB18030_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _GB18030State *)ps)->count == 0);
- }
+@@ -75,7 +76,7 @@ _GB18030_mbsinit(const mbstate_t *ps)
--size_t
-+static size_t
+ static size_t
_GB18030_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
- size_t n, mbstate_t * __restrict ps)
-+ size_t n, mbstate_t * __restrict ps, locale_t loc)
++ size_t n, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB18030State *gs;
wchar_t wch;
-@@ -92,7 +95,7 @@
+@@ -95,7 +96,7 @@ _GB18030_mbrtowc(wchar_t * __restrict pw
pwc = NULL;
}
memcpy(gs->bytes + gs->count, s, ncopy);
ocount = gs->count;
gs->count += ncopy;
-@@ -154,8 +157,8 @@
- return ((size_t)-1);
+@@ -158,7 +159,7 @@ ilseq:
}
--size_t
+ static size_t
-_GB18030_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
-+_GB18030_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
++_GB18030_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB18030State *gs;
size_t len;
*/
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/gb2312.c,v 1.8 2004/05/12 14:09:04 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/gb2312.c,v 1.10 2007/10/13 16:28:21 ache Exp $");
#include <errno.h>
#include <runetype.h>
#include <wchar.h>
#include "mblocal.h"
-int _GB2312_init(_RuneLocale *);
-size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _GB2312_mbsinit(const mbstate_t *);
-size_t _GB2312_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+extern int __mb_sb_limit;
+
+static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _GB2312_mbsinit(const mbstate_t *);
+static size_t _GB2312_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
typedef struct {
int count;
__wcrtomb = _GB2312_wcrtomb;
__mbsinit = _GB2312_mbsinit;
__mb_cur_max = 2;
+ __mb_sb_limit = 128;
return (0);
}
-int
+static int
_GB2312_mbsinit(const mbstate_t *ps)
{
return (1);
}
-size_t
+static size_t
_GB2312_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps)
{
return (wc == L'\0' ? 0 : len - ocount);
}
-size_t
+static size_t
_GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
_GB2312State *gs;
---- gb2312.c.orig Thu Nov 25 11:38:17 2004
-+++ gb2312.c Fri Feb 18 15:45:33 2005
+--- gb2312.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ gb2312.c 2009-11-09 16:10:25.000000000 -0800
@@ -28,6 +28,8 @@
#include <sys/param.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/gb2312.c,v 1.8 2004/05/12 14:09:04 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/gb2312.c,v 1.10 2007/10/13 16:28:21 ache Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
-@@ -35,31 +37,32 @@
+@@ -35,34 +37,32 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--int _GB2312_init(_RuneLocale *);
--size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _GB2312_mbsinit(const mbstate_t *);
--size_t _GB2312_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+-extern int __mb_sb_limit;
+#define GB2312_MB_CUR_MAX 2
-+
-+__private_extern__ int _GB2312_init(struct __xlocale_st_runelocale *);
-+static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
-+static int _GB2312_mbsinit(const mbstate_t *, locale_t);
-+static size_t _GB2312_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+ static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _GB2312_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
++static int _GB2312_mbsinit(const mbstate_t *, locale_t);
+ static size_t _GB2312_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
+-
++ mbstate_t * __restrict, locale_t);
typedef struct {
int count;
u_char bytes[2];
- __wcrtomb = _GB2312_wcrtomb;
- __mbsinit = _GB2312_mbsinit;
- __mb_cur_max = 2;
+- __mb_sb_limit = 128;
+ xrl->__mbrtowc = _GB2312_mbrtowc;
+ xrl->__wcrtomb = _GB2312_wcrtomb;
+ xrl->__mbsinit = _GB2312_mbsinit;
+ xrl->__mb_cur_max = GB2312_MB_CUR_MAX;
++ xrl->__mb_sb_limit = 128;
return (0);
}
--int
+ static int
-_GB2312_mbsinit(const mbstate_t *ps)
-+static int
-+_GB2312_mbsinit(const mbstate_t *ps, locale_t loc)
++_GB2312_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _GB2312State *)ps)->count == 0);
-@@ -88,9 +91,9 @@
- return (1);
- }
+@@ -93,7 +93,7 @@ _GB2312_check(const char *str, size_t n)
--size_t
-+static size_t
+ static size_t
_GB2312_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps)
-+ mbstate_t * __restrict ps, locale_t loc)
++ mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB2312State *gs;
wchar_t wc;
-@@ -110,7 +113,7 @@
+@@ -113,7 +113,7 @@ _GB2312_mbrtowc(wchar_t * __restrict pwc
pwc = NULL;
}
memcpy(gs->bytes + gs->count, s, ncopy);
ocount = gs->count;
gs->count += ncopy;
-@@ -129,8 +132,8 @@
- return (wc == L'\0' ? 0 : len - ocount);
+@@ -133,7 +133,7 @@ _GB2312_mbrtowc(wchar_t * __restrict pwc
}
--size_t
+ static size_t
-_GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
-+_GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
++_GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB2312State *gs;
* 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.
* SUCH DAMAGE.
*/
-#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/gbk.c,v 1.11 2004/05/17 11:16:14 tjr Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/gbk.c,v 1.14 2007/10/13 16:28:21 ache Exp $");
+#include <sys/types.h>
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
-int _GBK_init(_RuneLocale *);
-size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _GBK_mbsinit(const mbstate_t *);
-size_t _GBK_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+extern int __mb_sb_limit;
+
+static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _GBK_mbsinit(const mbstate_t *);
+static size_t _GBK_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
typedef struct {
wchar_t ch;
__mbsinit = _GBK_mbsinit;
_CurrentRuneLocale = rl;
__mb_cur_max = 2;
+ __mb_sb_limit = 128;
return (0);
}
-int
+static int
_GBK_mbsinit(const mbstate_t *ps)
{
return ((c >= 0x81 && c <= 0xfe) ? 2 : 1);
}
-size_t
+static size_t
_GBK_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps)
{
}
}
-size_t
+static size_t
_GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
_GBKState *gs;
---- gbk.c.orig Thu Nov 25 11:38:17 2004
-+++ gbk.c Fri Feb 18 15:46:58 2005
-@@ -38,6 +38,8 @@
- #include <sys/param.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/gbk.c,v 1.11 2004/05/17 11:16:14 tjr Exp $");
+--- gbk.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ gbk.c 2009-11-09 16:27:30.000000000 -0800
+@@ -34,6 +34,8 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/locale/gbk.c,v 1.14 2007/10/13 16:28:21 ache Exp $");
+#include "xlocale_private.h"
+
+ #include <sys/types.h>
#include <errno.h>
#include <runetype.h>
- #include <stdlib.h>
-@@ -45,30 +47,29 @@
+@@ -42,33 +44,30 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--int _GBK_init(_RuneLocale *);
--size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _GBK_mbsinit(const mbstate_t *);
--size_t _GBK_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
-+__private_extern__ int _GBK_init(struct __xlocale_st_runelocale *);
-+static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
+-extern int __mb_sb_limit;
+-
+ static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _GBK_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
+static int _GBK_mbsinit(const mbstate_t *, locale_t);
-+static size_t _GBK_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+ static size_t _GBK_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
- __mbsinit = _GBK_mbsinit;
- _CurrentRuneLocale = rl;
- __mb_cur_max = 2;
+- __mb_sb_limit = 128;
+ xrl->__mbrtowc = _GBK_mbrtowc;
+ xrl->__wcrtomb = _GBK_wcrtomb;
+ xrl->__mbsinit = _GBK_mbsinit;
+ xrl->__mb_cur_max = 2;
++ xrl->__mb_sb_limit = 128;
return (0);
}
--int
+ static int
-_GBK_mbsinit(const mbstate_t *ps)
-+static int
-+_GBK_mbsinit(const mbstate_t *ps, locale_t loc)
++_GBK_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _GBKState *)ps)->ch == 0);
-@@ -82,9 +83,9 @@
- return ((c >= 0x81 && c <= 0xfe) ? 2 : 1);
- }
+@@ -84,7 +83,7 @@ _gbk_check(u_int c)
--size_t
-+static size_t
+ static size_t
_GBK_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps)
-+ mbstate_t * __restrict ps, locale_t loc)
++ mbstate_t * __restrict ps, locale_t loc __unused)
{
_GBKState *gs;
wchar_t wc;
-@@ -143,8 +144,8 @@
- }
+@@ -144,7 +143,7 @@ _GBK_mbrtowc(wchar_t * __restrict pwc, c
}
--size_t
+ static size_t
-_GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
-+_GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
++_GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GBKState *gs;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isalnum.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isalnum.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isalnum.3,v 1.24 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISALNUM 3
.Os
.Sh NAME
or
.Xr isdigit 3
is true.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Xr isalpha 3 ,
.Xr isdigit 3 ,
.Xr iswalnum 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- isalnum.3 2004-11-25 11:38:17.000000000 -0800
-+++ isalnum.3.edit 2006-08-09 13:19:45.000000000 -0700
-@@ -59,14 +59,14 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
- or the value of
+--- isalnum.3.bsdnew 2009-11-10 13:13:10.000000000 -0800
++++ isalnum.3 2009-11-10 13:22:59.000000000 -0800
+@@ -58,7 +58,7 @@ or the value of
.Dv EOF .
+ .Pp
In the ASCII character set, this includes the following characters
-(with their numeric values shown in octal):
+(preceded by their numeric values, in octal):
.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It "\&060\ ``0'' \t061\ ``1'' \t062\ ``2'' \t063\ ``3'' \t064\ ``4''"
-@@ -100,6 +100,7 @@
+@@ -92,6 +92,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isalpha.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isalpha.3,v 1.18 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isalpha.3,v 1.23 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISALPHA 3
.Os
.Sh NAME
or
.Xr islower 3
is true.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Xr islower 3 ,
.Xr isupper 3 ,
.Xr iswalpha 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- isalpha.3 2004-11-25 11:38:17.000000000 -0800
-+++ isalpha.3.edit 2006-08-09 13:21:04.000000000 -0700
-@@ -59,14 +59,14 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
- or the value of
+--- isalpha.3.bsdnew 2009-11-10 13:13:10.000000000 -0800
++++ isalpha.3 2009-11-10 13:24:18.000000000 -0800
+@@ -58,7 +58,7 @@ or the value of
.Dv EOF .
+ .Pp
In the ASCII character set, this includes the following characters
-(with their numeric values shown in octal):
+(preceded by their numeric values, in octal):
.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It "\&101\ ``A'' \t102\ ``B'' \t103\ ``C'' \t104\ ``D'' \t105\ ``E''"
-@@ -98,6 +98,7 @@
+@@ -90,6 +90,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isascii.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/locale/isascii.3,v 1.13 2002/10/06 10:15:38 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isascii.3,v 1.16 2009/09/04 07:44:58 des Exp $
.\"
.Dd October 6, 2002
.Dt ISASCII 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isblank.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isblank.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isblank.3,v 1.26 2009/11/11 11:31:02 roam Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISBLANK 3
.Os
.Sh NAME
.It "\&``\et''\t`` ''"
.El
.Pp
-In the "C" locale
+In the "C" locale, a successful
.Fn isblank
-successful test is limited to this characters only.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+test is limited to these characters only.
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Sh RETURN VALUES
+The
+.Fn isblank
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
.Sh COMPATIBILITY
The
.Bx 4.4
The
.Fn iswblank
function should be used instead.
-.Sh RETURN VALUES
-The
-.Fn isblank
-function returns zero if the character tests false and
-returns non-zero if the character tests true.
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswblank 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- isblank.3 2004-11-25 11:38:17.000000000 -0800
-+++ isblank.3.edit 2006-08-09 13:23:09.000000000 -0700
-@@ -54,13 +54,13 @@
- .It "\&``\et''\t`` ''"
- .El
- .Pp
--In the "C" locale
-+In the "C" locale,
- .Fn isblank
--successful test is limited to this characters only.
-+successful test is limited to these characters only.
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
-@@ -83,6 +83,7 @@
- returns non-zero if the character tests true.
+--- isblank.3.orig 2009-11-30 16:10:19.000000000 -0800
++++ isblank.3 2009-11-30 16:10:19.000000000 -0800
+@@ -74,6 +74,7 @@ The
+ function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswblank 3 ,
- .Xr multibyte 3 ,
.Xr ascii 7
+ .Sh STANDARDS
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)iscntrl.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/iscntrl.3,v 1.17 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/iscntrl.3,v 1.22 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISCNTRL 3
.Os
.Sh NAME
The
.Fn iscntrl
function tests for any control character.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswcntrl 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- iscntrl.3 2004-11-25 11:38:17.000000000 -0800
-+++ iscntrl.3.edit 2006-08-09 13:23:23.000000000 -0700
-@@ -55,14 +55,14 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
- or the value of
+--- iscntrl.3.bsdnew 2009-11-10 13:13:10.000000000 -0800
++++ iscntrl.3 2009-11-10 13:33:05.000000000 -0800
+@@ -54,7 +54,7 @@ or the value of
.Dv EOF .
+ .Pp
In the ASCII character set, this includes the following characters
-(with their numeric values shown in octal):
+(preceded by their numeric values, in octal):
.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It "\&000\ NUL \t001\ SOH \t002\ STX \t003\ ETX \t004\ EOT"
-@@ -90,6 +90,7 @@
+@@ -82,6 +82,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswcntrl 3 ,
- .Xr multibyte 3 ,
.Xr ascii 7
+ .Sh STANDARDS
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isdigit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isdigit.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isdigit.3,v 1.25 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd May 4, 2007
.Dt ISDIGIT 3
.Os
.Sh NAME
but may recognize additional characters, depending on the current locale
setting.
.Pp
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
and
.Fn isnumber
functions return zero if the character tests false and
-returns non-zero if the character tests true.
+return non-zero if the character tests true.
.Sh COMPATIBILITY
The
.Bx 4.4
---- isdigit.3 2004-11-25 11:38:17.000000000 -0800
-+++ isdigit.3.edit 2006-08-09 13:23:40.000000000 -0700
-@@ -71,7 +71,7 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
-@@ -83,7 +83,7 @@
- and
- .Fn isnumber
- functions return zero if the character tests false and
--returns non-zero if the character tests true.
-+return non-zero if the character tests true.
- .Sh COMPATIBILITY
- The
- .Bx 4.4
-@@ -96,6 +96,7 @@
+--- isdigit.3.bsdnew 2009-11-10 13:13:10.000000000 -0800
++++ isdigit.3 2009-11-10 13:34:59.000000000 -0800
+@@ -87,6 +87,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isgraph.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/locale/isgraph.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isgraph.3,v 1.25 2009/11/13 09:03:50 roam Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISGRAPH 3
.Os
.Sh NAME
function tests for any printing character except space
.Pq Ql "\ "
and other
-locale specific space-like characters.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+locale-specific space-like characters.
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswgraph 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- isgraph.3 2004-11-25 11:38:17.000000000 -0800
-+++ isgraph.3.edit 2006-08-09 13:23:59.000000000 -0700
-@@ -54,18 +54,18 @@
- function tests for any printing character except space
- .Pq Ql "\ "
- and other
--locale specific space-like characters.
-+locale-specific, space-like characters.
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
- or the value of
+--- isgraph.3.orig 2009-11-30 16:10:19.000000000 -0800
++++ isgraph.3 2009-11-30 16:11:41.000000000 -0800
+@@ -57,7 +57,7 @@ or the value of
.Dv EOF .
+ .Pp
In the ASCII character set, this includes the following characters
-(with their numeric values shown in octal):
+(preceded by their numeric values, in octal):
.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It "\&041\ ``!'' \t042\ ``""'' \t043\ ``#'' \t044\ ``$'' \t045\ ``%''"
-@@ -105,6 +105,7 @@
+@@ -97,6 +97,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswgraph 3 ,
- .Xr multibyte 3 ,
.Xr ascii 7
+ .Sh STANDARDS
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isideogram.3,v 1.2 2004/07/04 20:55:48 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/isideogram.3,v 1.4 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISIDEOGRAM 3
---- isideogram.3.orig Fri Mar 11 19:25:22 2005
-+++ isideogram.3 Fri Mar 11 19:26:54 2005
-@@ -49,7 +49,8 @@
+--- isideogram.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ isideogram.3 2009-11-09 15:05:26.000000000 -0800
+@@ -49,7 +49,8 @@ returns non-zero if the character tests
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr isphonogram 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)islower.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/islower.3,v 1.17 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/islower.3,v 1.22 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISLOWER 3
.Os
.Sh NAME
The
.Fn islower
function tests for any lower-case letters.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswlower 3 ,
-.Xr multibyte 3 ,
.Xr tolower 3 ,
.Xr ascii 7
.Sh STANDARDS
---- islower.3 2004-11-25 11:38:17.000000000 -0800
-+++ islower.3.edit 2006-08-09 13:24:14.000000000 -0700
-@@ -89,6 +89,7 @@
+--- islower.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ islower.3 2009-11-09 15:05:26.000000000 -0800
+@@ -81,6 +81,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswlower 3 ,
- .Xr multibyte 3 ,
.Xr tolower 3 ,
+ .Xr ascii 7
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isphonogram.3,v 1.1 2004/03/30 07:23:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isphonogram.3,v 1.3 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISPHONOGRAM 3
---- isphonogram.3.orig Fri Mar 11 19:25:22 2005
-+++ isphonogram.3 Fri Mar 11 19:26:47 2005
-@@ -49,7 +49,8 @@
+--- isphonogram.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ isphonogram.3 2009-11-09 15:05:26.000000000 -0800
+@@ -49,7 +49,8 @@ returns non-zero if the character tests
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr isideogram 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isprint.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isprint.3,v 1.20 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isprint.3,v 1.26 2009/11/13 09:07:33 roam Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISPRINT 3
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn isprint
-function tests for any printing character including space
+function tests for any printing character, including space
.Pq Ql "\ " .
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswprint 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- isprint.3 2004-11-25 11:38:17.000000000 -0800
-+++ isprint.3.edit 2006-08-09 13:24:27.000000000 -0700
-@@ -51,19 +51,19 @@
- .Sh DESCRIPTION
- The
- .Fn isprint
--function tests for any printing character including space
-+function tests for any printing character, including space
- .Pq Ql "\ " .
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
- or the value of
+--- isprint.3.orig 2009-11-30 16:10:19.000000000 -0800
++++ isprint.3 2009-11-30 16:10:29.000000000 -0800
+@@ -55,7 +55,7 @@ or the value of
.Dv EOF .
+ .Pp
In the ASCII character set, this includes the following characters
-(with their numeric values shown in octal):
+(preceded by their numeric values, in octal):
.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It "\&040\ sp \t041\ ``!'' \t042\ ``""'' \t043\ ``#'' \t044\ ``$''"
-@@ -103,6 +103,7 @@
+@@ -95,6 +95,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswprint 3 ,
- .Xr multibyte 3 ,
.Xr ascii 7
+ .Sh STANDARDS
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ispunct.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/ispunct.3,v 1.18 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/ispunct.3,v 1.23 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISPUNCT 3
.Os
.Sh NAME
character for which
.Xr isalnum 3
is true.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswpunct 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- ispunct.3 2004-11-25 11:38:17.000000000 -0800
-+++ ispunct.3.edit 2006-08-09 13:24:42.000000000 -0700
-@@ -51,7 +51,7 @@
+--- ispunct.3.bsdnew 2009-11-10 13:13:10.000000000 -0800
++++ ispunct.3 2009-11-10 13:17:02.000000000 -0800
+@@ -47,7 +47,7 @@
.Sh DESCRIPTION
The
.Fn ispunct
.Pq Ql "\ "
or a
character for which
-@@ -60,14 +60,14 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
- or the value of
+@@ -59,7 +59,7 @@ or the value of
.Dv EOF .
+ .Pp
In the ASCII character set, this includes the following characters
-(with their numeric values shown in octal):
+(preceded by their numeric values, in octal):
.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It "\&041\ ``!'' \t042\ ``""'' \t043\ ``#'' \t044\ ``$'' \t045\ ``%''"
-@@ -95,6 +95,7 @@
+@@ -87,6 +87,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswpunct 3 ,
- .Xr multibyte 3 ,
.Xr ascii 7
+ .Sh STANDARDS
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isrune.3,v 1.1 2004/03/30 07:23:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isrune.3,v 1.3 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISRUNE 3
---- isrune.3.orig Fri Mar 11 19:25:22 2005
-+++ isrune.3 Fri Mar 11 19:26:33 2005
-@@ -55,7 +55,8 @@
+--- isrune.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ isrune.3 2009-11-09 15:05:26.000000000 -0800
+@@ -55,7 +55,8 @@ returns non-zero if the character tests
.Xr ctype 3 ,
.Xr isascii 3 ,
.Xr iswrune 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isspace.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isspace.3,v 1.17 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isspace.3,v 1.22 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISSPACE 3
.Os
.Sh NAME
In the "C" locale
.Fn isspace
successful test is limited to this characters only.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
---- isspace.3 2004-11-25 11:38:17.000000000 -0800
-+++ isspace.3.edit 2006-08-09 13:24:59.000000000 -0700
-@@ -58,13 +58,13 @@
+--- isspace.3.bsdnew 2009-11-10 13:13:10.000000000 -0800
++++ isspace.3 2009-11-10 13:45:41.000000000 -0800
+@@ -54,9 +54,9 @@ For any locale, this includes the follow
.It "\&``\et''\t``\en''\t``\ev''\t``\ef''\t``\er''\t`` ''"
.El
.Pp
.Fn isspace
-successful test is limited to this characters only.
+successful test is limited to these characters only.
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
-@@ -87,6 +87,7 @@
+ The value of the argument must be representable as an
+ .Vt "unsigned char"
+ or the value of
+@@ -78,6 +78,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isspecial.3,v 1.1 2004/03/30 07:23:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isspecial.3,v 1.3 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISSPECIAL 3
---- isspecial.3.orig Fri Mar 11 19:25:22 2005
-+++ isspecial.3 Fri Mar 11 19:26:16 2005
-@@ -48,7 +48,8 @@
+--- isspecial.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ isspecial.3 2009-11-09 15:05:26.000000000 -0800
+@@ -48,7 +48,8 @@ function returns zero if the character t
returns non-zero if the character tests true.
.Sh SEE ALSO
.Xr ctype 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isupper.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isupper.3,v 1.18 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isupper.3,v 1.23 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISUPPER 3
.Os
.Sh NAME
The
.Fn isupper
function tests for any upper-case letter.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswupper 3 ,
-.Xr multibyte 3 ,
.Xr toupper 3 ,
.Xr ascii 7
.Sh STANDARDS
---- isupper.3 2004-11-25 11:38:17.000000000 -0800
-+++ isupper.3.edit 2006-08-09 13:25:22.000000000 -0700
-@@ -55,14 +55,14 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
- or the value of
+--- isupper.3.bsdnew 2009-11-10 13:13:10.000000000 -0800
++++ isupper.3 2009-11-10 13:48:09.000000000 -0800
+@@ -54,7 +54,7 @@ or the value of
.Dv EOF .
+ .Pp
In the ASCII character set, this includes the following characters
-(with their numeric values shown in octal):
+(preceded by their numeric values, in octal):
.Pp
.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
.It "\&101\ ``A'' \t102\ ``B'' \t103\ ``C'' \t104\ ``D'' \t105\ ``E''"
-@@ -89,6 +89,7 @@
+@@ -81,6 +81,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswupper 3 ,
- .Xr multibyte 3 ,
.Xr toupper 3 ,
+ .Xr ascii 7
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isalnum.3 5.2 (Berkeley) 6/29/91
-.\" $FreeBSD: src/lib/libc/locale/iswalnum.3,v 1.5 2002/11/29 17:35:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/iswalnum.3,v 1.6 2007/01/09 00:28:00 imp Exp $
.\"
.Dd October 3, 2002
.Dt ISWALNUM 3
---- iswalnum.3 2003-05-20 15:21:44.000000000 -0700
-+++ iswalnum.3.edit 2006-08-09 13:28:43.000000000 -0700
-@@ -111,9 +111,15 @@
+--- iswalnum.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ iswalnum.3 2009-11-09 15:05:26.000000000 -0800
+@@ -107,9 +107,15 @@ for use with wide characters
or
.Vt wint_t ) .
See the description for the similarly-named single byte classification
.Sh RETURN VALUES
The functions return zero if the character tests false and
return non-zero if the character tests true.
-@@ -136,6 +142,7 @@
+@@ -132,6 +138,7 @@ return non-zero if the character tests t
.Xr isspace 3 ,
.Xr isspecial 3 ,
.Xr isupper 3 ,
.Xr isxdigit 3 ,
.Xr wctype 3
.Sh STANDARDS
-@@ -147,7 +154,7 @@
+@@ -143,7 +150,7 @@ except
.Fn iswideogram ,
.Fn iswnumber ,
.Fn iswphonogram ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isxdigit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isxdigit.3,v 1.20 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isxdigit.3,v 1.25 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISXDIGIT 3
.Os
.Sh NAME
but may recognize additional characters,
depending on the current locale setting.
.Pp
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr iswxdigit 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
---- isxdigit.3 2004-11-25 11:38:17.000000000 -0800
-+++ isxdigit.3.edit 2006-08-09 13:29:19.000000000 -0700
-@@ -74,7 +74,7 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
-@@ -97,6 +97,7 @@
+--- isxdigit.3.bsdnew 2009-11-10 13:13:11.000000000 -0800
++++ isxdigit.3 2009-11-10 13:48:37.000000000 -0800
+@@ -88,6 +88,7 @@ The
function should be used instead.
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr isalnum_l 3 ,
.Xr iswxdigit 3 ,
- .Xr multibyte 3 ,
.Xr ascii 7
+ .Sh STANDARDS
---- ldpart.c.orig 2008-06-03 18:15:42.000000000 -0700
-+++ ldpart.c 2008-06-18 13:23:20.000000000 -0700
+--- ldpart.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ ldpart.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/ldpart.c,v 1.15 2004/04/25 19:56:50 ache Exp $");
---- ldpart.h.orig 2004-11-25 11:38:17.000000000 -0800
-+++ ldpart.h 2005-02-13 19:02:54.000000000 -0800
+--- ldpart.h.orig 2009-11-09 15:05:25.000000000 -0800
++++ ldpart.h 2009-11-09 15:05:25.000000000 -0800
@@ -33,7 +33,7 @@
#define _LDP_ERROR (-1)
#define _LDP_CACHE 1
---- lmessages.c.orig 2004-11-25 11:38:17.000000000 -0800
-+++ lmessages.c 2005-02-17 10:13:34.000000000 -0800
+--- lmessages.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ lmessages.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,7 +27,10 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/lmessages.c,v 1.14 2003/06/26 10:46:16 phantom Exp $");
#include "ldpart.h"
#include "lmessages.h"
-@@ -45,47 +48,76 @@
+@@ -45,47 +48,76 @@ static const struct lc_messages_T _C_mes
"no" /* nostr */
};
---- lmessages.h.orig 2003-05-20 15:21:44.000000000 -0700
-+++ lmessages.h 2005-02-19 14:39:44.000000000 -0800
+--- lmessages.h.orig 2009-11-09 15:05:25.000000000 -0800
++++ lmessages.h 2009-11-09 15:05:25.000000000 -0800
@@ -29,6 +29,8 @@
#ifndef _LMESSAGES_H_
#define _LMESSAGES_H_
struct lc_messages_T {
const char *yesexpr;
const char *noexpr;
-@@ -36,7 +38,7 @@
+@@ -36,7 +38,7 @@ struct lc_messages_T {
const char *nostr;
};
---- lmonetary.c.orig 2004-11-25 11:38:17.000000000 -0800
-+++ lmonetary.c 2005-03-16 23:05:30.000000000 -0800
+--- lmonetary.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ lmonetary.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,14 +27,16 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/lmonetary.c,v 1.19 2003/06/26 10:46:16 phantom Exp $");
extern const char * __fix_locale_grouping_str(const char *);
#define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *))
-@@ -50,7 +52,7 @@
+@@ -50,7 +52,7 @@ static const struct lc_monetary_T _C_mon
empty, /* currency_symbol */
empty, /* mon_decimal_point */
empty, /* mon_thousands_sep */
empty, /* positive_sign */
empty, /* negative_sign */
numempty, /* int_frac_digits */
-@@ -69,10 +71,6 @@
+@@ -69,10 +71,6 @@ static const struct lc_monetary_T _C_mon
numempty /* int_n_sign_posn */
};
static char
cnv(const char *str)
{
-@@ -83,23 +81,57 @@
+@@ -83,23 +81,57 @@ cnv(const char *str)
return ((char)i);
}
M_ASSIGN_CHAR(int_frac_digits);
M_ASSIGN_CHAR(frac_digits);
-@@ -117,9 +149,9 @@
+@@ -117,9 +149,9 @@ __monetary_load_locale(const char *name)
*/
#define M_ASSIGN_ICHAR(NAME) \
do { \
else \
M_ASSIGN_CHAR(int_##NAME); \
} while (0)
-@@ -130,21 +162,27 @@
+@@ -130,21 +162,27 @@ __monetary_load_locale(const char *name)
M_ASSIGN_ICHAR(n_sep_by_space);
M_ASSIGN_ICHAR(p_sign_posn);
M_ASSIGN_ICHAR(n_sign_posn);
printf( "int_curr_symbol = %s\n"
"currency_symbol = %s\n"
"mon_decimal_point = %s\n"
-@@ -166,27 +204,27 @@
+@@ -166,27 +204,27 @@ printf( "int_curr_symbol = %s\n"
"int_n_sep_by_space = %d\n"
"int_p_sign_posn = %d\n"
"int_n_sign_posn = %d\n",
---- lmonetary.h.orig 2003-05-20 15:21:44.000000000 -0700
-+++ lmonetary.h 2005-02-19 14:41:58.000000000 -0800
+--- lmonetary.h.orig 2009-11-09 15:05:25.000000000 -0800
++++ lmonetary.h 2009-11-09 15:05:25.000000000 -0800
@@ -29,6 +29,8 @@
#ifndef _LMONETARY_H_
#define _LMONETARY_H_
struct lc_monetary_T {
const char *int_curr_symbol;
const char *currency_symbol;
-@@ -53,7 +55,7 @@
+@@ -53,7 +55,7 @@ struct lc_monetary_T {
const char *int_n_sign_posn;
};
---- lnumeric.c.orig 2004-11-25 11:38:17.000000000 -0800
-+++ lnumeric.c 2005-03-16 23:06:13.000000000 -0800
+--- lnumeric.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ lnumeric.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,67 +27,103 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/lnumeric.c,v 1.16 2003/06/26 10:46:16 phantom Exp $");
---- lnumeric.h.orig 2003-05-20 15:21:44.000000000 -0700
-+++ lnumeric.h 2005-02-19 14:44:29.000000000 -0800
+--- lnumeric.h.orig 2009-11-09 15:05:25.000000000 -0800
++++ lnumeric.h 2009-11-09 15:05:25.000000000 -0800
@@ -29,13 +29,15 @@
#ifndef _LNUMERIC_H_
#define _LNUMERIC_H_
.\" 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.
.\"
.\" From @(#)setlocale.3 8.1 (Berkeley) 6/9/93
.\" From FreeBSD: src/lib/libc/locale/setlocale.3,v 1.28 2003/11/15 02:26:04 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/localeconv.3,v 1.2 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/localeconv.3,v 1.3 2007/01/09 00:28:00 imp Exp $
.\"
.Dd November 21, 2003
.Dt LOCALECONV 3
---- _SB/Libc/locale/FreeBSD/localeconv.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/localeconv.3.edit 2006-06-29 11:04:42.000000000 -0700
-@@ -40,14 +40,22 @@
+--- localeconv.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ localeconv.3 2009-11-09 15:05:26.000000000 -0800
+@@ -36,14 +36,22 @@
.Dt LOCALECONV 3
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn localeconv
-@@ -201,6 +209,14 @@
+@@ -197,6 +205,14 @@ a value that is not in the current local
A
.Dv CHAR_MAX
result similarly denotes an unavailable value.
.Sh RETURN VALUES
The
.Fn localeconv
-@@ -213,7 +229,8 @@
+@@ -209,7 +225,8 @@ or
No errors are defined.
.Sh SEE ALSO
.Xr setlocale 3 ,
* 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.
static char sccsid[] = "@(#)localeconv.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.13 2003/06/26 10:46:16 phantom Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.14 2007/12/12 07:43:23 phantom Exp $");
#include <locale.h>
---- localeconv.c.orig 2008-10-09 11:37:42.000000000 -0700
-+++ localeconv.c 2008-10-10 01:37:33.000000000 -0700
-@@ -38,11 +38,71 @@ static char sccsid[] = "@(#)localeconv.c
+--- localeconv.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ localeconv.c 2009-11-09 15:05:26.000000000 -0800
+@@ -34,11 +34,71 @@ static char sccsid[] = "@(#)localeconv.c
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.13 2003/06/26 10:46:16 phantom Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.14 2007/12/12 07:43:23 phantom Exp $");
+#include "xlocale_private.h"
+
/*
* The localeconv() function constructs a struct lconv from the current
* monetary and numeric locales.
-@@ -52,25 +112,28 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
+@@ -48,25 +108,28 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* lconv structure are computed only when the monetary or numeric
* locale has been changed.
*/
M_ASSIGN_STR(int_curr_symbol);
M_ASSIGN_STR(currency_symbol);
M_ASSIGN_STR(mon_decimal_point);
-@@ -92,21 +155,45 @@ localeconv()
+@@ -88,21 +151,45 @@ localeconv()
M_ASSIGN_CHAR(int_n_sep_by_space);
M_ASSIGN_CHAR(int_p_sign_posn);
M_ASSIGN_CHAR(int_n_sign_posn);
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/mblen.3,v 1.5 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/mblen.3,v 1.6 2007/01/09 00:28:00 imp Exp $
.\"
.Dd April 11, 2004
.Dt MBLEN 3
---- _SB/Libc/locale/FreeBSD/mblen.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/mblen.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -41,33 +41,53 @@
+--- mblen.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ mblen.3 2009-11-09 15:05:26.000000000 -0800
+@@ -37,33 +37,53 @@
.Dt MBLEN 3
.Os
.Sh NAME
is
.Dv NULL ,
the
-@@ -76,14 +96,14 @@
+@@ -72,14 +92,14 @@ function returns nonzero if shift states
zero otherwise.
.Pp
Otherwise, if
or returns \-1 if no multibyte character
could be recognized or converted.
In this case,
-@@ -102,7 +122,8 @@
+@@ -98,7 +118,8 @@ The internal conversion state is not val
.Sh SEE ALSO
.Xr mbrlen 3 ,
.Xr mbtowc 3 ,
---- mblen.c.orig Thu Nov 25 11:38:18 2004
-+++ mblen.c Fri Feb 18 16:55:20 2005
+--- mblen.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mblen.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,24 +27,32 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/mblen.c,v 1.9 2004/07/29 06:18:40 tjr Exp $");
if (rval == (size_t)-1 || rval == (size_t)-2)
return (-1);
return ((int)rval);
-+}
+ }
+
+int
+mblen(const char *s, size_t n)
+{
+ return mblen_l(s, n, __current_locale());
- }
++}
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/lib/libc/locale/mblocal.h,v 1.4 2004/10/17 06:51:50 tjr Exp $
+ * $FreeBSD: src/lib/libc/locale/mblocal.h,v 1.7 2008/01/21 23:48:12 ache Exp $
*/
#ifndef _MBLOCAL_H_
#define _MBLOCAL_H_
+#include <runetype.h>
+
+/*
+ * Rune initialization function prototypes.
+ */
+int _none_init(_RuneLocale *);
+int _ascii_init(_RuneLocale *);
+int _UTF8_init(_RuneLocale *);
+int _EUC_init(_RuneLocale *);
+int _GB18030_init(_RuneLocale *);
+int _GB2312_init(_RuneLocale *);
+int _GBK_init(_RuneLocale *);
+int _BIG5_init(_RuneLocale *);
+int _MSKanji_init(_RuneLocale *);
+
/*
* Conversion function pointers for current encoding.
*/
extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict);
-/*
- * Conversion functions for "NONE"/C/POSIX encoding.
- */
-extern size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
- size_t, mbstate_t * __restrict);
-extern int _none_mbsinit(const mbstate_t *);
-extern size_t _none_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
-extern size_t _none_wcrtomb(char * __restrict, wchar_t,
- mbstate_t * __restrict);
-extern size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
-
extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
size_t, size_t, mbstate_t * __restrict);
extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict,
---- mblocal.h.orig 2004-11-25 11:38:18.000000000 -0800
-+++ mblocal.h 2005-02-18 18:25:53.000000000 -0800
-@@ -30,33 +30,21 @@
- #define _MBLOCAL_H_
-
+--- mblocal.h.orig 2009-11-09 15:05:25.000000000 -0800
++++ mblocal.h 2009-11-09 19:00:41.000000000 -0800
+@@ -34,31 +34,31 @@
/*
+ * Rune initialization function prototypes.
+ */
+-int _none_init(_RuneLocale *);
+-int _ascii_init(_RuneLocale *);
+-int _UTF8_init(_RuneLocale *);
+-int _EUC_init(_RuneLocale *);
+-int _GB18030_init(_RuneLocale *);
+-int _GB2312_init(_RuneLocale *);
+-int _GBK_init(_RuneLocale *);
+-int _BIG5_init(_RuneLocale *);
+-int _MSKanji_init(_RuneLocale *);
++__private_extern__ int _none_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _ascii_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _UTF2_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _UTF8_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _EUC_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _GB18030_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _GB2312_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _GBK_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _BIG5_init(struct __xlocale_st_runelocale *);
++__private_extern__ int _MSKanji_init(struct __xlocale_st_runelocale *);
+
+-/*
- * Conversion function pointers for current encoding.
- */
-extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict,
-extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict);
-extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
--
--/*
- * Conversion functions for "NONE"/C/POSIX encoding.
- */
- extern size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
-- size_t, mbstate_t * __restrict);
--extern int _none_mbsinit(const mbstate_t *);
-+ size_t, mbstate_t * __restrict, locale_t);
-+extern int _none_mbsinit(const mbstate_t *, locale_t);
- extern size_t _none_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
-- size_t, size_t, mbstate_t * __restrict);
-+ size_t, size_t, mbstate_t * __restrict, locale_t);
- extern size_t _none_wcrtomb(char * __restrict, wchar_t,
-- mbstate_t * __restrict);
-+ mbstate_t * __restrict, locale_t);
- extern size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
-- size_t, size_t, mbstate_t * __restrict);
-+ size_t, size_t, mbstate_t * __restrict, locale_t);
++__private_extern__ size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
++ size_t, mbstate_t * __restrict, locale_t);
++__private_extern__ int _none_mbsinit(const mbstate_t *, locale_t);
++__private_extern__ size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
++ const char ** __restrict src, size_t nms, size_t len,
++ mbstate_t * __restrict ps __unused, locale_t);
++__private_extern__ size_t _none_wcrtomb(char * __restrict, wchar_t,
++ mbstate_t * __restrict, locale_t);
++__private_extern__ size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
++ size_t, size_t, mbstate_t * __restrict, locale_t);
extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
---- _SB/Libc/locale/FreeBSD/mbrlen.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/mbrlen.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- mbrlen.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbrlen.3 2009-11-09 15:05:25.000000000 -0800
@@ -28,21 +28,35 @@
.Dt MBRLEN 3
.Os
to determine the number of bytes needed to complete the next
multibyte character.
.Pp
-@@ -63,7 +77,7 @@
+@@ -63,7 +77,7 @@ It is equivalent to:
.Pp
.Dl "mbrtowc(NULL, s, n, ps);"
.Pp
.Fa ps
is a
.Dv NULL
-@@ -72,6 +86,14 @@
+@@ -72,6 +86,14 @@ pointer,
uses its own static, internal
.Vt mbstate_t
object to keep track of the shift state.
.Sh RETURN VALUES
The
.Fn mbrlen
-@@ -137,7 +159,8 @@
+@@ -137,7 +159,8 @@ The conversion state is invalid.
.Sh SEE ALSO
.Xr mblen 3 ,
.Xr mbrtowc 3 ,
---- mbrlen.c.orig Thu Nov 25 11:38:18 2004
-+++ mbrlen.c Fri Feb 18 16:54:36 2005
+--- mbrlen.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbrlen.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,15 +27,23 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/mbrlen.c,v 1.4 2004/05/12 14:26:54 tjr Exp $");
---- _SB/Libc/locale/FreeBSD/mbrtowc.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/mbrtowc.3.edit 2006-06-29 11:10:29.000000000 -0700
+--- mbrtowc.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbrtowc.3 2009-11-09 15:05:25.000000000 -0800
@@ -28,7 +28,8 @@
.Dt MBRTOWC 3
.Os
to determine the number of bytes needed to complete the next multibyte
character.
If a character can be completed, and
-@@ -65,14 +78,14 @@
+@@ -65,14 +78,14 @@ is
.Fn mbrtowc
behaves as if
.Fa pwc
.Pp
The
.Vt mbstate_t
-@@ -86,6 +99,14 @@
+@@ -86,6 +99,14 @@ uses an internal, static
.Vt mbstate_t
object, which is initialized to the initial conversion state
at program startup.
.Sh RETURN VALUES
The
.Fn mbrtowc
-@@ -131,7 +152,8 @@
+@@ -131,7 +152,8 @@ The conversion state is invalid.
.Xr mbtowc 3 ,
.Xr multibyte 3 ,
.Xr setlocale 3 ,
---- mbrtowc.c.orig 2004-11-25 11:38:18.000000000 -0800
-+++ mbrtowc.c 2005-02-18 18:21:18.000000000 -0800
+--- mbrtowc.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbrtowc.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,16 +27,24 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/mbrtowc.c,v 1.7 2004/05/12 14:09:04 tjr Exp $");
---- _SB/Libc/locale/FreeBSD/mbsinit.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/mbsinit.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- mbsinit.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbsinit.3 2009-11-09 15:05:25.000000000 -0800
@@ -28,7 +28,8 @@
.Dt MBSINIT 3
.Os
.Sh DESCRIPTION
The
.Fn mbsinit
-@@ -44,6 +49,14 @@
+@@ -44,6 +49,14 @@ function determines whether the
object pointed to by
.Fa ps
describes an initial conversion state.
.Sh RETURN VALUES
The
.Fn mbsinit
-@@ -51,15 +64,16 @@
+@@ -51,15 +64,16 @@ function returns non-zero if
.Fa ps
is
.Dv NULL
---- mbsinit.c.orig Thu Nov 25 11:38:18 2004
-+++ mbsinit.c Fri Feb 18 16:12:33 2005
+--- mbsinit.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbsinit.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,12 +27,21 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/mbsinit.c,v 1.3 2004/05/12 14:09:04 tjr Exp $");
---- mbsnrtowcs.c.orig Thu Nov 25 11:38:18 2004
-+++ mbsnrtowcs.c Fri Feb 18 16:57:14 2005
+--- mbsnrtowcs.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbsnrtowcs.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/mbsnrtowcs.c,v 1.1 2004/07/21 10:54:57 tjr Exp $");
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
-@@ -34,31 +36,40 @@
+@@ -34,31 +36,40 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "mblocal.h"
size_t
/* Invalid sequence - mbrtowc() sets errno. */
return ((size_t)-1);
else if (nb == 0 || nb == (size_t)-2)
-@@ -71,7 +82,7 @@
+@@ -71,7 +82,7 @@ __mbsnrtowcs_std(wchar_t * __restrict ds
}
while (len-- > 0) {
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/mbsrtowcs.3,v 1.5 2004/07/21 10:54:57 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/mbsrtowcs.3,v 1.6 2005/01/11 20:50:49 ru Exp $
.Dd July 21, 2004
.Dt MBSRTOWCS 3
.Os
.Fn mbsrtowcs ,
except that conversion stops after reading at most
.Fa nms
-bytes from the buffer pointed to by
+bytes from the buffer pointed to by
.Fa src .
.Sh RETURN VALUES
The
---- _SB/Libc/locale/FreeBSD/mbsrtowcs.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/mbsrtowcs.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- mbsrtowcs.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbsrtowcs.3 2009-11-09 15:05:26.000000000 -0800
@@ -27,29 +27,55 @@
.Dt MBSRTOWCS 3
.Os
.Fa len
of them in the
.Vt wchar_t
-@@ -97,6 +123,18 @@
+@@ -97,6 +123,18 @@ except that conversion stops after readi
.Fa nms
- bytes from the buffer pointed to by
+ bytes from the buffer pointed to by
.Fa src .
+.Pp
+While the
.Sh RETURN VALUES
The
.Fn mbsrtowcs
-@@ -123,7 +161,8 @@
+@@ -123,7 +161,8 @@ The conversion state is invalid.
.Xr mbrtowc 3 ,
.Xr mbstowcs 3 ,
.Xr multibyte 3 ,
---- mbsrtowcs.c.orig 2004-11-25 11:38:18.000000000 -0800
-+++ mbsrtowcs.c 2005-02-18 18:28:00.000000000 -0800
+--- mbsrtowcs.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbsrtowcs.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/mbsrtowcs.c,v 1.6 2004/07/21 10:54:57 tjr Exp $");
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
-@@ -34,12 +36,18 @@
+@@ -34,12 +36,18 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "mblocal.h"
size_t
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/mbstowcs.3,v 1.4 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/mbstowcs.3,v 1.5 2007/01/09 00:28:00 imp Exp $
.\"
.Dd April 8, 2004
.Dt MBSTOWCS 3
---- _SB/Libc/locale/FreeBSD/mbstowcs.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/mbstowcs.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -41,7 +41,8 @@
+--- mbstowcs.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbstowcs.3 2009-11-09 15:05:26.000000000 -0800
+@@ -37,7 +37,8 @@
.Dt MBSTOWCS 3
.Os
.Sh NAME
.Nd convert a character string to a wide-character string
.Sh LIBRARY
.Lb libc
-@@ -49,21 +50,39 @@
+@@ -45,21 +46,39 @@
.In stdlib.h
.Ft size_t
.Fo mbstowcs
.Sh RETURN VALUES
The
.Fn mbstowcs
-@@ -83,7 +102,8 @@
+@@ -79,7 +98,8 @@ The conversion state is invalid.
.Sh SEE ALSO
.Xr mbsrtowcs 3 ,
.Xr mbtowc 3 ,
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/mbstowcs.c,v 1.11 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbstowcs.c,v 1.12 2009/01/15 18:53:52 rdivacky Exp $");
#include <limits.h>
#include <stdlib.h>
{
static const mbstate_t initial;
mbstate_t mbs;
+ const char *sp;
mbs = initial;
- return (__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs));
+ sp = s;
+ return (__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs));
}
---- mbstowcs.c.orig Thu Nov 25 11:38:18 2004
-+++ mbstowcs.c Fri Feb 18 17:02:15 2005
-@@ -27,17 +27,27 @@
+--- mbstowcs.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ mbstowcs.c 2009-11-09 16:20:59.000000000 -0800
+@@ -27,19 +27,29 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/mbstowcs.c,v 1.11 2004/07/21 10:54:57 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/mbstowcs.c,v 1.12 2009/01/15 18:53:52 rdivacky Exp $");
+#include "xlocale_private.h"
+
{
static const mbstate_t initial;
mbstate_t mbs;
+ const char *sp;
+ NORMALIZE_LOCALE(loc);
mbs = initial;
-- return (__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs));
-+ return (loc->__lc_ctype->__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs, loc));
+ sp = s;
+- return (__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs));
++ return (loc->__lc_ctype->__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs, loc));
+}
+
+size_t
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/mbtowc.3,v 1.4 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/mbtowc.3,v 1.5 2007/01/09 00:28:00 imp Exp $
.\"
.Dd April 11, 2004
.Dt MBTOWC 3
---- _SB/Libc/locale/FreeBSD/mbtowc.3 2004-11-25 11:38:18.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/mbtowc.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -41,7 +41,8 @@
+--- mbtowc.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbtowc.3 2009-11-09 15:05:26.000000000 -0800
+@@ -37,7 +37,8 @@
.Dt MBTOWC 3
.Os
.Sh NAME
.Nd convert a character to a wide-character code
.Sh LIBRARY
.Lb libc
-@@ -49,30 +50,48 @@
+@@ -45,30 +46,48 @@
.In stdlib.h
.Ft int
.Fo mbtowc
is
.Dv NULL ,
the
-@@ -81,14 +100,14 @@
+@@ -77,14 +96,14 @@ function returns nonzero if shift states
zero otherwise.
.Pp
Otherwise, if
or returns \-1 if no multibyte character
could be recognized or converted.
In this case,
-@@ -110,7 +129,8 @@
+@@ -106,7 +125,8 @@ The internal conversion state is invalid
.Xr mbrtowc 3 ,
.Xr mbstowcs 3 ,
.Xr multibyte 3 ,
---- mbtowc.c.orig Thu Nov 25 11:38:18 2004
-+++ mbtowc.c Fri Feb 18 17:12:35 2005
+--- mbtowc.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mbtowc.c 2009-11-09 15:05:25.000000000 -0800
@@ -27,24 +27,33 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/mbtowc.c,v 1.11 2004/07/29 06:18:40 tjr Exp $");
if (rval == (size_t)-1 || rval == (size_t)-2)
return (-1);
return ((int)rval);
-+}
+ }
+
+int
+mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n)
+{
+ return mbtowc_l(pwc, s, n, __current_locale());
- }
++}
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)mskanji.c 1.0 (Phase One) 5/5/95";
#endif /* LIBC_SCCS and not lint */
-#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/mskanji.c,v 1.16 2004/05/14 15:40:47 tjr Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/mskanji.c,v 1.18 2007/10/13 16:28:22 ache Exp $");
+#include <sys/types.h>
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
-int _MSKanji_init(_RuneLocale *);
-size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _MSKanji_mbsinit(const mbstate_t *);
-size_t _MSKanji_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+extern int __mb_sb_limit;
+
+static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _MSKanji_mbsinit(const mbstate_t *);
+static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
typedef struct {
wchar_t ch;
__mbsinit = _MSKanji_mbsinit;
_CurrentRuneLocale = rl;
__mb_cur_max = 2;
+ __mb_sb_limit = 256;
return (0);
}
-int
+static int
_MSKanji_mbsinit(const mbstate_t *ps)
{
return (ps == NULL || ((const _MSKanjiState *)ps)->ch == 0);
}
-size_t
+static size_t
_MSKanji_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps)
{
}
}
-size_t
+static size_t
_MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
_MSKanjiState *ms;
---- mskanji.c.orig Thu Nov 25 11:38:18 2004
-+++ mskanji.c Fri Feb 18 15:49:37 2005
-@@ -36,9 +36,12 @@
- #if defined(LIBC_SCCS) && !defined(lint)
- static char sccsid[] = "@(#)mskanji.c 1.0 (Phase One) 5/5/95";
- #endif /* LIBC_SCCS and not lint */
--#include <sys/param.h>
-+#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/mskanji.c,v 1.16 2004/05/14 15:40:47 tjr Exp $");
+--- mskanji.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ mskanji.c 2009-11-09 16:30:02.000000000 -0800
+@@ -39,6 +39,8 @@ static char sccsid[] = "@(#)mskanji.c 1.
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/locale/mskanji.c,v 1.18 2007/10/13 16:28:22 ache Exp $");
+#include "xlocale_private.h"
+
-+#include <sys/param.h>
+ #include <sys/types.h>
#include <errno.h>
#include <runetype.h>
- #include <stdlib.h>
-@@ -46,38 +49,37 @@
+@@ -47,33 +49,30 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--int _MSKanji_init(_RuneLocale *);
--size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _MSKanji_mbsinit(const mbstate_t *);
--size_t _MSKanji_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
-+__private_extern__ int _MSKanji_init(struct __xlocale_st_runelocale *);
-+static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
+-extern int __mb_sb_limit;
+-
+ static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _MSKanji_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
+static int _MSKanji_mbsinit(const mbstate_t *, locale_t);
-+static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+ static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
- __mbsinit = _MSKanji_mbsinit;
- _CurrentRuneLocale = rl;
- __mb_cur_max = 2;
+- __mb_sb_limit = 256;
+ xrl->__mbrtowc = _MSKanji_mbrtowc;
+ xrl->__wcrtomb = _MSKanji_wcrtomb;
+ xrl->__mbsinit = _MSKanji_mbsinit;
+ xrl->__mb_cur_max = 2;
++ xrl->__mb_sb_limit = 256;
return (0);
}
--int
+ static int
-_MSKanji_mbsinit(const mbstate_t *ps)
-+static int
-+_MSKanji_mbsinit(const mbstate_t *ps, locale_t loc)
++_MSKanji_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _MSKanjiState *)ps)->ch == 0);
- }
+@@ -81,7 +80,7 @@ _MSKanji_mbsinit(const mbstate_t *ps)
--size_t
-+static size_t
+ static size_t
_MSKanji_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps)
-+ mbstate_t * __restrict ps, locale_t loc)
++ mbstate_t * __restrict ps, locale_t loc __unused)
{
_MSKanjiState *ms;
wchar_t wc;
-@@ -133,8 +135,8 @@
- }
+@@ -138,7 +137,7 @@ _MSKanji_mbrtowc(wchar_t * __restrict pw
}
--size_t
+ static size_t
-_MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
-+_MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
++_MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_MSKanjiState *ms;
int len, i;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)multibyte.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/multibyte.3,v 1.27 2004/10/17 02:29:15 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/multibyte.3,v 1.28 2007/01/09 00:28:00 imp Exp $
.\"
.Dd April 8, 2004
.Dt MULTIBYTE 3
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/nextwctype.3,v 1.1 2004/07/08 06:43:37 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/nextwctype.3,v 1.3 2005/07/21 10:27:45 tjr Exp $
.\"
-.Dd July 8, 2004
+.Dd July 21, 2005
.Dt NEXTWCTYPE 3
.Os
.Sh NAME
.Sh SYNOPSIS
.In wctype.h
.Ft wint_t
-.Fo nextwctype
-.Fa "wint_t ch" "wctype_t wct"
-.Fc
+.Fn nextwctype "wint_t ch" "wctype_t wct"
.Sh DESCRIPTION
The
.Fn nextwctype
.Sh RETURN VALUES
The
.Fn nextwctype
-functions returns the next character, or \-1 if there are no more.
+function returns the next character, or \-1 if there are no more.
+.Sh COMPATIBILITY
+This function is a non-standard
+.Fx
+extension and should not be used where the standard
+.Fn iswctype
+function would suffice.
.Sh SEE ALSO
.Xr wctype 3
+.Sh HISTORY
+The
+.Fn nextwctype
+function appeared in
+.Fx 5.4 .
---- nextwctype.3.orig Fri Mar 11 19:44:47 2005
-+++ nextwctype.3 Fri Mar 11 19:53:29 2005
+--- nextwctype.3.orig 2009-11-10 13:13:11.000000000 -0800
++++ nextwctype.3 2009-11-10 14:53:56.000000000 -0800
@@ -29,7 +29,8 @@
.Dt NEXTWCTYPE 3
.Os
.Nd "iterate through character classes"
.Sh LIBRARY
.Lb libc
-@@ -39,6 +40,11 @@
- .Fo nextwctype
- .Fa "wint_t ch" "wctype_t wct"
- .Fc
+@@ -37,6 +38,9 @@
+ .In wctype.h
+ .Ft wint_t
+ .Fn nextwctype "wint_t ch" "wctype_t wct"
+.In xlocale.h
+.Ft wint_t
-+.Fo nextwctype_l
-+.Fa "wint_t ch" "wctype_t wct" "locale_t loc"
-+.Fc
++.Fn nextwctype_l "wint_t ch" "wctype_t wct" "locale_t loc"
.Sh DESCRIPTION
The
.Fn nextwctype
-@@ -50,9 +56,18 @@
+@@ -48,6 +52,14 @@ If
.Fa ch
is \-1, the search begins at the first member of
.Fa wct .
+While the
+.Fn nextwctype
+function uses the current locale, the
-+.Fn nextwctype_l
++ .Fn nextwctype_l
+function may be passed a locale directly. See
+.Xr xlocale 3
+for more information.
.Sh RETURN VALUES
The
.Fn nextwctype
- functions returns the next character, or \-1 if there are no more.
+@@ -59,7 +71,8 @@ extension and should not be used where t
+ .Fn iswctype
+ function would suffice.
.Sh SEE ALSO
-.Xr wctype 3
+.Xr wctype 3 ,
+.Xr xlocale 3
+ .Sh HISTORY
+ The
+ .Fn nextwctype
---- nextwctype.c.orig 2004-11-25 11:38:19.000000000 -0800
-+++ nextwctype.c 2005-02-19 03:44:49.000000000 -0800
+--- nextwctype.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ nextwctype.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,28 +27,32 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/nextwctype.c,v 1.1 2004/07/08 06:43:37 tjr Exp $");
if (rr->__ranges != NULL && wc < rr->__ranges[0].__min) {
wc = rr->__ranges[0].__min;
noinc = 1;
-@@ -88,3 +92,9 @@
+@@ -88,3 +92,9 @@ found:
}
return (-1);
}
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/nl_langinfo.3,v 1.5 2003/09/08 19:57:14 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/nl_langinfo.3,v 1.7 2009/11/16 14:33:31 brueffer Exp $
.\"
.Dd May 3, 2001
.Dt NL_LANGINFO 3
or to the
category
.Dv LC_ALL ,
-may overwrite buffer pointed by the return value.
-.Sh EXAMPLES
-For example:
-.Pp
-.Dl nl_langinfo(ABDAY_1)
-.Pp
-would return a pointer to the string
-.Qq Li Dom
-if the identified language was
-Portuguese, and
-.Qq Li Sun
-if the identified language was English.
+may overwrite the buffer pointed to by the return value.
.Sh RETURN VALUES
In a locale where langinfo data is not defined,
.Fn nl_langinfo
returns a pointer to an empty string if
.Fa item
contains an invalid setting.
+.Sh EXAMPLES
+For example:
+.Pp
+.Dl nl_langinfo(ABDAY_1)
+.Pp
+would return a pointer to the string
+.Qq Li Dom
+if the identified language was
+Portuguese, and
+.Qq Li Sun
+if the identified language was English.
.Sh SEE ALSO
.Xr setlocale 3
.Sh STANDARDS
---- _SB/Libc/locale/FreeBSD/nl_langinfo.3 2004-11-25 11:38:19.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/nl_langinfo.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- nl_langinfo.3.orig 2009-11-30 16:10:29.000000000 -0800
++++ nl_langinfo.3 2009-11-30 16:10:30.000000000 -0800
@@ -28,14 +28,24 @@
.Dt NL_LANGINFO 3
.Os
.Sh DESCRIPTION
The
.Fn nl_langinfo
-@@ -53,7 +63,7 @@
- or to the
- category
- .Dv LC_ALL ,
--may overwrite buffer pointed by the return value.
-+may overwrite the buffer pointed to by the return value.
- .Sh EXAMPLES
- For example:
- .Pp
-@@ -65,6 +75,14 @@
+@@ -76,8 +86,17 @@ if the identified language was
Portuguese, and
.Qq Li Sun
if the identified language was English.
+function may be passed a locale directly. See
+.Xr xlocale 3
+for more information.
- .Sh RETURN VALUES
- In a locale where langinfo data is not defined,
- .Fn nl_langinfo
-@@ -77,7 +95,8 @@
- .Fa item
- contains an invalid setting.
.Sh SEE ALSO
-.Xr setlocale 3
+.Xr setlocale 3 ,
---- nl_langinfo.c.orig 2008-01-15 11:30:57.000000000 -0800
-+++ nl_langinfo.c 2008-01-17 23:58:24.000000000 -0800
+--- nl_langinfo.c.orig 2009-11-09 18:47:29.000000000 -0800
++++ nl_langinfo.c 2009-11-09 18:47:34.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/nl_langinfo.c,v 1.17 2003/06/26 10:46:16 phantom Exp $");
#include <langinfo.h>
#include <limits.h>
#include <locale.h>
-@@ -36,62 +38,66 @@
+@@ -36,62 +38,66 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "lnumeric.h"
#include "lmessages.h"
#include "lmonetary.h"
break;
case ERA:
/* XXX: need to be implemented */
-@@ -114,16 +120,16 @@
+@@ -114,16 +120,16 @@ nl_langinfo(nl_item item)
ret = "";
break;
case RADIXCHAR:
break;
/*
* YESSTR and NOSTR items marked with LEGACY are available, but not
-@@ -131,25 +137,25 @@
+@@ -131,25 +137,25 @@ nl_langinfo(nl_item item)
* they're subject to remove in future specification editions.
*/
case YESSTR: /* LEGACY */
psn = '.';
} else
psn = pos ? '-' : '+';
-@@ -166,10 +172,19 @@
+@@ -166,10 +172,19 @@ nl_langinfo(nl_item item)
}
break;
case D_MD_ORDER: /* FreeBSD local extension */
* 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.
static char sccsid[] = "@(#)none.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/none.c,v 1.12 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/none.c,v 1.15 2007/10/13 16:28:22 ache Exp $");
#include <errno.h>
#include <limits.h>
#include <wchar.h>
#include "mblocal.h"
-int _none_init(_RuneLocale *);
-size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _none_mbsinit(const mbstate_t *);
-size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
- const char ** __restrict src, size_t nms, size_t len,
- mbstate_t * __restrict ps __unused);
-size_t _none_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
-size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
+static size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _none_mbsinit(const mbstate_t *);
+static size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps __unused);
+static size_t _none_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+
+/* setup defaults */
+
+int __mb_cur_max = 1;
+int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */
int
_none_init(_RuneLocale *rl)
__wcsnrtombs = _none_wcsnrtombs;
_CurrentRuneLocale = rl;
__mb_cur_max = 1;
+ __mb_sb_limit = 256;
return(0);
}
-int
+static int
_none_mbsinit(const mbstate_t *ps __unused)
{
return (1);
}
-size_t
+static size_t
_none_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps __unused)
{
return (*s == '\0' ? 0 : 1);
}
-size_t
+static size_t
_none_wcrtomb(char * __restrict s, wchar_t wc,
mbstate_t * __restrict ps __unused)
{
return (1);
}
-size_t
+static size_t
_none_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
size_t nms, size_t len, mbstate_t * __restrict ps __unused)
{
return (nchr);
}
-size_t
+static size_t
_none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
{
*src = s;
return (nchr);
}
+
+/* setup defaults */
+
+size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t,
+ mbstate_t * __restrict) = _none_mbrtowc;
+int (*__mbsinit)(const mbstate_t *) = _none_mbsinit;
+size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
+ size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs;
+size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) =
+ _none_wcrtomb;
+size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs;
+
---- none.c.orig Fri Feb 18 15:34:30 2005
-+++ none.c Fri Feb 18 15:37:15 2005
-@@ -41,6 +41,8 @@
+--- none.c.orig 2009-11-09 18:24:17.000000000 -0800
++++ none.c 2009-11-10 11:08:33.000000000 -0800
+@@ -37,6 +37,8 @@ static char sccsid[] = "@(#)none.c 8.1 (
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/none.c,v 1.12 2004/07/21 10:54:57 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/none.c,v 1.15 2007/10/13 16:28:22 ache Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <limits.h>
#include <runetype.h>
-@@ -51,33 +53,32 @@
+@@ -47,39 +49,27 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--int _none_init(_RuneLocale *);
--size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _none_mbsinit(const mbstate_t *);
--size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
-+__private_extern__ int _none_init(struct __xlocale_st_runelocale *);
-+__private_extern__ size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
-+__private_extern__ int _none_mbsinit(const mbstate_t *, locale_t);
-+__private_extern__ size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
- const char ** __restrict src, size_t nms, size_t len,
-- mbstate_t * __restrict ps __unused);
--size_t _none_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
--size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
-- size_t, size_t, mbstate_t * __restrict);
-+ mbstate_t * __restrict ps __unused, locale_t);
-+__private_extern__ size_t _none_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
-+__private_extern__ size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
-+ size_t, size_t, mbstate_t * __restrict, locale_t);
+-static size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _none_mbsinit(const mbstate_t *);
+-static size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
+- const char ** __restrict src, size_t nms, size_t len,
+- mbstate_t * __restrict ps __unused);
+-static size_t _none_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
+-static size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+- size_t, size_t, mbstate_t * __restrict);
+-
+ /* setup defaults */
+
+ int __mb_cur_max = 1;
+ int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */
-int
-_none_init(_RuneLocale *rl)
- __wcsnrtombs = _none_wcsnrtombs;
- _CurrentRuneLocale = rl;
- __mb_cur_max = 1;
+- __mb_sb_limit = 256;
+ xrl->__mbrtowc = _none_mbrtowc;
+ xrl->__mbsinit = _none_mbsinit;
+ xrl->__mbsnrtowcs = _none_mbsnrtowcs;
+ xrl->__wcrtomb = _none_wcrtomb;
+ xrl->__wcsnrtombs = _none_wcsnrtombs;
+ xrl->__mb_cur_max = 1;
++ xrl->__mb_sb_limit = 256;
return(0);
}
--int
+-static int
-_none_mbsinit(const mbstate_t *ps __unused)
+__private_extern__ int
-+_none_mbsinit(const mbstate_t *ps __unused, locale_t loc)
++_none_mbsinit(const mbstate_t *ps __unused, locale_t loc __unused)
{
/*
-@@ -87,9 +88,9 @@
+@@ -89,9 +79,9 @@ _none_mbsinit(const mbstate_t *ps __unus
return (1);
}
--size_t
+-static size_t
+__private_extern__ size_t
_none_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps __unused)
-+ mbstate_t * __restrict ps __unused, locale_t loc)
++ mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
if (s == NULL)
-@@ -103,9 +104,9 @@
+@@ -105,9 +95,9 @@ _none_mbrtowc(wchar_t * __restrict pwc,
return (*s == '\0' ? 0 : 1);
}
--size_t
+-static size_t
+__private_extern__ size_t
_none_wcrtomb(char * __restrict s, wchar_t wc,
- mbstate_t * __restrict ps __unused)
-+ mbstate_t * __restrict ps __unused, locale_t loc)
++ mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
if (s == NULL)
-@@ -119,9 +120,9 @@
+@@ -121,9 +111,9 @@ _none_wcrtomb(char * __restrict s, wchar
return (1);
}
--size_t
+-static size_t
+__private_extern__ size_t
_none_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
- size_t nms, size_t len, mbstate_t * __restrict ps __unused)
-+ size_t nms, size_t len, mbstate_t * __restrict ps __unused, locale_t loc)
++ size_t nms, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
const char *s;
size_t nchr;
-@@ -144,9 +145,9 @@
+@@ -146,9 +136,9 @@ _none_mbsnrtowcs(wchar_t * __restrict ds
return (nchr);
}
--size_t
+-static size_t
+__private_extern__ size_t
_none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
- size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
-+ size_t nwc, size_t len, mbstate_t * __restrict ps __unused, locale_t loc)
++ size_t nwc, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
const wchar_t *s;
size_t nchr;
+@@ -179,16 +169,3 @@ _none_wcsnrtombs(char * __restrict dst,
+ *src = s;
+ return (nchr);
+ }
+-
+-/* setup defaults */
+-
+-size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t,
+- mbstate_t * __restrict) = _none_mbrtowc;
+-int (*__mbsinit)(const mbstate_t *) = _none_mbsinit;
+-size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
+- size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs;
+-size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) =
+- _none_wcrtomb;
+-size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
+- size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs;
+-
---- rune.c.orig 2004-11-25 11:38:19.000000000 -0800
-+++ rune.c 2005-04-12 17:18:12.000000000 -0700
-@@ -34,28 +34,98 @@
+Index: rune.c
+===================================================================
+--- rune.c (revision 59751)
++++ rune.c (working copy)
+@@ -34,28 +34,100 @@
* SUCH DAMAGE.
*/
#include "namespace.h"
#include <arpa/inet.h>
#include <errno.h>
-+#endif /* !RUNEOFF32 */
#include <runetype.h>
++#else
++#include "runetype.h"
++#endif /* !RUNEOFF32 */
#include <stdio.h>
+#ifndef RUNEOFF32
#include <string.h>
void *lastp;
_RuneLocale *rl;
_RuneEntry *rr;
-@@ -65,13 +135,20 @@
+@@ -65,13 +137,20 @@
if (_fstat(fileno(fp), &sb) < 0)
return (NULL);
errno = 0;
rewind(fp); /* Someone might have read the magic number once already */
-@@ -82,26 +159,43 @@
+@@ -82,26 +161,43 @@
return (NULL);
}
rl->__runetype_ext.__nranges = ntohl(rl->__runetype_ext.__nranges);
rl->__maplower_ext.__nranges = ntohl(rl->__maplower_ext.__nranges);
rl->__mapupper_ext.__nranges = ntohl(rl->__mapupper_ext.__nranges);
-@@ -111,7 +205,54 @@
+@@ -111,7 +207,54 @@
rl->__maplower[x] = ntohl(rl->__maplower[x]);
rl->__mapupper[x] = ntohl(rl->__mapupper[x]);
}
rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable;
rl->__variable = rl->__runetype_ext.__ranges +
rl->__runetype_ext.__nranges;
-@@ -142,8 +283,10 @@
+@@ -142,8 +285,10 @@
for (x = 0; x < rl->__runetype_ext.__nranges; ++x) {
rr = rl->__runetype_ext.__ranges;
if ((rr[x].__map = ntohl(rr[x].__map)) == 0) {
int len = rr[x].__max - rr[x].__min + 1;
rr[x].__types = rl->__variable;
-@@ -153,12 +296,15 @@
+@@ -153,12 +298,15 @@
errno = EFTYPE;
return (NULL);
}
for (x = 0; x < rl->__maplower_ext.__nranges; ++x) {
rr = rl->__maplower_ext.__ranges;
-@@ -174,6 +320,22 @@
+@@ -174,6 +322,22 @@
rr[x].__max = ntohl(rr[x].__max);
rr[x].__map = ntohl(rr[x].__map);
}
if (((char *)rl->__variable) + rl->__variable_len > (char *)lastp) {
free(data);
errno = EFTYPE;
-@@ -195,5 +357,7 @@
+@@ -195,5 +359,7 @@
if (!rl->__mapupper_ext.__nranges)
rl->__mapupper_ext.__ranges = 0;
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/runetype.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/runetype.c,v 1.14 2007/01/09 00:28:00 imp Exp $");
+#include <ctype.h>
#include <stdio.h>
#include <runetype.h>
unsigned long
-___runetype(c)
- __ct_rune_t c;
+___runetype(__ct_rune_t c)
{
size_t lim;
_RuneRange *rr = &_CurrentRuneLocale->__runetype_ext;
---- runetype.c.orig 2004-11-25 11:38:19.000000000 -0800
-+++ runetype.c 2005-02-16 22:43:53.000000000 -0800
-@@ -37,20 +37,25 @@
+--- runetype.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ runetype.c 2009-11-09 16:54:21.000000000 -0800
+@@ -33,20 +33,24 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/runetype.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/runetype.c,v 1.14 2007/01/09 00:28:00 imp Exp $");
+#include "xlocale_private.h"
+
+ #include <ctype.h>
#include <stdio.h>
#include <runetype.h>
unsigned long
--___runetype(c)
-+___runetype_l(c, loc)
- __ct_rune_t c;
-+ locale_t loc;
+-___runetype(__ct_rune_t c)
++___runetype_l(__ct_rune_t c, locale_t loc)
{
size_t lim;
- _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext;
/* Binary search -- see bsearch.c for explanation. */
base = rr->__ranges;
for (lim = rr->__nranges; lim != 0; lim >>= 1) {
-@@ -68,3 +73,10 @@
+@@ -64,3 +68,9 @@ ___runetype(__ct_rune_t c)
return(0L);
}
+
+unsigned long
-+___runetype(c)
-+ __ct_rune_t c;
++___runetype(__ct_rune_t c)
+{
+ return ___runetype_l(c, __current_locale());
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)setlocale.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/locale/setlocale.3,v 1.33 2004/10/17 06:51:50 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/setlocale.3,v 1.35 2007/01/09 00:28:00 imp Exp $
.\"
.Dd November 21, 2003
.Dt SETLOCALE 3
and
.Fa locale
makes no sense.
-.Sh ERRORS
-No errors are defined.
.Sh FILES
.Bl -tag -width /usr/share/locale/locale/category -compact
.It Pa $PATH_LOCALE/ Ns Em locale/category
and the category
.Em category .
.El
+.Sh ERRORS
+No errors are defined.
.Sh SEE ALSO
.Xr colldef 1 ,
.Xr mklocale 1 ,
---- _SB/Libc/locale/FreeBSD/setlocale.3 2004-11-25 11:38:19.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/setlocale.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -46,7 +46,10 @@
+--- setlocale.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ setlocale.3 2009-11-09 15:05:26.000000000 -0800
+@@ -42,7 +42,10 @@
.Sh SYNOPSIS
.In locale.h
.Ft char *
.Sh DESCRIPTION
The
.Fn setlocale
-@@ -105,14 +108,14 @@
+@@ -101,14 +104,14 @@ Set a locale for formatting dates and ti
function.
.El
.Pp
* 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.
static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/setlocale.c,v 1.50 2004/01/31 19:15:32 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/setlocale.c,v 1.51 2007/01/09 00:28:00 imp Exp $");
#include <sys/types.h>
#include <sys/stat.h>
---- setlocale.c.orig 2008-01-24 17:13:46.000000000 -0800
-+++ setlocale.c 2008-02-17 13:23:02.000000000 -0800
-@@ -41,6 +41,8 @@ static char sccsid[] = "@(#)setlocale.c
+--- setlocale.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ setlocale.c 2009-11-09 15:05:26.000000000 -0800
+@@ -37,6 +37,8 @@ static char sccsid[] = "@(#)setlocale.c
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/setlocale.c,v 1.50 2004/01/31 19:15:32 ache Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/setlocale.c,v 1.51 2007/01/09 00:28:00 imp Exp $");
+#include "xlocale_private.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
-@@ -56,7 +58,7 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
+@@ -52,7 +54,7 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "lmessages.h" /* for __messages_load_locale() */
#include "setlocale.h"
#include "ldpart.h"
/*
* Category names for getenv()
-@@ -99,15 +101,18 @@ static char current_locale_string[_LC_LA
+@@ -95,15 +97,18 @@ static char current_locale_string[_LC_LA
static char *currentlocale(void);
static char *loadlocale(int);
if (category < LC_ALL || category >= _LC_LAST) {
errno = EINVAL;
-@@ -118,6 +123,7 @@ setlocale(category, locale)
+@@ -114,6 +119,7 @@ setlocale(category, locale)
return (category != LC_ALL ?
current_categories[category] : currentlocale());
/*
* Default to the current locale for everything.
*/
-@@ -133,7 +139,7 @@ setlocale(category, locale)
+@@ -129,7 +135,7 @@ setlocale(category, locale)
env = __get_locale_env(i);
if (strlen(env) > ENCODING_LEN) {
errno = EINVAL;
}
(void)strcpy(new_categories[i], env);
}
-@@ -141,21 +147,21 @@ setlocale(category, locale)
+@@ -137,21 +143,21 @@ setlocale(category, locale)
env = __get_locale_env(category);
if (strlen(env) > ENCODING_LEN) {
errno = EINVAL;
}
for (i = 1; i < _LC_LAST; ++i)
(void)strcpy(new_categories[i], locale);
-@@ -164,14 +170,14 @@ setlocale(category, locale)
+@@ -160,14 +166,14 @@ setlocale(category, locale)
;
if (!r[1]) {
errno = EINVAL;
}
(void)strlcpy(new_categories[i], locale,
len + 1);
-@@ -191,8 +197,11 @@ setlocale(category, locale)
+@@ -187,8 +193,11 @@ setlocale(category, locale)
}
if (category != LC_ALL)
for (i = 1; i < _LC_LAST; ++i) {
(void)strcpy(saved_categories[i], current_categories[i]);
if (loadlocale(i) == NULL) {
-@@ -205,11 +214,15 @@ setlocale(category, locale)
+@@ -201,11 +210,15 @@ setlocale(category, locale)
(void)loadlocale(j);
}
}
}
static char *
-@@ -237,7 +250,7 @@ loadlocale(category)
+@@ -233,7 +246,7 @@ loadlocale(category)
{
char *new = new_categories[category];
char *old = current_categories[category];
int saved_errno;
if ((new[0] == '.' &&
-@@ -280,15 +293,26 @@ loadlocale(category)
+@@ -276,15 +289,26 @@ loadlocale(category)
if (strcmp(new, old) == 0)
return (old);
__get_locale_env(category)
int category;
{
-@@ -315,7 +339,7 @@ __get_locale_env(category)
+@@ -311,7 +335,7 @@ __get_locale_env(category)
/*
* Detect locale storage location and store its value to _PathLocale variable
*/
---- setlocale.h.orig 2004-11-25 11:38:19.000000000 -0800
-+++ setlocale.h 2005-02-19 14:45:55.000000000 -0800
+--- setlocale.h.orig 2009-11-09 15:05:25.000000000 -0800
++++ setlocale.h 2009-11-09 15:05:26.000000000 -0800
@@ -29,12 +29,14 @@
#ifndef _SETLOCALE_H_
#define _SETLOCALE_H_
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/setrunelocale.c,v 1.44 2004/10/18 02:06:18 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/setrunelocale.c,v 1.51 2008/01/23 03:05:35 ache Exp $");
#include <runetype.h>
#include <errno.h>
#include "mblocal.h"
#include "setlocale.h"
-extern int _none_init(_RuneLocale *);
-extern int _UTF8_init(_RuneLocale *);
-extern int _EUC_init(_RuneLocale *);
-extern int _GB18030_init(_RuneLocale *);
-extern int _GB2312_init(_RuneLocale *);
-extern int _GBK_init(_RuneLocale *);
-extern int _BIG5_init(_RuneLocale *);
-extern int _MSKanji_init(_RuneLocale *);
+extern int __mb_sb_limit;
+
extern _RuneLocale *_Read_RuneMagi(FILE *);
static int __setrunelocale(const char *);
char name[PATH_MAX];
_RuneLocale *rl;
int saverr, ret;
+ size_t (*old__mbrtowc)(wchar_t * __restrict,
+ const char * __restrict, size_t, mbstate_t * __restrict);
+ size_t (*old__wcrtomb)(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+ int (*old__mbsinit)(const mbstate_t *);
+ size_t (*old__mbsnrtowcs)(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t, mbstate_t * __restrict);
+ size_t (*old__wcsnrtombs)(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
static char ctype_encoding[ENCODING_LEN + 1];
static _RuneLocale *CachedRuneLocale;
static int Cached__mb_cur_max;
+ static int Cached__mb_sb_limit;
static size_t (*Cached__mbrtowc)(wchar_t * __restrict,
const char * __restrict, size_t, mbstate_t * __restrict);
static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t,
* The "C" and "POSIX" locale are always here.
*/
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
- _CurrentRuneLocale = &_DefaultRuneLocale;
- __mb_cur_max = 1;
- __mbrtowc = _none_mbrtowc;
- __mbsinit = _none_mbsinit;
- __mbsnrtowcs = _none_mbsnrtowcs;
- __wcrtomb = _none_wcrtomb;
- __wcsnrtombs = _none_wcsnrtombs;
+ (void) _none_init(&_DefaultRuneLocale);
return (0);
}
strcmp(encoding, ctype_encoding) == 0) {
_CurrentRuneLocale = CachedRuneLocale;
__mb_cur_max = Cached__mb_cur_max;
+ __mb_sb_limit = Cached__mb_sb_limit;
__mbrtowc = Cached__mbrtowc;
__mbsinit = Cached__mbsinit;
__mbsnrtowcs = Cached__mbsnrtowcs;
}
(void)fclose(fp);
+ old__mbrtowc = __mbrtowc;
+ old__mbsinit = __mbsinit;
+ old__mbsnrtowcs = __mbsnrtowcs;
+ old__wcrtomb = __wcrtomb;
+ old__wcsnrtombs = __wcsnrtombs;
+
__mbrtowc = NULL;
__mbsinit = NULL;
__mbsnrtowcs = __mbsnrtowcs_std;
__wcrtomb = NULL;
__wcsnrtombs = __wcsnrtombs_std;
+
rl->__sputrune = NULL;
rl->__sgetrune = NULL;
if (strcmp(rl->__encoding, "NONE") == 0)
ret = _none_init(rl);
+ else if (strcmp(rl->__encoding, "ASCII") == 0)
+ ret = _ascii_init(rl);
else if (strcmp(rl->__encoding, "UTF-8") == 0)
ret = _UTF8_init(rl);
else if (strcmp(rl->__encoding, "EUC") == 0)
ret = _EUC_init(rl);
- else if (strcmp(rl->__encoding, "GB18030") == 0)
+ else if (strcmp(rl->__encoding, "GB18030") == 0)
ret = _GB18030_init(rl);
else if (strcmp(rl->__encoding, "GB2312") == 0)
ret = _GB2312_init(rl);
ret = _MSKanji_init(rl);
else
ret = EFTYPE;
+
if (ret == 0) {
if (CachedRuneLocale != NULL) {
/* See euc.c */
}
CachedRuneLocale = _CurrentRuneLocale;
Cached__mb_cur_max = __mb_cur_max;
+ Cached__mb_sb_limit = __mb_sb_limit;
Cached__mbrtowc = __mbrtowc;
Cached__mbsinit = __mbsinit;
Cached__mbsnrtowcs = __mbsnrtowcs;
Cached__wcrtomb = __wcrtomb;
Cached__wcsnrtombs = __wcsnrtombs;
(void)strcpy(ctype_encoding, encoding);
- } else
+ } else {
+ __mbrtowc = old__mbrtowc;
+ __mbsinit = old__mbsinit;
+ __mbsnrtowcs = old__mbsnrtowcs;
+ __wcrtomb = old__wcrtomb;
+ __wcsnrtombs = old__wcsnrtombs;
free(rl);
+ }
return (ret);
}
---- setrunelocale.c.orig 2008-05-12 17:37:36.000000000 -0700
-+++ setrunelocale.c 2008-05-13 00:32:37.000000000 -0700
-@@ -37,6 +37,8 @@
+--- setrunelocale.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ setrunelocale.c 2009-11-09 17:20:45.000000000 -0800
+@@ -33,6 +33,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/setrunelocale.c,v 1.44 2004/10/18 02:06:18 ache Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/setrunelocale.c,v 1.51 2008/01/23 03:05:35 ache Exp $");
+#include "xlocale_private.h"
+
#include <runetype.h>
#include <errno.h>
#include <limits.h>
-@@ -49,67 +51,66 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
+@@ -45,67 +47,60 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "mblocal.h"
#include "setlocale.h"
--extern int _none_init(_RuneLocale *);
--extern int _UTF8_init(_RuneLocale *);
--extern int _EUC_init(_RuneLocale *);
--extern int _GB18030_init(_RuneLocale *);
--extern int _GB2312_init(_RuneLocale *);
--extern int _GBK_init(_RuneLocale *);
--extern int _BIG5_init(_RuneLocale *);
--extern int _MSKanji_init(_RuneLocale *);
--extern _RuneLocale *_Read_RuneMagi(FILE *);
+-extern int __mb_sb_limit;
-
--static int __setrunelocale(const char *);
-+extern int _none_init(struct __xlocale_st_runelocale *);
-+extern int _UTF8_init(struct __xlocale_st_runelocale *);
-+extern int _EUC_init(struct __xlocale_st_runelocale *);
-+extern int _GB18030_init(struct __xlocale_st_runelocale *);
-+extern int _GB2312_init(struct __xlocale_st_runelocale *);
-+extern int _GBK_init(struct __xlocale_st_runelocale *);
-+extern int _BIG5_init(struct __xlocale_st_runelocale *);
-+extern int _MSKanji_init(struct __xlocale_st_runelocale *);
-+extern int _UTF2_init(struct __xlocale_st_runelocale *); /* deprecated */
+-extern _RuneLocale *_Read_RuneMagi(FILE *);
+extern struct __xlocale_st_runelocale *_Read_RuneMagi(FILE *);
-+
-+#ifdef LEGACY_RUNE_APIS
+
+-static int __setrunelocale(const char *);
++#ifdef UNIFDEF_LEGACY_RUNE_APIS
+/* depreciated interfaces */
+rune_t sgetrune(const char *, size_t, char const **);
+int sputrune(rune_t, char *, size_t, char **);
-+#endif /* LEGACY_RUNE_APIS */
++#endif /* UNIFDEF_LEGACY_RUNE_APIS */
-static int
-__setrunelocale(const char *encoding)
+ struct __xlocale_st_runelocale *xrl;
_RuneLocale *rl;
int saverr, ret;
+- size_t (*old__mbrtowc)(wchar_t * __restrict,
+- const char * __restrict, size_t, mbstate_t * __restrict);
+- size_t (*old__wcrtomb)(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
+- int (*old__mbsinit)(const mbstate_t *);
+- size_t (*old__mbsnrtowcs)(wchar_t * __restrict,
+- const char ** __restrict, size_t, size_t, mbstate_t * __restrict);
+- size_t (*old__wcsnrtombs)(char * __restrict,
+- const wchar_t ** __restrict, size_t, size_t,
+- mbstate_t * __restrict);
- static char ctype_encoding[ENCODING_LEN + 1];
- static _RuneLocale *CachedRuneLocale;
- static int Cached__mb_cur_max;
+- static int Cached__mb_sb_limit;
- static size_t (*Cached__mbrtowc)(wchar_t * __restrict,
- const char * __restrict, size_t, mbstate_t * __restrict);
- static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t,
- mbstate_t * __restrict);
+ static struct __xlocale_st_runelocale *CachedRuneLocale;
+ extern int __mb_cur_max;
++ extern int __mb_sb_limit;
+ static pthread_lock_t cache_lock = LOCK_INITIALIZER;
/*
* The "C" and "POSIX" locale are always here.
*/
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
-- _CurrentRuneLocale = &_DefaultRuneLocale;
-- __mb_cur_max = 1;
-- __mbrtowc = _none_mbrtowc;
-- __mbsinit = _none_mbsinit;
-- __mbsnrtowcs = _none_mbsnrtowcs;
-- __wcrtomb = _none_wcrtomb;
-- __wcsnrtombs = _none_wcsnrtombs;
+- (void) _none_init(&_DefaultRuneLocale);
+ XL_RELEASE(loc->__lc_ctype);
+ loc->__lc_ctype = &_DefaultRuneXLocale;
+ /* no need to retain _DefaultRuneXLocale */
+ if (loc == &__global_locale) {
+ _CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale;
+ __mb_cur_max = loc->__lc_ctype->__mb_cur_max;
++ __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
+ }
return (0);
}
- strcmp(encoding, ctype_encoding) == 0) {
- _CurrentRuneLocale = CachedRuneLocale;
- __mb_cur_max = Cached__mb_cur_max;
+- __mb_sb_limit = Cached__mb_sb_limit;
- __mbrtowc = Cached__mbrtowc;
- __mbsinit = Cached__mbsinit;
- __mbsnrtowcs = Cached__mbsnrtowcs;
+ if (loc == &__global_locale) {
+ _CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale;
+ __mb_cur_max = loc->__lc_ctype->__mb_cur_max;
++ __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
+ }
+ UNLOCK(cache_lock);
return (0);
/*
* Slurp the locale file into the cache.
-@@ -124,63 +125,86 @@ __setrunelocale(const char *encoding)
+@@ -120,80 +115,90 @@ __setrunelocale(const char *encoding)
if ((fp = fopen(name, "r")) == NULL)
return (errno == 0 ? ENOENT : errno);
}
(void)fclose(fp);
+- old__mbrtowc = __mbrtowc;
+- old__mbsinit = __mbsinit;
+- old__mbsnrtowcs = __mbsnrtowcs;
+- old__wcrtomb = __wcrtomb;
+- old__wcsnrtombs = __wcsnrtombs;
+-
- __mbrtowc = NULL;
- __mbsinit = NULL;
- __mbsnrtowcs = __mbsnrtowcs_std;
- __wcrtomb = NULL;
- __wcsnrtombs = __wcsnrtombs_std;
+-
+ xrl->__mbrtowc = NULL;
+ xrl->__mbsinit = NULL;
+ xrl->__mbsnrtowcs = __mbsnrtowcs_std;
+
+ rl = &xrl->_CurrentRuneLocale;
+
-+#ifdef LEGACY_RUNE_APIS
++#ifdef UNIFDEF_LEGACY_RUNE_APIS
+ /* provide backwards compatibility (depreciated interface) */
+ rl->__sputrune = sputrune;
+ rl->__sgetrune = sgetrune;
-+#else /* LEGACY_RUNE_APIS */
++#else /* UNIFDEF_LEGACY_RUNE_APIS */
rl->__sputrune = NULL;
rl->__sgetrune = NULL;
-+#endif /* LEGACY_RUNE_APIS */
++#endif /* UNIFDEF_LEGACY_RUNE_APIS */
+
if (strcmp(rl->__encoding, "NONE") == 0)
- ret = _none_init(rl);
+ ret = _none_init(xrl);
+ else if (strcmp(rl->__encoding, "ASCII") == 0)
+- ret = _ascii_init(rl);
++ ret = _ascii_init(xrl);
else if (strcmp(rl->__encoding, "UTF-8") == 0)
- ret = _UTF8_init(rl);
+ ret = _UTF8_init(xrl);
else if (strcmp(rl->__encoding, "EUC") == 0)
- ret = _EUC_init(rl);
+ ret = _EUC_init(xrl);
- else if (strcmp(rl->__encoding, "GB18030") == 0)
+ else if (strcmp(rl->__encoding, "GB18030") == 0)
- ret = _GB18030_init(rl);
+ ret = _GB18030_init(xrl);
else if (strcmp(rl->__encoding, "GB2312") == 0)
+ ret = _UTF2_init(xrl);
else
ret = EFTYPE;
+
if (ret == 0) {
- if (CachedRuneLocale != NULL) {
- /* See euc.c */
+ if (loc == &__global_locale) {
+ _CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale;
+ __mb_cur_max = loc->__lc_ctype->__mb_cur_max;
++ __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
}
- CachedRuneLocale = _CurrentRuneLocale;
- Cached__mb_cur_max = __mb_cur_max;
+- Cached__mb_sb_limit = __mb_sb_limit;
- Cached__mbrtowc = __mbrtowc;
- Cached__mbsinit = __mbsinit;
- Cached__mbsnrtowcs = __mbsnrtowcs;
- Cached__wcrtomb = __wcrtomb;
- Cached__wcsnrtombs = __wcsnrtombs;
- (void)strcpy(ctype_encoding, encoding);
+- } else {
+- __mbrtowc = old__mbrtowc;
+- __mbsinit = old__mbsinit;
+- __mbsnrtowcs = old__mbsnrtowcs;
+- __wcrtomb = old__wcrtomb;
+- __wcsnrtombs = old__wcsnrtombs;
+- free(rl);
+- }
+ LOCK(cache_lock);
+ XL_RELEASE(CachedRuneLocale);
+ CachedRuneLocale = xrl;
+ XL_RETAIN(CachedRuneLocale);
+ UNLOCK(cache_lock);
- } else
-- free(rl);
++ } else
+ XL_RELEASE(xrl);
return (ret);
}
-+#ifdef LEGACY_RUNE_APIS
++#ifdef UNIFDEF_LEGACY_RUNE_APIS
int
-__wrap_setrunelocale(const char *locale)
+setrunelocale(const char *encoding)
+ XL_UNLOCK(&__global_locale);
+ return ret;
+}
-+#endif /* LEGACY_RUNE_APIS */
++#endif /* UNIFDEF_LEGACY_RUNE_APIS */
+
+__private_extern__ int
+__wrap_setrunelocale(const char *locale, locale_t loc)
* 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.
static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/27/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/table.c,v 1.26 2004/10/17 06:51:50 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/table.c,v 1.28 2007/01/09 00:28:00 imp Exp $");
#include <ctype.h>
#include <runetype.h>
_RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;
-int __mb_cur_max = 1;
-size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict) = _none_mbrtowc;
-int (*__mbsinit)(const mbstate_t *) = _none_mbsinit;
-size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs;
-size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) =
- _none_wcrtomb;
-size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs;
---- table.c.orig 2004-11-25 11:38:19.000000000 -0800
-+++ table.c 2005-03-30 16:33:51.000000000 -0800
-@@ -40,13 +40,16 @@
+--- table.c.orig 2010-06-21 14:25:20.000000000 -0700
++++ table.c 2010-06-21 14:25:34.000000000 -0700
+@@ -36,13 +36,16 @@ static char sccsid[] = "@(#)table.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/table.c,v 1.26 2004/10/17 06:51:50 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/table.c,v 1.28 2007/01/09 00:28:00 imp Exp $");
+#include "xlocale_private.h"
+
#include <wchar.h>
#include "mblocal.h"
-+/* _DefaultRuneLocale is depreciated; _DefaultRuneXLocale is used instead */
- _RuneLocale _DefaultRuneLocale = {
+-_RuneLocale _DefaultRuneLocale = {
- _RUNE_MAGIC_1,
++/* _DefaultRuneLocale is depreciated; _DefaultRuneXLocale is used instead */
++_RuneLocale _DefaultRuneLocale __attribute__((section("__DATA,__constrw"))) = {
+ _RUNE_MAGIC_A,
"NONE",
NULL,
NULL,
-@@ -249,15 +252,222 @@
+@@ -245,5 +248,221 @@ _RuneLocale _DefaultRuneLocale = {
},
};
-_RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;
-+__private_extern__ struct __xlocale_st_runelocale _DefaultRuneXLocale = {
++__private_extern__ struct __xlocale_st_runelocale _DefaultRuneXLocale __attribute__((section("__DATA,__constrw"))) = {
+ 0,
+ XPERMANENT,
+ "C",
+ 1,
++ 256,
+ _none_mbrtowc,
+ _none_mbsinit,
+ _none_mbsnrtowcs,
+ },
+ },
+};
-+
-+_RuneLocale *_CurrentRuneLocale = &_DefaultRuneXLocale._CurrentRuneLocale;
- int __mb_cur_max = 1;
--size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict) = _none_mbrtowc;
--int (*__mbsinit)(const mbstate_t *) = _none_mbsinit;
--size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
-- size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs;
--size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) =
-- _none_wcrtomb;
--size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
-- size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs;
++_RuneLocale *_CurrentRuneLocale = &_DefaultRuneXLocale._CurrentRuneLocale;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)toascii.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/toascii.3,v 1.7 2002/01/09 13:43:31 nik Exp $
+.\" $FreeBSD: src/lib/libc/locale/toascii.3,v 1.10 2009/09/04 07:44:58 des Exp $
.\"
.Dd June 4, 1993
.Dt TOASCII 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)tolower.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/tolower.3,v 1.16 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/tolower.3,v 1.21 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt TOLOWER 3
.Os
.Sh NAME
.Fn tolower
function converts an upper-case letter to the corresponding lower-case
letter.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr islower 3 ,
-.Xr multibyte 3 ,
.Xr towlower 3
.Sh STANDARDS
The
---- _SB/Libc/locale/FreeBSD/tolower.3 2004-11-25 11:38:19.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/tolower.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -40,14 +40,24 @@
+--- tolower.3.bsdnew 2009-11-10 13:13:11.000000000 -0800
++++ tolower.3 2009-11-10 13:51:11.000000000 -0800
+@@ -36,14 +36,24 @@
.Dt TOLOWER 3
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn tolower
-@@ -56,17 +66,25 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
+@@ -53,11 +63,19 @@ The argument must be representable as an
+ .Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
.Sh COMPATIBILITY
The
.Bx 4.4
-@@ -81,7 +99,8 @@
+@@ -71,7 +89,8 @@ function should be used instead.
+ .Sh SEE ALSO
.Xr ctype 3 ,
.Xr islower 3 ,
- .Xr multibyte 3 ,
-.Xr towlower 3
+.Xr towlower 3 ,
+.Xr xlocale 3
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/tolower.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/tolower.c,v 1.13 2007/01/09 00:28:01 imp Exp $");
+#include <ctype.h>
#include <stdio.h>
#include <runetype.h>
---- tolower.c.orig 2004-11-25 11:38:19.000000000 -0800
-+++ tolower.c 2005-02-17 16:43:19.000000000 -0800
-@@ -37,20 +37,32 @@
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/tolower.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
+--- tolower.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ tolower.c 2009-11-09 17:31:29.000000000 -0800
+@@ -32,22 +32,34 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/locale/tolower.c,v 1.13 2007/01/09 00:28:01 imp Exp $");
++
+#include "xlocale_private.h"
-+
+
+ #include <ctype.h>
#include <stdio.h>
#include <runetype.h>
/* Binary search -- see bsearch.c for explanation. */
base = rr->__ranges;
for (lim = rr->__nranges; lim != 0; lim >>= 1) {
-@@ -65,3 +77,10 @@
+@@ -62,3 +74,10 @@ ___tolower(c)
return(c);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)toupper.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/toupper.3,v 1.16 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/toupper.3,v 1.21 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt TOUPPER 3
.Os
.Sh NAME
.Fn toupper
function converts a lower-case letter to the corresponding
upper-case letter.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr isupper 3 ,
-.Xr multibyte 3 ,
.Xr towupper 3
.Sh STANDARDS
The
---- _SB/Libc/locale/FreeBSD/toupper.3 2004-11-25 11:38:20.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/toupper.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -40,14 +40,24 @@
+--- toupper.3.bsdnew 2009-11-10 13:13:11.000000000 -0800
++++ toupper.3 2009-11-10 13:52:49.000000000 -0800
+@@ -36,14 +36,24 @@
.Dt TOUPPER 3
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn toupper
-@@ -56,17 +66,25 @@
- For single C
- .Va char Ns s
- locales (see
--.Xr multibyte 3 )
-+.Xr multibyte 3 ) ,
- the value of the argument is
- representable as an
- .Li unsigned char
+@@ -53,11 +63,19 @@ The argument must be representable as an
+ .Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
.Sh COMPATIBILITY
The
.Bx 4.4
-@@ -81,7 +99,8 @@
+@@ -71,7 +89,8 @@ function should be used instead.
+ .Sh SEE ALSO
.Xr ctype 3 ,
.Xr isupper 3 ,
- .Xr multibyte 3 ,
-.Xr towupper 3
+.Xr towupper 3 ,
+.Xr xlocale 3
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/toupper.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/toupper.c,v 1.13 2007/01/09 00:28:01 imp Exp $");
+#include <ctype.h>
#include <stdio.h>
#include <runetype.h>
---- toupper.c.orig 2005-02-17 16:40:25.000000000 -0800
-+++ toupper.c 2005-02-17 16:42:30.000000000 -0800
-@@ -37,20 +37,32 @@
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/toupper.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
+--- toupper.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ toupper.c 2009-11-09 17:30:20.000000000 -0800
+@@ -32,22 +32,34 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/locale/toupper.c,v 1.13 2007/01/09 00:28:01 imp Exp $");
++
+#include "xlocale_private.h"
-+
+
+ #include <ctype.h>
#include <stdio.h>
#include <runetype.h>
/* Binary search -- see bsearch.c for explanation. */
base = rr->__ranges;
for (lim = rr->__nranges; lim != 0; lim >>= 1) {
-@@ -65,3 +77,10 @@
+@@ -62,3 +74,10 @@ ___toupper(c)
return(c);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)tolower.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/towlower.3,v 1.5 2002/11/29 17:35:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/towlower.3,v 1.6 2007/01/09 00:28:01 imp Exp $
.\"
.Dd October 3, 2002
.Dt TOWLOWER 3
---- _SB/Libc/locale/FreeBSD/towlower.3 2003-05-20 15:21:44.000000000 -0700
-+++ _SB/Libc/locale/FreeBSD/towlower.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -40,29 +40,48 @@
+--- towlower.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ towlower.3 2009-11-09 15:05:26.000000000 -0800
+@@ -36,29 +36,48 @@
.Dt TOWLOWER 3
.Os
.Sh NAME
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)toupper.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/towupper.3,v 1.2 2002/11/29 17:35:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/towupper.3,v 1.3 2007/01/09 00:28:01 imp Exp $
.\"
.Dd October 3, 2002
.Dt TOWUPPER 3
---- _SB/Libc/locale/FreeBSD/towupper.3 2003-05-20 15:21:44.000000000 -0700
-+++ _SB/Libc/locale/FreeBSD/towupper.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -40,29 +40,48 @@
+--- towupper.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ towupper.3 2009-11-09 15:05:26.000000000 -0800
+@@ -36,29 +36,48 @@
.Dt TOWUPPER 3
.Os
.Sh NAME
---- utf2.c.orig Fri Feb 18 15:49:55 2005
-+++ utf2.c Fri Feb 18 15:52:07 2005
-@@ -25,8 +25,11 @@
- */
-
+--- utf2.c.bsdnew 2009-11-09 17:38:09.000000000 -0800
++++ utf2.c 2009-11-09 17:41:17.000000000 -0800
+@@ -27,6 +27,8 @@
#include <sys/param.h>
-+/* dumb down UTF-8 to do UTF2 */
- __FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.11 2004/07/27 06:29:48 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.16 2007/10/15 09:51:30 ache Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <limits.h>
#include <runetype.h>
-@@ -35,54 +38,55 @@
+@@ -35,62 +37,61 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _UTF8_mbsinit(const mbstate_t *);
--size_t _UTF8_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
-- size_t, size_t, mbstate_t * __restrict);
--size_t _UTF8_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
--size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
-- size_t, size_t, mbstate_t * __restrict);
+-extern int __mb_sb_limit;
+#define UTF2_MB_CUR_MAX 3
-+
-+static size_t _UTF2_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
+
+-static size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _UTF8_mbsinit(const mbstate_t *);
+-static size_t _UTF8_mbsnrtowcs(wchar_t * __restrict,
++static size_t _UTF2_mbrtowc(wchar_t * __restrict, const char * __restrict,
++ size_t, mbstate_t * __restrict, locale_t);
+static int _UTF2_mbsinit(const mbstate_t *, locale_t);
-+static size_t _UTF2_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
-+ size_t, size_t, mbstate_t * __restrict, locale_t);
-+static size_t _UTF2_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
++static size_t _UTF2_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+- mbstate_t * __restrict);
+-static size_t _UTF8_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
+-static size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+- size_t, size_t, mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
++static size_t _UTF2_wcrtomb(char * __restrict, wchar_t,
++ mbstate_t * __restrict, locale_t);
+static size_t _UTF2_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
-+ size_t, size_t, mbstate_t * __restrict, locale_t);
++ size_t, size_t, mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
+ xrl->__mbsnrtowcs = _UTF2_mbsnrtowcs;
+ xrl->__wcsnrtombs = _UTF2_wcsnrtombs;
+ xrl->__mb_cur_max = UTF2_MB_CUR_MAX;
+ /*
+ * UCS-4 encoding used as the internal representation, so
+ * slots 0x0080-0x00FF are occuped and must be excluded
+ * from the single byte ctype by setting the limit.
+ */
+- __mb_sb_limit = 128;
++ xrl->__mb_sb_limit = 128;
return (0);
}
--int
+ static int
-_UTF8_mbsinit(const mbstate_t *ps)
-+static int
+_UTF2_mbsinit(const mbstate_t *ps, locale_t loc)
{
+ return (ps == NULL || ((const _UTF2State *)ps)->want == 0);
}
--size_t
+ static size_t
-_UTF8_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps)
-+static size_t
+_UTF2_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps, locale_t loc)
{
- us = (_UTF8State *)ps;
+ us = (_UTF2State *)ps;
-- if (us->want < 0 || us->want > 6) {
-+ if (us->want < 0 || us->want > 3) {
+ if (us->want < 0 || us->want > 6) {
errno = EINVAL;
- return ((size_t)-1);
- }
-@@ -130,21 +134,9 @@
+@@ -140,21 +141,9 @@ _UTF8_mbrtowc(wchar_t * __restrict pwc,
mask = 0x0f;
want = 3;
lbound = 0x800;
- mask = 0x03;
- want = 5;
- lbound = 0x200000;
-- } else if ((ch & 0xfc) == 0xfc) {
+- } else if ((ch & 0xfe) == 0xfc) {
- mask = 0x01;
- want = 6;
- lbound = 0x4000000;
*/
errno = EILSEQ;
return ((size_t)-1);
-@@ -194,17 +186,17 @@
- return (wch == L'\0' ? 0 : want);
+@@ -205,16 +194,16 @@ _UTF8_mbrtowc(wchar_t * __restrict pwc,
}
--size_t
+ static size_t
-_UTF8_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
- size_t nms, size_t len, mbstate_t * __restrict ps)
-+static size_t
+_UTF2_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps, locale_t loc)
{
s = *src;
nchr = 0;
-@@ -226,7 +218,7 @@
+@@ -236,7 +225,7 @@ _UTF8_mbsnrtowcs(wchar_t * __restrict ds
* excluding NUL.
*/
nb = 1;
(size_t)-1)
/* Invalid sequence - mbrtowc() sets errno. */
return ((size_t)-1);
-@@ -256,7 +248,7 @@
+@@ -266,7 +255,7 @@ _UTF8_mbsnrtowcs(wchar_t * __restrict ds
*/
*dst = (wchar_t)*s;
nb = 1;
(size_t)-1) {
*src = s;
return ((size_t)-1);
-@@ -276,14 +268,14 @@
- return (nchr);
+@@ -287,13 +276,13 @@ _UTF8_mbsnrtowcs(wchar_t * __restrict ds
}
--size_t
+ static size_t
-_UTF8_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
+_UTF2_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
{
- _UTF8State *us;
if (us->want != 0) {
errno = EINVAL;
-@@ -315,15 +307,6 @@
+@@ -325,15 +314,6 @@ _UTF8_wcrtomb(char * __restrict s, wchar
} else if ((wc & ~0xffff) == 0) {
lead = 0xe0;
len = 3;
} else {
errno = EILSEQ;
return ((size_t)-1);
-@@ -344,17 +327,17 @@
- return (len);
+@@ -355,16 +335,16 @@ _UTF8_wcrtomb(char * __restrict s, wchar
}
--size_t
+ static size_t
-_UTF8_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
- size_t nwc, size_t len, mbstate_t * __restrict ps)
-+static size_t
+_UTF2_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps, locale_t loc)
{
if (us->want != 0) {
errno = EINVAL;
-@@ -369,7 +352,7 @@
+@@ -379,7 +359,7 @@ _UTF8_wcsnrtombs(char * __restrict dst,
if (0 <= *s && *s < 0x80)
/* Fast path for plain ASCII characters. */
nb = 1;
(size_t)-1)
/* Invalid character - wcrtomb() sets errno. */
return ((size_t)-1);
-@@ -386,9 +369,9 @@
+@@ -396,9 +376,9 @@ _UTF8_wcsnrtombs(char * __restrict dst,
/* Fast path for plain ASCII characters. */
nb = 1;
*dst = *s;
- } else if (len > (size_t)MB_CUR_MAX) {
+ } else if (len > (size_t)UTF2_MB_CUR_MAX) {
/* Enough space to translate in-place. */
-- if ((nb = (int)_UTF8_wcrtomb(dst, *s, ps)) < 0) {
-+ if ((nb = (int)_UTF2_wcrtomb(dst, *s, ps, loc)) < 0) {
+- if ((nb = _UTF8_wcrtomb(dst, *s, ps)) == (size_t)-1) {
++ if ((nb = _UTF2_wcrtomb(dst, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
-@@ -396,7 +379,7 @@
+@@ -406,7 +386,7 @@ _UTF8_wcsnrtombs(char * __restrict dst,
/*
* May not be enough space; use temp. buffer.
*/
-- if ((nb = (int)_UTF8_wcrtomb(buf, *s, ps)) < 0) {
-+ if ((nb = (int)_UTF2_wcrtomb(buf, *s, ps, loc)) < 0) {
+- if ((nb = _UTF8_wcrtomb(buf, *s, ps)) == (size_t)-1) {
++ if ((nb = _UTF2_wcrtomb(buf, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)utf2.4 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/utf8.5,v 1.6 2004/10/17 02:29:15 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/utf8.5,v 1.7 2007/01/09 00:28:01 imp Exp $
.\"
.Dd April 7, 2004
.Dt UTF8 5
*/
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.11 2004/07/27 06:29:48 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.16 2007/10/15 09:51:30 ache Exp $");
#include <errno.h>
#include <limits.h>
#include <wchar.h>
#include "mblocal.h"
-size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict);
-int _UTF8_mbsinit(const mbstate_t *);
-size_t _UTF8_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
-size_t _UTF8_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
-size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
+extern int __mb_sb_limit;
+
+static size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _UTF8_mbsinit(const mbstate_t *);
+static size_t _UTF8_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _UTF8_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
typedef struct {
wchar_t ch;
__wcsnrtombs = _UTF8_wcsnrtombs;
_CurrentRuneLocale = rl;
__mb_cur_max = 6;
+ /*
+ * UCS-4 encoding used as the internal representation, so
+ * slots 0x0080-0x00FF are occuped and must be excluded
+ * from the single byte ctype by setting the limit.
+ */
+ __mb_sb_limit = 128;
return (0);
}
-int
+static int
_UTF8_mbsinit(const mbstate_t *ps)
{
return (ps == NULL || ((const _UTF8State *)ps)->want == 0);
}
-size_t
+static size_t
_UTF8_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps)
{
mask = 0x03;
want = 5;
lbound = 0x200000;
- } else if ((ch & 0xfc) == 0xfc) {
+ } else if ((ch & 0xfe) == 0xfc) {
mask = 0x01;
want = 6;
lbound = 0x4000000;
return (wch == L'\0' ? 0 : want);
}
-size_t
+static size_t
_UTF8_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
size_t nms, size_t len, mbstate_t * __restrict ps)
{
return (nchr);
}
-size_t
+static size_t
_UTF8_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
_UTF8State *us;
return (len);
}
-size_t
+static size_t
_UTF8_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
size_t nwc, size_t len, mbstate_t * __restrict ps)
{
*dst = *s;
} else if (len > (size_t)MB_CUR_MAX) {
/* Enough space to translate in-place. */
- if ((nb = (int)_UTF8_wcrtomb(dst, *s, ps)) < 0) {
+ if ((nb = _UTF8_wcrtomb(dst, *s, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
/*
* May not be enough space; use temp. buffer.
*/
- if ((nb = (int)_UTF8_wcrtomb(buf, *s, ps)) < 0) {
+ if ((nb = _UTF8_wcrtomb(buf, *s, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
---- utf8.c.orig Thu Nov 25 11:38:20 2004
-+++ utf8.c Fri Feb 18 15:40:44 2005
+--- utf8.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ utf8.c 2009-11-09 17:35:23.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/param.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.11 2004/07/27 06:29:48 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.16 2007/10/15 09:51:30 ache Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <limits.h>
#include <runetype.h>
-@@ -35,14 +37,16 @@
+@@ -35,18 +37,18 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include <wchar.h>
#include "mblocal.h"
--size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-- mbstate_t * __restrict);
--int _UTF8_mbsinit(const mbstate_t *);
--size_t _UTF8_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
-- size_t, size_t, mbstate_t * __restrict);
--size_t _UTF8_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
--size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
-- size_t, size_t, mbstate_t * __restrict);
+-extern int __mb_sb_limit;
+#define UTF8_MB_CUR_MAX 6
-+
-+static size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
-+ mbstate_t * __restrict, locale_t);
+
+ static size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict,
+- size_t, mbstate_t * __restrict);
+-static int _UTF8_mbsinit(const mbstate_t *);
++ size_t, mbstate_t * __restrict, locale_t);
+static int _UTF8_mbsinit(const mbstate_t *, locale_t);
-+static size_t _UTF8_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
-+ size_t, size_t, mbstate_t * __restrict, locale_t);
-+static size_t _UTF8_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
-+static size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
-+ size_t, size_t, mbstate_t * __restrict, locale_t);
+ static size_t _UTF8_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
+ static size_t _UTF8_wcrtomb(char * __restrict, wchar_t,
+- mbstate_t * __restrict);
++ mbstate_t * __restrict, locale_t);
+ static size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+- size_t, size_t, mbstate_t * __restrict);
++ size_t, size_t, mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
-@@ -50,31 +54,30 @@
+@@ -54,29 +56,28 @@ typedef struct {
wchar_t lbound;
} _UTF8State;
+ xrl->__mbsnrtowcs = _UTF8_mbsnrtowcs;
+ xrl->__wcsnrtombs = _UTF8_wcsnrtombs;
+ xrl->__mb_cur_max = UTF8_MB_CUR_MAX;
+ /*
+ * UCS-4 encoding used as the internal representation, so
+ * slots 0x0080-0x00FF are occuped and must be excluded
+ * from the single byte ctype by setting the limit.
+ */
+- __mb_sb_limit = 128;
++ xrl->__mb_sb_limit = 128;
return (0);
}
--int
+ static int
-_UTF8_mbsinit(const mbstate_t *ps)
-+static int
+_UTF8_mbsinit(const mbstate_t *ps, locale_t loc)
{
return (ps == NULL || ((const _UTF8State *)ps)->want == 0);
- }
+@@ -84,7 +85,7 @@ _UTF8_mbsinit(const mbstate_t *ps)
--size_t
-+static size_t
+ static size_t
_UTF8_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps)
+ mbstate_t * __restrict ps, locale_t loc)
{
_UTF8State *us;
int ch, i, mask, want;
-@@ -194,9 +197,9 @@
- return (wch == L'\0' ? 0 : want);
- }
+@@ -206,7 +207,7 @@ _UTF8_mbrtowc(wchar_t * __restrict pwc,
--size_t
-+static size_t
+ static size_t
_UTF8_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
- size_t nms, size_t len, mbstate_t * __restrict ps)
+ size_t nms, size_t len, mbstate_t * __restrict ps, locale_t loc)
{
_UTF8State *us;
const char *s;
-@@ -226,7 +229,7 @@
+@@ -236,7 +237,7 @@ _UTF8_mbsnrtowcs(wchar_t * __restrict ds
* excluding NUL.
*/
nb = 1;
(size_t)-1)
/* Invalid sequence - mbrtowc() sets errno. */
return ((size_t)-1);
-@@ -256,7 +259,7 @@
+@@ -266,7 +267,7 @@ _UTF8_mbsnrtowcs(wchar_t * __restrict ds
*/
*dst = (wchar_t)*s;
nb = 1;
(size_t)-1) {
*src = s;
return ((size_t)-1);
-@@ -276,8 +279,8 @@
- return (nchr);
+@@ -287,7 +288,7 @@ _UTF8_mbsnrtowcs(wchar_t * __restrict ds
}
--size_t
+ static size_t
-_UTF8_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
-+static size_t
+_UTF8_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
{
_UTF8State *us;
unsigned char lead;
-@@ -344,9 +347,9 @@
- return (len);
- }
+@@ -356,7 +357,7 @@ _UTF8_wcrtomb(char * __restrict s, wchar
--size_t
-+static size_t
+ static size_t
_UTF8_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
- size_t nwc, size_t len, mbstate_t * __restrict ps)
+ size_t nwc, size_t len, mbstate_t * __restrict ps, locale_t loc)
{
_UTF8State *us;
char buf[MB_LEN_MAX];
-@@ -369,7 +372,7 @@
+@@ -379,7 +380,7 @@ _UTF8_wcsnrtombs(char * __restrict dst,
if (0 <= *s && *s < 0x80)
/* Fast path for plain ASCII characters. */
nb = 1;
(size_t)-1)
/* Invalid character - wcrtomb() sets errno. */
return ((size_t)-1);
-@@ -386,9 +389,9 @@
+@@ -396,9 +397,9 @@ _UTF8_wcsnrtombs(char * __restrict dst,
/* Fast path for plain ASCII characters. */
nb = 1;
*dst = *s;
- } else if (len > (size_t)MB_CUR_MAX) {
+ } else if (len > (size_t)UTF8_MB_CUR_MAX) {
/* Enough space to translate in-place. */
-- if ((nb = (int)_UTF8_wcrtomb(dst, *s, ps)) < 0) {
-+ if ((nb = (int)_UTF8_wcrtomb(dst, *s, ps, loc)) < 0) {
+- if ((nb = _UTF8_wcrtomb(dst, *s, ps)) == (size_t)-1) {
++ if ((nb = _UTF8_wcrtomb(dst, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
-@@ -396,7 +399,7 @@
+@@ -406,7 +407,7 @@ _UTF8_wcsnrtombs(char * __restrict dst,
/*
* May not be enough space; use temp. buffer.
*/
-- if ((nb = (int)_UTF8_wcrtomb(buf, *s, ps)) < 0) {
-+ if ((nb = (int)_UTF8_wcrtomb(buf, *s, ps, loc)) < 0) {
+- if ((nb = _UTF8_wcrtomb(buf, *s, ps)) == (size_t)-1) {
++ if ((nb = _UTF8_wcrtomb(buf, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
---- _SB/Libc/locale/FreeBSD/wcrtomb.3 2004-11-25 11:38:20.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/wcrtomb.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- wcrtomb.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcrtomb.3 2009-11-09 15:05:26.000000000 -0800
@@ -28,14 +28,28 @@
.Dt WCRTOMB 3
.Os
.Sh DESCRIPTION
The
.Fn wcrtomb
-@@ -44,10 +58,10 @@
+@@ -44,10 +58,10 @@ wide character
.Fa wc ,
including any necessary shift sequences, to the
character array
.Pp
If
.Fa s
-@@ -58,7 +72,7 @@
+@@ -58,7 +72,7 @@ behaves as if
.Fa s
pointed to an internal buffer and
.Fa wc
.Pp
The
.Ft mbstate_t
-@@ -72,6 +86,14 @@
+@@ -72,6 +86,14 @@ uses an internal, static
.Vt mbstate_t
object, which is initialized to the initial conversion state
at program startup.
.Sh RETURN VALUES
The
.Fn wcrtomb
-@@ -97,7 +119,8 @@
+@@ -97,7 +119,8 @@ The conversion state is invalid.
.Xr mbrtowc 3 ,
.Xr multibyte 3 ,
.Xr setlocale 3 ,
---- wcrtomb.c.orig 2004-11-25 11:38:20.000000000 -0800
-+++ wcrtomb.c 2005-02-18 18:30:14.000000000 -0800
+--- wcrtomb.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcrtomb.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,15 +27,23 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wcrtomb.c,v 1.8 2004/05/12 14:09:04 tjr Exp $");
---- _SB/Libc/locale/FreeBSD/wcsftime.3 2003-05-20 15:21:44.000000000 -0700
-+++ _SB/Libc/locale/FreeBSD/wcsftime.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- wcsftime.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcsftime.3 2009-11-09 15:05:26.000000000 -0800
@@ -28,7 +28,8 @@
.Dt WCSFTIME 3
.Os
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.6 2009/01/15 20:45:59 rdivacky Exp $");
#include <errno.h>
#include <limits.h>
{
static const mbstate_t initial;
mbstate_t mbs;
- char *dst, *dstp, *sformat;
+ char *dst, *sformat;
+ const char *dstp;
+ const wchar_t *formatp;
size_t n, sflen;
int sverrno;
* for strftime(), which only handles single-byte characters.
*/
mbs = initial;
- sflen = wcsrtombs(NULL, &format, 0, &mbs);
+ formatp = format;
+ sflen = wcsrtombs(NULL, &formatp, 0, &mbs);
if (sflen == (size_t)-1)
goto error;
if ((sformat = malloc(sflen + 1)) == NULL)
goto error;
mbs = initial;
- wcsrtombs(sformat, &format, sflen + 1, &mbs);
+ wcsrtombs(sformat, &formatp, sflen + 1, &mbs);
/*
* Allocate memory for longest multibyte sequence that will fit
goto error;
dstp = dst;
mbs = initial;
- n = mbsrtowcs(wcs, (const char **)&dstp, maxsize, &mbs);
+ n = mbsrtowcs(wcs, &dstp, maxsize, &mbs);
if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
goto error;
---- wcsftime.c.orig 2004-11-25 11:38:20.000000000 -0800
-+++ wcsftime.c 2005-02-24 00:53:36.000000000 -0800
+--- wcsftime.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ wcsftime.c 2009-11-09 17:45:28.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.6 2009/01/15 20:45:59 rdivacky Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
-@@ -47,8 +49,9 @@
+@@ -47,8 +49,9 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* format specifications in the format string.
*/
size_t
{
static const mbstate_t initial;
mbstate_t mbs;
-@@ -56,6 +59,7 @@
+@@ -58,6 +61,7 @@ wcsftime(wchar_t * __restrict wcs, size_
size_t n, sflen;
int sverrno;
sformat = dst = NULL;
/*
-@@ -63,13 +67,13 @@
- * for strftime(), which only handles single-byte characters.
+@@ -66,13 +70,13 @@ wcsftime(wchar_t * __restrict wcs, size_
*/
mbs = initial;
-- sflen = wcsrtombs(NULL, &format, 0, &mbs);
-+ sflen = wcsrtombs_l(NULL, &format, 0, &mbs, loc);
+ formatp = format;
+- sflen = wcsrtombs(NULL, &formatp, 0, &mbs);
++ sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, loc);
if (sflen == (size_t)-1)
goto error;
if ((sformat = malloc(sflen + 1)) == NULL)
goto error;
mbs = initial;
-- wcsrtombs(sformat, &format, sflen + 1, &mbs);
-+ wcsrtombs_l(sformat, &format, sflen + 1, &mbs, loc);
+- wcsrtombs(sformat, &formatp, sflen + 1, &mbs);
++ wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, loc);
/*
* Allocate memory for longest multibyte sequence that will fit
-@@ -77,18 +81,18 @@
+@@ -80,18 +84,18 @@ wcsftime(wchar_t * __restrict wcs, size_
* Then, copy and convert the result back into wide characters in
* the caller's buffer.
*/
goto error;
dstp = dst;
mbs = initial;
-- n = mbsrtowcs(wcs, (const char **)&dstp, maxsize, &mbs);
-+ n = mbsrtowcs_l(wcs, (const char **)&dstp, maxsize, &mbs, loc);
+- n = mbsrtowcs(wcs, &dstp, maxsize, &mbs);
++ n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, loc);
if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
goto error;
-@@ -103,3 +107,10 @@
+@@ -106,3 +110,10 @@ error:
errno = sverrno;
return (0);
}
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcsnrtombs.c,v 1.2 2004/07/22 02:57:29 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcsnrtombs.c,v 1.3 2005/02/12 08:45:12 stefanf Exp $");
#include <limits.h>
#include <stdlib.h>
while (len > 0 && nwc-- > 0) {
if (len > (size_t)MB_CUR_MAX) {
/* Enough space to translate in-place. */
- if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) {
+ if ((nb = __wcrtomb(dst, *s, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
* character is too long for the buffer.
*/
mbsbak = *ps;
- if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) {
+ if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
---- wcsnrtombs.c.orig 2004-11-25 11:38:20.000000000 -0800
-+++ wcsnrtombs.c 2005-02-18 18:38:25.000000000 -0800
+--- wcsnrtombs.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ wcsnrtombs.c 2009-11-09 17:47:14.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcsnrtombs.c,v 1.2 2004/07/22 02:57:29 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcsnrtombs.c,v 1.3 2005/02/12 08:45:12 stefanf Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-@@ -34,32 +36,41 @@
+@@ -34,32 +36,41 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "mblocal.h"
size_t
/* Invalid character - wcrtomb() sets errno. */
return ((size_t)-1);
else if (*s == L'\0')
-@@ -71,9 +82,9 @@
+@@ -71,9 +82,9 @@ __wcsnrtombs_std(char * __restrict dst,
}
while (len > 0 && nwc-- > 0) {
- if (len > (size_t)MB_CUR_MAX) {
+ if (len > (size_t)mb_cur_max) {
/* Enough space to translate in-place. */
-- if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) {
-+ if ((nb = (int)__wcrtomb(dst, *s, ps, loc)) < 0) {
+- if ((nb = __wcrtomb(dst, *s, ps)) == (size_t)-1) {
++ if ((nb = __wcrtomb(dst, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
-@@ -86,7 +97,7 @@
+@@ -86,7 +97,7 @@ __wcsnrtombs_std(char * __restrict dst,
* character is too long for the buffer.
*/
mbsbak = *ps;
-- if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) {
-+ if ((nb = (int)__wcrtomb(buf, *s, ps, loc)) < 0) {
+- if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) {
++ if ((nb = __wcrtomb(buf, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
---- _SB/Libc/locale/FreeBSD/wcsrtombs.3 2004-11-25 11:38:20.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/wcsrtombs.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- wcsrtombs.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcsrtombs.3 2009-11-09 15:05:26.000000000 -0800
@@ -28,30 +28,57 @@
.Dt WCSRTOMBS 3
.Os
.Fa dst .
No more than
.Fa len
-@@ -97,15 +124,28 @@
+@@ -97,15 +124,28 @@ except that conversion stops after readi
.Fa nwc
characters from the buffer pointed to by
.Fa src .
.Po Vt size_t Pc Ns \-1 .
.Sh ERRORS
The
-@@ -122,7 +162,8 @@
+@@ -122,7 +162,8 @@ The conversion state is invalid.
.Sh SEE ALSO
.Xr mbsrtowcs 3 ,
.Xr wcrtomb 3 ,
---- wcsrtombs.c.orig 2004-11-25 11:38:20.000000000 -0800
-+++ wcsrtombs.c 2005-02-18 18:36:45.000000000 -0800
+--- wcsrtombs.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcsrtombs.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wcsrtombs.c,v 1.6 2004/07/21 10:54:57 tjr Exp $");
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-@@ -34,12 +36,18 @@
+@@ -34,12 +36,18 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
#include "mblocal.h"
size_t
---- wcstod.3 2004-11-25 11:38:20.000000000 -0800
-+++ wcstod.3.edit 2006-08-09 13:29:59.000000000 -0700
+--- wcstod.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstod.3 2009-11-09 15:05:26.000000000 -0800
@@ -28,40 +28,57 @@
.Dt WCSTOD 3
.Os
---- wcstod.c.orig 2008-10-09 11:50:53.000000000 -0700
-+++ wcstod.c 2008-10-29 00:50:24.000000000 -0700
+--- wcstod.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstod.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,9 +27,31 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wcstod.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
---- wcstof.c.orig 2008-10-09 11:50:52.000000000 -0700
-+++ wcstof.c 2008-10-29 00:51:43.000000000 -0700
+--- wcstof.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstof.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,44 +27,67 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wcstof.c,v 1.3 2004/04/07 09:47:56 tjr Exp $");
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoimax.c,v 1.2 2003/01/01 18:48:43 schweikh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoimax.c,v 1.3 2007/01/09 00:28:01 imp Exp $");
#include <errno.h>
#include <inttypes.h>
---- wcstoimax.c.orig 2003-05-20 15:21:45.000000000 -0700
-+++ wcstoimax.c 2005-02-23 16:06:32.000000000 -0800
-@@ -40,6 +40,8 @@
+--- wcstoimax.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstoimax.c 2009-11-09 15:05:26.000000000 -0800
+@@ -36,6 +36,8 @@ __FBSDID("FreeBSD: src/lib/libc/stdlib/s
#endif
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoimax.c,v 1.2 2003/01/01 18:48:43 schweikh Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoimax.c,v 1.3 2007/01/09 00:28:01 imp Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
-@@ -50,8 +52,8 @@
+@@ -46,8 +48,8 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* Convert a wide character string to an intmax_t integer.
*/
intmax_t
{
const wchar_t *s;
uintmax_t acc;
-@@ -59,13 +61,14 @@
+@@ -55,13 +57,14 @@ wcstoimax(const wchar_t * __restrict npt
uintmax_t cutoff;
int neg, any, cutlim;
if (c == L'-') {
neg = 1;
c = *s++;
-@@ -92,8 +95,8 @@
+@@ -88,8 +91,8 @@ wcstoimax(const wchar_t * __restrict npt
cutoff /= base;
for ( ; ; c = *s++) {
#ifdef notyet
else
#endif
if (c >= L'0' && c <= L'9')
-@@ -126,3 +129,10 @@
+@@ -122,3 +125,10 @@ noconv:
*endptr = (wchar_t *)(any ? s - 1 : nptr);
return (acc);
}
---- wcstol.3 2003-05-20 15:21:45.000000000 -0700
-+++ wcstol.3.edit 2006-07-12 11:29:16.000000000 -0700
+--- wcstol.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstol.3 2009-11-09 15:05:26.000000000 -0800
@@ -28,15 +28,18 @@
.Dt WCSTOL 3
.Os
or
.Vt uintmax_t
integer
-@@ -45,25 +48,50 @@
+@@ -45,25 +48,50 @@ integer
.Sh SYNOPSIS
.In wchar.h
.Ft long
and
.Fn wcstoumax
functions are wide-character versions of the
-@@ -71,23 +99,42 @@
+@@ -71,23 +99,42 @@ functions are wide-character versions of
.Fn strtoul ,
.Fn strtoll ,
.Fn strtoull ,
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstol.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstol.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include <ctype.h>
#include <errno.h>
---- wcstol.c.orig Tue May 20 15:21:45 2003
-+++ wcstol.c Fri Feb 18 14:50:27 2005
-@@ -34,6 +34,8 @@
+--- wcstol.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstol.c 2009-11-09 15:05:26.000000000 -0800
+@@ -30,6 +30,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcstol.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcstol.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
+#include "xlocale_private.h"
+
#include <ctype.h>
#include <errno.h>
#include <limits.h>
-@@ -44,7 +46,8 @@
+@@ -40,7 +42,8 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* Convert a string to a long integer.
*/
long
{
const wchar_t *s;
unsigned long acc;
-@@ -52,13 +55,14 @@
+@@ -48,13 +51,14 @@ wcstol(const wchar_t * __restrict nptr,
unsigned long cutoff;
int neg, any, cutlim;
if (c == '-') {
neg = 1;
c = *s++;
-@@ -85,8 +89,8 @@
+@@ -81,8 +85,8 @@ wcstol(const wchar_t * __restrict nptr,
cutoff /= base;
for ( ; ; c = *s++) {
#ifdef notyet
else
#endif
if (c >= L'0' && c <= L'9')
-@@ -118,4 +122,10 @@
- if (endptr != NULL)
+@@ -115,3 +119,9 @@ noconv:
*endptr = (wchar_t *)(any ? s - 1 : nptr);
return (acc);
-+}
+ }
+
+long
+wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+ return wcstol_l(nptr, endptr, base, __current_locale());
- }
++}
---- wcstold.c.orig 2008-10-09 11:50:53.000000000 -0700
-+++ wcstold.c 2008-10-29 00:51:34.000000000 -0700
+--- wcstold.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstold.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,44 +27,67 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wcstold.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoll.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoll.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include <errno.h>
#include <limits.h>
---- wcstoll.c.orig Tue May 20 15:21:45 2003
-+++ wcstoll.c Fri Feb 18 14:54:25 2005
-@@ -40,6 +40,8 @@
+--- wcstoll.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstoll.c 2009-11-09 15:05:26.000000000 -0800
+@@ -36,6 +36,8 @@ __FBSDID("FreeBSD: src/lib/libc/stdlib/s
#endif
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoll.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoll.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
-@@ -50,7 +52,8 @@
+@@ -46,7 +48,8 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* Convert a wide character string to a long long integer.
*/
long long
{
const wchar_t *s;
unsigned long long acc;
-@@ -58,13 +61,14 @@
+@@ -54,13 +57,14 @@ wcstoll(const wchar_t * __restrict nptr,
unsigned long long cutoff;
int neg, any, cutlim;
if (c == L'-') {
neg = 1;
c = *s++;
-@@ -91,8 +95,8 @@
+@@ -87,8 +91,8 @@ wcstoll(const wchar_t * __restrict nptr,
cutoff /= base;
for ( ; ; c = *s++) {
#ifdef notyet
else
#endif
if (c >= L'0' && c <= L'9')
-@@ -124,4 +128,10 @@
- if (endptr != NULL)
+@@ -121,3 +125,9 @@ noconv:
*endptr = (wchar_t *)(any ? s - 1 : nptr);
return (acc);
-+}
+ }
+
+long long
+wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+ return wcstoll_l(nptr, endptr, base, __current_locale());
- }
++}
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/wcstombs.3,v 1.4 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/wcstombs.3,v 1.5 2007/01/09 00:28:01 imp Exp $
.\"
.Dd April 8, 2004
.Dt WCSTOMBS 3
---- _SB/Libc/locale/FreeBSD/wcstombs.3 2004-11-25 11:38:20.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/wcstombs.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -41,7 +41,8 @@
+--- wcstombs.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstombs.3 2009-11-09 15:05:26.000000000 -0800
+@@ -37,7 +37,8 @@
.Dt WCSTOMBS 3
.Os
.Sh NAME
.Nd convert a wide-character string to a character string
.Sh LIBRARY
.Lb libc
-@@ -49,28 +50,47 @@
+@@ -45,28 +46,47 @@
.In stdlib.h
.Ft size_t
.Fo wcstombs
.Po Vt size_t Pc Ns \-1 .
.Sh ERRORS
The
-@@ -86,7 +106,8 @@
+@@ -82,7 +102,8 @@ The conversion state is invalid.
.Xr mbstowcs 3 ,
.Xr multibyte 3 ,
.Xr wcsrtombs 3 ,
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstombs.c,v 1.10 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstombs.c,v 1.11 2009/01/15 18:53:52 rdivacky Exp $");
#include <limits.h>
#include <stdlib.h>
{
static const mbstate_t initial;
mbstate_t mbs;
+ const wchar_t *pwcsp;
mbs = initial;
- return (__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs));
+ pwcsp = pwcs;
+ return (__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs));
}
---- wcstombs.c.orig Thu Nov 25 11:38:20 2004
-+++ wcstombs.c Fri Feb 18 17:17:37 2005
-@@ -27,17 +27,27 @@
+--- wcstombs.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ wcstombs.c 2009-11-09 17:49:26.000000000 -0800
+@@ -27,19 +27,29 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcstombs.c,v 1.10 2004/07/21 10:54:57 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcstombs.c,v 1.11 2009/01/15 18:53:52 rdivacky Exp $");
+#include "xlocale_private.h"
+
{
static const mbstate_t initial;
mbstate_t mbs;
+ const wchar_t *pwcsp;
+ NORMALIZE_LOCALE(loc);
mbs = initial;
-- return (__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs));
-+ return (loc->__lc_ctype->__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs, loc));
+ pwcsp = pwcs;
+- return (__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs));
++ return (loc->__lc_ctype->__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs, loc));
+}
+
+size_t
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoul.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoul.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include <ctype.h>
#include <errno.h>
---- wcstoul.c.orig Tue May 20 15:21:45 2003
-+++ wcstoul.c Fri Feb 18 14:56:18 2005
-@@ -34,6 +34,8 @@
+--- wcstoul.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstoul.c 2009-11-09 15:05:26.000000000 -0800
+@@ -30,6 +30,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoul.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoul.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
+#include "xlocale_private.h"
+
#include <ctype.h>
#include <errno.h>
#include <limits.h>
-@@ -44,7 +46,8 @@
+@@ -40,7 +42,8 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* Convert a wide character string to an unsigned long integer.
*/
unsigned long
{
const wchar_t *s;
unsigned long acc;
-@@ -52,13 +55,14 @@
+@@ -48,13 +51,14 @@ wcstoul(const wchar_t * __restrict nptr,
unsigned long cutoff;
int neg, any, cutlim;
if (c == L'-') {
neg = 1;
c = *s++;
-@@ -83,8 +87,8 @@
+@@ -79,8 +83,8 @@ wcstoul(const wchar_t * __restrict nptr,
cutlim = ULONG_MAX % base;
for ( ; ; c = *s++) {
#ifdef notyet
else
#endif
if (c >= L'0' && c <= L'9')
-@@ -116,4 +120,10 @@
- if (endptr != NULL)
+@@ -113,3 +117,9 @@ noconv:
*endptr = (wchar_t *)(any ? s - 1 : nptr);
return (acc);
-+}
+ }
+
+unsigned long
+wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+ return wcstoul_l(nptr, endptr, base, __current_locale());
- }
++}
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoull.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoull.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include <errno.h>
#include <limits.h>
---- wcstoull.c.orig Tue May 20 15:21:45 2003
-+++ wcstoull.c Fri Feb 18 14:58:24 2005
-@@ -40,6 +40,8 @@
+--- wcstoull.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstoull.c 2009-11-09 15:05:26.000000000 -0800
+@@ -36,6 +36,8 @@ __FBSDID("FreeBSD: src/lib/libc/stdlib/s
#endif
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoull.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoull.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
-@@ -50,8 +52,8 @@
+@@ -46,8 +48,8 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* Convert a wide character string to an unsigned long long integer.
*/
unsigned long long
{
const wchar_t *s;
unsigned long long acc;
-@@ -59,13 +61,14 @@
+@@ -55,13 +57,14 @@ wcstoull(const wchar_t * __restrict nptr
unsigned long long cutoff;
int neg, any, cutlim;
if (c == L'-') {
neg = 1;
c = *s++;
-@@ -90,8 +93,8 @@
+@@ -86,8 +89,8 @@ wcstoull(const wchar_t * __restrict nptr
cutlim = ULLONG_MAX % base;
for ( ; ; c = *s++) {
#ifdef notyet
else
#endif
if (c >= L'0' && c <= L'9')
-@@ -123,4 +126,11 @@
- if (endptr != NULL)
+@@ -120,3 +123,10 @@ noconv:
*endptr = (wchar_t *)(any ? s - 1 : nptr);
return (acc);
-+}
+ }
+
+unsigned long long
+wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base)
+{
+ return wcstoull_l(nptr, endptr, base, __current_locale());
- }
++}
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoumax.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoumax.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include <errno.h>
#include <inttypes.h>
---- wcstoumax.c.orig 2003-05-20 15:21:45.000000000 -0700
-+++ wcstoumax.c 2005-02-23 16:08:34.000000000 -0800
-@@ -40,6 +40,8 @@
+--- wcstoumax.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcstoumax.c 2009-11-09 15:05:26.000000000 -0800
+@@ -36,6 +36,8 @@ __FBSDID("FreeBSD: src/lib/libc/stdlib/s
#endif
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoumax.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcstoumax.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
-@@ -50,8 +52,8 @@
+@@ -46,8 +48,8 @@ __FBSDID("$FreeBSD: src/lib/libc/locale/
* Convert a wide character string to a uintmax_t integer.
*/
uintmax_t
{
const wchar_t *s;
uintmax_t acc;
-@@ -59,13 +61,14 @@
+@@ -55,13 +57,14 @@ wcstoumax(const wchar_t * __restrict npt
uintmax_t cutoff;
int neg, any, cutlim;
if (c == L'-') {
neg = 1;
c = *s++;
-@@ -90,8 +93,8 @@
+@@ -86,8 +89,8 @@ wcstoumax(const wchar_t * __restrict npt
cutlim = UINTMAX_MAX % base;
for ( ; ; c = *s++) {
#ifdef notyet
else
#endif
if (c >= L'0' && c <= L'9')
-@@ -124,3 +127,10 @@
+@@ -120,3 +123,10 @@ noconv:
*endptr = (wchar_t *)(any ? s - 1 : nptr);
return (acc);
}
---- wctob.c.orig 2004-11-25 11:38:20.000000000 -0800
-+++ wctob.c 2005-02-18 18:16:08.000000000 -0800
+--- wctob.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wctob.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,19 +27,28 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wctob.c,v 1.4 2004/05/12 14:26:54 tjr Exp $");
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/wctomb.3,v 1.3 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/wctomb.3,v 1.4 2007/01/09 00:28:01 imp Exp $
.\"
.Dd April 8, 2004
.Dt WCTOMB 3
---- _SB/Libc/locale/FreeBSD/wctomb.3 2004-11-25 11:38:20.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/wctomb.3.edit 2006-06-28 16:55:51.000000000 -0700
-@@ -41,37 +41,56 @@
+--- wctomb.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wctomb.3 2009-11-09 15:05:26.000000000 -0800
+@@ -37,37 +37,56 @@
.Dt WCTOMB 3
.Os
.Sh NAME
is
.Dv NULL ,
the
-@@ -79,12 +98,12 @@
+@@ -75,12 +94,12 @@ the
function returns nonzero if shift states are supported,
zero otherwise.
If
or \-1 if no multibyte character
could be recognized or converted.
In this case,
-@@ -104,7 +123,8 @@
+@@ -100,7 +119,8 @@ The internal conversion state is invalid
.Xr mbtowc 3 ,
.Xr wcrtomb 3 ,
.Xr wcstombs 3 ,
---- wctomb.c.orig 2004-11-25 11:38:20.000000000 -0800
-+++ wctomb.c 2005-02-18 18:40:43.000000000 -0800
+--- wctomb.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wctomb.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,23 +27,31 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wctomb.c,v 1.8 2004/07/29 06:18:40 tjr Exp $");
---- _SB/Libc/locale/FreeBSD/wctrans.3 2003-05-20 15:21:45.000000000 -0700
-+++ _SB/Libc/locale/FreeBSD/wctrans.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- wctrans.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wctrans.3 2009-11-09 15:05:26.000000000 -0800
@@ -28,21 +28,42 @@
.Dt WCTRANS 3
.Os
which represents the requested wide character mapping operation and
may be used as the second argument for calls to
.Fn towctrans .
-@@ -55,9 +76,21 @@
+@@ -55,9 +76,21 @@ The following character mapping names ar
The
.Fn towctrans
function transliterates the wide character
.Sh RETURN VALUES
The
.Fn towctrans
-@@ -105,7 +138,8 @@
+@@ -105,7 +138,8 @@ The requested mapping name is invalid.
.Sh SEE ALSO
.Xr tolower 3 ,
.Xr toupper 3 ,
---- wctrans.c.orig 2004-11-25 11:38:20.000000000 -0800
-+++ wctrans.c 2005-02-19 14:30:32.000000000 -0800
+--- wctrans.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wctrans.c 2009-11-09 15:05:26.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/locale/wctrans.c,v 1.3 2003/11/01 08:20:58 tjr Exp $");
#include <errno.h>
#include <string.h>
#include <wctype.h>
-@@ -38,15 +40,16 @@
+@@ -38,15 +40,16 @@ enum {
};
wint_t
break;
case _WCT_ERROR:
default:
-@@ -57,6 +60,12 @@
+@@ -57,6 +60,12 @@ towctrans(wint_t wc, wctrans_t desc)
return (wc);
}
wctrans_t
wctrans(const char *charclass)
{
-@@ -78,3 +87,14 @@
+@@ -78,3 +87,14 @@ wctrans(const char *charclass)
errno = EINVAL;
return (ccls[i].trans);
}
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/wctype.3,v 1.5 2004/03/27 08:59:21 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/wctype.3,v 1.7 2006/10/13 16:11:12 ru Exp $
.\"
.Dd March 27, 2004
.Dt WCTYPE 3
}
.Ed
.Sh SEE ALSO
-.Xr ctype 3
+.Xr ctype 3 ,
+.Xr nextwctype 3
.Sh STANDARDS
The
.Fn iswctype
.St -p1003.1-2001 .
The
.Dq Li ideogram ,
-.Dq Li phonogram
+.Dq Li phonogram ,
.Dq Li special ,
and
.Dq Li rune
---- _SB/Libc/locale/FreeBSD/wctype.3 2004-11-25 11:38:20.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/wctype.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- wctype.3.bsdnew 2009-11-10 13:13:11.000000000 -0800
++++ wctype.3 2009-11-10 14:11:00.000000000 -0800
@@ -28,21 +28,42 @@
.Dt WCTYPE 3
.Os
which represents the requested wide character class and
may be used as the second argument for calls to
.Fn iswctype .
-@@ -60,6 +81,18 @@
+@@ -60,6 +81,18 @@ function checks whether the wide charact
.Fa wc
is in the character class
.Fa charclass .
.Sh RETURN VALUES
The
.Fn iswctype
-@@ -75,7 +108,7 @@
+@@ -75,7 +108,7 @@ The
.Fn wctype
function returns 0 if
.Fa property
.Vt wctype_t
that can be used in subsequent calls to
.Fn iswctype .
-@@ -94,7 +127,8 @@
- }
+@@ -95,7 +128,8 @@ myiswalpha(wint_t wc)
.Ed
.Sh SEE ALSO
--.Xr ctype 3
-+.Xr ctype 3 ,
+ .Xr ctype 3 ,
+-.Xr nextwctype 3
++.Xr nextwctype 3 ,
+.Xr xlocale 3
.Sh STANDARDS
The
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wctype.c,v 1.3 2004/03/27 08:59:21 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wctype.c,v 1.4 2008/03/17 18:22:23 antoine Exp $");
#include <ctype.h>
#include <string.h>
wctype_t
wctype(const char *property)
{
- struct {
+ static const struct {
const char *name;
wctype_t mask;
} props[] = {
---- wctype.c.orig 2005-10-17 23:42:33.000000000 -0700
-+++ wctype.c 2005-10-17 23:44:47.000000000 -0700
-@@ -27,48 +27,63 @@
+--- wctype.c.bsdnew 2009-11-09 15:05:25.000000000 -0800
++++ wctype.c 2009-11-09 17:53:01.000000000 -0800
+@@ -27,21 +27,17 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/wctype.c,v 1.3 2004/03/27 08:59:21 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wctype.c,v 1.4 2008/03/17 18:22:23 antoine Exp $");
+#include "xlocale_private.h"
+
#include <ctype.h>
#include <string.h>
#include <wctype.h>
-+#include <limits.h>
-
+-
-#undef iswctype
-int
-iswctype(wint_t wc, wctype_t charclass)
-
- return (__istype(wc, charclass));
-}
-+static struct {
-+ const char *name;
-+ wctype_t mask;
-+} props[] = {
-+ { "alnum", _CTYPE_A|_CTYPE_D },
-+ { "alpha", _CTYPE_A },
-+ { "blank", _CTYPE_B },
-+ { "cntrl", _CTYPE_C },
-+ { "digit", _CTYPE_D },
-+ { "graph", _CTYPE_G },
-+ { "lower", _CTYPE_L },
-+ { "print", _CTYPE_R },
-+ { "punct", _CTYPE_P },
-+ { "space", _CTYPE_S },
-+ { "upper", _CTYPE_U },
-+ { "xdigit", _CTYPE_X },
-+ { "ideogram", _CTYPE_I }, /* BSD extension */
-+ { "special", _CTYPE_T }, /* BSD extension */
-+ { "phonogram", _CTYPE_Q }, /* BSD extension */
-+ { "rune", 0xFFFFFFF0L }, /* BSD extension */
-+ { NULL, 0UL }, /* Default */
-+};
++#include <limits.h>
wctype_t
-wctype(const char *property)
+wctype_l(const char *property, locale_t loc)
{
-- struct {
-- const char *name;
-- wctype_t mask;
-- } props[] = {
-- { "alnum", _CTYPE_A|_CTYPE_D },
-- { "alpha", _CTYPE_A },
-- { "blank", _CTYPE_B },
-- { "cntrl", _CTYPE_C },
-- { "digit", _CTYPE_D },
-- { "graph", _CTYPE_G },
-- { "lower", _CTYPE_L },
-- { "print", _CTYPE_R },
-- { "punct", _CTYPE_P },
-- { "space", _CTYPE_S },
-- { "upper", _CTYPE_U },
-- { "xdigit", _CTYPE_X },
-- { "ideogram", _CTYPE_I }, /* BSD extension */
-- { "special", _CTYPE_T }, /* BSD extension */
-- { "phonogram", _CTYPE_Q }, /* BSD extension */
-- { "rune", 0xFFFFFF00L }, /* BSD extension */
-- { NULL, 0UL }, /* Default */
-- };
- int i;
+ _RuneLocale *rl;
-
- i = 0;
+ static const struct {
+ const char *name;
+ wctype_t mask;
+@@ -70,5 +66,23 @@ wctype(const char *property)
while (props[i].name != NULL && strcmp(props[i].name, property) != 0)
i++;
---- _SB/Libc/locale/FreeBSD/wcwidth.3 2004-11-25 11:38:21.000000000 -0800
-+++ _SB/Libc/locale/FreeBSD/wcwidth.3.edit 2006-06-28 16:55:51.000000000 -0700
+--- wcwidth.3.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcwidth.3 2009-11-09 15:05:26.000000000 -0800
@@ -28,20 +28,38 @@
.Dt WCWIDTH 3
.Os
.Sh RETURN VALUES
The
.Fn wcwidth
-@@ -50,8 +68,8 @@
+@@ -50,8 +68,8 @@ function returns 0 if the
argument is a null wide character (L'\e0'),
\-1 if
.Fa wc
character occupies.
.Sh EXAMPLES
This code fragment reads text from standard input and
-@@ -79,7 +97,8 @@
+@@ -79,7 +97,8 @@ while ((ch = getwchar()) != WEOF) {
.Ed
.Sh SEE ALSO
.Xr iswprint 3 ,
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcwidth.c,v 1.7 2004/08/12 12:19:11 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcwidth.c,v 1.8 2007/01/09 00:28:01 imp Exp $");
#include <wchar.h>
---- wcwidth.c.orig 2004-11-25 11:38:21.000000000 -0800
-+++ wcwidth.c 2005-02-24 00:37:25.000000000 -0800
-@@ -42,6 +42,8 @@
+--- wcwidth.c.orig 2009-11-09 15:05:25.000000000 -0800
++++ wcwidth.c 2009-11-09 15:05:26.000000000 -0800
+@@ -38,6 +38,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/locale/wcwidth.c,v 1.7 2004/08/12 12:19:11 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/locale/wcwidth.c,v 1.8 2007/01/09 00:28:01 imp Exp $");
+#include "xlocale_private.h"
+
#include <wchar.h>
#undef wcwidth
-@@ -50,5 +52,13 @@
+@@ -46,5 +48,13 @@ int
wcwidth(wchar_t wc)
{
MISRCS += isctype.c iswctype.c xlocale.c
.include "Makefile.fbsd_begin"
-FBSDMISRCS= big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \
+FBSDMISRCS= ascii.c big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \
gb18030.c gb2312.c gbk.c \
ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c \
mblen.c mbrlen.c mbrtowc.c mbsinit.c mbsnrtowcs.c mbsrtowcs.c \
ARCH32 = $(_ARCH:C/64$//)
.endif
${_cwd}/rune32.h: ${_cwd}/rune-fbsd.c
- ${HOSTCC} -arch ${ARCH32} -D_LIBC_NO_FEATURE_VERIFICATION -I${.CURDIR}/include -DRUNEOFF32 -o ${_cwd}/rune32 ${.ALLSRC}
+ ${CP} ${.CURDIR}/include/runetype.h ${_cwd}
+ ${HOSTCC} -arch ${ARCH32} -D_LIBC_NO_FEATURE_VERIFICATION -DRUNEOFF32 -o ${_cwd}/rune32 ${.ALLSRC}
${_cwd}/rune32 > ${.TARGET}
- ${RM} ${_cwd}/rune32
+ ${RM} ${_cwd}/rune32 ${_cwd}/runetype.h
AUTOPATCHHDRS+= ${_cwd}/rune32.h
.endfor # _cwd
--- /dev/null
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/ascii.c,v 1.1 2008/01/21 23:48:12 ache Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <runetype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+static size_t _ascii_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
+static int _ascii_mbsinit(const mbstate_t *, locale_t);
+static size_t _ascii_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps __unused, locale_t);
+static size_t _ascii_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
+static size_t _ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict, locale_t);
+
+__private_extern__ int
+_ascii_init(struct __xlocale_st_runelocale *xrl)
+{
+
+ xrl->__mbrtowc = _ascii_mbrtowc;
+ xrl->__mbsinit = _ascii_mbsinit;
+ xrl->__mbsnrtowcs = _ascii_mbsnrtowcs;
+ xrl->__wcrtomb = _ascii_wcrtomb;
+ xrl->__wcsnrtombs = _ascii_wcsnrtombs;
+ xrl->__mb_cur_max = 1;
+ xrl->__mb_sb_limit = 128;
+ return(0);
+}
+
+static int
+_ascii_mbsinit(const mbstate_t *ps __unused, locale_t loc __unused)
+{
+
+ /*
+ * Encoding is not state dependent - we are always in the
+ * initial state.
+ */
+ return (1);
+}
+
+static size_t
+_ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps __unused, locale_t loc __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (0);
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if (pwc != NULL)
+ *pwc = (unsigned char)*s;
+ return (*s == '\0' ? 0 : 1);
+}
+
+static size_t
+_ascii_wcrtomb(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps __unused, locale_t loc __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if (wc < 0 || wc > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ *s = (unsigned char)wc;
+ return (1);
+}
+
+static size_t
+_ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
+{
+ const char *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ for (s = *src; nms > 0 && *s != '\0'; s++, nms--) {
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ return (s - *src);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nms-- > 0) {
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if ((*dst++ = (unsigned char)*s++) == L'\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
+static size_t
+_ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
+{
+ const wchar_t *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
+ if (*s < 0 || *s > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ return (s - *src);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nwc-- > 0) {
+ if (*s < 0 || *s > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if ((*dst++ = *s++) == '\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)big5.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/big5.c,v 1.16 2004/05/17 11:16:14 tjr Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/big5.c,v 1.18 2007/10/13 16:28:21 ache Exp $");
#include "xlocale_private.h"
+#include <sys/types.h>
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
-__private_extern__ int _BIG5_init(struct __xlocale_st_runelocale *);
-static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _BIG5_mbsinit(const mbstate_t *, locale_t);
-static size_t _BIG5_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+static size_t _BIG5_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
xrl->__wcrtomb = _BIG5_wcrtomb;
xrl->__mbsinit = _BIG5_mbsinit;
xrl->__mb_cur_max = 2;
+ xrl->__mb_sb_limit = 128;
return (0);
}
static int
-_BIG5_mbsinit(const mbstate_t *ps, locale_t loc)
+_BIG5_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _BIG5State *)ps)->ch == 0);
static size_t
_BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps, locale_t loc)
+ mbstate_t * __restrict ps, locale_t loc __unused)
{
_BIG5State *bs;
wchar_t wc;
}
static size_t
-_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
+_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_BIG5State *bs;
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.33 2004/09/22 16:56:48 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.35 2005/02/27 20:31:13 ru Exp $");
#include "xlocale_private.h"
/* assumes the locale_t variable is named loc */
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/lib/libc/locale/collate.h,v 1.14 2002/08/30 20:26:02 ache Exp $
+ * $FreeBSD: src/lib/libc/locale/collate.h,v 1.15 2005/02/27 20:31:13 ru Exp $
*/
#ifndef _COLLATE_H_
#define COLLATE_VERSION "1.0\n"
#define COLLATE_VERSION1_1 "1.1\n"
#define COLLATE_VERSION1_1A "1.1A\n"
+#define COLLATE_VERSION1_2 "1.2\n"
+
/* see discussion in string/FreeBSD/strxfrm for this value */
#define COLLATE_MAX_PRIORITY ((1 << 24) - 1)
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.17 2003/08/03 19:28:23 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/collcmp.c,v 1.18 2005/02/27 14:54:23 phantom Exp $");
#include <xlocale.h>
#include <wchar.h>
*/
__private_extern__ int
-__collate_range_cmp(c1, c2, loc)
- wchar_t c1, c2;
- locale_t loc;
+__collate_range_cmp(wchar_t c1, wchar_t c2, locale_t loc)
{
static wchar_t s1[2], s2[2];
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/ctype.3,v 1.15 2004/06/30 20:09:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/ctype.3,v 1.18 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt CTYPE 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)digittoint.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/digittoint.3,v 1.3 2004/03/30 07:19:35 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/digittoint.3,v 1.6 2009/09/04 07:44:58 des Exp $
.\"
.Dd April 6, 2001
.Dt DIGITTOINT 3
static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.20 2004/06/23 07:01:43 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.22 2007/10/13 16:28:21 ache Exp $");
#include "xlocale_private.h"
#include <wchar.h>
#include "mblocal.h"
-__private_extern__ int _EUC_init(struct __xlocale_st_runelocale *);
-static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _EUC_mbsinit(const mbstate_t *, locale_t);
-static size_t _EUC_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict,
- locale_t);
+static size_t _EUC_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
typedef struct {
int count[4];
}
rl->__variable = ei;
rl->__variable_len = sizeof(_EucInfo);
- xrl->__mb_cur_max = new__mb_cur_max;
- xrl->__mbrtowc = _EUC_mbrtowc;
- xrl->__wcrtomb = _EUC_wcrtomb;
- xrl->__mbsinit = _EUC_mbsinit;
- xrl->__free_extra = (__free_extra_t)_EUC_free_extra;
+ xrl->__mb_cur_max = new__mb_cur_max;
+ xrl->__mbrtowc = _EUC_mbrtowc;
+ xrl->__wcrtomb = _EUC_wcrtomb;
+ xrl->__mbsinit = _EUC_mbsinit;
+ xrl->__mb_sb_limit = 256;
+ xrl->__free_extra = (__free_extra_t)_EUC_free_extra;
return (0);
}
static int
-_EUC_mbsinit(const mbstate_t *ps, locale_t loc)
+_EUC_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _EucState *)ps)->want == 0);
static __inline int
_euc_set(u_int c)
{
+
c &= 0xff;
return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
}
}
static size_t
-_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps,
- locale_t loc)
+_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
{
_EucState *es;
wchar_t m, nm;
*/
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/gb18030.c,v 1.6 2004/05/12 14:09:04 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/gb18030.c,v 1.8 2007/10/13 16:28:21 ache Exp $");
#include "xlocale_private.h"
#define GB18030_MB_CUR_MAX 4
-__private_extern__ int _GB18030_init(struct __xlocale_st_runelocale *);
-static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _GB18030_mbsinit(const mbstate_t *, locale_t);
-static size_t _GB18030_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+static size_t _GB18030_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
typedef struct {
int count;
xrl->__wcrtomb = _GB18030_wcrtomb;
xrl->__mbsinit = _GB18030_mbsinit;
xrl->__mb_cur_max = GB18030_MB_CUR_MAX;
+ xrl->__mb_sb_limit = 128;
return (0);
}
static int
-_GB18030_mbsinit(const mbstate_t *ps, locale_t loc)
+_GB18030_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _GB18030State *)ps)->count == 0);
static size_t
_GB18030_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
- size_t n, mbstate_t * __restrict ps, locale_t loc)
+ size_t n, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB18030State *gs;
wchar_t wch;
}
static size_t
-_GB18030_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
+_GB18030_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB18030State *gs;
size_t len;
*/
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/gb2312.c,v 1.8 2004/05/12 14:09:04 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/gb2312.c,v 1.10 2007/10/13 16:28:21 ache Exp $");
#include "xlocale_private.h"
#define GB2312_MB_CUR_MAX 2
-__private_extern__ int _GB2312_init(struct __xlocale_st_runelocale *);
-static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _GB2312_mbsinit(const mbstate_t *, locale_t);
-static size_t _GB2312_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
-
+static size_t _GB2312_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
typedef struct {
int count;
u_char bytes[2];
xrl->__wcrtomb = _GB2312_wcrtomb;
xrl->__mbsinit = _GB2312_mbsinit;
xrl->__mb_cur_max = GB2312_MB_CUR_MAX;
+ xrl->__mb_sb_limit = 128;
return (0);
}
static int
-_GB2312_mbsinit(const mbstate_t *ps, locale_t loc)
+_GB2312_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _GB2312State *)ps)->count == 0);
static size_t
_GB2312_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps, locale_t loc)
+ mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB2312State *gs;
wchar_t wc;
}
static size_t
-_GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
+_GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GB2312State *gs;
* 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.
* SUCH DAMAGE.
*/
-#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/gbk.c,v 1.11 2004/05/17 11:16:14 tjr Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/locale/gbk.c,v 1.14 2007/10/13 16:28:21 ache Exp $");
#include "xlocale_private.h"
+#include <sys/types.h>
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
-__private_extern__ int _GBK_init(struct __xlocale_st_runelocale *);
-static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _GBK_mbsinit(const mbstate_t *, locale_t);
-static size_t _GBK_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+static size_t _GBK_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
xrl->__wcrtomb = _GBK_wcrtomb;
xrl->__mbsinit = _GBK_mbsinit;
xrl->__mb_cur_max = 2;
+ xrl->__mb_sb_limit = 128;
return (0);
}
static int
-_GBK_mbsinit(const mbstate_t *ps, locale_t loc)
+_GBK_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _GBKState *)ps)->ch == 0);
static size_t
_GBK_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps, locale_t loc)
+ mbstate_t * __restrict ps, locale_t loc __unused)
{
_GBKState *gs;
wchar_t wc;
}
static size_t
-_GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
+_GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_GBKState *gs;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isalnum.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isalnum.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isalnum.3,v 1.24 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISALNUM 3
.Os
.Sh NAME
or
.Xr isdigit 3
is true.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(preceded by their numeric values, in octal):
.Pp
.Xr isalpha 3 ,
.Xr isdigit 3 ,
.Xr iswalnum 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isalpha.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isalpha.3,v 1.18 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isalpha.3,v 1.23 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISALPHA 3
.Os
.Sh NAME
or
.Xr islower 3
is true.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(preceded by their numeric values, in octal):
.Pp
.Xr islower 3 ,
.Xr isupper 3 ,
.Xr iswalpha 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isblank.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isblank.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isblank.3,v 1.26 2009/11/11 11:31:02 roam Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISBLANK 3
.Os
.Sh NAME
.It "\&``\et''\t`` ''"
.El
.Pp
-In the "C" locale,
+In the "C" locale, a successful
.Fn isblank
-successful test is limited to these characters only.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+test is limited to these characters only.
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Sh RETURN VALUES
+The
+.Fn isblank
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
.Sh COMPATIBILITY
The
.Bx 4.4
The
.Fn iswblank
function should be used instead.
-.Sh RETURN VALUES
-The
-.Fn isblank
-function returns zero if the character tests false and
-returns non-zero if the character tests true.
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswblank 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)iscntrl.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/iscntrl.3,v 1.17 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/iscntrl.3,v 1.22 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISCNTRL 3
.Os
.Sh NAME
The
.Fn iscntrl
function tests for any control character.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(preceded by their numeric values, in octal):
.Pp
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswcntrl 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isdigit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isdigit.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isdigit.3,v 1.25 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd May 4, 2007
.Dt ISDIGIT 3
.Os
.Sh NAME
but may recognize additional characters, depending on the current locale
setting.
.Pp
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isgraph.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/locale/isgraph.3,v 1.19 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isgraph.3,v 1.25 2009/11/13 09:03:50 roam Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISGRAPH 3
.Os
.Sh NAME
function tests for any printing character except space
.Pq Ql "\ "
and other
-locale-specific, space-like characters.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+locale-specific space-like characters.
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(preceded by their numeric values, in octal):
.Pp
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswgraph 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isideogram.3,v 1.2 2004/07/04 20:55:48 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/isideogram.3,v 1.4 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISIDEOGRAM 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)islower.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/islower.3,v 1.17 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/islower.3,v 1.22 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISLOWER 3
.Os
.Sh NAME
The
.Fn islower
function tests for any lower-case letters.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 )
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(with their numeric values shown in octal):
.Pp
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswlower 3 ,
-.Xr multibyte 3 ,
.Xr tolower 3 ,
.Xr ascii 7
.Sh STANDARDS
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isphonogram.3,v 1.1 2004/03/30 07:23:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isphonogram.3,v 1.3 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISPHONOGRAM 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isprint.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isprint.3,v 1.20 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isprint.3,v 1.26 2009/11/13 09:07:33 roam Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISPRINT 3
.Os
.Sh NAME
.Fn isprint
function tests for any printing character, including space
.Pq Ql "\ " .
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(preceded by their numeric values, in octal):
.Pp
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswprint 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ispunct.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/ispunct.3,v 1.18 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/ispunct.3,v 1.23 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISPUNCT 3
.Os
.Sh NAME
character for which
.Xr isalnum 3
is true.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(preceded by their numeric values, in octal):
.Pp
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswpunct 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isrune.3,v 1.1 2004/03/30 07:23:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isrune.3,v 1.3 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISRUNE 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isspace.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isspace.3,v 1.17 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isspace.3,v 1.22 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISSPACE 3
.Os
.Sh NAME
In the "C" locale,
.Fn isspace
successful test is limited to these characters only.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/isspecial.3,v 1.1 2004/03/30 07:23:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isspecial.3,v 1.3 2009/09/04 07:44:58 des Exp $
.\"
.Dd March 30, 2004
.Dt ISSPECIAL 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isupper.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isupper.3,v 1.18 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isupper.3,v 1.23 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISUPPER 3
.Os
.Sh NAME
The
.Fn isupper
function tests for any upper-case letter.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
In the ASCII character set, this includes the following characters
(preceded by their numeric values, in octal):
.Pp
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswupper 3 ,
-.Xr multibyte 3 ,
.Xr toupper 3 ,
.Xr ascii 7
.Sh STANDARDS
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isalnum.3 5.2 (Berkeley) 6/29/91
-.\" $FreeBSD: src/lib/libc/locale/iswalnum.3,v 1.5 2002/11/29 17:35:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/iswalnum.3,v 1.6 2007/01/09 00:28:00 imp Exp $
.\"
.Dd October 3, 2002
.Dt ISWALNUM 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)isxdigit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/isxdigit.3,v 1.20 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/isxdigit.3,v 1.25 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt ISXDIGIT 3
.Os
.Sh NAME
but may recognize additional characters,
depending on the current locale setting.
.Pp
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The value of the argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Sh RETURN VALUES
.Xr ctype 3 ,
.Xr isalnum_l 3 ,
.Xr iswxdigit 3 ,
-.Xr multibyte 3 ,
.Xr ascii 7
.Sh STANDARDS
The
* 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.
static char sccsid[] = "@(#)localeconv.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.13 2003/06/26 10:46:16 phantom Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/localeconv.c,v 1.14 2007/12/12 07:43:23 phantom Exp $");
#include "xlocale_private.h"
.\" 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.
.\"
.\" From @(#)setlocale.3 8.1 (Berkeley) 6/9/93
.\" From FreeBSD: src/lib/libc/locale/setlocale.3,v 1.28 2003/11/15 02:26:04 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/localeconv.3,v 1.2 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/localeconv.3,v 1.3 2007/01/09 00:28:00 imp Exp $
.\"
.Dd November 21, 2003
.Dt LOCALECONV 3
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/mblen.3,v 1.5 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/mblen.3,v 1.6 2007/01/09 00:28:00 imp Exp $
.\"
.Dd April 11, 2004
.Dt MBLEN 3
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/lib/libc/locale/mblocal.h,v 1.4 2004/10/17 06:51:50 tjr Exp $
+ * $FreeBSD: src/lib/libc/locale/mblocal.h,v 1.7 2008/01/21 23:48:12 ache Exp $
*/
#ifndef _MBLOCAL_H_
#define _MBLOCAL_H_
+#include <runetype.h>
+
/*
- * Conversion functions for "NONE"/C/POSIX encoding.
+ * Rune initialization function prototypes.
*/
-extern size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
- size_t, mbstate_t * __restrict, locale_t);
-extern int _none_mbsinit(const mbstate_t *, locale_t);
-extern size_t _none_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict, locale_t);
-extern size_t _none_wcrtomb(char * __restrict, wchar_t,
- mbstate_t * __restrict, locale_t);
-extern size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict, locale_t);
+__private_extern__ int _none_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _ascii_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _UTF2_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _UTF8_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _EUC_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _GB18030_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _GB2312_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _GBK_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _BIG5_init(struct __xlocale_st_runelocale *);
+__private_extern__ int _MSKanji_init(struct __xlocale_st_runelocale *);
+
+__private_extern__ size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
+__private_extern__ int _none_mbsinit(const mbstate_t *, locale_t);
+__private_extern__ size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps __unused, locale_t);
+__private_extern__ size_t _none_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
+__private_extern__ size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict, locale_t);
extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
size_t, size_t, mbstate_t * __restrict, locale_t);
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/mbsrtowcs.3,v 1.5 2004/07/21 10:54:57 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/mbsrtowcs.3,v 1.6 2005/01/11 20:50:49 ru Exp $
.Dd July 21, 2004
.Dt MBSRTOWCS 3
.Os
.Fn mbsrtowcs ,
except that conversion stops after reading at most
.Fa nms
-bytes from the buffer pointed to by
+bytes from the buffer pointed to by
.Fa src .
.Pp
While the
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/mbstowcs.c,v 1.11 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/mbstowcs.c,v 1.12 2009/01/15 18:53:52 rdivacky Exp $");
#include "xlocale_private.h"
{
static const mbstate_t initial;
mbstate_t mbs;
+ const char *sp;
NORMALIZE_LOCALE(loc);
mbs = initial;
- return (loc->__lc_ctype->__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs, loc));
+ sp = s;
+ return (loc->__lc_ctype->__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs, loc));
}
size_t
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/mbstowcs.3,v 1.4 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/mbstowcs.3,v 1.5 2007/01/09 00:28:00 imp Exp $
.\"
.Dd April 8, 2004
.Dt MBSTOWCS 3
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/mbtowc.3,v 1.4 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/mbtowc.3,v 1.5 2007/01/09 00:28:00 imp Exp $
.\"
.Dd April 11, 2004
.Dt MBTOWC 3
static char sccsid[] = "@(#)mskanji.c 1.0 (Phase One) 5/5/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/mskanji.c,v 1.16 2004/05/14 15:40:47 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/mskanji.c,v 1.18 2007/10/13 16:28:22 ache Exp $");
#include "xlocale_private.h"
-#include <sys/param.h>
+#include <sys/types.h>
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
-__private_extern__ int _MSKanji_init(struct __xlocale_st_runelocale *);
-static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _MSKanji_mbsinit(const mbstate_t *, locale_t);
-static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
xrl->__wcrtomb = _MSKanji_wcrtomb;
xrl->__mbsinit = _MSKanji_mbsinit;
xrl->__mb_cur_max = 2;
+ xrl->__mb_sb_limit = 256;
return (0);
}
static int
-_MSKanji_mbsinit(const mbstate_t *ps, locale_t loc)
+_MSKanji_mbsinit(const mbstate_t *ps, locale_t loc __unused)
{
return (ps == NULL || ((const _MSKanjiState *)ps)->ch == 0);
static size_t
_MSKanji_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps, locale_t loc)
+ mbstate_t * __restrict ps, locale_t loc __unused)
{
_MSKanjiState *ms;
wchar_t wc;
}
static size_t
-_MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc)
+_MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc __unused)
{
_MSKanjiState *ms;
int len, i;
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/nextwctype.3,v 1.1 2004/07/08 06:43:37 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/nextwctype.3,v 1.3 2005/07/21 10:27:45 tjr Exp $
.\"
-.Dd July 8, 2004
+.Dd July 21, 2005
.Dt NEXTWCTYPE 3
.Os
.Sh NAME
.Sh SYNOPSIS
.In wctype.h
.Ft wint_t
-.Fo nextwctype
-.Fa "wint_t ch" "wctype_t wct"
-.Fc
+.Fn nextwctype "wint_t ch" "wctype_t wct"
.In xlocale.h
.Ft wint_t
-.Fo nextwctype_l
-.Fa "wint_t ch" "wctype_t wct" "locale_t loc"
-.Fc
+.Fn nextwctype_l "wint_t ch" "wctype_t wct" "locale_t loc"
.Sh DESCRIPTION
The
.Fn nextwctype
While the
.Fn nextwctype
function uses the current locale, the
-.Fn nextwctype_l
+ .Fn nextwctype_l
function may be passed a locale directly. See
.Xr xlocale 3
for more information.
.Sh RETURN VALUES
The
.Fn nextwctype
-functions returns the next character, or \-1 if there are no more.
+function returns the next character, or \-1 if there are no more.
+.Sh COMPATIBILITY
+This function is a non-standard
+.Fx
+extension and should not be used where the standard
+.Fn iswctype
+function would suffice.
.Sh SEE ALSO
.Xr wctype 3 ,
.Xr xlocale 3
+.Sh HISTORY
+The
+.Fn nextwctype
+function appeared in
+.Fx 5.4 .
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/nl_langinfo.3,v 1.5 2003/09/08 19:57:14 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/nl_langinfo.3,v 1.7 2009/11/16 14:33:31 brueffer Exp $
.\"
.Dd May 3, 2001
.Dt NL_LANGINFO 3
category
.Dv LC_ALL ,
may overwrite the buffer pointed to by the return value.
+.Sh RETURN VALUES
+In a locale where langinfo data is not defined,
+.Fn nl_langinfo
+returns a pointer to the corresponding string in the
+.Tn POSIX
+locale.
+In all locales,
+.Fn nl_langinfo
+returns a pointer to an empty string if
+.Fa item
+contains an invalid setting.
.Sh EXAMPLES
For example:
.Pp
function may be passed a locale directly. See
.Xr xlocale 3
for more information.
-.Sh RETURN VALUES
-In a locale where langinfo data is not defined,
-.Fn nl_langinfo
-returns a pointer to the corresponding string in the
-.Tn POSIX
-locale.
-In all locales,
-.Fn nl_langinfo
-returns a pointer to an empty string if
-.Fa item
-contains an invalid setting.
.Sh SEE ALSO
.Xr setlocale 3 ,
.Xr xlocale 3
* 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.
static char sccsid[] = "@(#)none.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/none.c,v 1.12 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/none.c,v 1.15 2007/10/13 16:28:22 ache Exp $");
#include "xlocale_private.h"
#include <wchar.h>
#include "mblocal.h"
-__private_extern__ int _none_init(struct __xlocale_st_runelocale *);
-__private_extern__ size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
-__private_extern__ int _none_mbsinit(const mbstate_t *, locale_t);
-__private_extern__ size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
- const char ** __restrict src, size_t nms, size_t len,
- mbstate_t * __restrict ps __unused, locale_t);
-__private_extern__ size_t _none_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
-__private_extern__ size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict, locale_t);
+/* setup defaults */
+
+int __mb_cur_max = 1;
+int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */
__private_extern__ int
_none_init(struct __xlocale_st_runelocale *xrl)
xrl->__wcrtomb = _none_wcrtomb;
xrl->__wcsnrtombs = _none_wcsnrtombs;
xrl->__mb_cur_max = 1;
+ xrl->__mb_sb_limit = 256;
return(0);
}
__private_extern__ int
-_none_mbsinit(const mbstate_t *ps __unused, locale_t loc)
+_none_mbsinit(const mbstate_t *ps __unused, locale_t loc __unused)
{
/*
__private_extern__ size_t
_none_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
- mbstate_t * __restrict ps __unused, locale_t loc)
+ mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
if (s == NULL)
__private_extern__ size_t
_none_wcrtomb(char * __restrict s, wchar_t wc,
- mbstate_t * __restrict ps __unused, locale_t loc)
+ mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
if (s == NULL)
__private_extern__ size_t
_none_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
- size_t nms, size_t len, mbstate_t * __restrict ps __unused, locale_t loc)
+ size_t nms, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
const char *s;
size_t nchr;
__private_extern__ size_t
_none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
- size_t nwc, size_t len, mbstate_t * __restrict ps __unused, locale_t loc)
+ size_t nwc, size_t len, mbstate_t * __restrict ps __unused, locale_t loc __unused)
{
const wchar_t *s;
size_t nchr;
#include "namespace.h"
#include <arpa/inet.h>
#include <errno.h>
-#endif /* !RUNEOFF32 */
#include <runetype.h>
+#else
+#include "runetype.h"
+#endif /* !RUNEOFF32 */
#include <stdio.h>
#ifndef RUNEOFF32
#include <string.h>
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/runetype.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/runetype.c,v 1.14 2007/01/09 00:28:00 imp Exp $");
#include "xlocale_private.h"
+#include <ctype.h>
#include <stdio.h>
#include <runetype.h>
unsigned long
-___runetype_l(c, loc)
- __ct_rune_t c;
- locale_t loc;
+___runetype_l(__ct_rune_t c, locale_t loc)
{
size_t lim;
_RuneRange *rr;
}
unsigned long
-___runetype(c)
- __ct_rune_t c;
+___runetype(__ct_rune_t c)
{
return ___runetype_l(c, __current_locale());
}
* 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.
static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/setlocale.c,v 1.50 2004/01/31 19:15:32 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/setlocale.c,v 1.51 2007/01/09 00:28:00 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)setlocale.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/locale/setlocale.3,v 1.33 2004/10/17 06:51:50 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/setlocale.3,v 1.35 2007/01/09 00:28:00 imp Exp $
.\"
.Dd November 21, 2003
.Dt SETLOCALE 3
and
.Fa locale
makes no sense.
-.Sh ERRORS
-No errors are defined.
.Sh FILES
.Bl -tag -width /usr/share/locale/locale/category -compact
.It Pa $PATH_LOCALE/ Ns Em locale/category
and the category
.Em category .
.El
+.Sh ERRORS
+No errors are defined.
.Sh SEE ALSO
.Xr colldef 1 ,
.Xr mklocale 1 ,
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/setrunelocale.c,v 1.44 2004/10/18 02:06:18 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/setrunelocale.c,v 1.51 2008/01/23 03:05:35 ache Exp $");
#include "xlocale_private.h"
#include "mblocal.h"
#include "setlocale.h"
-extern int _none_init(struct __xlocale_st_runelocale *);
-extern int _UTF8_init(struct __xlocale_st_runelocale *);
-extern int _EUC_init(struct __xlocale_st_runelocale *);
-extern int _GB18030_init(struct __xlocale_st_runelocale *);
-extern int _GB2312_init(struct __xlocale_st_runelocale *);
-extern int _GBK_init(struct __xlocale_st_runelocale *);
-extern int _BIG5_init(struct __xlocale_st_runelocale *);
-extern int _MSKanji_init(struct __xlocale_st_runelocale *);
-extern int _UTF2_init(struct __xlocale_st_runelocale *); /* deprecated */
extern struct __xlocale_st_runelocale *_Read_RuneMagi(FILE *);
-#ifdef LEGACY_RUNE_APIS
+#ifdef UNIFDEF_LEGACY_RUNE_APIS
/* depreciated interfaces */
rune_t sgetrune(const char *, size_t, char const **);
int sputrune(rune_t, char *, size_t, char **);
-#endif /* LEGACY_RUNE_APIS */
+#endif /* UNIFDEF_LEGACY_RUNE_APIS */
__private_extern__ int
__setrunelocale(const char *encoding, locale_t loc)
int saverr, ret;
static struct __xlocale_st_runelocale *CachedRuneLocale;
extern int __mb_cur_max;
+ extern int __mb_sb_limit;
static pthread_lock_t cache_lock = LOCK_INITIALIZER;
/*
if (loc == &__global_locale) {
_CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale;
__mb_cur_max = loc->__lc_ctype->__mb_cur_max;
+ __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
}
return (0);
}
if (loc == &__global_locale) {
_CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale;
__mb_cur_max = loc->__lc_ctype->__mb_cur_max;
+ __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
}
UNLOCK(cache_lock);
return (0);
rl = &xrl->_CurrentRuneLocale;
-#ifdef LEGACY_RUNE_APIS
+#ifdef UNIFDEF_LEGACY_RUNE_APIS
/* provide backwards compatibility (depreciated interface) */
rl->__sputrune = sputrune;
rl->__sgetrune = sgetrune;
-#else /* LEGACY_RUNE_APIS */
+#else /* UNIFDEF_LEGACY_RUNE_APIS */
rl->__sputrune = NULL;
rl->__sgetrune = NULL;
-#endif /* LEGACY_RUNE_APIS */
+#endif /* UNIFDEF_LEGACY_RUNE_APIS */
if (strcmp(rl->__encoding, "NONE") == 0)
ret = _none_init(xrl);
+ else if (strcmp(rl->__encoding, "ASCII") == 0)
+ ret = _ascii_init(xrl);
else if (strcmp(rl->__encoding, "UTF-8") == 0)
ret = _UTF8_init(xrl);
else if (strcmp(rl->__encoding, "EUC") == 0)
ret = _EUC_init(xrl);
- else if (strcmp(rl->__encoding, "GB18030") == 0)
+ else if (strcmp(rl->__encoding, "GB18030") == 0)
ret = _GB18030_init(xrl);
else if (strcmp(rl->__encoding, "GB2312") == 0)
ret = _GB2312_init(xrl);
ret = _UTF2_init(xrl);
else
ret = EFTYPE;
+
if (ret == 0) {
(void)strcpy(xrl->__ctype_encoding, encoding);
XL_RELEASE(loc->__lc_ctype);
if (loc == &__global_locale) {
_CurrentRuneLocale = &loc->__lc_ctype->_CurrentRuneLocale;
__mb_cur_max = loc->__lc_ctype->__mb_cur_max;
+ __mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
}
LOCK(cache_lock);
XL_RELEASE(CachedRuneLocale);
return (ret);
}
-#ifdef LEGACY_RUNE_APIS
+#ifdef UNIFDEF_LEGACY_RUNE_APIS
int
setrunelocale(const char *encoding)
{
XL_UNLOCK(&__global_locale);
return ret;
}
-#endif /* LEGACY_RUNE_APIS */
+#endif /* UNIFDEF_LEGACY_RUNE_APIS */
__private_extern__ int
__wrap_setrunelocale(const char *locale, locale_t loc)
* 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.
static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/27/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/table.c,v 1.26 2004/10/17 06:51:50 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/table.c,v 1.28 2007/01/09 00:28:00 imp Exp $");
#include "xlocale_private.h"
#include "mblocal.h"
/* _DefaultRuneLocale is depreciated; _DefaultRuneXLocale is used instead */
-_RuneLocale _DefaultRuneLocale = {
+_RuneLocale _DefaultRuneLocale __attribute__((section("__DATA,__constrw"))) = {
_RUNE_MAGIC_A,
"NONE",
NULL,
},
};
-__private_extern__ struct __xlocale_st_runelocale _DefaultRuneXLocale = {
+__private_extern__ struct __xlocale_st_runelocale _DefaultRuneXLocale __attribute__((section("__DATA,__constrw"))) = {
0,
XPERMANENT,
"C",
1,
+ 256,
_none_mbrtowc,
_none_mbsinit,
_none_mbsnrtowcs,
};
_RuneLocale *_CurrentRuneLocale = &_DefaultRuneXLocale._CurrentRuneLocale;
-
-int __mb_cur_max = 1;
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/tolower.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
-
+__FBSDID("$FreeBSD: src/lib/libc/locale/tolower.c,v 1.13 2007/01/09 00:28:01 imp Exp $");
+
#include "xlocale_private.h"
+#include <ctype.h>
#include <stdio.h>
#include <runetype.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)tolower.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/tolower.3,v 1.16 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/tolower.3,v 1.21 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt TOLOWER 3
.Os
.Sh NAME
.Fn tolower
function converts an upper-case letter to the corresponding lower-case
letter.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr islower 3 ,
-.Xr multibyte 3 ,
.Xr towlower 3 ,
.Xr xlocale 3
.Sh STANDARDS
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/toupper.c,v 1.11 2004/07/29 06:16:19 tjr Exp $");
-
+__FBSDID("$FreeBSD: src/lib/libc/locale/toupper.c,v 1.13 2007/01/09 00:28:01 imp Exp $");
+
#include "xlocale_private.h"
+#include <ctype.h>
#include <stdio.h>
#include <runetype.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)toupper.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/toupper.3,v 1.16 2004/08/21 07:37:08 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/toupper.3,v 1.21 2009/09/04 07:44:58 des Exp $
.\"
-.Dd August 21, 2004
+.Dd July 17, 2005
.Dt TOUPPER 3
.Os
.Sh NAME
.Fn toupper
function converts a lower-case letter to the corresponding
upper-case letter.
-For single C
-.Va char Ns s
-locales (see
-.Xr multibyte 3 ) ,
-the value of the argument is
-representable as an
-.Li unsigned char
+The argument must be representable as an
+.Vt "unsigned char"
or the value of
.Dv EOF .
.Pp
.Sh SEE ALSO
.Xr ctype 3 ,
.Xr isupper 3 ,
-.Xr multibyte 3 ,
.Xr towupper 3 ,
.Xr xlocale 3
.Sh STANDARDS
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)tolower.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/towlower.3,v 1.5 2002/11/29 17:35:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/towlower.3,v 1.6 2007/01/09 00:28:01 imp Exp $
.\"
.Dd October 3, 2002
.Dt TOWLOWER 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)toupper.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/locale/towupper.3,v 1.2 2002/11/29 17:35:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/towupper.3,v 1.3 2007/01/09 00:28:01 imp Exp $
.\"
.Dd October 3, 2002
.Dt TOWUPPER 3
*/
#include <sys/param.h>
-/* dumb down UTF-8 to do UTF2 */
-__FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.11 2004/07/27 06:29:48 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.16 2007/10/15 09:51:30 ache Exp $");
#include "xlocale_private.h"
#define UTF2_MB_CUR_MAX 3
-static size_t _UTF2_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _UTF2_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _UTF2_mbsinit(const mbstate_t *, locale_t);
-static size_t _UTF2_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict, locale_t);
-static size_t _UTF2_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+static size_t _UTF2_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict, locale_t);
+static size_t _UTF2_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
static size_t _UTF2_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict, locale_t);
+ size_t, size_t, mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
xrl->__mbsnrtowcs = _UTF2_mbsnrtowcs;
xrl->__wcsnrtombs = _UTF2_wcsnrtombs;
xrl->__mb_cur_max = UTF2_MB_CUR_MAX;
+ /*
+ * UCS-4 encoding used as the internal representation, so
+ * slots 0x0080-0x00FF are occuped and must be excluded
+ * from the single byte ctype by setting the limit.
+ */
+ xrl->__mb_sb_limit = 128;
return (0);
}
us = (_UTF2State *)ps;
- if (us->want < 0 || us->want > 3) {
+ if (us->want < 0 || us->want > 6) {
errno = EINVAL;
return ((size_t)-1);
}
*dst = *s;
} else if (len > (size_t)UTF2_MB_CUR_MAX) {
/* Enough space to translate in-place. */
- if ((nb = (int)_UTF2_wcrtomb(dst, *s, ps, loc)) < 0) {
+ if ((nb = _UTF2_wcrtomb(dst, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
/*
* May not be enough space; use temp. buffer.
*/
- if ((nb = (int)_UTF2_wcrtomb(buf, *s, ps, loc)) < 0) {
+ if ((nb = _UTF2_wcrtomb(buf, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
*/
#include <sys/param.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.11 2004/07/27 06:29:48 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/utf8.c,v 1.16 2007/10/15 09:51:30 ache Exp $");
#include "xlocale_private.h"
#define UTF8_MB_CUR_MAX 6
-static size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict, locale_t);
+static size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, locale_t);
static int _UTF8_mbsinit(const mbstate_t *, locale_t);
-static size_t _UTF8_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict, locale_t);
-static size_t _UTF8_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
+static size_t _UTF8_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict, locale_t);
+static size_t _UTF8_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict, locale_t);
static size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict, locale_t);
+ size_t, size_t, mbstate_t * __restrict, locale_t);
typedef struct {
wchar_t ch;
xrl->__mbsnrtowcs = _UTF8_mbsnrtowcs;
xrl->__wcsnrtombs = _UTF8_wcsnrtombs;
xrl->__mb_cur_max = UTF8_MB_CUR_MAX;
+ /*
+ * UCS-4 encoding used as the internal representation, so
+ * slots 0x0080-0x00FF are occuped and must be excluded
+ * from the single byte ctype by setting the limit.
+ */
+ xrl->__mb_sb_limit = 128;
return (0);
}
mask = 0x03;
want = 5;
lbound = 0x200000;
- } else if ((ch & 0xfc) == 0xfc) {
+ } else if ((ch & 0xfe) == 0xfc) {
mask = 0x01;
want = 6;
lbound = 0x4000000;
*dst = *s;
} else if (len > (size_t)UTF8_MB_CUR_MAX) {
/* Enough space to translate in-place. */
- if ((nb = (int)_UTF8_wcrtomb(dst, *s, ps, loc)) < 0) {
+ if ((nb = _UTF8_wcrtomb(dst, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
/*
* May not be enough space; use temp. buffer.
*/
- if ((nb = (int)_UTF8_wcrtomb(buf, *s, ps, loc)) < 0) {
+ if ((nb = _UTF8_wcrtomb(buf, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.6 2009/01/15 20:45:59 rdivacky Exp $");
#include "xlocale_private.h"
{
static const mbstate_t initial;
mbstate_t mbs;
- char *dst, *dstp, *sformat;
+ char *dst, *sformat;
+ const char *dstp;
+ const wchar_t *formatp;
size_t n, sflen;
int sverrno;
* for strftime(), which only handles single-byte characters.
*/
mbs = initial;
- sflen = wcsrtombs_l(NULL, &format, 0, &mbs, loc);
+ formatp = format;
+ sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, loc);
if (sflen == (size_t)-1)
goto error;
if ((sformat = malloc(sflen + 1)) == NULL)
goto error;
mbs = initial;
- wcsrtombs_l(sformat, &format, sflen + 1, &mbs, loc);
+ wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, loc);
/*
* Allocate memory for longest multibyte sequence that will fit
goto error;
dstp = dst;
mbs = initial;
- n = mbsrtowcs_l(wcs, (const char **)&dstp, maxsize, &mbs, loc);
+ n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, loc);
if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
goto error;
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcsnrtombs.c,v 1.2 2004/07/22 02:57:29 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcsnrtombs.c,v 1.3 2005/02/12 08:45:12 stefanf Exp $");
#include "xlocale_private.h"
while (len > 0 && nwc-- > 0) {
if (len > (size_t)mb_cur_max) {
/* Enough space to translate in-place. */
- if ((nb = (int)__wcrtomb(dst, *s, ps, loc)) < 0) {
+ if ((nb = __wcrtomb(dst, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
* character is too long for the buffer.
*/
mbsbak = *ps;
- if ((nb = (int)__wcrtomb(buf, *s, ps, loc)) < 0) {
+ if ((nb = __wcrtomb(buf, *s, ps, loc)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoimax.c,v 1.2 2003/01/01 18:48:43 schweikh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoimax.c,v 1.3 2007/01/09 00:28:01 imp Exp $");
#include "xlocale_private.h"
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstol.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstol.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include "xlocale_private.h"
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoll.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoll.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include "xlocale_private.h"
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstombs.c,v 1.10 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstombs.c,v 1.11 2009/01/15 18:53:52 rdivacky Exp $");
#include "xlocale_private.h"
{
static const mbstate_t initial;
mbstate_t mbs;
+ const wchar_t *pwcsp;
NORMALIZE_LOCALE(loc);
mbs = initial;
- return (loc->__lc_ctype->__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs, loc));
+ pwcsp = pwcs;
+ return (loc->__lc_ctype->__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs, loc));
}
size_t
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/wcstombs.3,v 1.4 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/wcstombs.3,v 1.5 2007/01/09 00:28:01 imp Exp $
.\"
.Dd April 8, 2004
.Dt WCSTOMBS 3
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoul.c,v 1.1 2002/09/08 13:27:26 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoul.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include "xlocale_private.h"
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoull.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoull.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include "xlocale_private.h"
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoumax.c,v 1.1 2002/09/22 08:06:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcstoumax.c,v 1.2 2007/01/09 00:28:01 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\"
.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
-.\" $FreeBSD: src/lib/libc/locale/wctomb.3,v 1.3 2004/07/05 06:36:36 ru Exp $
+.\" $FreeBSD: src/lib/libc/locale/wctomb.3,v 1.4 2007/01/09 00:28:01 imp Exp $
.\"
.Dd April 8, 2004
.Dt WCTOMB 3
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wctype.c,v 1.3 2004/03/27 08:59:21 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wctype.c,v 1.4 2008/03/17 18:22:23 antoine Exp $");
#include "xlocale_private.h"
#include <wctype.h>
#include <limits.h>
-static struct {
- const char *name;
- wctype_t mask;
-} props[] = {
- { "alnum", _CTYPE_A|_CTYPE_D },
- { "alpha", _CTYPE_A },
- { "blank", _CTYPE_B },
- { "cntrl", _CTYPE_C },
- { "digit", _CTYPE_D },
- { "graph", _CTYPE_G },
- { "lower", _CTYPE_L },
- { "print", _CTYPE_R },
- { "punct", _CTYPE_P },
- { "space", _CTYPE_S },
- { "upper", _CTYPE_U },
- { "xdigit", _CTYPE_X },
- { "ideogram", _CTYPE_I }, /* BSD extension */
- { "special", _CTYPE_T }, /* BSD extension */
- { "phonogram", _CTYPE_Q }, /* BSD extension */
- { "rune", 0xFFFFFFF0L }, /* BSD extension */
- { NULL, 0UL }, /* Default */
-};
-
wctype_t
wctype_l(const char *property, locale_t loc)
{
- int i;
_RuneLocale *rl;
+ static const struct {
+ const char *name;
+ wctype_t mask;
+ } props[] = {
+ { "alnum", _CTYPE_A|_CTYPE_D },
+ { "alpha", _CTYPE_A },
+ { "blank", _CTYPE_B },
+ { "cntrl", _CTYPE_C },
+ { "digit", _CTYPE_D },
+ { "graph", _CTYPE_G },
+ { "lower", _CTYPE_L },
+ { "print", _CTYPE_R },
+ { "punct", _CTYPE_P },
+ { "space", _CTYPE_S },
+ { "upper", _CTYPE_U },
+ { "xdigit", _CTYPE_X },
+ { "ideogram", _CTYPE_I }, /* BSD extension */
+ { "special", _CTYPE_T }, /* BSD extension */
+ { "phonogram", _CTYPE_Q }, /* BSD extension */
+ { "rune", 0xFFFFFF00L }, /* BSD extension */
+ { NULL, 0UL }, /* Default */
+ };
+ int i;
i = 0;
while (props[i].name != NULL && strcmp(props[i].name, property) != 0)
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/locale/wctype.3,v 1.5 2004/03/27 08:59:21 tjr Exp $
+.\" $FreeBSD: src/lib/libc/locale/wctype.3,v 1.7 2006/10/13 16:11:12 ru Exp $
.\"
.Dd March 27, 2004
.Dt WCTYPE 3
.Ed
.Sh SEE ALSO
.Xr ctype 3 ,
+.Xr nextwctype 3 ,
.Xr xlocale 3
.Sh STANDARDS
The
.St -p1003.1-2001 .
The
.Dq Li ideogram ,
-.Dq Li phonogram
+.Dq Li phonogram ,
.Dq Li special ,
and
.Dq Li rune
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/locale/wcwidth.c,v 1.7 2004/08/12 12:19:11 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/locale/wcwidth.c,v 1.8 2007/01/09 00:28:01 imp Exp $");
#include "xlocale_private.h"
loc->__numeric_fp_cvt = LC_NUMERIC_FP_SAME_LOCALE;
return loc;
} else {
- loc->__lc_numeric_loc = newlocale(LC_CTYPE_MASK, numeric, &__c_locale);
+ loc->__lc_numeric_loc = newlocale(LC_CTYPE_MASK, numeric, (locale_t)&__c_locale);
if (loc->__lc_numeric_loc) {
loc->__numeric_fp_cvt = LC_NUMERIC_FP_USE_LOCALE;
return loc->__lc_numeric_loc;
__STRUCT_COMMON
char __ctype_encoding[ENCODING_LEN + 1];
int __mb_cur_max;
+ int __mb_sb_limit;
size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict,
size_t, __darwin_mbstate_t * __restrict, struct _xlocale *);
int (*__mbsinit)(const __darwin_mbstate_t *, struct _xlocale *);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)inet.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/net/inet.3,v 1.29 2004/07/02 23:52:11 ru Exp $
+.\" $FreeBSD: src/lib/libc/net/inet.3,v 1.36 2007/06/14 07:13:28 delphij Exp $
.\"
-.Dd June 14, 2004
+.Dd June 14, 2007
.Dt INET 3
.Os
.Sh NAME
.Nm inet_addr ,
.Nm inet_network ,
.Nm inet_ntoa ,
+.Nm inet_ntoa_r ,
.Nm inet_ntop ,
.Nm inet_pton ,
.Nm inet_makeaddr ,
.Fn inet_network "const char *cp"
.Ft char *
.Fn inet_ntoa "struct in_addr in"
+.Ft char *
+.Fo inet_ntoa_r
+.Fa "struct in_addr in"
+.Fa "char *buf"
+.Fa "socklen_t size"
+.Fc
.Ft const char *
.Fo inet_ntop
.Fa "int af"
.Ft struct in_addr
or some other internal binary representation, in network byte order).
It returns 1 if the address was valid for the specified address family, or
-0 if the address wasn't parseable in the specified address family, or -1
+0 if the address was not parseable in the specified address family, or -1
if some system error occurred (in which case
.Va errno
will have been set).
.Fa size
argument specifies the size, in bytes, of the buffer
.Fa *dst .
+.Dv INET_ADDRSTRLEN
+and
+.Dv INET6_ADDRSTRLEN
+define the maximum size required to convert an address of the respective
+type.
It returns NULL if a system error occurs (in which case,
.Va errno
will have been set), or it returns a pointer to the destination string.
.Ql .\&
notation.
The routine
+.Fn inet_ntoa_r
+is the reentrant version of
+.Fn inet_ntoa .
+The routine
.Fn inet_makeaddr
takes an Internet network number and a local
network address and constructs an Internet address
in the C language (i.e., a leading 0x or 0X implies
hexadecimal; otherwise, a leading 0 implies octal;
otherwise, the number is interpreted as decimal).
-.Pp
-The
-.Fn inet_aton
-and
-.Fn inet_ntoa
-functions are semi-deprecated in favor of the
-.Xr addr2ascii 3
-family.
-However, since those functions are not yet widely implemented,
-portable programs cannot rely on their presence and will continue
-to use the
-.Xr inet 3
-functions for some time.
.Sh DIAGNOSTICS
The constant
.Dv INADDR_NONE
family address.
.El
.Sh SEE ALSO
-.Xr addr2ascii 3 ,
.Xr byteorder 3 ,
+.Xr getaddrinfo 3 ,
.Xr gethostbyname 3 ,
+.Xr getnameinfo 3 ,
.Xr getnetent 3 ,
.Xr inet_net 3 ,
.Xr hosts 5 ,
.Fn inet_ntoa
resides in a static memory area.
.Pp
-Inet_addr should return a
+The
+.Fn inet_addr
+function should return a
.Fa struct in_addr .
---- inet.3 2004-11-25 11:38:29.000000000 -0800
-+++ inet.3.edit 2006-07-12 11:23:50.000000000 -0700
-@@ -36,50 +36,67 @@
+--- inet.3.bsdnew 2009-11-10 16:23:10.000000000 -0800
++++ inet.3 2009-11-10 16:35:18.000000000 -0800
+@@ -32,32 +32,51 @@
.Dt INET 3
.Os
.Sh NAME
+.Nm inet_netof ,
.Nm inet_network ,
.Nm inet_ntoa ,
+ .Nm inet_ntoa_r ,
.Nm inet_ntop ,
-.Nm inet_pton ,
-.Nm inet_makeaddr ,
+.Fa "const char *cp"
+.Fa "struct in_addr *pin"
+.Fc
- .Ft in_addr_t
--.Fn inet_addr "const char *cp"
++.Ft in_addr_t
+.Fo inet_lnaof
+.Fa "struct in_addr in"
+.Fc
+.Fa "in_addr_t lna"
+.Fc
.Ft in_addr_t
--.Fn inet_network "const char *cp"
+-.Fn inet_addr "const char *cp"
+.Fo inet_netof
+.Fa "struct in_addr in"
+.Fc
-+.Ft in_addr_t
+ .Ft in_addr_t
+-.Fn inet_network "const char *cp"
+.Fo inet_network
+.Fa "const char *cp"
+.Fc
+.Fo inet_ntoa
+.Fa "struct in_addr in"
+.Fc
- .Ft const char *
- .Fo inet_ntop
- .Fa "int af"
--.Fa "const void * restrict src"
--.Fa "char * restrict dst"
-+.Fa "const void *restrict src"
-+.Fa "char *restrict dst"
+ .Ft char *
+ .Fo inet_ntoa_r
+ .Fa "struct in_addr in"
+@@ -72,13 +91,11 @@
.Fa "socklen_t size"
.Fc
.Ft int
-.Fn inet_netof "struct in_addr in"
+.Fo inet_pton
+.Fa "int af"
-+.Fa "const char *restrict src"
-+.Fa "void *restrict dst"
++.Fa "const char * restrict src"
++.Fa "void * restrict dst"
+.Fc
.Sh DESCRIPTION
The routines
.Fn inet_aton ,
--.Fn inet_addr
-+.Fn inet_addr ,
- and
- .Fn inet_network
- interpret character strings representing
-@@ -242,9 +259,6 @@
+@@ -241,9 +258,6 @@ The
.Fn inet_ntop
call fails if:
.Bl -tag -width Er
.It Bq Er EAFNOSUPPORT
.Fa *src
was not an
-@@ -252,13 +266,24 @@
+@@ -251,7 +265,17 @@ was not an
or
.Dv AF_INET6
family address.
+.Pp
+These include files are necessary for all functions.
.Sh SEE ALSO
- .Xr addr2ascii 3 ,
.Xr byteorder 3 ,
- .Xr gethostbyname 3 ,
- .Xr getnetent 3 ,
- .Xr inet_net 3 ,
-+.Xr compat 5 ,
- .Xr hosts 5 ,
- .Xr networks 5
- .Rs
+ .Xr getaddrinfo 3 ,
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.1 2005/04/27 05:00:53 sra Exp $";
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_pton.c,v 1.3 2007/06/03 17:20:26 ume Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_pton.c,v 1.4 2008/12/14 19:39:53 ume Exp $");
#include "port_before.h"
assert(n >= 0 && n <= 9);
bits *= 10;
bits += n;
+ if (bits > 32)
+ goto enoent;
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
if (ch != '\0')
goto enoent;
- if (bits > 32)
- goto emsgsize;
}
/* Firey death and destruction unless we prefetched EOS. */
---- inet_net_pton.c.orig 2008-09-01 22:59:17.000000000 -0700
-+++ inet_net_pton.c 2008-09-01 23:00:34.000000000 -0700
+--- inet_net_pton.c.bsdnew 2009-11-10 16:23:10.000000000 -0800
++++ inet_net_pton.c 2009-11-10 16:23:10.000000000 -0800
@@ -18,6 +18,10 @@
#if defined(LIBC_SCCS) && !defined(lint)
- static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.1 2005/04/27 05:00:53 sra Exp $";
+ static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
#endif
+
+/* the algorithms only can deal with ASCII, so we optimize for it */
+#define USE_ASCII
+
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_pton.c,v 1.3 2007/06/03 17:20:26 ume Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_pton.c,v 1.4 2008/12/14 19:39:53 ume Exp $");
-@@ -135,11 +139,11 @@ inet_net_pton_ipv4(const char *src, u_ch
- assert(n >= 0 && n <= 9);
- bits *= 10;
- bits += n;
-+ if (bits > 32)
-+ goto emsgsize;
- } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
- if (ch != '\0')
- goto enoent;
-- if (bits > 32)
-- goto emsgsize;
- }
-
- /* Firey death and destruction unless we prefetched EOS. */
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)linkaddr.3 8.1 (Berkeley) 7/28/93
-.\" $FreeBSD: src/lib/libc/net/linkaddr.3,v 1.14 2004/07/03 22:30:08 ru Exp $
+.\" $FreeBSD: src/lib/libc/net/linkaddr.3,v 1.16 2007/02/28 21:18:38 bms Exp $
.\"
-.Dd June 17, 1996
+.Dd February 28, 2007
.Dt LINK_ADDR 3
.Os
.Sh NAME
.Li le0:8.0.9.13.d.30
represents an ethernet address
to be transmitted on the first Lance ethernet interface.
-.Pp
-The direct use of these functions is deprecated in favor of the
-.Xr addr2ascii 3
-interface; however, portable programs cannot rely on the latter as it is
-not yet widely implemented.
.Sh RETURN VALUES
The
.Fn link_ntoa
(See
.Sx BUGS . )
.Sh SEE ALSO
-.Xr addr2ascii 3
-.\" .Xr iso 4
+.Xr getnameinfo 3
.Sh HISTORY
The
.Fn link_addr
--- /dev/null
+.\" Copyright (c) 2007-2009 Bruce Simpson.
+.\" 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/libc/net/sourcefilter.3,v 1.2 2009/03/04 01:59:14 bms Exp $
+.\"
+.Dd February 13, 2009
+.Dt SOURCEFILTER 3
+.Os
+.Sh NAME
+.Nm sourcefilter
+.Nd advanced multicast group membership API
+.Sh SYNOPSIS
+.In sys/socket.h
+.In netinet/in.h
+.Ft int
+.Fo getipv4sourcefilter
+.Fa "int s"
+.Fa "struct in_addr interface"
+.Fa "struct in_addr group"
+.Fa "uint32_t *fmode"
+.Fa "uint32_t *numsrc"
+.Fa "struct in_addr *slist"
+.Fc
+.Ft int
+.Fo getsourcefilter
+.Fa "int s"
+.Fa "uint32_t interface"
+.Fa "struct sockaddr *group"
+.Fa "socklen_t grouplen"
+.Fa "uint32_t *fmode"
+.Fa "uint32_t *numsrc"
+.Fa "struct sockaddr_storage *slist"
+.Fc
+.Ft int
+.Fo setipv4sourcefilter
+.Fa "int s"
+.Fa "struct in_addr interface"
+.Fa "struct in_addr group"
+.Fa "uint32_t fmode"
+.Fa "uint32_t numsrc"
+.Fa "struct in_addr *slist"
+.Fc
+.Ft int
+.Fo setsourcefilter
+.Fa "int s"
+.Fa "uint32_t interface"
+.Fa "struct sockaddr *group"
+.Fa "socklen_t grouplen"
+.Fa "uint32_t fmode"
+.Fa "uint32_t numsrc"
+.Fa "struct sockaddr_storage *slist"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm
+functions implement the advanced, full-state multicast API
+defined in RFC 3678.
+An application may use these functions to atomically set and
+retrieve the multicast source address filters associated with a socket
+.Fa s
+and a multicast
+.Fa group .
+.Pp
+The functions
+.Fn getipv4sourcefilter
+and
+.Fn getsourcefilter
+allow an application to discover the filter mode, and
+source filter entries,
+for an existing group membership.
+.Pp
+The kernel will always return the number of source filter
+entries on the socket for that group in
+.Fa *numsrc .
+If the
+.Fa *numsrc
+argument is non-zero, the kernel will attempt to return up to
+.Fa *numsrc
+filter entries in the array pointed to by
+.Fa slist .
+The
+.Fa *numsrc
+argument may be set to 0, in which case the
+.Fa slist
+argument will be ignored.
+.Pp
+For the
+.Fn setipv4sourcefilter
+and
+.Fn setsourcefilter
+functions,
+the
+.Fa fmode
+argument may be used to place the socket into inclusive or exclusive
+group membership modes, by using the
+.Dv MCAST_INCLUDE
+or
+.Dv MCAST_EXCLUDE
+constants respectively.
+The
+.Fa numsrc
+argument specifies the number of source entries in the
+.Fa slist
+array.
+If the
+.Fa numsrc
+argument has a value of 0,
+all source filters will be removed from the socket.
+Removing all source filters from a membership which is in the
+.Dv MCAST_INCLUDE
+filter mode will cause the group to be left on that socket.
+.Pp
+The protocol-independent function
+.Fn setsourcefilter
+allows an application to join a multicast group on an interface
+which may not have an assigned protocol address,
+by passing its index for the
+.Fa interface
+argument.
+.Pp
+Any changes made by these functions
+will be communicated to IGMPv3 and/or MLDv2 routers
+on the local network as appropriate.
+If no IGMPv3 or MLDv2 routers are present, changes in the source filter
+lists made by these functions will not cause
+state changes to be transmitted, with the exception of any
+change which causes a group to be joined or left.
+The kernel will continue to maintain the source filter state
+regardless of the IGMP or MLD version in use on the link.
+.Sh IMPLEMENTATION NOTES
+The IPv4 specific versions of these functions are implemented in terms
+of the protocol-independent functions.
+Application writers are encouraged to use the protocol-independent functions
+for efficiency, and forwards compatibility with IPv6 networks.
+.Pp
+For the protocol-independent functions
+.Fn getsourcefilter
+and
+.Fn setsourcefilter ,
+the argument
+.Fa grouplen
+argument specifies the size of the structure pointed to by
+.Fa group .
+This is required in order to differentiate between different
+address families.
+.Pp
+Currently
+.Fx
+does not support source address selection for the IPv4
+protocol family, therefore the use of multicast APIs with
+an unnumbered IPv4 interface is
+.Em not recommended.
+In all cases, the first assigned IPv4 address on the interface
+will be used as the source address of IGMP control traffic.
+If this address is removed or changed, the results are undefined.
+.Sh RETURN VALUES
+.Rv -std getsourcefilter getipv4sourcefilter setsourcefilter setipv4sourcefilter
+.Sh ERRORS
+The
+.Nm
+functions may fail because of:
+.Bl -tag -width Er
+.It Bq Er EADDRNOTAVAIL
+The network interface which the
+.Dv interface
+argument refers to was not configured in the system,
+or the system is not a member of the
+.Dv group .
+.It Bq Er EAFNOSUPPORT
+The
+.Dv group
+and/or one or more of the
+.Dv slist
+arguments were of an address family unsupported by the system,
+or the address family of the
+.Dv group
+and
+.Dv slist
+arguments were not identical.
+.It Bq Er EINVAL
+The
+.Dv group
+argument does not contain a multicast address.
+The
+.Dv fmode
+argument is invalid; it must be set to either
+.Dv MCAST_INCLUDE
+or
+.Dv MCAST_EXCLUDE .
+The
+.Dv numsrc
+or
+.Dv slist
+arguments do not specify a source list.
+.It Bq Er ENOMEM
+Insufficient memory was available to carry out the requested
+operation.
+.El
+.Sh SEE ALSO
+.Xr ip 4 ,
+.Xr ip6 4 ,
+.Xr multicast 4,
+.Xr ifmcstat 8
+.Rs
+.%A D. Thaler
+.%A B. Fenner
+.%A B. Quinn
+.%T "Socket Interface Extensions for Multicast Source Filters"
+.%N RFC 3678
+.%D Jan 2004
+.Re
+.Sh HISTORY
+The
+.Nm
+functions first appeared in
+.Fx 7.0 .
+.Sh AUTHORS
+Bruce M. Simpson
+.Aq bms@FreeBSD.org
--- /dev/null
+--- sourcefilter.3.orig 2010-05-19 12:42:53.000000000 -0700
++++ sourcefilter.3 2010-05-19 12:43:19.000000000 -0700
+@@ -219,9 +219,7 @@ operation.
+ .El
+ .Sh SEE ALSO
+ .Xr ip 4 ,
+-.Xr ip6 4 ,
+-.Xr multicast 4,
+-.Xr ifmcstat 8
++.Xr ip6 4
+ .Rs
+ .%A D. Thaler
+ .%A B. Fenner
--- /dev/null
+/*-
+ * Copyright (c) 2007-2009 Bruce Simpson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/net/sourcefilter.c,v 1.5 2009/04/29 09:58:31 bms Exp $");
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "un-namespace.h"
+
+/*
+ * Advanced (Full-state) multicast group membership APIs [RFC3678]
+ * Currently this module assumes IPv4 support (INET) in the base system.
+ */
+#ifndef INET
+#define INET
+#endif
+
+union sockunion {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_dl sdl;
+#ifdef INET
+ struct sockaddr_in sin;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+};
+typedef union sockunion sockunion_t;
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * Internal: Map an IPv4 unicast address to an interface index.
+ * This is quite inefficient so it is recommended applications use
+ * the newer, more portable, protocol independent API.
+ */
+static uint32_t
+__inaddr_to_index(in_addr_t ifaddr)
+{
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifaddrs;
+ char *ifname;
+ int ifindex;
+ sockunion_t *psu;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return (0);
+
+ ifindex = 0;
+ ifname = NULL;
+
+ /*
+ * Pass #1: Find the ifaddr entry corresponding to the
+ * supplied IPv4 address. We should really use the ifindex
+ * consistently for matches, however it is not available to
+ * us on this pass.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ psu = (sockunion_t *)ifa->ifa_addr;
+ if (psu && psu->ss.ss_family == AF_INET &&
+ psu->sin.sin_addr.s_addr == ifaddr) {
+ ifname = ifa->ifa_name;
+ break;
+ }
+ }
+ if (ifname == NULL)
+ goto out;
+
+ /*
+ * Pass #2: Find the index of the interface matching the name
+ * we obtained from looking up the IPv4 ifaddr in pass #1.
+ * There must be a better way of doing this.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ psu = (sockunion_t *)ifa->ifa_addr;
+ if (psu && psu->ss.ss_family == AF_LINK &&
+ strcmp(ifa->ifa_name, ifname) == 0) {
+ ifindex = psu->sdl.sdl_index;
+ break;
+ }
+ }
+ assert(ifindex != 0);
+
+out:
+ freeifaddrs(ifaddrs);
+ return (ifindex);
+}
+
+/*
+ * Set IPv4 source filter list in use on socket.
+ *
+ * Stubbed to setsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ */
+int
+setipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t fmode, uint32_t numsrc, struct in_addr *slist)
+{
+#ifdef INET
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ sockunion_t *psu, *tmpslist;
+ int err;
+ size_t i;
+ uint32_t ifindex;
+
+ assert(s != -1);
+
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+ if (ifindex == 0) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (numsrc != 0 || slist != NULL) {
+ tmpslist = calloc(numsrc, sizeof(sockunion_t));
+ if (tmpslist == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ pina = slist;
+ psu = tmpslist;
+ for (i = 0; i < numsrc; i++, pina++, psu++) {
+ psu->sin.sin_family = AF_INET;
+ psu->sin.sin_len = sizeof(struct sockaddr_in);
+ psu->sin.sin_addr = *pina;
+ }
+ }
+
+ err = setsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL)
+ free(tmpslist);
+
+ return (err);
+#else /* !INET */
+ return (EAFNOSUPPORT);
+#endif /* INET */
+}
+
+/*
+ * Get IPv4 source filter list in use on socket.
+ *
+ * Stubbed to getsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int
+getipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t *fmode, uint32_t *numsrc, struct in_addr *slist)
+{
+ sockunion_t *psu, *tmpslist;
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ int err;
+ size_t i;
+ uint32_t ifindex, onumsrc;
+
+ assert(s != -1);
+ assert(fmode != NULL);
+ assert(numsrc != NULL);
+
+ onumsrc = *numsrc;
+ *numsrc = 0;
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (onumsrc != 0 && slist == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+ if (ifindex == 0) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (onumsrc != 0 || slist != NULL) {
+ tmpslist = calloc(onumsrc, sizeof(sockunion_t));
+ if (tmpslist == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+
+ err = getsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL && *numsrc != 0) {
+ pina = slist;
+ psu = tmpslist;
+ for (i = 0; i < MIN(onumsrc, *numsrc); i++, psu++) {
+ if (psu->ss.ss_family != AF_INET)
+ continue;
+ *pina++ = psu->sin.sin_addr;
+ }
+ free(tmpslist);
+ }
+
+ return (err);
+}
+
+/*
+ * Set protocol-independent source filter list in use on socket.
+ */
+int
+setsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t fmode, uint32_t numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int level, optname;
+
+ if (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr)))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ memset(&msfr, 0, sizeof(msfr));
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = fmode;
+ msfr.msfr_nsrcs = numsrc;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+ msfr.msfr_srcs = slist; /* pointer */
+
+ return (_setsockopt(s, level, optname, &msfr, sizeof(msfr)));
+}
+
+/*
+ * Get protocol-independent source filter list in use on socket.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int
+getsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t *fmode, uint32_t *numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int err, level, nsrcs, optlen, optname;
+
+ if (interface == 0 || group == NULL || numsrc == NULL ||
+ fmode == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ nsrcs = *numsrc;
+ *numsrc = 0;
+ *fmode = 0;
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr)))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ break;
+ }
+
+ optlen = sizeof(struct __msfilterreq);
+ memset(&msfr, 0, optlen);
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = 0;
+ msfr.msfr_nsrcs = nsrcs;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+
+ /*
+ * msfr_srcs is a pointer to a vector of sockaddr_storage. It
+ * may be NULL. The kernel will always return the total number
+ * of filter entries for the group in msfr.msfr_nsrcs.
+ */
+ msfr.msfr_srcs = slist;
+ err = _getsockopt(s, level, optname, &msfr, &optlen);
+ if (err == 0) {
+ *numsrc = msfr.msfr_nsrcs;
+ *fmode = msfr.msfr_fmode;
+ }
+
+ return (err);
+}
--- /dev/null
+--- sourcefilter.c.orig 2010-06-29 16:12:54.000000000 -0700
++++ sourcefilter.c 2010-06-29 17:55:54.000000000 -0700
+@@ -27,6 +27,9 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/net/sourcefilter.c,v 1.5 2009/04/29 09:58:31 bms Exp $");
+
++/* 8120237: enable INET6 */
++#define __APPLE_USE_RFC_3542
++
+ #include "namespace.h"
+
+ #include <sys/types.h>
+@@ -56,6 +59,10 @@ __FBSDID("$FreeBSD: src/lib/libc/net/sou
+ #ifndef INET
+ #define INET
+ #endif
++/* 8120237: enable INET6 */
++#ifndef INET6
++#define INET6
++#endif
+
+ union sockunion {
+ struct sockaddr_storage ss;
FBSDMISRCS= addr2ascii.c ascii2addr.c inet_addr.c inet_lnaof.c \
inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.c \
inet_netof.c inet_network.c inet_ntoa.c linkaddr.c nsap_addr.c \
- recv.c send.c sockatmark.c
+ recv.c send.c sockatmark.c sourcefilter.c
.include "Makefile.fbsd_end"
LEGACYSRCS+= recv.c send.c
.if ${LIB} == "c"
MAN3+= byteorder.3 ethers.3 rcmdsh.3
.include "Makefile.fbsd_begin"
-FBSDMAN3= addr2ascii.3 inet.3 inet_net.3 linkaddr.3 sockatmark.3
+FBSDMAN3= addr2ascii.3 inet.3 inet_net.3 linkaddr.3 sockatmark.3 sourcefilter.3
.include "Makefile.fbsd_end"
MLINKS+= addr2ascii.3 ascii2addr.3
MLINKS+= linkaddr.3 link_addr.3 \
linkaddr.3 link_ntoa.3
+
+MLINKS+= sourcefilter.3 getsourcefilter.3 \
+ sourcefilter.3 getipv4sourcefilter.3 \
+ sourcefilter.3 setsourcefilter.3 \
+ sourcefilter.3 setipv4sourcefilter.3
+
.endif
.Pa /etc/ethers
file.
.Sh SEE ALSO
-.Xr yp 4 ,
+.Xr yp 8 ,
.Xr ethers 5
.Sh BUGS
The
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)inet.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/net/inet.3,v 1.29 2004/07/02 23:52:11 ru Exp $
+.\" $FreeBSD: src/lib/libc/net/inet.3,v 1.36 2007/06/14 07:13:28 delphij Exp $
.\"
-.Dd June 14, 2004
+.Dd June 14, 2007
.Dt INET 3
.Os
.Sh NAME
.Nm inet_netof ,
.Nm inet_network ,
.Nm inet_ntoa ,
+.Nm inet_ntoa_r ,
.Nm inet_ntop ,
.Nm inet_pton
.Nd Internet address manipulation routines
.Fo inet_ntoa
.Fa "struct in_addr in"
.Fc
+.Ft char *
+.Fo inet_ntoa_r
+.Fa "struct in_addr in"
+.Fa "char *buf"
+.Fa "socklen_t size"
+.Fc
.Ft const char *
.Fo inet_ntop
.Fa "int af"
-.Fa "const void *restrict src"
-.Fa "char *restrict dst"
+.Fa "const void * restrict src"
+.Fa "char * restrict dst"
.Fa "socklen_t size"
.Fc
.Ft int
.Fo inet_pton
.Fa "int af"
-.Fa "const char *restrict src"
-.Fa "void *restrict dst"
+.Fa "const char * restrict src"
+.Fa "void * restrict dst"
.Fc
.Sh DESCRIPTION
The routines
.Fn inet_aton ,
-.Fn inet_addr ,
+.Fn inet_addr
and
.Fn inet_network
interpret character strings representing
.Ft struct in_addr
or some other internal binary representation, in network byte order).
It returns 1 if the address was valid for the specified address family, or
-0 if the address wasn't parseable in the specified address family, or -1
+0 if the address was not parseable in the specified address family, or -1
if some system error occurred (in which case
.Va errno
will have been set).
.Fa size
argument specifies the size, in bytes, of the buffer
.Fa *dst .
+.Dv INET_ADDRSTRLEN
+and
+.Dv INET6_ADDRSTRLEN
+define the maximum size required to convert an address of the respective
+type.
It returns NULL if a system error occurs (in which case,
.Va errno
will have been set), or it returns a pointer to the destination string.
.Ql .\&
notation.
The routine
+.Fn inet_ntoa_r
+is the reentrant version of
+.Fn inet_ntoa .
+The routine
.Fn inet_makeaddr
takes an Internet network number and a local
network address and constructs an Internet address
in the C language (i.e., a leading 0x or 0X implies
hexadecimal; otherwise, a leading 0 implies octal;
otherwise, the number is interpreted as decimal).
-.Pp
-The
-.Fn inet_aton
-and
-.Fn inet_ntoa
-functions are semi-deprecated in favor of the
-.Xr addr2ascii 3
-family.
-However, since those functions are not yet widely implemented,
-portable programs cannot rely on their presence and will continue
-to use the
-.Xr inet 3
-functions for some time.
.Sh DIAGNOSTICS
The constant
.Dv INADDR_NONE
.Pp
These include files are necessary for all functions.
.Sh SEE ALSO
-.Xr addr2ascii 3 ,
.Xr byteorder 3 ,
+.Xr getaddrinfo 3 ,
.Xr gethostbyname 3 ,
+.Xr getnameinfo 3 ,
.Xr getnetent 3 ,
.Xr inet_net 3 ,
-.Xr compat 5 ,
.Xr hosts 5 ,
.Xr networks 5
.Rs
.Fn inet_ntoa
resides in a static memory area.
.Pp
-Inet_addr should return a
+The
+.Fn inet_addr
+function should return a
.Fa struct in_addr .
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.1 2005/04/27 05:00:53 sra Exp $";
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
#endif
/* the algorithms only can deal with ASCII, so we optimize for it */
#define USE_ASCII
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_pton.c,v 1.3 2007/06/03 17:20:26 ume Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_pton.c,v 1.4 2008/12/14 19:39:53 ume Exp $");
#include "port_before.h"
bits *= 10;
bits += n;
if (bits > 32)
- goto emsgsize;
+ goto enoent;
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
if (ch != '\0')
goto enoent;
--- /dev/null
+/*-
+ * Copyright (c) 2007-2009 Bruce Simpson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/net/sourcefilter.c,v 1.5 2009/04/29 09:58:31 bms Exp $");
+
+/* 8120237: enable INET6 */
+#define __APPLE_USE_RFC_3542
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "un-namespace.h"
+
+/*
+ * Advanced (Full-state) multicast group membership APIs [RFC3678]
+ * Currently this module assumes IPv4 support (INET) in the base system.
+ */
+#ifndef INET
+#define INET
+#endif
+/* 8120237: enable INET6 */
+#ifndef INET6
+#define INET6
+#endif
+
+union sockunion {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_dl sdl;
+#ifdef INET
+ struct sockaddr_in sin;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+};
+typedef union sockunion sockunion_t;
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * Internal: Map an IPv4 unicast address to an interface index.
+ * This is quite inefficient so it is recommended applications use
+ * the newer, more portable, protocol independent API.
+ */
+static uint32_t
+__inaddr_to_index(in_addr_t ifaddr)
+{
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifaddrs;
+ char *ifname;
+ int ifindex;
+ sockunion_t *psu;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return (0);
+
+ ifindex = 0;
+ ifname = NULL;
+
+ /*
+ * Pass #1: Find the ifaddr entry corresponding to the
+ * supplied IPv4 address. We should really use the ifindex
+ * consistently for matches, however it is not available to
+ * us on this pass.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ psu = (sockunion_t *)ifa->ifa_addr;
+ if (psu && psu->ss.ss_family == AF_INET &&
+ psu->sin.sin_addr.s_addr == ifaddr) {
+ ifname = ifa->ifa_name;
+ break;
+ }
+ }
+ if (ifname == NULL)
+ goto out;
+
+ /*
+ * Pass #2: Find the index of the interface matching the name
+ * we obtained from looking up the IPv4 ifaddr in pass #1.
+ * There must be a better way of doing this.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ psu = (sockunion_t *)ifa->ifa_addr;
+ if (psu && psu->ss.ss_family == AF_LINK &&
+ strcmp(ifa->ifa_name, ifname) == 0) {
+ ifindex = psu->sdl.sdl_index;
+ break;
+ }
+ }
+ assert(ifindex != 0);
+
+out:
+ freeifaddrs(ifaddrs);
+ return (ifindex);
+}
+
+/*
+ * Set IPv4 source filter list in use on socket.
+ *
+ * Stubbed to setsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ */
+int
+setipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t fmode, uint32_t numsrc, struct in_addr *slist)
+{
+#ifdef INET
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ sockunion_t *psu, *tmpslist;
+ int err;
+ size_t i;
+ uint32_t ifindex;
+
+ assert(s != -1);
+
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+ if (ifindex == 0) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (numsrc != 0 || slist != NULL) {
+ tmpslist = calloc(numsrc, sizeof(sockunion_t));
+ if (tmpslist == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ pina = slist;
+ psu = tmpslist;
+ for (i = 0; i < numsrc; i++, pina++, psu++) {
+ psu->sin.sin_family = AF_INET;
+ psu->sin.sin_len = sizeof(struct sockaddr_in);
+ psu->sin.sin_addr = *pina;
+ }
+ }
+
+ err = setsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL)
+ free(tmpslist);
+
+ return (err);
+#else /* !INET */
+ return (EAFNOSUPPORT);
+#endif /* INET */
+}
+
+/*
+ * Get IPv4 source filter list in use on socket.
+ *
+ * Stubbed to getsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int
+getipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t *fmode, uint32_t *numsrc, struct in_addr *slist)
+{
+ sockunion_t *psu, *tmpslist;
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ int err;
+ size_t i;
+ uint32_t ifindex, onumsrc;
+
+ assert(s != -1);
+ assert(fmode != NULL);
+ assert(numsrc != NULL);
+
+ onumsrc = *numsrc;
+ *numsrc = 0;
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (onumsrc != 0 && slist == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+ if (ifindex == 0) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (onumsrc != 0 || slist != NULL) {
+ tmpslist = calloc(onumsrc, sizeof(sockunion_t));
+ if (tmpslist == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+
+ err = getsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL && *numsrc != 0) {
+ pina = slist;
+ psu = tmpslist;
+ for (i = 0; i < MIN(onumsrc, *numsrc); i++, psu++) {
+ if (psu->ss.ss_family != AF_INET)
+ continue;
+ *pina++ = psu->sin.sin_addr;
+ }
+ free(tmpslist);
+ }
+
+ return (err);
+}
+
+/*
+ * Set protocol-independent source filter list in use on socket.
+ */
+int
+setsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t fmode, uint32_t numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int level, optname;
+
+ if (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr)))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ memset(&msfr, 0, sizeof(msfr));
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = fmode;
+ msfr.msfr_nsrcs = numsrc;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+ msfr.msfr_srcs = slist; /* pointer */
+
+ return (_setsockopt(s, level, optname, &msfr, sizeof(msfr)));
+}
+
+/*
+ * Get protocol-independent source filter list in use on socket.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int
+getsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t *fmode, uint32_t *numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int err, level, nsrcs, optlen, optname;
+
+ if (interface == 0 || group == NULL || numsrc == NULL ||
+ fmode == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ nsrcs = *numsrc;
+ *numsrc = 0;
+ *fmode = 0;
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr)))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ break;
+ }
+
+ optlen = sizeof(struct __msfilterreq);
+ memset(&msfr, 0, optlen);
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = 0;
+ msfr.msfr_nsrcs = nsrcs;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+
+ /*
+ * msfr_srcs is a pointer to a vector of sockaddr_storage. It
+ * may be NULL. The kernel will always return the total number
+ * of filter entries for the group in msfr.msfr_nsrcs.
+ */
+ msfr.msfr_srcs = slist;
+ err = _getsockopt(s, level, optname, &msfr, &optlen);
+ if (err == 0) {
+ *numsrc = msfr.msfr_nsrcs;
+ *fmode = msfr.msfr_fmode;
+ }
+
+ return (err);
+}
--- /dev/null
+.\" Copyright (c) 2007-2009 Bruce Simpson.
+.\" 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/libc/net/sourcefilter.3,v 1.2 2009/03/04 01:59:14 bms Exp $
+.\"
+.Dd February 13, 2009
+.Dt SOURCEFILTER 3
+.Os
+.Sh NAME
+.Nm sourcefilter
+.Nd advanced multicast group membership API
+.Sh SYNOPSIS
+.In sys/socket.h
+.In netinet/in.h
+.Ft int
+.Fo getipv4sourcefilter
+.Fa "int s"
+.Fa "struct in_addr interface"
+.Fa "struct in_addr group"
+.Fa "uint32_t *fmode"
+.Fa "uint32_t *numsrc"
+.Fa "struct in_addr *slist"
+.Fc
+.Ft int
+.Fo getsourcefilter
+.Fa "int s"
+.Fa "uint32_t interface"
+.Fa "struct sockaddr *group"
+.Fa "socklen_t grouplen"
+.Fa "uint32_t *fmode"
+.Fa "uint32_t *numsrc"
+.Fa "struct sockaddr_storage *slist"
+.Fc
+.Ft int
+.Fo setipv4sourcefilter
+.Fa "int s"
+.Fa "struct in_addr interface"
+.Fa "struct in_addr group"
+.Fa "uint32_t fmode"
+.Fa "uint32_t numsrc"
+.Fa "struct in_addr *slist"
+.Fc
+.Ft int
+.Fo setsourcefilter
+.Fa "int s"
+.Fa "uint32_t interface"
+.Fa "struct sockaddr *group"
+.Fa "socklen_t grouplen"
+.Fa "uint32_t fmode"
+.Fa "uint32_t numsrc"
+.Fa "struct sockaddr_storage *slist"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm
+functions implement the advanced, full-state multicast API
+defined in RFC 3678.
+An application may use these functions to atomically set and
+retrieve the multicast source address filters associated with a socket
+.Fa s
+and a multicast
+.Fa group .
+.Pp
+The functions
+.Fn getipv4sourcefilter
+and
+.Fn getsourcefilter
+allow an application to discover the filter mode, and
+source filter entries,
+for an existing group membership.
+.Pp
+The kernel will always return the number of source filter
+entries on the socket for that group in
+.Fa *numsrc .
+If the
+.Fa *numsrc
+argument is non-zero, the kernel will attempt to return up to
+.Fa *numsrc
+filter entries in the array pointed to by
+.Fa slist .
+The
+.Fa *numsrc
+argument may be set to 0, in which case the
+.Fa slist
+argument will be ignored.
+.Pp
+For the
+.Fn setipv4sourcefilter
+and
+.Fn setsourcefilter
+functions,
+the
+.Fa fmode
+argument may be used to place the socket into inclusive or exclusive
+group membership modes, by using the
+.Dv MCAST_INCLUDE
+or
+.Dv MCAST_EXCLUDE
+constants respectively.
+The
+.Fa numsrc
+argument specifies the number of source entries in the
+.Fa slist
+array.
+If the
+.Fa numsrc
+argument has a value of 0,
+all source filters will be removed from the socket.
+Removing all source filters from a membership which is in the
+.Dv MCAST_INCLUDE
+filter mode will cause the group to be left on that socket.
+.Pp
+The protocol-independent function
+.Fn setsourcefilter
+allows an application to join a multicast group on an interface
+which may not have an assigned protocol address,
+by passing its index for the
+.Fa interface
+argument.
+.Pp
+Any changes made by these functions
+will be communicated to IGMPv3 and/or MLDv2 routers
+on the local network as appropriate.
+If no IGMPv3 or MLDv2 routers are present, changes in the source filter
+lists made by these functions will not cause
+state changes to be transmitted, with the exception of any
+change which causes a group to be joined or left.
+The kernel will continue to maintain the source filter state
+regardless of the IGMP or MLD version in use on the link.
+.Sh IMPLEMENTATION NOTES
+The IPv4 specific versions of these functions are implemented in terms
+of the protocol-independent functions.
+Application writers are encouraged to use the protocol-independent functions
+for efficiency, and forwards compatibility with IPv6 networks.
+.Pp
+For the protocol-independent functions
+.Fn getsourcefilter
+and
+.Fn setsourcefilter ,
+the argument
+.Fa grouplen
+argument specifies the size of the structure pointed to by
+.Fa group .
+This is required in order to differentiate between different
+address families.
+.Pp
+Currently
+.Fx
+does not support source address selection for the IPv4
+protocol family, therefore the use of multicast APIs with
+an unnumbered IPv4 interface is
+.Em not recommended.
+In all cases, the first assigned IPv4 address on the interface
+will be used as the source address of IGMP control traffic.
+If this address is removed or changed, the results are undefined.
+.Sh RETURN VALUES
+.Rv -std getsourcefilter getipv4sourcefilter setsourcefilter setipv4sourcefilter
+.Sh ERRORS
+The
+.Nm
+functions may fail because of:
+.Bl -tag -width Er
+.It Bq Er EADDRNOTAVAIL
+The network interface which the
+.Dv interface
+argument refers to was not configured in the system,
+or the system is not a member of the
+.Dv group .
+.It Bq Er EAFNOSUPPORT
+The
+.Dv group
+and/or one or more of the
+.Dv slist
+arguments were of an address family unsupported by the system,
+or the address family of the
+.Dv group
+and
+.Dv slist
+arguments were not identical.
+.It Bq Er EINVAL
+The
+.Dv group
+argument does not contain a multicast address.
+The
+.Dv fmode
+argument is invalid; it must be set to either
+.Dv MCAST_INCLUDE
+or
+.Dv MCAST_EXCLUDE .
+The
+.Dv numsrc
+or
+.Dv slist
+arguments do not specify a source list.
+.It Bq Er ENOMEM
+Insufficient memory was available to carry out the requested
+operation.
+.El
+.Sh SEE ALSO
+.Xr ip 4 ,
+.Xr ip6 4
+.Rs
+.%A D. Thaler
+.%A B. Fenner
+.%A B. Quinn
+.%T "Socket Interface Extensions for Multicast Source Filters"
+.%N RFC 3678
+.%D Jan 2004
+.Re
+.Sh HISTORY
+The
+.Nm
+functions first appeared in
+.Fx 7.0 .
+.Sh AUTHORS
+Bruce M. Simpson
+.Aq bms@FreeBSD.org
.\" (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/libc/nls/catclose.3,v 1.14 2001/10/01 16:08:56 ru Exp $
-.Dd May 29, 1994
+.\" $FreeBSD: src/lib/libc/nls/catclose.3,v 1.15 2005/02/27 16:30:16 phantom Exp $
+.Dd February 12, 2005
.Dt CATCLOSE 3
.Os
.Sh NAME
The
.Fn catclose
function conforms to
-.St -xpg4 .
+.St -p1003.1-2001 .
.\" (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/libc/nls/catgets.3,v 1.11 2001/10/01 16:08:56 ru Exp $
-.Dd May 29, 1994
+.\" $FreeBSD: src/lib/libc/nls/catgets.3,v 1.13 2005/06/15 19:04:04 ru Exp $
+.Dd February 12, 2005
.Dt CATGETS 3
.Os
.Sh NAME
returns a pointer to an internal buffer containing the message string;
otherwise it returns
.Fa s .
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa catd
+argument is not a valid message catalog descriptor.
+.It Bq Er EBADMSG
+The message identified by
+.Fa set_id
+and
+.Fa msg_id
+is not in the message catalog.
+.El
.Sh SEE ALSO
.Xr gencat 1 ,
.Xr catclose 3 ,
The
.Fn catgets
function conforms to
-.St -xpg4 .
+.St -p1003.1-2001 .
.\" (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/libc/nls/catopen.3,v 1.16 2001/10/01 16:08:56 ru Exp $
-.Dd May 29, 1994
+.\" $FreeBSD: src/lib/libc/nls/catopen.3,v 1.17 2005/02/27 16:30:16 phantom Exp $
+.Dd February 12, 2005
.Dt CATOPEN 3
.Os
.Sh NAME
.It Bq Er EINVAL
Argument
.Fa name
-does not point to a valid message catalog.
+does not point to a valid message catalog, or catalog is corrupt.
.It Bq Er ENAMETOOLONG
An entire path to the message catalog exceeded 1024 characters.
.It Bq Er ENOENT
The
.Fn catopen
function conforms to
-.St -xpg4 .
+.St -p1003.1-2001 .
******************************************************************/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/nls/msgcat.c,v 1.48 2003/10/29 10:45:01 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/nls/msgcat.c,v 1.49 2005/02/01 16:04:55 phantom Exp $");
/*
* We need a better way of handling errors than printing text. I need
#define NLERR ((nl_catd) -1)
#define NLRETERR(errc) { errno = errc; return (NLERR); }
-static nl_catd loadCat();
-static int loadSet();
-static void __nls_free_resources();
+static nl_catd loadCat(__const char *);
+static int loadSet(MCCatT *, MCSetT *);
+static void __nls_free_resources(MCCatT *, int);
nl_catd
-catopen(name, type)
- __const char *name;
- int type;
+catopen(__const char *name, int type)
{
int spcleft, saverr;
char path[PATH_MAX];
(pathP - path) - 1;
if (strlcpy(pathP, tmpptr, spcleft) >=
spcleft) {
- too_long:
+ too_long:
free(plang);
free(base);
NLRETERR(ENAMETOOLONG);
}
static MCSetT *
-MCGetSet(cat, setId)
- MCCatT *cat;
- int setId;
+MCGetSet(MCCatT *cat, int setId)
{
MCSetT *set;
long lo, hi, cur, dir;
}
static MCMsgT *
-MCGetMsg(set, msgId)
- MCSetT *set;
- int msgId;
+MCGetMsg(MCSetT *set, int msgId)
{
MCMsgT *msg;
long lo, hi, cur, dir;
}
char *
-catgets(catd, setId, msgId, dflt)
- nl_catd catd;
- int setId;
- int msgId;
- __const char *dflt;
+catgets(nl_catd catd, int setId, int msgId, __const char *dflt)
{
MCMsgT *msg;
MCCatT *cat = (MCCatT *)catd;
}
int
-catclose(catd)
- nl_catd catd;
+catclose(nl_catd catd)
{
MCCatT *cat = (MCCatT *)catd;
errno = EBADF;
return (-1);
}
-#if 0
- if (cat->loadType != MCLoadAll)
-#endif
- (void)fclose(cat->fp);
+
+ (void)fclose(cat->fp);
__nls_free_resources(cat, cat->numSets);
free(cat);
return (0);
}
static void
-__nls_free_resources(cat, i)
- MCCatT *cat;
- int i;
+__nls_free_resources(MCCatT *cat, int i)
{
MCSetT *set;
int j;
}
static nl_catd
-loadCat(catpath)
- __const char *catpath;
+loadCat(__const char *catpath)
{
MCHeaderT header;
MCCatT *cat;
if ((cat = (MCCatT *)malloc(sizeof(MCCatT))) == NULL)
return (NLERR);
- cat->loadType = MCLoadBySet;
if ((cat->fp = fopen(catpath, "r")) == NULL) {
saverr = errno;
nextSet = set->nextSet;
continue;
}
-#if 0
- if (cat->loadType == MCLoadAll) {
- int res;
-
- if ((res = loadSet(cat, set)) <= 0) {
- saverr = errno;
- __nls_free_resources(cat, i);
- errno = saverr;
- if (res < 0)
- NOSPACE();
- CORRUPT();
- }
- } else
-#endif
- set->invalid = TRUE;
+ set->invalid = TRUE;
nextSet = set->nextSet;
}
-#if 0
- if (cat->loadType == MCLoadAll) {
- (void)fclose(cat->fp);
- cat->fp = NULL;
- }
-#endif
+
return ((nl_catd) cat);
}
static int
-loadSet(cat, set)
- MCCatT *cat;
- MCSetT *set;
+loadSet(MCCatT *cat, MCSetT *set)
{
MCMsgT *msg;
int i;
---- msgcat.c.orig 2007-02-07 01:54:34.000000000 -0800
-+++ msgcat.c 2007-02-07 02:03:33.000000000 -0800
-@@ -45,16 +45,22 @@
+--- msgcat.c.orig 2009-12-05 13:47:14.000000000 -0800
++++ msgcat.c 2009-12-05 13:49:56.000000000 -0800
+@@ -45,16 +45,22 @@ __FBSDID("$FreeBSD: src/lib/libc/nls/msg
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L"
-@@ -87,7 +93,7 @@
+@@ -85,7 +91,7 @@ catopen(__const char *name, int type)
return (loadCat(name));
if (type == NL_CAT_LOCALE)
else
lang = getenv("LANG");
-@@ -210,21 +216,21 @@
+@@ -208,21 +214,21 @@ catopen(__const char *name, int type)
#define LOOKUP(PARENT, CHILD, ID, NUM, SET) { \
lo = 0; \
dir = 1; \
} else { \
hi = cur; \
-@@ -240,32 +246,28 @@
- }
-
- static MCSetT *
--MCGetSet(cat, setId)
-- MCCatT *cat;
-- int setId;
-+MCGetSet(MCCatT *cat, int setId)
+@@ -241,11 +247,11 @@ static MCSetT *
+ MCGetSet(MCCatT *cat, int setId)
{
MCSetT *set;
- long lo, hi, cur, dir;
if (set->invalid && loadSet(cat, set) <= 0)
return (NULL);
return (set);
- }
-
- static MCMsgT *
--MCGetMsg(set, msgId)
-- MCSetT *set;
-- int msgId;
-+MCGetMsg(MCSetT *set, int msgId)
+@@ -255,11 +261,11 @@ static MCMsgT *
+ MCGetMsg(MCSetT *set, int msgId)
{
MCMsgT *msg;
- long lo, hi, cur, dir;
return (msg);
}
-@@ -357,7 +359,7 @@
+@@ -341,7 +347,7 @@ loadCat(__const char *catpath)
MCHeaderT header;
MCCatT *cat;
MCSetT *set;
off_t nextSet;
int saverr;
-@@ -377,27 +379,30 @@
+@@ -360,27 +366,30 @@ loadCat(__const char *catpath)
strncmp(header.magic, MCMagic, MCMagicLen) != 0)
CORRUPT();
for (i = 0; i < cat->numSets; ++i) {
if (fseeko(cat->fp, nextSet, SEEK_SET) == -1) {
__nls_free_resources(cat, i);
-@@ -414,7 +419,7 @@
+@@ -397,11 +406,11 @@ loadCat(__const char *catpath)
/* if it's invalid, skip over it (and backup 'i') */
if (set->invalid) {
--i;
+ nextSet = ntohll(set->nextSet);
continue;
}
- #if 0
-@@ -432,7 +437,7 @@
- } else
- #endif
- set->invalid = TRUE;
+ set->invalid = TRUE;
- nextSet = set->nextSet;
+ nextSet = ntohll(set->nextSet);
}
- #if 0
- if (cat->loadType == MCLoadAll) {
-@@ -453,11 +458,11 @@
+
+ return ((nl_catd) cat);
+@@ -415,11 +424,11 @@ loadSet(MCCatT *cat, MCSetT *set)
int saverr;
/* Get the data */
saverr = errno;
free(set->data.str);
errno = saverr;
-@@ -465,13 +470,13 @@
+@@ -427,13 +436,13 @@ loadSet(MCCatT *cat, MCSetT *set)
}
/* Get the messages */
NULL) {
saverr = errno;
free(set->data.str);
-@@ -479,7 +484,7 @@
+@@ -441,7 +450,7 @@ loadSet(MCCatT *cat, MCSetT *set)
return (-1);
}
msg = set->u.msgs + i;
if (fread(msg, sizeof(*msg), 1, cat->fp) != 1) {
saverr = errno;
-@@ -492,7 +497,7 @@
+@@ -454,7 +463,7 @@ loadSet(MCCatT *cat, MCSetT *set)
--i;
continue;
}
-/* $FreeBSD: src/lib/libc/nls/msgcat.h,v 1.8 2000/09/03 21:05:10 ache Exp $ */
+/* $FreeBSD: src/lib/libc/nls/msgcat.h,v 1.9 2005/02/01 16:04:55 phantom Exp $ */
#ifndef _MSGCAT_H_
#define _MSGCAT_H_
******************************************************************/
-
-#include <sys/types.h>
-
/*
- * On disk data structures
+ * Magic definitions
*/
-/* For or'd constants */
-#define MCMakeId(s,m) (unsigned long) ( ((unsigned short)s << (sizeof(short)*8)) \
- | (unsigned short)m )
-#define MCSetId(id) (unsigned int) ( id >> (sizeof(short) * 8) )
-#define MCMsgId(id) (unsigned int) ( (id << (sizeof(short) * 8)) \
- >> (sizeof(short) * 8) )
#define MCMagicLen 8
#define MCMagic "*nazgul*"
-#define MCLastMsg 0
-#define MCLastSet 0
#define MCMajorVer 1L
#define MCMinorVer 0
+/* For or'd constants */
+#define MCMakeId(s,m) (unsigned long) ( ((unsigned short)s << (sizeof(short)*8)) \
+ | (unsigned short)m )
+
/*
* Critical note here. Sets and Messages *MUST* be stored in ascending
* order. There are stored that way (by specification) in the original
* no guarantee that this will all work.
*/
-/* These should be publicly available */
-
-#define MCLoadBySet 0 /* Load entire sets as they are used */
-#define MCLoadAll 1 /* Load entire DB on catopen */
-
/*
* MCOffsetT - Union to handle both disk and runtime pointers
*/
* MCCatT - Runtime catalog pointer
*/
typedef struct {
- long loadType; /* How to load the messages (see MSLoadType) */
FILE *fp; /* File descriptor of catalog (if load-on-demand) */
long numSets; /* Number of sets */
MCSetT *sets; /* Pointer to the sets */
---- msgcat.h.orig 2007-02-07 11:30:18.000000000 -0800
-+++ msgcat.h 2007-02-07 11:57:46.000000000 -0800
-@@ -44,7 +44,7 @@
- */
+--- msgcat.h.orig 2009-11-23 18:16:18.000000000 -0800
++++ msgcat.h 2009-12-05 13:58:11.000000000 -0800
+@@ -43,13 +43,14 @@ up-to-date. Many thanks.
+ #define MCMagicLen 8
+ #define MCMagic "*nazgul*"
+
+-#define MCMajorVer 1L
++#define MCMajorVer 1
+ #define MCMinorVer 0
/* For or'd constants */
-#define MCMakeId(s,m) (unsigned long) ( ((unsigned short)s << (sizeof(short)*8)) \
+#define MCMakeId(s,m) (u_int32_t) ( ((unsigned short)s << (sizeof(short)*8)) \
| (unsigned short)m )
- #define MCSetId(id) (unsigned int) ( id >> (sizeof(short) * 8) )
- #define MCMsgId(id) (unsigned int) ( (id << (sizeof(short) * 8)) \
-@@ -54,7 +54,7 @@
- #define MCLastMsg 0
- #define MCLastSet 0
-
--#define MCMajorVer 1L
-+#define MCMajorVer 1
- #define MCMinorVer 0
++
/*
-@@ -100,38 +100,44 @@
+ * Critical note here. Sets and Messages *MUST* be stored in ascending
+ * order. There are stored that way (by specification) in the original
+@@ -88,37 +89,43 @@ typedef union {
struct _MCSetT *set;
} MCOffsetT;
* MCCatT - Runtime catalog pointer
*/
typedef struct {
-- long loadType; /* How to load the messages (see MSLoadType) */
-+ int32_t loadType; /* How to load the messages (see MSLoadType) */
FILE *fp; /* File descriptor of catalog (if load-on-demand) */
- long numSets; /* Number of sets */
+ int32_t numSets; /* Number of sets */
MCSetT *sets; /* Pointer to the sets */
off_t firstSet; /* Offset of first set on disk */
} MCCatT;
-@@ -141,10 +147,10 @@
+@@ -128,10 +135,10 @@ typedef struct {
*/
typedef struct {
char magic[MCMagicLen]; /* Magic cookie "*nazgul*" */
******************************************************************/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/nls/msgcat.c,v 1.48 2003/10/29 10:45:01 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/nls/msgcat.c,v 1.49 2005/02/01 16:04:55 phantom Exp $");
/*
* We need a better way of handling errors than printing text. I need
#define NLERR ((nl_catd) -1)
#define NLRETERR(errc) { errno = errc; return (NLERR); }
-static nl_catd loadCat();
-static int loadSet();
-static void __nls_free_resources();
+static nl_catd loadCat(__const char *);
+static int loadSet(MCCatT *, MCSetT *);
+static void __nls_free_resources(MCCatT *, int);
nl_catd
-catopen(name, type)
- __const char *name;
- int type;
+catopen(__const char *name, int type)
{
int spcleft, saverr;
char path[PATH_MAX];
(pathP - path) - 1;
if (strlcpy(pathP, tmpptr, spcleft) >=
spcleft) {
- too_long:
+ too_long:
free(plang);
free(base);
NLRETERR(ENAMETOOLONG);
}
char *
-catgets(catd, setId, msgId, dflt)
- nl_catd catd;
- int setId;
- int msgId;
- __const char *dflt;
+catgets(nl_catd catd, int setId, int msgId, __const char *dflt)
{
MCMsgT *msg;
MCCatT *cat = (MCCatT *)catd;
}
int
-catclose(catd)
- nl_catd catd;
+catclose(nl_catd catd)
{
MCCatT *cat = (MCCatT *)catd;
errno = EBADF;
return (-1);
}
-#if 0
- if (cat->loadType != MCLoadAll)
-#endif
- (void)fclose(cat->fp);
+
+ (void)fclose(cat->fp);
__nls_free_resources(cat, cat->numSets);
free(cat);
return (0);
}
static void
-__nls_free_resources(cat, i)
- MCCatT *cat;
- int i;
+__nls_free_resources(MCCatT *cat, int i)
{
MCSetT *set;
int j;
}
static nl_catd
-loadCat(catpath)
- __const char *catpath;
+loadCat(__const char *catpath)
{
MCHeaderT header;
MCCatT *cat;
if ((cat = (MCCatT *)malloc(sizeof(MCCatT))) == NULL)
return (NLERR);
- cat->loadType = MCLoadBySet;
if ((cat->fp = fopen(catpath, "r")) == NULL) {
saverr = errno;
nextSet = ntohll(set->nextSet);
continue;
}
-#if 0
- if (cat->loadType == MCLoadAll) {
- int res;
-
- if ((res = loadSet(cat, set)) <= 0) {
- saverr = errno;
- __nls_free_resources(cat, i);
- errno = saverr;
- if (res < 0)
- NOSPACE();
- CORRUPT();
- }
- } else
-#endif
- set->invalid = TRUE;
+ set->invalid = TRUE;
nextSet = ntohll(set->nextSet);
}
-#if 0
- if (cat->loadType == MCLoadAll) {
- (void)fclose(cat->fp);
- cat->fp = NULL;
- }
-#endif
+
return ((nl_catd) cat);
}
static int
-loadSet(cat, set)
- MCCatT *cat;
- MCSetT *set;
+loadSet(MCCatT *cat, MCSetT *set)
{
MCMsgT *msg;
int i;
-/* $FreeBSD: src/lib/libc/nls/msgcat.h,v 1.8 2000/09/03 21:05:10 ache Exp $ */
+/* $FreeBSD: src/lib/libc/nls/msgcat.h,v 1.9 2005/02/01 16:04:55 phantom Exp $ */
#ifndef _MSGCAT_H_
#define _MSGCAT_H_
******************************************************************/
-
-#include <sys/types.h>
-
/*
- * On disk data structures
+ * Magic definitions
*/
-/* For or'd constants */
-#define MCMakeId(s,m) (u_int32_t) ( ((unsigned short)s << (sizeof(short)*8)) \
- | (unsigned short)m )
-#define MCSetId(id) (unsigned int) ( id >> (sizeof(short) * 8) )
-#define MCMsgId(id) (unsigned int) ( (id << (sizeof(short) * 8)) \
- >> (sizeof(short) * 8) )
#define MCMagicLen 8
#define MCMagic "*nazgul*"
-#define MCLastMsg 0
-#define MCLastSet 0
#define MCMajorVer 1
#define MCMinorVer 0
+/* For or'd constants */
+#define MCMakeId(s,m) (u_int32_t) ( ((unsigned short)s << (sizeof(short)*8)) \
+ | (unsigned short)m )
+
+
/*
* Critical note here. Sets and Messages *MUST* be stored in ascending
* order. There are stored that way (by specification) in the original
* no guarantee that this will all work.
*/
-/* These should be publicly available */
-
-#define MCLoadBySet 0 /* Load entire sets as they are used */
-#define MCLoadAll 1 /* Load entire DB on catopen */
-
/*
* MCOffsetT - Union to handle both disk and runtime pointers
*/
* MCCatT - Runtime catalog pointer
*/
typedef struct {
- int32_t loadType; /* How to load the messages (see MSLoadType) */
FILE *fp; /* File descriptor of catalog (if load-on-demand) */
int32_t numSets; /* Number of sets */
MCSetT *sets; /* Pointer to the sets */
acl_clear_flags_np.3 \
acl_clear_perms.3 \
acl_copy_entry.3 \
+ acl_copy_ext.3 \
acl_create_entry.3 \
acl_delete_entry.3 \
acl_delete_flag_np.3 \
acl_get_entry.3 \
acl_get_flagset_np.3 \
acl_get_permset.3 \
+ acl_get_permset_mask_np.3 \
acl_get_perm_np.3 \
acl_get_qualifier.3 \
acl_get_tag_type.3 \
acl_to_text.3 \
acl_valid.3
+MLINKS+= acl.3 posix1e.3
+
+MLINKS+= acl_copy_ext.3 acl_copy_ext_native.3 \
+ acl_copy_ext.3 acl_copy_int.3 \
+ acl_copy_ext.3 acl_copy_int_native.3 \
+ acl_copy_ext.3 acl_size.3
+
MLINKS+= acl_create_entry.3 acl_create_entry_np.3
#MLINKS+= acl_delete.3 acl_delete_fd_np.3 \
acl_get.3 acl_get_file.3 \
acl_get.3 acl_get_link_np.3
+MLINKS+= acl_get_permset_mask_np.3 acl_set_permset_mask_np.3 \
+ acl_get_permset_mask_np.3 acl_maximal_permset_mask_np.3
+
MLINKS+= acl_set.3 acl_set_fd.3 \
acl_set.3 acl_set_fd_np.3 \
acl_set.3 acl_set_file.3 \
This function is described in
.Xr acl_create_entry 3 ,
and may be used to create an empty entry in an ACL.
-.It Xo
-.Fn acl_delete_fd_np ,
-.Fn acl_delete_file_np ,
-.Fn acl_delete_link_np
-.Xc
-These functions are described in
-.Xr acl_delete 3 ,
-and may be used to delete ACLs from file system objects.
.It Fn acl_delete_entry
This function is described in
.Xr acl_delete_entry 3 ,
as appropriate for a particular file system object regardless of semantics.
.El
.Pp
-Documentation of the internal kernel interfaces backing these calls may
-be found in
-.Xr acl 9 .
The syscalls between the internal interfaces and the public library
routines may change over time, and as such are not documented.
They are not intended to be called directly without going through the
.Xr acl_to_text 3 ,
.Xr acl_valid 3 ,
.Xr posix1e 3
-.\".Xr acl 9
.Sh UNSUPPORTED FUNCTIONS
.Xr acl_calc_mask 3 ,
.Fn acl_delete_def_file
#include <sys/types.h>
#include <sys/acl.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
* Without tracking the addresses of text buffers and qualifiers,
* we can't validate the obj argument here at all.
*/
- free(obj);
+ if(obj != _FILESEC_REMOVE_ACL)
+ free(obj);
return(0);
}
--- /dev/null
+.Dd February 3, 2011
+.Dt ACL_COPY_EXT 3
+.Sh NAME
+.Nm acl_copy_ext ,
+.Nm acl_copy_ext_native ,
+.Nm acl_copy_int ,
+.Nm acl_copy_int_native,
+.Nm acl_size
+.Nd convert an ACL to and from an external representation
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft ssize_t
+.Fo acl_copy_ext
+.Fa "void *buf"
+.Fa "acl_t acl"
+.Fa "ssize_t size"
+.Fc
+.Ft ssize_t
+.Fo acl_copy_ext_native
+.Fa "void *buf"
+.Fa "acl_t acl"
+.Fa "ssize_t size"
+.Fc
+.Ft acl_t
+.Fo acl_copy_int
+.Fa "const void *buf"
+.Fc
+.Ft acl_t
+.Fo acl_copy_int_native
+.Fa "const void *buf"
+.Fc
+.Ft ssize_t
+.Fo acl_size
+.Fa "acl_t acl"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn acl_copy_ext
+and
+.Fn acl_copy_ext_native
+functions convert the ACL given by the argument
+.Fa acl
+into a binary external representation that can be saved to a file,
+passed to another program, etc.
+This external representation is written to the buffer pointed to by the argument
+.Fa buf ,
+which is assumed to have at least the number of contiguous bytes passed in the
+.Fa size
+argument.
+The number of bytes actually written is returned.
+.Pp
+The
+.Fn acl_copy_ext
+function writes data in big-endian byte-order, and so is portable across
+machines with different byte-order.
+To the contrary, the
+.Fn acl_copy_ext_native
+function uses the machine's native byte-order, and so is only portable to
+machines of like byte-order.
+.Pp
+The
+.Fn acl_copy_int
+and
+.Fn acl_copy_int_native
+functions do the reverse conversion; the ACL represented by the external
+representation passed in the argument
+.Fa buf ,
+is returned.
+The
+.Fn acl_copy_int
+function expects an external representation in big-endian byte-order (as
+returned by
+.Fn acl_copy_ext ) ,
+while
+.Fn acl_copy_int_native
+expects an external representation in native byte-order (as returned by
+.Fn acl_copy_ext_native ) .
+.Pp
+The
+.Fn acl_size
+function returns the corresponding external representation size, in bytes, for
+the given ACL passed in the argument
+.Fa acl .
+This size can be used to allocate sufficient memory for the buffer in
+subsequent calls to
+.Fn acl_copy_ext
+and
+.Fn acl_copy_ext_native .
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn acl_copy_ext
+and
+.Fn acl_copy_ext_native
+functions shall return the number of bytes actually written to the buffer.
+Otherwise, a value of
+.Va -1
+shall be returned and
+.Va errno
+shall be set to indicate the error.
+.Pp
+Upon successful completion, the
+.Fn acl_copy_int
+and
+.Fn acl_copy_int_native
+functions shall return the ACL represented by the external representation
+passed in the buffer.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned and
+.Va errno
+shall be set to indicate the error.
+.Pp
+Upon successful completion, the
+.Fn acl_size
+function shall return the size of the external representation.
+Otherwise, a value of
+.Va -1
+shall be returned and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+The
+.Fn acl_copy_ext
+and
+.Fn acl_copy_ext_native
+functions fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+.It Bq Er ERANGE
+The given buffer is too small to contain the converted external representation.
+.El
+.Pp
+The
+.Fn acl_copy_int
+and
+.Fn acl_copy_int_native
+functions fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The buffer does not contain a valid external representation.
+.El
+.Pp
+The
+.Fn acl_size
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+.El
+.Sh NOTE
+While the external representation may use pre-existing data structures,
+no assumptions on the internal structure should be made.
+.Pp
+The
+.Xr acl_to_text 3
+and
+.Xr acl_from_text 3
+functions also convert to and from a different external representation,
+a human-readable string.
+Neither of these representations are cross-platform, lacking a cross-platform
+standard.
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_from_text 3 ,
+.Xr acl_to_text 3
+.Sh AUTHORS
+.An Michael Smith
+.An Robert N M Watson
is a POSIX.1e call that creates a new ACL entry in the ACL
pointed to by
.Fa acl_p .
+The function will return in
+.Fa entry_p
+a descriptor for this ACL entry.
.Pp
The
.Fn acl_create_entry_np
/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "aclvar.h"
+#if __DARWIN_ACL_EXTENDED_ALLOW != KAUTH_ACE_PERMIT
+# error __DARWIN_ACL_EXTENDED_ALLOW != KAUTH_ACE_PERMIT
+#endif
+#if __DARWIN_ACL_EXTENDED_DENY != KAUTH_ACE_DENY
+# error __DARWIN_ACL_EXTENDED_DENY != KAUTH_ACE_DENY
+#endif
+
int
acl_copy_entry(acl_entry_t dest, acl_entry_t src)
{
ap->a_entries++;
/* initialise new entry */
+ memset(&ap->a_ace[index], 0, sizeof(ap->a_ace[index]));
ap->a_ace[index].ae_magic = _ACL_ENTRY_MAGIC;
ap->a_ace[index].ae_tag = ACL_UNDEFINED_TAG;
/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "aclvar.h"
+#if __DARWIN_ACL_ENTRY_INHERITED != KAUTH_ACE_INHERITED
+# error __DARWIN_ACL_ENTRY_INHERITED != KAUTH_ACE_INHERITED
+#endif
+#if __DARWIN_ACL_ENTRY_FILE_INHERIT != KAUTH_ACE_FILE_INHERIT
+# error __DARWIN_ACL_ENTRY_FILE_INHERIT != KAUTH_ACE_FILE_INHERIT
+#endif
+#if __DARWIN_ACL_ENTRY_DIRECTORY_INHERIT != KAUTH_ACE_DIRECTORY_INHERIT
+# error __DARWIN_ACL_ENTRY_DIRECTORY_INHERIT != KAUTH_ACE_DIRECTORY_INHERIT
+#endif
+#if __DARWIN_ACL_ENTRY_LIMIT_INHERIT != KAUTH_ACE_LIMIT_INHERIT
+# error __DARWIN_ACL_ENTRY_LIMIT_INHERIT != KAUTH_ACE_LIMIT_INHERIT
+#endif
+#if __DARWIN_ACL_ENTRY_ONLY_INHERIT != KAUTH_ACE_ONLY_INHERIT
+# error __DARWIN_ACL_ENTRY_ONLY_INHERIT != KAUTH_ACE_ONLY_INHERIT
+#endif
+#if __DARWIN_ACL_FLAG_NO_INHERIT != KAUTH_ACL_NO_INHERIT
+# error __DARWIN_ACL_FLAG_NO_INHERIT != KAUTH_ACL_NO_INHERIT
+#endif
+
int
acl_add_flag_np(acl_flagset_t flags, acl_flag_t flag)
{
--- /dev/null
+.Dd August 24, 2010
+.Os Darwin
+.Dt ACL_PERMSET_MASK 3
+.Sh NAME
+.Nm acl_permset_mask
+.Nd Manipulate ACL permissions using bitmasks
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_maximal_permset_mask_np "acl_permset_mask_t * mask_p"
+.Ft int
+.Fn acl_get_permset_mask_np "acl_entry_t entry_d" "acl_permset_mask_t * mask_p"
+.Ft int
+.Fn acl_set_permset_mask_np "acl_entry_t entry_d" "acl_permset_mask_t mask"
+.Sh DESCRIPTION
+The
+.Fa acl_permset_mask_t
+functions are a Darwin extension to the POSIX.1e ACL standard which allow
+manipulation of permissions in an
+.Fa acl_entry_t
+using a bitmask of type
+.Fa acl_permset_mask_t
+rather than a constructed acl_permset_t (as done by
+.Xr acl_get_permset 3
+and
+.Xr acl_set_permset 3 ) .
+.Pp
+.Fa acl_permset_mask_t
+values may be constructed using bitwise operations over
+.Fa acl_perm_t
+values.
+.Pp
+.Fn acl_maximal_permset_mask_np
+sets the value pointed to by
+.Fa mask_p
+to a bitmask of all valid
+.Fa acl_perm_t
+values.
+.Pp
+.Fn acl_get_permset_mask_np
+returns via
+.Fa mask_p
+a bitmask of permissions set on the ACL entry
+.Fa entry_d .
+.Pp
+.Fn acl_set_permset_mask_np
+sets the permissions of ACL entry
+.Fa entry_d
+to match the permission bitmask provided by
+.Fa mask .
+.Sh RETURN VALUES
+.Rv -std acl_maximal_permset_mask_np
+.Pp
+.Rv -std acl_get_permset_mask_np
+.Pp
+.Rv -std acl_set_permset_mask_np
+.Sh ERRORS
+The
+.Fn acl_get_permset_mask_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.El
+.Pp
+The
+.Fn acl_set_permset_mask_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.It Bq Er EINVAL
+Argument
+.Fa mask
+is not a valid bitmask of ACL permissions.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh AUTHORS
+.An Jeremy Huddleston
/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2010 Apple, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "aclvar.h"
+#if __DARWIN_ACL_READ_DATA != KAUTH_VNODE_READ_DATA
+# error __DARWIN_ACL_READ_DATA != KAUTH_VNODE_READ_DATA
+#endif
+#if __DARWIN_ACL_LIST_DIRECTORY != KAUTH_VNODE_LIST_DIRECTORY
+# error __DARWIN_ACL_LIST_DIRECTORY != KAUTH_VNODE_LIST_DIRECTORY
+#endif
+#if __DARWIN_ACL_WRITE_DATA != KAUTH_VNODE_WRITE_DATA
+# error __DARWIN_ACL_WRITE_DATA != KAUTH_VNODE_WRITE_DATA
+#endif
+#if __DARWIN_ACL_ADD_FILE != KAUTH_VNODE_ADD_FILE
+# error __DARWIN_ACL_ADD_FILE != KAUTH_VNODE_ADD_FILE
+#endif
+#if __DARWIN_ACL_EXECUTE != KAUTH_VNODE_EXECUTE
+# error __DARWIN_ACL_EXECUTE != KAUTH_VNODE_EXECUTE
+#endif
+#if __DARWIN_ACL_SEARCH != KAUTH_VNODE_SEARCH
+# error __DARWIN_ACL_SEARCH != KAUTH_VNODE_SEARCH
+#endif
+#if __DARWIN_ACL_DELETE != KAUTH_VNODE_DELETE
+# error __DARWIN_ACL_DELETE != KAUTH_VNODE_DELETE
+#endif
+#if __DARWIN_ACL_APPEND_DATA != KAUTH_VNODE_APPEND_DATA
+# error __DARWIN_ACL_APPEND_DATA != KAUTH_VNODE_APPEND_DATA
+#endif
+#if __DARWIN_ACL_ADD_SUBDIRECTORY != KAUTH_VNODE_ADD_SUBDIRECTORY
+# error __DARWIN_ACL_ADD_SUBDIRECTORY != KAUTH_VNODE_ADD_SUBDIRECTORY
+#endif
+#if __DARWIN_ACL_DELETE_CHILD != KAUTH_VNODE_DELETE_CHILD
+# error __DARWIN_ACL_DELETE_CHILD != KAUTH_VNODE_DELETE_CHILD
+#endif
+#if __DARWIN_ACL_READ_ATTRIBUTES != KAUTH_VNODE_READ_ATTRIBUTES
+# error __DARWIN_ACL_READ_ATTRIBUTES != KAUTH_VNODE_READ_ATTRIBUTES
+#endif
+#if __DARWIN_ACL_WRITE_ATTRIBUTES != KAUTH_VNODE_WRITE_ATTRIBUTES
+# error __DARWIN_ACL_WRITE_ATTRIBUTES != KAUTH_VNODE_WRITE_ATTRIBUTES
+#endif
+#if __DARWIN_ACL_READ_EXTATTRIBUTES != KAUTH_VNODE_READ_EXTATTRIBUTES
+# error __DARWIN_ACL_READ_EXTATTRIBUTES != KAUTH_VNODE_READ_EXTATTRIBUTES
+#endif
+#if __DARWIN_ACL_WRITE_EXTATTRIBUTES != KAUTH_VNODE_WRITE_EXTATTRIBUTES
+# error __DARWIN_ACL_WRITE_EXTATTRIBUTES != KAUTH_VNODE_WRITE_EXTATTRIBUTES
+#endif
+#if __DARWIN_ACL_READ_SECURITY != KAUTH_VNODE_READ_SECURITY
+# error __DARWIN_ACL_READ_SECURITY != KAUTH_VNODE_READ_SECURITY
+#endif
+#if __DARWIN_ACL_WRITE_SECURITY != KAUTH_VNODE_WRITE_SECURITY
+# error __DARWIN_ACL_WRITE_SECURITY != KAUTH_VNODE_WRITE_SECURITY
+#endif
+#if __DARWIN_ACL_CHANGE_OWNER != KAUTH_VNODE_CHANGE_OWNER
+# error __DARWIN_ACL_CHANGE_OWNER != KAUTH_VNODE_CHANGE_OWNER
+#endif
+
int
acl_add_perm(acl_permset_t permset, acl_perm_t perm)
{
entry->ae_perms = permset->ap_perms;
return(0);
}
+
+int
+acl_maximal_permset_mask_np(acl_permset_mask_t * mask_p)
+{
+ /* Bitwise or of all possible acl_perm_t values */
+ *mask_p = _ACL_PERMS_MASK;
+ return (0);
+}
+
+int
+acl_get_permset_mask_np(acl_entry_t entry, acl_permset_mask_t * mask_p)
+{
+ _ACL_VALIDATE_ENTRY(entry);
+
+ *mask_p = (acl_permset_mask_t)entry->ae_perms;
+ return (0);
+}
+
+int
+acl_set_permset_mask_np(acl_entry_t entry, acl_permset_mask_t mask)
+{
+ _ACL_VALIDATE_ENTRY(entry);
+ _ACL_VALIDATE_PERM(mask);
+
+ entry->ae_perms = mask;
+ return (0);
+}
/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2010, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <sys/appleapiopts.h>
#include <sys/types.h>
#include <sys/acl.h>
+#include <sys/fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <membership.h>
#include <membershipPriv.h>
#include <pwd.h>
errno = ERANGE;
return(-1);
}
+
+ bzero(ext, reqsize);
+ ext->fsec_magic = OSSwapHostToBigInt32(KAUTH_FILESEC_MAGIC);
+
+ /* special case for _FILESEC_REMOVE_ACL */
+ if (acl == (acl_t)_FILESEC_REMOVE_ACL) {
+ ext->fsec_entrycount = OSSwapHostToBigInt32(KAUTH_FILESEC_NOACL);
+ return(reqsize);
+ }
/* export the header */
- ext->fsec_magic = OSSwapHostToBigInt32(KAUTH_FILESEC_MAGIC);
ext->fsec_entrycount = OSSwapHostToBigInt32(acl->a_entries);
ext->fsec_flags = OSSwapHostToBigInt32(acl->a_flags);
errno = ERANGE;
return(-1);
}
+
+ bzero(ext, reqsize);
+ ext->fsec_magic = KAUTH_FILESEC_MAGIC;
+
+ /* special case for _FILESEC_REMOVE_ACL */
+ if (acl == (acl_t)_FILESEC_REMOVE_ACL) {
+ ext->fsec_entrycount = KAUTH_FILESEC_NOACL;
+ return(reqsize);
+ }
/* export the header */
- ext->fsec_magic = KAUTH_FILESEC_MAGIC;
ext->fsec_entrycount = acl->a_entries;
ext->fsec_flags = acl->a_flags;
- /* XXX owner? */
/* copy ACEs */
for (i = 0; i < acl->a_entries; i++) {
{ACL_ENTRY_DIRECTORY_INHERIT, "directory_inherit", ACL_TYPE_DIR},
{ACL_ENTRY_LIMIT_INHERIT, "limit_inherit", ACL_TYPE_FILE | ACL_TYPE_DIR},
{ACL_ENTRY_ONLY_INHERIT, "only_inherit", ACL_TYPE_DIR},
+ {ACL_FLAG_NO_INHERIT, "no_inherit", ACL_TYPE_ACL},
{0, NULL, 0}
};
if (((uu = (uuid_t *) acl_get_qualifier(entry)) == NULL)
|| (acl_get_tag_type(entry, &tag) != 0)
|| (acl_get_flagset_np(entry, &flags) != 0)
- || (acl_get_permset(entry, &perms) != 0)
- || ((str = uuid_to_name(uu, &id, &isgid)) == NULL)) {
+ || (acl_get_permset(entry, &perms) != 0)) {
if (uu != NULL) acl_free(uu);
continue;
}
uuid_unparse_upper(*uu, uu_str);
- valid = raosnprintf(&buf, &bufsize, len_p, "\n%s:%s:%s:%d:%s",
- isgid ? "group" : "user",
- uu_str,
- str,
- id,
- (tag == ACL_EXTENDED_ALLOW) ? "allow" : "deny");
+ if ((str = uuid_to_name(uu, &id, &isgid)) != NULL) {
+ valid = raosnprintf(&buf, &bufsize, len_p, "\n%s:%s:%s:%d:%s",
+ isgid ? "group" : "user",
+ uu_str,
+ str,
+ id,
+ (tag == ACL_EXTENDED_ALLOW) ? "allow" : "deny");
+ } else {
+ valid = raosnprintf(&buf, &bufsize, len_p, "\nuser:%s:::%s",
+ uu_str,
+ (tag == ACL_EXTENDED_ALLOW) ? "allow" : "deny");
+ }
free(str);
acl_free(uu);
ssize_t
acl_size(acl_t acl)
{
+ /* special case for _FILESEC_REMOVE_ACL */
+ if (acl == (acl_t)_FILESEC_REMOVE_ACL)
+ return KAUTH_FILESEC_SIZE(0);
+
_ACL_VALIDATE_ACL(acl);
return(KAUTH_FILESEC_SIZE(acl->a_entries));
/*
- * Copyright (c) 2004, 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004, 2008, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Argument validation.
*/
+/*
+ * Because of the use of special values for structure pointer (like
+ * _FILESEC_REMOVE_ACL), dereferences causes crashes. Rather than try to
+ * enumerate all such special values, we will assume there are a small
+ * number of these values, centered about zero, so we can just check the
+ * values are in this range. We have to do the check for both ACLs and
+ * ACEs, because the API uses the same routines on ACLs and ACEs.
+ */
+
+#define _ACL_SPECIAL_RANGE 16
-#define _ACL_VALID_ENTRY(_e) ((_e)->ae_magic == _ACL_ENTRY_MAGIC)
+#define _ACL_VALID_ENTRY(_e) ((((intptr_t)(_e)) > _ACL_SPECIAL_RANGE || ((intptr_t)(_e)) < -(_ACL_SPECIAL_RANGE)) && (_e)->ae_magic == _ACL_ENTRY_MAGIC)
-#define _ACL_VALID_ACL(_a) ((_a)->a_magic == _ACL_ACL_MAGIC)
+#define _ACL_VALID_ACL(_a) ((((intptr_t)(_a)) > _ACL_SPECIAL_RANGE || ((intptr_t)(_a)) < -(_ACL_SPECIAL_RANGE)) && (_a)->a_magic == _ACL_ACL_MAGIC)
#define _ACL_ENTRY_CONTAINED(_a, _e) \
((_e) >= &(_a)->a_ace[0]) && ((_e) < &(_a)->a_ace[ACL_MAX_ENTRIES])
_setjmp.s \
setjmp.s \
_sigtramp.s
-
-MDCOPYFILES+= ${.CURDIR}/Platforms/${RC_TARGET_CONFIG}/ppc/libc.syscall.ppc
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
LSCIE1:
.long 0 ; CIE Identifier Tag
.byte 0x3 ; CIE Version
- .ascii "zR\0" ; CIE Augmentation
+ .ascii "zRS\0" ; CIE Augmentation
;; Both these alignment values are unused.
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
_setjmp.s \
setjmp.s \
_sigtramp.s
-
-MDCOPYFILES+= ${.CURDIR}/Platforms/${RC_TARGET_CONFIG}/ppc64/libc.syscall.ppc64
MISRCS += pthread_cancelable.c pthread_cond.c pthread_tsd.c pthread.c \
pthread_mutex.c thread_setup.c stack.s pthread_rwlock.c
+DYLDSRCS += pthread.c pthread_mutex.c pthread_tsd.c
+
.ifdef FEATURE_PLOCKSTAT
${SYMROOTINC}/plockstat.h: ${.CURDIR}/pthreads/plockstat.d
${MKDIR} ${SYMROOTINC}
.endfor
.endif # FEATURE_PLOCKSTAT
-PTHREADS_INSTHDRS += pthread.h pthread_impl.h sched.h
+PTHREADS_INSTHDRS += pthread.h pthread_spis.h pthread_impl.h sched.h
PTHREADS_INSTHDRS := ${PTHREADS_INSTHDRS:S/^/${.CURDIR}\/pthreads\//}
INSTHDRS += ${PTHREADS_INSTHDRS}
#include <sys/resource.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
+#include <sys/mman.h>
#include <machine/vmparam.h>
#include <mach/vm_statistics.h>
+#include <mach/mach_init.h>
#define __APPLE_API_PRIVATE
#include <machine/cpu_capabilities.h>
#include <libkern/OSAtomic.h>
static int _pthread_create_pthread_onstack(pthread_attr_t *attrs, void **stack, pthread_t *thread);
static kern_return_t _pthread_free_pthread_onstack(pthread_t t, int freestruct, int termthread);
static void _pthread_struct_init(pthread_t t, const pthread_attr_t *attrs, void * stack, size_t stacksize, int kernalloc, int nozero);
-static void _pthread_tsd_reinit(pthread_t t);
static int _new_pthread_create_suspended(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
} while(!_spin_lock_try(lock));
}
-extern mach_port_t thread_recycle_port;
+static mach_port_t thread_recycle_port = MACH_PORT_NULL;
/* These are used to keep track of a semaphore pool shared by mutexes and condition
** variables.
static OSSpinLock __workqueue_list_lock = OS_SPINLOCK_INIT;
-static void _pthread_exit(pthread_t self, void *value_ptr);
+static void _pthread_exit(pthread_t self, void *value_ptr) __dead2;
static void _pthread_setcancelstate_exit(pthread_t self, void *value_ptr, int conforming);
static pthread_attr_t _pthread_attr_default = {0};
static void _pthread_workq_init(pthread_workqueue_t wq, const pthread_workqueue_attr_t * attr);
static int kernel_workq_setup = 0;
static volatile int32_t kernel_workq_count = 0;
-static volatile unsigned int user_workq_count = 0;
+static volatile unsigned int user_workq_count = 0; /* number of outstanding workqueues */
+static volatile unsigned int user_workitem_count = 0; /* number of outstanding workitems */
#define KERNEL_WORKQ_ELEM_MAX 64 /* Max number of elements in the kerrel */
static int wqreadyprio = 0; /* current highest prio queue ready with items */
-static int __pthread_workqueue_affinity = 1; /* 0 means no affinity */
__private_extern__ struct __pthread_workitem_pool __pthread_workitem_pool_head = TAILQ_HEAD_INITIALIZER(__pthread_workitem_pool_head);
__private_extern__ struct __pthread_workqueue_pool __pthread_workqueue_pool_head = TAILQ_HEAD_INITIALIZER(__pthread_workqueue_pool_head);
+static struct _pthread_workitem * __workqueue_pool_ptr;
+static size_t __workqueue_pool_size = 0;
+static int __workqueue_nitems = 0;
+
struct _pthread_workqueue_head __pthread_workq0_head;
struct _pthread_workqueue_head __pthread_workq1_head;
struct _pthread_workqueue_head __pthread_workq2_head;
-pthread_workqueue_head_t __pthread_wq_head_tbl[WQ_NUM_PRIO_QS] = {&__pthread_workq0_head, &__pthread_workq1_head, &__pthread_workq2_head};
+struct _pthread_workqueue_head __pthread_workq3_head;
+pthread_workqueue_head_t __pthread_wq_head_tbl[WORKQ_NUM_PRIOQUEUE] = {&__pthread_workq0_head, &__pthread_workq1_head, &__pthread_workq2_head, &__pthread_workq3_head};
static void workqueue_list_lock(void);
static void workqueue_list_unlock(void);
extern void thread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *), void * funarg, size_t stacksize, unsigned int flags);
static pthread_workitem_t alloc_workitem(void);
static void free_workitem(pthread_workitem_t);
+static void grow_workitem(void);
static pthread_workqueue_t alloc_workqueue(void);
static void free_workqueue(pthread_workqueue_t);
static int _pthread_work_internal_init(void);
static void workqueue_exit(pthread_t self, pthread_workqueue_t workq, pthread_workitem_t item);
+void _pthread_fork_child_postinit();
void pthread_workqueue_atfork_prepare(void);
void pthread_workqueue_atfork_parent(void);
static int pthread_setschedparam_internal(pthread_t, mach_port_t, int, const struct sched_param *);
extern pthread_t __bsdthread_create(void *(*func)(void *), void * func_arg, void * stack, pthread_t thread, unsigned int flags);
-extern int __bsdthread_register(void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), void (*)(pthread_t, mach_port_t, void *, pthread_workitem_t, int), int,void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), void (*)(pthread_t, mach_port_t, void *, pthread_workitem_t, int),__uint64_t);
+extern int __bsdthread_register(void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), void (*)(pthread_t, mach_port_t, void *, pthread_workitem_t, int), int,void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), int32_t *,__uint64_t);
extern int __bsdthread_terminate(void * freeaddr, size_t freesize, mach_port_t kport, mach_port_t joinsem);
extern __uint64_t __thread_selfid( void );
extern int __pthread_canceled(int);
kern_return_t res = 0;
vm_address_t freeaddr;
size_t freesize;
- task_t self = mach_task_self();
int thread_count;
mach_port_t kport;
semaphore_t joinsem = SEMAPHORE_NULL;
_pthread_body(pthread_t self)
{
_pthread_set_self(self);
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ if( (self->thread_id = __thread_selfid()) == (__uint64_t)-1)
+ printf("Failed to set thread_id in _pthread_body\n");
+#endif
_pthread_exit(self, (self->fun)(self->arg));
}
void
_pthread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *), void * funarg, size_t stacksize, unsigned int pflags)
{
- int ret;
#if WQ_DEBUG
pthread_t pself;
#endif
t->policy = attrs->policy;
t->param = attrs->param;
t->freeStackOnExit = attrs->freeStackOnExit;
- t->mutexes = (struct _pthread_mutex *)NULL;
+ t->cancel_error = 0;
t->sig = _PTHREAD_SIG;
t->reply_port = MACH_PORT_NULL;
t->cthread_self = NULL;
void
_pthread_struct_init(pthread_t t, const pthread_attr_t *attrs, void * stack, size_t stacksize, int kernalloc, int nozero)
{
- mach_vm_offset_t stackaddr = (mach_vm_offset_t)(long)stack;
+ mach_vm_offset_t stackaddr = (mach_vm_offset_t)(uintptr_t)stack;
if (nozero == 0) {
memset(t, 0, sizeof(*t));
t->schedset = attrs->schedset;
t->tsd[0] = t;
if (kernalloc != 0) {
- stackaddr = (mach_vm_offset_t)(long)t;
+ stackaddr = (mach_vm_offset_t)(uintptr_t)t;
/* if allocated from kernel set values appropriately */
t->stacksize = stacksize;
- t->stackaddr = (void *)(long)stackaddr;
+ t->stackaddr = (void *)(uintptr_t)stackaddr;
t->freeStackOnExit = 1;
- t->freeaddr = (void *)(long)(stackaddr - stacksize - vm_page_size);
+ t->freeaddr = (void *)(uintptr_t)(stackaddr - stacksize - vm_page_size);
t->freesize = pthreadsize + stacksize + vm_page_size;
} else {
t->stacksize = attrs->stacksize;
t->inherit = attrs->inherit;
t->policy = attrs->policy;
t->param = attrs->param;
- t->mutexes = (struct _pthread_mutex *)NULL;
+ t->cancel_error = 0;
t->sig = _PTHREAD_SIG;
t->reply_port = MACH_PORT_NULL;
t->cthread_self = NULL;
t->max_tsd_key = 0;
}
-static void
-_pthread_tsd_reinit(pthread_t t)
-{
- bzero(&t->tsd[1], (_INTERNAL_POSIX_THREAD_KEYS_END-1) * sizeof(void *));
-}
-
-
/* Need to deprecate this in future */
int
_pthread_is_threaded(void)
size_t
pthread_get_stacksize_np(pthread_t t)
{
- int ret,nestingDepth=0;
+ int ret;
size_t size = 0;
- vm_address_t address=0;
- vm_size_t region_size=0;
- struct vm_region_submap_info_64 info;
- mach_msg_type_number_t count;
if (t == NULL)
return(ESRCH);
void * addr = NULL;
if (t == NULL)
- return((void *)(long)ESRCH);
+ return((void *)(uintptr_t)ESRCH);
if(t == pthread_self() || t == &_thread) //since the main thread will not get deallocated from underneath us
return t->stackaddr;
if ((ret = _pthread_find_thread(t)) != 0) {
UNLOCK(_pthread_list_lock);
- return((void *)(long)ret);
+ return((void *)(uintptr_t)ret);
}
addr = t->stackaddr;
UNLOCK(_pthread_list_lock);
pthread_setname_np(const char *threadname)
{
int rval;
- size_t len;
+ int len;
rval = 0;
len = strlen(threadname);
- rval = sysctlbyname("kern.threadname", NULL, 0, threadname, len);
+
+ /* protytype is in pthread_internals.h */
+ rval = proc_setthreadname((void *)threadname, len);
if(rval == 0)
{
- strlcpy((pthread_self())->pthread_name, threadname, len+1);
+ strlcpy((pthread_self())->pthread_name, threadname, MAXTHREADNAMESIZE);
}
return rval;
__kdebug_trace(0x9000008, t, 0, 0, 1, 0);
#endif
if(t->freeStackOnExit)
- vm_deallocate(self, (mach_vm_address_t)(long)t, pthreadsize);
+ vm_deallocate(self, (mach_vm_address_t)(uintptr_t)t, pthreadsize);
else
free(t);
} else if (t->childrun == 0) {
#if PTH_TRACE
__kdebug_trace(0x9000008, t, pthreadsize, 0, 2, 0);
#endif
- vm_deallocate(self, (mach_vm_address_t)(long)t, pthreadsize);
+ vm_deallocate(self, (mach_vm_address_t)(uintptr_t)t, pthreadsize);
} else if (t->childrun == 0) {
TAILQ_INSERT_TAIL(&__pthread_head, t, plist);
_pthread_count++;
return (t1 == t2);
}
-__private_extern__ void
+// Force LLVM not to optimise this to a call to __pthread_set_self, if it does
+// then _pthread_set_self won't be bound when secondary threads try and start up.
+void __attribute__((noinline))
_pthread_set_self(pthread_t p)
{
- extern void __pthread_set_self(pthread_t);
+ extern void __pthread_set_self(void *);
+
if (p == 0) {
- bzero(&_thread, sizeof(struct _pthread));
+ if (_thread.tsd[0] != 0) {
+ bzero(&_thread, sizeof(struct _pthread));
+ }
p = &_thread;
}
p->tsd[0] = p;
- __pthread_set_self(p);
+ __pthread_set_self(&p->tsd[0]);
}
void
/*
* Perform package initialization - called automatically when application starts
*/
-__private_extern__ int
+int
pthread_init(void)
{
pthread_attr_t *attrs;
workq_targetconc[WORKQ_HIGH_PRIOQUEUE] = ncpus;
workq_targetconc[WORKQ_DEFAULT_PRIOQUEUE] = ncpus;
workq_targetconc[WORKQ_LOW_PRIOQUEUE] = ncpus;
+ workq_targetconc[WORKQ_BG_PRIOQUEUE] = ncpus;
mach_port_deallocate(mach_task_self(), host);
/* We ignore the return result here. The ObjC runtime will just have to deal. */
}
#endif
-
+ //added so that thread_recycle_port is initialized on new launch.
+ _pthread_fork_child_postinit();
mig_init(1); /* enable multi-threaded mig interfaces */
if (__oldstyle == 0) {
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
- __bsdthread_register(thread_start, start_wqthread, round_page(sizeof(struct _pthread)), _pthread_start, &workq_targetconc[0], (__uint64_t)(&thread->tsd[__PTK_LIBDISPATCH_KEY0]) - (__uint64_t)thread);
+ __bsdthread_register(thread_start, start_wqthread, round_page(sizeof(struct _pthread)), _pthread_start, &workq_targetconc[0], (uintptr_t)(&thread->tsd[__PTK_LIBDISPATCH_KEY0]) - (uintptr_t)(&thread->tsd[0]));
#else
- __bsdthread_register(_pthread_start, _pthread_wqthread, round_page(sizeof(struct _pthread)), NULL, &workq_targetconc[0], (__uint64_t)&thread->tsd[__PTK_LIBDISPATCH_KEY0] - (__uint64_t)thread);
+ __bsdthread_register(_pthread_start, _pthread_wqthread, round_page(sizeof(struct _pthread)), NULL, &workq_targetconc[0], (uintptr_t)&thread->tsd[__PTK_LIBDISPATCH_KEY0] - (uintptr_t)thread);
#endif
}
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
if( (thread->thread_id = __thread_selfid()) == (__uint64_t)-1)
printf("Failed to set thread_id in pthread_init\n");
- return 0;
#endif
+ return 0;
}
int sched_yield(void)
}
/* This used to be the "magic" that gets the initialization routine called when the application starts */
-static int _do_nothing(void) { return 0; }
-int (*_cthread_init_routine)(void) = _do_nothing;
+/*
+ * (These has been moved to setenv.c, so we can use it to fix a less than 10.5
+ * crt1.o issue)
+ * static int _do_nothing(void) { return 0; }
+ * int (*_cthread_init_routine)(void) = _do_nothing;
+ */
/* Get a semaphore from the pool, growing it if necessary */
#endif
}
+void _pthread_fork_child_postinit() {
+ kern_return_t kr;
+
+ kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &thread_recycle_port);
+ if (kr != KERN_SUCCESS) {
+ abort();
+ }
+}
+
/*
* Query/update the cancelability 'state' of a thread
*/
_pthread_join_cleanup(pthread_t thread, void ** value_ptr, int conforming)
{
kern_return_t res;
- int detached = 0, ret;
+ int ret;
#if PTH_TRACE
__kdebug_trace(0x9000028, thread, 0, 0, 1, 0);
#if PTH_TRACE
__kdebug_trace(0x9000028, thread, 0, 0, 2, 0);
#endif
- vm_deallocate(mach_task_self(), (mach_vm_address_t)(long)thread, pthreadsize);
+ vm_deallocate(mach_task_self(), (mach_vm_address_t)(uintptr_t)thread, pthreadsize);
} else {
thread->sig = _PTHREAD_NO_SIG;
#if PTH_TRACE
case WORKQ_HIGH_PRIOQUEUE:
case WORKQ_DEFAULT_PRIOQUEUE:
case WORKQ_LOW_PRIOQUEUE:
+ case WORKQ_BG_PRIOQUEUE:
attr->queueprio = qprio;
break;
default:
{
int i, error;
pthread_workqueue_head_t headp;
- pthread_workitem_t witemp;
pthread_workqueue_t wq;
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ pthread_t self = pthread_self();
+#endif
if (kernel_workq_setup == 0) {
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
- __bsdthread_register(thread_start, start_wqthread, round_page(sizeof(struct _pthread)),NULL,NULL, NULL);
+ __bsdthread_register(thread_start, start_wqthread, round_page(sizeof(struct _pthread)), _pthread_start, &workq_targetconc[0], (uintptr_t)(&self->tsd[__PTK_LIBDISPATCH_KEY0]) - (uintptr_t)(&self->tsd[0]));
#else
- __bsdthread_register(_pthread_start, _pthread_wqthread, round_page(sizeof(struct _pthread)),NULL,NULL, NULL);
+ __bsdthread_register(_pthread_start, _pthread_wqthread, round_page(sizeof(struct _pthread)),NULL,NULL,0);
#endif
_pthread_wq_attr_default.queueprio = WORKQ_DEFAULT_PRIOQUEUE;
_pthread_wq_attr_default.sig = PTHREAD_WORKQUEUE_ATTR_SIG;
- for( i = 0; i< WQ_NUM_PRIO_QS; i++) {
+ for( i = 0; i< WORKQ_NUM_PRIOQUEUE; i++) {
headp = __pthread_wq_head_tbl[i];
TAILQ_INIT(&headp->wqhead);
headp->next_workq = 0;
}
- /* create work item and workqueue pools */
- witemp = (struct _pthread_workitem *)malloc(sizeof(struct _pthread_workitem) * WORKITEM_POOL_SIZE);
- bzero(witemp, (sizeof(struct _pthread_workitem) * WORKITEM_POOL_SIZE));
- for (i = 0; i < WORKITEM_POOL_SIZE; i++) {
- TAILQ_INSERT_TAIL(&__pthread_workitem_pool_head, &witemp[i], item_entry);
- }
+ __workqueue_pool_ptr = NULL;
+ __workqueue_pool_size = round_page(sizeof(struct _pthread_workitem) * WORKITEM_POOL_SIZE);
+
+ __workqueue_pool_ptr = (struct _pthread_workitem *)mmap(NULL, __workqueue_pool_size,
+ PROT_READ|PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE,
+ 0,
+ 0);
+
+ if (__workqueue_pool_ptr == MAP_FAILED) {
+ /* Not expected to fail, if it does, always malloc for work items */
+ __workqueue_nitems = WORKITEM_POOL_SIZE;
+ __workqueue_pool_ptr = NULL;
+ } else
+ __workqueue_nitems = 0;
+
+ /* sets up the workitem pool */
+ grow_workitem();
+
+ /* since the size is less than a page, leaving this in malloc pool */
wq = (struct _pthread_workqueue *)malloc(sizeof(struct _pthread_workqueue) * WORKQUEUE_POOL_SIZE);
bzero(wq, (sizeof(struct _pthread_workqueue) * WORKQUEUE_POOL_SIZE));
for (i = 0; i < WORKQUEUE_POOL_SIZE; i++) {
if (error = __workq_open()) {
TAILQ_INIT(&__pthread_workitem_pool_head);
TAILQ_INIT(&__pthread_workqueue_pool_head);
- free(witemp);
+ if (__workqueue_pool_ptr != NULL) {
+ munmap((void *)__workqueue_pool_ptr, __workqueue_pool_size);
+ }
free(wq);
return(ENOMEM);
}
pthread_workitem_t witem;
if (TAILQ_EMPTY(&__pthread_workitem_pool_head)) {
- workqueue_list_unlock();
- witem = malloc(sizeof(struct _pthread_workitem));
- witem->gencount = 0;
- workqueue_list_lock();
- } else {
- witem = TAILQ_FIRST(&__pthread_workitem_pool_head);
- TAILQ_REMOVE(&__pthread_workitem_pool_head, witem, item_entry);
+ /* the chunk size is set so some multiple of it is pool size */
+ if (__workqueue_nitems < WORKITEM_POOL_SIZE) {
+ grow_workitem();
+ } else {
+ workqueue_list_unlock();
+ witem = malloc(sizeof(struct _pthread_workitem));
+ workqueue_list_lock();
+ witem->fromcache = 0;
+ goto out;
+ }
}
+ witem = TAILQ_FIRST(&__pthread_workitem_pool_head);
+ TAILQ_REMOVE(&__pthread_workitem_pool_head, witem, item_entry);
+ witem->fromcache = 1;
+out:
+ witem->flags = 0;
+ witem->item_entry.tqe_next = 0;
+ witem->item_entry.tqe_prev = 0;
+ user_workitem_count++;
return(witem);
}
static void
free_workitem(pthread_workitem_t witem)
{
- witem->gencount++;
- TAILQ_INSERT_TAIL(&__pthread_workitem_pool_head, witem, item_entry);
+ user_workitem_count--;
+ witem->flags = 0;
+ if (witem->fromcache != 0)
+ TAILQ_INSERT_TAIL(&__pthread_workitem_pool_head, witem, item_entry);
+ else
+ free(witem);
+}
+
+static void
+grow_workitem(void)
+{
+ pthread_workitem_t witemp;
+ int i;
+
+ witemp = &__workqueue_pool_ptr[__workqueue_nitems];
+ bzero(witemp, (sizeof(struct _pthread_workitem) * WORKITEM_CHUNK_SIZE));
+ for (i = 0; i < WORKITEM_CHUNK_SIZE; i++) {
+ witemp[i].fromcache = 1;
+ TAILQ_INSERT_TAIL(&__pthread_workitem_pool_head, &witemp[i], item_entry);
+ }
+ __workqueue_nitems += WORKITEM_CHUNK_SIZE;
}
/* This routine is called with list lock held */
loop:
while (kernel_workq_count < KERNEL_WORKQ_ELEM_MAX) {
found = 0;
- for (i = 0; i < WQ_NUM_PRIO_QS; i++) {
+ for (i = 0; i < WORKQ_NUM_PRIOQUEUE; i++) {
wqreadyprio = i; /* because there is nothing else higher to run */
headp = __pthread_wq_head_tbl[i];
#if WQ_LISTTRACE
__kdebug_trace(0x90080a8, workq, &workq->item_listhead, workq->item_listhead.tqh_first, workq->item_listhead.tqh_last, 0);
#endif
- witem->flags = 0;
free_workitem(witem);
#if WQ_TRACE
__kdebug_trace(0x9000064, 4, workq->barrier_count, 0, 0, 0);
__kdebug_trace(0x900006c, workq, workq->kq_count, 0, 0xff, 0);
#endif
}
- witem->flags = 0;
free_workitem(witem);
workq->flags |= PTHREAD_WORKQ_DESTROYED;
#if WQ_TRACE
static void
workqueue_exit(pthread_t self, pthread_workqueue_t workq, pthread_workitem_t item)
{
- pthread_attr_t *attrs = &_pthread_attr_default;
pthread_workitem_t baritem;
pthread_workqueue_head_t headp;
void (*func)(pthread_workqueue_t, void *);
#if WQ_TRACE
__kdebug_trace(0x9000070, self, 1, item->func_arg, workq->kq_count, 0);
#endif
- item->flags = 0;
free_workitem(item);
if ((workq->flags & PTHREAD_WORKQ_BARRIER_ON) == PTHREAD_WORKQ_BARRIER_ON) {
#if WQ_LISTTRACE
__kdebug_trace(0x90080a8, workq, &workq->item_listhead, workq->item_listhead.tqh_first, workq->item_listhead.tqh_last, 0);
#endif
- baritem->flags = 0;
free_workitem(baritem);
workq->flags &= ~PTHREAD_WORKQ_BARRIER_ON;
#if WQ_TRACE
witem = alloc_workitem();
witem->func = workitem_func;
witem->func_arg = workitem_arg;
- witem->flags = 0;
witem->workq = workq;
- witem->item_entry.tqe_next = 0;
- witem->item_entry.tqe_prev = 0;
/* alloc workitem can drop the lock, check the state */
if ((workq->flags & (PTHREAD_WORKQ_IN_TERMINATE | PTHREAD_WORKQ_DESTROYED)) != 0) {
if (itemhandlep != NULL)
*itemhandlep = (pthread_workitem_handle_t *)witem;
if (gencountp != NULL)
- *gencountp = witem->gencount;
+ *gencountp = 0;
#if WQ_TRACE
__kdebug_trace(0x9008090, witem, witem->func, witem->func_arg, workq, 0);
#endif
int
pthread_workqueue_getovercommit_np(pthread_workqueue_t workq, unsigned int *ocommp)
{
- pthread_workitem_t witem;
-
if (valid_workq(workq) == 0) {
return(EINVAL);
}
}
-/* DEPRECATED
-int pthread_workqueue_removeitem_np(pthread_workqueue_t workq, pthread_workitem_handle_t itemhandle, unsigned int gencount)
-int pthread_workqueue_addbarrier_np(pthread_workqueue_t workq, void (* callback_func)(pthread_workqueue_t, void *), void * callback_arg, pthread_workitem_handle_t *itemhandlep, unsigned int *gencountp)
-int pthread_workqueue_suspend_np(pthread_workqueue_t workq)
-int pthread_workqueue_resume_np(pthread_workqueue_t workq)
-*/
-
#else /* !BUILDING_VARIANT ] [ */
extern int __unix_conforming;
extern int _pthread_count;
int already_exited, res;
void * dummy;
semaphore_t death;
- mach_port_t joinport;
- int newstyle = 0;
+ int newstyle;
LOCK(thread->lock);
already_exited = (thread->detached & _PTHREAD_EXITED);
*/
#include <sys/cdefs.h>
+#include <Availability.h>
__BEGIN_DECLS
/*
#define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}}
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER {_PTHREAD_ERRORCHECK_MUTEX_SIG_init, {0}}
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER {_PTHREAD_RECURSIVE_MUTEX_SIG_init, {0}}
+#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE */
+
/*
* Condition variable attributes
*/
/* returns non-zero if pthread_create or cthread_fork have been called */
int pthread_is_threaded_np(void);
-#if defined(__i386__) || defined(__x86_64__)
-int pthread_threadid_np(pthread_t,__uint64_t*);
-#endif
+int pthread_threadid_np(pthread_t,__uint64_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
+
+int pthread_rwlock_longrdlock_np(pthread_rwlock_t *) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t *) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+int pthread_rwlock_downgrade_np(pthread_rwlock_t *);
+int pthread_rwlock_upgrade_np(pthread_rwlock_t *);
+int pthread_rwlock_tryupgrade_np(pthread_rwlock_t *);
+int pthread_rwlock_held_np(pthread_rwlock_t *);
+int pthread_rwlock_rdheld_np(pthread_rwlock_t *);
+int pthread_rwlock_wrheld_np(pthread_rwlock_t *);
/*SPI to set and get pthread name*/
-int pthread_getname_np(pthread_t,char*,size_t);
-int pthread_setname_np(const char*);
+int pthread_getname_np(pthread_t,char*,size_t) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
+int pthread_setname_np(const char*) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
/* returns non-zero if the current thread is the main thread */
int pthread_main_np(void);
void *);
int pthread_kill(pthread_t, int);
-pthread_t pthread_from_mach_thread_np(mach_port_t);
+pthread_t pthread_from_mach_thread_np(mach_port_t) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
//Begin-Libc
#ifndef LIBC_ALIAS_PTHREAD_SIGMASK
#define PLOCKSTAT_MUTEX_RELEASE(x, y)
#endif /* PLOCKSTAT */
-
extern int __semwait_signal(int, int, int, int, int64_t, int32_t);
extern int _pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *, int);
extern int __unix_conforming;
+extern int usenew_mtximpl;
#ifdef PR_5243343
/* 5243343 - temporary hack to detect if we are running the conformance test */
extern int PR_5243343_flag;
#endif /* PR_5243343 */
-#if defined(__i386__) || defined(__x86_64__)
-__private_extern__ int __new_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime, int isRelative, int isconforming);
-extern int _new_pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *, int);
-extern int _new_pthread_cond_destroy(pthread_cond_t *);
-extern int _new_pthread_cond_destroy_locked(pthread_cond_t *);
-int _new_pthread_cond_broadcast(pthread_cond_t *cond);
-int _new_pthread_cond_signal_thread_np(pthread_cond_t *cond, pthread_t thread);
-int _new_pthread_cond_signal(pthread_cond_t *cond);
-int _new_pthread_cond_timedwait_relative_np(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
-int _new_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
-int _new_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
-static void _new_cond_cleanup(void *arg);
-static void _new_cond_dropwait(npthread_cond_t * cond);
-
+__private_extern__ int _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime, int isRelative, int isconforming);
+#ifndef BUILDING_VARIANT
+static void cond_cleanup(void *arg);
+static void cond_dropwait(npthread_cond_t * cond, int error, uint32_t updateval);
+static void __pthread_cond_set_signature(npthread_cond_t * cond);
+static int _pthread_cond_destroy_locked(pthread_cond_t *cond);
+#endif
#if defined(__LP64__)
-#define COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt) \
+#define COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt, c_sseqcnt) \
{ \
if (cond->misalign != 0) { \
c_lseqcnt = &cond->c_seq[1]; \
- c_useqcnt = &cond->c_seq[2]; \
+ c_sseqcnt = &cond->c_seq[2]; \
+ c_useqcnt = &cond->c_seq[0]; \
} else { \
/* aligned */ \
c_lseqcnt = &cond->c_seq[0]; \
- c_useqcnt = &cond->c_seq[1]; \
+ c_sseqcnt = &cond->c_seq[1]; \
+ c_useqcnt = &cond->c_seq[2]; \
} \
}
#else /* __LP64__ */
-#define COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt) \
+#define COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt, c_sseqcnt) \
{ \
if (cond->misalign != 0) { \
c_lseqcnt = &cond->c_seq[1]; \
- c_useqcnt = &cond->c_seq[2]; \
+ c_sseqcnt = &cond->c_seq[2]; \
+ c_useqcnt = &cond->c_seq[0]; \
} else { \
/* aligned */ \
c_lseqcnt = &cond->c_seq[0]; \
- c_useqcnt = &cond->c_seq[1]; \
+ c_sseqcnt = &cond->c_seq[1]; \
+ c_useqcnt = &cond->c_seq[2]; \
} \
}
#endif /* __LP64__ */
#define _KSYN_TRACE_UM_CVWAIT 0x9000070
#define _KSYN_TRACE_UM_CVSIG 0x9000074
#define _KSYN_TRACE_UM_CVBRD 0x9000078
+#define _KSYN_TRACE_UM_CDROPWT 0x90000a0
+#define _KSYN_TRACE_UM_CVCLRPRE 0x90000a4
#endif /* _KSYN_TRACE_ */
-#endif /* __i386__ || __x86_64__ */
#ifndef BUILDING_VARIANT /* [ */
-/*
- * Destroy a condition variable.
- */
-int
-pthread_cond_destroy(pthread_cond_t *cond)
-{
- int ret;
- int sig = cond->sig;
-
- /* to provide backwards compat for apps using united condtn vars */
- if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init))
- return(EINVAL);
-
- LOCK(cond->lock);
- if (cond->sig == _PTHREAD_COND_SIG)
- {
-#if defined(__i386__) || defined(__x86_64__)
- if (cond->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_cond_destroy_locked(cond);
- UNLOCK(cond->lock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
- if (cond->busy == (pthread_mutex_t *)NULL)
- {
- cond->sig = _PTHREAD_NO_SIG;
- ret = 0;
- } else
- ret = EBUSY;
- } else
- ret = EINVAL; /* Not an initialized condition variable structure */
- UNLOCK(cond->lock);
- return (ret);
-}
-
-
-/*
- * Signal a condition variable, waking up all threads waiting for it.
- */
-int
-pthread_cond_broadcast(pthread_cond_t *cond)
-{
- kern_return_t kern_res;
- semaphore_t sem;
- int sig = cond->sig;
-
- /* to provide backwards compat for apps using united condtn vars */
- if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init))
- return(EINVAL);
-
- LOCK(cond->lock);
- if (cond->sig != _PTHREAD_COND_SIG)
- {
- int res;
-
- if (cond->sig == _PTHREAD_COND_SIG_init)
- {
- _pthread_cond_init(cond, NULL, 0);
- res = 0;
- } else
- res = EINVAL; /* Not a condition variable */
- UNLOCK(cond->lock);
- return (res);
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if (cond->pshared == PTHREAD_PROCESS_SHARED) {
- UNLOCK(cond->lock);
- return(_new_pthread_cond_broadcast(cond));
- }
-#endif /* __i386__ || __x86_64__ */
- else if ((sem = cond->sem) == SEMAPHORE_NULL)
- {
- /* Avoid kernel call since there are no waiters... */
- UNLOCK(cond->lock);
- return (0);
- }
- cond->sigspending++;
- UNLOCK(cond->lock);
-
- PTHREAD_MACH_CALL(semaphore_signal_all(sem), kern_res);
-
- LOCK(cond->lock);
- cond->sigspending--;
- if (cond->waiters == 0 && cond->sigspending == 0)
- {
- cond->sem = SEMAPHORE_NULL;
- restore_sem_to_pool(sem);
- }
- UNLOCK(cond->lock);
- if (kern_res != KERN_SUCCESS)
- return (EINVAL);
- return (0);
-}
-
-/*
- * Signal a condition variable, waking a specified thread.
- */
-int
-pthread_cond_signal_thread_np(pthread_cond_t *cond, pthread_t thread)
-{
- kern_return_t kern_res;
- semaphore_t sem;
- int sig = cond->sig;
-
- /* to provide backwards compat for apps using united condtn vars */
-
- if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init))
- return(EINVAL);
- LOCK(cond->lock);
- if (cond->sig != _PTHREAD_COND_SIG)
- {
- int ret;
-
- if (cond->sig == _PTHREAD_COND_SIG_init)
- {
- _pthread_cond_init(cond, NULL, 0);
- ret = 0;
- } else
- ret = EINVAL; /* Not a condition variable */
- UNLOCK(cond->lock);
- return (ret);
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if (cond->pshared == PTHREAD_PROCESS_SHARED) {
- UNLOCK(cond->lock);
- return(_new_pthread_cond_signal_thread_np(cond, thread));
- }
-#endif /* __i386__ || __x86_64__ */
- else if ((sem = cond->sem) == SEMAPHORE_NULL)
- {
- /* Avoid kernel call since there are not enough waiters... */
- UNLOCK(cond->lock);
- return (0);
- }
- cond->sigspending++;
- UNLOCK(cond->lock);
-
- if (thread == (pthread_t)NULL)
- {
- kern_res = semaphore_signal_thread(sem, THREAD_NULL);
- if (kern_res == KERN_NOT_WAITING)
- kern_res = KERN_SUCCESS;
- }
- else if (thread->sig == _PTHREAD_SIG)
- {
- PTHREAD_MACH_CALL(semaphore_signal_thread(
- sem, pthread_mach_thread_np(thread)), kern_res);
- }
- else
- kern_res = KERN_FAILURE;
-
- LOCK(cond->lock);
- cond->sigspending--;
- if (cond->waiters == 0 && cond->sigspending == 0)
- {
- cond->sem = SEMAPHORE_NULL;
- restore_sem_to_pool(sem);
- }
- UNLOCK(cond->lock);
- if (kern_res != KERN_SUCCESS)
- return (EINVAL);
- return (0);
-}
-
-/*
- * Signal a condition variable, waking only one thread.
- */
-int
-pthread_cond_signal(pthread_cond_t *cond)
-{
- return pthread_cond_signal_thread_np(cond, NULL);
-}
-
-/*
- * Manage a list of condition variables associated with a mutex
- */
-
-static void
-_pthread_cond_add(pthread_cond_t *cond, pthread_mutex_t *mutex)
-{
- pthread_cond_t *c;
- LOCK(mutex->lock);
- if ((c = mutex->busy) != (pthread_cond_t *)NULL)
- {
- c->prev = cond;
- }
- cond->next = c;
- cond->prev = (pthread_cond_t *)NULL;
- mutex->busy = cond;
- UNLOCK(mutex->lock);
- if (cond->sem == SEMAPHORE_NULL)
- cond->sem = new_sem_from_pool();
-}
-
-static void
-_pthread_cond_remove(pthread_cond_t *cond, pthread_mutex_t *mutex)
-{
- pthread_cond_t *n, *p;
-
- LOCK(mutex->lock);
- if ((n = cond->next) != (pthread_cond_t *)NULL)
- {
- n->prev = cond->prev;
- }
- if ((p = cond->prev) != (pthread_cond_t *)NULL)
- {
- p->next = cond->next;
- }
- else
- { /* This is the first in the list */
- mutex->busy = n;
- }
- UNLOCK(mutex->lock);
- if (cond->sigspending == 0)
- {
- restore_sem_to_pool(cond->sem);
- cond->sem = SEMAPHORE_NULL;
- }
-}
-
-static void
-cond_cleanup(void *arg)
-{
- pthread_cond_t *cond = (pthread_cond_t *)arg;
- pthread_mutex_t *mutex;
-// 4597450: begin
- pthread_t thread = pthread_self();
- int thcanceled = 0;
-
- LOCK(thread->lock);
- thcanceled = (thread->detached & _PTHREAD_WASCANCEL);
- UNLOCK(thread->lock);
-
- if (thcanceled == 0)
- return;
-
-// 4597450: end
- LOCK(cond->lock);
- mutex = cond->busy;
- cond->waiters--;
- if (cond->waiters == 0) {
- _pthread_cond_remove(cond, mutex);
- cond->busy = (pthread_mutex_t *)NULL;
- }
- UNLOCK(cond->lock);
-
- /*
- ** Can't do anything if this fails -- we're on the way out
- */
- (void)pthread_mutex_lock(mutex);
-}
-
-/*
- * Suspend waiting for a condition variable.
- * Note: we have to keep a list of condition variables which are using
- * this same mutex variable so we can detect invalid 'destroy' sequences.
- * If isconforming < 0, we skip the _pthread_testcancel(), but keep the
- * remaining conforming behavior..
- */
-__private_extern__ int
-_pthread_cond_wait(pthread_cond_t *cond,
- pthread_mutex_t *mutex,
- const struct timespec *abstime,
- int isRelative,
- int isconforming)
-{
- int res;
- kern_return_t kern_res = KERN_SUCCESS;
- int wait_res = 0;
- pthread_mutex_t *busy;
- mach_timespec_t then = {0, 0};
- struct timespec cthen = {0,0};
- int sig = cond->sig;
- int msig = mutex->sig;
-extern void _pthread_testcancel(pthread_t thread, int isconforming);
-
- /* to provide backwards compat for apps using united condtn vars */
- if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init))
- return(EINVAL);
-
- if (isconforming) {
- if((msig != _PTHREAD_MUTEX_SIG) && (msig != _PTHREAD_MUTEX_SIG_init))
- return(EINVAL);
- if (isconforming > 0)
- _pthread_testcancel(pthread_self(), 1);
- }
- LOCK(cond->lock);
- if (cond->sig != _PTHREAD_COND_SIG)
- {
- if (cond->sig != _PTHREAD_COND_SIG_init)
- {
- UNLOCK(cond->lock);
- return (EINVAL); /* Not a condition variable */
- }
- _pthread_cond_init(cond, NULL, 0);
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if (cond->pshared == PTHREAD_PROCESS_SHARED) {
- UNLOCK(cond->lock);
- return(__new_pthread_cond_wait(cond, mutex, abstime, isRelative, isconforming));
- }
-#endif /* __i386__ || __x86_64__ */
-
- if (abstime) {
- if (!isconforming)
- {
- if (isRelative == 0) {
- struct timespec now;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- TIMEVAL_TO_TIMESPEC(&tv, &now);
-
- /* Compute relative time to sleep */
- then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
- then.tv_sec = abstime->tv_sec - now.tv_sec;
- if (then.tv_nsec < 0)
- {
- then.tv_nsec += NSEC_PER_SEC;
- then.tv_sec--;
- }
- if (((int)then.tv_sec < 0) ||
- ((then.tv_sec == 0) && (then.tv_nsec == 0)))
- {
- UNLOCK(cond->lock);
- return ETIMEDOUT;
- }
- } else {
- then.tv_sec = abstime->tv_sec;
- then.tv_nsec = abstime->tv_nsec;
- }
- if (then.tv_nsec >= NSEC_PER_SEC) {
- UNLOCK(cond->lock);
- return EINVAL;
- }
- } else {
- if (isRelative == 0) {
- /* preflight the checks for failures */
- struct timespec now;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- TIMEVAL_TO_TIMESPEC(&tv, &now);
-
- /* Compute relative time to sleep */
- then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
- then.tv_sec = abstime->tv_sec - now.tv_sec;
- if (then.tv_nsec < 0)
- {
- then.tv_nsec += NSEC_PER_SEC;
- then.tv_sec--;
- }
- if (((int)then.tv_sec < 0) ||
- ((then.tv_sec == 0) && (then.tv_nsec == 0)))
- {
- UNLOCK(cond->lock);
- return ETIMEDOUT;
- }
- if (then.tv_nsec >= NSEC_PER_SEC) {
- UNLOCK(cond->lock);
- return EINVAL;
- }
- }
- /* we can cleanup this code and pass the calculated time
- * to the kernel. But kernel is going to do the same. TILL
- * we change the kernel do this anyway
- */
- cthen.tv_sec = abstime->tv_sec;
- cthen.tv_nsec = abstime->tv_nsec;
- if ((cthen.tv_sec < 0) || (cthen.tv_nsec < 0)) {
- UNLOCK(cond->lock);
- return EINVAL;
- }
- if (cthen.tv_nsec >= NSEC_PER_SEC) {
- UNLOCK(cond->lock);
- return EINVAL;
- }
- }
- }
-
- if (++cond->waiters == 1)
- {
- _pthread_cond_add(cond, mutex);
- cond->busy = mutex;
- }
- else if ((busy = cond->busy) != mutex)
- {
- /* Must always specify the same mutex! */
- cond->waiters--;
- UNLOCK(cond->lock);
- return (EINVAL);
- }
- UNLOCK(cond->lock);
-
- LOCK(mutex->lock);
- if (--mutex->mtxopts.options.lock_count == 0)
- {
- PLOCKSTAT_MUTEX_RELEASE(mutex, (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)? 1:0);
-
- if (mutex->sem == SEMAPHORE_NULL)
- mutex->sem = new_sem_from_pool();
- mutex->owner = _PTHREAD_MUTEX_OWNER_SWITCHING;
- UNLOCK(mutex->lock);
-
- if (!isconforming) {
- if (abstime) {
- kern_res = semaphore_timedwait_signal(cond->sem, mutex->sem, then);
- } else {
- PTHREAD_MACH_CALL(semaphore_wait_signal(cond->sem, mutex->sem), kern_res);
- }
- } else {
- pthread_cleanup_push(cond_cleanup, (void *)cond);
- wait_res = __semwait_signal(cond->sem, mutex->sem, abstime != NULL, isRelative,
- (int64_t)cthen.tv_sec, (int32_t)cthen.tv_nsec);
- pthread_cleanup_pop(0);
- }
- } else {
- PLOCKSTAT_MUTEX_RELEASE(mutex, (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)? 1:0);
- UNLOCK(mutex->lock);
- if (!isconforming) {
- if (abstime) {
- kern_res = semaphore_timedwait(cond->sem, then);
- } else {
- PTHREAD_MACH_CALL(semaphore_wait(cond->sem), kern_res);
- }
- } else {
- pthread_cleanup_push(cond_cleanup, (void *)cond);
- wait_res = __semwait_signal(cond->sem, 0, abstime != NULL, isRelative,
- (int64_t)cthen.tv_sec, (int32_t)cthen.tv_nsec);
- pthread_cleanup_pop(0);
- }
-
- }
-
- LOCK(cond->lock);
- cond->waiters--;
- if (cond->waiters == 0)
- {
- _pthread_cond_remove(cond, mutex);
- cond->busy = (pthread_mutex_t *)NULL;
- }
- UNLOCK(cond->lock);
- if ((res = pthread_mutex_lock(mutex)) != 0)
- return (res);
-
- if (!isconforming) {
- /* KERN_ABORTED can be treated as a spurious wakeup */
- if ((kern_res == KERN_SUCCESS) || (kern_res == KERN_ABORTED))
- return (0);
- else if (kern_res == KERN_OPERATION_TIMED_OUT)
- return (ETIMEDOUT);
- return (EINVAL);
- } else {
- if (wait_res < 0) {
- if (errno == ETIMEDOUT) {
- return ETIMEDOUT;
- } else if (errno == EINTR) {
- /*
- ** EINTR can be treated as a spurious wakeup unless we were canceled.
- */
- return 0;
- }
- return EINVAL;
- }
- return 0;
- }
-}
-
-
-int
-pthread_cond_timedwait_relative_np(pthread_cond_t *cond,
- pthread_mutex_t *mutex,
- const struct timespec *abstime)
-{
- return (_pthread_cond_wait(cond, mutex, abstime, 1, 0));
-}
-
int
pthread_condattr_init(pthread_condattr_t *attr)
{
}
-__private_extern__ int
-_pthread_cond_init(pthread_cond_t *cond,
- const pthread_condattr_t *attr,
- int conforming)
-{
- cond->next = (pthread_cond_t *)NULL;
- cond->prev = (pthread_cond_t *)NULL;
- cond->busy = (pthread_mutex_t *)NULL;
- cond->waiters = 0;
- cond->sigspending = 0;
- if (conforming) {
- if (attr)
- cond->pshared = attr->pshared;
- else
- cond->pshared = _PTHREAD_DEFAULT_PSHARED;
- } else
- cond->pshared = _PTHREAD_DEFAULT_PSHARED;
- cond->sem = SEMAPHORE_NULL;
- cond->sig = _PTHREAD_COND_SIG;
- return (0);
-}
/* temp home till pshared is fixed correctly */
if (attr->sig == _PTHREAD_COND_ATTR_SIG)
{
#if __DARWIN_UNIX03
-#ifdef PR_5243343
- if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED && PR_5243343_flag))
-#else /* !PR_5243343 */
if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED))
-#endif /* PR_5243343 */
#else /* __DARWIN_UNIX03 */
if ( pshared == PTHREAD_PROCESS_PRIVATE)
#endif /* __DARWIN_UNIX03 */
{
- attr->pshared = pshared;
+ attr->pshared = pshared;
return (0);
- } else
- {
+ } else {
return (EINVAL); /* Invalid parameter */
}
} else
}
-#if defined(__i386__) || defined(__x86_64__)
-
__private_extern__ int
-_new_pthread_cond_init(pthread_cond_t *ocond,
+_pthread_cond_init(pthread_cond_t *ocond,
const pthread_condattr_t *attr,
int conforming)
{
cond->c_seq[0] = 0;
cond->c_seq[1] = 0;
cond->c_seq[2] = 0;
-
cond->rfu = 0;
+
if (((uintptr_t)cond & 0x07) != 0) {
cond->misalign = 1;
+ cond->c_seq[2] = PTH_RWS_CV_CBIT;
} else {
cond->misalign = 0;
+ cond->c_seq[1] = PTH_RWS_CV_CBIT; /* set Sword to 0c */
}
if (conforming) {
if (attr)
cond->pshared = _PTHREAD_DEFAULT_PSHARED;
} else
cond->pshared = _PTHREAD_DEFAULT_PSHARED;
- cond->sig = _PTHREAD_COND_SIG;
+ /*
+ * For the new style mutex, interlocks are not held all the time.
+ * We needed the signature to be set in the end. And we need
+ * to protect against the code getting reorganized by compiler.
+ * cond->sig = _PTHREAD_COND_SIG;
+ */
+ __pthread_cond_set_signature(cond);
return (0);
}
int
-_new_pthread_cond_destroy(pthread_cond_t * ocond)
+pthread_cond_destroy(pthread_cond_t * ocond)
{
npthread_cond_t *cond = (npthread_cond_t *)ocond;
int ret;
+ /* to provide backwards compat for apps using united condtn vars */
+ if((cond->sig != _PTHREAD_COND_SIG) && (cond->sig != _PTHREAD_COND_SIG_init))
+ return(EINVAL);
+
LOCK(cond->lock);
- ret = _new_pthread_cond_destroy_locked(ocond);
+ ret = _pthread_cond_destroy_locked(ocond);
UNLOCK(cond->lock);
return(ret);
}
-int
-_new_pthread_cond_destroy_locked(pthread_cond_t * ocond)
+static int
+_pthread_cond_destroy_locked(pthread_cond_t * ocond)
{
npthread_cond_t *cond = (npthread_cond_t *)ocond;
int ret;
- int sig = cond->sig;
- uint32_t * c_lseqcnt;
- uint32_t * c_useqcnt;
- uint32_t lgenval , ugenval;
-
- /* to provide backwards compat for apps using united condtn vars */
- if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init))
- return(EINVAL);
+ volatile uint32_t * c_lseqcnt, *c_useqcnt, *c_sseqcnt;
+ uint32_t lcntval , ucntval, scntval;
+ uint64_t oldval64, newval64;
+retry:
if (cond->sig == _PTHREAD_COND_SIG)
{
- COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt);
-retry:
- lgenval = *c_lseqcnt;
- ugenval = *c_useqcnt;
- if (lgenval == ugenval)
- {
+ COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt, c_sseqcnt);
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
+
+ if ((lcntval & PTHRW_COUNT_MASK) == (scntval & PTHRW_COUNT_MASK)) {
+ /* validate it is not busy */
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+ newval64 = oldval64;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry;
cond->sig = _PTHREAD_NO_SIG;
ret = 0;
} else
ret = EBUSY;
+ } else if (cond->sig == _PTHREAD_COND_SIG_init) {
+ cond->sig = _PTHREAD_NO_SIG;
+ ret = 0;
} else
ret = EINVAL; /* Not an initialized condition variable structure */
return (ret);
* Signal a condition variable, waking up all threads waiting for it.
*/
int
-_new_pthread_cond_broadcast(pthread_cond_t *ocond)
+pthread_cond_broadcast(pthread_cond_t *ocond)
{
npthread_cond_t * cond = (npthread_cond_t *)ocond;
int sig = cond->sig;
- npthread_mutex_t * mutex;
- uint32_t lgenval, ugenval, mgen, ugen, flags, mtxgen, mtxugen, notify;
- int diffgen, retval, dropcount, mutexrefs;
- uint64_t oldval64, newval64;
- uint32_t * c_lseqcnt;
- uint32_t * c_useqcnt;
+ uint32_t flags, updateval;
+ uint32_t lcntval , ucntval, scntval;
+ uint64_t oldval64, newval64, mugen, cvlsgen, cvudgen, mtid=0;
+ int diffgen, error = 0;
+ volatile uint32_t * c_lseqcnt, *c_useqcnt, *c_sseqcnt;
uint32_t * pmtx = NULL;
-
+ uint32_t nlval, ulval;
+ int needclearpre = 0, retry_count = 0;
/* to provide backwards compat for apps using united condtn vars */
if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init))
if (sig != _PTHREAD_COND_SIG)
{
- int res;
-
LOCK(cond->lock);
if (cond->sig == _PTHREAD_COND_SIG_init)
{
- _new_pthread_cond_init(ocond, NULL, 0);
- res = 0;
+ _pthread_cond_init(ocond, NULL, 0);
+ /* just inited nothing to post */
+ UNLOCK(cond->lock);
+ return (0);
} else if (cond->sig != _PTHREAD_COND_SIG) {
- res = EINVAL; /* Not a condition variable */
+ /* Not a condition variable */
UNLOCK(cond->lock);
- return (res);
+ return (EINVAL);
}
UNLOCK(cond->lock);
}
(void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_START, (uint32_t)cond, 0, 0, 0, 0);
#endif
- COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt);
+ COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt, c_sseqcnt);
retry:
- lgenval = *c_lseqcnt;
- ugenval = *c_useqcnt;
- diffgen = lgenval - ugenval; /* pendig waiters */
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, (uint32_t)cond, lcntval, ucntval, scntval, 0);
+#endif
- if (diffgen <= 0) {
- return(0);
+ if (((lcntval & PTHRW_COUNT_MASK) == (scntval & PTHRW_COUNT_MASK)) ||
+ ((lcntval & PTHRW_COUNT_MASK) == (ucntval & PTHRW_COUNT_MASK))) {
+ /* validate it is spurious and return */
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+ newval64 = oldval64;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_END, (uint32_t)cond, 0, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, (uint32_t)cond, lcntval, ucntval, 0xf1f1f1f1, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_END, (uint32_t)cond, scntval, 0, 0xf1f1f1f1, 0);
#endif
+ return(0);
}
-
- mutex = cond->busy;
-
- if (OSAtomicCompareAndSwap32(ugenval, ugenval+diffgen, (volatile int *)c_useqcnt) != TRUE)
- goto retry;
-#ifdef COND_MTX_WAITQUEUEMOVE
+ if (is_seqhigher((ucntval & PTHRW_COUNT_MASK), (lcntval & PTHRW_COUNT_MASK)) || is_seqhigher((scntval & PTHRW_COUNT_MASK), (lcntval & PTHRW_COUNT_MASK))) {
+ /* since ucntval may be newer, just redo */
+ retry_count++;
+ if (retry_count > 8192) {
+ return(EAGAIN);
+ } else {
+ sched_yield();
+ goto retry;
+ }
+ }
- if ((mutex != NULL) && cond->pshared != PTHREAD_PROCESS_SHARED) {
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, (uint32_t)cond, 1, diffgen, 0, 0);
-#endif
- (void)__mtx_holdlock(mutex, diffgen, &flags, &pmtx, &mgen, &ugen);
- mutexrefs = 1;
+ if (is_seqlower(ucntval & PTHRW_COUNT_MASK, scntval & PTHRW_COUNT_MASK) != 0) {
+ /* If U < S, set U = S+diff due to intr's TO, etc */
+ ulval = (scntval & PTHRW_COUNT_MASK);
} else {
- if (cond->pshared != PTHREAD_PROCESS_SHARED)
- flags = _PTHREAD_MTX_OPT_NOHOLD;
- else
- flags = _PTHREAD_MTX_OPT_NOHOLD | _PTHREAD_MTX_OPT_PSHARED;
- mgen = ugen = 0;
- mutexrefs = 0;
- pmtx = NULL;
+ /* If U >= S, set U = U+diff due to intr's TO, etc */
+ ulval = (ucntval & PTHRW_COUNT_MASK);
}
-#else /* COND_MTX_WAITQUEUEMOVE */
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, lcntval, ucntval, scntval, diffgen, 0);
+#endif
- if (cond->pshared != PTHREAD_PROCESS_SHARED)
- flags = _PTHREAD_MTX_OPT_NOHOLD;
- else
- flags = _PTHREAD_MTX_OPT_NOHOLD | _PTHREAD_MTX_OPT_PSHARED;
+ diffgen = diff_genseq((lcntval & PTHRW_COUNT_MASK), (ulval & PTHRW_COUNT_MASK));
+
+ /* set U = L */
+ ulval = (lcntval & PTHRW_COUNT_MASK);
+ if (OSAtomicCompareAndSwap32(ucntval, ulval, (volatile int32_t *)c_useqcnt) != TRUE) {
+ goto retry;
+ }
+
+ flags = 0;
+ if (cond->pshared == PTHREAD_PROCESS_SHARED)
+ flags |= _PTHREAD_MTX_OPT_PSHARED;
pmtx = NULL;
- mgen = ugen = 0;
- mutexrefs = 0;
-#endif /* COND_MTX_WAITQUEUEMOVE */
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, (uint32_t)cond, 3, diffgen, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, (uint32_t)cond, 3, diffgen, flags, 0);
#endif
- retval = __psynch_cvbroad(ocond, lgenval, diffgen, (pthread_mutex_t *)pmtx, mgen, ugen , (uint64_t)0, flags);
+ nlval = lcntval;
+
+ /* pass old u val so kernel will know the diffgen */
+ mugen = 0;
+ cvlsgen = ((uint64_t)scntval << 32) | nlval;
+ cvudgen = ((uint64_t)ucntval << 32) | diffgen;
+
+ updateval = __psynch_cvbroad(ocond, cvlsgen, cvudgen, flags, (pthread_mutex_t *)pmtx, mugen, mtid);
+
+ if (updateval != (uint32_t)-1) {
+
+ /* if kernel granted woke some threads, updatwe S for them as they will not access cv on their way out */
+ /* Were any threads woken or bits to be set? */
+ if (updateval != 0) {
+retry2:
+ needclearpre = 0;
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
+ /* update scntval with number of expected returns and bits */
+ nlval = (scntval & PTHRW_COUNT_MASK) + (updateval & PTHRW_COUNT_MASK);
+ /* set bits */
+ nlval |= ((scntval & PTH_RWS_CV_BITSALL) | (updateval & PTH_RWS_CV_BITSALL));
-#ifdef COND_MTX_WAITQUEUEMOVE
- if ((retval != -1) && (retval != 0)) {
- if ((mutexrefs != 0) && (retval <= PTHRW_MAX_READERS/2)) {
- dropcount = (retval);
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, (uint32_t)cond, 2, dropcount, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, 0x25, lcntval, scntval, updateval, 0);
#endif
- retval = __mtx_droplock(mutex, dropcount, &flags, &pmtx, &mtxgen, &mtxugen, ¬ify);
- }
- }
-#endif /* COND_MTX_WAITQUEUEMOVE */
+ /* if L==S and c&p bits are set, needs clearpre */
+ if (((nlval & PTHRW_COUNT_MASK) == (lcntval & PTHRW_COUNT_MASK))
+ && ((nlval & PTH_RWS_CV_BITSALL) == PTH_RWS_CV_BITSALL)) {
+ /* reset p bit but retain c bit on the sword */
+ nlval &= PTH_RWS_CV_RESET_PBIT;
+ needclearpre = 1;
+ }
- oldval64 = (((uint64_t)(ugenval+diffgen)) << 32);
- oldval64 |= lgenval;
- newval64 = 0;
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+ newval64 = (((uint64_t)nlval) << 32);
+ newval64 |= lcntval;
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_NONE, 0x25, nlval, scntval, updateval, 0);
+#endif
- OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt);
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry2;
+
+ /* if L == S, then reset associated mutex */
+ if ((nlval & PTHRW_COUNT_MASK) == (lcntval & PTHRW_COUNT_MASK)) {
+ cond->busy = (npthread_mutex_t *)NULL;
+ }
+
+ if (needclearpre != 0) {
+ (void)__psynch_cvclrprepost(ocond, lcntval, ucntval, nlval, 0, lcntval, flags);
+ }
+ }
+
+ }
+ error = 0;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_END, (uint32_t)cond, 0, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVBRD | DBG_FUNC_END, (uint32_t)cond, 0, error, 0, 0);
#endif
- return(0);
+ return(error);
}
/*
* Signal a condition variable, waking a specified thread.
*/
+
int
-_new_pthread_cond_signal_thread_np(pthread_cond_t *ocond, pthread_t thread)
+pthread_cond_signal_thread_np(pthread_cond_t *ocond, pthread_t thread)
{
npthread_cond_t * cond = (npthread_cond_t *)ocond;
int sig = cond->sig;
- npthread_mutex_t * mutex;
- int retval, dropcount;
- uint32_t lgenval, ugenval, diffgen, mgen, ugen, flags, mtxgen, mtxugen, notify;
- uint32_t * c_lseqcnt;
- uint32_t * c_useqcnt;
- uint64_t oldval64, newval64;
- int mutexrefs;
- uint32_t * pmtx = NULL;
+ uint32_t flags, updateval;
+ uint32_t lcntval , ucntval, scntval;
+ uint32_t nlval, ulval=0;
+ volatile uint32_t * c_lseqcnt, *c_useqcnt, *c_sseqcnt;
+ uint64_t oldval64, newval64, mugen, cvlsgen, mtid = 0;
+ int needclearpre = 0, retry_count = 0;
+ int error;
/* to provide backwards compat for apps using united condtn vars */
if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init))
return(EINVAL);
+
if (cond->sig != _PTHREAD_COND_SIG) {
LOCK(cond->lock);
if (cond->sig != _PTHREAD_COND_SIG) {
if (cond->sig == _PTHREAD_COND_SIG_init) {
- _new_pthread_cond_init(ocond, NULL, 0);
+ _pthread_cond_init(ocond, NULL, 0);
+ /* just inited, nothing to post yet */
+ UNLOCK(cond->lock);
+ return(0);
} else {
UNLOCK(cond->lock);
return(EINVAL);
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_START, (uint32_t)cond, 0, 0, 0, 0);
#endif
- COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt);
+ COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt, c_sseqcnt);
retry:
- lgenval = *c_lseqcnt;
- ugenval = *c_useqcnt;
- diffgen = lgenval - ugenval; /* pendig waiters */
- if (diffgen <= 0) {
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_END, (uint32_t)cond, 0, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, lcntval, ucntval, scntval, 0);
#endif
- return(0);
- }
-
- mutex = cond->busy;
- if (OSAtomicCompareAndSwap32(ugenval, ugenval+1, (volatile int *)c_useqcnt) != TRUE)
- goto retry;
+ if (((lcntval & PTHRW_COUNT_MASK) == (scntval & PTHRW_COUNT_MASK)) ||
+ ((thread == 0) && ((lcntval & PTHRW_COUNT_MASK) == (ucntval & PTHRW_COUNT_MASK)))) {
+ /* If L <= S+U, it is spurious broadcasr */
+ /* validate it is spurious and return */
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+ newval64 = oldval64;
-#ifdef COND_MTX_WAITQUEUEMOVE
- if ((mutex != NULL) && (cond->pshared != PTHREAD_PROCESS_SHARED)) {
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, 1, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, lcntval, ucntval, 0xf1f1f1f1, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_END, (uint32_t)cond, scntval, 0, 0xf1f1f1f1, 0);
#endif
- (void)__mtx_holdlock(mutex, 1, &flags, &pmtx, &mgen, &ugen);
- mutexrefs = 1;
- } else {
- if (cond->pshared != PTHREAD_PROCESS_SHARED)
- flags = _PTHREAD_MTX_OPT_NOHOLD;
- else
- flags = _PTHREAD_MTX_OPT_NOHOLD | _PTHREAD_MTX_OPT_PSHARED;
- mgen = ugen = 0;
- mutexrefs = 0;
+ return(0);
}
-#else /* COND_MTX_WAITQUEUEMOVE */
- if (cond->pshared != PTHREAD_PROCESS_SHARED)
- flags = _PTHREAD_MTX_OPT_NOHOLD;
- else
- flags = _PTHREAD_MTX_OPT_NOHOLD | _PTHREAD_MTX_OPT_PSHARED;
- mgen = ugen = 0;
- mutexrefs = 0;
-
-#endif /* COND_MTX_WAITQUEUEMOVE */
+
+ if (((thread == 0) && (is_seqhigher((ucntval & PTHRW_COUNT_MASK), (lcntval & PTHRW_COUNT_MASK)))) || is_seqhigher((scntval & PTHRW_COUNT_MASK), (lcntval & PTHRW_COUNT_MASK))) {
+ /* since ucntval may be newer, just redo */
+ retry_count++;
+ if (retry_count > 8192) {
+ return(EAGAIN);
+ } else {
+ sched_yield();
+ goto retry;
+ }
+ }
+
+ if (thread == 0) {
+ /*
+ * skip manipulating U count as ESRCH from kernel cannot be handled properly.
+ * S count will cover the imbalance and next signal without thread or broadcast
+ * will correct it. But we need to send the right U to kernel so it will use
+ * that to look for the appropriate sequenc. So the ulval is computed anyway.
+ */
+
+ if (is_seqlower(ucntval & PTHRW_COUNT_MASK, scntval & PTHRW_COUNT_MASK) != 0) {
+ /* If U < S, set U = S+1 due to intr's TO, etc */
+ ulval = (scntval & PTHRW_COUNT_MASK) + PTHRW_INC;
+ } else {
+ /* If U >= S, set U = U+1 due to intr's TO, etc */
+ ulval = (ucntval & PTHRW_COUNT_MASK) + PTHRW_INC;
+ }
+
+ if (OSAtomicCompareAndSwap32(ucntval, ulval, (volatile int32_t *)c_useqcnt) != TRUE) {
+ goto retry;
+ }
+ }
+
+ flags = 0;
+ if (cond->pshared == PTHREAD_PROCESS_SHARED)
+ flags |= _PTHREAD_MTX_OPT_PSHARED;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, 3, lgenval, ugenval+1, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, 3, nlval, ulval, 0);
#endif
- retval = __psynch_cvsignal(ocond, lgenval, ugenval+1,(pthread_mutex_t *)mutex, mgen, ugen, pthread_mach_thread_np(thread), flags);
+ nlval = lcntval;
+ /* pass old u val so kernel will know the diffgen */
+ mugen = 0;
+ cvlsgen = ((uint64_t)scntval << 32) | nlval;
+
+ updateval = __psynch_cvsignal(ocond, cvlsgen, ucntval, pthread_mach_thread_np(thread), (pthread_mutex_t *)0, mugen, mtid, flags);
+
+
+ if (updateval != (uint32_t)-1) {
+
+ /* if kernel granted woke some threads, updatwe S for them as they will not access cv on their way out */
+ /* Were any threads woken or bits to be set? */
+ if (updateval != 0) {
+retry2:
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
+ /* update scntval with number of expected returns and bits */
+ nlval = (scntval & PTHRW_COUNT_MASK) + (updateval & PTHRW_COUNT_MASK);
+ /* set bits */
+ nlval |= ((scntval & PTH_RWS_CV_BITSALL) | (updateval & PTH_RWS_CV_BITSALL));
-#ifdef COND_MTX_WAITQUEUEMOVE
- if ((retval != -1) && (retval != 0) && (mutexrefs != 0)) {
- dropcount = retval;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, 4, dropcount, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, 0x25, 0, 0, updateval, 0);
#endif
- retval = __mtx_droplock(mutex, dropcount, &flags, &pmtx, &mtxgen, &mtxugen, ¬ify);
- }
-#endif /* COND_MTX_WAITQUEUEMOVE */
+ /* if L==S and c&p bits are set, needs clearpre */
+ if (((nlval & PTHRW_COUNT_MASK) == (lcntval & PTHRW_COUNT_MASK))
+ && ((nlval & PTH_RWS_CV_BITSALL) == PTH_RWS_CV_BITSALL)) {
+ /* reset p bit but retain c bit on the sword */
+ nlval &= PTH_RWS_CV_RESET_PBIT;
+ needclearpre = 1;
+ } else
+ needclearpre = 0;
+
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+ newval64 = (((uint64_t)nlval) << 32);
+ newval64 |= lcntval;
- if (lgenval == ugenval+1){
- oldval64 = (((uint64_t)(ugenval+1)) << 32);
- oldval64 |= lgenval;
- newval64 = 0;
- OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt);
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, 5, 0, 0, 0);
+(void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, 0x25, nlval, ulval, updateval, 0);
#endif
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry2;
+
+ /* if L == S, then reset associated mutex */
+ if ((nlval & PTHRW_COUNT_MASK) == (lcntval & PTHRW_COUNT_MASK)) {
+ cond->busy = (npthread_mutex_t *)NULL;
+ }
+
+ if (needclearpre != 0) {
+ (void)__psynch_cvclrprepost(ocond, lcntval, ucntval, nlval, 0, lcntval, flags);
+ }
+ }
}
-
+
+ error = 0;
+
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_END, (uint32_t)cond, 0, 0, 0, 0);
#endif
- return (0);
+ return (error);
}
/*
* Signal a condition variable, waking only one thread.
*/
int
-_new_pthread_cond_signal(pthread_cond_t *cond)
+pthread_cond_signal(pthread_cond_t *cond)
{
- return _new_pthread_cond_signal_thread_np(cond, NULL);
+ return pthread_cond_signal_thread_np(cond, NULL);
}
/*
* remaining conforming behavior..
*/
__private_extern__ int
-__new_pthread_cond_wait(pthread_cond_t *ocond,
+_pthread_cond_wait(pthread_cond_t *ocond,
pthread_mutex_t *omutex,
const struct timespec *abstime,
int isRelative,
struct timespec cthen = {0,0};
int sig = cond->sig;
int msig = mutex->sig;
- int firstfit = 0;
npthread_mutex_t * pmtx;
- uint32_t mtxgen, mtxugen, flags, updateval, notify;
- uint32_t lgenval, ugenval;
- uint32_t * c_lseqcnt;
- uint32_t * c_useqcnt;
+ uint32_t mtxgen, mtxugen, flags=0, updateval;
+ uint32_t lcntval , ucntval, scntval;
+ uint32_t nlval, ulval, savebits;
+ volatile uint32_t * c_lseqcnt, *c_useqcnt, *c_sseqcnt;
+ uint64_t oldval64, newval64, mugen, cvlsgen;
uint32_t * npmtx = NULL;
+ int error, local_error;
extern void _pthread_testcancel(pthread_t thread, int isconforming);
return(EINVAL);
if (isconforming) {
- if((msig != _PTHREAD_MUTEX_SIG) && (msig != _PTHREAD_MUTEX_SIG_init))
+ if((msig != _PTHREAD_MUTEX_SIG) && ((msig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP))
return(EINVAL);
if (isconforming > 0)
_pthread_testcancel(pthread_self(), 1);
}
+
if (cond->sig != _PTHREAD_COND_SIG)
{
LOCK(cond->lock);
- if (cond->sig != _PTHREAD_COND_SIG_init)
- {
+ if (cond->sig != _PTHREAD_COND_SIG) {
+ if (cond->sig == _PTHREAD_COND_SIG_init) {
+ _pthread_cond_init(ocond, NULL, 0);
+ } else {
UNLOCK(cond->lock);
- return (EINVAL); /* Not a condition variable */
+ return(EINVAL);
+ }
}
- _new_pthread_cond_init(ocond, NULL, 0);
UNLOCK(cond->lock);
}
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_START, (uint32_t)cond, 0, 0, (uint32_t)abstime, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_START, (uint32_t)cond, isRelative, 0, (uint32_t)abstime, 0);
#endif
- COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt);
+ COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt, c_sseqcnt);
/* send relative time to kernel */
if (abstime) {
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_START, 0x11111111, abstime->tv_nsec, abstime->tv_sec, 0, 0);
+#endif
if (isRelative == 0) {
struct timespec now;
struct timeval tv;
if (((int)then.tv_sec < 0) ||
((then.tv_sec == 0) && (then.tv_nsec == 0)))
{
- UNLOCK(cond->lock);
return ETIMEDOUT;
}
if (isconforming != 0) {
cthen.tv_sec = abstime->tv_sec;
cthen.tv_nsec = abstime->tv_nsec;
if ((cthen.tv_sec < 0) || (cthen.tv_nsec < 0)) {
- UNLOCK(cond->lock);
return EINVAL;
}
if (cthen.tv_nsec >= NSEC_PER_SEC) {
- UNLOCK(cond->lock);
return EINVAL;
}
}
} else {
then.tv_sec = abstime->tv_sec;
then.tv_nsec = abstime->tv_nsec;
+ if ((then.tv_sec == 0) && (then.tv_nsec == 0)) {
+ return ETIMEDOUT;
+ }
}
if(isconforming && ((then.tv_sec < 0) || (then.tv_nsec < 0))) {
return EINVAL;
}
}
- cond->busy = mutex;
+ if ((cond->busy != (npthread_mutex_t *)NULL) && (cond->busy != mutex))
+ return (EINVAL);
+
pmtx = mutex;
+retry:
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
- ugenval = *c_useqcnt;
- lgenval = OSAtomicIncrement32((volatile int32_t *)c_lseqcnt);
-
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+
+ /* remove c and p bits on S word */
+ savebits = scntval & PTH_RWS_CV_BITSALL;
+ ulval = (scntval & PTHRW_COUNT_MASK);
+ nlval = lcntval + PTHRW_INC;
+ newval64 = (((uint64_t)ulval) << 32);
+ newval64 |= nlval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry;
+
+ cond->busy = mutex;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, 1, lgenval, ugenval, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, lcntval, ucntval, scntval, 0);
#endif
- notify = 0;
- retval = __mtx_droplock(pmtx, 1, &flags, &npmtx, &mtxgen, &mtxugen, ¬ify);
+ retval = __mtx_droplock(pmtx, PTHRW_INC, &flags, &npmtx, &mtxgen, &mtxugen);
+
+ /* TBD: cases are for normal (non owner for recursive mutex; error checking)*/
if (retval != 0)
return(EINVAL);
- if ((notify & 1) == 0) {
+ if ((flags & _PTHREAD_MTX_OPT_NOTIFY) == 0) {
npmtx = NULL;
- }
- if ((notify & 0xc0000000) != 0)
- then.tv_nsec |= (notify & 0xc0000000);
+ mugen = 0;
+ } else
+ mugen = ((uint64_t)mtxugen << 32) | mtxgen;
+ flags &= ~_PTHREAD_MTX_OPT_MUTEX; /* reset the mutex bit as this is cvar */
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, 3, (uint32_t)mutex, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, 3, (uint32_t)mutex, flags, 0);
#endif
+
+ cvlsgen = ((uint64_t)(ulval | savebits)<< 32) | nlval;
+
if (isconforming) {
- pthread_cleanup_push(_new_cond_cleanup, (void *)cond);
- updateval = __psynch_cvwait(ocond, lgenval, ugenval, (pthread_mutex_t *)npmtx, mtxgen, mtxugen, (uint64_t)then.tv_sec, (uint64_t)then.tv_nsec);
+ pthread_cleanup_push(cond_cleanup, (void *)cond);
+ updateval = __psynch_cvwait(ocond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)then.tv_sec, (int32_t)then.tv_nsec);
pthread_cleanup_pop(0);
} else {
- updateval = __psynch_cvwait(ocond, lgenval, ugenval, (pthread_mutex_t *)npmtx, mtxgen, mtxugen, (uint64_t)then.tv_sec, (uint64_t)then.tv_nsec);
+ updateval = __psynch_cvwait(ocond, cvlsgen, ucntval, (pthread_mutex_t *)npmtx, mugen, flags, (int64_t)then.tv_sec, (int32_t)then.tv_nsec);
}
retval = 0;
-#ifdef COND_MTX_WAITQUEUEMOVE
- /* Needs to handle timedout */
if (updateval == (uint32_t)-1) {
- retval = errno;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, 4, retval, 0, 0);
-#endif
- /* add unlock ref to show one less waiter */
- _new_cond_dropwait(cond);
-
- pthread_mutex_lock(omutex);
-
- } else if ((updateval & PTHRW_MTX_NONE) != 0) {
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, 5, updateval, 0, 0);
-#endif
- pthread_mutex_lock(omutex);
- } else {
- /* on successful return mutex held */
- /* returns 0 on succesful update */
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, 6, updateval, 0, 0);
-#endif
- firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
- if (__mtx_updatebits( mutex, updateval, firstfit, 1) == 1) {
- /* not expected to be here */
- LIBC_ABORT("CONDWAIT mutex acquire mishap");
- }
- if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
- mutex->mtxopts.options.lock_count++;
- }
-#else /* COND_MTX_WAITQUEUEMOVE */
- if (updateval == (uint32_t)-1) {
- if (errno == ETIMEDOUT) {
+ local_error = errno;
+ error = local_error & 0xff;
+ if (error == ETIMEDOUT) {
retval = ETIMEDOUT;
- } else if (errno == EINTR) {
+ } else if (error == EINTR) {
/*
** EINTR can be treated as a spurious wakeup unless we were canceled.
*/
retval = 0;
} else
retval = EINVAL;
+//#if _KSYN_TRACE_
+// (void)__kdebug_trace(0x9000070 | 0, (uint32_t)cond, 0xf1f1f2f2, local_error, error, 0);
+//#endif
/* add unlock ref to show one less waiter */
- _new_cond_dropwait(cond);
- } else
+ cond_dropwait(cond, local_error, 0);
+ } else {
+//#if _KSYN_TRACE_
+// (void)__kdebug_trace(0x9000070 | 0, (uint32_t)cond, 0xf3f3f4f4, updateval, 0, 0);
+//#endif
+ /* succesful wait */
+ if (updateval != 0) {
+ /* the return due to prepost and might have bit states */
+ /* update S and return for prepo if needed */
+ cond_dropwait(cond, 0, updateval);
+ }
retval = 0;
+ }
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_NONE, (uint32_t)cond, 4, retval, 0, 0);
#endif
- pthread_mutex_lock(omutex);
-
-#endif /* COND_MTX_WAITQUEUEMOVE */
+ pthread_mutex_lock(omutex);
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_CVWAIT | DBG_FUNC_END, (uint32_t)cond, 0, 0, retval, 0);
return(retval);
}
+/*
+ * For the new style mutex, interlocks are not held all the time.
+ * We needed the signature to be set in the end. And we need
+ * to protect against the code getting reorganized by compiler.
+ */
+static void
+__pthread_cond_set_signature(npthread_cond_t * cond)
+{
+ cond->sig = _PTHREAD_COND_SIG;
+}
+
+
static void
-_new_cond_cleanup(void *arg)
+cond_cleanup(void *arg)
{
npthread_cond_t *cond = (npthread_cond_t *)arg;
pthread_mutex_t *mutex;
return;
// 4597450: end
- mutex = cond->busy;
+ mutex = (pthread_mutex_t *) cond->busy;
/* add unlock ref to show one less waiter */
- _new_cond_dropwait(cond);
+ cond_dropwait(cond, thread->cancel_error, 0);
/*
** Can't do anything if this fails -- we're on the way out
*/
if (mutex != NULL)
(void)pthread_mutex_lock(mutex);
-
}
+#define ECVCERORR 256
+#define ECVPERORR 512
+
void
-_new_cond_dropwait(npthread_cond_t * cond)
+cond_dropwait(npthread_cond_t * cond, int error, uint32_t updateval)
{
int sig = cond->sig;
- int retval;
- uint32_t lgenval, ugenval, diffgen, mgen, ugen, flags;
- uint32_t * c_lseqcnt;
- uint32_t * c_useqcnt;
+ pthread_cond_t * ocond = (pthread_cond_t *)cond;
+ int needclearpre = 0;
+ uint32_t diffgen, nlval, ulval, flags;
+ uint32_t lcntval , ucntval, scntval, lval;
+ volatile uint32_t * c_lseqcnt, *c_useqcnt, *c_sseqcnt;
uint64_t oldval64, newval64;
/* to provide backwards compat for apps using united condtn vars */
if (sig != _PTHREAD_COND_SIG)
return;
+ COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt, c_sseqcnt);
+
+ if (error != 0) {
+ lval = PTHRW_INC;
+ if ((error & ECVCERORR) != 0)
+ lval |= PTH_RWS_CV_CBIT;
+ if ((error & ECVPERORR) != 0)
+ lval |= PTH_RWS_CV_PBIT;
+ } else {
+ lval = updateval;
+ }
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_START, (uint32_t)cond, 0, 0, 0xee, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CDROPWT | DBG_FUNC_START, (uint32_t)cond, error, updateval, 0xee, 0);
#endif
- COND_GETSEQ_ADDR(cond, c_lseqcnt, c_useqcnt);
retry:
- lgenval = *c_lseqcnt;
- ugenval = *c_useqcnt;
- diffgen = lgenval - ugenval; /* pending waiters */
+ lcntval = *c_lseqcnt;
+ ucntval = *c_useqcnt;
+ scntval = *c_sseqcnt;
+ diffgen = diff_genseq((lcntval & PTHRW_COUNT_MASK), (scntval & PTHRW_COUNT_MASK)); /* pendig waiters */
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CDROPWT | DBG_FUNC_NONE, (uint32_t)cond, lcntval, scntval, diffgen, 0);
+#endif
if (diffgen <= 0) {
+ /* TBD: Assert, should not be the case */
+ /* validate it is spurious and return */
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+ newval64 = oldval64;
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_END, (uint32_t)cond, 1, 0, 0xee, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CDROPWT | DBG_FUNC_END, (uint32_t)cond, 0, 0, 0, 0);
#endif
return;
}
-
- if (OSAtomicCompareAndSwap32(ugenval, ugenval+1, (volatile int *)c_useqcnt) != TRUE)
- goto retry;
- if (lgenval == ugenval+1) {
- /* last one */
- /* send last drop notify to erase pre post */
- flags = _PTHREAD_MTX_OPT_LASTDROP;
+ /* update S by one */
+ oldval64 = (((uint64_t)scntval) << 32);
+ oldval64 |= lcntval;
+
+ /* update scntval with number of expected returns and bits */
+ ulval = (scntval & PTHRW_COUNT_MASK) + (lval & PTHRW_COUNT_MASK);
+ /* set bits */
+ ulval |= ((scntval & PTH_RWS_CV_BITSALL) | (lval & PTH_RWS_CV_BITSALL));
+
+ nlval = lcntval;
+
+ needclearpre = 0;
+
+ /* If L==S, need to return to kernel */
+ if ((nlval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK)) {
+ if ((ulval & PTH_RWS_CV_BITSALL) == PTH_RWS_CV_BITSALL) {
+ /* reset p bit but retain c bit on the sword */
+ needclearpre = 1;
+ ulval &= PTH_RWS_CV_RESET_PBIT;
+ }
+ }
- if (cond->pshared == PTHREAD_PROCESS_SHARED)
- flags |= _PTHREAD_MTX_OPT_PSHARED;
- mgen = ugen = 0;
+ newval64 = (((uint64_t)ulval) << 32);
+ newval64 |= nlval;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_NONE, (uint32_t)cond, 1, 0, 0xee, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CDROPWT | DBG_FUNC_NONE, (uint32_t)cond, 0xffff, nlval, ulval, 0);
#endif
- retval = __psynch_cvsignal((pthread_cond_t *)cond, lgenval, ugenval+1,(pthread_mutex_t *)NULL, mgen, ugen, MACH_PORT_NULL, flags);
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE)
+ goto retry;
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CDROPWT | DBG_FUNC_NONE, (uint32_t)cond, 2, 0, 0xee, 0);
+#endif
+ if ((nlval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK)) {
+ /* last usage remove the mutex */
+ cond->busy = NULL;
+ }
- oldval64 = (((uint64_t)(ugenval+1)) << 32);
- oldval64 |= lgenval;
- newval64 = 0;
- OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)c_lseqcnt);
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CDROPWT | DBG_FUNC_NONE, nlval, ucntval, ulval, PTHRW_INC, 0);
+#endif
+ if (needclearpre != 0) {
+ flags = 0;
+ if (cond->pshared == PTHREAD_PROCESS_SHARED)
+ flags |= _PTHREAD_MTX_OPT_PSHARED;
+ /* reset prepost */
+ (void)__psynch_cvclrprepost(ocond, nlval, ucntval, ulval, 0, nlval, flags);
}
-
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_CVSIG | DBG_FUNC_END, (uint32_t)cond, 2, 0, 0xee, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_CDROPWT | DBG_FUNC_END, nlval, ucntval, ulval, PTHRW_INC, 0);
#endif
return;
}
int
-_new_pthread_cond_timedwait_relative_np(pthread_cond_t *cond,
+pthread_cond_timedwait_relative_np(pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime)
{
- return (__new_pthread_cond_wait(cond, mutex, abstime, 1, 0));
-}
-
-
-int
-_new_pthread_cond_wait(pthread_cond_t *cond,
- pthread_mutex_t *mutex)
-{
- return(__new_pthread_cond_wait(cond, mutex, 0, 0, 1));
+ return (_pthread_cond_wait(cond, mutex, abstime, 1, 0));
}
-int
-_new_pthread_cond_timedwait(pthread_cond_t *cond,
- pthread_mutex_t *mutex,
- const struct timespec *abstime)
-{
- return(__new_pthread_cond_wait(cond, mutex, abstime, 0, 1));
-}
-#endif /* __i386__ || __x86_64__ */
#else /* !BUILDING_VARIANT */
conforming = 0;
#endif /* __DARWIN_UNIX03 */
+ /* lock is same offset in both structures */
LOCK_INIT(cond->lock);
-#if defined(__i386__) || defined(__x86_64__)
- if ((attr != NULL) && (attr->pshared == PTHREAD_PROCESS_SHARED)) {
- return(_new_pthread_cond_init(cond, attr, conforming));
- }
-#endif /* __i386__ || __x86_64__ */
-
+
return (_pthread_cond_init(cond, attr, conforming));
}
* [Internal] data structure signatures
*/
#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7
+
+#define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
+#define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
+#define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
+
#define _PTHREAD_COND_SIG_init 0x3CB0B1BB
#define _PTHREAD_ONCE_SIG_init 0x30B1BCBA
#define _PTHREAD_RWLOCK_SIG_init 0x2DA8B3B4
+
/*
* POSIX scheduling policies
*/
#include "pthread_spinlock.h" /* spinlock definitions. */
TAILQ_HEAD(__pthread_list, _pthread);
+
+extern int __pthread_lock_debug;
+extern int __pthread_lock_old;
+
extern struct __pthread_list __pthread_head; /* head of list of open files */
extern pthread_lock_t _pthread_list_lock;
extern size_t pthreadsize;
int pad0; /* for backwards compatibility */
#endif
struct sched_param param;
- struct _pthread_mutex *mutexes;
+ uint32_t cancel_error;
+#if defined(__LP64__)
+ uint32_t cancel_pad; /* pad value for alignment */
+#endif
struct _pthread *joiner;
#if !defined(__LP64__)
int pad1; /* for backwards compatibility */
uint64_t thread_id;
} *pthread_t;
-/*
- * This will cause a compile-time failure if someone moved the tsd field
- * and we need to change _PTHREAD_TSD_OFFSET in pthread_machdep.h
- */
-typedef char _need_to_change_PTHREAD_TSD_OFFSET[(_PTHREAD_TSD_OFFSET == offsetof(struct _pthread, tsd[0])) ? 0 : -1] ;
-
/*
* Thread attributes
*/
policy:3,
hold:2,
misalign:1, /* 8 byte aligned? */
- rfu:4,
+ notify:1, /* CV notify field for kernel */
+ mutex:1, /* used in clrprepo that it is a mutex */
+ rfu:2,
lock_count:16;
};
#define _PTHREAD_MTX_OPT_PSHARED 0x010
-#define _PTHREAD_MTX_OPT_HOLD 0x200
-#define _PTHREAD_MTX_OPT_NOHOLD 0x400
-#define _PTHREAD_MTX_OPT_LASTDROP (_PTHREAD_MTX_OPT_NOHOLD | _PTHREAD_MTX_OPT_HOLD)
+#define _PTHREAD_MTX_OPT_HOLD 0x200 /* current owner of the mutex */
+#define _PTHREAD_MTX_OPT_NOMTX 0x400 /* no mutex refs held */
+
+#define _PTHREAD_MTX_OPT_NOTIFY 0x1000 /* notify to drop mutex handling in cvwait */
+#define _PTHREAD_MTX_OPT_MUTEX 0x2000 /* this is a mutex type */
#define _PTHREAD_MUTEX_T
int pshared;
} pthread_rwlock_t;
+#define PTHRW_RFU_64BIT 124 /* 31 * sizeof(uint32_t) */
+#define PTHRW_RFU_32BIT 72 /* 18 * sizeof(uint32_t) */
+
#define _PTHREAD_RWLOCK_T
typedef struct {
long sig;
pthread_t rw_owner;
int reserv;
#endif /* __LP64__ */
- volatile uint32_t * rw_lseqaddr;
- volatile uint32_t * rw_wcaddr;
- volatile uint32_t * rw_useqaddr;
+ volatile uint32_t * rw_lcntaddr;
+ volatile uint32_t * rw_seqaddr;
+ volatile uint32_t * rw_ucntaddr;
uint32_t rw_flags;
int misalign;
#if defined(__LP64__)
- uint32_t rfu[31];
+ char rfu[PTHRW_RFU_64BIT];
#else /* __LP64__ */
- uint32_t rfu[18];
+ char rfu[PTHRW_RFU_32BIT];
#endif /* __LP64__ */
int pshared;
} npthread_rwlock_t;
#define PTHRW_KERN_PROCESS_SHARED 0x10
#define PTHRW_KERN_PROCESS_PRIVATE 0x20
#define PTHRW_KERN_PROCESS_FLAGS_MASK 0x30
+#define _PTHREAD_RWLOCK_UPGRADE_TRY 0x10000
+
+/* New model bits on Lword */
+#define PTH_RWL_KBIT 0x01 /* users cannot acquire in user mode */
+#define PTH_RWL_EBIT 0x02 /* exclusive lock in progress */
+#define PTH_RWL_WBIT 0x04 /* write waiters pending in kernel */
+#define PTH_RWL_PBIT 0x04 /* prepost (cv) pending in kernel */
+#define PTH_RWL_YBIT 0x08 /* yielding write waiters pending in kernel */
+#define PTH_RWL_RETRYBIT 0x08 /* mutex retry wait */
+#define PTH_RWL_LBIT 0x10 /* long read in progress */
+#define PTH_RWL_MTXNONE 0x10 /* indicates the cvwait does not have mutex held */
+#define PTH_RWL_UBIT 0x20 /* upgrade request pending */
+#define PTH_RWL_MTX_WAIT 0x20 /* in cvar in mutex wait */
+#define PTH_RWL_RBIT 0x40 /* reader pending in kernel(not used) */
+#define PTH_RWL_MBIT 0x40 /* overlapping grants from kernel */
+#define PTH_RWL_TRYLKBIT 0x40 /* sets try lock attempt */
+#define PTH_RWL_IBIT 0x80 /* lock reset, held untill first succeesful unlock */
+
+/* UBIT values for mutex, cvar */
+#define PTH_RWU_SBIT 0x01
+#define PTH_RWU_BBIT 0x02
+
+#define PTHRW_RWL_INIT PTH_RWL_IBIT /* reset on the lock bits (U)*/
+#define PTHRW_RWLOCK_INIT (PTH_RWL_IBIT | PTH_RWL_RBIT) /* reset on the lock bits (U)*/
+#define PTH_RWLOCK_RESET_RBIT 0xffffffbf
-#define PTHRW_EBIT 0x01
-#define PTHRW_LBIT 0x02
-#define PTHRW_YBIT 0x04
-#define PTHRW_WBIT 0x08
-#define PTHRW_UBIT 0x10
-#define PTHRW_RETRYBIT 0x20
-#define PTHRW_SHADOW_W 0x20 /* same as 0x20, shadow W bit for rwlock */
+#define PTHRW_INC 0x100
+#define PTHRW_BIT_MASK 0x000000ff
-#define PTHRW_TRYLKBIT 0x40
-#define PTHRW_RW_HUNLOCK 0x40 /* readers responsible for handling unlock */
+#define PTHRW_UN_BIT_MASK 0x000000bf /* remove overlap bit */
-#define PTHRW_MTX_NONE 0x80
-#define PTHRW_RW_INIT 0x80 /* reset on the lock bits */
-#define PTHRW_RW_SPURIOUS 0x80 /* same as 0x80, spurious rwlock unlock ret from kernel */
-#define PTHRW_INC 0x100
-#define PTHRW_BIT_MASK 0x000000ff
-#define PTHRW_UN_BIT_MASK 0x000000df /* remove shadow bit */
+/* New model bits on Sword */
+#define PTH_RWS_SBIT 0x01 /* kernel transition seq not set yet*/
+#define PTH_RWS_IBIT 0x02 /* Sequence is not set on return from kernel */
+
+#define PTH_RWS_CV_CBIT PTH_RWS_SBIT /* kernel has cleared all info w.r.s.t CV */
+#define PTH_RWS_CV_PBIT PTH_RWS_IBIT /* kernel has prepost/fake structs only,no waiters */
+#define PTH_RWS_CV_BITSALL (PTH_RWS_CV_CBIT | PTH_RWS_CV_PBIT)
+#define PTH_RWS_CV_MBIT PTH_RWL_MBIT /* to indicate prepost return from kernel */
+#define PTH_RWS_CV_RESET_PBIT 0xfffffffd
+
+#define PTH_RWS_WSVBIT 0x04 /* save W bit */
+#define PTH_RWS_USVBIT 0x08 /* save U bit */
+#define PTH_RWS_YSVBIT 0x10 /* save Y bit */
+#define PTHRW_RWS_INIT PTH_RWS_SBIT /* reset on the lock bits (U)*/
+#define PTHRW_RWS_SAVEMASK (PTH_RWS_WSVBIT|PTH_RWS_USVBIT|PTH_RWS_YSVBIT) /*save bits mask*/
+#define PTHRW_SW_Reset_BIT_MASK 0x000000fe /* remove S bit and get rest of the bits */
#define PTHRW_COUNT_SHIFT 8
#define PTHRW_COUNT_MASK 0xffffff00
#define PTHREAD_MTX_TID_SWITCHING (uint64_t)-1
-#define is_rw_ewubit_set(x) (((x) & (PTHRW_EBIT | PTHRW_WBIT | PTHRW_UBIT)) != 0)
-#define is_rw_lbit_set(x) (((x) & PTHRW_LBIT) != 0)
-#define is_rw_lybit_set(x) (((x) & (PTHRW_LBIT | PTHRW_YBIT)) != 0)
-#define is_rw_ebit_set(x) (((x) & PTHRW_EBIT) != 0)
-#define is_rw_ebit_clear(x) (((x) & PTHRW_EBIT) == 0)
-#define is_rw_uebit_set(x) (((x) & (PTHRW_EBIT | PTHRW_UBIT)) != 0)
-#define is_rw_ewuybit_set(x) (((x) & (PTHRW_EBIT | PTHRW_WBIT | PTHRW_UBIT | PTHRW_YBIT)) != 0)
-#define is_rw_ewuybit_clear(x) (((x) & (PTHRW_EBIT | PTHRW_WBIT | PTHRW_UBIT | PTHRW_YBIT)) == 0)
-#define is_rw_ewubit_set(x) (((x) & (PTHRW_EBIT | PTHRW_WBIT | PTHRW_UBIT)) != 0)
-#define is_rw_ewubit_clear(x) (((x) & (PTHRW_EBIT | PTHRW_WBIT | PTHRW_UBIT)) == 0)
+/* new L word defns */
+#define can_rwl_readinuser(x) ((((x) & (PTH_RWL_UBIT | PTH_RWL_WBIT | PTH_RWL_KBIT)) == 0)||(((x) & PTH_RWL_LBIT) != 0))
+#define can_rwl_longreadinuser(x) (((x) & (PTH_RWL_UBIT | PTH_RWL_WBIT | PTH_RWL_KBIT | PTH_RWL_YBIT)) == 0)
+#define is_rwl_ebit_set(x) (((x) & PTH_RWL_EBIT) != 0)
+#define is_rwl_eubit_set(x) (((x) & (PTH_RWL_EBIT | PTH_RWL_UBIT)) != 0)
+#define is_rwl_wbit_set(x) (((x) & PTH_RWL_WBIT) != 0)
+#define is_rwl_lbit_set(x) (((x) & PTH_RWL_LBIT) != 0)
+#define is_rwl_ebit_clear(x) (((x) & PTH_RWL_EBIT) == 0)
+#define is_rwl_lbit_clear(x) (((x) & PTH_RWL_LBIT) == 0)
+#define is_rwl_readoverlap(x) (((x) & PTH_RWL_MBIT) != 0)
+
+/* S word checks */
+#define is_rws_setseq(x) (((x) & PTH_RWS_SBIT))
+#define is_rws_setunlockinit(x) (((x) & PTH_RWS_IBIT))
/* is x lower than Y */
-#define is_seqlower(x, y) ((x < y) || ((x - y) > (PTHRW_MAX_READERS/2)))
+static inline int is_seqlower(uint32_t x, uint32_t y) {
+ if (x < y) {
+ if ((y-x) < (PTHRW_MAX_READERS/2))
+ return(1);
+ } else {
+ if ((x-y) > (PTHRW_MAX_READERS/2))
+ return(1);
+ }
+ return(0);
+}
+
/* is x lower than or eq Y */
-#define is_seqlower_eq(x, y) ((x <= y) || ((x - y) > (PTHRW_MAX_READERS/2)))
+static inline int is_seqlower_eq(uint32_t x, uint32_t y) {
+ if (x==y)
+ return(1);
+ else
+ return(is_seqlower(x,y));
+}
/* is x greater than Y */
-#define is_seqhigher(x, y) ((x > y) || ((y - x) > (PTHRW_MAX_READERS/2)))
+static inline int is_seqhigher(uint32_t x, uint32_t y) {
+ if (x > y) {
+ if ((x-y) < (PTHRW_MAX_READERS/2))
+ return(1);
+ } else {
+ if ((y-x) > (PTHRW_MAX_READERS/2))
+ return(1);
+ }
+ return(0);
+}
static inline int diff_genseq(uint32_t x, uint32_t y) {
- if (x > y) {
+ if (x == y) {
+ return(0);
+ } else if (x > y) {
return(x-y);
} else {
- return((PTHRW_MAX_READERS - y) + x +1);
+ return((PTHRW_MAX_READERS - y) + x + PTHRW_INC);
}
}
void * func_arg;
struct _pthread_workqueue * workq;
unsigned int flags;
- unsigned int gencount;
+ unsigned int fromcache; /* padding for 64bit */
} * pthread_workitem_t;
#define PTH_WQITEM_INKERNEL_QUEUE 1
#define PTH_WQITEM_APPLIED 0x80
#define PTH_WQITEM_KERN_COUNT 0x100
-#define WORKITEM_POOL_SIZE 1000
+/* try to fit these within multiple of pages (8 pages for now) */
+#define WORKITEM_POOL_SIZE 680
+/* ensure some multiple of the chunk is the pool size */
+#define WORKITEM_CHUNK_SIZE 40
+
+#define WORKITEM_STARTPOOL_SIZE WORKITEM_CHUNK_SIZE
+
TAILQ_HEAD(__pthread_workitem_pool, _pthread_workitem);
extern struct __pthread_workitem_pool __pthread_workitem_pool_head; /* head list of workitem pool */
-#define WQ_NUM_PRIO_QS 3 /* WORKQ_HIGH/DEFAULT/LOW_PRIOQUEUE */
-
#define _PTHREAD_WORKQUEUE_HEAD_T
typedef struct _pthread_workqueue_head {
TAILQ_HEAD(, _pthread_workqueue) wqhead;
} * pthread_workqueue_head_t;
+/* sized to be 128 bytes both in 32 and 64bit archs */
#define _PTHREAD_WORKQUEUE_T
typedef struct _pthread_workqueue {
unsigned int sig; /* Unique signature for this structure */
void * term_callarg;
pthread_workqueue_head_t headp;
int overcommit;
-#if defined(__ppc64__) || defined(__x86_64__)
- unsigned int rev2[2];
-#else
+#if !defined(__LP64__)
unsigned int rev2[12];
#endif
} * pthread_workqueue_t;
#define PTHREAD_WORKQ_REQUEUED 0x20
#define PTHREAD_WORKQ_SUSPEND 0x40
-#define WORKQUEUE_POOL_SIZE 100
+#define WORKQUEUE_POOL_SIZE 16
TAILQ_HEAD(__pthread_workqueue_pool, _pthread_workqueue);
extern struct __pthread_workqueue_pool __pthread_workqueue_pool_head; /* head list of workqueue pool */
-#include "pthread.h"
+#include "pthread_spis.h"
#if defined(__i386__) || defined(__ppc64__) || defined(__x86_64__) || (defined(__arm__) && (defined(_ARM_ARCH_7) || !defined(_ARM_ARCH_6) || !defined(__thumb__)))
/*
inline static pthread_t __attribute__((__pure__))
_pthread_self_direct(void)
{
- pthread_t ret;
+ pthread_t ret;
+
#if defined(__i386__) || defined(__x86_64__)
- asm("mov %%gs:%P1, %0" : "=r" (ret) : "i" (offsetof(struct _pthread, tsd[0])));
+ ret = _pthread_getspecific_direct(0);
#elif defined(__ppc64__)
register const pthread_t __pthread_self asm ("r13");
ret = __pthread_self;
#elif defined(__arm__) && defined(_ARM_ARCH_6)
- __asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r"(ret));
+ ret = _pthread_getspecific_direct(0);
#elif defined(__arm__) && !defined(_ARM_ARCH_6)
- register const pthread_t __pthread_self asm ("r9");
- ret = __pthread_self;
+ ret = _pthread_getspecific_direct(0);
#endif
return ret;
}
#define _PTHREAD_MUTEX_ATTR_SIG 0x4D545841 /* 'MTXA' */
#define _PTHREAD_MUTEX_SIG 0x4D555458 /* 'MUTX' */
#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 /* [almost] ~'MUTX' */
+#define _PTHREAD_ERRORCHECK_MUTEX_SIG_init 0x32AAABA1
+#define _PTHREAD_RECURSIVE_MUTEX_SIG_init 0x32AAABA2
+#define _PTHREAD_FIRSTFIT_MUTEX_SIG_init 0x32AAABA3
+#define _PTHREAD_MUTEX_SIG_init_MASK 0xfffffff0
+#define _PTHREAD_MUTEX_SIG_CMP 0x32AAABA0
#define _PTHREAD_COND_ATTR_SIG 0x434E4441 /* 'CNDA' */
#define _PTHREAD_COND_SIG 0x434F4E44 /* 'COND' */
#define _PTHREAD_COND_SIG_init 0x3CB0B1BB /* [almost] ~'COND' */
extern void _pthread_tsd_cleanup(pthread_t self);
-#if defined(__i386__) || defined(__x86_64__)
-__private_extern__ void __mtx_holdlock(npthread_mutex_t *mutex, uint32_t diff, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp);
-__private_extern__ int __mtx_droplock(npthread_mutex_t *mutex, int count, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp, uint32_t * notifyp);
-__private_extern__ int __mtx_updatebits(npthread_mutex_t *mutex, uint32_t updateval, int firstfiti, int fromcond);
+__private_extern__ void __mtx_holdlock(npthread_mutex_t *mutex, uint32_t diff, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp, uint64_t *tidp);
+__private_extern__ int __mtx_droplock(npthread_mutex_t *mutex, uint32_t diff, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp);
+__private_extern__ int __mtx_updatebits(npthread_mutex_t *mutex, uint32_t updateval, int firstfiti, int fromcond, uint64_t selfid);
/* syscall interfaces */
extern uint32_t __psynch_mutexwait(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
extern uint32_t __psynch_mutexdrop(pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
-extern int __psynch_cvbroad(pthread_cond_t * cv, uint32_t cvgen, uint32_t diffgen, pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t tid, uint32_t flags);
-extern int __psynch_cvsignal(pthread_cond_t * cv, uint32_t cvgen, uint32_t cvugen, pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, int thread_port, uint32_t flags);
-extern uint32_t __psynch_cvwait(pthread_cond_t * cv, uint32_t cvgen, uint32_t cvugen, pthread_mutex_t * mutex, uint32_t mgen, uint32_t ugen, uint64_t sec, uint64_t usec);
+
+extern uint32_t __psynch_cvbroad(pthread_cond_t * cv, uint64_t cvlsgen, uint64_t cvudgen, uint32_t flags, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid);
+extern uint32_t __psynch_cvsignal(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, int thread_port, pthread_mutex_t * mutex, uint64_t mugen, uint64_t tid, uint32_t flags);
+extern uint32_t __psynch_cvwait(pthread_cond_t * cv, uint64_t cvlsgen, uint32_t cvugen, pthread_mutex_t * mutex, uint64_t mugen, uint32_t flags, int64_t sec, uint32_t nsec);
+extern uint32_t __psynch_cvclrprepost(void * cv, uint32_t cvgen, uint32_t cvugen, uint32_t cvsgen, uint32_t prepocnt, uint32_t preposeq, uint32_t flags);
extern uint32_t __psynch_rw_longrdlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
extern uint32_t __psynch_rw_yieldwrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
extern int __psynch_rw_downgrade(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
extern uint32_t __psynch_rw_wrlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
extern uint32_t __psynch_rw_unlock(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
extern uint32_t __psynch_rw_unlock2(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t ugenval, uint32_t rw_wc, int flags);
-#endif /* __i386__ || __x86_64__ */
__private_extern__ semaphore_t new_sem_from_pool(void);
__private_extern__ void restore_sem_to_pool(semaphore_t);
__private_extern__ void _pthread_atfork_queue_init(void);
int _pthread_lookup_thread(pthread_t thread, mach_port_t * port, int only_joinable);
int _pthread_join_cleanup(pthread_t thread, void ** value_ptr, int conforming);
+__private_extern__ int proc_setthreadname(void * buffer, int buffersize);
#endif /* _POSIX_PTHREAD_INTERNALS_H */
#ifndef _POSIX_PTHREAD_MACHDEP_H
#define _POSIX_PTHREAD_MACHDEP_H
-#ifdef __LP64__
-#define _PTHREAD_TSD_OFFSET 0x60
-#else
-#define _PTHREAD_TSD_OFFSET 0x48
-#endif /* __LP64__ */
-
#ifndef __ASSEMBLER__
#include <System/machine/cpu_capabilities.h>
#ifdef __arm__
#include <arm/arch.h>
#endif
+#include <TargetConditionals.h>
/*
** Define macros for inline pthread_getspecific() usage.
#define _PTHREAD_TSD_SLOT_DYLD_2 2
#define _PTHREAD_TSD_SLOT_DYLD_3 3
#define _PTHREAD_TSD_RESERVED_SLOT_COUNT 4
+/* To mirror the usage by dyld for Unwind_SjLj */
+#define _PTHREAD_TSD_SLOT_DYLD_8 8
/* Keys 10 - 29 are for Libc/Libsystem internal ussage */
/* used as __pthread_tsd_first + Num */
#define __PTK_LIBC_GMTIME_KEY 13
#define __PTK_LIBC_GDTOA_BIGINT_KEY 14
#define __PTK_LIBC_PARSEFLOAT_KEY 15
+/* for usage by dyld */
+#define __PTK_LIBC_DYLD_Unwind_SjLj_Key 18
/* Keys 20-25 for libdispactch usage */
#define __PTK_LIBDISPATCH_KEY0 20
/* Keys 80-89 for Garbage Collection */
-#define __PTK_FRAMEWORK_GC_KEY0 80
-#define __PTK_FRAMEWORK_GC_KEY1 81
-#define __PTK_FRAMEWORK_GC_KEY2 82
-#define __PTK_FRAMEWORK_GC_KEY3 83
-#define __PTK_FRAMEWORK_GC_KEY4 84
-#define __PTK_FRAMEWORK_GC_KEY5 85
-#define __PTK_FRAMEWORK_GC_KEY6 86
-#define __PTK_FRAMEWORK_GC_KEY7 87
-#define __PTK_FRAMEWORK_GC_KEY8 88
-#define __PTK_FRAMEWORK_GC_KEY9 89
+#define __PTK_FRAMEWORK_OLDGC_KEY0 80
+#define __PTK_FRAMEWORK_OLDGC_KEY1 81
+#define __PTK_FRAMEWORK_OLDGC_KEY2 82
+#define __PTK_FRAMEWORK_OLDGC_KEY3 83
+#define __PTK_FRAMEWORK_OLDGC_KEY4 84
+#define __PTK_FRAMEWORK_OLDGC_KEY5 85
+#define __PTK_FRAMEWORK_OLDGC_KEY6 86
+#define __PTK_FRAMEWORK_OLDGC_KEY7 87
+#define __PTK_FRAMEWORK_OLDGC_KEY8 88
+#define __PTK_FRAMEWORK_OLDGC_KEY9 89
+
+/* Keys 90-94 for JavaScriptCore Collection */
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0 90
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY1 91
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY2 92
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY3 93
+#define __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 94
+/* Keys 110-119 for Garbage Collection */
+#define __PTK_FRAMEWORK_GC_KEY0 110
+#define __PTK_FRAMEWORK_GC_KEY1 111
+#define __PTK_FRAMEWORK_GC_KEY2 112
+#define __PTK_FRAMEWORK_GC_KEY3 113
+#define __PTK_FRAMEWORK_GC_KEY4 114
+#define __PTK_FRAMEWORK_GC_KEY5 115
+#define __PTK_FRAMEWORK_GC_KEY6 116
+#define __PTK_FRAMEWORK_GC_KEY7 117
+#define __PTK_FRAMEWORK_GC_KEY8 118
+#define __PTK_FRAMEWORK_GC_KEY9 119
/*
** Define macros for inline pthread_getspecific() usage.
typedef int pthread_lock_t;
+#if TARGET_IPHONE_SIMULATOR
+
+/* Similator will use the host implementation, so bypass the macro that is in the target code */
+
+inline static int
+_pthread_has_direct_tsd(void)
+{
+ return 0;
+}
+
+#define _pthread_getspecific_direct(key) pthread_getspecific(key)
+#define _pthread_setspecific_direct(key, val) pthread_setspecific(key, val)
+
+#else /* TARGET_IPHONE_SIMULATOR */
+
inline static int
_pthread_has_direct_tsd(void)
{
} else {
return 0;
}
-#elif defined(__arm__) && defined(__thumb__) && defined(_ARM_ARCH_6) && !defined(_ARM_ARCH_7)
- return 0;
#else
return 1;
#endif
_pthread_getspecific_direct(unsigned long slot)
{
void *ret;
+
#if defined(__i386__) || defined(__x86_64__)
-#if defined(__OPTIMIZE__)
- asm volatile("mov %%gs:%P1, %0" : "=r" (ret) : "i" (slot * sizeof(void *) + _PTHREAD_TSD_OFFSET));
-#else
- asm("mov %%gs:%P2(,%1,%P3), %0" : "=r" (ret) : "r" (slot), "i" (_PTHREAD_TSD_OFFSET), "i" (sizeof (void *)));
-#endif
-#elif defined(__ppc__)
- void **__pthread_tsd;
- asm volatile("mfspr %0, 259" : "=r" (__pthread_tsd));
- ret = __pthread_tsd[slot + (_PTHREAD_TSD_OFFSET / sizeof(void *))];
-#elif defined(__ppc64__)
- register void **__pthread_tsd asm ("r13");
- ret = __pthread_tsd[slot + (_PTHREAD_TSD_OFFSET / sizeof(void *))];
+ asm("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *))));
+#elif defined(__ppc64__) || defined(__ppc__)
+ ret = pthread_getspecific(slot);
#elif defined(__arm__) && defined(_ARM_ARCH_6) && !defined(_ARM_ARCH_7) && defined(__thumb__) && !defined(__OPTIMIZE__)
ret = pthread_getspecific(slot);
#elif defined(__arm__) && defined(_ARM_ARCH_6)
void **__pthread_tsd;
- __asm__ ("mrc p15, 0, %0, c13, c0, 3" : "=r"(__pthread_tsd));
- ret = __pthread_tsd[slot + (_PTHREAD_TSD_OFFSET / sizeof(void *))];
+ __asm__ (
+ "mrc p15, 0, %0, c13, c0, 3\n"
+ "bic %0, %0, #3\n"
+ : "=r"(__pthread_tsd));
+ ret = __pthread_tsd[slot];
#elif defined(__arm__) && !defined(_ARM_ARCH_6)
register void **__pthread_tsd asm ("r9");
- ret = __pthread_tsd[slot + (_PTHREAD_TSD_OFFSET / sizeof(void *))];
+ ret = __pthread_tsd[slot];
#else
#error no pthread_getspecific_direct implementation for this arch
#endif
return ret;
}
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+/* To be used with static constant keys only */
+inline static int
+_pthread_setspecific_direct(unsigned long slot, void * val)
+{
+
+#if defined(__i386__)
+#if defined(__PIC__)
+ asm("movl %1,%%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "rn" (val));
+#else
+ asm("movl %1,%%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "ri" (val));
+#endif
+#elif defined(__x86_64__)
+ /* PIC is free and cannot be disabled, even with: gcc -mdynamic-no-pic ... */
+ asm("movq %1,%%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "rn" (val));
+#elif defined(__arm__) && defined(_ARM_ARCH_6)
+ void **__pthread_tsd;
+ __asm__ (
+ "mrc p15, 0, %0, c13, c0, 3\n"
+ "bic %0, %0, #3\n"
+ : "=r"(__pthread_tsd));
+ __pthread_tsd[slot] = val;
+#elif defined(__arm__) && !defined(_ARM_ARCH_6)
+ register void **__pthread_tsd asm ("r9");
+ __pthread_tsd[slot] = val;
+#endif
+ return(0);
+}
+#elif defined(__ppc__) || defined(__ppc64__)
/* To be used with static constant keys only */
#define _pthread_setspecific_direct(key, val) pthread_setspecific(key, val)
+#else
+#error no pthread_setspecific_direct implementation for this arch
+#endif
+
+#endif /* TARGET_IPHONE_SIMULATOR */
#define LOCK_INIT(l) ((l) = 0)
#define LOCK_INITIALIZER 0
extern int __unix_conforming;
extern int __unix_conforming;
-int _pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
-#if defined(__i386__) || defined(__x86_64__)
+#ifndef BUILDING_VARIANT
+__private_extern__ int usenew_mtximpl = 1;
+static void __pthread_mutex_set_signature(npthread_mutex_t * mutex);
+int __mtx_markprepost(npthread_mutex_t *mutex, uint32_t oupdateval, int firstfit);
+static int _pthread_mutex_destroy_locked(pthread_mutex_t *omutex);
+#else /* BUILDING_VARIANT */
+extern int usenew_mtximpl;
+#endif /* BUILDING_VARIANT */
+
+
+#ifdef NOTNEEDED
#define USE_COMPAGE 1
+extern int _commpage_pthread_mutex_lock(uint32_t * lvalp, int flags, uint64_t mtid, uint32_t mask, uint64_t * tidp, int *sysret);
+#endif
#include <machine/cpu_capabilities.h>
-extern int _commpage_pthread_mutex_lock(uint32_t * lvalp, int flags, uint64_t mtid, uint32_t mask, uint64_t * tidp, int *sysret);
+int _pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr, uint32_t static_type);
-int _new_pthread_mutex_destroy(pthread_mutex_t *mutex);
-int _new_pthread_mutex_destroy_locked(pthread_mutex_t *mutex);
-int _new_pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
-int _new_pthread_mutex_lock(pthread_mutex_t *omutex);
-int _new_pthread_mutex_trylock(pthread_mutex_t *omutex);
-int _new_pthread_mutex_unlock(pthread_mutex_t *omutex);
#if defined(__LP64__)
#define MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr) \
#define _KSYN_TRACE_UM_MHOLD 0x9000068
#define _KSYN_TRACE_UM_MDROP 0x900006c
#define _KSYN_TRACE_UM_MUBITS 0x900007c
+#define _KSYN_TRACE_UM_MARKPP 0x90000a8
#endif /* _KSYN_TRACE_ */
-#endif /* __i386__ || __x86_64__ */
-
#ifndef BUILDING_VARIANT /* [ */
#define BLOCK_FAIL_PLOCKSTAT 0
PLOCKSTAT_MUTEX_SPUN(NULL, 0, 0);
}
-/*
- * Destroy a mutex variable.
- */
-int
-pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
- int res;
-
- LOCK(mutex->lock);
- if (mutex->sig == _PTHREAD_MUTEX_SIG)
- {
-
-#if defined(__i386__) || defined(__x86_64__)
- if(mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED){
-
- res = _new_pthread_mutex_destroy_locked(mutex);
- UNLOCK(mutex->lock);
- return(res);
- }
-#endif /* __i386__ || __x86_64__ */
-
- if (mutex->owner == (pthread_t)NULL &&
- mutex->busy == (pthread_cond_t *)NULL)
- {
- mutex->sig = _PTHREAD_NO_SIG;
- res = 0;
- }
- else
- res = EBUSY;
- } else
- res = EINVAL;
- UNLOCK(mutex->lock);
- return (res);
-}
-
-/*
- * Initialize a mutex variable, possibly with additional attributes.
- */
-int
-_pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
-{
- if (attr)
- {
- if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG)
- return (EINVAL);
-#if defined(__i386__) || defined(__x86_64__)
- if (attr->pshared == PTHREAD_PROCESS_SHARED) {
- return(_new_pthread_mutex_init(mutex, attr));
- } else
-#endif /* __i386__ || __x86_64__ */
- {
- mutex->prioceiling = attr->prioceiling;
- mutex->mtxopts.options.protocol = attr->protocol;
- mutex->mtxopts.options.policy = attr->policy;
- mutex->mtxopts.options.type = attr->type;
- mutex->mtxopts.options.pshared = attr->pshared;
- }
- } else {
- mutex->prioceiling = _PTHREAD_DEFAULT_PRIOCEILING;
- mutex->mtxopts.options.protocol = _PTHREAD_DEFAULT_PROTOCOL;
- mutex->mtxopts.options.policy = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
- mutex->mtxopts.options.type = PTHREAD_MUTEX_DEFAULT;
- mutex->mtxopts.options.pshared = _PTHREAD_DEFAULT_PSHARED;
- }
- mutex->mtxopts.options.lock_count = 0;
- mutex->owner = (pthread_t)NULL;
- mutex->next = (pthread_mutex_t *)NULL;
- mutex->prev = (pthread_mutex_t *)NULL;
- mutex->busy = (pthread_cond_t *)NULL;
- mutex->waiters = 0;
- mutex->sem = SEMAPHORE_NULL;
- mutex->order = SEMAPHORE_NULL;
- mutex->prioceiling = 0;
- mutex->sig = _PTHREAD_MUTEX_SIG;
- return (0);
-}
/*
* Initialize a mutex variable, possibly with additional attributes.
return EBUSY;
#endif
LOCK_INIT(mutex->lock);
- return (_pthread_mutex_init(mutex, attr));
-}
-
-/*
- * Lock a mutex.
- * TODO: Priority inheritance stuff
- */
-int
-pthread_mutex_lock(pthread_mutex_t *mutex)
-{
- kern_return_t kern_res;
- pthread_t self;
- int sig = mutex->sig;
-
- /* To provide backwards compat for apps using mutex incorrectly */
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig != _PTHREAD_MUTEX_SIG_init)) {
- PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
- return(EINVAL);
- }
-
- LOCK(mutex->lock);
- if (mutex->sig != _PTHREAD_MUTEX_SIG)
- {
- if (mutex->sig != _PTHREAD_MUTEX_SIG_init)
- {
- UNLOCK(mutex->lock);
- PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
- return (EINVAL);
- }
- _pthread_mutex_init(mutex, NULL);
- self = _PTHREAD_MUTEX_OWNER_SELF;
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if(mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED){
- UNLOCK(mutex->lock);
- return(_new_pthread_mutex_lock(mutex));
- }
-#endif /* __i386__ || __x86_64__ */
- else if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL)
- {
- self = pthread_self();
- if (mutex->owner == self)
- {
- int res;
-
- if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
- {
- if (mutex->mtxopts.options.lock_count < USHRT_MAX)
- {
- mutex->mtxopts.options.lock_count++;
- PLOCKSTAT_MUTEX_ACQUIRE(mutex, 1, 0);
- res = 0;
- } else {
- res = EAGAIN;
- PLOCKSTAT_MUTEX_ERROR(mutex, res);
- }
- } else { /* PTHREAD_MUTEX_ERRORCHECK */
- res = EDEADLK;
- PLOCKSTAT_MUTEX_ERROR(mutex, res);
- }
- UNLOCK(mutex->lock);
- return (res);
- }
- } else
- self = _PTHREAD_MUTEX_OWNER_SELF;
-
- if (mutex->owner != (pthread_t)NULL) {
- if (mutex->waiters || mutex->owner != _PTHREAD_MUTEX_OWNER_SWITCHING)
- {
- semaphore_t sem, order;
-
- if (++mutex->waiters == 1)
- {
- mutex->sem = sem = new_sem_from_pool();
- mutex->order = order = new_sem_from_pool();
- }
- else
- {
- sem = mutex->sem;
- order = mutex->order;
- do {
- PTHREAD_MACH_CALL(semaphore_wait(order), kern_res);
- } while (kern_res == KERN_ABORTED);
- }
- UNLOCK(mutex->lock);
-
- PLOCKSTAT_MUTEX_BLOCK(mutex);
- PTHREAD_MACH_CALL(semaphore_wait_signal(sem, order), kern_res);
- while (kern_res == KERN_ABORTED)
- {
- PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
- }
-
- PLOCKSTAT_MUTEX_BLOCKED(mutex, BLOCK_SUCCESS_PLOCKSTAT);
-
- LOCK(mutex->lock);
- if (--mutex->waiters == 0)
- {
- PTHREAD_MACH_CALL(semaphore_wait(order), kern_res);
- mutex->sem = mutex->order = SEMAPHORE_NULL;
- restore_sem_to_pool(order);
- restore_sem_to_pool(sem);
- }
- }
- else if (mutex->owner == _PTHREAD_MUTEX_OWNER_SWITCHING)
- {
- semaphore_t sem = mutex->sem;
- do {
- PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
- } while (kern_res == KERN_ABORTED);
- mutex->sem = SEMAPHORE_NULL;
- restore_sem_to_pool(sem);
- }
- }
-
- mutex->mtxopts.options.lock_count = 1;
- mutex->owner = self;
- UNLOCK(mutex->lock);
- PLOCKSTAT_MUTEX_ACQUIRE(mutex, 0, 0);
- return (0);
-}
-
-/*
- * Attempt to lock a mutex, but don't block if this isn't possible.
- */
-int
-pthread_mutex_trylock(pthread_mutex_t *mutex)
-{
- kern_return_t kern_res;
- pthread_t self;
-
- LOCK(mutex->lock);
- if (mutex->sig != _PTHREAD_MUTEX_SIG)
- {
- if (mutex->sig != _PTHREAD_MUTEX_SIG_init)
- {
- PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
- UNLOCK(mutex->lock);
- return (EINVAL);
- }
- _pthread_mutex_init(mutex, NULL);
- self = _PTHREAD_MUTEX_OWNER_SELF;
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if(mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED){
- UNLOCK(mutex->lock);
- return(_new_pthread_mutex_trylock(mutex));
- }
-#endif /* __i386__ || __x86_64__ */
- else if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL)
- {
- self = pthread_self();
- if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
- {
- if (mutex->owner == self)
- {
- int res;
-
- if (mutex->mtxopts.options.lock_count < USHRT_MAX)
- {
- mutex->mtxopts.options.lock_count++;
- PLOCKSTAT_MUTEX_ACQUIRE(mutex, 1, 0);
- res = 0;
- } else {
- res = EAGAIN;
- PLOCKSTAT_MUTEX_ERROR(mutex, res);
- }
- UNLOCK(mutex->lock);
- return (res);
- }
- }
- } else
- self = _PTHREAD_MUTEX_OWNER_SELF;
-
- if (mutex->owner != (pthread_t)NULL)
- {
- if (mutex->waiters || mutex->owner != _PTHREAD_MUTEX_OWNER_SWITCHING)
- {
- PLOCKSTAT_MUTEX_ERROR(mutex, EBUSY);
- UNLOCK(mutex->lock);
- return (EBUSY);
- }
- else if (mutex->owner == _PTHREAD_MUTEX_OWNER_SWITCHING)
- {
- semaphore_t sem = mutex->sem;
-
- do {
- PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
- } while (kern_res == KERN_ABORTED);
- restore_sem_to_pool(sem);
- mutex->sem = SEMAPHORE_NULL;
- }
- }
-
- mutex->mtxopts.options.lock_count = 1;
- mutex->owner = self;
- UNLOCK(mutex->lock);
- PLOCKSTAT_MUTEX_ACQUIRE(mutex, 0, 0);
- return (0);
-}
-
-/*
- * Unlock a mutex.
- * TODO: Priority inheritance stuff
- */
-int
-pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
- kern_return_t kern_res;
- int waiters;
- int sig = mutex->sig;
-
-
- /* To provide backwards compat for apps using mutex incorrectly */
-
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig != _PTHREAD_MUTEX_SIG_init)) {
- PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
- return(EINVAL);
- }
- LOCK(mutex->lock);
- if (mutex->sig != _PTHREAD_MUTEX_SIG)
- {
- if (mutex->sig != _PTHREAD_MUTEX_SIG_init)
- {
- PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
- UNLOCK(mutex->lock);
- return (EINVAL);
- }
- _pthread_mutex_init(mutex, NULL);
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if(mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED){
- UNLOCK(mutex->lock);
- return(_new_pthread_mutex_unlock(mutex));
- }
-#endif /* __i386__ || __x86_64__ */
- else if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL)
- {
- pthread_t self = pthread_self();
- if (mutex->owner != self)
- {
- PLOCKSTAT_MUTEX_ERROR(mutex, EPERM);
- UNLOCK(mutex->lock);
- return EPERM;
- } else if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE &&
- --mutex->mtxopts.options.lock_count)
- {
- PLOCKSTAT_MUTEX_RELEASE(mutex, 1);
- UNLOCK(mutex->lock);
- return(0);
- }
- }
-
- mutex->mtxopts.options.lock_count = 0;
-
- waiters = mutex->waiters;
- if (waiters)
- {
- mutex->owner = _PTHREAD_MUTEX_OWNER_SWITCHING;
- PLOCKSTAT_MUTEX_RELEASE(mutex, 0);
- UNLOCK(mutex->lock);
- PTHREAD_MACH_CALL(semaphore_signal(mutex->sem), kern_res);
- }
- else
- {
- mutex->owner = (pthread_t)NULL;
- PLOCKSTAT_MUTEX_RELEASE(mutex, 0);
- UNLOCK(mutex->lock);
- }
- return (0);
+ return (_pthread_mutex_init(mutex, attr, 0x7));
}
/*
}
}
-#ifdef NOTYET
int
pthread_mutexattr_setpolicy_np(pthread_mutexattr_t *attr,
int policy)
{
if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
{
- if ((policy == _PTHREAD_MUTEX_POLICY_FAIRSHARE) ||
- (policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT) ||
+ if (
+ (policy == _PTHREAD_MUTEX_POLICY_FAIRSHARE) ||
+ (policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT)
+#if NOTYET
+ ||
(policy == _PTHREAD_MUTEX_POLICY_REALTIME) ||
(policy == _PTHREAD_MUTEX_POLICY_ADAPTIVE) ||
(policy == _PTHREAD_MUTEX_POLICY_PRIPROTECT) ||
- (policy == _PTHREAD_MUTEX_POLICY_PRIINHERIT))
+ (policy == _PTHREAD_MUTEX_POLICY_PRIINHERIT)
+#endif /* NOTYET */
+ )
{
attr->policy = policy;
return (0);
return (EINVAL); /* Not an initialized 'attribute' structure */
}
}
-#endif /* NOTYET */
/*
* Set the mutex 'type' value in a mutex attribute structure.
if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
{
#if __DARWIN_UNIX03
-#ifdef PR_5243343
- if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED && PR_5243343_flag))
-#else /* !PR_5243343 */
if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED))
-#endif /* PR_5243343 */
#else /* __DARWIN_UNIX03 */
if ( pshared == PTHREAD_PROCESS_PRIVATE)
#endif /* __DARWIN_UNIX03 */
- {
+ {
attr->pshared = pshared;
return (0);
- } else
- {
+ } else {
return (EINVAL); /* Invalid parameter */
}
} else
}
}
-#if defined(__i386__) || defined(__x86_64__)
-
-/*
- * Acquire lock seq for condition var signalling/broadcast
- */
-__private_extern__ void
-__mtx_holdlock(npthread_mutex_t * mutex, uint32_t diff, uint32_t * flagp, uint32_t **pmtxp, uint32_t * mgenp, uint32_t * ugenp)
-{
- uint32_t mgen, ugen, ngen;
- int hold = 0;
- int firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
- uint32_t * lseqaddr;
- uint32_t * useqaddr;
-
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MHOLD | DBG_FUNC_START, (uint32_t)mutex, diff, firstfit, 0, 0);
-#endif
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED) {
- /* no holds for shared mutexes */
- hold = 2;
- mgen = 0;
- ugen = 0;
- MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- goto out;
- } else {
- lseqaddr = mutex->m_lseqaddr;
- useqaddr = mutex->m_useqaddr;
- }
-
-retry:
- mgen = *lseqaddr;
- ugen = *useqaddr;
- /* no need to do extra wrap */
- ngen = mgen + (PTHRW_INC * diff);
- hold = 0;
-
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MHOLD | DBG_FUNC_NONE, (uint32_t)mutex, 0, mgen, ngen, 0);
-#endif
- /* can we acquire the lock ? */
- if ((mgen & PTHRW_EBIT) == 0) {
- /* if it is firstfit, no need to hold till the cvar returns */
- if (firstfit == 0) {
- ngen |= PTHRW_EBIT;
- hold = 1;
- }
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MHOLD | DBG_FUNC_NONE, (uint32_t)mutex, 1, mgen, ngen, 0);
-#endif
- }
-
- /* update lockseq */
- if (OSAtomicCompareAndSwap32(mgen, ngen, (volatile int32_t *)lseqaddr) != TRUE)
- goto retry;
- if (hold == 1) {
- mutex->m_tid = PTHREAD_MTX_TID_SWITCHING ;
- }
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MHOLD | DBG_FUNC_NONE, (uint32_t)mutex, 2, hold, 0, 0);
-#endif
-
-out:
- if (flagp != NULL) {
- if (hold == 1) {
- *flagp = (mutex->mtxopts.value | _PTHREAD_MTX_OPT_HOLD);
- } else if (hold == 2) {
- *flagp = (mutex->mtxopts.value | _PTHREAD_MTX_OPT_NOHOLD);
- } else {
- *flagp = mutex->mtxopts.value;
- }
- }
- if (mgenp != NULL)
- *mgenp = mgen;
- if (ugenp != NULL)
- *ugenp = ugen;
- if (pmtxp != NULL)
- *pmtxp = lseqaddr;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MHOLD | DBG_FUNC_END, (uint32_t)mutex, hold, 0, 0, 0);
-#endif
-}
-
-
/*
* Drop the mutex unlock references(from cond wait or mutex_unlock().
- * mgenp and ugenp valid only if notifyp is set
*
*/
__private_extern__ int
-__mtx_droplock(npthread_mutex_t * mutex, int count, uint32_t * flagp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp, uint32_t *notifyp)
+__mtx_droplock(npthread_mutex_t * mutex, uint32_t diffgen, uint32_t * flagsp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp)
{
- int oldval, newval, lockval, unlockval;
- uint64_t oldtid;
- pthread_t self = pthread_self();
- uint32_t notify = 0;
- uint64_t oldval64, newval64;
- uint32_t * lseqaddr;
- uint32_t * useqaddr;
+ pthread_t self;
+ uint64_t selfid, resettid;
int firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
+ uint32_t lgenval, ugenval, nlval, ulval, morewaiters=0, flags;
+ volatile uint32_t * lseqaddr, *useqaddr;
+ uint64_t oldval64, newval64;
+ int numwaiters=0, clearprepost = 0;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_START, (uint32_t)mutex, count, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_START, (uint32_t)mutex, diffgen, 0, 0, 0);
#endif
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED) {
- MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- } else {
- lseqaddr = mutex->m_lseqaddr;
- useqaddr = mutex->m_useqaddr;
- }
-
- if (flagp != NULL)
- *flagp = mutex->mtxopts.value;
-
- if (firstfit != 0)
- notify |= 0x80000000;
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED)
- notify |= 0x40000000;
+ MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
+
+ flags = mutex->mtxopts.value;
+ flags &= ~_PTHREAD_MTX_OPT_NOTIFY; /* no notification by default */
+
+
if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL)
{
- if (mutex->m_tid != (uint64_t)((uintptr_t)self))
+ self = pthread_self();
+ (void) pthread_threadid_np(self, &selfid);
+
+ if (mutex->m_tid != selfid)
{
+ //LIBC_ABORT("dropping recur or error mutex not owned by the thread\n");
PLOCKSTAT_MUTEX_ERROR((pthread_mutex_t *)mutex, EPERM);
return(EPERM);
} else if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE &&
}
- if (mutex->m_tid != (uint64_t)((uintptr_t)self))
- return(EINVAL);
-
-
-ml0:
- oldval = *useqaddr;
- unlockval = oldval + (PTHRW_INC * count);
- lockval = *lseqaddr;
-
+retry:
+ lgenval = *lseqaddr;
+ ugenval = *useqaddr;
+
+ numwaiters = diff_genseq((lgenval & PTHRW_COUNT_MASK),(ugenval & PTHRW_COUNT_MASK)); /* pendig waiters */
+
+ if (numwaiters == 0) {
+ /* spurious unlocks, do not touch tid */
+ oldval64 = (((uint64_t)ugenval) << 32);
+ oldval64 |= lgenval;
+ if ((firstfit != 0) && ((lgenval & PTH_RWL_PBIT) != 0)) {
+ clearprepost = 1;
+ lgenval &= ~PTH_RWL_PBIT;
+ newval64 = (((uint64_t)ugenval) << 32);
+ newval64 |= lgenval;
+ } else
+ newval64 = oldval64;
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
+ goto retry;
+ /* validated L & U to be same, this is spurious unlock */
+ flags &= ~_PTHREAD_MTX_OPT_NOTIFY;
+ if (clearprepost == 1)
+ __psynch_cvclrprepost(mutex, lgenval, ugenval, 0, 0, lgenval, (flags | _PTHREAD_MTX_OPT_MUTEX));
+
+ goto out;
+ }
+ if (numwaiters < diffgen) {
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, 10, lockval, oldval, 0);
-#endif
-#if 1
- if (lockval == oldval)
- LIBC_ABORT("same unlock and lockseq \n");
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, numwaiters, lgenval, ugenval, 0);
#endif
-
- if ((lockval & PTHRW_COUNT_MASK) == unlockval) {
- oldtid = mutex->m_tid;
-
- mutex->m_tid = 0;
-
- oldval64 = (((uint64_t)oldval) << 32);
- oldval64 |= lockval;
-
- newval64 = 0;
+ /* cannot drop more than existing number of waiters */
+ diffgen = numwaiters;
+ }
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, 1, 0, 0, 0);
-#endif
- goto out;
- } else {
- mutex->m_tid = oldtid;
- /* fall thru for kernel call */
- goto ml0;
+ oldval64 = (((uint64_t)ugenval) << 32);
+ oldval64 |= lgenval;
+ ulval = ugenval + diffgen;
+ nlval = lgenval;
+
+ if ((lgenval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK)) {
+ /* do not reset Ibit, just K&E */
+ nlval &= ~(PTH_RWL_KBIT | PTH_RWL_EBIT);
+ flags &= ~_PTHREAD_MTX_OPT_NOTIFY;
+ if ((firstfit != 0) && ((lgenval & PTH_RWL_PBIT) != 0)) {
+ clearprepost = 1;
+ nlval &= ~PTH_RWL_PBIT;
}
- }
+ } else {
+ /* need to signal others waiting for mutex */
+ morewaiters = 1;
+ flags |= _PTHREAD_MTX_OPT_NOTIFY;
+ }
- if (firstfit != 0) {
- /* reset ebit along with unlock */
- newval = (lockval & ~PTHRW_EBIT);
+ if (((nlval & PTH_RWL_EBIT) != 0) && (firstfit != 0)) {
+ nlval &= ~PTH_RWL_EBIT; /* reset Ebit so another can acquire meanwhile */
+ }
- lockval = newval;
- oldval64 = (((uint64_t)oldval) << 32);
- oldval64 |= lockval;
+ newval64 = (((uint64_t)ulval) << 32);
+ newval64 |= nlval;
- newval64 = (((uint64_t)unlockval) << 32);
- newval64 |= newval;
+ resettid = mutex->m_tid;
+
+ if ((lgenval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK))
+ mutex->m_tid = 0;
+ else if (firstfit == 0)
+ mutex->m_tid = PTHREAD_MTX_TID_SWITCHING;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE) {
+ mutex->m_tid = resettid;
+ goto retry;
+ }
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE) {
- goto ml0;
- }
- lockval = newval;
- } else {
- /* fairshare , just update and go to kernel */
- if (OSAtomicCompareAndSwap32(oldval, unlockval, (volatile int32_t *)useqaddr) != TRUE)
- goto ml0;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, 2, oldval, unlockval, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, 2, nlval, ulval, 0);
#endif
- }
-
- notify |= 1;
- if (notifyp != 0) {
- if (mgenp != NULL)
- *mgenp = lockval;
- if (ugenp != NULL)
- *ugenp = unlockval;
- if (pmtxp != NULL)
- *pmtxp = lseqaddr;
- *notifyp = notify;
+ if (clearprepost != 0) {
+ __psynch_cvclrprepost(mutex, nlval, ulval, 0, 0, nlval, (flags | _PTHREAD_MTX_OPT_MUTEX));
}
+
+ if (mgenp != NULL)
+ *mgenp = nlval;
+ if (ugenp != NULL)
+ *ugenp = ulval;
+#if USE_COMPAGE
+ if (pmtxp != NULL)
+ *pmtxp = lseqaddr;
+#else
+ if (pmtxp != NULL)
+ *pmtxp = (uint32_t *)mutex;
+#endif
+
out:
- if (notifyp != 0) {
- *notifyp = notify;
- }
+ if (flagsp != NULL)
+ *flagsp = flags;
+
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_END, (uint32_t)mutex, flags, 0, 0, 0);
#endif
return(0);
}
int
-__mtx_updatebits(npthread_mutex_t *mutex, uint32_t oupdateval, int firstfit, int fromcond)
+__mtx_updatebits(npthread_mutex_t *mutex, uint32_t oupdateval, int firstfit, int fromcond, uint64_t selfid)
{
- uint32_t lgenval, newval, bits;
- int isebit = 0;
uint32_t updateval = oupdateval;
+#if !USE_COMPAGE
pthread_mutex_t * omutex = (pthread_mutex_t *)mutex;
- uint32_t * lseqaddr;
- uint32_t * useqaddr;
+#endif
+ int isebit = 0;
+ uint32_t lgenval, ugenval, nval, uval, bits;
+ volatile uint32_t * lseqaddr, *useqaddr;
+ uint64_t oldval64, newval64;
+
+ MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED) {
- MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- } else {
- lseqaddr = mutex->m_lseqaddr;
- useqaddr = mutex->m_useqaddr;
- }
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_START, (uint32_t)mutex, oupdateval, firstfit, fromcond, 0);
#endif
retry:
lgenval = *lseqaddr;
+ ugenval = *useqaddr;
bits = updateval & PTHRW_BIT_MASK;
- if (lgenval == updateval)
- goto out;
-
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 1, lgenval, updateval, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 1, lgenval, ugenval, 0);
#endif
- if ((lgenval & PTHRW_BIT_MASK) == bits)
- goto out;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, bits, 0);
-#endif
- /* firsfit might not have EBIT */
- if (firstfit != 0) {
- lgenval &= ~PTHRW_EBIT; /* see whether EBIT is set */
- if ((lgenval & PTHRW_EBIT) != 0)
- isebit = 1;
+
+ if ((updateval & PTH_RWL_MTX_WAIT) != 0) {
+ lgenval = (updateval & PTHRW_COUNT_MASK) | (lgenval & PTHRW_BIT_MASK);
+ if (fromcond == 0) {
+ /* if from mutex_lock(), it will handle the rewind */
+ return(1);
+ }
+ /* go block in the kernel with same lgenval as returned */
+ goto ml1;
+ } else {
+ /* firsfit might not have EBIT */
+ if (firstfit != 0) {
+ if ((lgenval & PTH_RWL_EBIT) != 0)
+ isebit = 1;
+ else
+ isebit = 0;
+ } else if ((lgenval & (PTH_RWL_KBIT|PTH_RWL_EBIT)) == (PTH_RWL_KBIT|PTH_RWL_EBIT)) {
+ /* fairshare mutex and the bits are already set, just update tid */
+ goto out;
+ }
}
- if ((lgenval & PTHRW_COUNT_MASK) == (updateval & PTHRW_COUNT_MASK)) {
+ /* either firstfist or no E bit set */
+ /* update the bits */
+ oldval64 = (((uint64_t)ugenval) << 32);
+ oldval64 |= lgenval;
+ uval = ugenval;
+ nval = lgenval | (PTH_RWL_KBIT|PTH_RWL_EBIT);
+ newval64 = (((uint64_t)uval) << 32);
+ newval64 |= nval;
+
+ /* set s and b bit */
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 3, lgenval, updateval, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 2, nval, uval, 0);
#endif
- updateval |= PTHRW_EBIT; /* just in case.. */
- if (OSAtomicCompareAndSwap32(lgenval, updateval, (volatile int32_t *)lseqaddr) != TRUE) {
- if (firstfit == 0)
- goto retry;
+ if ((firstfit != 0) && (isebit != 0))
goto handleffit;
- }
- /* update succesfully */
- goto out;
- }
-
- if (((lgenval & PTHRW_WBIT) != 0) && ((updateval & PTHRW_WBIT) == 0)) {
- newval = lgenval | (bits | PTHRW_WBIT | PTHRW_EBIT);
- } else {
- newval = lgenval | (bits | PTHRW_EBIT);
+ goto out;
+ } else {
+ if (firstfit == 0)
+ goto retry;
+ else
+ goto handleffit;
}
-
+
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 4, lgenval, newval, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 4, nval, uval, 0);
#endif
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE) {
- if (firstfit == 0)
- goto retry;
- goto handleffit;
- }
+
out:
/* succesful bits updation */
- mutex->m_tid = (uint64_t)((uintptr_t)pthread_self());
+ mutex->m_tid = selfid;
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
#endif
handleffit:
/* firstfit failure */
- newval = *lseqaddr;
- if ((newval & PTHRW_EBIT) == 0)
+ lgenval = *lseqaddr;
+ ugenval = *useqaddr;
+ if ((lgenval & PTH_RWL_EBIT) == 0)
goto retry;
- if (((lgenval & PTHRW_COUNT_MASK) == (newval & PTHRW_COUNT_MASK)) && (isebit == 1)) {
- if (fromcond == 0)
- return(1);
- else {
- /* called from condition variable code block again */
+
+ if (fromcond == 0)
+ return(1);
+ else {
+ /* called from condition variable code block again */
ml1:
#if USE_COMPAGE /* [ */
- updateval = __psynch_mutexwait((pthread_mutex_t *)lseqaddr, newval | PTHRW_RETRYBIT, *useqaddr, (uint64_t)0,
- mutex->mtxopts.value);
+ updateval = __psynch_mutexwait((pthread_mutex_t *)lseqaddr, lgenval | PTH_RWL_RETRYBIT, ugenval, mutex->m_tid,
+ mutex->mtxopts.value);
#else /* USECOMPAGE ][ */
- updateval = __psynch_mutexwait(omutex, newval | PTHRW_RETRYBIT, *useqaddr, (uint64_t)0,
+ updateval = __psynch_mutexwait(omutex, lgenval | PTH_RWL_RETRYBIT, ugenval, mutex->m_tid,
+ mutex->mtxopts.value);
#endif /* USE_COMPAGE ] */
- if (updateval == (uint32_t)-1) {
- goto ml1;
- }
-
- goto retry;
+ if (updateval == (uint32_t)-1) {
+ goto ml1;
}
+
+ /* now update the bits */
+ goto retry;
}
- /* seqcount changed, retry */
+ /* cannot reach */
goto retry;
}
+
int
-_new_pthread_mutex_lock(pthread_mutex_t *omutex)
+__mtx_markprepost(npthread_mutex_t *mutex, uint32_t oupdateval, int firstfit)
+{
+ uint32_t updateval = oupdateval;
+ int clearprepost = 0;
+ uint32_t lgenval, ugenval,flags;
+ volatile uint32_t * lseqaddr, *useqaddr;
+ uint64_t oldval64, newval64;
+
+ MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_START, (uint32_t)mutex, oupdateval, firstfit, 0, 0);
+#endif
+
+retry:
+
+
+
+ if ((firstfit != 0) && ((updateval & PTH_RWL_PBIT) != 0)) {
+ flags = mutex->mtxopts.value;
+
+ lgenval = *lseqaddr;
+ ugenval = *useqaddr;
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_NONE, (uint32_t)mutex, 1, lgenval, ugenval, 0);
+#endif
+ /* update the bits */
+ oldval64 = (((uint64_t)ugenval) << 32);
+ oldval64 |= lgenval;
+
+ if ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK)) {
+ clearprepost = 1;
+ lgenval &= ~PTH_RWL_PBIT;
+
+ } else {
+ lgenval |= PTH_RWL_PBIT;
+ }
+ newval64 = (((uint64_t)ugenval) << 32);
+ newval64 |= lgenval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
+#endif
+
+ if (clearprepost != 0)
+ __psynch_cvclrprepost(mutex, lgenval, ugenval, 0, 0, lgenval, (flags | _PTHREAD_MTX_OPT_MUTEX));
+
+ } else {
+ goto retry;
+ }
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
+#endif
+ }
+ return(0);
+}
+
+/*
+ * For the new style mutex, interlocks are not held all the time.
+ * We needed the signature to be set in the end. And we need
+ * to protect against the code getting reorganized by compiler.
+ */
+static void
+__pthread_mutex_set_signature(npthread_mutex_t * mutex)
+{
+ mutex->sig = _PTHREAD_MUTEX_SIG;
+}
+
+int
+pthread_mutex_lock(pthread_mutex_t *omutex)
{
pthread_t self;
+ uint64_t selfid;
npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
int sig = mutex->sig;
+#if NEVERINCOMPAGE || !USE_COMPAGE
+ //uint32_t oldval, newval;
+#endif
int retval;
- uint32_t oldval, newval, uval, updateval;
- int gotlock = 0;
- int firstfit = 0;
- int retrybit = 0;
- uint32_t * lseqaddr;
- uint32_t * useqaddr;
- int updatebitsonly = 0;
+ int gotlock = 0, firstfit = 0;
+ uint32_t updateval, lgenval, ugenval, nval, uval;
+ volatile uint32_t * lseqaddr, *useqaddr;
+ uint64_t oldval64, newval64;
#if USE_COMPAGE
- uint64_t mytid;
int sysret = 0;
uint32_t mask;
#else
-
+ int retrybit = 0;
#endif
/* To provide backwards compat for apps using mutex incorrectly */
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig != _PTHREAD_MUTEX_SIG_init)) {
+ if ((sig != _PTHREAD_MUTEX_SIG) && ((sig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP)) {
PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
return(EINVAL);
}
- if (sig != _PTHREAD_MUTEX_SIG) {
+ if (mutex->sig != _PTHREAD_MUTEX_SIG) {
LOCK(mutex->lock);
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig == _PTHREAD_MUTEX_SIG_init)) {
- /* static initializer, init the mutex */
- _new_pthread_mutex_init(omutex, NULL);
- self = _PTHREAD_MUTEX_OWNER_SELF;
- } else {
+ if ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) == _PTHREAD_MUTEX_SIG_CMP) {
+ /* static initializer, init the mutex */
+ if(retval = _pthread_mutex_init(omutex, NULL, (mutex->sig & 0xf)) != 0){
+ UNLOCK(mutex->lock);
+ PLOCKSTAT_MUTEX_ERROR(omutex, retval);
+ return(retval);
+ }
+ } else if (mutex->sig != _PTHREAD_MUTEX_SIG) {
UNLOCK(mutex->lock);
PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
return(EINVAL);
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_START, (uint32_t)mutex, 0, 0, 0, 0);
#endif
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED) {
- MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- } else {
- lseqaddr = mutex->m_lseqaddr;
- useqaddr = mutex->m_useqaddr;
- }
+ MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
self = pthread_self();
+ (void) pthread_threadid_np(self, &selfid);
+
if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL) {
- if (mutex->m_tid == (uint64_t)((uintptr_t)self)) {
+ if (mutex->m_tid == selfid) {
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
{
if (mutex->mtxopts.options.lock_count < USHRT_MAX)
return (retval);
}
}
+
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 1, 0, 0, 0);
#endif
-loop:
-#if USE_COMPAGE /* [ */
- mytid = (uint64_t)((uintptr_t)pthread_self());
+#if USE_COMPAGE /* [ */
ml0:
- mask = PTHRW_EBIT;
- retval = _commpage_pthread_mutex_lock(lseqaddr, mutex->mtxopts.value, mytid, mask, &mutex->m_tid, &sysret);
+ mask = PTH_RWL_EBIT;
+ retval = _commpage_pthread_mutex_lock(lseqaddr, mutex->mtxopts.value, selfid, mask, &mutex->m_tid, &sysret);
if (retval == 0) {
gotlock = 1;
} else if (retval == 1) {
gotlock = 1;
updateval = sysret;
/* returns 0 on succesful update */
- if (__mtx_updatebits( mutex, updateval, firstfit, 0) == 1) {
+ if (__mtx_updatebits( mutex, updateval, firstfit, 0, selfid) == 1) {
/* could not acquire, may be locked in ffit case */
#if USE_COMPAGE
LIBC_ABORT("comapge implementatin looping in libc \n");
}
#endif
else {
- LIBC_ABORT("comapge implementatin bombed \n");
+ LIBC_ABORT("comapge implementation bombed \n");
}
#else /* USECOMPAGE ][ */
- oldval = *lseqaddr;
- uval = *useqaddr;
- newval = oldval + PTHRW_INC;
+retry:
+ lgenval = *lseqaddr;
+ ugenval = *useqaddr;
- (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, oldval, uval, 0);
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
+#endif /* _KSYN_TRACE_ */
- if((oldval & PTHRW_EBIT) == 0) {
+ if((lgenval & PTH_RWL_EBIT) == 0) {
gotlock = 1;
- newval |= PTHRW_EBIT;
} else {
gotlock = 0;
- newval |= PTHRW_WBIT;
}
-
- if (OSAtomicCompareAndSwap32(oldval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- if (gotlock != 0)
- mutex->m_tid = (uint64_t)((uintptr_t)self);
+
+ oldval64 = (((uint64_t)ugenval) << 32);
+ oldval64 |= lgenval;
+ uval = ugenval;
+ nval = (lgenval + PTHRW_INC) | (PTH_RWL_EBIT|PTH_RWL_KBIT);
+ newval64 = (((uint64_t)uval) << 32);
+ newval64 |= nval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, oldval, newval, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, nval, uval, 0);
#endif
+ if (gotlock != 0) {
+ mutex->m_tid = selfid;
+ goto out;
+ }
} else
- goto loop;
+ goto retry;
retrybit = 0;
if (gotlock == 0) {
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 3, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 3, nval, uval, 0);
#endif
firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
ml1:
- updateval = __psynch_mutexwait(omutex, newval | retrybit, uval, (uint64_t)0,
+ updateval = __psynch_mutexwait(omutex, nval | retrybit, uval, mutex->m_tid,
mutex->mtxopts.value);
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 4, updateval, 0, 0);
+#endif
if (updateval == (uint32_t)-1) {
- updatebitsonly = 0;
goto ml1;
}
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 4, updateval, 0, 0);
-#endif
- /* returns 0 on succesful update */
- if (__mtx_updatebits( mutex, updateval, firstfit, 0) == 1) {
+ /* returns 0 on succesful update; in firstfit it may fail with 1 */
+ if (__mtx_updatebits( mutex, PTHRW_INC | (PTH_RWL_KBIT | PTH_RWL_EBIT), firstfit, 0, selfid) == 1) {
/* could not acquire, may be locked in ffit case */
- retrybit = PTHRW_RETRYBIT;
+ retrybit = PTH_RWL_RETRYBIT;
#if USE_COMPAGE
LIBC_ABORT("comapge implementatin looping in libc \n");
}
#endif /* USE_COMPAGE ] */
+out:
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
- mutex->mtxopts.options.lock_count++;
+ mutex->mtxopts.options.lock_count = 1;
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
* Attempt to lock a mutex, but don't block if this isn't possible.
*/
int
-_new_pthread_mutex_trylock(pthread_mutex_t *omutex)
+pthread_mutex_trylock(pthread_mutex_t *omutex)
{
npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
int sig = mutex->sig;
- uint32_t oldval, newval;
int error = 0;
pthread_t self;
- uint32_t * lseqaddr;
- uint32_t * useqaddr;
+ uint64_t selfid;
+ int gotlock = 0;
+ uint32_t lgenval, ugenval, nval, uval;
+ volatile uint32_t * lseqaddr, *useqaddr;
+ uint64_t oldval64, newval64;
/* To provide backwards compat for apps using mutex incorrectly */
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig != _PTHREAD_MUTEX_SIG_init)) {
+ if ((sig != _PTHREAD_MUTEX_SIG) && ((sig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP)) {
PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
return(EINVAL);
}
- if (sig != _PTHREAD_MUTEX_SIG) {
+ if ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) == _PTHREAD_MUTEX_SIG_CMP) {
LOCK(mutex->lock);
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig == _PTHREAD_MUTEX_SIG_init)) {
+ if (mutex->sig == _PTHREAD_MUTEX_SIG_init) {
/* static initializer, init the mutex */
- _new_pthread_mutex_init(omutex, NULL);
- self = _PTHREAD_MUTEX_OWNER_SELF;
- } else {
+ if((error = _pthread_mutex_init(omutex, NULL, (mutex->sig & 0xf))) != 0){
+ UNLOCK(mutex->lock);
+ PLOCKSTAT_MUTEX_ERROR(omutex, error);
+ return(error);
+ }
+ } else if (mutex->sig != _PTHREAD_MUTEX_SIG) {
UNLOCK(mutex->lock);
PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
return(EINVAL);
UNLOCK(mutex->lock);
}
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED) {
- MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- } else {
- lseqaddr = mutex->m_lseqaddr;
- useqaddr = mutex->m_useqaddr;
- }
+ MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
self = pthread_self();
+ (void) pthread_threadid_np(self, &selfid);
+
if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL) {
- if (mutex->m_tid == (uint64_t)((uintptr_t)self)) {
+ if (mutex->m_tid == selfid) {
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
{
if (mutex->mtxopts.options.lock_count < USHRT_MAX)
return (error);
}
}
-retry:
- oldval = *lseqaddr;
+retry:
+ lgenval = *lseqaddr;
+ ugenval = *useqaddr;
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
+#endif /* _KSYN_TRACE_ */
+
- if ((oldval & PTHRW_EBIT) != 0) {
- newval = oldval | PTHRW_TRYLKBIT;
- if (OSAtomicCompareAndSwap32(oldval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- error = EBUSY;
- } else
- goto retry;
+ oldval64 = (((uint64_t)ugenval) << 32);
+ oldval64 |= lgenval;
+ uval = ugenval;
+
+ /* if we can acquire go ahead otherwise ensure it is still busy */
+ if((lgenval & PTH_RWL_EBIT) == 0) {
+ gotlock = 1;
+ nval = (lgenval + PTHRW_INC) | (PTH_RWL_EBIT|PTH_RWL_KBIT);
} else {
- newval = (oldval + PTHRW_INC)| PTHRW_EBIT;
- if ((OSAtomicCompareAndSwap32(oldval, newval, (volatile int32_t *)lseqaddr) == TRUE)) {
- mutex->m_tid = (uint64_t)((uintptr_t)self);
- if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
- mutex->mtxopts.options.lock_count++;
- } else
- goto retry;
+ nval = (lgenval | PTH_RWL_TRYLKBIT);
+ gotlock = 0;
}
+
+ newval64 = (((uint64_t)uval) << 32);
+ newval64 |= nval;
+
+ /* set s and b bit */
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, nval, uval, 0);
+#endif
+ if (gotlock != 0) {
+ mutex->m_tid = selfid;
+ if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
+ mutex->mtxopts.options.lock_count = 1;
+ PLOCKSTAT_MUTEX_ACQUIRE(omutex, 1, 0);
+ } else {
+ error = EBUSY;
+ PLOCKSTAT_MUTEX_ERROR(omutex, error);
+ }
+ } else
+ goto retry;
- return(error);
+
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_END, (uint32_t)mutex, 0xfafafafa, 0, error, 0);
+#endif
+ return (error);
}
/*
* TODO: Priority inheritance stuff
*/
int
-_new_pthread_mutex_unlock(pthread_mutex_t *omutex)
+pthread_mutex_unlock(pthread_mutex_t *omutex)
{
npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
int retval;
- uint32_t mtxgen, mtxugen, flags, notify;
+ uint32_t mtxgen, mtxugen, flags, notify, updateval;
int sig = mutex->sig;
- pthread_t self = pthread_self();
- uint32_t * lseqaddr;
- uint32_t * useqaddr;
+ pthread_t self;
+ uint64_t selfid;
+ volatile uint32_t * lseqaddr, *useqaddr;
+ int firstfit = 0;
/* To provide backwards compat for apps using mutex incorrectly */
#if _KSYN_TRACE_
(void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_START, (uint32_t)mutex, 0, 0, 0, 0);
#endif
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig != _PTHREAD_MUTEX_SIG_init)) {
+ if ((sig != _PTHREAD_MUTEX_SIG) && ((sig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP)) {
PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
return(EINVAL);
}
- if (sig != _PTHREAD_MUTEX_SIG) {
+
+ if (mutex->sig != _PTHREAD_MUTEX_SIG) {
LOCK(mutex->lock);
- if ((sig != _PTHREAD_MUTEX_SIG) && (sig == _PTHREAD_MUTEX_SIG_init)) {
+ if ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) == _PTHREAD_MUTEX_SIG_CMP) {
/* static initializer, init the mutex */
- _new_pthread_mutex_init(omutex, NULL);
- self = _PTHREAD_MUTEX_OWNER_SELF;
- } else {
+ if((retval = _pthread_mutex_init(omutex, NULL, (mutex->sig & 0xf))) != 0){
+ UNLOCK(mutex->lock);
+ PLOCKSTAT_MUTEX_ERROR(omutex, retval);
+ return(retval);
+ }
+ } else if (mutex->sig != _PTHREAD_MUTEX_SIG) {
UNLOCK(mutex->lock);
PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
return(EINVAL);
}
UNLOCK(mutex->lock);
}
-
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED) {
- MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- } else {
- lseqaddr = mutex->m_lseqaddr;
- useqaddr = mutex->m_useqaddr;
- }
+
+ MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
+
notify = 0;
- retval = __mtx_droplock(mutex, 1, &flags, NULL, &mtxgen, &mtxugen, ¬ify);
+ retval = __mtx_droplock(mutex, PTHRW_INC, &flags, NULL, &mtxgen, &mtxugen);
if (retval != 0)
return(retval);
- if ((notify & 1) != 0) {
+ if ((flags & _PTHREAD_MTX_OPT_NOTIFY) != 0) {
+ firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
+
+ self = pthread_self();
+ (void) pthread_threadid_np(self, &selfid);
+
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_NONE, (uint32_t)mutex, 1, 0, 0, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_NONE, (uint32_t)mutex, 1, mtxgen, mtxugen, 0);
#endif
#if USE_COMPAGE /* [ */
- if ( __psynch_mutexdrop((pthread_mutex_t *)lseqaddr, mtxgen, mtxugen, (uint64_t)0, flags)== (uint32_t)-1)
+ if ((updateval = __psynch_mutexdrop((pthread_mutex_t *)lseqaddr, mtxgen, mtxugen, mutex->m_tid, flags)) == (uint32_t)-1)
#else /* USECOMPAGE ][ */
- if ( __psynch_mutexdrop(omutex, mtxgen, mtxugen, (uint64_t)0, flags)== (uint32_t)-1)
+ if ((updateval = __psynch_mutexdrop(omutex, mtxgen, mtxugen, mutex->m_tid, flags))== (uint32_t)-1)
#endif /* USE_COMPAGE ] */
{
- if (errno == EINTR)
+ retval = errno;
+#if _KSYN_TRACE_
+ (void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_END, (uint32_t)mutex, retval, 0, 0, 0);
+#endif
+ if (retval == 0)
return(0);
- else
- return(errno);
+ else if (errno == EINTR)
+ return(0);
+ else {
+ LIBC_ABORT("__p_mutexdrop failed with error %d\n", retval);
+ return(retval);
+ }
+ } else if (firstfit == 1) {
+ if ((updateval & PTH_RWL_PBIT) != 0) {
+ __mtx_markprepost(mutex, updateval, firstfit);
+ }
}
}
#if _KSYN_TRACE_
* Initialize a mutex variable, possibly with additional attributes.
*/
int
-_new_pthread_mutex_init(pthread_mutex_t *omutex, const pthread_mutexattr_t *attr)
+_pthread_mutex_init(pthread_mutex_t *omutex, const pthread_mutexattr_t *attr, uint32_t static_type)
{
npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
mutex->mtxopts.options.type = attr->type;
mutex->mtxopts.options.pshared = attr->pshared;
} else {
+ switch(static_type) {
+ case 1:
+ mutex->mtxopts.options.type = PTHREAD_MUTEX_ERRORCHECK;
+ break;
+ case 2:
+ mutex->mtxopts.options.type = PTHREAD_MUTEX_RECURSIVE;
+ break;
+ case 3:
+ /* firstfit fall thru */
+ case 7:
+ mutex->mtxopts.options.type = PTHREAD_MUTEX_DEFAULT;
+ break;
+ default:
+ return(EINVAL);
+ }
+
mutex->prioceiling = _PTHREAD_DEFAULT_PRIOCEILING;
mutex->mtxopts.options.protocol = _PTHREAD_DEFAULT_PROTOCOL;
- mutex->mtxopts.options.policy = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
- mutex->mtxopts.options.type = PTHREAD_MUTEX_DEFAULT;
+ if (static_type != 3)
+ mutex->mtxopts.options.policy = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
+ else
+ mutex->mtxopts.options.policy = _PTHREAD_MUTEX_POLICY_FIRSTFIT;
mutex->mtxopts.options.pshared = _PTHREAD_DEFAULT_PSHARED;
}
+ mutex->mtxopts.options.notify = 0;
+ mutex->mtxopts.options.rfu = 0;
+ mutex->mtxopts.options.hold = 0;
+ mutex->mtxopts.options.mutex = 1;
mutex->mtxopts.options.lock_count = 0;
/* address 8byte aligned? */
if (((uintptr_t)mutex & 0x07) != 0) {
mutex->m_seq[2] = 0;
mutex->prioceiling = 0;
mutex->priority = 0;
- mutex->sig = _PTHREAD_MUTEX_SIG;
+ /*
+ * For the new style mutex, interlocks are not held all the time.
+ * We needed the signature to be set in the end. And we need
+ * to protect against the code getting reorganized by compiler.
+ * mutex->sig = _PTHREAD_MUTEX_SIG;
+ */
+ __pthread_mutex_set_signature(mutex);
return (0);
}
-
/*
* Destroy a mutex variable.
*/
int
-_new_pthread_mutex_destroy(pthread_mutex_t *omutex)
+pthread_mutex_destroy(pthread_mutex_t *omutex)
{
int res;
npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
LOCK(mutex->lock);
- res = _new_pthread_mutex_destroy_locked(omutex);
+ res = _pthread_mutex_destroy_locked(omutex);
UNLOCK(mutex->lock);
return(res);
}
-int
-_new_pthread_mutex_destroy_locked(pthread_mutex_t *omutex)
+static int
+_pthread_mutex_destroy_locked(pthread_mutex_t *omutex)
{
int res;
npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
- uint32_t lgenval;
- uint32_t * lseqaddr;
- uint32_t * useqaddr;
+ uint32_t lgenval, ugenval;
+ volatile uint32_t * lseqaddr, *useqaddr;
if (mutex->sig == _PTHREAD_MUTEX_SIG)
{
- if (mutex->mtxopts.options.pshared == PTHREAD_PROCESS_SHARED) {
- MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
- } else {
- lseqaddr = mutex->m_lseqaddr;
- useqaddr = mutex->m_useqaddr;
- }
+ MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
lgenval = *(lseqaddr);
+ ugenval = *(useqaddr);
if ((mutex->m_tid == (uint64_t)0) &&
- ((lgenval & PTHRW_COUNT_MASK) == 0))
+ ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK)))
{
mutex->sig = _PTHREAD_NO_SIG;
res = 0;
}
else
res = EBUSY;
- } else
+ } else if((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK )== _PTHREAD_MUTEX_SIG_CMP) {
+ mutex->sig = _PTHREAD_NO_SIG;
+ res = 0;
+ } else
res = EINVAL;
return (res);
}
-#endif /* __i386__ || __x86_64__ */
#endif /* !BUILDING_VARIANT ] */
/* maximum number of times a read lock may be obtained */
#define MAX_READ_LOCKS (INT_MAX - 1)
-#if defined(__i386__) || defined(__x86_64__)
#ifndef BUILDING_VARIANT /* [ */
-int usenew_impl = 0;
+__private_extern__ int usenew_impl = 1;
#else /* BUILDING_VARIANT */
extern int usenew_impl;
#endif /* BUILDING_VARIANT */
+extern int PR_5243343_flag;
#if defined(__LP64__)
-#define RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr) \
+#define RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr) \
{ \
if (rwlock->misalign != 0) { \
- lseqaddr = &rwlock->rw_seq[1]; \
- wcaddr = &rwlock->rw_seq[2]; \
- useqaddr = &rwlock->rw_seq[3]; \
+ lcntaddr = &rwlock->rw_seq[1]; \
+ seqaddr = &rwlock->rw_seq[2]; \
+ ucntaddr = &rwlock->rw_seq[3]; \
} else { \
- lseqaddr = &rwlock->rw_seq[0]; \
- wcaddr = &rwlock->rw_seq[1]; \
- useqaddr = &rwlock->rw_seq[2]; \
+ lcntaddr = &rwlock->rw_seq[0]; \
+ seqaddr = &rwlock->rw_seq[1]; \
+ ucntaddr = &rwlock->rw_seq[2]; \
} \
}
#else /* __LP64__ */
-#define RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr) \
+#define RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr) \
{ \
if (rwlock->misalign != 0) { \
- lseqaddr = &rwlock->rw_seq[0]; \
- wcaddr = &rwlock->rw_seq[1]; \
- useqaddr = &rwlock->rw_seq[2]; \
- }else { \
- lseqaddr = &rwlock->rw_seq[1]; \
- wcaddr = &rwlock->rw_seq[2]; \
- useqaddr = &rwlock->rw_seq[3]; \
+ lcntaddr = &rwlock->rw_seq[1]; \
+ seqaddr = &rwlock->rw_seq[2]; \
+ ucntaddr = &rwlock->rw_seq[3]; \
+ } else { \
+ lcntaddr = &rwlock->rw_seq[0]; \
+ seqaddr = &rwlock->rw_seq[1]; \
+ ucntaddr = &rwlock->rw_seq[2]; \
} \
}
#endif /* __LP64__ */
-int _new_pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
-int _new_pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_longrdlock_np(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_yieldwrlock_np(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_downgrade_np(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_upgrade_np(pthread_rwlock_t *rwlock);
+__private_extern__ int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
+
#define _KSYN_TRACE_ 0
#if _KSYN_TRACE_
+#include <sys/sysctl.h>
+#ifndef BUILDING_VARIANT /* [ */
+static void set_enable(int);
+#endif /* !BUILDING_VARIANT ] */
+
/* The Function qualifiers */
#define DBG_FUNC_START 1
#define DBG_FUNC_END 2
#define _KSYN_TRACE_RW_UNACT2 0x9008090
#define _KSYN_TRACE_RW_UNACTK 0x9008094
#define _KSYN_TRACE_RW_UNACTE 0x9008098
+#define _KSYN_TRACE_RW_UNACTR 0x900809c
+#define _KSYN_TRACE_RW_TOOMANY 0x90080a0
+#define _KSYN_TRACE_RW_TRYWRLOCK 0x90080a4
+#define _KSYN_TRACE_RW_TRYRDLOCK 0x90080a8
#endif /* _KSYN_TRACE_ */
-#endif /* __i386__ || __x86_64__ */
-
-#ifndef BUILDING_VARIANT /* [ */
-#if defined(__i386__) || defined(__x86_64__)
-static int rwlock_unlock_action_onread(pthread_rwlock_t * rwlock, uint32_t updateval);
-static int rwlock_unlock_action1(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t updateval);
-static int rwlock_unlock_action2(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t updateval);
-static uint32_t modbits(uint32_t lgenval, uint32_t updateval);
-static int rwlock_unlock_action_k(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t updateval);
-static int rwlock_exclusive_lockreturn(pthread_rwlock_t * rwlock, uint32_t updateval);
-static int rw_diffgenseq(uint32_t x, uint32_t y);
-#endif /* __i386__ || __x86_64__ */
+__private_extern__ void rwlock_action_onreturn(pthread_rwlock_t * rwlock, uint32_t updateval);
+__private_extern__ int rw_diffgenseq(uint32_t x, uint32_t y);
+#ifndef BUILDING_VARIANT /* [ */
+static uint32_t modbits(uint32_t lgenval, uint32_t updateval, uint32_t savebits);
int
pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
}
-#if defined(__i386__) || defined(__x86_64__) /* [ */
-int
-_new_pthread_rwlock_destroy(pthread_rwlock_t *orwlock)
+__private_extern__ int
+__pthread_rwlock_init(pthread_rwlock_t * orwlock, const pthread_rwlockattr_t *attr)
{
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-#if __DARWIN_UNIX03
- uint32_t rw_lseqcnt, rw_useqcnt;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-#endif /* __DARWIN_UNIX03 */
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- return(EINVAL);
- } else {
-#if __DARWIN_UNIX03
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- rw_lseqcnt = *lseqaddr;
- rw_useqcnt = *useqaddr;
-
- if((rw_lseqcnt & PTHRW_COUNT_MASK) != rw_useqcnt)
- return(EBUSY);
-
-#endif /* __DARWIN_UNIX03 */
- //bzero(rwlock, sizeof(npthread_rwlock_t));
- rwlock->sig = _PTHREAD_NO_SIG;
- return(0);
- }
-}
-
-int
-_new_pthread_rwlock_init(pthread_rwlock_t * orwlock, const pthread_rwlockattr_t *attr)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-#if __DARWIN_UNIX03
- uint32_t rw_lseqcnt, rw_useqcnt;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-#endif /* __DARWIN_UNIX03 */
-
-#if __DARWIN_UNIX03
- if (attr && (attr->sig != _PTHREAD_RWLOCK_ATTR_SIG)) {
- return(EINVAL);
- }
-
- /* if already inited check whether it is in use, then return EBUSY */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG) {
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
- rw_lseqcnt = *lseqaddr;
- rw_useqcnt = *useqaddr;
-
- if ((rw_lseqcnt & PTHRW_COUNT_MASK) != rw_useqcnt)
- return(EBUSY);
-
- }
-#endif /* __DARWIN_UNIX03 */
-
- /* initialize the lock */
- bzero(rwlock, sizeof(pthread_rwlock_t));
-
if ((attr != NULL) && (attr->pshared == PTHREAD_PROCESS_SHARED)) {
rwlock->pshared = PTHREAD_PROCESS_SHARED;
rwlock->rw_flags = PTHRW_KERN_PROCESS_SHARED;
-
} else {
rwlock->pshared = _PTHREAD_DEFAULT_PSHARED;
rwlock->rw_flags = PTHRW_KERN_PROCESS_PRIVATE;
if (((uintptr_t)rwlock & 0x07) != 0) {
rwlock->misalign = 1;
#if defined(__LP64__)
- rwlock->rw_lseqaddr = &rwlock->rw_seq[1];
- rwlock->rw_wcaddr = &rwlock->rw_seq[2];
- rwlock->rw_useqaddr = &rwlock->rw_seq[3];
- rwlock->rw_seq[1]= PTHRW_RW_INIT;
+ rwlock->rw_lcntaddr = &rwlock->rw_seq[1];
+ rwlock->rw_seqaddr = &rwlock->rw_seq[2];
+ rwlock->rw_ucntaddr = &rwlock->rw_seq[3];
+ rwlock->rw_seq[1]= PTHRW_RWLOCK_INIT;
+ rwlock->rw_seq[2]= PTHRW_RWS_INIT;
+ rwlock->rw_seq[3]= 0;
#else /* __LP64__ */
- rwlock->rw_lseqaddr = &rwlock->rw_seq[0];
- rwlock->rw_wcaddr = &rwlock->rw_seq[1];
- rwlock->rw_useqaddr = &rwlock->rw_seq[2];
- rwlock->rw_seq[0]= PTHRW_RW_INIT;
+ rwlock->rw_lcntaddr = &rwlock->rw_seq[1];
+ rwlock->rw_seqaddr = &rwlock->rw_seq[2];
+ rwlock->rw_ucntaddr = &rwlock->rw_seq[3];
+ rwlock->rw_seq[1]= PTHRW_RWLOCK_INIT;
+ rwlock->rw_seq[2]= PTHRW_RWS_INIT;
+ rwlock->rw_seq[3]= 0;
#endif /* __LP64__ */
} else {
rwlock->misalign = 0;
#if defined(__LP64__)
- rwlock->rw_lseqaddr = &rwlock->rw_seq[0];
- rwlock->rw_wcaddr = &rwlock->rw_seq[1];
- rwlock->rw_useqaddr = &rwlock->rw_seq[2];
- rwlock->rw_seq[0]= PTHRW_RW_INIT;
+ rwlock->rw_lcntaddr = &rwlock->rw_seq[0];
+ rwlock->rw_seqaddr = &rwlock->rw_seq[1];
+ rwlock->rw_ucntaddr = &rwlock->rw_seq[2];
+ rwlock->rw_seq[0]= PTHRW_RWLOCK_INIT;
+ rwlock->rw_seq[1]= PTHRW_RWS_INIT;
+ rwlock->rw_seq[2]= 0;
#else /* __LP64__ */
- rwlock->rw_lseqaddr = &rwlock->rw_seq[1];
- rwlock->rw_wcaddr = &rwlock->rw_seq[2];
- rwlock->rw_useqaddr = &rwlock->rw_seq[3];
- rwlock->rw_seq[1]= PTHRW_RW_INIT;
+ rwlock->rw_lcntaddr = &rwlock->rw_seq[0];
+ rwlock->rw_seqaddr = &rwlock->rw_seq[1];
+ rwlock->rw_ucntaddr = &rwlock->rw_seq[2];
+ rwlock->rw_seq[0]= PTHRW_RWLOCK_INIT;
+ rwlock->rw_seq[1]= PTHRW_RWS_INIT;
+ rwlock->rw_seq[2]= 0;
#endif /* __LP64__ */
}
+
+ rwlock->reserv = 0;
+ rwlock->rw_owner = NULL;
+#if defined(__LP64__)
+ memset(rwlock->rfu, 0, PTHRW_RFU_64BIT);
+#else
+ memset(rwlock->rfu, 0, PTHRW_RFU_32BIT);
+#endif
+
rwlock->sig = _PTHREAD_RWLOCK_SIG;
return(0);
}
-int
-_new_pthread_rwlock_rdlock(pthread_rwlock_t * orwlock)
+#if _KSYN_TRACE_
+static void
+set_enable(int val)
{
-#if __DARWIN_UNIX03
- pthread_t self;
-#endif /* __DARWIN_UNIX03 */
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval, ugenval, rw_wc, newval, updateval;
- int error = 0, ret;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+ int mib[6];
+ size_t needed = 0;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_KDEBUG;
+ mib[2] = KERN_KDENABLE;
+ mib[3] = val;
+ mib[4] = 0;
+ mib[5] = 0;
+ /* best effort to stop the trace */
+ (void)sysctl(mib, 4, NULL, &needed, NULL, 0);
+}
+#endif
+
+static uint32_t
+modbits(uint32_t lgenval, uint32_t updateval, uint32_t savebits)
+{
+ uint32_t lval = lgenval & PTHRW_BIT_MASK;
+ uint32_t uval = updateval & PTHRW_BIT_MASK;
+ uint32_t rval, nlval;
+
+ nlval = (lval | uval) & ~(PTH_RWL_MBIT);
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
+ /* reconcile bits on the lock with what kernel needs to set */
+ if ((uval & PTH_RWL_LBIT) != 0)
+ nlval &= ~PTH_RWL_KBIT;
+ else if (((uval & PTH_RWL_KBIT) == 0) && ((lval & PTH_RWL_WBIT) == 0))
+ nlval &= ~PTH_RWL_KBIT;
+
+ if (savebits !=0 ) {
+ if (((savebits & PTH_RWS_WSVBIT) != 0) && ((nlval & PTH_RWL_WBIT) == 0) &&
+ ((nlval & PTH_RWL_EBIT) == 0)) {
+ if ((nlval & PTH_RWL_LBIT) == 0)
+ nlval |= (PTH_RWL_WBIT | PTH_RWL_KBIT);
+ else
+ nlval |= PTH_RWL_WBIT;
+ }
+ if (((savebits & PTH_RWS_YSVBIT) != 0) && ((nlval & PTH_RWL_YBIT) == 0) &&
+ ((nlval & PTH_RWL_EBIT) == 0)) {
+ nlval |= PTH_RWL_YBIT;
+ }
+ if (((savebits & PTH_RWS_USVBIT) != 0) && ((nlval & PTH_RWL_EBIT) == 0)) {
+ if ((nlval & PTH_RWL_LBIT) == 0)
+ nlval |= (PTH_RWL_UBIT | PTH_RWL_KBIT);
+ else
+ nlval |= PTH_RWL_UBIT;
}
}
+ rval = (lgenval & PTHRW_COUNT_MASK) | nlval;
+ return(rval);
+}
+
+
+__private_extern__ void
+rwlock_action_onreturn(pthread_rwlock_t * orwlock, uint32_t updateval)
+{
+
+ npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+ uint32_t lcntval, rw_seq, newval = 0, newsval, lval, uval;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t oldval64, newval64;
+ int setbits = 0;
+ int overlap = 0;
+ uint32_t savebits = 0;
+ int isoverlap = 0;
+ /* TBD: restore U bit */
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_START, (uint32_t)rwlock, lgenval, newval, rw_wc, 0);
-#endif
-
- if (is_rw_lbit_set(lgenval))
- goto gotlock;
- if(is_rw_ewubit_clear(lgenval))
- goto gotlock;
-
-#if __DARWIN_UNIX03
- if (is_rw_ebit_set(lgenval)) {
- self = pthread_self();
- if(rwlock->rw_owner == self) {
- error = EDEADLK;
- goto out;
- }
+ lcntaddr = rwlock->rw_lcntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
-#endif /* __DARWIN_UNIX03 */
-
- /* mean Lbit is set and R bit not set; block in kernel */
- newval = (lgenval + PTHRW_INC);
-
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
-
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
- newval64 |= newval;
-
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- goto loop;
-
- /* give writers priority over readers */
- PLOCKSTAT_RW_BLOCK(orwlock, READ_LOCK_PLOCKSTAT);
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lgenval, newval, rw_wc+1, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_START, updateval, 0, 0, 0, 0);
#endif
-retry:
- updateval = __psynch_rw_rdlock(orwlock, (newval & ~PTHRW_RW_INIT), ugenval, rw_wc, rwlock->rw_flags);
-
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if (error == EINTR)
- goto retry;
-
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
-
-
+ isoverlap = updateval & PTH_RWL_MBIT;
- if (error == 0) {
- if ((updateval & PTHRW_RW_HUNLOCK) != 0) {
- ret = rwlock_unlock_action_onread(orwlock, (updateval & ~PTHRW_RW_HUNLOCK));
- if (ret != 0) {
- LIBC_ABORT("rdlock_unlock handling failed");
- }
+loop:
+ setbits = 0;
+ lcntval = *lcntaddr;
+ rw_seq = *seqaddr;
+ savebits = 0;
+
+ if (isoverlap != 0) {
+ /* overlap return, just increment and inspect bits */
+ setbits = 1;
+ overlap = 1;
+ /* set s word, increment by specified value */
+ newsval = rw_seq + (updateval & PTHRW_COUNT_MASK);
+ if ((newsval & PTHRW_RWS_SAVEMASK) != 0) {
+ savebits = newsval & PTHRW_RWS_SAVEMASK;
+ newsval &= ~PTHRW_RWS_SAVEMASK;
}
- PLOCKSTAT_RW_BLOCKED(orwlock, READ_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
- PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
- return(0);
} else {
- PLOCKSTAT_RW_BLOCKED(orwlock, READ_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT);
- goto out;
- }
- /* Not reached */
-
-gotlock:
- /* check for max readers */
- ugenval = *useqaddr;
- if (rw_diffgenseq(lgenval, ugenval) >= PTHRW_MAX_READERS) {
- error = EAGAIN;
- goto out;
+ /* normal return */
+ if (is_rws_setunlockinit(rw_seq) != 0) {
+ setbits = 1;
+ /* set s word to passed in value */
+ newsval = (rw_seq & PTHRW_COUNT_MASK) + (updateval & PTHRW_COUNT_MASK);
+ if ((rw_seq & PTHRW_RWS_SAVEMASK) != 0) {
+ savebits = rw_seq & PTHRW_RWS_SAVEMASK;
+ newsval &= ~PTHRW_RWS_SAVEMASK;
+ }
+ } else {
+ newval = lcntval;
+ newsval = rw_seq;
+ }
}
-
- newval = (lgenval + PTHRW_INC);
+ if (setbits != 0) {
+ newval = modbits(lcntval, updateval, savebits);
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lgenval, newval, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, rw_seq, newsval, 0xeeeeeeee, updateval, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, lcntval, newval, 0xeeeeeeee, updateval, 0);
#endif
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, 0, 0, 0);
-#endif
- return(0);
- } else
- goto loop;
-out:
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
+ /* Check for consistency */
+ lval = lcntval & PTHRW_BIT_MASK;
+ uval = updateval & PTHRW_BIT_MASK;
+ }
+
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_END, rw_seq, newsval, 0xffffffff, 0, 0);
#endif
- return(error);
+ return;
}
-
-int
-_new_pthread_rwlock_tryrdlock(pthread_rwlock_t * orwlock)
+/* returns are not bit shifted */
+__private_extern__ int
+rw_diffgenseq(uint32_t x, uint32_t y)
{
- uint32_t lgenval, newval, ugenval;
- int error = 0;
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ uint32_t lx = (x & PTHRW_COUNT_MASK);
+ uint32_t ly = (y &PTHRW_COUNT_MASK);
+
+ if (lx > ly) {
+ return(lx-ly);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ return((PTHRW_MAX_READERS - y) + lx + PTHRW_INC);
}
-loop:
- lgenval = *lseqaddr;
- if (is_rw_lbit_set(lgenval))
- goto gotlock;
- if (is_rw_ewubit_clear(lgenval))
- goto gotlock;
-
-
- error = EBUSY;
- goto out;
-
-gotlock:
- ugenval = *useqaddr;
- if (rw_diffgenseq(lgenval, ugenval) >= PTHRW_MAX_READERS) {
- error = EAGAIN;
- goto out;
- }
-
- newval = (lgenval + PTHRW_INC);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
- return(0);
- } else
- goto loop;
-out:
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
}
#ifdef NOTYET
-/*****************************************************************************/
-/* TBD need to add towards MAX_READERS */
+/********************************************************** */
+static int pthread_rwlock_upgrade_internal(pthread_rwlock_t * orwlock, int trylock);
+
int
-_new_pthread_rwlock_longrdlock_np(pthread_rwlock_t * orwlock)
+pthread_rwlock_longrdlock_np(pthread_rwlock_t * orwlock)
{
pthread_t self;
- uint32_t lgenval, ugenval, rw_wc, newval, updateval;
- int error = 0, ret;
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
+ int error = 0, retry_count = 0;
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t myid = 0;
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+ LOCK(rwlock->lock);
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
return(error);
}
- } else {
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
+ UNLOCK(rwlock->lock);
}
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
loop:
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
- if (is_rw_ewuybit_clear(lgenval))
+ if (can_rwl_longreadinuser(lcntval))
goto gotlock;
-
- /* if w bit is set ensure there is no deadlock */
- if (is_rw_ebit_set(lgenval)) {
+
+#if __DARWIN_UNIX03
+ if (is_rwl_ebit_set(lcntval)) {
self = pthread_self();
if(rwlock->rw_owner == self) {
error = EDEADLK;
goto out;
}
}
+#endif /* __DARWIN_UNIX03 */
- newval = (lgenval + PTHRW_INC);
+ /* need to block in kernel */
+ newval = (lcntval + PTHRW_INC);
+
+ newsval = rw_seq;
+ if (is_rws_setseq(rw_seq)) {
+ newsval &= PTHRW_SW_Reset_BIT_MASK;
+ newsval |= (newval & PTHRW_COUNT_MASK);
+ }
+
/* update lock seq and block in kernel */
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
+ newval64 = (((uint64_t)(newsval)) << 32);
newval64 |= newval;
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
goto loop;
kblock:
- updateval = __psynch_rw_longrdlock(orwlock, newval, ugenval, (rw_wc+1), rwlock->rw_flags);
+ updateval = __psynch_rw_longrdlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
if (updateval == (uint32_t)-1) {
error = errno;
} else
if (error == EINTR)
goto kblock;
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
if (error == 0) {
-
- if ((updateval & PTHRW_RW_HUNLOCK) != 0) {
- ret = rwlock_unlock_action_onread(orwlock, (updateval & ~PTHRW_RW_HUNLOCK));
- if (ret != 0) {
- LIBC_ABORT("rdlock_unlock handling failed");
- }
- }
-
- error = FALSE;
- while (error == FALSE) {
- lgenval = *lseqaddr;
- newval = lgenval | PTHRW_LBIT;
- error = OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr);
+ rwlock_action_onreturn(orwlock, updateval);
+ if ( is_rwl_lbit_clear(updateval)) {
+#if _KSYN_TRACE_
+ set_enable(2);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("yieldwrlock from kernel without EBit %x: tid %x\n", updateval, (uint32_t)myid);
+ /* kernel cannot wakeup without granting E bit */
}
-
goto successout;
- } else
+ } else {
+#if _KSYN_TRACE_
+ set_enable(2);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("yieldwrlock from kernel with unknown error %x: tid %x\n", updateval, (uint32_t)myid);
goto out;
- goto successout;
+ }
gotlock:
- newval = ((lgenval + PTHRW_INC)| PTHRW_LBIT);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- goto loop;
+ if (rw_diffgenseq(lcntval, ucntval) >= PTHRW_MAX_READERS) {
+ /* since ucntval may be newer, just redo */
+ retry_count++;
+ if (retry_count > 1024) {
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TOOMANY | DBG_FUNC_NONE, (uint32_t)rwlock, 0XEEEEEEEE, lcntval, ucntval, 0);
+#endif
+ error = EAGAIN;
+ goto out;
+ } else {
+ sched_yield();
+ goto loop;
+ }
+ }
+
+ /* Need to update L and S word */
+ newval = (lcntval + PTHRW_INC) | PTH_RWL_LBIT;
+ newsval = (rw_seq + PTHRW_INC);
+
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
+
successout:
PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
return(0);
PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
return(error);
}
-/**************************************************************/
-#endif /* NOTYET */
int
-_new_pthread_rwlock_trywrlock(pthread_rwlock_t * orwlock)
+pthread_rwlock_yieldwrlock_np(pthread_rwlock_t * orwlock)
{
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
int error = 0;
- uint32_t lgenval, newval;
#if __DARWIN_UNIX03
pthread_t self = pthread_self();
#endif /* __DARWIN_UNIX03 */
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+ uint64_t oldval64, newval64;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t myid = 0;
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
+ LOCK(rwlock->lock);
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
return(error);
}
- } else {
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
+ UNLOCK(rwlock->lock);
}
-
+
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
- lgenval = PTHRW_RW_INIT;
- newval = PTHRW_RW_INIT | PTHRW_INC | PTHRW_EBIT;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
-#if __DARWIN_UNIX03
- rwlock->rw_owner = self;
-#endif /* __DARWIN_UNIX03 */
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
- return(0);
- }
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EBUSY);
- return(EBUSY);
-}
+loop:
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
-int
-_new_pthread_rwlock_wrlock(pthread_rwlock_t * orwlock)
-{
- uint32_t lgenval, newval, ugenval, updateval, rw_wc;
- int error = 0;
-#if __DARWIN_UNIX03
- pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lgenval, ugenval, rw_wc, 0);
-#endif
#if __DARWIN_UNIX03
- if (is_rw_ebit_set(lgenval)) {
- if(rwlock->rw_owner == self) {
+ if (is_rwl_ebit_set(lcntval)) {
+ if (rwlock->rw_owner == self) {
error = EDEADLK;
goto out;
}
}
#endif /* __DARWIN_UNIX03 */
- if (lgenval == PTHRW_RW_INIT) {
- newval = ( PTHRW_RW_INIT | PTHRW_INC | PTHRW_EBIT);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
+ if (lcntval == PTHRW_RWL_INIT) {
+ /* if we can acquire set L and S word */
+ lcntval = PTHRW_RWL_INIT;
+ newval = PTHRW_RWL_INIT | PTHRW_INC | PTH_RWL_KBIT| PTH_RWL_EBIT;
+ newsval = rw_seq + PTHRW_INC;
+
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) == TRUE) {
goto gotit;
- }
+ } else
+ goto loop;
}
- newval = (lgenval + PTHRW_INC) | PTHRW_WBIT | PTHRW_SHADOW_W;
+ newval = (lcntval + PTHRW_INC)| PTH_RWL_YBIT;
+
+ newsval = rw_seq;
+ if (is_rws_setseq(rw_seq)) {
+ newsval &= PTHRW_SW_Reset_BIT_MASK;
+ newsval |= (newval & PTHRW_COUNT_MASK);
+ }
- /* update lock seq and block in kernel */
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
+ newval64 = (((uint64_t)(newsval)) << 32);
newval64 |= newval;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lgenval, newval, 0);
-#endif
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
goto loop;
-
-retry:
+
PLOCKSTAT_RW_BLOCK(orwlock, WRITE_LOCK_PLOCKSTAT);
-retry1:
- updateval = __psynch_rw_wrlock(orwlock, newval, ugenval, (rw_wc+1), rwlock->rw_flags);
+retry:
+ updateval = __psynch_rw_yieldwrlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
if (updateval == (uint32_t)-1) {
error = errno;
} else
error = 0;
- if (error == EINTR) {
- goto retry1;
- }
+ if (error == EINTR)
+ goto retry;
+
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x33333333, newval, updateval, 0);
-#endif
PLOCKSTAT_RW_BLOCKED(orwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
if (error != 0) {
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- goto out;
- }
-
- if (is_rw_ebit_clear(updateval)) {
- /* kernel cannot wakeup without granting E bit */
- abort();
+#if _KSYN_TRACE_
+ set_enable(2);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("yieldwrlock from kernel with unknown error %x: tid %x\n", updateval, (uint32_t)myid);
}
- error = rwlock_exclusive_lockreturn(orwlock, updateval);
- if (error == EAGAIN)
- goto retry;
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
+out:
if (error == 0) {
gotit:
+ rwlock_action_onreturn(orwlock, updateval);
+ if ( is_rwl_ebit_clear(updateval)) {
+#if _KSYN_TRACE_
+ set_enable(2);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("yieldwrlock from kernel without EBit %x: tid %x\n", updateval, (uint32_t)myid);
+ }
#if __DARWIN_UNIX03
rwlock->rw_owner = self;
#endif /* __DARWIN_UNIX03 */
PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
return(0);
- }
-out:
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(error);
+ } else {
+ PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
+ return(error);
+ }
}
-
-
-#ifdef NOTYET
-/*****************************************************************************/
int
-_new_pthread_rwlock_yieldwrlock_np(pthread_rwlock_t * orwlock)
+pthread_rwlock_downgrade_np(pthread_rwlock_t * orwlock)
{
- uint32_t lgenval, newval, ugenval, updateval, rw_wc;
- int error = 0;
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
+ int error = 0, haswbit = 0, hasubit = 0, hasybit = 0;
#if __DARWIN_UNIX03
pthread_t self = pthread_self();
#endif /* __DARWIN_UNIX03 */
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t myid = 0;
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
+ LOCK(rwlock->lock);
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
return(error);
}
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
+ UNLOCK(rwlock->lock);
}
-
-
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
+ }
+
+loop:
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
+
+
+ /* if not holding exclusive lock, return */
+ if ((is_rwl_ebit_set(lcntval )== 0) || (rwlock->rw_owner != self)) {
+ return(EINVAL);
}
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
+ /* no other waiters and be granted in user space? ? */
+ if ((lcntval & PTHRW_COUNT_MASK) == (ucntval + PTHRW_INC)) {
+#if 0
+ /* should have no write waiters pending */
+ if (is_rwl_wbit_set(lcntval) != 0) {
+#if _KSYN_TRACE_
+ set_enable(2);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("downgrade in user mode but W bit set %x: tid %x\n", lcntval, (uint32_t)myid);
+ }
+#endif
+ /* preserve count and remove ke bits */
+ newval = lcntval & ~(PTH_RWL_EBIT | PTH_RWL_KBIT);
+ /* if we can acquire set L and S word */
+ newsval = rw_seq;
+
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) == TRUE) {
#if __DARWIN_UNIX03
- if (is_rw_ebit_set(lgenval)) {
- if (rwlock->rw_owner == self) {
- error = EDEADLK;
- goto out;
+ rwlock->rw_owner = (pthread_t)0;
+#endif /* __DARWIN_UNIX03 */
+ return(0);
+ } else
+ goto loop;
+ } else {
+
+ haswbit = lcntval & PTH_RWL_WBIT;
+ hasubit = lcntval & PTH_RWL_UBIT;
+ hasybit = lcntval & PTH_RWL_YBIT;
+
+ /* reset all bits and set k */
+ newval = (lcntval & PTHRW_COUNT_MASK) | PTH_RWL_KBIT;
+ /* set I bit on S word */
+ newsval = rw_seq | PTH_RWS_IBIT;
+ if (haswbit != 0)
+ newsval |= PTH_RWS_WSVBIT;
+ if (hasubit != 0)
+ newsval |= PTH_RWS_USVBIT;
+ if (hasybit != 0)
+ newsval |= PTH_RWS_YSVBIT;
+
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
+
+#if __DARWIN_UNIX03
+ rwlock->rw_owner = 0;
+#endif /* __DARWIN_UNIX03 */
+
+retry:
+ updateval = __psynch_rw_downgrade(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
+ if (updateval == (uint32_t)-1) {
+ error = errno;
+ } else
+ error = 0;
+
+ /* TBD: what to do with the error, EINTR ?? */
+ if (error == EINTR)
+ goto retry;
+
+ if (error == 0) {
+ rwlock_action_onreturn(orwlock, updateval);
+ return(0);
+ } else {
+#if _KSYN_TRACE_
+ set_enable(1);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("downgrade from kernel with unknown error %x with tid %x\n", updateval, (uint32_t)myid);
}
+ /* Not reached */
}
+ return(EINVAL);
+}
+
+int
+pthread_rwlock_upgrade_np(pthread_rwlock_t * orwlock)
+{
+ return(pthread_rwlock_upgrade_internal(orwlock, 0));
+}
+
+int
+pthread_rwlock_tryupgrade_np(pthread_rwlock_t *orwlock)
+{
+ return(pthread_rwlock_upgrade_internal(orwlock, 1));
+}
+
+static int
+pthread_rwlock_upgrade_internal(pthread_rwlock_t * orwlock, int trylock)
+{
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
+ int error = 0, flags ;
+#if __DARWIN_UNIX03
+ pthread_t self = pthread_self();
#endif /* __DARWIN_UNIX03 */
+ npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+ uint64_t oldval64, newval64;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t myid = 0;
- if (lgenval == PTHRW_RW_INIT) {
- newval = PTHRW_RW_INIT | PTHRW_INC | PTHRW_EBIT;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- goto gotit;
+ if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+ /* check for static initialization */
+ LOCK(rwlock->lock);
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ return(error);
+ }
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ return(EINVAL);
}
+ UNLOCK(rwlock->lock);
+ }
+ if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+ } else {
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
+ }
+
+loop:
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
+
+ if (is_rwl_eubit_set(lcntval) !=0) {
+ return(EBUSY);
}
- newval = (lgenval + PTHRW_INC);
- if ((lgenval & PTHRW_WBIT) == 0)
- newval |= PTHRW_YBIT;
+ /* set U and K bit and go to kernel */
+ newval = (lcntval | (PTH_RWL_UBIT | PTH_RWL_KBIT));
+ newsval = rw_seq;
+#if 0
+ if (is_rws_setseq(rw_seq)) {
+ newsval &= PTHRW_SW_Reset_BIT_MASK;
+ newsval |= (newval & PTHRW_COUNT_MASK);
+ }
+#endif
+
+ /* update lock seq and block in kernel */
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
+ newval64 = (((uint64_t)(newsval)) << 32);
newval64 |= newval;
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- PLOCKSTAT_RW_BLOCK(orwlock, WRITE_LOCK_PLOCKSTAT);
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
+ flags = rwlock->rw_flags;
+ if (trylock != 0) {
+ flags |= _PTHREAD_RWLOCK_UPGRADE_TRY;
+ }
retry:
- updateval = __psynch_rw_yieldwrlock(orwlock, newval, ugenval, (rw_wc+1), rwlock->rw_flags);
+ updateval = __psynch_rw_upgrade(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
if (updateval == (uint32_t)-1) {
error = errno;
} else
error = 0;
-
+
if (error == EINTR)
goto retry;
-
-
- PLOCKSTAT_RW_BLOCKED(orwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
- if (error != 0) {
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- goto out;
- }
-
- if (is_rw_ebit_clear(updateval)) {
- /* kernel cannot wakeup without granting E bit */
- abort();
- }
-
- error = rwlock_exclusive_lockreturn(orwlock, updateval);
- if (error == EAGAIN)
- goto retry;
-
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
+
+
if (error == 0) {
- gotit:
+ rwlock_action_onreturn(orwlock, updateval);
+ if ( is_rwl_ebit_clear(updateval)) {
+#if _KSYN_TRACE_
+ set_enable(2);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("upgrade from kernel without EBit %x: tid %x\n", updateval, (uint32_t)myid);
+ }
#if __DARWIN_UNIX03
rwlock->rw_owner = self;
#endif /* __DARWIN_UNIX03 */
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
return(0);
} else {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
+ if (trylock != 0) {
+ return (EBUSY);
+ }
}
- return(error);
-out:
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
- return(error);
+
+ return(error);
}
-/**************************************************************/
-#endif /* NOTYET */
-int
-_new_pthread_rwlock_unlock(pthread_rwlock_t * orwlock)
+/* Returns true if the rwlock is held for reading by any thread or held for writing by the current thread */
+int
+pthread_rwlock_held_np(pthread_rwlock_t * orwlock)
{
- uint32_t lgenval, ugenval, rw_wc, newval, nlval, ulval;
+ uint32_t lcntval, ucntval, rw_seq;
int error = 0;
- int wrlock = 0, kern_trans;
- uint32_t updateval, bits, newbits;
- uint32_t isupgrade = 0;
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- int retry_count = 0, retry_count1 = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
- pthread_t self = NULL;
- uint64_t threadid = 0;
- int ubitchanged = 0, initbitset = 0, num;
-
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
+ LOCK(rwlock->lock);
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, wrlock, error);
- return(error);
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ return(0);
}
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, wrlock, EINVAL);
- return(EINVAL);
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ return(-1);
}
+ UNLOCK(rwlock->lock);
}
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
+
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
+ if ((lcntval & PTHRW_COUNT_MASK) == (ucntval & PTHRW_COUNT_MASK))
+ return(0);
+ return(1);
+}
-loop1:
- if ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK)) {
- retry_count++;
- sched_yield();
- if (retry_count < 1024)
- goto loop;
- error = EINVAL;
- goto out;
- }
- retry_count = 0;
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lgenval, ugenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, rw_wc, 0, 0);
-#endif
- if (is_rw_ebit_set(lgenval)) {
- wrlock = 1;
-#if __DARWIN_UNIX03
- rwlock->rw_owner = (pthread_t)0;
-#endif /* __DARWIN_UNIX03 */
- }
+/* Returns true if the rwlock is held for reading by any thread */
+int
+pthread_rwlock_rdheld_np(pthread_rwlock_t * orwlock)
+{
+ uint32_t lcntval, ucntval, rw_seq;
+ int error = 0;
+ npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
- /* last unlock ? */
- if((lgenval & PTHRW_COUNT_MASK) == (ugenval + PTHRW_INC)) {
- if (OSAtomicCompareAndSwap32(ugenval, 0, (volatile int32_t *)useqaddr) != TRUE) {
- goto loop;
- }
- if (OSAtomicCompareAndSwap32(lgenval, PTHRW_RW_INIT, (volatile int32_t *)lseqaddr) != TRUE) {
- if (OSAtomicCompareAndSwap32(0, ugenval, (volatile int32_t *)useqaddr) != TRUE) {
-lp1:
- ulval = *useqaddr;
- nlval = ugenval+ulval;
- if (OSAtomicCompareAndSwap32(ulval, nlval, (volatile int32_t *)useqaddr) != TRUE)
- goto lp1;
+ if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+ LOCK(rwlock->lock);
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ return(0);
}
-
- goto loop;
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ return(-1);
}
-
- goto succout;
- }
-
- /* do we need kernel trans? */
-
-lp11:
- nlval = lgenval & PTHRW_COUNT_MASK;
- if (ubitchanged == 0)
- ulval = (ugenval + PTHRW_INC) & PTHRW_COUNT_MASK;
- else
- ulval = ugenval & PTHRW_COUNT_MASK;
-
- num = rw_diffgenseq(nlval, ulval);
- kern_trans = ( num == (rw_wc << PTHRW_COUNT_SHIFT));
- /* if three more waiters than needed for kernel tras*/
- if ((ubitchanged ==0) && (kern_trans == 0) && (num < (rw_wc << PTHRW_COUNT_SHIFT))) {
- retry_count1++;
- sched_yield();
- if (retry_count1 < 1024)
- goto loop;
- }
- retry_count1 = 0;
-
- if (ubitchanged == 0) {
- if (OSAtomicCompareAndSwap32(ugenval, ugenval+PTHRW_INC, (volatile int32_t *)useqaddr) != TRUE)
- goto loop;
- ubitchanged = 1;
+ UNLOCK(rwlock->lock);
}
- if (kern_trans == 0) {
- goto succout;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 1, ugenval+PTHRW_INC, 0);
-#endif
- initbitset = 0;
- bits = lgenval & PTHRW_BIT_MASK;
- newbits = bits;
- /* if this is first unlock to kernel, notify kernel of init status */
- if ((bits & PTHRW_RW_INIT) != 0) {
- /* reset the initbit if present */
- newbits &= ~PTHRW_RW_INIT;
- initbitset = PTHRW_RW_INIT;
- }
- if (((bits & PTHRW_EBIT) != 0) && ((bits & PTHRW_WBIT) == 0)) {
- /* reset E bit is no U bit is set */
- newbits &= ~PTHRW_EBIT;
- }
- /* clear shadow bit, as W is going to be sent to kernel */
- if ((bits & PTHRW_WBIT) != 0) {
- newbits &= ~PTHRW_SHADOW_W;
- }
-
- /* reset L bit */
- if (bits & PTHRW_LBIT)
- newbits &= ~PTHRW_LBIT;
- if (bits & PTHRW_UBIT) {
- /* reset U and set E bit */
- newbits &= ~PTHRW_LBIT;
- newbits |= PTHRW_EBIT;
- isupgrade = PTHRW_UBIT;
- }
-
- /* updates bits on the L */
- newval = (lgenval & PTHRW_COUNT_MASK) | newbits;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE) {
- /* reread the value */
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
- /* since lgen changed check for trans again */
- goto lp11;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 2, newval, 0);
-#endif
-
- /* send upgrade bit to kernel */
- newval |= (isupgrade | initbitset);
- updateval = __psynch_rw_unlock(orwlock, newval, ugenval+PTHRW_INC, rw_wc, rwlock->rw_flags);
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if(error != 0) {
- /* not sure what is the scenario */
- if(error != EINTR)
- goto out;
- }
-
- /*
- * If the unlock is spurious return. Also if the
- * exclusive lock is being granted, let that thread
- * manage the status bits, otherwise stale bits exclusive
- * bit can be set, if that thread had already unlocked.
- */
- if ((updateval & (PTHRW_RW_SPURIOUS | PTHRW_EBIT)) != 0) {
- goto succout;
+ if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+ } else {
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
-lp2:
- lgenval = *lseqaddr;
-
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 3, lgenval, 0);
-#endif
- /* if the kernel antcipated seq and one on the lock are same, set the one from kernel */
- if ((lgenval & PTHRW_COUNT_MASK) == (updateval & PTHRW_COUNT_MASK)) {
- if (OSAtomicCompareAndSwap32(lgenval, updateval, (volatile int32_t *)lseqaddr) != TRUE)
- goto lp2;
- goto succout;
- }
-
- /* state bits are same? */
- if ((lgenval & PTHRW_BIT_MASK) == (updateval & PTHRW_BIT_MASK)) {
- /* nothing to do */
- goto succout;
+ if ((lcntval & PTHRW_COUNT_MASK) == (ucntval & PTHRW_COUNT_MASK))
+ return(0);
+
+ if (is_rwl_ebit_set(lcntval) !=0) {
+ return(0);
}
-
- newval = ((lgenval & PTHRW_UN_BIT_MASK) << PTHRW_COUNT_SHIFT) | (updateval & PTHRW_BIT_MASK);
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 4, newval, 0);
-#endif
- /* high bits are state on the lock; lowbits are one kernel need to set */
- switch (newval) {
- /* W States */
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
-
- /* L states */
- case ((PTHRW_LBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* Y states */
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* YU states */
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* E states */
- case ((PTHRW_EBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WE states */
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WL states */
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- default:
- /* illegal states */
- self = pthread_self();
- threadid = self->thread_id;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 6, lgenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 7, updateval, 0);
-#endif
- LIBC_ABORT("incorect state on return 0x%x: lgenval 0x%x, updateval 0x%x; threadid (0x%x)\n", newval, lgenval, updateval, (uint32_t)threadid);
-
- };
-
- if (error != 0)
- goto lp2;
-succout:
- PLOCKSTAT_RW_RELEASE(orwlock, wrlock);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(0);
-out:
- PLOCKSTAT_RW_ERROR(orwlock, wrlock, error);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(error);
+ return(1);
}
-#ifdef NOTYET
-/*****************************************************************************/
-int
-_new_pthread_rwlock_downgrade_np(pthread_rwlock_t * orwlock)
+/* Returns true if the rwlock is held for writing by the current thread */
+int
+pthread_rwlock_wrheld_np(pthread_rwlock_t * orwlock)
{
- uint32_t lgenval, newval, ugenval, rw_wc;
- int error = 0;
+ uint32_t lcntval, ucntval, rw_seq;
pthread_t self = pthread_self();
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ int error = 0;
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
+ LOCK(rwlock->lock);
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(error);
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ return(0);
}
- } else {
- return(EINVAL);
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ return(-1);
}
+ UNLOCK(rwlock->lock);
}
+
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
-
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
- if ((is_rw_ebit_set(lgenval )) && (rwlock->rw_owner != self)) {
- return(EINVAL);
+
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
+
+ if ((is_rwl_ebit_set(lcntval)) && (rwlock->rw_owner == self)) {
+ return(1);
}
-
- if ((lgenval & PTHRW_COUNT_MASK) != ugenval) {
-
- newval = lgenval & ~PTHRW_EBIT;
-
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
+ return(0);
+}
+/******************************************************/
+#endif /* NOTYET */
+
+
+#endif /* !BUILDING_VARIANT ] */
+
+int
+pthread_rwlock_destroy(pthread_rwlock_t *orwlock)
+{
+ npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
#if __DARWIN_UNIX03
- rwlock->rw_owner = 0;
+ uint32_t rw_lcnt, rw_ucnt;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
#endif /* __DARWIN_UNIX03 */
- if (rw_wc != 0) {
- error = __psynch_rw_downgrade(orwlock, newval, ugenval, rw_wc, rwlock->rw_flags);
-
- }
- return(0);
+
+ if (rwlock->sig != _PTHREAD_RWLOCK_SIG && rwlock->sig != _PTHREAD_RWLOCK_SIG_init)
+ return(EINVAL);
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG) {
+#if __DARWIN_UNIX03
+ if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- goto loop;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
- }
- return(EINVAL);
+
+ rw_lcnt = *lcntaddr;
+ rw_ucnt = *ucntaddr;
+
+ if((rw_lcnt & PTHRW_COUNT_MASK) != rw_ucnt)
+ return(EBUSY);
+
+#endif /* __DARWIN_UNIX03 */
+ //bzero(rwlock, sizeof(npthread_rwlock_t));
+ rwlock->sig = _PTHREAD_NO_SIG;
+ return(0);
+ } else if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+ rwlock->sig = _PTHREAD_NO_SIG;
+ return(0);
+ } else
+ return(EINVAL);
}
int
-_new_pthread_rwlock_upgrade_np(pthread_rwlock_t * orwlock)
+pthread_rwlock_init(pthread_rwlock_t * orwlock, const pthread_rwlockattr_t *attr)
{
- uint32_t lgenval, newval, ugenval, ulval, updateval, rw_wc;
- int error = 0, kern_trans;
- pthread_t self = pthread_self();
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(error);
- }
- } else {
- return(EINVAL);
- }
- }
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
+#if __DARWIN_UNIX03
+ uint32_t rw_lcnt, rw_ucnt;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+#endif /* __DARWIN_UNIX03 */
- if (is_rw_uebit_set(lgenval)) {
+#if __DARWIN_UNIX03
+ if (attr && (attr->sig != _PTHREAD_RWLOCK_ATTR_SIG)) {
return(EINVAL);
-
}
- if ((lgenval & PTHRW_COUNT_MASK) == ugenval)
- return(EINVAL);
-
- if (lgenval > ugenval)
- ulval = (lgenval & PTHRW_COUNT_MASK) - (ugenval & PTHRW_COUNT_MASK);
- else
- ulval = (ugenval & PTHRW_COUNT_MASK) - (lgenval & PTHRW_COUNT_MASK);
-
-
- newval = lgenval | PTHRW_UBIT;
-
- kern_trans = 1;
- if (rw_wc != 0) {
- if (ulval == ((rw_wc - 1) << PTHRW_COUNT_SHIFT))
- kern_trans = 0;
- } else if (ulval == 1)
- kern_trans = 0;
-
- if (kern_trans == 0) {
- newval = ((lgenval | PTHRW_EBIT) & ~PTHRW_LBIT);
- } else {
- newval = lgenval | PTHRW_UBIT;
- }
- if (kern_trans == 0) {
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- goto loop;
-
- } else {
- newval = (lgenval + PTHRW_INC);
-
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
-
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
- newval64 |= newval;
-
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- goto loop;
- /* kern_trans == 1 */
- retry:
- updateval = __psynch_rw_upgrade(orwlock, newval, ugenval, rw_wc+1, rwlock->rw_flags);
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if (error == EINTR)
- goto retry;
-
- if (error != 0) {
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- goto out;
- }
-
- if (is_rw_ebit_set(updateval)) {
- /* kernel cannot wakeup without granting E bit */
- abort();
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG) {
+ if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+ } else {
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
- error = rwlock_exclusive_lockreturn(orwlock, updateval);
- if (error == EAGAIN)
- goto retry;
+ rw_lcnt = *lcntaddr;
+ rw_ucnt = *ucntaddr;
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
+ if ((rw_lcnt & PTHRW_COUNT_MASK) != rw_ucnt)
+ return(EBUSY);
}
- if (error == 0) {
- rwlock->rw_owner = self;
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
- return(0);
- }
+#endif
+ LOCK_INIT(rwlock->lock);
+ return(__pthread_rwlock_init(orwlock, attr));
-out:
- return(error);
}
int
-pthread_rwlock_tryupgrade_np(pthread_rwlock_t *orwlock)
+pthread_rwlock_rdlock(pthread_rwlock_t * orwlock)
{
- pthread_t self = pthread_self();
- uint32_t lgenval, newval, ugenval, ulval, rw_wc;
- int error = 0, kern_trans;
+#if __DARWIN_UNIX03
+ pthread_t self;
+#endif /* __DARWIN_UNIX03 */
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
+ int error = 0, retry_count = 0;
+ uint64_t oldval64, newval64;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t myid = 0;
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+ LOCK(rwlock->lock);
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
return(error);
}
- } else {
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
+ UNLOCK(rwlock->lock);
}
+
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
+#endif
loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lcntval, (ucntval | 0xee), rw_seq, 0);
+#endif
- if (is_rw_uebit_set(lgenval)) {
- return(EBUSY);
+ /* if l bit is on or u and k bit is clear, acquire lock in userland */
+ if (can_rwl_readinuser(lcntval))
+ goto gotlock;
+
+#if __DARWIN_UNIX03
+ if (is_rwl_ebit_set(lcntval)) {
+ self = pthread_self();
+ if(rwlock->rw_owner == self) {
+ error = EDEADLK;
+ goto out;
+ }
}
+#endif /* __DARWIN_UNIX03 */
- if ((lgenval & PTHRW_COUNT_MASK) == ugenval)
- return(EINVAL);
+
+ /* Need to block in kernel , remove Rbit */
+ newval = (lcntval + PTHRW_INC) & PTH_RWLOCK_RESET_RBIT;
- if (lgenval > ugenval)
- ulval = (lgenval & PTHRW_COUNT_MASK) - (ugenval & PTHRW_COUNT_MASK);
- else
- ulval = (ugenval & PTHRW_COUNT_MASK) - (lgenval & PTHRW_COUNT_MASK);
+ newsval = rw_seq;
+ if (is_rws_setseq(rw_seq)) {
+ newsval &= PTHRW_SW_Reset_BIT_MASK;
+ newsval |= (newval & PTHRW_COUNT_MASK);
+ }
+
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
- newval = lgenval | PTHRW_UBIT;
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
+
+ /* give writers priority over readers */
+ PLOCKSTAT_RW_BLOCK(orwlock, READ_LOCK_PLOCKSTAT);
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lcntval, newval, newsval, 0);
+#endif
+
+retry:
+ updateval = __psynch_rw_rdlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
- kern_trans = 1;
- if (rw_wc != 0) {
- /* there is only one reader thread */
- if (ulval == (rw_wc - 1))
- kern_trans = 0;
- } else if (ulval == 1)
- kern_trans = 0;
+ if (updateval == (uint32_t)-1) {
+ error = errno;
+ } else
+ error = 0;
- if (kern_trans == 0) {
- newval = (lgenval | PTHRW_EBIT) & ~PTHRW_LBIT;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- goto loop;
-
- rwlock->rw_owner = self;
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
- return(0);
- }
- return(EBUSY);
-}
+ if (error == EINTR)
+ goto retry;
-/* Returns true if the rwlock is held for reading by any thread or held for writing by the current thread */
-int
-pthread_rwlock_held_np(pthread_rwlock_t * orwlock)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval, ugenval;
- int error = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(0);
- }
- } else {
- return(-1);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
-
- if ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK))
+ if (error == 0) {
+ rwlock_action_onreturn(orwlock, updateval);
+ PLOCKSTAT_RW_BLOCKED(orwlock, READ_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
+ PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
return(0);
-
- return(1);
-}
-
-/* Returns true if the rwlock is held for reading by any thread */
-int
-pthread_rwlock_rdheld_np(pthread_rwlock_t * orwlock)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval;
- int error = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(0);
- }
- } else {
- return(-1);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = *lseqaddr;
-
- if (is_rw_ebit_set(lgenval)) {
- return(0);
+ PLOCKSTAT_RW_BLOCKED(orwlock, READ_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT);
+#if _KSYN_TRACE_
+ set_enable(1);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("rdlock from kernel with unknown error %x with tid %x\n", updateval, (uint32_t)myid);
+ goto out;
}
- return(0);
-}
-
-/* Returns true if the rwlock is held for writing by the current thread */
-int
-pthread_rwlock_wrheld_np(pthread_rwlock_t * orwlock)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- pthread_t self;
- uint32_t lgenval;
- int error = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+ /* Not reached */
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(0);
- }
+gotlock:
+ if (rw_diffgenseq(lcntval, ucntval) >= PTHRW_MAX_READERS) {
+ /* since ucntval may be newer, just redo */
+ retry_count++;
+ if (retry_count > 1024) {
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TOOMANY | DBG_FUNC_NONE, (uint32_t)rwlock, 0XEEEEEEEE, lcntval, ucntval, 0);
+#endif
+ error = EAGAIN;
+ goto out;
} else {
- return(-1);
+ sched_yield();
+ goto loop;
}
}
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- self = pthread_self();
-
- lgenval = *lseqaddr;
- if ((is_rw_ebit_set(lgenval)) && (rwlock->rw_owner == self)) {
- return(1);
- }
- return(0);
-}
-/**************************************************************/
-#endif /* NOTYET */
-
-static int
-rwlock_unlock_action_onread(pthread_rwlock_t * orwlock, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- int error = 0;
- uint32_t lgenval, newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
- pthread_t self;
- uint64_t threadid;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = *lseqaddr;
+ /* Need to update L (remove R bit) and S word */
+ newval = (lcntval + PTHRW_INC) & PTH_RWLOCK_RESET_RBIT;
+ newsval = (rw_seq + PTHRW_INC);
-lp2:
- lgenval = *lseqaddr;
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 3, lgenval, 0);
-#endif
- /* if the kernel antcipated seq and one on the lock are same, set the one from kernel */
- if ((lgenval & PTHRW_COUNT_MASK) == (updateval & PTHRW_COUNT_MASK)) {
- if (OSAtomicCompareAndSwap32(lgenval, updateval, (volatile int32_t *)lseqaddr) != TRUE)
- goto lp2;
- goto succout;
- }
-
- /* state bits are same? */
- if ((lgenval & PTHRW_BIT_MASK) == (updateval & PTHRW_BIT_MASK)) {
- /* nothing to do */
- goto succout;
- }
-
- newval = ((lgenval & PTHRW_UN_BIT_MASK) << PTHRW_COUNT_SHIFT) | (updateval & PTHRW_BIT_MASK);
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 4, newval, 0);
-#endif
- /* high bits are state on the lock; lowbits are one kernel need to set */
- switch (newval) {
- /* W States */
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
-
- /* L states */
- case ((PTHRW_LBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* Y states */
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* YU states */
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* E states */
- case ((PTHRW_EBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WE states */
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WL states */
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- default:
- /* illegal states */
- self = pthread_self();
- threadid = self->thread_id;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 6, lgenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 7, updateval, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lcntval, newval, 0);
#endif
- LIBC_ABORT("incorect state on return 0x%x: lgenval 0x%x, updateval 0x%x; threadid (0x%x)\n", newval, lgenval, updateval, (uint32_t)threadid);
- };
-
- if (error != 0)
- goto lp2;
-succout:
+ PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, lgenval, newval, 0, 0, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, 0, 0, 0);
#endif
return(0);
-}
-
-
-static uint32_t
-modbits(uint32_t lgenval, uint32_t updateval)
-{
- uint32_t lval = lgenval & PTHRW_BIT_MASK;
- uint32_t uval = updateval & PTHRW_BIT_MASK;
- uint32_t rval, nlval;
-
- nlval = (lval | uval);
- if ((uval & PTHRW_EBIT) == 0)
- nlval &= ~PTHRW_EBIT;
- if ((nlval & (PTHRW_WBIT | PTHRW_YBIT)) == (PTHRW_WBIT | PTHRW_YBIT))
- nlval &= ~PTHRW_YBIT;
- /* no new writers and kernel resets w bit, reset W bit on the lock */
- if (((nlval & (PTHRW_WBIT | PTHRW_SHADOW_W)) == PTHRW_WBIT) && ((updateval & PTHRW_WBIT) == 0))
- nlval &= ~PTHRW_WBIT;
-
- rval = (lgenval & PTHRW_COUNT_MASK) | nlval;
- return(rval);
-}
-
-static int
-rwlock_unlock_action1(pthread_rwlock_t * orwlock, uint32_t lgenval, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- int error = 0;
- uint32_t newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- newval = modbits(lgenval, updateval);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- error = EINVAL;
+out:
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, lgenval, newval, 0, 0, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
#endif
return(error);
}
-static int
-rwlock_unlock_action2(pthread_rwlock_t * orwlock, uint32_t lgenval, uint32_t updateval)
+int
+pthread_rwlock_tryrdlock(pthread_rwlock_t * orwlock)
{
npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval;
+ int error = 0, retry_count = 0;
+ uint64_t oldval64, newval64;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- newval = modbits(lgenval, updateval);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- /* roundtrip kernel */
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT2 | DBG_FUNC_NONE, lgenval, newval, 0, 0, 0);
-#endif
- (void) __psynch_rw_unlock2(orwlock, lgenval, *useqaddr, *wcaddr, rwlock->rw_flags);
- return(0);
+ if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+ LOCK(rwlock->lock);
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
+ return(error);
+ }
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
+ return(EINVAL);
+ }
+ UNLOCK(rwlock->lock);
}
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT2 | DBG_FUNC_NONE, 0xffffffff, 0, 0, 0, 0);
-#endif
-
- return(EINVAL);
-}
-
-/* This is used when an exclusive write lock of any kind is being granted. For unlock thread, it needs to try to set the bit, if not move on */
-static int
-rwlock_unlock_action_k(pthread_rwlock_t * orwlock, uint32_t lgenval, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
} else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
- newval = modbits(lgenval, updateval);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTK | DBG_FUNC_NONE, lgenval, updateval, newval, 0, 0);
-#endif
- /* try to set, if not not a prolem as the thread taking exclusive will take care of the discrepency */
-
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTK | DBG_FUNC_NONE, 0x55555555, lgenval, newval, 0, 0);
-#endif
-
- } else {
+loop:
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTK | DBG_FUNC_NONE, 0xAAAAAAAA, lgenval, newval, 0, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TRYRDLOCK | DBG_FUNC_START, (uint32_t)rwlock, lcntval, ucntval, rw_seq, 0);
#endif
- }
-
- return(0);
-}
-
-static int
-rwlock_exclusive_lockreturn(pthread_rwlock_t * orwlock, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval, newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
- pthread_t self;
- uint64_t threadid;
-
- int error = 0;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-lp2:
- lgenval = *lseqaddr;
-
- /* if the kernel antcipated seq and one on the lock are same, set the one from kernel */
- if ((lgenval & PTHRW_COUNT_MASK) == (updateval & PTHRW_COUNT_MASK)) {
- if (OSAtomicCompareAndSwap32(lgenval, updateval, (volatile int32_t *)lseqaddr) != TRUE)
- goto lp2;
- goto out;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, lgenval, updateval, 1, 0, 0);
-#endif
- /* state bits are same? */
- if ((lgenval & PTHRW_BIT_MASK) == (updateval & PTHRW_BIT_MASK)) {
- /* nothing to do */
- goto out;
- }
-
+ /* if l bit is on or u and k bit is clear, acquire lock in userland */
+ if (can_rwl_readinuser(lcntval))
+ goto gotlock;
- newval = ((lgenval & PTHRW_UN_BIT_MASK) << PTHRW_COUNT_SHIFT) | (updateval & PTHRW_BIT_MASK);
+ error = EBUSY;
+ goto out;
+gotlock:
+ if (rw_diffgenseq(lcntval, ucntval) >= PTHRW_MAX_READERS) {
+ /* since ucntval may be newer, just redo */
+ retry_count++;
+ if (retry_count > 1024) {
+
#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, newval, 0, 2, 0, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TOOMANY | DBG_FUNC_NONE, (uint32_t)rwlock, 0XEEEEEEEE, lcntval, ucntval, 0);
#endif
- /* high bits are state on the lock; lowbits are one kernel need to set */
- switch (newval) {
- /* W States */
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
error = EAGAIN;
- }
- break;
-
-
- /* All L states illegal here */
-
- /* Y states */
- case (PTHRW_YBIT << PTHRW_COUNT_SHIFT) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
-
- /* YU states */
- case ((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
-
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
-
- /* E states */
- case ((PTHRW_EBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WE states */
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* All WL states are illegal*/
-
- default:
- /* illegal states */
- self = pthread_self();
- threadid = self->thread_id;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 6, lgenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 7, updateval, 0);
-#endif
- LIBC_ABORT("rwlock_exclusive_lockreturn: incorect state on return 0x%x: lgenval 0x%x, updateval 0x%x; threadid (0x%x)\n", newval, lgenval, updateval, (uint32_t)threadid);
- };
-
- if (error == EINVAL)
- goto lp2;
-out:
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, error, 0, 0xffffffff, 0, 0);
-#endif
- return(error);
-}
-
-/* returns are not bit shifted */
-static int
-rw_diffgenseq(uint32_t x, uint32_t y)
-{
- uint32_t lx = (x & PTHRW_COUNT_MASK);
- uint32_t ly = (y &PTHRW_COUNT_MASK);
-
- if (lx > ly) {
- return(lx-ly);
- } else {
- return((PTHRW_MAX_READERS - y) + lx + PTHRW_INC);
- }
-
-}
-
-#endif /* i386 || x86_64 ] */
-
-
-#endif /* !BUILDING_VARIANT ] */
-
-int
-pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
-{
-#if defined(__i386__) || defined(__x86_64__) || defined(__DARWIN_UNIX03)
- int ret;
-#endif /* __i386__ || __x86_64__ */
-
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_destroy(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- return(EINVAL);
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_destroy(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
- else {
-#if __DARWIN_UNIX03
- /* grab the monitor lock */
- if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0)
- return(ret);
-
- if (rwlock->state != 0) {
- pthread_mutex_unlock(&rwlock->lock);
- return(EBUSY);
- }
- pthread_mutex_unlock(&rwlock->lock);
-#endif /* __DARWIN_UNIX03 */
-
- pthread_mutex_destroy(&rwlock->lock);
- pthread_cond_destroy(&rwlock->read_signal);
- pthread_cond_destroy(&rwlock->write_signal);
- rwlock->sig = _PTHREAD_NO_SIG;
- return(0);
- }
-}
-
-int
-pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
-{
- int ret;
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_init(rwlock, attr));
- }
-#endif /* __i386__ || __x86_64__ */
-
-#if __DARWIN_UNIX03
- if (attr && (attr->sig != _PTHREAD_RWLOCK_ATTR_SIG)) {
- return(EINVAL);
- }
-#endif /* __DARWIN_UNIX03 */
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((attr != NULL) && (attr->pshared == PTHREAD_PROCESS_SHARED)) {
- ret = _new_pthread_rwlock_init(rwlock, attr);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
-
-#if __DARWIN_UNIX03
- /* if already inited check whether it is in use, then return EBUSY */
- if ((rwlock->sig == _PTHREAD_RWLOCK_SIG) && (rwlock->state !=0 )) {
- return(EBUSY);
- }
-#endif /* __DARWIN_UNIX03 */
-
- /* initialize the lock */
- if ((ret = pthread_mutex_init(&rwlock->lock, NULL)) != 0)
- return(ret);
- else {
- /* initialize the read condition signal */
- ret = pthread_cond_init(&rwlock->read_signal, NULL);
-
- if (ret != 0) {
- pthread_mutex_destroy(&rwlock->lock);
- return(ret);
+ goto out;
} else {
- /* initialize the write condition signal */
- ret = pthread_cond_init(&rwlock->write_signal, NULL);
-
- if (ret != 0) {
- pthread_cond_destroy(&rwlock->read_signal);
- pthread_mutex_destroy(&rwlock->lock);
- return(ret);
- } else {
- /* success */
- rwlock->state = 0;
- rwlock->owner = (pthread_t)0;
- rwlock->blocked_writers = 0;
- if (attr)
- rwlock->pshared = attr->pshared;
- else
- rwlock->pshared = _PTHREAD_DEFAULT_PSHARED;
-
- rwlock->sig = _PTHREAD_RWLOCK_SIG;
- return(0);
- }
- }
- }
-}
-
-int
-pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
-{
- int ret;
-#if __DARWIN_UNIX03
- pthread_t self = pthread_self();
-#endif
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_rdlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- return(ret);
- }
- }
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_rdlock(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
- /* grab the monitor lock */
- if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- return(ret);
- }
-
-#if __DARWIN_UNIX03
- if ((rwlock->state < 0) && (rwlock->owner == self)) {
- pthread_mutex_unlock(&rwlock->lock);
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EDEADLK);
- return(EDEADLK);
- }
-#endif /* __DARWIN_UNIX03 */
-
-#if __DARWIN_UNIX03
- while (rwlock->blocked_writers || ((rwlock->state < 0) && (rwlock->owner != self)))
-#else /* __DARWIN_UNIX03 */
- while (rwlock->blocked_writers || rwlock->state < 0)
-
-#endif /* __DARWIN_UNIX03 */
- {
- /* give writers priority over readers */
- PLOCKSTAT_RW_BLOCK(rwlock, READ_LOCK_PLOCKSTAT);
- ret = pthread_cond_wait(&rwlock->read_signal, &rwlock->lock);
-
- if (ret != 0) {
- /* can't do a whole lot if this fails */
- pthread_mutex_unlock(&rwlock->lock);
- PLOCKSTAT_RW_BLOCKED(rwlock, READ_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT);
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- return(ret);
+ sched_yield();
+ goto loop;
}
-
- PLOCKSTAT_RW_BLOCKED(rwlock, READ_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
}
+
+ /* Need to update L(remove Rbit ) and S word */
+ newval = (lcntval + PTHRW_INC) & PTH_RWLOCK_RESET_RBIT;
+ newsval = (rw_seq + PTHRW_INC);
- /* check lock count */
- if (rwlock->state == MAX_READ_LOCKS) {
- ret = EAGAIN;
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- }
- else {
- ++rwlock->state; /* indicate we are locked for reading */
- PLOCKSTAT_RW_ACQUIRE(rwlock, READ_LOCK_PLOCKSTAT);
- }
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
- /*
- * Something is really wrong if this call fails. Returning
- * error won't do because we've already obtained the read
- * lock. Decrementing 'state' is no good because we probably
- * don't have the monitor lock.
- */
- pthread_mutex_unlock(&rwlock->lock);
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TRYRDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lcntval, newval, 0);
+#endif
+
+ PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
+ return(0);
- return(ret);
+out:
+ PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TRYRDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, error, 0, 0);
+#endif
+ return(error);
}
int
-pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
+pthread_rwlock_trywrlock(pthread_rwlock_t * orwlock)
{
- int ret;
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_tryrdlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- return(ret);
- }
- }
-
+#if __DARWIN_UNIX03
+ pthread_t self = pthread_self();
+#endif /* __DARWIN_UNIX03 */
+ npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+ uint32_t lcntval, rw_seq, newval, newsval;
+ int error = 0, gotlock = 0;
+ uint64_t oldval64, newval64;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
+ LOCK(rwlock->lock);
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
+ return(error);
+ }
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
+ return(EINVAL);
+ }
+ UNLOCK(rwlock->lock);
}
-#if defined(__i386__) || defined(__x86_64__)
+
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_tryrdlock(rwlock);
- return(ret);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+ } else {
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
-#endif /* __i386__ || __x86_64__ */
- /* grab the monitor lock */
- if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- return(ret);
- }
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TRYWRLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
+#endif
+loop:
+ lcntval = *lcntaddr;
+ rw_seq = *seqaddr;
+
+ /* can we acquire in userland? */
+ if ((lcntval & PTH_RWL_RBIT) != 0) {
+ newval = ((lcntval + PTHRW_INC) & PTHRW_COUNT_MASK) | PTH_RWL_IBIT | PTH_RWL_KBIT| PTH_RWL_EBIT;
+ newsval = rw_seq + PTHRW_INC;
+ gotlock = 1;
+ } else
+ gotlock = 0;
- /* give writers priority over readers */
- if (rwlock->blocked_writers || rwlock->state < 0) {
- ret = EBUSY;
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- }
- else if (rwlock->state == MAX_READ_LOCKS) {
- ret = EAGAIN; /* too many read locks acquired */
- PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
- }
- else {
- ++rwlock->state; /* indicate we are locked for reading */
- PLOCKSTAT_RW_ACQUIRE(rwlock, READ_LOCK_PLOCKSTAT);
- }
- /* see the comment on this in pthread_rwlock_rdlock */
- pthread_mutex_unlock(&rwlock->lock);
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+
+ if (gotlock != 0) {
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+ } else
+ newval64 = oldval64;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE) {
+ goto loop;
+ }
+ if (gotlock == 1) {
+#if __DARWIN_UNIX03
+ rwlock->rw_owner = self;
+#endif /* __DARWIN_UNIX03 */
+ PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TRYWRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0, 0, 0, 0);
+#endif
+ return(0);
+ } else {
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_TRYWRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, EBUSY, 0, 0);
+#endif
- return(ret);
+ PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EBUSY);
+ return(EBUSY);
+ }
}
int
-pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
+pthread_rwlock_wrlock(pthread_rwlock_t * orwlock)
{
- int ret;
#if __DARWIN_UNIX03
pthread_t self = pthread_self();
#endif /* __DARWIN_UNIX03 */
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_trywrlock(rwlock));
+ npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
+ int error = 0, gotlock = 0;
+ uint64_t oldval64, newval64;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t myid = 0;
+
+ if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+ LOCK(rwlock->lock);
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
+ return(error);
+ }
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
+ return(EINVAL);
+ }
+ UNLOCK(rwlock->lock);
+ }
+
+ if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+ } else {
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
-#endif /* __i386__ || __x86_64__ */
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
+#endif
+loop:
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lcntval, ucntval, rw_seq, 0);
+#endif
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
- return(ret);
+#if __DARWIN_UNIX03
+ if (is_rwl_ebit_set(lcntval)) {
+ if(rwlock->rw_owner == self) {
+ error = EDEADLK;
+ goto out;
}
}
+#endif /* __DARWIN_UNIX03 */
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
+
+ if ((lcntval & PTH_RWL_RBIT) != 0) {
+ /* lock is restart state, writer can acquire the lock */
+ newval = ((lcntval + PTHRW_INC) & PTHRW_COUNT_MASK) | PTH_RWL_IBIT | PTH_RWL_KBIT| PTH_RWL_EBIT;
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_trywrlock(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
+ newsval = rw_seq + PTHRW_INC;
+ gotlock = 1;
+
+ } else {
+ if (is_rwl_lbit_set(lcntval))
+ newval = (lcntval + PTHRW_INC)| PTH_RWL_WBIT;
+ else
+ newval = (lcntval + PTHRW_INC) | PTH_RWL_KBIT| PTH_RWL_WBIT;
- /* grab the monitor lock */
- if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
- return(ret);
+ newsval = rw_seq;
+ if (is_rws_setseq(rw_seq)) {
+ newsval &= PTHRW_SW_Reset_BIT_MASK;
+ newsval |= (newval & PTHRW_COUNT_MASK);
+ }
+ gotlock = 0;
}
+ /* update lock seq */
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lcntval, newval, 0);
+#endif
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto loop;
+
+ /* lock acquired in userland itself? */
+ if (gotlock != 0)
+ goto gotit;
+
+ /* unable to acquire in userland, transition to kernel */
+
+ PLOCKSTAT_RW_BLOCK(orwlock, WRITE_LOCK_PLOCKSTAT);
+retry:
+ updateval = __psynch_rw_wrlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
+ if (updateval == (uint32_t)-1) {
+ error = errno;
+ } else
+ error = 0;
+
+ if (error == EINTR) {
+ goto retry;
+ }
- if (rwlock->state != 0) {
- ret = EBUSY;
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
+ if (error != 0) {
+#if _KSYN_TRACE_
+ set_enable(2);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("wrlock from kernel with unknown error %x: tid %x\n", updateval, (uint32_t)myid);
}
- else {
- /* indicate we are locked for writing */
- rwlock->state = -1;
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x33333333, newval, updateval, 0);
+#endif
+ PLOCKSTAT_RW_BLOCKED(orwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
+ if (error == 0) {
+ rwlock_action_onreturn(orwlock, updateval);
+gotit:
#if __DARWIN_UNIX03
- rwlock->owner = self;
+ rwlock->rw_owner = self;
#endif /* __DARWIN_UNIX03 */
- PLOCKSTAT_RW_ACQUIRE(rwlock, WRITE_LOCK_PLOCKSTAT);
- }
-
- /* see the comment on this in pthread_rwlock_rdlock */
- pthread_mutex_unlock(&rwlock->lock);
-
- return(ret);
+ PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
+#endif
+ return(0);
+ }
+#if __DARWIN_UNIX03
+out:
+#endif /* __DARWIN_UNIX03 */
+ PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
+#endif
+ return(error);
}
+
int
-pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
+pthread_rwlock_unlock(pthread_rwlock_t * orwlock)
{
- int ret;
- int writer = (rwlock < 0) ? 1:0;
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_unlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
+ npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+ uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval, ulval;
+ int error = 0, wrlock = 0, haswbit = 0, hasubit = 0, hasybit = 0;
+ uint64_t oldval64, newval64;
+ volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+ uint64_t myid = 0;
+
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- PLOCKSTAT_RW_ERROR(rwlock, writer, EINVAL);
- return(EINVAL);
+ LOCK(rwlock->lock);
+ if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+ if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0) {
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, wrlock, error);
+ return(error);
+ }
+ } else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
+ UNLOCK(rwlock->lock);
+ PLOCKSTAT_RW_ERROR(orwlock, wrlock, EINVAL);
+ return(EINVAL);
+ }
+ UNLOCK(rwlock->lock);
}
-
-#if defined(__i386__) || defined(__x86_64__)
+
if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_unlock(rwlock);
- return(ret);
+ RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+ } else {
+ lcntaddr = rwlock->rw_lcntaddr;
+ ucntaddr = rwlock->rw_ucntaddr;
+ seqaddr = rwlock->rw_seqaddr;
}
-#endif /* __i386__ || __x86_64__ */
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
+#endif
+loop:
+ lcntval = *lcntaddr;
+ ucntval = *ucntaddr;
+ rw_seq = *seqaddr;
+
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x51515151, lcntval, ucntval, 0);
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x51515151, rw_seq, 0, 0);
+#endif
+ /* check for spurious unlocks */
+ if ((lcntval & PTH_RWL_RBIT) != 0) {
+ newval = lcntval ;
+ newsval = rw_seq;
- /* grab the monitor lock */
- if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, writer, ret);
- return(ret);
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) == TRUE) {
+ /* spurious unlock, return */
+ error = EINVAL;
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x1a1b1c1d, lcntval, ucntval, 0);
+#endif
+ goto succout;
+ } else
+ goto loop;
}
- if (rwlock->state > 0) {
- if (--rwlock->state == 0 && rwlock->blocked_writers)
- ret = pthread_cond_signal(&rwlock->write_signal);
- } else if (rwlock->state < 0) {
- rwlock->state = 0;
+ if (is_rwl_ebit_set(lcntval)) {
+ wrlock = 1;
#if __DARWIN_UNIX03
- rwlock->owner = (pthread_t)0;
+ rwlock->rw_owner = (pthread_t)0;
#endif /* __DARWIN_UNIX03 */
+ }
+
+ /* update U */
+
+ ulval = (ucntval + PTHRW_INC);
- if (rwlock->blocked_writers)
- ret = pthread_cond_signal(&rwlock->write_signal);
- else
- ret = pthread_cond_broadcast(&rwlock->read_signal);
- } else
- ret = EINVAL;
+ if (OSAtomicCompareAndSwap32(ucntval, ulval, (volatile int32_t *)ucntaddr) != TRUE)
+ goto loop;
+
+lp11:
+ /* just validate the l and S values */
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
- if (ret == 0) {
- PLOCKSTAT_RW_RELEASE(rwlock, writer);
- } else {
- PLOCKSTAT_RW_ERROR(rwlock, writer, ret);
+ newval64 = oldval64;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE) {
+ lcntval = *lcntaddr;
+ rw_seq = *seqaddr;
+ goto lp11;
}
- /* see the comment on this in pthread_rwlock_rdlock */
- pthread_mutex_unlock(&rwlock->lock);
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xd1d2d3d4, lcntval, rw_seq, 0);
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xd1d2d3d4, ulval, 0, 0);
+#endif
- return(ret);
-}
+ /* last unlock, note U is already updated ? */
+ if((lcntval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK)) {
-int
-pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
-{
- int ret;
-#if __DARWIN_UNIX03
- pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xbbbbbbbb, lcntval, ucntval, 0);
+#endif
+ /* Set L with R and init bits and set S to L */
+ newval = (lcntval & PTHRW_COUNT_MASK)| PTHRW_RWLOCK_INIT;
+ newsval = (lcntval & PTHRW_COUNT_MASK)| PTHRW_RWS_INIT;
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_wrlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
- return(ret);
- }
- }
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE) {
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xcccccccc, 0, 0, 0);
+#endif
+ lcntval = *lcntaddr;
+ rw_seq = *seqaddr;
+ goto lp11;
+ }
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xdddddddd, lcntval, ucntval, 0);
+#endif
+ goto succout;
}
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_wrlock(rwlock);
- return(ret);
+ /* if it is not exclusive or no Writer/yield pending, skip */
+ if ((lcntval & (PTH_RWL_EBIT | PTH_RWL_WBIT | PTH_RWL_YBIT | PTH_RWL_KBIT)) == 0) {
+ goto succout;
}
-#endif /* __i386__ || __x86_64__ */
+ /* kernel transition needed? */
+ /* U+1 == S? */
+ if ((ulval + PTHRW_INC) != (rw_seq & PTHRW_COUNT_MASK)) {
+ if ((lcntval & PTH_RWL_UBIT) != 0) {
+ /* if U bit is set U + 2 == S ? */
+ if ((ulval + PTHRW_INC + PTHRW_INC) != (rw_seq & PTHRW_COUNT_MASK))
+ goto succout;
+ } else
+ goto succout;
+ }
+
+ haswbit = lcntval & PTH_RWL_WBIT;
+ hasubit = lcntval & PTH_RWL_UBIT;
+ hasybit = lcntval & PTH_RWL_YBIT;
+
+ /* reset all bits and set k */
+ newval = (lcntval & PTHRW_COUNT_MASK) | PTH_RWL_KBIT;
+ /* set I bit on S word */
+ newsval = rw_seq | PTH_RWS_IBIT;
+ if (haswbit != 0)
+ newsval |= PTH_RWS_WSVBIT;
+ if (hasubit != 0)
+ newsval |= PTH_RWS_USVBIT;
+ if (hasybit != 0)
+ newsval |= PTH_RWS_YSVBIT;
+
+ oldval64 = (((uint64_t)rw_seq) << 32);
+ oldval64 |= lcntval;
+
+ newval64 = (((uint64_t)newsval) << 32);
+ newval64 |= newval;
+
+ if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+ goto lp11;
- /* grab the monitor lock */
- if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
- return(ret);
- }
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555511, 1, ulval, 0);
+#endif
+ updateval = __psynch_rw_unlock(orwlock, lcntval, ulval, newsval, rwlock->rw_flags);
+ if (updateval == (uint32_t)-1) {
+ error = errno;
+ } else
+ error = 0;
+
+ if(error != 0) {
-#if __DARWIN_UNIX03
- if ((rwlock->state < 0) && (rwlock->owner == self)) {
- pthread_mutex_unlock(&rwlock->lock);
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EDEADLK);
- return(EDEADLK);
- }
-#endif /* __DARWIN_UNIX03 */
- while (rwlock->state != 0) {
- ++rwlock->blocked_writers;
-
- PLOCKSTAT_RW_BLOCK(rwlock, WRITE_LOCK_PLOCKSTAT);
- ret = pthread_cond_wait(&rwlock->write_signal, &rwlock->lock);
-
- if (ret != 0) {
- --rwlock->blocked_writers;
- pthread_mutex_unlock(&rwlock->lock);
- PLOCKSTAT_RW_BLOCKED(rwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT);
- PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
- return(ret);
+ /* not sure what is the scenario */
+ if(error != EINTR) {
+#if _KSYN_TRACE_
+ set_enable(4);
+#endif /* _KSYN_TRACE_ */
+ (void)pthread_threadid_np(pthread_self(), &myid);
+ LIBC_ABORT("rwunlock from kernel with unknown error %x: tid %x\n", error, (uint32_t)myid);
+ goto succout;
}
-
- PLOCKSTAT_RW_BLOCKED(rwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
-
- --rwlock->blocked_writers;
+ error = 0;
}
+
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555522, 3, lcntval, 0);
+#endif
- /* indicate we are locked for writing */
- rwlock->state = -1;
-#if __DARWIN_UNIX03
- rwlock->owner = self;
-#endif /* __DARWIN_UNIX03 */
- PLOCKSTAT_RW_ACQUIRE(rwlock, WRITE_LOCK_PLOCKSTAT);
-
- /* see the comment on this in pthread_rwlock_rdlock */
- pthread_mutex_unlock(&rwlock->lock);
-
- return(ret);
+succout:
+ PLOCKSTAT_RW_RELEASE(orwlock, wrlock);
+#if _KSYN_TRACE_
+ if (__pthread_lock_debug != 0)
+ (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
+#endif
+ return(0);
}
--- /dev/null
+/*
+ * Copyright (c) 2000-2011 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * MkLinux
+ */
+
+/*
+ * Extension SPIs.
+ */
+
+#ifndef _PTHREAD_SPIS_H
+#define _PTHREAD_SPIS_H
+
+
+#include <pthread.h>
+
+__BEGIN_DECLS
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
+/* firstfit */
+#define PTHREAD_FIRSTFIT_MUTEX_INITIALIZER {_PTHREAD_FIRSTFIT_MUTEX_SIG_init, {0}}
+/*
+ * Mutex attributes
+ */
+#define _PTHREAD_MUTEX_POLICY_NONE 0
+#define _PTHREAD_MUTEX_POLICY_FAIRSHARE 1
+#define _PTHREAD_MUTEX_POLICY_FIRSTFIT 2
+
+/* sets the mutex policy attributes */
+int pthread_mutexattr_setpolicy_np(pthread_mutexattr_t *, int );
+
+#endif /* (!_POSIX_C_SOURCE && !_XOPEN_SOURCE) || _DARWIN_C_SOURCE */
+
+__END_DECLS
+
+#endif /* _PTHREAD_SPIS_H */
#include <sys/cdefs.h>
#include <pthread.h>
-
+#include <Availability.h>
#define __PTHREAD_WORKQ_SIZE__ 128
#define __PTHREAD_WORKQ_ATTR_SIZE__ 60
typedef void * pthread_workitem_handle_t;
/* Kernel expected target concurrency of the workqueue clients for the three priority queues */
-#define WORKQ_HIGH_PRIOQUEUE 0
-#define WORKQ_DEFAULT_PRIOQUEUE 1
-#define WORKQ_LOW_PRIOQUEUE 2
+#define WORKQ_HIGH_PRIOQUEUE 0 /* high priority queue */
+#define WORKQ_DEFAULT_PRIOQUEUE 1 /* default priority queue */
+#define WORKQ_LOW_PRIOQUEUE 2 /* low priority queue */
+#define WORKQ_BG_PRIOQUEUE 3 /* background priority queue */
-#define WORKQ_NUM_PRIOQUEUE 3
+#define WORKQ_NUM_PRIOQUEUE 4
extern __int32_t workq_targetconc[WORKQ_NUM_PRIOQUEUE];
__BEGIN_DECLS
-int pthread_workqueue_init_np(void);
-int pthread_workqueue_attr_init_np(pthread_workqueue_attr_t * attr);
-int pthread_workqueue_attr_destroy_np(pthread_workqueue_attr_t * attr);
-int pthread_workqueue_attr_getqueuepriority_np(const pthread_workqueue_attr_t * attr, int * qprio);
+int pthread_workqueue_init_np(void) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int pthread_workqueue_attr_init_np(pthread_workqueue_attr_t * attr) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int pthread_workqueue_attr_destroy_np(pthread_workqueue_attr_t * attr) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int pthread_workqueue_attr_getqueuepriority_np(const pthread_workqueue_attr_t * attr, int * qprio) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
/* WORKQ_HIGH/DEFAULT/LOW_PRIOQUEUE are the only valid values */
-int pthread_workqueue_attr_setqueuepriority_np(pthread_workqueue_attr_t * attr, int qprio);
-int pthread_workqueue_attr_getovercommit_np(const pthread_workqueue_attr_t * attr, int * ocommp);
-int pthread_workqueue_attr_setovercommit_np(pthread_workqueue_attr_t * attr, int ocomm);
+int pthread_workqueue_attr_setqueuepriority_np(pthread_workqueue_attr_t * attr, int qprio) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int pthread_workqueue_attr_getovercommit_np(const pthread_workqueue_attr_t * attr, int * ocommp) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
+int pthread_workqueue_attr_setovercommit_np(pthread_workqueue_attr_t * attr, int ocomm) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
-int pthread_workqueue_create_np(pthread_workqueue_t * workqp, const pthread_workqueue_attr_t * attr);
-int pthread_workqueue_additem_np(pthread_workqueue_t workq, void ( *workitem_func)(void *), void * workitem_arg, pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp);
+int pthread_workqueue_create_np(pthread_workqueue_t * workqp, const pthread_workqueue_attr_t * attr) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
+int pthread_workqueue_additem_np(pthread_workqueue_t workq, void ( *workitem_func)(void *), void * workitem_arg, pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
/* If the queue value is WORKQ_NUM_PRIOQUEUE, the request for concurrency is for all queues */
-int pthread_workqueue_requestconcurrency_np(int queue, int concurrency);
-int pthread_workqueue_getovercommit_np(pthread_workqueue_t workq, unsigned int *ocommp);
+int pthread_workqueue_requestconcurrency_np(int queue, int concurrency) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
+int pthread_workqueue_getovercommit_np(pthread_workqueue_t workq, unsigned int *ocommp) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
/*
* If the arg is non zero, it enables kill on current thread.
* If the arg of zero, it disables kill on current thread.
*/
-int __pthread_workqueue_setkill(int);
+int __pthread_workqueue_setkill(int) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
__END_DECLS
#endif /* _POSIX_PTHREAD_WORKQUEUE_H */
* 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.
* SUCH DAMAGE.
*
* @(#)cname.h 8.3 (Berkeley) 3/20/94
- * $FreeBSD: src/lib/libc/regex/cname.h,v 1.3 2002/03/22 23:41:56 obrien Exp $
+ * $FreeBSD: src/lib/libc/regex/cname.h,v 1.4 2007/01/09 00:28:04 imp Exp $
*/
/* character-name table */
--- /dev/null
+--- cname.h.orig 2010-05-05 14:45:26.000000000 -0700
++++ cname.h 2010-05-05 14:45:56.000000000 -0700
+@@ -39,8 +39,8 @@
+ */
+
+ /* character-name table */
+-static struct cname {
+- char *name;
++static const struct cname {
++ const char *name;
+ char code;
+ } cnames[] = {
+ {"NUL", '\0'},
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/engine.c,v 1.14 2004/07/12 07:35:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/engine.c,v 1.23 2009/09/16 06:32:23 dds Exp $");
/*
* The matching engine and friends. This file is #included by regexec.c
struct re_guts *g;
int eflags;
regmatch_t *pmatch; /* [nsub+1] (0 element unused) */
- char *offp; /* offsets work from here */
- char *beginp; /* start of string -- virtual NUL precedes */
- char *endp; /* end of string -- virtual NUL here */
- char *coldp; /* can be no match starting before here */
- char **lastpos; /* [nplus+1] */
+ const char *offp; /* offsets work from here */
+ const char *beginp; /* start of string -- virtual NUL precedes */
+ const char *endp; /* end of string -- virtual NUL here */
+ const char *coldp; /* can be no match starting before here */
+ const char **lastpos; /* [nplus+1] */
STATEVARS;
states st; /* current states */
states fresh; /* states for a fresh start */
#endif
/* === engine.c === */
-static int matcher(struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
-static char *dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *backref(struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
-static char *fast(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *slow(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static int matcher(struct re_guts *g, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static const char *dissect(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *backref(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst, sopno lev, int);
+static const char *fast(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *slow(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
static states step(struct re_guts *g, sopno start, sopno stop, states bef, wint_t ch, states aft);
+#define MAX_RECURSION 100
#define BOL (OUT-1)
#define EOL (BOL-1)
#define BOLEOL (BOL-2)
#define BADCHAR (BOL-6)
#define NONCHAR(c) ((c) <= OUT)
#ifdef REDEBUG
-static void print(struct match *m, char *caption, states st, int ch, FILE *d);
+static void print(struct match *m, const char *caption, states st, int ch, FILE *d);
#endif
#ifdef REDEBUG
-static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst);
+static void at(struct match *m, const char *title, const char *start, const char *stop, sopno startst, sopno stopst);
#endif
#ifdef REDEBUG
-static char *pchar(int ch);
+static const char *pchar(int ch);
#endif
#ifdef __cplusplus
/*
- matcher - the actual matching engine
- == static int matcher(struct re_guts *g, char *string, \
+ == static int matcher(struct re_guts *g, const char *string, \
== size_t nmatch, regmatch_t pmatch[], int eflags);
*/
static int /* 0 success, REG_NOMATCH failure */
-matcher(g, string, nmatch, pmatch, eflags)
-struct re_guts *g;
-char *string;
-size_t nmatch;
-regmatch_t pmatch[];
-int eflags;
+matcher(struct re_guts *g,
+ const char *string,
+ size_t nmatch,
+ regmatch_t pmatch[],
+ int eflags)
{
- char *endp;
+ const char *endp;
int i;
struct match mv;
struct match *m = &mv;
- char *dp;
+ const char *dp;
const sopno gf = g->firststate+1; /* +1 for OEND */
const sopno gl = g->laststate;
- char *start;
- char *stop;
+ const char *start;
+ const char *stop;
/* Boyer-Moore algorithms variables */
- char *pp;
+ const char *pp;
int cj, mj;
- char *mustfirst;
- char *mustlast;
+ const char *mustfirst;
+ const char *mustlast;
int *matchjump;
int *charjump;
if (g->moffset > -1)
start = ((dp - g->moffset) < start) ? start : dp - g->moffset;
+ SP("mloop", m->st, *start);
+
/* this loop does only one repetition except for backrefs */
for (;;) {
endp = fast(m, start, stop, gf, gl);
if (endp == NULL) { /* a miss */
+ if (m->pmatch != NULL)
+ free((char *)m->pmatch);
+ if (m->lastpos != NULL)
+ free((char *)m->lastpos);
STATETEARDOWN(m);
return(REG_NOMATCH);
}
dp = dissect(m, m->coldp, endp, gf, gl);
} else {
if (g->nplus > 0 && m->lastpos == NULL)
- m->lastpos = (char **)malloc((g->nplus+1) *
- sizeof(char *));
+ m->lastpos = malloc((g->nplus+1) *
+ sizeof(const char *));
if (g->nplus > 0 && m->lastpos == NULL) {
free(m->pmatch);
STATETEARDOWN(m);
return(REG_ESPACE);
}
NOTE("backref dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
}
if (dp != NULL)
break;
}
#endif
NOTE("backoff dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
}
assert(dp == NULL || dp == endp);
if (dp != NULL) /* found a shorter one */
NOTE("false alarm");
/* recycle starting later */
start = m->coldp + XMBRTOWC(NULL, m->coldp,
- m->endp - m->coldp, &m->mbs, 0);
+ stop - m->coldp, &m->mbs, 0);
assert(start <= stop);
}
/*
- dissect - figure out what matched what, no back references
- == static char *dissect(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst);
+ == static const char *dissect(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
*/
-static char * /* == stop (success) always */
-dissect(m, start, stop, startst, stopst)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char * /* == stop (success) always */
+dissect(struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
int i;
sopno ss; /* start sop of current subRE */
sopno es; /* end sop of current subRE */
- char *sp; /* start of string matched by it */
- char *stp; /* string matched by it cannot pass here */
- char *rest; /* start of rest of string */
- char *tail; /* string unmatched by rest of RE */
+ const char *sp; /* start of string matched by it */
+ const char *stp; /* string matched by it cannot pass here */
+ const char *rest; /* start of rest of string */
+ const char *tail; /* string unmatched by rest of RE */
sopno ssub; /* start sop of subsubRE */
sopno esub; /* end sop of subsubRE */
- char *ssp; /* start of string matched by subsubRE */
- char *sep; /* end of string matched by subsubRE */
- char *oldssp; /* previous ssp */
- char *dp;
+ const char *ssp; /* start of string matched by subsubRE */
+ const char *sep; /* end of string matched by subsubRE */
+ const char *oldssp; /* previous ssp */
+ const char *dp;
AT("diss", start, stop, startst, stopst);
sp = start;
/*
- backref - figure out what matched what, figuring in back references
- == static char *backref(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst, sopno lev);
+ == static const char *backref(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst, sopno lev);
*/
-static char * /* == stop (success) or NULL (failure) */
-backref(m, start, stop, startst, stopst, lev)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
-sopno lev; /* PLUS nesting level */
+static const char * /* == stop (success) or NULL (failure) */
+backref(struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst,
+ sopno lev, /* PLUS nesting level */
+ int rec)
{
int i;
sopno ss; /* start sop of current subRE */
- char *sp; /* start of string matched by it */
+ const char *sp; /* start of string matched by it */
sopno ssub; /* start sop of subsubRE */
sopno esub; /* end sop of subsubRE */
- char *ssp; /* start of string matched by subsubRE */
- char *dp;
+ const char *ssp; /* start of string matched by subsubRE */
+ const char *dp;
size_t len;
int hard;
sop s;
return(NULL);
assert(m->pmatch[i].rm_so != -1);
len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+ if (len == 0 && rec++ > MAX_RECURSION)
+ return(NULL);
assert(stop - m->beginp >= len);
if (sp > stop - len)
return(NULL); /* not enough left to match */
return(NULL);
while (m->g->strip[ss] != SOP(O_BACK, i))
ss++;
- return(backref(m, sp+len, stop, ss+1, stopst, lev));
+ return(backref(m, sp+len, stop, ss+1, stopst, lev, rec));
break;
case OQUEST_: /* to null or not */
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
if (dp != NULL)
return(dp); /* not */
- return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
+ return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec));
break;
case OPLUS_:
assert(m->lastpos != NULL);
assert(lev+1 <= m->g->nplus);
m->lastpos[lev+1] = sp;
- return(backref(m, sp, stop, ss+1, stopst, lev+1));
+ return(backref(m, sp, stop, ss+1, stopst, lev+1, rec));
break;
case O_PLUS:
if (sp == m->lastpos[lev]) /* last pass matched null */
- return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
/* try another pass */
m->lastpos[lev] = sp;
- dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
+ dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec);
if (dp == NULL)
- return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
else
return(dp);
break;
esub = ss + OPND(s) - 1;
assert(OP(m->g->strip[esub]) == OOR1);
for (;;) { /* find first matching branch */
- dp = backref(m, sp, stop, ssub, esub, lev);
+ dp = backref(m, sp, stop, ssub, esub, lev, rec);
if (dp != NULL)
return(dp);
/* that one missed, try next one */
assert(0 < i && i <= m->g->nsub);
offsave = m->pmatch[i].rm_so;
m->pmatch[i].rm_so = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
if (dp != NULL)
return(dp);
m->pmatch[i].rm_so = offsave;
assert(0 < i && i <= m->g->nsub);
offsave = m->pmatch[i].rm_eo;
m->pmatch[i].rm_eo = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
if (dp != NULL)
return(dp);
m->pmatch[i].rm_eo = offsave;
/*
- fast - step through the string at top speed
- == static char *fast(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst);
+ == static const char *fast(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
*/
-static char * /* where tentative match ended, or NULL */
-fast(m, start, stop, startst, stopst)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char * /* where tentative match ended, or NULL */
+fast( struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
states st = m->st;
states fresh = m->fresh;
states tmp = m->tmp;
- char *p = start;
+ const char *p = start;
wint_t c;
wint_t lastc; /* previous c */
wint_t flagch;
int i;
- char *coldp; /* last p after which no match was underway */
+ const char *coldp; /* last p after which no match was underway */
size_t clen;
CLEAR(st);
SET1(st, startst);
+ SP("fast", st, *p);
st = step(m->g, startst, stopst, st, NOTHING, st);
ASSIGN(fresh, st);
SP("start", st, *p);
for (;;) {
/* next character */
lastc = c;
- if (p == m->endp)
+ if (p == m->endp) {
+ clen = 0;
c = OUT;
- else
+ } else
clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR);
if (EQ(st, fresh))
coldp = p;
}
/* are we done? */
- if (ISSET(st, stopst) || p == stop)
+ if (ISSET(st, stopst) || p == stop || clen > stop - p)
break; /* NOTE BREAK OUT */
/* no, we must deal with this character */
assert(coldp != NULL);
m->coldp = coldp;
if (ISSET(st, stopst))
- return(p+XMBRTOWC(NULL, p, m->endp - p, &m->mbs, 0));
+ return(p+XMBRTOWC(NULL, p, stop - p, &m->mbs, 0));
else
return(NULL);
}
/*
- slow - step through the string more deliberately
- == static char *slow(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst);
+ == static const char *slow(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
*/
-static char * /* where it ended */
-slow(m, start, stop, startst, stopst)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char * /* where it ended */
+slow( struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
states st = m->st;
states empty = m->empty;
states tmp = m->tmp;
- char *p = start;
+ const char *p = start;
wint_t c;
wint_t lastc; /* previous c */
wint_t flagch;
int i;
- char *matchp; /* last p at which a match ended */
+ const char *matchp; /* last p at which a match ended */
size_t clen;
AT("slow", start, stop, startst, stopst);
/* are we done? */
if (ISSET(st, stopst))
matchp = p;
- if (EQ(st, empty) || p == stop)
+ if (EQ(st, empty) || p == stop || clen > stop - p)
break; /* NOTE BREAK OUT */
/* no, we must deal with this character */
== #define NONCHAR(c) ((c) <= OUT)
*/
static states
-step(g, start, stop, bef, ch, aft)
-struct re_guts *g;
-sopno start; /* start state within strip */
-sopno stop; /* state after stop state within strip */
-states bef; /* states reachable before */
-wint_t ch; /* character or NONCHAR code */
-states aft; /* states already known reachable after */
+step(struct re_guts *g,
+ sopno start, /* start state within strip */
+ sopno stop, /* state after stop state within strip */
+ states bef, /* states reachable before */
+ wint_t ch, /* character or NONCHAR code */
+ states aft) /* states already known reachable after */
{
cset *cs;
sop s;
OP(s = g->strip[pc+look]) != O_CH;
look += OPND(s))
assert(OP(s) == OOR2);
- FWD(aft, aft, look);
+ FWD(aft, aft, look + 1);
}
break;
case OOR2: /* propagate OCH_'s marking */
/*
- print - print a set of states
== #ifdef REDEBUG
- == static void print(struct match *m, char *caption, states st, \
+ == static void print(struct match *m, const char *caption, states st, \
== int ch, FILE *d);
== #endif
*/
static void
-print(m, caption, st, ch, d)
-struct match *m;
-char *caption;
-states st;
-int ch;
-FILE *d;
+print(struct match *m,
+ const char *caption,
+ states st,
+ int ch,
+ FILE *d)
{
struct re_guts *g = m->g;
int i;
/*
- at - print current situation
== #ifdef REDEBUG
- == static void at(struct match *m, char *title, char *start, char *stop, \
- == sopno startst, sopno stopst);
+ == static void at(struct match *m, const char *title, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
== #endif
*/
static void
-at(m, title, start, stop, startst, stopst)
-struct match *m;
-char *title;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+at( struct match *m,
+ const char *title,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
if (!(m->eflags®_TRACE))
return;
/*
- pchar - make a character printable
== #ifdef REDEBUG
- == static char *pchar(int ch);
+ == static const char *pchar(int ch);
== #endif
*
* Is this identical to regchar() over in debug.c? Well, yes. But a
* a matching debug.o, and this is convenient. It all disappears in
* the non-debug compilation anyway, so it doesn't matter much.
*/
-static char * /* -> representation */
-pchar(ch)
-int ch;
+static const char * /* -> representation */
+pchar(int ch)
{
static char pbuf[10];
---- engine.c.orig 2004-11-25 11:38:32.000000000 -0800
-+++ engine.c 2005-04-18 16:52:09.000000000 -0700
-@@ -270,7 +270,7 @@ int eflags;
+--- engine.c.bsdnew 2009-11-11 11:29:04.000000000 -0800
++++ engine.c 2009-11-11 11:30:28.000000000 -0800
+@@ -272,7 +272,7 @@ matcher(struct re_guts *g,
break;
assert(m->coldp < m->endp);
m->coldp += XMBRTOWC(NULL, m->coldp,
}
if (nmatch == 1 && !g->backrefs)
break; /* no further info needed */
-@@ -331,7 +331,7 @@ int eflags;
+@@ -333,7 +333,7 @@ matcher(struct re_guts *g,
NOTE("false alarm");
/* recycle starting later */
start = m->coldp + XMBRTOWC(NULL, m->coldp,
-- m->endp - m->coldp, &m->mbs, 0);
-+ m->endp - m->coldp, &m->mbs, 0, g->loc);
+- stop - m->coldp, &m->mbs, 0);
++ stop - m->coldp, &m->mbs, 0, g->loc);
assert(start <= stop);
}
-@@ -409,7 +409,7 @@ sopno stopst;
+@@ -410,7 +410,7 @@ dissect(struct match *m,
assert(nope);
break;
case OCHAR:
break;
case OBOL:
case OEOL:
-@@ -418,7 +418,7 @@ sopno stopst;
+@@ -419,7 +419,7 @@ dissect(struct match *m,
break;
case OANY:
case OANYOF:
break;
case OBACK_:
case O_BACK:
-@@ -479,6 +479,10 @@ sopno stopst;
+@@ -480,6 +480,10 @@ dissect(struct match *m,
sep = ssp;
ssp = oldssp;
}
assert(sep == rest); /* must exhaust substring */
assert(slow(m, ssp, sep, ssub, esub) == rest);
dp = dissect(m, ssp, sep, ssub, esub);
-@@ -531,6 +535,14 @@ sopno stopst;
+@@ -532,6 +536,14 @@ dissect(struct match *m,
i = OPND(m->g->strip[ss]);
assert(0 < i && i <= m->g->nsub);
m->pmatch[i].rm_so = sp - m->offp;
break;
case ORPAREN:
i = OPND(m->g->strip[ss]);
-@@ -585,14 +597,14 @@ sopno lev; /* PLUS nesting level */
+@@ -586,14 +598,14 @@ backref(struct match *m,
case OCHAR:
if (sp == stop)
return(NULL);
if (wc == BADCHAR)
return (NULL);
break;
-@@ -600,8 +612,8 @@ sopno lev; /* PLUS nesting level */
+@@ -601,8 +613,8 @@ backref(struct match *m,
if (sp == stop)
return (NULL);
cs = &m->g->sets[OPND(s)];
return(NULL);
break;
case OBOL:
-@@ -625,8 +637,8 @@ sopno lev; /* PLUS nesting level */
+@@ -626,8 +638,8 @@ backref(struct match *m,
(sp < m->endp && *(sp-1) == '\n' &&
(m->g->cflags®_NEWLINE)) ||
(sp > m->beginp &&
{ /* yes */ }
else
return(NULL);
-@@ -635,8 +647,8 @@ sopno lev; /* PLUS nesting level */
+@@ -636,8 +648,8 @@ backref(struct match *m,
if (( (sp == m->endp && !(m->eflags®_NOTEOL)) ||
(sp < m->endp && *sp == '\n' &&
(m->g->cflags®_NEWLINE)) ||
{ /* yes */ }
else
return(NULL);
-@@ -807,7 +819,7 @@ sopno stopst;
- if (p == m->endp)
+@@ -811,7 +823,7 @@ fast( struct match *m,
+ clen = 0;
c = OUT;
- else
+ } else
- clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR);
+ clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR, m->g->loc);
if (EQ(st, fresh))
coldp = p;
-@@ -831,12 +843,12 @@ sopno stopst;
+@@ -835,12 +847,12 @@ fast( struct match *m,
}
/* how about a word boundary? */
flagch = EOW;
}
if (flagch == BOW || flagch == EOW) {
-@@ -861,7 +873,7 @@ sopno stopst;
+@@ -865,7 +877,7 @@ fast( struct match *m,
assert(coldp != NULL);
m->coldp = coldp;
if (ISSET(st, stopst))
-- return(p+XMBRTOWC(NULL, p, m->endp - p, &m->mbs, 0));
-+ return(p+XMBRTOWC(NULL, p, m->endp - p, &m->mbs, 0, m->g->loc));
+- return(p+XMBRTOWC(NULL, p, stop - p, &m->mbs, 0));
++ return(p+XMBRTOWC(NULL, p, stop - p, &m->mbs, 0, m->g->loc));
else
return(NULL);
}
-@@ -913,7 +925,7 @@ sopno stopst;
+@@ -916,7 +928,7 @@ slow( struct match *m,
c = OUT;
clen = 0;
} else
/* is there an EOL and/or BOL between lastc and c? */
flagch = '\0';
-@@ -935,12 +947,12 @@ sopno stopst;
+@@ -938,12 +950,12 @@ slow( struct match *m,
}
/* how about a word boundary? */
flagch = EOW;
}
if (flagch == BOW || flagch == EOW) {
-@@ -1031,7 +1043,7 @@ states aft; /* states already known re
+@@ -1033,7 +1045,7 @@ step(struct re_guts *g,
break;
case OANYOF:
cs = &g->sets[OPND(s)];
.\" SUCH DAMAGE.
.\"
.\" @(#)re_format.7 8.3 (Berkeley) 3/20/94
-.\" $FreeBSD: src/lib/libc/regex/re_format.7,v 1.11 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/regex/re_format.7,v 1.12 2008/09/05 17:41:20 keramida Exp $
.\"
.Dd March 20, 1994
.Dt RE_FORMAT 7
A locale may provide others.
A character class may not be used as an endpoint of a range.
.Pp
+A bracketed expression like
+.Ql [[:class:]]
+can be used to match a single character that belongs to a character
+class.
+The reverse, matching any character that does not belong to a specific
+class, the negation operator of bracket expressions may be used:
+.Ql [^[:class:]] .
+.Pp
There are two special cases\(dd of bracket expressions:
the bracket expressions
.Ql [[:<:]]
* 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.
static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.34 2004/10/03 15:42:59 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.36 2007/06/11 03:05:54 delphij Exp $");
#include <sys/types.h>
#include <stdio.h>
= #define REG_DUMP 0200
*/
int /* 0 success, otherwise REG_something */
-regcomp(preg, pattern, cflags)
-regex_t * __restrict preg;
-const char * __restrict pattern;
-int cflags;
+regcomp(regex_t * __restrict preg,
+ const char * __restrict pattern,
+ int cflags)
{
struct parse pa;
struct re_guts *g;
== static void p_ere(struct parse *p, int stop);
*/
static void
-p_ere(p, stop)
-struct parse *p;
-int stop; /* character this ERE should end at */
+p_ere(struct parse *p,
+ int stop) /* character this ERE should end at */
{
char c;
sopno prevback;
== static void p_ere_exp(struct parse *p);
*/
static void
-p_ere_exp(p)
-struct parse *p;
+p_ere_exp(struct parse *p)
{
char c;
wint_t wc;
== static void p_str(struct parse *p);
*/
static void
-p_str(p)
-struct parse *p;
+p_str(struct parse *p)
{
(void)REQUIRE(MORE(), REG_EMPTY);
while (MORE())
* The amount of lookahead needed to avoid this kludge is excessive.
*/
static void
-p_bre(p, end1, end2)
-struct parse *p;
-int end1; /* first terminating character */
-int end2; /* second terminating character */
+p_bre(struct parse *p,
+ int end1, /* first terminating character */
+ int end2) /* second terminating character */
{
sopno start = HERE();
int first = 1; /* first subexpression? */
== static int p_simp_re(struct parse *p, int starordinary);
*/
static int /* was the simple RE an unbackslashed $? */
-p_simp_re(p, starordinary)
-struct parse *p;
-int starordinary; /* is a leading * an ordinary character? */
+p_simp_re(struct parse *p,
+ int starordinary) /* is a leading * an ordinary character? */
{
int c;
int count;
== static int p_count(struct parse *p);
*/
static int /* the value */
-p_count(p)
-struct parse *p;
+p_count(struct parse *p)
{
int count = 0;
int ndigits = 0;
== static void p_bracket(struct parse *p);
*/
static void
-p_bracket(p)
-struct parse *p;
+p_bracket(struct parse *p)
{
cset *cs;
wint_t ch;
== static void p_b_term(struct parse *p, cset *cs);
*/
static void
-p_b_term(p, cs)
-struct parse *p;
-cset *cs;
+p_b_term(struct parse *p, cset *cs)
{
char c;
wint_t start, finish;
== static void p_b_cclass(struct parse *p, cset *cs);
*/
static void
-p_b_cclass(p, cs)
-struct parse *p;
-cset *cs;
+p_b_cclass(struct parse *p, cset *cs)
{
char *sp = p->next;
size_t len;
* This implementation is incomplete. xxx
*/
static void
-p_b_eclass(p, cs)
-struct parse *p;
-cset *cs;
+p_b_eclass(struct parse *p, cset *cs)
{
wint_t c;
== static char p_b_symbol(struct parse *p);
*/
static wint_t /* value of symbol */
-p_b_symbol(p)
-struct parse *p;
+p_b_symbol(struct parse *p)
{
wint_t value;
== static char p_b_coll_elem(struct parse *p, int endc);
*/
static wint_t /* value of collating element */
-p_b_coll_elem(p, endc)
-struct parse *p;
-wint_t endc; /* name ended by endc,']' */
+p_b_coll_elem(struct parse *p,
+ wint_t endc) /* name ended by endc,']' */
{
char *sp = p->next;
struct cname *cp;
== static char othercase(int ch);
*/
static wint_t /* if no counterpart, return ch */
-othercase(ch)
-wint_t ch;
+othercase(wint_t ch)
{
assert(iswalpha(ch));
if (iswupper(ch))
* Boy, is this implementation ever a kludge...
*/
static void
-bothcases(p, ch)
-struct parse *p;
-wint_t ch;
+bothcases(struct parse *p, wint_t ch)
{
char *oldnext = p->next;
char *oldend = p->end;
== static void ordinary(struct parse *p, int ch);
*/
static void
-ordinary(p, ch)
-struct parse *p;
-wint_t ch;
+ordinary(struct parse *p, wint_t ch)
{
cset *cs;
* Boy, is this implementation ever a kludge...
*/
static void
-nonnewline(p)
-struct parse *p;
+nonnewline(struct parse *p)
{
char *oldnext = p->next;
char *oldend = p->end;
== static void repeat(struct parse *p, sopno start, int from, int to);
*/
static void
-repeat(p, start, from, to)
-struct parse *p;
-sopno start; /* operand from here to end of strip */
-int from; /* repeated from this number */
-int to; /* to this number of times (maybe INFINITY) */
+repeat(struct parse *p,
+ sopno start, /* operand from here to end of strip */
+ int from, /* repeated from this number */
+ int to) /* to this number of times (maybe INFINITY) */
{
sopno finish = HERE();
# define N 2
- character can't be converted. Returns the number of bytes consumed.
*/
static wint_t
-wgetnext(p)
-struct parse *p;
+wgetnext(struct parse *p)
{
mbstate_t mbs;
wchar_t wc;
== static int seterr(struct parse *p, int e);
*/
static int /* useless but makes type checking happy */
-seterr(p, e)
-struct parse *p;
-int e;
+seterr(struct parse *p, int e)
{
if (p->error == 0) /* keep earliest error condition */
p->error = e;
== static cset *allocset(struct parse *p);
*/
static cset *
-allocset(p)
-struct parse *p;
+allocset(struct parse *p)
{
cset *cs, *ncs;
== static void freeset(struct parse *p, cset *cs);
*/
static void
-freeset(p, cs)
-struct parse *p;
-cset *cs;
+freeset(struct parse *p, cset *cs)
{
cset *top = &p->g->sets[p->g->ncsets];
- returning it if so, otherwise returning OUT.
*/
static wint_t
-singleton(cs)
-cset *cs;
+singleton(cset *cs)
{
wint_t i, s, n;
- CHadd - add character to character set.
*/
static void
-CHadd(p, cs, ch)
-struct parse *p;
-cset *cs;
-wint_t ch;
+CHadd(struct parse *p, cset *cs, wint_t ch)
{
wint_t nch, *newwides;
assert(ch >= 0);
- CHaddrange - add all characters in the range [min,max] to a character set.
*/
static void
-CHaddrange(p, cs, min, max)
-struct parse *p;
-cset *cs;
-wint_t min, max;
+CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
{
crange *newranges;
- CHaddtype - add all characters of a certain type to a character set.
*/
static void
-CHaddtype(p, cs, wct)
-struct parse *p;
-cset *cs;
-wctype_t wct;
+CHaddtype(struct parse *p, cset *cs, wctype_t wct)
{
wint_t i;
wctype_t *newtypes;
== static sopno dupl(struct parse *p, sopno start, sopno finish);
*/
static sopno /* start of duplicate */
-dupl(p, start, finish)
-struct parse *p;
-sopno start; /* from here */
-sopno finish; /* to this less one */
+dupl(struct parse *p,
+ sopno start, /* from here */
+ sopno finish) /* to this less one */
{
sopno ret = HERE();
sopno len = finish - start;
* some changes to the data structures. Maybe later.
*/
static void
-doemit(p, op, opnd)
-struct parse *p;
-sop op;
-size_t opnd;
+doemit(struct parse *p, sop op, size_t opnd)
{
/* avoid making error situations worse */
if (p->error != 0)
== static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
*/
static void
-doinsert(p, op, opnd, pos)
-struct parse *p;
-sop op;
-size_t opnd;
-sopno pos;
+doinsert(struct parse *p, sop op, size_t opnd, sopno pos)
{
sopno sn;
sop s;
== static void dofwd(struct parse *p, sopno pos, sop value);
*/
static void
-dofwd(p, pos, value)
-struct parse *p;
-sopno pos;
-sop value;
+dofwd(struct parse *p, sopno pos, sop value)
{
/* avoid making error situations worse */
if (p->error != 0)
== static void enlarge(struct parse *p, sopno size);
*/
static void
-enlarge(p, size)
-struct parse *p;
-sopno size;
+enlarge(struct parse *p, sopno size)
{
sop *sp;
== static void stripsnug(struct parse *p, struct re_guts *g);
*/
static void
-stripsnug(p, g)
-struct parse *p;
-struct re_guts *g;
+stripsnug(struct parse *p, struct re_guts *g)
{
g->nstates = p->slen;
g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
* Note that must and mlen got initialized during setup.
*/
static void
-findmust(p, g)
-struct parse *p;
-struct re_guts *g;
+findmust(struct parse *p, struct re_guts *g)
{
sop *scan;
sop *start;
* re paths.
*/
static int
-altoffset(scan, offset)
-sop *scan;
-int offset;
+altoffset(sop *scan, int offset)
{
int largest;
int try;
* the value of the character from the text that was mismatched.
*/
static void
-computejumps(p, g)
-struct parse *p;
-struct re_guts *g;
+computejumps(struct parse *p, struct re_guts *g)
{
int ch;
int mindex;
* the search algorithm works.
*/
static void
-computematchjumps(p, g)
-struct parse *p;
-struct re_guts *g;
+computematchjumps(struct parse *p, struct re_guts *g)
{
int mindex; /* General "must" iterator */
int suffix; /* Keeps track of matching suffix */
== static sopno pluscount(struct parse *p, struct re_guts *g);
*/
static sopno /* nesting depth */
-pluscount(p, g)
-struct parse *p;
-struct re_guts *g;
+pluscount(struct parse *p, struct re_guts *g)
{
sop *scan;
sop s;
---- regcomp.c.orig 2004-11-25 11:38:32.000000000 -0800
-+++ regcomp.c 2005-04-05 14:46:18.000000000 -0700
-@@ -43,6 +43,8 @@
+--- regcomp.c.orig 2010-06-21 14:05:04.000000000 -0700
++++ regcomp.c 2010-06-21 14:23:51.000000000 -0700
+@@ -39,6 +39,8 @@ static char sccsid[] = "@(#)regcomp.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.34 2004/10/03 15:42:59 stefanf Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.36 2007/06/11 03:05:54 delphij Exp $");
+#include "xlocale_private.h"
+
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
-@@ -73,6 +75,9 @@
+@@ -69,6 +71,9 @@ struct parse {
sopno ssize; /* malloced strip size (allocated) */
sopno slen; /* malloced strip length (used) */
int ncsalloc; /* number of csets allocated */
struct re_guts *g;
# define NPAREN 10 /* we need to remember () 1-9 for back refs */
sopno pbegin[NPAREN]; /* -> ( ([0] unused) */
-@@ -97,7 +102,7 @@
+@@ -93,7 +98,7 @@ static void p_b_cclass(struct parse *p,
static void p_b_eclass(struct parse *p, cset *cs);
static wint_t p_b_symbol(struct parse *p);
static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
static void bothcases(struct parse *p, wint_t ch);
static void ordinary(struct parse *p, wint_t ch);
static void nonnewline(struct parse *p);
-@@ -108,7 +113,7 @@
+@@ -104,7 +109,7 @@ static void freeset(struct parse *p, cse
static void CHadd(struct parse *p, cset *cs, wint_t ch);
static void CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max);
static void CHaddtype(struct parse *p, cset *cs, wctype_t wct);
static sopno dupl(struct parse *p, sopno start, sopno finish);
static void doemit(struct parse *p, sop op, size_t opnd);
static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
-@@ -227,10 +232,14 @@
+@@ -222,10 +227,14 @@ regcomp(regex_t * __restrict preg,
p->end = p->next + len;
p->error = 0;
p->ncsalloc = 0;
g->sets = NULL;
g->ncsets = 0;
g->cflags = cflags;
-@@ -308,8 +317,12 @@
+@@ -302,8 +311,12 @@ p_ere(struct parse *p,
conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop)
p_ere_exp(p);
if (!EAT('|'))
break; /* NOTE BREAK OUT */
-@@ -417,7 +430,7 @@
+@@ -410,7 +423,7 @@ p_ere_exp(struct parse *p)
ordinary(p, wc);
break;
case '{': /* okay as ordinary except if digit follows */
/* FALLTHROUGH */
default:
p->next--;
-@@ -431,7 +444,7 @@
+@@ -424,7 +437,7 @@ p_ere_exp(struct parse *p)
c = PEEK();
/* we call { a repetition if followed by a digit */
if (!( c == '*' || c == '+' || c == '?' ||
return; /* no repetition, we're done */
NEXT();
-@@ -460,7 +473,7 @@
+@@ -453,7 +466,7 @@ p_ere_exp(struct parse *p)
case '{':
count = p_count(p);
if (EAT(',')) {
count2 = p_count(p);
(void)REQUIRE(count <= count2, REG_BADBR);
} else /* single number with comma */
-@@ -481,7 +494,7 @@
+@@ -474,7 +487,7 @@ p_ere_exp(struct parse *p)
return;
c = PEEK();
if (!( c == '*' || c == '+' || c == '?' ||
return;
SETERROR(REG_BADRPT);
}
-@@ -494,7 +507,12 @@
- p_str(p)
- struct parse *p;
+@@ -486,7 +499,12 @@ p_ere_exp(struct parse *p)
+ static void
+ p_str(struct parse *p)
{
+#if __DARWIN_UNIX03
+ if (!p->zerorepeats) REQUIRE(MORE(), REG_EMPTY);
while (MORE())
ordinary(p, WGETNEXT());
}
-@@ -534,8 +552,12 @@
+@@ -525,8 +543,12 @@ p_bre(struct parse *p,
p->g->iflags |= USEEOL;
p->g->neol++;
}
}
/*
-@@ -609,12 +631,22 @@
+@@ -599,12 +621,22 @@ p_simp_re(struct parse *p,
i = (c&~BACKSL) - '0';
assert(i < NPAREN);
if (p->pend[i] != 0) {
EMIT(O_BACK, i);
} else
SETERROR(REG_ESUBREG);
-@@ -637,9 +669,10 @@
+@@ -627,9 +659,10 @@ p_simp_re(struct parse *p,
INSERT(OQUEST_, pos);
ASTERN(O_QUEST, pos);
} else if (EATTWO('\\', '{')) {
count2 = p_count(p);
(void)REQUIRE(count <= count2, REG_BADBR);
} else /* single number with comma */
-@@ -670,7 +703,7 @@
+@@ -659,7 +692,7 @@ p_count(struct parse *p)
int count = 0;
int ndigits = 0;
count = count*10 + (GETNEXT() - '0');
ndigits++;
}
-@@ -709,10 +742,22 @@
+@@ -697,10 +730,22 @@ p_bracket(struct parse *p)
cs->icase = 1;
if (EAT('^'))
cs->invert = 1;
while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
p_b_term(p, cs);
if (EAT('-'))
-@@ -725,7 +770,7 @@
+@@ -713,7 +758,7 @@ p_bracket(struct parse *p)
if (cs->invert && p->g->cflags®_NEWLINE)
cs->bmp['\n' >> 3] |= 1 << ('\n' & 7);
ordinary(p, ch);
freeset(p, cs);
} else
-@@ -751,8 +796,16 @@
+@@ -737,8 +782,16 @@ p_b_term(struct parse *p, cset *cs)
c = (MORE2()) ? PEEK2() : '\0';
break;
case '-':
break;
default:
c = '\0';
-@@ -773,7 +826,11 @@
+@@ -759,7 +812,11 @@ p_b_term(struct parse *p, cset *cs)
NEXT2();
(void)REQUIRE(MORE(), REG_EBRACK);
c = PEEK();
p_b_eclass(p, cs);
(void)REQUIRE(MORE(), REG_EBRACK);
(void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
-@@ -792,14 +849,14 @@
+@@ -778,14 +835,14 @@ p_b_term(struct parse *p, cset *cs)
if (start == finish)
CHadd(p, cs, start);
else {
)
CHadd(p, cs, i);
}
-@@ -823,7 +880,7 @@
+@@ -807,7 +864,7 @@ p_b_cclass(struct parse *p, cset *cs)
wctype_t wct;
char clname[16];
NEXT();
len = p->next - sp;
if (len >= sizeof(clname) - 1) {
-@@ -832,7 +889,7 @@
+@@ -816,7 +873,7 @@ p_b_cclass(struct parse *p, cset *cs)
}
memcpy(clname, sp, len);
clname[len] = '\0';
SETERROR(REG_ECTYPE);
return;
}
-@@ -842,16 +899,40 @@
+@@ -826,14 +883,38 @@ p_b_cclass(struct parse *p, cset *cs)
/*
- p_b_eclass - parse an equivalence-class name and deal with it
== static void p_b_eclass(struct parse *p, cset *cs);
- * This implementation is incomplete. xxx
*/
static void
- p_b_eclass(p, cs)
- struct parse *p;
- cset *cs;
+ p_b_eclass(struct parse *p, cset *cs)
{
- wint_t c;
-
c = p_b_coll_elem(p, '=');
CHadd(p, cs, c);
}
-@@ -889,7 +970,7 @@
- struct cname *cp;
+@@ -866,10 +947,10 @@ p_b_coll_elem(struct parse *p,
+ wint_t endc) /* name ended by endc,']' */
+ {
+ char *sp = p->next;
+- struct cname *cp;
++ const struct cname *cp;
int len;
mbstate_t mbs;
- wchar_t wc;
size_t clen;
while (MORE() && !SEETWO(endc, ']'))
-@@ -903,9 +984,10 @@
+@@ -883,9 +964,10 @@ p_b_coll_elem(struct parse *p,
if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
return(cp->code); /* known name */
memset(&mbs, 0, sizeof(mbs));
SETERROR(REG_ILLSEQ);
else
SETERROR(REG_ECOLLATE); /* neither */
-@@ -914,17 +996,18 @@
+@@ -894,16 +976,16 @@ p_b_coll_elem(struct parse *p,
/*
- othercase - return the case counterpart of an alphabetic
- == static char othercase(int ch);
-+ == static char othercase(int ch, locale_t loc);
++ == static char othercase(wint_t ch, locale_t loc);
*/
static wint_t /* if no counterpart, return ch */
--othercase(ch)
-+othercase(ch, loc)
- wint_t ch;
-+locale_t loc;
+-othercase(wint_t ch)
++othercase(wint_t ch, locale_t loc)
{
- assert(iswalpha(ch));
- if (iswupper(ch))
else /* peculiar, but could happen */
return(ch);
}
-@@ -946,10 +1029,10 @@
+@@ -923,10 +1005,10 @@ bothcases(struct parse *p, wint_t ch)
size_t n;
mbstate_t mbs;
assert(n != (size_t)-1);
bracket[n] = ']';
bracket[n + 1] = '\0';
-@@ -971,7 +1054,7 @@
+@@ -946,7 +1028,7 @@ ordinary(struct parse *p, wint_t ch)
{
cset *cs;
bothcases(p, ch);
else if ((ch & OPDMASK) == ch)
EMIT(OCHAR, ch);
-@@ -1039,10 +1122,22 @@
+@@ -1012,10 +1094,22 @@ repeat(struct parse *p,
switch (REP(MAP(from), MAP(to))) {
case REP(0, 0): /* must be user doing this */
DROP(finish-start); /* drop the operand */
/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
INSERT(OCH_, start); /* offset is wrong... */
repeat(p, start+1, 1, to);
-@@ -1056,6 +1151,10 @@
+@@ -1029,6 +1123,10 @@ repeat(struct parse *p,
/* done */
break;
case REP(1, N): /* as x?x{1,n-1} */
/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
INSERT(OCH_, start);
ASTERN(OOR1, start);
-@@ -1063,6 +1162,7 @@
+@@ -1036,6 +1134,7 @@ repeat(struct parse *p,
EMIT(OOR2, 0); /* offset very wrong... */
AHEAD(THERE()); /* ...so fix it */
ASTERN(O_CH, THERETHERE());
copy = dupl(p, start+1, finish+1);
assert(copy == finish+4);
repeat(p, copy, 1, to-1);
-@@ -1099,7 +1199,7 @@
+@@ -1071,7 +1170,7 @@ wgetnext(struct parse *p)
size_t n;
memset(&mbs, 0, sizeof(mbs));
if (n == (size_t)-1 || n == (size_t)-2) {
SETERROR(REG_ILLSEQ);
return (0);
-@@ -1172,13 +1272,14 @@
+@@ -1139,12 +1238,12 @@ freeset(struct parse *p, cset *cs)
- returning it if so, otherwise returning OUT.
*/
static wint_t
--singleton(cs)
-+singleton(cs, loc)
- cset *cs;
-+locale_t loc;
+-singleton(cset *cs)
++singleton(cset *cs, locale_t loc)
{
wint_t i, s, n;
n++;
s = i;
}
-@@ -1215,9 +1316,9 @@
+@@ -1178,9 +1277,9 @@ CHadd(struct parse *p, cset *cs, wint_t
cs->wides[cs->nwides++] = ch;
}
if (cs->icase) {
cs->bmp[nch >> 3] |= 1 << (nch & 7);
}
}
-@@ -1262,7 +1363,7 @@
+@@ -1219,7 +1318,7 @@ CHaddtype(struct parse *p, cset *cs, wct
wctype_t *newtypes;
for (i = 0; i < NC; i++)
CHadd(p, cs, i);
newtypes = realloc(cs->types, (cs->ntypes + 1) *
sizeof(*cs->types));
-@@ -1451,6 +1552,7 @@
+@@ -1391,6 +1490,7 @@ findmust(struct parse *p, struct re_guts
char buf[MB_LEN_MAX];
size_t clen;
mbstate_t mbs;
/* avoid making error situations worse */
if (p->error != 0)
-@@ -1461,8 +1563,8 @@
+@@ -1401,8 +1501,8 @@ findmust(struct parse *p, struct re_guts
* multibyte character strings, but it's safe for at least
* UTF-8 (see RFC 3629).
*/
return;
/* find the longest OCHAR sequence in strip */
-@@ -1478,7 +1580,7 @@
+@@ -1418,7 +1518,7 @@ findmust(struct parse *p, struct re_guts
memset(&mbs, 0, sizeof(mbs));
newstart = scan - 1;
}
if (clen == (size_t)-1)
goto toohard;
newlen += clen;
-@@ -1597,7 +1699,7 @@
+@@ -1537,7 +1637,7 @@ findmust(struct parse *p, struct re_guts
while (cp < g->must + g->mlen) {
while (OP(s = *scan++) != OCHAR)
continue;
* 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.
static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/regerror.c,v 1.9 2004/07/12 06:07:26 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/regerror.c,v 1.11 2007/06/11 03:05:54 delphij Exp $");
#include <sys/types.h>
#include <stdio.h>
*/
/* ARGSUSED */
size_t
-regerror(errcode, preg, errbuf, errbuf_size)
-int errcode;
-const regex_t * __restrict preg;
-char * __restrict errbuf;
-size_t errbuf_size;
+regerror(int errcode,
+ const regex_t * __restrict preg,
+ char * __restrict errbuf,
+ size_t errbuf_size)
{
struct rerr *r;
size_t len;
== static char *regatoi(const regex_t *preg, char *localbuf);
*/
static char *
-regatoi(preg, localbuf)
-const regex_t *preg;
-char *localbuf;
+regatoi(const regex_t *preg, char *localbuf)
{
struct rerr *r;
--- /dev/null
+--- regerror.c.orig 2010-05-05 14:42:17.000000000 -0700
++++ regerror.c 2010-05-05 14:42:24.000000000 -0700
+@@ -85,10 +85,10 @@ static char *regatoi(const regex_t *preg
+ = #define REG_ATOI 255 // convert name to number (!)
+ = #define REG_ITOA 0400 // convert number to name (!)
+ */
+-static struct rerr {
++static const struct rerr {
+ int code;
+- char *name;
+- char *explain;
++ const char *name;
++ const char *explain;
+ } rerrs[] = {
+ {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
+ {REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
+@@ -122,10 +122,10 @@ const regex_t * __restrict preg;
+ char * __restrict errbuf;
+ size_t errbuf_size;
+ {
+- struct rerr *r;
++ const struct rerr *r;
+ size_t len;
+ int target = errcode &~ REG_ITOA;
+- char *s;
++ const char *s;
+ char convbuf[50];
+
+ if (errcode == REG_ATOI)
+@@ -168,7 +168,7 @@ regatoi(preg, localbuf)
+ const regex_t *preg;
+ char *localbuf;
+ {
+- struct rerr *r;
++ const struct rerr *r;
+
+ for (r = rerrs; r->code != 0; r++)
+ if (strcmp(r->name, preg->re_endp) == 0)
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)regex.3 8.4 (Berkeley) 3/20/94
-.\" $FreeBSD: src/lib/libc/regex/regex.3,v 1.17 2004/07/12 11:03:42 tjr Exp $
+.\" $FreeBSD: src/lib/libc/regex/regex.3,v 1.21 2007/01/09 00:28:04 imp Exp $
.\"
-.Dd July 12, 2004
+.Dd August 17, 2005
.Dt REGEX 3
.Os
.Sh NAME
limiting the length (including the NUL) to at most
.Fa errbuf_size
bytes.
-If the whole message won't fit,
+If the whole message will not fit,
as much of it as will fit before the terminating NUL is supplied.
In any case,
the returned value is the size of buffer needed to hold the whole
beginning and ending subexpressions in obsolete
.Pq Dq basic
REs are anchors, not ordinary characters.
-.Sh SEE ALSO
-.Xr grep 1 ,
-.Xr re_format 7
-.Pp
-.St -p1003.2 ,
-sections 2.8 (Regular Expression Notation)
-and
-B.5 (C Binding for Regular Expression Matching).
.Sh DIAGNOSTICS
Non-zero error codes from
.Fn regcomp
.It Dv REG_EMPTY
empty (sub)expression
.It Dv REG_ASSERT
-can't happen - you found a bug
+cannot happen - you found a bug
.It Dv REG_INVARG
invalid argument, e.g.\& negative-length string
.It Dv REG_ILLSEQ
illegal byte sequence (bad multibyte character)
.El
+.Sh SEE ALSO
+.Xr grep 1 ,
+.Xr re_format 7
+.Pp
+.St -p1003.2 ,
+sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
.Sh HISTORY
Originally written by
.An Henry Spencer .
is
a special character only in the presence of a previous unmatched
.Ql (\& .
-This can't be fixed until the spec is fixed.
+This cannot be fixed until the spec is fixed.
.Pp
The standard's definition of back references is vague.
For example, does
.Pp
The implementation of word-boundary matching is a bit of a kludge,
and bugs may lurk in combinations of word-boundary matching and anchoring.
+.Pp
+Word-boundary matching does not work properly in multibyte locales.
---- regex.3 2004-11-25 11:38:32.000000000 -0800
-+++ regex.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -41,8 +41,8 @@
+--- regex.3.bsdnew 2009-11-11 11:29:04.000000000 -0800
++++ regex.3 2009-11-11 11:29:04.000000000 -0800
+@@ -37,8 +37,8 @@
.Os
.Sh NAME
.Nm regcomp ,
.Nm regfree
.Nd regular-expression library
.Sh LIBRARY
-@@ -51,20 +51,29 @@
+@@ -47,20 +47,29 @@
.In regex.h
.Ft int
.Fo regcomp
.Sh DESCRIPTION
These routines implement
.St -p1003.2
-@@ -75,12 +84,11 @@
+@@ -71,12 +80,11 @@ see
The
.Fn regcomp
function
* 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.
* SUCH DAMAGE.
*
* @(#)regex2.h 8.4 (Berkeley) 3/20/94
- * $FreeBSD: src/lib/libc/regex/regex2.h,v 1.8 2004/07/12 07:35:59 tjr Exp $
+ * $FreeBSD: src/lib/libc/regex/regex2.h,v 1.11 2007/01/09 00:28:04 imp Exp $
*/
/*
} cset;
static int
-CHIN1(cs, ch)
-cset *cs;
-wint_t ch;
+CHIN1(cset *cs, wint_t ch)
{
int i;
}
static __inline int
-CHIN(cs, ch)
-cset *cs;
-wint_t ch;
+CHIN(cset *cs, wint_t ch)
{
assert(ch >= 0);
};
/* misc utilities */
-#define OUT (-2) /* a non-character value */
+#define OUT (CHAR_MIN - 1) /* a non-character value */
#define ISWORD(c) (iswalnum((uch)(c)) || (c) == '_')
---- regex2.h.orig 2005-04-19 14:43:24.000000000 -0700
-+++ regex2.h 2005-04-19 14:41:08.000000000 -0700
-@@ -124,16 +124,26 @@
+--- regex2.h.bsdnew 2009-11-11 11:29:04.000000000 -0800
++++ regex2.h 2009-11-11 12:18:35.000000000 -0800
+@@ -120,14 +120,23 @@ typedef struct {
int nranges;
int invert;
int icase;
+#include "collate.h"
+
static int
--CHIN1(cs, ch)
-+CHIN1(cs, ch, loc)
- cset *cs;
- wint_t ch;
-+locale_t loc;
+-CHIN1(cset *cs, wint_t ch)
++CHIN1(cset *cs, wint_t ch, locale_t loc)
{
int i;
if (ch < NC)
return (((cs->bmp[ch >> 3] & (1 << (ch & 7))) != 0) ^
cs->invert);
-@@ -144,26 +154,27 @@
+@@ -138,24 +147,24 @@ CHIN1(cset *cs, wint_t ch)
if (cs->ranges[i].min <= ch && ch <= cs->ranges[i].max)
return (!cs->invert);
for (i = 0; i < cs->ntypes; i++)
}
static __inline int
--CHIN(cs, ch)
-+CHIN(cs, ch, loc)
- cset *cs;
- wint_t ch;
-+locale_t loc;
+-CHIN(cset *cs, wint_t ch)
++CHIN(cset *cs, wint_t ch, locale_t loc)
{
assert(ch >= 0);
}
/*
-@@ -193,8 +204,9 @@
+@@ -185,8 +194,9 @@ struct re_guts {
size_t nsub; /* copy of re_nsub */
int backrefs; /* does it use back references? */
sopno nplus; /* how deep does it nest +s? */
};
/* misc utilities */
--#define OUT (-2) /* a non-character value */
+-#define OUT (CHAR_MIN - 1) /* a non-character value */
-#define ISWORD(c) (iswalnum((uch)(c)) || (c) == '_')
-+#define OUT (-130) /* a non-character value */
++#define OUT (CHAR_MIN - 2) /* a non-character value */
+#define ISWORD(c,l) (iswalnum_l((uch)(c), l) || (c) == '_')
* 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.
static char sccsid[] = "@(#)regexec.c 8.3 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/regexec.c,v 1.6 2004/07/12 07:35:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/regexec.c,v 1.8 2007/06/11 03:05:54 delphij Exp $");
/*
* the outer shell of regexec()
static int nope __unused = 0; /* for use in asserts; shuts lint up */
static __inline size_t
-xmbrtowc(wi, s, n, mbs, dummy)
-wint_t *wi;
-const char *s;
-size_t n;
-mbstate_t *mbs;
-wint_t dummy;
+xmbrtowc(wint_t *wi, const char *s, size_t n, mbstate_t *mbs, wint_t dummy)
{
size_t nr;
wchar_t wc;
}
static __inline size_t
-xmbrtowc_dummy(wi, s, n, mbs, dummy)
-wint_t *wi;
-const char *s;
-size_t n __unused;
-mbstate_t *mbs __unused;
-wint_t dummy __unused;
+xmbrtowc_dummy(wint_t *wi,
+ const char *s,
+ size_t n __unused,
+ mbstate_t *mbs __unused,
+ wint_t dummy __unused)
{
if (wi != NULL)
* have been prototyped.
*/
int /* 0 success, REG_NOMATCH failure */
-regexec(preg, string, nmatch, pmatch, eflags)
-const regex_t * __restrict preg;
-const char * __restrict string;
-size_t nmatch;
-regmatch_t pmatch[__restrict];
-int eflags;
+regexec(const regex_t * __restrict preg,
+ const char * __restrict string,
+ size_t nmatch,
+ regmatch_t pmatch[__restrict],
+ int eflags)
{
struct re_guts *g = preg->re_g;
#ifdef REDEBUG
---- regexec.c.orig 2004-11-25 11:38:33.000000000 -0800
-+++ regexec.c 2005-02-24 14:20:50.000000000 -0800
-@@ -43,6 +43,8 @@
+--- regexec.c.bsdnew 2009-11-11 11:29:04.000000000 -0800
++++ regexec.c 2009-11-11 12:21:46.000000000 -0800
+@@ -39,6 +39,8 @@ static char sccsid[] = "@(#)regexec.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/regex/regexec.c,v 1.6 2004/07/12 07:35:59 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/regex/regexec.c,v 1.8 2007/06/11 03:05:54 delphij Exp $");
+#include "xlocale_private.h"
+
/*
* the outer shell of regexec()
*
-@@ -66,17 +68,18 @@
+@@ -62,12 +64,12 @@ __FBSDID("$FreeBSD: src/lib/libc/regex/r
static int nope __unused = 0; /* for use in asserts; shuts lint up */
static __inline size_t
--xmbrtowc(wi, s, n, mbs, dummy)
-+xmbrtowc(wi, s, n, mbs, dummy, loc)
- wint_t *wi;
- const char *s;
- size_t n;
- mbstate_t *mbs;
- wint_t dummy;
-+locale_t loc;
+-xmbrtowc(wint_t *wi, const char *s, size_t n, mbstate_t *mbs, wint_t dummy)
++xmbrtowc(wint_t *wi, const char *s, size_t n, mbstate_t *mbs, wint_t dummy, locale_t loc)
{
size_t nr;
wchar_t wc;
if (wi != NULL)
*wi = wc;
if (nr == 0)
-@@ -91,12 +94,13 @@
- }
-
- static __inline size_t
--xmbrtowc_dummy(wi, s, n, mbs, dummy)
-+xmbrtowc_dummy(wi, s, n, mbs, dummy, loc)
- wint_t *wi;
- const char *s;
- size_t n __unused;
- mbstate_t *mbs __unused;
- wint_t dummy __unused;
-+locale_t loc;
+@@ -86,7 +88,8 @@ xmbrtowc_dummy(wint_t *wi,
+ const char *s,
+ size_t n __unused,
+ mbstate_t *mbs __unused,
+- wint_t dummy __unused)
++ wint_t dummy __unused,
++ locale_t loc __unused)
{
if (wi != NULL)
-@@ -186,6 +190,8 @@
+@@ -176,6 +179,8 @@ xmbrtowc_dummy(wint_t *wi,
/* function names */
#define LNAMES /* flag */
#include "engine.c"
/* multibyte character & large states version */
-@@ -235,7 +241,8 @@
+@@ -224,7 +229,8 @@ regexec(const regex_t * __restrict preg,
return(REG_BADPAT);
eflags = GOODFLAGS(eflags);
* 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.
static char sccsid[] = "@(#)regfree.c 8.3 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/regfree.c,v 1.6 2004/07/12 07:35:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/regfree.c,v 1.8 2007/06/11 03:05:54 delphij Exp $");
#include <sys/types.h>
#include <stdio.h>
= extern void regfree(regex_t *);
*/
void
-regfree(preg)
-regex_t *preg;
+regfree(regex_t *preg)
{
struct re_guts *g;
int i;
---- regfree.c.orig 2004-11-25 11:38:33.000000000 -0800
-+++ regfree.c 2005-04-04 15:16:04.000000000 -0700
-@@ -81,6 +81,7 @@
+--- regfree.c.bsdnew 2009-11-11 11:29:04.000000000 -0800
++++ regfree.c 2009-11-11 11:29:04.000000000 -0800
+@@ -76,6 +76,7 @@ regfree(regex_t *preg)
free(g->sets[i].ranges);
free(g->sets[i].wides);
free(g->sets[i].types);
* 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.
* SUCH DAMAGE.
*
* @(#)utils.h 8.3 (Berkeley) 3/20/94
- * $FreeBSD: src/lib/libc/regex/utils.h,v 1.2 2002/03/22 23:41:56 obrien Exp $
+ * $FreeBSD: src/lib/libc/regex/utils.h,v 1.3 2007/01/09 00:28:04 imp Exp $
*/
/* utility definitions */
+++ /dev/null
-./cname.h
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * 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.
+ * 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.
+ *
+ * @(#)cname.h 8.3 (Berkeley) 3/20/94
+ * $FreeBSD: src/lib/libc/regex/cname.h,v 1.4 2007/01/09 00:28:04 imp Exp $
+ */
+
+/* character-name table */
+static const struct cname {
+ const char *name;
+ char code;
+} cnames[] = {
+ {"NUL", '\0'},
+ {"SOH", '\001'},
+ {"STX", '\002'},
+ {"ETX", '\003'},
+ {"EOT", '\004'},
+ {"ENQ", '\005'},
+ {"ACK", '\006'},
+ {"BEL", '\007'},
+ {"alert", '\007'},
+ {"BS", '\010'},
+ {"backspace", '\b'},
+ {"HT", '\011'},
+ {"tab", '\t'},
+ {"LF", '\012'},
+ {"newline", '\n'},
+ {"VT", '\013'},
+ {"vertical-tab", '\v'},
+ {"FF", '\014'},
+ {"form-feed", '\f'},
+ {"CR", '\015'},
+ {"carriage-return", '\r'},
+ {"SO", '\016'},
+ {"SI", '\017'},
+ {"DLE", '\020'},
+ {"DC1", '\021'},
+ {"DC2", '\022'},
+ {"DC3", '\023'},
+ {"DC4", '\024'},
+ {"NAK", '\025'},
+ {"SYN", '\026'},
+ {"ETB", '\027'},
+ {"CAN", '\030'},
+ {"EM", '\031'},
+ {"SUB", '\032'},
+ {"ESC", '\033'},
+ {"IS4", '\034'},
+ {"FS", '\034'},
+ {"IS3", '\035'},
+ {"GS", '\035'},
+ {"IS2", '\036'},
+ {"RS", '\036'},
+ {"IS1", '\037'},
+ {"US", '\037'},
+ {"space", ' '},
+ {"exclamation-mark", '!'},
+ {"quotation-mark", '"'},
+ {"number-sign", '#'},
+ {"dollar-sign", '$'},
+ {"percent-sign", '%'},
+ {"ampersand", '&'},
+ {"apostrophe", '\''},
+ {"left-parenthesis", '('},
+ {"right-parenthesis", ')'},
+ {"asterisk", '*'},
+ {"plus-sign", '+'},
+ {"comma", ','},
+ {"hyphen", '-'},
+ {"hyphen-minus", '-'},
+ {"period", '.'},
+ {"full-stop", '.'},
+ {"slash", '/'},
+ {"solidus", '/'},
+ {"zero", '0'},
+ {"one", '1'},
+ {"two", '2'},
+ {"three", '3'},
+ {"four", '4'},
+ {"five", '5'},
+ {"six", '6'},
+ {"seven", '7'},
+ {"eight", '8'},
+ {"nine", '9'},
+ {"colon", ':'},
+ {"semicolon", ';'},
+ {"less-than-sign", '<'},
+ {"equals-sign", '='},
+ {"greater-than-sign", '>'},
+ {"question-mark", '?'},
+ {"commercial-at", '@'},
+ {"left-square-bracket", '['},
+ {"backslash", '\\'},
+ {"reverse-solidus", '\\'},
+ {"right-square-bracket",']'},
+ {"circumflex", '^'},
+ {"circumflex-accent", '^'},
+ {"underscore", '_'},
+ {"low-line", '_'},
+ {"grave-accent", '`'},
+ {"left-brace", '{'},
+ {"left-curly-bracket", '{'},
+ {"vertical-line", '|'},
+ {"right-brace", '}'},
+ {"right-curly-bracket", '}'},
+ {"tilde", '~'},
+ {"DEL", '\177'},
+ {NULL, 0}
+};
--- /dev/null
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * 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.
+ * 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.
+ *
+ * @(#)cname.h 8.3 (Berkeley) 3/20/94
+ * $FreeBSD: src/lib/libc/regex/cname.h,v 1.4 2007/01/09 00:28:04 imp Exp $
+ */
+
+/* character-name table */
+static struct cname {
+ char *name;
+ char code;
+} cnames[] = {
+ {"NUL", '\0'},
+ {"SOH", '\001'},
+ {"STX", '\002'},
+ {"ETX", '\003'},
+ {"EOT", '\004'},
+ {"ENQ", '\005'},
+ {"ACK", '\006'},
+ {"BEL", '\007'},
+ {"alert", '\007'},
+ {"BS", '\010'},
+ {"backspace", '\b'},
+ {"HT", '\011'},
+ {"tab", '\t'},
+ {"LF", '\012'},
+ {"newline", '\n'},
+ {"VT", '\013'},
+ {"vertical-tab", '\v'},
+ {"FF", '\014'},
+ {"form-feed", '\f'},
+ {"CR", '\015'},
+ {"carriage-return", '\r'},
+ {"SO", '\016'},
+ {"SI", '\017'},
+ {"DLE", '\020'},
+ {"DC1", '\021'},
+ {"DC2", '\022'},
+ {"DC3", '\023'},
+ {"DC4", '\024'},
+ {"NAK", '\025'},
+ {"SYN", '\026'},
+ {"ETB", '\027'},
+ {"CAN", '\030'},
+ {"EM", '\031'},
+ {"SUB", '\032'},
+ {"ESC", '\033'},
+ {"IS4", '\034'},
+ {"FS", '\034'},
+ {"IS3", '\035'},
+ {"GS", '\035'},
+ {"IS2", '\036'},
+ {"RS", '\036'},
+ {"IS1", '\037'},
+ {"US", '\037'},
+ {"space", ' '},
+ {"exclamation-mark", '!'},
+ {"quotation-mark", '"'},
+ {"number-sign", '#'},
+ {"dollar-sign", '$'},
+ {"percent-sign", '%'},
+ {"ampersand", '&'},
+ {"apostrophe", '\''},
+ {"left-parenthesis", '('},
+ {"right-parenthesis", ')'},
+ {"asterisk", '*'},
+ {"plus-sign", '+'},
+ {"comma", ','},
+ {"hyphen", '-'},
+ {"hyphen-minus", '-'},
+ {"period", '.'},
+ {"full-stop", '.'},
+ {"slash", '/'},
+ {"solidus", '/'},
+ {"zero", '0'},
+ {"one", '1'},
+ {"two", '2'},
+ {"three", '3'},
+ {"four", '4'},
+ {"five", '5'},
+ {"six", '6'},
+ {"seven", '7'},
+ {"eight", '8'},
+ {"nine", '9'},
+ {"colon", ':'},
+ {"semicolon", ';'},
+ {"less-than-sign", '<'},
+ {"equals-sign", '='},
+ {"greater-than-sign", '>'},
+ {"question-mark", '?'},
+ {"commercial-at", '@'},
+ {"left-square-bracket", '['},
+ {"backslash", '\\'},
+ {"reverse-solidus", '\\'},
+ {"right-square-bracket",']'},
+ {"circumflex", '^'},
+ {"circumflex-accent", '^'},
+ {"underscore", '_'},
+ {"low-line", '_'},
+ {"grave-accent", '`'},
+ {"left-brace", '{'},
+ {"left-curly-bracket", '{'},
+ {"vertical-line", '|'},
+ {"right-brace", '}'},
+ {"right-curly-bracket", '}'},
+ {"tilde", '~'},
+ {"DEL", '\177'},
+ {NULL, 0}
+};
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/engine.c,v 1.14 2004/07/12 07:35:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/engine.c,v 1.23 2009/09/16 06:32:23 dds Exp $");
/*
* The matching engine and friends. This file is #included by regexec.c
struct re_guts *g;
int eflags;
regmatch_t *pmatch; /* [nsub+1] (0 element unused) */
- char *offp; /* offsets work from here */
- char *beginp; /* start of string -- virtual NUL precedes */
- char *endp; /* end of string -- virtual NUL here */
- char *coldp; /* can be no match starting before here */
- char **lastpos; /* [nplus+1] */
+ const char *offp; /* offsets work from here */
+ const char *beginp; /* start of string -- virtual NUL precedes */
+ const char *endp; /* end of string -- virtual NUL here */
+ const char *coldp; /* can be no match starting before here */
+ const char **lastpos; /* [nplus+1] */
STATEVARS;
states st; /* current states */
states fresh; /* states for a fresh start */
#endif
/* === engine.c === */
-static int matcher(struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
-static char *dissect(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *backref(struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);
-static char *fast(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
-static char *slow(struct match *m, char *start, char *stop, sopno startst, sopno stopst);
+static int matcher(struct re_guts *g, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static const char *dissect(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *backref(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst, sopno lev, int);
+static const char *fast(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *slow(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
static states step(struct re_guts *g, sopno start, sopno stop, states bef, wint_t ch, states aft);
+#define MAX_RECURSION 100
#define BOL (OUT-1)
#define EOL (BOL-1)
#define BOLEOL (BOL-2)
#define BADCHAR (BOL-6)
#define NONCHAR(c) ((c) <= OUT)
#ifdef REDEBUG
-static void print(struct match *m, char *caption, states st, int ch, FILE *d);
+static void print(struct match *m, const char *caption, states st, int ch, FILE *d);
#endif
#ifdef REDEBUG
-static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst);
+static void at(struct match *m, const char *title, const char *start, const char *stop, sopno startst, sopno stopst);
#endif
#ifdef REDEBUG
-static char *pchar(int ch);
+static const char *pchar(int ch);
#endif
#ifdef __cplusplus
/*
- matcher - the actual matching engine
- == static int matcher(struct re_guts *g, char *string, \
+ == static int matcher(struct re_guts *g, const char *string, \
== size_t nmatch, regmatch_t pmatch[], int eflags);
*/
static int /* 0 success, REG_NOMATCH failure */
-matcher(g, string, nmatch, pmatch, eflags)
-struct re_guts *g;
-char *string;
-size_t nmatch;
-regmatch_t pmatch[];
-int eflags;
+matcher(struct re_guts *g,
+ const char *string,
+ size_t nmatch,
+ regmatch_t pmatch[],
+ int eflags)
{
- char *endp;
+ const char *endp;
int i;
struct match mv;
struct match *m = &mv;
- char *dp;
+ const char *dp;
const sopno gf = g->firststate+1; /* +1 for OEND */
const sopno gl = g->laststate;
- char *start;
- char *stop;
+ const char *start;
+ const char *stop;
/* Boyer-Moore algorithms variables */
- char *pp;
+ const char *pp;
int cj, mj;
- char *mustfirst;
- char *mustlast;
+ const char *mustfirst;
+ const char *mustlast;
int *matchjump;
int *charjump;
if (g->moffset > -1)
start = ((dp - g->moffset) < start) ? start : dp - g->moffset;
+ SP("mloop", m->st, *start);
+
/* this loop does only one repetition except for backrefs */
for (;;) {
endp = fast(m, start, stop, gf, gl);
if (endp == NULL) { /* a miss */
+ if (m->pmatch != NULL)
+ free((char *)m->pmatch);
+ if (m->lastpos != NULL)
+ free((char *)m->lastpos);
STATETEARDOWN(m);
return(REG_NOMATCH);
}
dp = dissect(m, m->coldp, endp, gf, gl);
} else {
if (g->nplus > 0 && m->lastpos == NULL)
- m->lastpos = (char **)malloc((g->nplus+1) *
- sizeof(char *));
+ m->lastpos = malloc((g->nplus+1) *
+ sizeof(const char *));
if (g->nplus > 0 && m->lastpos == NULL) {
free(m->pmatch);
STATETEARDOWN(m);
return(REG_ESPACE);
}
NOTE("backref dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
}
if (dp != NULL)
break;
}
#endif
NOTE("backoff dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
}
assert(dp == NULL || dp == endp);
if (dp != NULL) /* found a shorter one */
NOTE("false alarm");
/* recycle starting later */
start = m->coldp + XMBRTOWC(NULL, m->coldp,
- m->endp - m->coldp, &m->mbs, 0, g->loc);
+ stop - m->coldp, &m->mbs, 0, g->loc);
assert(start <= stop);
}
/*
- dissect - figure out what matched what, no back references
- == static char *dissect(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst);
+ == static const char *dissect(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
*/
-static char * /* == stop (success) always */
-dissect(m, start, stop, startst, stopst)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char * /* == stop (success) always */
+dissect(struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
int i;
sopno ss; /* start sop of current subRE */
sopno es; /* end sop of current subRE */
- char *sp; /* start of string matched by it */
- char *stp; /* string matched by it cannot pass here */
- char *rest; /* start of rest of string */
- char *tail; /* string unmatched by rest of RE */
+ const char *sp; /* start of string matched by it */
+ const char *stp; /* string matched by it cannot pass here */
+ const char *rest; /* start of rest of string */
+ const char *tail; /* string unmatched by rest of RE */
sopno ssub; /* start sop of subsubRE */
sopno esub; /* end sop of subsubRE */
- char *ssp; /* start of string matched by subsubRE */
- char *sep; /* end of string matched by subsubRE */
- char *oldssp; /* previous ssp */
- char *dp;
+ const char *ssp; /* start of string matched by subsubRE */
+ const char *sep; /* end of string matched by subsubRE */
+ const char *oldssp; /* previous ssp */
+ const char *dp;
AT("diss", start, stop, startst, stopst);
sp = start;
/*
- backref - figure out what matched what, figuring in back references
- == static char *backref(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst, sopno lev);
+ == static const char *backref(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst, sopno lev);
*/
-static char * /* == stop (success) or NULL (failure) */
-backref(m, start, stop, startst, stopst, lev)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
-sopno lev; /* PLUS nesting level */
+static const char * /* == stop (success) or NULL (failure) */
+backref(struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst,
+ sopno lev, /* PLUS nesting level */
+ int rec)
{
int i;
sopno ss; /* start sop of current subRE */
- char *sp; /* start of string matched by it */
+ const char *sp; /* start of string matched by it */
sopno ssub; /* start sop of subsubRE */
sopno esub; /* end sop of subsubRE */
- char *ssp; /* start of string matched by subsubRE */
- char *dp;
+ const char *ssp; /* start of string matched by subsubRE */
+ const char *dp;
size_t len;
int hard;
sop s;
return(NULL);
assert(m->pmatch[i].rm_so != -1);
len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+ if (len == 0 && rec++ > MAX_RECURSION)
+ return(NULL);
assert(stop - m->beginp >= len);
if (sp > stop - len)
return(NULL); /* not enough left to match */
return(NULL);
while (m->g->strip[ss] != SOP(O_BACK, i))
ss++;
- return(backref(m, sp+len, stop, ss+1, stopst, lev));
+ return(backref(m, sp+len, stop, ss+1, stopst, lev, rec));
break;
case OQUEST_: /* to null or not */
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
if (dp != NULL)
return(dp); /* not */
- return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
+ return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec));
break;
case OPLUS_:
assert(m->lastpos != NULL);
assert(lev+1 <= m->g->nplus);
m->lastpos[lev+1] = sp;
- return(backref(m, sp, stop, ss+1, stopst, lev+1));
+ return(backref(m, sp, stop, ss+1, stopst, lev+1, rec));
break;
case O_PLUS:
if (sp == m->lastpos[lev]) /* last pass matched null */
- return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
/* try another pass */
m->lastpos[lev] = sp;
- dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
+ dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec);
if (dp == NULL)
- return(backref(m, sp, stop, ss+1, stopst, lev-1));
+ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
else
return(dp);
break;
esub = ss + OPND(s) - 1;
assert(OP(m->g->strip[esub]) == OOR1);
for (;;) { /* find first matching branch */
- dp = backref(m, sp, stop, ssub, esub, lev);
+ dp = backref(m, sp, stop, ssub, esub, lev, rec);
if (dp != NULL)
return(dp);
/* that one missed, try next one */
assert(0 < i && i <= m->g->nsub);
offsave = m->pmatch[i].rm_so;
m->pmatch[i].rm_so = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
if (dp != NULL)
return(dp);
m->pmatch[i].rm_so = offsave;
assert(0 < i && i <= m->g->nsub);
offsave = m->pmatch[i].rm_eo;
m->pmatch[i].rm_eo = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev);
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
if (dp != NULL)
return(dp);
m->pmatch[i].rm_eo = offsave;
/*
- fast - step through the string at top speed
- == static char *fast(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst);
+ == static const char *fast(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
*/
-static char * /* where tentative match ended, or NULL */
-fast(m, start, stop, startst, stopst)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char * /* where tentative match ended, or NULL */
+fast( struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
states st = m->st;
states fresh = m->fresh;
states tmp = m->tmp;
- char *p = start;
+ const char *p = start;
wint_t c;
wint_t lastc; /* previous c */
wint_t flagch;
int i;
- char *coldp; /* last p after which no match was underway */
+ const char *coldp; /* last p after which no match was underway */
size_t clen;
CLEAR(st);
SET1(st, startst);
+ SP("fast", st, *p);
st = step(m->g, startst, stopst, st, NOTHING, st);
ASSIGN(fresh, st);
SP("start", st, *p);
for (;;) {
/* next character */
lastc = c;
- if (p == m->endp)
+ if (p == m->endp) {
+ clen = 0;
c = OUT;
- else
+ } else
clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR, m->g->loc);
if (EQ(st, fresh))
coldp = p;
}
/* are we done? */
- if (ISSET(st, stopst) || p == stop)
+ if (ISSET(st, stopst) || p == stop || clen > stop - p)
break; /* NOTE BREAK OUT */
/* no, we must deal with this character */
assert(coldp != NULL);
m->coldp = coldp;
if (ISSET(st, stopst))
- return(p+XMBRTOWC(NULL, p, m->endp - p, &m->mbs, 0, m->g->loc));
+ return(p+XMBRTOWC(NULL, p, stop - p, &m->mbs, 0, m->g->loc));
else
return(NULL);
}
/*
- slow - step through the string more deliberately
- == static char *slow(struct match *m, char *start, \
- == char *stop, sopno startst, sopno stopst);
+ == static const char *slow(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
*/
-static char * /* where it ended */
-slow(m, start, stop, startst, stopst)
-struct match *m;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+static const char * /* where it ended */
+slow( struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
states st = m->st;
states empty = m->empty;
states tmp = m->tmp;
- char *p = start;
+ const char *p = start;
wint_t c;
wint_t lastc; /* previous c */
wint_t flagch;
int i;
- char *matchp; /* last p at which a match ended */
+ const char *matchp; /* last p at which a match ended */
size_t clen;
AT("slow", start, stop, startst, stopst);
/* are we done? */
if (ISSET(st, stopst))
matchp = p;
- if (EQ(st, empty) || p == stop)
+ if (EQ(st, empty) || p == stop || clen > stop - p)
break; /* NOTE BREAK OUT */
/* no, we must deal with this character */
== #define NONCHAR(c) ((c) <= OUT)
*/
static states
-step(g, start, stop, bef, ch, aft)
-struct re_guts *g;
-sopno start; /* start state within strip */
-sopno stop; /* state after stop state within strip */
-states bef; /* states reachable before */
-wint_t ch; /* character or NONCHAR code */
-states aft; /* states already known reachable after */
+step(struct re_guts *g,
+ sopno start, /* start state within strip */
+ sopno stop, /* state after stop state within strip */
+ states bef, /* states reachable before */
+ wint_t ch, /* character or NONCHAR code */
+ states aft) /* states already known reachable after */
{
cset *cs;
sop s;
OP(s = g->strip[pc+look]) != O_CH;
look += OPND(s))
assert(OP(s) == OOR2);
- FWD(aft, aft, look);
+ FWD(aft, aft, look + 1);
}
break;
case OOR2: /* propagate OCH_'s marking */
/*
- print - print a set of states
== #ifdef REDEBUG
- == static void print(struct match *m, char *caption, states st, \
+ == static void print(struct match *m, const char *caption, states st, \
== int ch, FILE *d);
== #endif
*/
static void
-print(m, caption, st, ch, d)
-struct match *m;
-char *caption;
-states st;
-int ch;
-FILE *d;
+print(struct match *m,
+ const char *caption,
+ states st,
+ int ch,
+ FILE *d)
{
struct re_guts *g = m->g;
int i;
/*
- at - print current situation
== #ifdef REDEBUG
- == static void at(struct match *m, char *title, char *start, char *stop, \
- == sopno startst, sopno stopst);
+ == static void at(struct match *m, const char *title, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
== #endif
*/
static void
-at(m, title, start, stop, startst, stopst)
-struct match *m;
-char *title;
-char *start;
-char *stop;
-sopno startst;
-sopno stopst;
+at( struct match *m,
+ const char *title,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
{
if (!(m->eflags®_TRACE))
return;
/*
- pchar - make a character printable
== #ifdef REDEBUG
- == static char *pchar(int ch);
+ == static const char *pchar(int ch);
== #endif
*
* Is this identical to regchar() over in debug.c? Well, yes. But a
* a matching debug.o, and this is convenient. It all disappears in
* the non-debug compilation anyway, so it doesn't matter much.
*/
-static char * /* -> representation */
-pchar(ch)
-int ch;
+static const char * /* -> representation */
+pchar(int ch)
{
static char pbuf[10];
* 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.
static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.34 2004/10/03 15:42:59 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.36 2007/06/11 03:05:54 delphij Exp $");
#include "xlocale_private.h"
= #define REG_DUMP 0200
*/
int /* 0 success, otherwise REG_something */
-regcomp(preg, pattern, cflags)
-regex_t * __restrict preg;
-const char * __restrict pattern;
-int cflags;
+regcomp(regex_t * __restrict preg,
+ const char * __restrict pattern,
+ int cflags)
{
struct parse pa;
struct re_guts *g;
== static void p_ere(struct parse *p, int stop);
*/
static void
-p_ere(p, stop)
-struct parse *p;
-int stop; /* character this ERE should end at */
+p_ere(struct parse *p,
+ int stop) /* character this ERE should end at */
{
char c;
sopno prevback;
== static void p_ere_exp(struct parse *p);
*/
static void
-p_ere_exp(p)
-struct parse *p;
+p_ere_exp(struct parse *p)
{
char c;
wint_t wc;
== static void p_str(struct parse *p);
*/
static void
-p_str(p)
-struct parse *p;
+p_str(struct parse *p)
{
#if __DARWIN_UNIX03
if (!p->zerorepeats) REQUIRE(MORE(), REG_EMPTY);
* The amount of lookahead needed to avoid this kludge is excessive.
*/
static void
-p_bre(p, end1, end2)
-struct parse *p;
-int end1; /* first terminating character */
-int end2; /* second terminating character */
+p_bre(struct parse *p,
+ int end1, /* first terminating character */
+ int end2) /* second terminating character */
{
sopno start = HERE();
int first = 1; /* first subexpression? */
== static int p_simp_re(struct parse *p, int starordinary);
*/
static int /* was the simple RE an unbackslashed $? */
-p_simp_re(p, starordinary)
-struct parse *p;
-int starordinary; /* is a leading * an ordinary character? */
+p_simp_re(struct parse *p,
+ int starordinary) /* is a leading * an ordinary character? */
{
int c;
int count;
== static int p_count(struct parse *p);
*/
static int /* the value */
-p_count(p)
-struct parse *p;
+p_count(struct parse *p)
{
int count = 0;
int ndigits = 0;
== static void p_bracket(struct parse *p);
*/
static void
-p_bracket(p)
-struct parse *p;
+p_bracket(struct parse *p)
{
cset *cs;
wint_t ch;
== static void p_b_term(struct parse *p, cset *cs);
*/
static void
-p_b_term(p, cs)
-struct parse *p;
-cset *cs;
+p_b_term(struct parse *p, cset *cs)
{
char c;
wint_t start, finish;
== static void p_b_cclass(struct parse *p, cset *cs);
*/
static void
-p_b_cclass(p, cs)
-struct parse *p;
-cset *cs;
+p_b_cclass(struct parse *p, cset *cs)
{
char *sp = p->next;
size_t len;
== static void p_b_eclass(struct parse *p, cset *cs);
*/
static void
-p_b_eclass(p, cs)
-struct parse *p;
-cset *cs;
+p_b_eclass(struct parse *p, cset *cs)
{
char *sp = p->next;
int len, ec;
== static char p_b_symbol(struct parse *p);
*/
static wint_t /* value of symbol */
-p_b_symbol(p)
-struct parse *p;
+p_b_symbol(struct parse *p)
{
wint_t value;
== static char p_b_coll_elem(struct parse *p, int endc);
*/
static wint_t /* value of collating element */
-p_b_coll_elem(p, endc)
-struct parse *p;
-wint_t endc; /* name ended by endc,']' */
+p_b_coll_elem(struct parse *p,
+ wint_t endc) /* name ended by endc,']' */
{
char *sp = p->next;
- struct cname *cp;
+ const struct cname *cp;
int len;
mbstate_t mbs;
wchar_t wbuf[16];
/*
- othercase - return the case counterpart of an alphabetic
- == static char othercase(int ch, locale_t loc);
+ == static char othercase(wint_t ch, locale_t loc);
*/
static wint_t /* if no counterpart, return ch */
-othercase(ch, loc)
-wint_t ch;
-locale_t loc;
+othercase(wint_t ch, locale_t loc)
{
assert(iswalpha_l(ch, loc));
if (iswupper_l(ch, loc))
* Boy, is this implementation ever a kludge...
*/
static void
-bothcases(p, ch)
-struct parse *p;
-wint_t ch;
+bothcases(struct parse *p, wint_t ch)
{
char *oldnext = p->next;
char *oldend = p->end;
== static void ordinary(struct parse *p, int ch);
*/
static void
-ordinary(p, ch)
-struct parse *p;
-wint_t ch;
+ordinary(struct parse *p, wint_t ch)
{
cset *cs;
* Boy, is this implementation ever a kludge...
*/
static void
-nonnewline(p)
-struct parse *p;
+nonnewline(struct parse *p)
{
char *oldnext = p->next;
char *oldend = p->end;
== static void repeat(struct parse *p, sopno start, int from, int to);
*/
static void
-repeat(p, start, from, to)
-struct parse *p;
-sopno start; /* operand from here to end of strip */
-int from; /* repeated from this number */
-int to; /* to this number of times (maybe INFINITY) */
+repeat(struct parse *p,
+ sopno start, /* operand from here to end of strip */
+ int from, /* repeated from this number */
+ int to) /* to this number of times (maybe INFINITY) */
{
sopno finish = HERE();
# define N 2
- character can't be converted. Returns the number of bytes consumed.
*/
static wint_t
-wgetnext(p)
-struct parse *p;
+wgetnext(struct parse *p)
{
mbstate_t mbs;
wchar_t wc;
== static int seterr(struct parse *p, int e);
*/
static int /* useless but makes type checking happy */
-seterr(p, e)
-struct parse *p;
-int e;
+seterr(struct parse *p, int e)
{
if (p->error == 0) /* keep earliest error condition */
p->error = e;
== static cset *allocset(struct parse *p);
*/
static cset *
-allocset(p)
-struct parse *p;
+allocset(struct parse *p)
{
cset *cs, *ncs;
== static void freeset(struct parse *p, cset *cs);
*/
static void
-freeset(p, cs)
-struct parse *p;
-cset *cs;
+freeset(struct parse *p, cset *cs)
{
cset *top = &p->g->sets[p->g->ncsets];
- returning it if so, otherwise returning OUT.
*/
static wint_t
-singleton(cs, loc)
-cset *cs;
-locale_t loc;
+singleton(cset *cs, locale_t loc)
{
wint_t i, s, n;
- CHadd - add character to character set.
*/
static void
-CHadd(p, cs, ch)
-struct parse *p;
-cset *cs;
-wint_t ch;
+CHadd(struct parse *p, cset *cs, wint_t ch)
{
wint_t nch, *newwides;
assert(ch >= 0);
- CHaddrange - add all characters in the range [min,max] to a character set.
*/
static void
-CHaddrange(p, cs, min, max)
-struct parse *p;
-cset *cs;
-wint_t min, max;
+CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
{
crange *newranges;
- CHaddtype - add all characters of a certain type to a character set.
*/
static void
-CHaddtype(p, cs, wct)
-struct parse *p;
-cset *cs;
-wctype_t wct;
+CHaddtype(struct parse *p, cset *cs, wctype_t wct)
{
wint_t i;
wctype_t *newtypes;
== static sopno dupl(struct parse *p, sopno start, sopno finish);
*/
static sopno /* start of duplicate */
-dupl(p, start, finish)
-struct parse *p;
-sopno start; /* from here */
-sopno finish; /* to this less one */
+dupl(struct parse *p,
+ sopno start, /* from here */
+ sopno finish) /* to this less one */
{
sopno ret = HERE();
sopno len = finish - start;
* some changes to the data structures. Maybe later.
*/
static void
-doemit(p, op, opnd)
-struct parse *p;
-sop op;
-size_t opnd;
+doemit(struct parse *p, sop op, size_t opnd)
{
/* avoid making error situations worse */
if (p->error != 0)
== static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
*/
static void
-doinsert(p, op, opnd, pos)
-struct parse *p;
-sop op;
-size_t opnd;
-sopno pos;
+doinsert(struct parse *p, sop op, size_t opnd, sopno pos)
{
sopno sn;
sop s;
== static void dofwd(struct parse *p, sopno pos, sop value);
*/
static void
-dofwd(p, pos, value)
-struct parse *p;
-sopno pos;
-sop value;
+dofwd(struct parse *p, sopno pos, sop value)
{
/* avoid making error situations worse */
if (p->error != 0)
== static void enlarge(struct parse *p, sopno size);
*/
static void
-enlarge(p, size)
-struct parse *p;
-sopno size;
+enlarge(struct parse *p, sopno size)
{
sop *sp;
== static void stripsnug(struct parse *p, struct re_guts *g);
*/
static void
-stripsnug(p, g)
-struct parse *p;
-struct re_guts *g;
+stripsnug(struct parse *p, struct re_guts *g)
{
g->nstates = p->slen;
g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
* Note that must and mlen got initialized during setup.
*/
static void
-findmust(p, g)
-struct parse *p;
-struct re_guts *g;
+findmust(struct parse *p, struct re_guts *g)
{
sop *scan;
sop *start;
* re paths.
*/
static int
-altoffset(scan, offset)
-sop *scan;
-int offset;
+altoffset(sop *scan, int offset)
{
int largest;
int try;
* the value of the character from the text that was mismatched.
*/
static void
-computejumps(p, g)
-struct parse *p;
-struct re_guts *g;
+computejumps(struct parse *p, struct re_guts *g)
{
int ch;
int mindex;
* the search algorithm works.
*/
static void
-computematchjumps(p, g)
-struct parse *p;
-struct re_guts *g;
+computematchjumps(struct parse *p, struct re_guts *g)
{
int mindex; /* General "must" iterator */
int suffix; /* Keeps track of matching suffix */
== static sopno pluscount(struct parse *p, struct re_guts *g);
*/
static sopno /* nesting depth */
-pluscount(p, g)
-struct parse *p;
-struct re_guts *g;
+pluscount(struct parse *p, struct re_guts *g)
{
sop *scan;
sop s;
+++ /dev/null
-./regerror.c
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * 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.
+ * 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.
+ *
+ * @(#)regerror.c 8.4 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/regex/regerror.c,v 1.11 2007/06/11 03:05:54 delphij Exp $");
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi(const regex_t *preg, char *localbuf);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+/*
+ = #define REG_NOMATCH 1
+ = #define REG_BADPAT 2
+ = #define REG_ECOLLATE 3
+ = #define REG_ECTYPE 4
+ = #define REG_EESCAPE 5
+ = #define REG_ESUBREG 6
+ = #define REG_EBRACK 7
+ = #define REG_EPAREN 8
+ = #define REG_EBRACE 9
+ = #define REG_BADBR 10
+ = #define REG_ERANGE 11
+ = #define REG_ESPACE 12
+ = #define REG_BADRPT 13
+ = #define REG_EMPTY 14
+ = #define REG_ASSERT 15
+ = #define REG_INVARG 16
+ = #define REG_ILLSEQ 17
+ = #define REG_ATOI 255 // convert name to number (!)
+ = #define REG_ITOA 0400 // convert number to name (!)
+ */
+static const struct rerr {
+ int code;
+ const char *name;
+ const char *explain;
+} rerrs[] = {
+ {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
+ {REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
+ {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"},
+ {REG_ECTYPE, "REG_ECTYPE", "invalid character class"},
+ {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"},
+ {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"},
+ {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"},
+ {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"},
+ {REG_EBRACE, "REG_EBRACE", "braces not balanced"},
+ {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"},
+ {REG_ERANGE, "REG_ERANGE", "invalid character range"},
+ {REG_ESPACE, "REG_ESPACE", "out of memory"},
+ {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"},
+ {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"},
+ {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"},
+ {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"},
+ {REG_ILLSEQ, "REG_ILLSEQ", "illegal byte sequence"},
+ {0, "", "*** unknown regexp error code ***"}
+};
+
+/*
+ - regerror - the interface to error numbers
+ = extern size_t regerror(int, const regex_t *, char *, size_t);
+ */
+/* ARGSUSED */
+size_t
+regerror(int errcode,
+ const regex_t * __restrict preg,
+ char * __restrict errbuf,
+ size_t errbuf_size)
+{
+ const struct rerr *r;
+ size_t len;
+ int target = errcode &~ REG_ITOA;
+ const char *s;
+ char convbuf[50];
+
+ if (errcode == REG_ATOI)
+ s = regatoi(preg, convbuf);
+ else {
+ for (r = rerrs; r->code != 0; r++)
+ if (r->code == target)
+ break;
+
+ if (errcode®_ITOA) {
+ if (r->code != 0)
+ (void) strcpy(convbuf, r->name);
+ else
+ sprintf(convbuf, "REG_0x%x", target);
+ assert(strlen(convbuf) < sizeof(convbuf));
+ s = convbuf;
+ } else
+ s = r->explain;
+ }
+
+ len = strlen(s) + 1;
+ if (errbuf_size > 0) {
+ if (errbuf_size > len)
+ (void) strcpy(errbuf, s);
+ else {
+ (void) strncpy(errbuf, s, errbuf_size-1);
+ errbuf[errbuf_size-1] = '\0';
+ }
+ }
+
+ return(len);
+}
+
+/*
+ - regatoi - internal routine to implement REG_ATOI
+ == static char *regatoi(const regex_t *preg, char *localbuf);
+ */
+static char *
+regatoi(const regex_t *preg, char *localbuf)
+{
+ const struct rerr *r;
+
+ for (r = rerrs; r->code != 0; r++)
+ if (strcmp(r->name, preg->re_endp) == 0)
+ break;
+ if (r->code == 0)
+ return("0");
+
+ sprintf(localbuf, "%d", r->code);
+ return(localbuf);
+}
--- /dev/null
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * 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.
+ * 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.
+ *
+ * @(#)regerror.c 8.4 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/regex/regerror.c,v 1.11 2007/06/11 03:05:54 delphij Exp $");
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi(const regex_t *preg, char *localbuf);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+/*
+ = #define REG_NOMATCH 1
+ = #define REG_BADPAT 2
+ = #define REG_ECOLLATE 3
+ = #define REG_ECTYPE 4
+ = #define REG_EESCAPE 5
+ = #define REG_ESUBREG 6
+ = #define REG_EBRACK 7
+ = #define REG_EPAREN 8
+ = #define REG_EBRACE 9
+ = #define REG_BADBR 10
+ = #define REG_ERANGE 11
+ = #define REG_ESPACE 12
+ = #define REG_BADRPT 13
+ = #define REG_EMPTY 14
+ = #define REG_ASSERT 15
+ = #define REG_INVARG 16
+ = #define REG_ILLSEQ 17
+ = #define REG_ATOI 255 // convert name to number (!)
+ = #define REG_ITOA 0400 // convert number to name (!)
+ */
+static struct rerr {
+ int code;
+ char *name;
+ char *explain;
+} rerrs[] = {
+ {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
+ {REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
+ {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"},
+ {REG_ECTYPE, "REG_ECTYPE", "invalid character class"},
+ {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"},
+ {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"},
+ {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"},
+ {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"},
+ {REG_EBRACE, "REG_EBRACE", "braces not balanced"},
+ {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"},
+ {REG_ERANGE, "REG_ERANGE", "invalid character range"},
+ {REG_ESPACE, "REG_ESPACE", "out of memory"},
+ {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"},
+ {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"},
+ {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"},
+ {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"},
+ {REG_ILLSEQ, "REG_ILLSEQ", "illegal byte sequence"},
+ {0, "", "*** unknown regexp error code ***"}
+};
+
+/*
+ - regerror - the interface to error numbers
+ = extern size_t regerror(int, const regex_t *, char *, size_t);
+ */
+/* ARGSUSED */
+size_t
+regerror(int errcode,
+ const regex_t * __restrict preg,
+ char * __restrict errbuf,
+ size_t errbuf_size)
+{
+ struct rerr *r;
+ size_t len;
+ int target = errcode &~ REG_ITOA;
+ char *s;
+ char convbuf[50];
+
+ if (errcode == REG_ATOI)
+ s = regatoi(preg, convbuf);
+ else {
+ for (r = rerrs; r->code != 0; r++)
+ if (r->code == target)
+ break;
+
+ if (errcode®_ITOA) {
+ if (r->code != 0)
+ (void) strcpy(convbuf, r->name);
+ else
+ sprintf(convbuf, "REG_0x%x", target);
+ assert(strlen(convbuf) < sizeof(convbuf));
+ s = convbuf;
+ } else
+ s = r->explain;
+ }
+
+ len = strlen(s) + 1;
+ if (errbuf_size > 0) {
+ if (errbuf_size > len)
+ (void) strcpy(errbuf, s);
+ else {
+ (void) strncpy(errbuf, s, errbuf_size-1);
+ errbuf[errbuf_size-1] = '\0';
+ }
+ }
+
+ return(len);
+}
+
+/*
+ - regatoi - internal routine to implement REG_ATOI
+ == static char *regatoi(const regex_t *preg, char *localbuf);
+ */
+static char *
+regatoi(const regex_t *preg, char *localbuf)
+{
+ struct rerr *r;
+
+ for (r = rerrs; r->code != 0; r++)
+ if (strcmp(r->name, preg->re_endp) == 0)
+ break;
+ if (r->code == 0)
+ return("0");
+
+ sprintf(localbuf, "%d", r->code);
+ return(localbuf);
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)regex.3 8.4 (Berkeley) 3/20/94
-.\" $FreeBSD: src/lib/libc/regex/regex.3,v 1.17 2004/07/12 11:03:42 tjr Exp $
+.\" $FreeBSD: src/lib/libc/regex/regex.3,v 1.21 2007/01/09 00:28:04 imp Exp $
.\"
-.Dd July 12, 2004
+.Dd August 17, 2005
.Dt REGEX 3
.Os
.Sh NAME
limiting the length (including the NUL) to at most
.Fa errbuf_size
bytes.
-If the whole message won't fit,
+If the whole message will not fit,
as much of it as will fit before the terminating NUL is supplied.
In any case,
the returned value is the size of buffer needed to hold the whole
beginning and ending subexpressions in obsolete
.Pq Dq basic
REs are anchors, not ordinary characters.
-.Sh SEE ALSO
-.Xr grep 1 ,
-.Xr re_format 7
-.Pp
-.St -p1003.2 ,
-sections 2.8 (Regular Expression Notation)
-and
-B.5 (C Binding for Regular Expression Matching).
.Sh DIAGNOSTICS
Non-zero error codes from
.Fn regcomp
.It Dv REG_EMPTY
empty (sub)expression
.It Dv REG_ASSERT
-can't happen - you found a bug
+cannot happen - you found a bug
.It Dv REG_INVARG
invalid argument, e.g.\& negative-length string
.It Dv REG_ILLSEQ
illegal byte sequence (bad multibyte character)
.El
+.Sh SEE ALSO
+.Xr grep 1 ,
+.Xr re_format 7
+.Pp
+.St -p1003.2 ,
+sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
.Sh HISTORY
Originally written by
.An Henry Spencer .
is
a special character only in the presence of a previous unmatched
.Ql (\& .
-This can't be fixed until the spec is fixed.
+This cannot be fixed until the spec is fixed.
.Pp
The standard's definition of back references is vague.
For example, does
.Pp
The implementation of word-boundary matching is a bit of a kludge,
and bugs may lurk in combinations of word-boundary matching and anchoring.
+.Pp
+Word-boundary matching does not work properly in multibyte locales.
* 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.
* SUCH DAMAGE.
*
* @(#)regex2.h 8.4 (Berkeley) 3/20/94
- * $FreeBSD: src/lib/libc/regex/regex2.h,v 1.8 2004/07/12 07:35:59 tjr Exp $
+ * $FreeBSD: src/lib/libc/regex/regex2.h,v 1.11 2007/01/09 00:28:04 imp Exp $
*/
/*
#include "collate.h"
static int
-CHIN1(cs, ch, loc)
-cset *cs;
-wint_t ch;
-locale_t loc;
+CHIN1(cset *cs, wint_t ch, locale_t loc)
{
int i;
}
static __inline int
-CHIN(cs, ch, loc)
-cset *cs;
-wint_t ch;
-locale_t loc;
+CHIN(cset *cs, wint_t ch, locale_t loc)
{
assert(ch >= 0);
};
/* misc utilities */
-#define OUT (-130) /* a non-character value */
+#define OUT (CHAR_MIN - 2) /* a non-character value */
#define ISWORD(c,l) (iswalnum_l((uch)(c), l) || (c) == '_')
* 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.
static char sccsid[] = "@(#)regexec.c 8.3 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/regexec.c,v 1.6 2004/07/12 07:35:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/regexec.c,v 1.8 2007/06/11 03:05:54 delphij Exp $");
#include "xlocale_private.h"
static int nope __unused = 0; /* for use in asserts; shuts lint up */
static __inline size_t
-xmbrtowc(wi, s, n, mbs, dummy, loc)
-wint_t *wi;
-const char *s;
-size_t n;
-mbstate_t *mbs;
-wint_t dummy;
-locale_t loc;
+xmbrtowc(wint_t *wi, const char *s, size_t n, mbstate_t *mbs, wint_t dummy, locale_t loc)
{
size_t nr;
wchar_t wc;
}
static __inline size_t
-xmbrtowc_dummy(wi, s, n, mbs, dummy, loc)
-wint_t *wi;
-const char *s;
-size_t n __unused;
-mbstate_t *mbs __unused;
-wint_t dummy __unused;
-locale_t loc;
+xmbrtowc_dummy(wint_t *wi,
+ const char *s,
+ size_t n __unused,
+ mbstate_t *mbs __unused,
+ wint_t dummy __unused,
+ locale_t loc __unused)
{
if (wi != NULL)
* have been prototyped.
*/
int /* 0 success, REG_NOMATCH failure */
-regexec(preg, string, nmatch, pmatch, eflags)
-const regex_t * __restrict preg;
-const char * __restrict string;
-size_t nmatch;
-regmatch_t pmatch[__restrict];
-int eflags;
+regexec(const regex_t * __restrict preg,
+ const char * __restrict string,
+ size_t nmatch,
+ regmatch_t pmatch[__restrict],
+ int eflags)
{
struct re_guts *g = preg->re_g;
#ifdef REDEBUG
* 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.
static char sccsid[] = "@(#)regfree.c 8.3 (Berkeley) 3/20/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/regex/regfree.c,v 1.6 2004/07/12 07:35:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/regex/regfree.c,v 1.8 2007/06/11 03:05:54 delphij Exp $");
#include <sys/types.h>
#include <stdio.h>
= extern void regfree(regex_t *);
*/
void
-regfree(preg)
-regex_t *preg;
+regfree(regex_t *preg)
{
struct re_guts *g;
int i;
strcpy_chk.c \
stpcpy_chk.c \
strncpy_chk.c \
+ stpncpy_chk.c \
strcat_chk.c \
strncat_chk.c \
sprintf_chk.c \
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+extern void __chk_fail (void) __attribute__((__noreturn__));
+
+void *
+__stpncpy_chk (char *restrict dest, char *restrict src,
+ size_t len, size_t dstlen)
+{
+ if (__builtin_expect (dstlen < len, 0))
+ __chk_fail ();
+
+ return stpncpy (dest, src, len);
+}
* 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 John Birrell.
- * 4. Neither the name of the author nor the names of any co-contributors
+ * 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/_flock_stub.c,v 1.14 2004/03/09 04:51:58 jb Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/_flock_stub.c,v 1.16 2008/04/17 22:17:53 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
__weak_reference(_ftrylockfile, ftrylockfile);
__weak_reference(_funlockfile, funlockfile);
-/*
- * We need to retain binary compatibility for a while. So pretend
- * that _lock is part of FILE * even though it is dereferenced off
- * _extra now. When we stop encoding the size of FILE into binaries
- * this can be changed in stdio.h. This will reduce the amount of
- * code that has to change in the future (just remove this comment
- * and #define).
- */
-#define _lock _extra
-
void
_flockfile(FILE *fp)
{
pthread_t curthread = _pthread_self();
- if (fp->_lock->fl_owner == curthread)
- fp->_lock->fl_count++;
+ if (fp->_fl_owner == curthread)
+ fp->_fl_count++;
else {
/*
* Make sure this mutex is treated as a private
* internal mutex:
*/
- _pthread_mutex_lock(&fp->_lock->fl_mutex);
- fp->_lock->fl_owner = curthread;
- fp->_lock->fl_count = 1;
+ _pthread_mutex_lock(&fp->_fl_mutex);
+ fp->_fl_owner = curthread;
+ fp->_fl_count = 1;
}
}
pthread_t curthread = _pthread_self();
int ret = 0;
- if (fp->_lock->fl_owner == curthread)
- fp->_lock->fl_count++;
+ if (fp->_fl_owner == curthread)
+ fp->_fl_count++;
/*
* Make sure this mutex is treated as a private
* internal mutex:
*/
- else if (_pthread_mutex_trylock(&fp->_lock->fl_mutex) == 0) {
- fp->_lock->fl_owner = curthread;
- fp->_lock->fl_count = 1;
+ else if (_pthread_mutex_trylock(&fp->_fl_mutex) == 0) {
+ fp->_fl_owner = curthread;
+ fp->_fl_count = 1;
}
else
ret = -1;
/*
* Check if this file is owned by the current thread:
*/
- if (fp->_lock->fl_owner == curthread) {
+ if (fp->_fl_owner == curthread) {
/*
* Check if this thread has locked the FILE
* more than once:
*/
- if (fp->_lock->fl_count > 1)
+ if (fp->_fl_count > 1)
/*
* Decrement the count of the number of
* times the running thread has locked this
* file:
*/
- fp->_lock->fl_count--;
+ fp->_fl_count--;
else {
/*
* The running thread will release the
* lock now:
*/
- fp->_lock->fl_count = 0;
- fp->_lock->fl_owner = NULL;
- _pthread_mutex_unlock(&fp->_lock->fl_mutex);
+ fp->_fl_count = 0;
+ fp->_fl_owner = NULL;
+ _pthread_mutex_unlock(&fp->_fl_mutex);
}
}
}
-/* $OpenBSD: asprintf.c,v 1.8 2002/02/19 19:39:36 millert Exp $ */
-
-/*
- * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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.
+ * 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 ``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.
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/asprintf.c,v 1.13 2002/09/26 13:09:48 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/asprintf.c,v 1.15 2009/03/02 04:11:42 das Exp $");
#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
#include <stdarg.h>
-#include "local.h"
-
int
-asprintf(char **str, char const *fmt, ...)
+asprintf(char ** __restrict s, char const * __restrict fmt, ...)
{
int ret;
va_list ap;
- FILE f;
- struct __sFILEX ext;
- f._file = -1;
- f._flags = __SWR | __SSTR | __SALC;
- f._bf._base = f._p = (unsigned char *)malloc(128);
- if (f._bf._base == NULL) {
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
va_start(ap, fmt);
- ret = __vfprintf(&f, fmt, ap); /* Use unlocked __vfprintf */
+ ret = vasprintf(s, fmt, ap);
va_end(ap);
- if (ret < 0) {
- free(f._bf._base);
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- *f._p = '\0';
- *str = (char *)f._bf._base;
return (ret);
}
---- asprintf.c.orig 2003-05-20 15:22:40.000000000 -0700
-+++ asprintf.c 2005-02-23 16:17:23.000000000 -0800
-@@ -30,6 +30,8 @@
+--- asprintf.c.bsdnew 2009-11-11 19:15:16.000000000 -0800
++++ asprintf.c 2009-11-11 19:15:42.000000000 -0800
+@@ -33,6 +33,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/asprintf.c,v 1.13 2002/09/26 13:09:48 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/asprintf.c,v 1.15 2009/03/02 04:11:42 das Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
-@@ -57,7 +59,41 @@
- f._extra = &ext;
- INITEXTRA(&f);
+ #include <stdarg.h>
+
+@@ -43,7 +45,19 @@ asprintf(char ** __restrict s, char cons
+ va_list ap;
+
va_start(ap, fmt);
-- ret = __vfprintf(&f, fmt, ap); /* Use unlocked __vfprintf */
-+ ret = __vfprintf(&f, __current_locale(), fmt, ap); /* Use unlocked __vfprintf */
+- ret = vasprintf(s, fmt, ap);
++ ret = vasprintf_l(s, __current_locale(), fmt, ap);
+ va_end(ap);
-+ if (ret < 0) {
-+ free(f._bf._base);
-+ *str = NULL;
-+ errno = ENOMEM;
-+ return (-1);
-+ }
-+ *f._p = '\0';
-+ *str = (char *)f._bf._base;
+ return (ret);
+}
+
+int
-+asprintf_l(char **str, locale_t loc, char const *fmt, ...)
++asprintf_l(char ** __restrict s, locale_t loc, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
-+ FILE f;
-+ struct __sFILEX ext;
+
-+ NORMALIZE_LOCALE(loc);
-+ f._file = -1;
-+ f._flags = __SWR | __SSTR | __SALC;
-+ f._bf._base = f._p = (unsigned char *)malloc(128);
-+ if (f._bf._base == NULL) {
-+ *str = NULL;
-+ errno = ENOMEM;
-+ return (-1);
-+ }
-+ f._bf._size = f._w = 127; /* Leave room for the NUL */
-+ f._extra = &ext;
-+ INITEXTRA(&f);
+ va_start(ap, fmt);
-+ ret = __vfprintf(&f, loc, fmt, ap); /* Use unlocked __vfprintf */
++ ret = vasprintf_l(s, loc, fmt, ap);
va_end(ap);
- if (ret < 0) {
- free(f._bf._base);
+ return (ret);
+ }
* 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.
static char sccsid[] = "@(#)clrerr.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/clrerr.c,v 1.9 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/clrerr.c,v 1.12 2008/05/05 16:03:52 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
#include "un-namespace.h"
#include "libc_private.h"
-#undef clearerr
+
+#undef clearerr
+#undef clearerr_unlocked
void
clearerr(fp)
__sclearerr(fp);
FUNLOCKFILE(fp);
}
+
+void
+clearerr_unlocked(FILE *fp)
+{
+
+ __sclearerr(fp);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/dprintf.c,v 1.1 2009/03/04 03:38:51 das Exp $");
+
+#define _WITH_DPRINTF
+#include "namespace.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include "un-namespace.h"
+
+int
+dprintf(int fd, const char * __restrict fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vdprintf(fd, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
--- /dev/null
+--- dprintf.c.orig 2009-12-15 17:43:05.000000000 -0800
++++ dprintf.c 2009-12-15 17:45:32.000000000 -0800
+@@ -27,7 +27,8 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/dprintf.c,v 1.1 2009/03/04 03:38:51 das Exp $");
+
+-#define _WITH_DPRINTF
++#include "xlocale_private.h"
++
+ #include "namespace.h"
+ #include <stdarg.h>
+ #include <stdio.h>
+@@ -40,7 +41,19 @@ dprintf(int fd, const char * __restrict
+ int ret;
+
+ va_start(ap, fmt);
+- ret = vdprintf(fd, fmt, ap);
++ ret = vdprintf_l(fd, __current_locale(), fmt, ap);
++ va_end(ap);
++ return (ret);
++}
++
++int
++dprintf_l(int fd, locale_t loc, const char * __restrict fmt, ...)
++{
++ va_list ap;
++ int ret;
++
++ va_start(ap, fmt);
++ ret = vdprintf_l(fd, loc, fmt, ap);
+ va_end(ap);
+ return (ret);
+ }
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fclose.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fclose.3,v 1.12 2002/12/18 12:45:10 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fclose.3,v 1.15 2007/01/09 00:28:06 imp Exp $
.\"
-.Dd June 4, 1993
+.Dd April 22, 2006
.Dt FCLOSE 3
.Os
.Sh NAME
-.Nm fclose
+.Nm fclose ,
+.Nm fcloseall
.Nd close a stream
.Sh LIBRARY
.Lb libc
.In stdio.h
.Ft int
.Fn fclose "FILE *stream"
+.Ft void
+.Fn fcloseall void
.Sh DESCRIPTION
The
.Fn fclose
If the stream was being used for output, any buffered data is written
first, using
.Xr fflush 3 .
+.Pp
+The
+.Fn fcloseall
+function calls
+.Fn fclose
+on all open streams.
.Sh RETURN VALUES
Upon successful completion 0 is returned.
Otherwise,
function
conforms to
.St -isoC .
+.Pp
+The
+.Fn fcloseall
+function first appeared in
+.Fx 7.0 .
* 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.
static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fclose.c,v 1.11 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fclose.c,v 1.12 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <errno.h>
---- fclose.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ fclose.c 2009-02-15 19:01:59.000000000 -0800
-@@ -53,6 +53,13 @@ fclose(FILE *fp)
+--- fclose.c.bsdnew 2009-11-11 13:33:03.000000000 -0800
++++ fclose.c 2009-11-11 13:33:03.000000000 -0800
+@@ -49,6 +49,13 @@ fclose(FILE *fp)
{
int r;
if (fp->_flags == 0) { /* not open! */
errno = EBADF;
return (EOF);
-@@ -69,7 +76,7 @@ fclose(FILE *fp)
+@@ -65,7 +72,7 @@ fclose(FILE *fp)
FREELB(fp);
fp->_file = -1;
fp->_r = fp->_w = 0; /* Mess up if reaccessed. */
* 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.
static char sccsid[] = "@(#)fdopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fdopen.c,v 1.7 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fdopen.c,v 1.11 2008/05/10 18:39:20 antoine Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <limits.h>
#include "un-namespace.h"
#include "local.h"
const char *mode;
{
FILE *fp;
- static int nofile;
int flags, oflags, fdflags, tmp;
- if (nofile == 0)
- nofile = getdtablesize();
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+ return (NULL);
+ }
if ((flags = __sflags(mode, &oflags)) == 0)
return (NULL);
---- fdopen.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ fdopen.c 2009-02-15 17:52:46.000000000 -0800
-@@ -34,6 +34,15 @@
+--- fdopen.c.bsdnew 2009-11-11 13:33:03.000000000 -0800
++++ fdopen.c 2009-11-11 13:33:04.000000000 -0800
+@@ -30,6 +30,15 @@
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)fdopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-@@ -73,7 +82,7 @@ fdopen(fd, mode)
+@@ -78,7 +87,7 @@ fdopen(fd, mode)
return (NULL);
}
* 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.
static char sccsid[] = "@(#)feof.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/feof.c,v 1.9 2004/03/17 01:43:07 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/feof.c,v 1.12 2008/05/05 16:03:52 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
#include "libc_private.h"
#undef feof
+#undef feof_unlocked
int
feof(FILE *fp)
FUNLOCKFILE(fp);
return (ret);
}
+
+int
+feof_unlocked(FILE *fp)
+{
+
+ return (__sfeof(fp));
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ferror.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/stdio/ferror.3,v 1.9 2003/02/23 01:47:47 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/ferror.3,v 1.13 2009/01/28 14:38:41 trhodes Exp $
.\"
-.Dd January 10, 2003
+.Dd January 28, 2009
.Dt FERROR 3
.Os
.Sh NAME
tests the end-of-file indicator for the stream pointed to by
.Fa stream ,
returning non-zero if it is set.
-The end-of-file indicator can only be cleared by the function
-.Fn clearerr .
+The end-of-file indicator may be cleared by explicitly calling
+.Fn clearerr ,
+or as a side-effect of other operations, e.g.\&
+.Fn fseek .
.Pp
The function
.Fn ferror
tests the error indicator for the stream pointed to by
.Fa stream ,
returning non-zero if it is set.
-The error indicator can only be reset by the
-.Fn clearerr
-function.
.Pp
The function
.Fn fileno
* 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.
static char sccsid[] = "@(#)ferror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/ferror.c,v 1.9 2004/03/17 01:43:07 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/ferror.c,v 1.12 2008/05/05 16:03:52 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
#include "libc_private.h"
#undef ferror
+#undef ferror_unlocked
int
ferror(FILE *fp)
FUNLOCKFILE(fp);
return (ret);
}
+
+int
+ferror_unlocked(FILE *fp)
+{
+
+ return (__sferror(fp));
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fflush.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fflush.3,v 1.10 2003/06/08 10:01:52 charnier Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fflush.3,v 1.11 2007/01/09 00:28:06 imp Exp $
.\"
.Dd June 4, 1993
.Dt FFLUSH 3
* 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.
static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fflush.c,v 1.13 2004/07/04 20:17:00 cperciva Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fflush.c,v 1.14 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <errno.h>
---- fflush.c.orig 2007-07-20 11:15:28.000000000 -0700
-+++ fflush.c 2007-07-20 15:47:15.000000000 -0700
-@@ -43,6 +43,7 @@
+--- fflush.c.bsdnew 2009-11-11 13:33:04.000000000 -0800
++++ fflush.c 2009-11-11 13:33:04.000000000 -0800
+@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
#include "namespace.h"
#include <errno.h>
#include <stdio.h>
#include "un-namespace.h"
#include "libc_private.h"
#include "local.h"
-@@ -126,6 +127,14 @@
+@@ -122,6 +123,14 @@ __sflush(FILE *fp)
for (; n > 0; n -= t, p += t) {
t = _swrite(fp, (char *)p, n);
if (t <= 0) {
* 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.
static char sccsid[] = "@(#)fgetc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetc.c,v 1.12 2004/03/19 09:04:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetc.c,v 1.13 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/stdio/fgetln.3,v 1.8 2004/07/16 06:07:12 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fgetln.3,v 1.10 2009/02/28 06:00:58 das Exp $
.\"
.Dd April 19, 1994
.Dt FGETLN 3
.Xr fgets 3 ,
.Xr fgetwln 3 ,
.Xr fopen 3 ,
+.Xr getline 3 ,
.Xr putc 3
.Sh HISTORY
The
--- /dev/null
+--- fgetln.3.orig 2010-07-09 13:54:22.000000000 -0700
++++ fgetln.3 2010-07-10 12:40:15.000000000 -0700
+@@ -97,6 +97,9 @@
+ The argument
+ .Fa stream
+ is not a stream open for reading.
++.It Bq Er ENOMEM
++The internal line buffer could not be expanded due to lack of available memory,
++or because it would need to expand beyond INT_MAX in size.
+ .El
+ .Pp
+ The
* 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.
static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetln.c,v 1.10 2004/07/16 05:52:51 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetln.c,v 1.11 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <stdio.h>
--- /dev/null
+--- fgetln.c.orig 2010-07-09 13:54:22.000000000 -0700
++++ fgetln.c 2010-07-10 12:23:58.000000000 -0700
+@@ -37,6 +37,7 @@ static char sccsid[] = "@(#)fgetln.c 8.2
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/fgetln.c,v 1.11 2007/01/09 00:28:06 imp Exp $");
+
+ #include "namespace.h"
++#include <errno.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -61,6 +62,10 @@ __slbexpand(FILE *fp, size_t newsize)
+ #endif
+ if (fp->_lb._size >= newsize)
+ return (0);
++ if (newsize > INT_MAX) {
++ errno = ENOMEM;
++ return (-1);
++ }
+ if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+ return (-1);
+ fp->_lb._base = p;
+@@ -159,6 +164,7 @@ fgetln(FILE *fp, size_t *lenp)
+
+ error:
+ *lenp = 0; /* ??? */
++ fp->_flags |= __SERR;
+ FUNLOCKFILE(fp);
+ return (NULL); /* ??? */
+ }
* 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.
static char sccsid[] = "@(#)fgetpos.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetpos.c,v 1.12 2002/10/12 16:13:37 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetpos.c,v 1.13 2007/01/09 00:28:06 imp Exp $");
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fgets.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fgets.3,v 1.19 2002/12/04 18:57:45 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fgets.3,v 1.22 2009/02/28 06:00:58 das Exp $
.\"
.Dd June 4, 1993
.Dt FGETS 3
.Xr feof 3 ,
.Xr ferror 3 ,
.Xr fgetln 3 ,
-.Xr fgetws 3
-.Rs
-.%T "The FreeBSD Security Architecture"
-.Re
-(See
-.Pa /usr/share/doc/{to be determined} . )
+.Xr fgetws 3 ,
+.Xr getline 3
.Sh STANDARDS
The functions
.Fn fgets
+++ /dev/null
---- _SB/Libc/stdio/FreeBSD/fgets.3 2003-05-20 15:22:41.000000000 -0700
-+++ _SB/Libc/stdio/FreeBSD/fgets.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -48,19 +48,19 @@
- .Sh SYNOPSIS
- .In stdio.h
- .Ft char *
--.Fn fgets "char * restrict str" "int size" "FILE * restrict stream"
-+.Fn fgets "char *restrict s" "int n" "FILE *restrict stream"
- .Ft char *
--.Fn gets "char *str"
-+.Fn gets "char *s"
- .Sh DESCRIPTION
- The
- .Fn fgets
- function
- reads at most one less than the number of characters specified by
--.Fa size
-+.Fa n
- from the given
- .Fa stream
- and stores them in the string
--.Fa str .
-+.Fa s .
- Reading stops when a newline character is found,
- at end-of-file or error.
- The newline, if any, is retained.
-@@ -74,7 +74,7 @@
- is equivalent to
- .Fn fgets
- with an infinite
--.Fa size
-+.Fa n
- and a
- .Fa stream
- of
-@@ -102,7 +102,7 @@
- and
- .Fn gets
- functions
--do not distinguish between end-of-file and error, and callers must use
-+do not distinguish between end-of-file and error; callers must use
- .Xr feof 3
- and
- .Xr ferror 3
-@@ -152,11 +152,6 @@
- .Xr ferror 3 ,
- .Xr fgetln 3 ,
- .Xr fgetws 3
--.Rs
--.%T "The FreeBSD Security Architecture"
--.Re
--(See
--.Pa /usr/share/doc/{to be determined} . )
- .Sh STANDARDS
- The functions
- .Fn fgets
* 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.
static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgets.c,v 1.13 2002/08/13 09:30:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgets.c,v 1.14 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <stdio.h>
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwc.c,v 1.12 2004/07/20 08:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwc.c,v 1.13 2008/04/17 22:17:53 jhb Exp $");
#include "namespace.h"
#include <errno.h>
return (wc);
}
do {
- nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_extra->mbstate);
+ nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate);
if (nconv == (size_t)-1)
break;
else if (nconv == (size_t)-2)
---- fgetwc.c.orig 2004-11-25 11:38:34.000000000 -0800
-+++ fgetwc.c 2005-02-23 17:15:00.000000000 -0800
+--- fgetwc.c.bsdnew 2009-11-11 13:33:05.000000000 -0800
++++ fgetwc.c 2009-11-11 13:43:19.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwc.c,v 1.12 2004/07/20 08:27:27 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwc.c,v 1.13 2008/04/17 22:17:53 jhb Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <errno.h>
#include <stdio.h>
-@@ -47,7 +49,21 @@
+@@ -47,7 +49,21 @@ fgetwc(FILE *fp)
FLOCKFILE(fp);
ORIENT(fp, 1);
FUNLOCKFILE(fp);
return (r);
-@@ -57,21 +73,23 @@
+@@ -57,21 +73,23 @@ fgetwc(FILE *fp)
* Non-MT-safe version.
*/
wint_t
return (wc);
}
do {
-- nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_extra->mbstate);
-+ nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_extra->mbstate, loc);
+- nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate);
++ nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate, loc);
if (nconv == (size_t)-1)
break;
else if (nconv == (size_t)-2)
--- /dev/null
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 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.
+.\"
+.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD: src/lib/libc/stdio/fgetwln.3,v 1.3 2007/01/09 00:28:06 imp Exp $
+.\"
+.Dd July 16, 2004
+.Dt FGETWLN 3
+.Os
+.Sh NAME
+.Nm fgetwln
+.Nd get a line of wide characters from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft wchar_t *
+.Fn fgetwln "FILE * restrict stream" "size_t * restrict len"
+.Sh DESCRIPTION
+The
+.Fn fgetwln
+function
+returns a pointer to the next line from the stream referenced by
+.Fa stream .
+This line is
+.Em not
+a standard wide character string as it does not end with a terminating
+null wide character.
+The length of the line, including the final newline,
+is stored in the memory location to which
+.Fa len
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
+.Sh RETURN VALUES
+Upon successful completion a pointer is returned;
+this pointer becomes invalid after the next
+.Tn I/O
+operation on
+.Fa stream
+(whether successful or not)
+or as soon as the stream is closed.
+Otherwise,
+.Dv NULL
+is returned.
+The
+.Fn fgetwln
+function
+does not distinguish between end-of-file and error; the routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used
+to determine which occurred.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv NULL
+until the condition is
+cleared with
+.Xr clearerr 3 .
+.Pp
+The text to which the returned pointer points may be modified,
+provided that no changes are made beyond the returned size.
+These changes are lost as soon as the pointer becomes invalid.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa stream
+is not a stream open for reading.
+.El
+.Pp
+The
+.Fn fgetwln
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr mbrtowc 3 ,
+.Xr realloc 3 ,
+or
+.Xr read 2 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgetln 3 ,
+.Xr fgetws 3 ,
+.Xr fopen 3
--- /dev/null
+--- fgetwln.3.orig 2009-10-29 11:41:29.000000000 -0700
++++ fgetwln.3 2009-10-29 11:44:37.000000000 -0700
+@@ -32,7 +32,8 @@
+ .Dt FGETWLN 3
+ .Os
+ .Sh NAME
+-.Nm fgetwln
++.Nm fgetwln ,
++.Nm fgetwln_l
+ .Nd get a line of wide characters from a stream
+ .Sh LIBRARY
+ .Lb libc
+@@ -41,6 +42,9 @@
+ .In wchar.h
+ .Ft wchar_t *
+ .Fn fgetwln "FILE * restrict stream" "size_t * restrict len"
++.In xlocale.h
++.Ft wchar_t *
++.Fn fgetwln_l "FILE * restrict stream" "size_t * restrict len" "locale_t loc"
+ .Sh DESCRIPTION
+ The
+ .Fn fgetwln
+@@ -58,6 +62,14 @@ points.
+ (Note, however, that if the line is the last
+ in a file that does not end in a newline,
+ the returned text will not contain a newline.)
++.Pp
++While the
++.Fn fgetwln
++function uses the current locale, the
++.Fn fgetwln_l
++function may be passed a locale directly. See
++.Xr xlocale 3
++for more information.
+ .Sh RETURN VALUES
+ Upon successful completion a pointer is returned;
+ this pointer becomes invalid after the next
+@@ -113,4 +125,5 @@ or
+ .Xr ferror 3 ,
+ .Xr fgetln 3 ,
+ .Xr fgetws 3 ,
+-.Xr fopen 3
++.Xr fopen 3 ,
++.Xr xlocale 3
--- /dev/null
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwln.c,v 1.2 2004/08/06 17:00:09 tjr Exp $");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+wchar_t *
+fgetwln(FILE * __restrict fp, size_t *lenp)
+{
+ wint_t wc;
+ size_t len;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+
+ len = 0;
+ while ((wc = __fgetwc(fp)) != WEOF) {
+#define GROW 512
+ if (len * sizeof(wchar_t) >= fp->_lb._size &&
+ __slbexpand(fp, (len + GROW) * sizeof(wchar_t)))
+ goto error;
+ *((wchar_t *)fp->_lb._base + len++) = wc;
+ if (wc == L'\n')
+ break;
+ }
+ if (len == 0)
+ goto error;
+
+ FUNLOCKFILE(fp);
+ *lenp = len;
+ return ((wchar_t *)fp->_lb._base);
+
+error:
+ FUNLOCKFILE(fp);
+ *lenp = 0;
+ return (NULL);
+}
--- /dev/null
+--- fgetwln.c.orig 2005-09-14 19:51:14.000000000 -0700
++++ fgetwln.c 2005-09-14 19:53:18.000000000 -0700
+@@ -35,7 +35,7 @@
+ #include "local.h"
+
+ wchar_t *
+-fgetwln(FILE * __restrict fp, size_t *lenp)
++fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t loc)
+ {
+ wint_t wc;
+ size_t len;
+@@ -44,7 +44,7 @@
+ ORIENT(fp, 1);
+
+ len = 0;
+- while ((wc = __fgetwc(fp)) != WEOF) {
++ while ((wc = __fgetwc(fp, loc)) != WEOF) {
+ #define GROW 512
+ if (len * sizeof(wchar_t) >= fp->_lb._size &&
+ __slbexpand(fp, (len + GROW) * sizeof(wchar_t)))
+@@ -65,3 +65,9 @@
+ *lenp = 0;
+ return (NULL);
+ }
++
++wchar_t *
++fgetwln(FILE * __restrict fp, size_t *lenp)
++{
++ return fgetwln_l(fp, lenp, __current_locale());
++}
.\" 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.
.\"
.\" @(#)fgets.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/stdio/fgets.3,v 1.16 2002/05/31 05:01:17 archie Exp
-.\" $FreeBSD: src/lib/libc/stdio/fgetws.3,v 1.3 2003/03/09 02:56:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fgetws.3,v 1.4 2007/01/09 00:28:06 imp Exp $
.\"
.Dd August 6, 2002
.Dt FGETWS 3
---- fgetws.3 2003-05-20 15:22:41.000000000 -0700
-+++ fgetws.3.edit 2006-08-12 09:44:23.000000000 -0700
-@@ -41,7 +41,8 @@
+--- fgetws.3.bsdnew 2009-11-11 13:33:05.000000000 -0800
++++ fgetws.3 2009-11-11 13:33:05.000000000 -0800
+@@ -37,7 +37,8 @@
.Dt FGETWS 3
.Os
.Sh NAME
.Nd get a line of wide characters from a stream
.Sh LIBRARY
.Lb libc
-@@ -49,7 +50,21 @@
+@@ -45,7 +46,21 @@
.In stdio.h
.In wchar.h
.Ft "wchar_t *"
.Sh DESCRIPTION
The
.Fn fgetws
-@@ -57,7 +72,7 @@
+@@ -53,7 +68,7 @@ function
reads at most one less than the number of characters specified by
.Fa n
from the given
and stores them in the wide character string
.Fa ws .
Reading stops when a newline character is found,
-@@ -66,6 +81,14 @@
+@@ -62,6 +77,14 @@ The newline, if any, is retained.
If any characters are read and there is no error, a
.Ql \e0
character is appended to end the string.
.Sh RETURN VALUES
Upon successful completion,
.Fn fgetws
-@@ -84,7 +107,8 @@
+@@ -80,7 +103,8 @@ and the buffer contents are indeterminat
The
.Fn fgetws
function
.Xr feof 3
and
.Xr ferror 3
-@@ -96,7 +120,7 @@
+@@ -92,7 +116,7 @@ function will fail if:
.Bl -tag -width Er
.It Bq Er EBADF
The given
argument is not a readable stream.
.It Bq Er EILSEQ
The data obtained from the input stream does not form a valid
-@@ -116,7 +140,8 @@
+@@ -112,7 +136,8 @@ or
.Sh SEE ALSO
.Xr feof 3 ,
.Xr ferror 3 ,
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.6 2004/10/03 15:48:32 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.8 2009/11/25 04:45:45 wollman Exp $");
#include "namespace.h"
#include <errno.h>
nl = memchr(fp->_p, '\n', fp->_r);
nconv = __mbsnrtowcs(wsp, &src,
nl != NULL ? (nl - fp->_p + 1) : fp->_r,
- n - 1, &fp->_extra->mbstate);
+ n - 1, &fp->_mbstate);
if (nconv == (size_t)-1)
/* Conversion error */
goto error;
if (wsp == ws)
/* EOF */
goto error;
- if (!__mbsinit(&fp->_extra->mbstate))
+ if (!__mbsinit(&fp->_mbstate))
/* Incomplete character */
goto error;
- *wsp++ = L'\0';
+ *wsp = L'\0';
FUNLOCKFILE(fp);
return (ws);
---- fgetws.c.orig 2004-11-25 11:38:34.000000000 -0800
-+++ fgetws.c 2005-02-24 16:20:29.000000000 -0800
+--- fgetws.c.bsdnew 2009-11-30 16:15:32.000000000 -0800
++++ fgetws.c 2009-11-30 16:15:32.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.6 2004/10/03 15:48:32 stefanf Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.8 2009/11/25 04:45:45 wollman Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <errno.h>
#include <stdio.h>
-@@ -38,13 +40,18 @@
+@@ -38,13 +40,18 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
#include "mblocal.h"
wchar_t *
FLOCKFILE(fp);
ORIENT(fp, 1);
-@@ -58,11 +65,11 @@
+@@ -58,11 +65,11 @@ fgetws(wchar_t * __restrict ws, int n, F
goto error;
wsp = ws;
do {
nl = memchr(fp->_p, '\n', fp->_r);
nconv = __mbsnrtowcs(wsp, &src,
nl != NULL ? (nl - fp->_p + 1) : fp->_r,
-- n - 1, &fp->_extra->mbstate);
-+ n - 1, &fp->_extra->mbstate, loc);
+- n - 1, &fp->_mbstate);
++ n - 1, &fp->_mbstate, loc);
if (nconv == (size_t)-1)
/* Conversion error */
goto error;
-@@ -86,7 +93,7 @@
+@@ -86,7 +93,7 @@ fgetws(wchar_t * __restrict ws, int n, F
if (wsp == ws)
/* EOF */
goto error;
-- if (!__mbsinit(&fp->_extra->mbstate))
-+ if (!rl->__mbsinit(&fp->_extra->mbstate, loc))
+- if (!__mbsinit(&fp->_mbstate))
++ if (!rl->__mbsinit(&fp->_mbstate, loc))
/* Incomplete character */
goto error;
- *wsp++ = L'\0';
-@@ -98,3 +105,9 @@
+ *wsp = L'\0';
+@@ -98,3 +105,9 @@ error:
FUNLOCKFILE(fp);
return (NULL);
}
* 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.
static char sccsid[] = "@(#)fileno.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fileno.c,v 1.10 2004/03/17 01:43:07 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fileno.c,v 1.13 2008/05/05 16:03:52 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
#include "libc_private.h"
#undef fileno
+#undef fileno_unlocked
int
fileno(FILE *fp)
return (fd);
}
+
+int
+fileno_unlocked(FILE *fp)
+{
+
+ return (__sfileno(fp));
+}
* 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.
static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/findfp.c,v 1.29 2004/05/22 15:19:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/findfp.c,v 1.34 2009/12/05 19:31:38 ed Exp $");
#include <sys/param.h>
#include <machine/atomic.h>
#define NDYNAMIC 10 /* add ten more whenever necessary */
-#define std(flags, file) \
- {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
- {0}, __sFX + file}
- /* p r w flags file _bf z cookie close read seek write */
- /* _ub _extra */
+#define std(flags, file) { \
+ ._flags = (flags), \
+ ._file = (file), \
+ ._cookie = __sF + (file), \
+ ._close = __sclose, \
+ ._read = __sread, \
+ ._seek = __sseek, \
+ ._write = __swrite, \
+}
/* the usual - (stdin + stdout + stderr) */
static FILE usual[FOPEN_MAX - 3];
-static struct __sFILEX usual_extra[FOPEN_MAX - 3];
static struct glue uglue = { NULL, FOPEN_MAX - 3, usual };
-static struct __sFILEX __sFX[3];
-
-/*
- * We can't make this 'static' until 6.0-current due to binary
- * compatibility concerns. This also means we cannot change the
- * sizeof(FILE) until that time either and must continue to use the
- * __sFILEX stuff to add to FILE.
- */
-FILE __sF[3] = {
+static FILE __sF[3] = {
std(__SRD, STDIN_FILENO),
std(__SWR, STDOUT_FILENO),
std(__SWR|__SNBF, STDERR_FILENO)
};
-/*
- * The following kludge is done to ensure enough binary compatibility
- * with future versions of libc. Or rather it allows us to work with
- * libraries that have been built with a newer libc that defines these
- * symbols and expects libc to provide them. We only have need to support
- * i386 and alpha because they are the only "old" systems we have deployed.
- */
FILE *__stdinp = &__sF[0];
FILE *__stdoutp = &__sF[1];
FILE *__stderrp = &__sF[2];
{
struct glue *g;
static FILE empty;
- static struct __sFILEX emptyx;
FILE *p;
- struct __sFILEX *fx;
- g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE) +
- n * sizeof(struct __sFILEX));
+ g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE));
if (g == NULL)
return (NULL);
p = (FILE *)ALIGN(g + 1);
- fx = (struct __sFILEX *)&p[n];
g->next = NULL;
g->niobs = n;
g->iobs = p;
- while (--n >= 0) {
- *p = empty;
- p->_extra = fx;
- *p->_extra = emptyx;
- p++, fx++;
- }
+ while (--n >= 0)
+ *p++ = empty;
return (g);
}
fp->_lb._base = NULL; /* no line buffer */
fp->_lb._size = 0;
/* fp->_lock = NULL; */ /* once set always set (reused) */
- fp->_extra->orientation = 0;
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
+ fp->_orientation = 0;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
return (fp);
}
"warning: this program uses f_prealloc(), which is not recommended.");
void
-f_prealloc()
+f_prealloc(void)
{
struct glue *g;
int n;
void
__sinit()
{
- int i;
- THREAD_LOCK();
- if (__sdidinit == 0) {
- /* Set _extra for the usual suspects. */
- for (i = 0; i < FOPEN_MAX - 3; i++)
- usual[i]._extra = &usual_extra[i];
-
- /* Make sure we clean up on exit. */
- __cleanup = _cleanup; /* conservative */
- __sdidinit = 1;
- }
- THREAD_UNLOCK();
+ /* Make sure we clean up on exit. */
+ __cleanup = _cleanup; /* conservative */
+ __sdidinit = 1;
}
---- findfp.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ findfp.c 2009-02-15 18:45:19.000000000 -0800
-@@ -46,7 +46,10 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
+--- findfp.c.orig 2011-02-15 16:29:38.000000000 -0800
++++ findfp.c 2011-02-16 10:36:00.000000000 -0800
+@@ -36,13 +36,18 @@ static char sccsid[] = "@(#)findfp.c 8.2
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/findfp.c,v 1.34 2009/12/05 19:31:38 ed Exp $");
+
++#include <TargetConditionals.h>
++
+ #include <sys/param.h>
+ #include <machine/atomic.h>
+ #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <spinlock.h>
#include "libc_private.h"
-@@ -62,12 +65,19 @@ int __sdidinit;
- {0}, __sFX + file}
- /* p r w flags file _bf z cookie close read seek write */
- /* _ub _extra */
-+#define __sFXInit {0, PTHREAD_MUTEX_INITIALIZER}
+@@ -51,7 +56,11 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
+
+ int __sdidinit;
+
++#if !TARGET_OS_EMBEDDED
+ #define NDYNAMIC 10 /* add ten more whenever necessary */
++#else
++#define NDYNAMIC 1 /* add one at a time on embedded */
++#endif
+
+ #define std(flags, file) { \
+ ._flags = (flags), \
+@@ -61,12 +70,32 @@ int __sdidinit;
+ ._read = __sread, \
+ ._seek = __sseek, \
+ ._write = __swrite, \
++ ._extra = __sFX + file, \
+ }
++#define __sFXInit {.fl_mutex = PTHREAD_MUTEX_INITIALIZER}
+ /* set counted */
-+#define __sFXInit3 {0, PTHREAD_MUTEX_INITIALIZER, 0, 0, 0, 1}
- /* the usual - (stdin + stdout + stderr) */
++#define __sFXInit3 {.fl_mutex = PTHREAD_MUTEX_INITIALIZER, .counted = 1}
+
+static int __scounted; /* streams counted against STREAM_MAX */
+static int __stream_max;
+
++#if !TARGET_OS_EMBEDDED
++/* usual and usual_extra are data pigs. See 7929728. For embedded we should
++ * always allocate dynamically, and probably should for desktop too. */
+ /* the usual - (stdin + stdout + stderr) */
static FILE usual[FOPEN_MAX - 3];
- static struct __sFILEX usual_extra[FOPEN_MAX - 3];
++static struct __sFILEX usual_extra[FOPEN_MAX - 3];
static struct glue uglue = { NULL, FOPEN_MAX - 3, usual };
++#endif /* !TARGET_OS_EMBEDDED */
--static struct __sFILEX __sFX[3];
+-static FILE __sF[3] = {
+static struct __sFILEX __sFX[3] = {__sFXInit3, __sFXInit3, __sFXInit3};
++
++/*
++ * We can't make this 'static' due to binary compatibility concerns.
++ * This also means we cannot change the sizeof(FILE) and must continue to
++ * use the __sFILEX stuff to add to FILE.
++ */
++FILE __sF[3] = {
+ std(__SRD, STDIN_FILENO),
+ std(__SWR, STDOUT_FILENO),
+ std(__SWR|__SNBF, STDERR_FILENO)
+@@ -76,8 +105,13 @@ FILE *__stdinp = &__sF[0];
+ FILE *__stdoutp = &__sF[1];
+ FILE *__stderrp = &__sF[2];
- /*
- * We can't make this 'static' until 6.0-current due to binary
-@@ -113,7 +123,7 @@ moreglue(n)
- {
++#if !TARGET_OS_EMBEDDED
+ struct glue __sglue = { &uglue, 3, __sF };
+ static struct glue *lastglue = &uglue;
++#else
++struct glue __sglue = { NULL, 3, __sF };
++static struct glue *lastglue = &__sglue;
++#endif
+
+ static struct glue * moreglue(int);
+
+@@ -98,16 +132,25 @@ moreglue(n)
struct glue *g;
static FILE empty;
-- static struct __sFILEX emptyx;
-+ static struct __sFILEX emptyx = __sFXInit;
FILE *p;
- struct __sFILEX *fx;
++ static struct __sFILEX emptyx = __sFXInit;
++ struct __sFILEX *fx;
+
+- g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE));
++ g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE) +
++ n * sizeof(struct __sFILEX));
+ if (g == NULL)
+ return (NULL);
+ p = (FILE *)ALIGN(g + 1);
++ fx = (struct __sFILEX *)&p[n];
+ g->next = NULL;
+ g->niobs = n;
+ g->iobs = p;
+- while (--n >= 0)
+- *p++ = empty;
++
++ while (--n >= 0) {
++ *p = empty;
++ p->_extra = fx;
++ *p->_extra = emptyx;
++ p++, fx++;
++ }
+ return (g);
+ }
-@@ -139,7 +149,7 @@ moreglue(n)
+@@ -115,7 +158,7 @@ moreglue(n)
* Find a free FILE for fopen et al.
*/
FILE *
{
FILE *fp;
int n;
-@@ -147,6 +157,15 @@ __sfp()
+@@ -123,6 +166,15 @@ __sfp()
if (!__sdidinit)
__sinit();
/*
* The list must be locked because a FILE may be updated.
*/
-@@ -179,12 +198,27 @@ found:
+@@ -155,12 +207,25 @@ found:
fp->_lb._base = NULL; /* no line buffer */
fp->_lb._size = 0;
/* fp->_lock = NULL; */ /* once set always set (reused) */
-+ fp->_extra->fl_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
- fp->_extra->orientation = 0;
+- fp->_orientation = 0;
+- memset(&fp->_mbstate, 0, sizeof(mbstate_t));
++ INITEXTRA(fp);
+ fp->_extra->counted = count ? 1 : 0;
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
return (fp);
}
+__private_extern__ void
+__sfprelease(FILE *fp)
+{
-+ if (fp->_extra->counted) {
++ if (fp->_counted) {
+ OSAtomicDecrement32(&__scounted);
-+ fp->_extra->counted = 0;
++ fp->_counted = 0;
+ }
+ fp->_flags = 0;
+}
* XXX. Force immediate allocation of internal memory. Not used by stdio,
* but documented historically for certain applications. Bad applications.
*/
-@@ -244,6 +278,8 @@ __sinit()
- /* Make sure we clean up on exit. */
- __cleanup = _cleanup; /* conservative */
- __sdidinit = 1;
+@@ -209,8 +274,25 @@ _cleanup()
+ void
+ __sinit()
+ {
++ THREAD_LOCK();
++ if (__sdidinit == 0) {
++#if !TARGET_OS_EMBEDDED
++ int i;
++#endif
++ /* Make sure we clean up on exit. */
++ __cleanup = _cleanup; /* conservative */
+ __stream_max = sysconf(_SC_STREAM_MAX);
+ __scounted = 3; /* std{in,out,err} already exists */
- }
- THREAD_UNLOCK();
++
++#if !TARGET_OS_EMBEDDED
++ /* Set _extra for the usual suspects. */
++ for (i = 0; i < FOPEN_MAX - 3; i++) {
++ usual[i]._extra = &usual_extra[i];
++ INITEXTRA(&usual[i]);
++ }
++#endif
+
+- /* Make sure we clean up on exit. */
+- __cleanup = _cleanup; /* conservative */
+- __sdidinit = 1;
++ __sdidinit = 1;
++ }
++ THREAD_UNLOCK();
}
* 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.
static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/flags.c,v 1.9 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/flags.c,v 1.10 2007/01/09 00:28:06 imp Exp $");
#include <sys/types.h>
#include <sys/file.h>
---- flags.c.orig 2003-05-20 15:22:41.000000000 -0700
-+++ flags.c 2005-11-16 17:49:13.000000000 -0800
-@@ -85,10 +85,17 @@
+--- flags.c.bsdnew 2009-11-11 13:33:06.000000000 -0800
++++ flags.c 2009-11-11 13:33:06.000000000 -0800
+@@ -81,10 +81,17 @@ __sflags(mode, optr)
}
/* [rwa]\+ or [rwa]b\+ means read and write */
* 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.
* SUCH DAMAGE.
*
* @(#)floatio.h 8.1 (Berkeley) 6/4/93
- * $FreeBSD: src/lib/libc/stdio/floatio.h,v 1.5 2004/01/18 08:28:47 das Exp $
+ * $FreeBSD: src/lib/libc/stdio/floatio.h,v 1.6 2007/01/09 00:28:06 imp Exp $
*/
/*
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fopen.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fopen.3,v 1.18 2003/01/26 10:01:59 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fopen.3,v 1.21 2009/09/09 19:38:19 ed Exp $
.\"
.Dd January 26, 2003
.Dt FOPEN 3
Open for reading and writing.
The stream is positioned at the beginning of the file.
.It Dq Li w
-Truncate file to zero length or create text file for writing.
+Truncate to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
.It Dq Li w+
Open for reading and writing.
.Pp
The
.Fa mode
-string can also include the letter ``b'' either as a third character or
+string can also include the letter ``b'' either as last character or
as a character between the characters in any of the two-character strings
described above.
This is strictly for compatibility with
---- fopen.3 2003-05-20 15:22:41.000000000 -0700
-+++ fopen.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -40,8 +40,8 @@
+--- fopen.3.bsdnew 2009-11-11 13:33:06.000000000 -0800
++++ fopen.3 2009-11-11 13:33:07.000000000 -0800
+@@ -36,8 +36,8 @@
.Dt FOPEN 3
.Os
.Sh NAME
.Nm freopen
.Nd stream open functions
.Sh LIBRARY
-@@ -49,17 +49,27 @@
+@@ -45,17 +45,27 @@
.Sh SYNOPSIS
.In stdio.h
.Ft FILE *
and associates a stream with it.
.Pp
The argument
-@@ -107,6 +117,17 @@
+@@ -103,6 +113,17 @@ This is strictly for compatibility with
.St -isoC
and has no effect; the ``b'' is ignored.
.Pp
Any created files will have mode
.Pf \\*q Dv S_IRUSR
\&|
-@@ -148,7 +169,7 @@
+@@ -144,7 +165,7 @@ The
.Fn freopen
function
opens the file whose name is the string pointed to by
and associates the stream pointed to by
.Fa stream
with it.
-@@ -160,7 +181,7 @@
+@@ -156,7 +177,7 @@ argument is used just as in the
function.
.Pp
If the
argument is
.Dv NULL ,
.Fn freopen
-@@ -204,7 +225,7 @@
+@@ -200,7 +221,7 @@ or
.Sh RETURN VALUES
Upon successful completion
.Fn fopen ,
* 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.
static char sccsid[] = "@(#)fopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fopen.c,v 1.10 2002/10/12 16:13:37 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fopen.c,v 1.14 2008/04/22 17:03:32 jhb Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <limits.h>
#include "un-namespace.h"
#include "local.h"
fp->_flags = 0; /* release */
return (NULL);
}
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (f > SHRT_MAX) {
+ fp->_flags = 0; /* release */
+ _close(f);
+ errno = EMFILE;
+ return (NULL);
+ }
fp->_file = f;
fp->_flags = flags;
fp->_cookie = fp;
---- fopen.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ fopen.c 2009-02-15 17:53:37.000000000 -0800
-@@ -34,6 +34,15 @@
+--- fopen.c.bsdnew 2009-11-11 13:33:07.000000000 -0800
++++ fopen.c 2009-11-11 13:33:07.000000000 -0800
+@@ -30,6 +30,15 @@
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)fopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-@@ -61,10 +70,10 @@ fopen(file, mode)
+@@ -59,10 +68,10 @@ fopen(file, mode)
if ((flags = __sflags(mode, &oflags)) == 0)
return (NULL);
+ __sfprelease(fp); /* release */
return (NULL);
}
- fp->_file = f;
+ /*
* 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.
static char sccsid[] = "@(#)fprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fprintf.c,v 1.10 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fprintf.c,v 1.11 2007/01/09 00:28:06 imp Exp $");
#include <stdio.h>
#include <stdarg.h>
---- fprintf.c.orig 2003-05-20 15:22:41.000000000 -0700
-+++ fprintf.c 2005-02-23 16:20:47.000000000 -0800
-@@ -40,6 +40,8 @@
+--- fprintf.c.bsdnew 2009-11-11 13:33:07.000000000 -0800
++++ fprintf.c 2009-11-11 13:33:07.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)fprintf.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/fprintf.c,v 1.10 2002/09/06 11:23:55 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/fprintf.c,v 1.11 2007/01/09 00:28:06 imp Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
#include <stdarg.h>
-@@ -50,7 +52,20 @@
+@@ -46,7 +48,20 @@ fprintf(FILE * __restrict fp, const char
va_list ap;
va_start(ap, fmt);
* 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.
static char sccsid[] = "@(#)fpurge.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fpurge.c,v 1.10 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fpurge.c,v 1.11 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <errno.h>
* 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.
static char sccsid[] = "@(#)fputc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fputc.c,v 1.13 2004/03/19 09:04:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fputc.c,v 1.14 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fputs.3,v 1.11 2002/12/19 09:40:24 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fputs.3,v 1.14 2007/04/19 14:01:04 phk Exp $
.\"
.Dd June 4, 1993
.Dt FPUTS 3
to the stream
.Dv stdout .
.Sh RETURN VALUES
-The
+The functions
.Fn fputs
-function
-returns 0 on success and
-.Dv EOF
-on error;
+and
.Fn puts
-returns a nonnegative integer on success and
+return a nonnegative integer on success and
.Dv EOF
on error.
.Sh ERRORS
---- fputs.3 2003-05-20 15:22:42.000000000 -0700
-+++ fputs.3.edit 2006-07-13 09:28:07.000000000 -0700
-@@ -48,14 +48,19 @@
+--- fputs.3.bsdnew 2009-11-11 13:33:07.000000000 -0800
++++ fputs.3 2009-11-11 13:33:08.000000000 -0800
+@@ -44,14 +44,19 @@
.Sh SYNOPSIS
.In stdio.h
.Ft int
to the stream pointed to by
.Fa stream .
.\" The terminating
-@@ -65,7 +70,7 @@
+@@ -61,7 +66,7 @@ to the stream pointed to by
The function
.Fn puts
writes the string
and a terminating newline character,
to the stream
.Dv stdout .
-@@ -97,6 +102,14 @@
+@@ -90,6 +95,14 @@ may also fail and set
.Va errno
for any of the errors specified for the routines
.Xr write 2 .
.Sh SEE ALSO
.Xr ferror 3 ,
.Xr fputws 3 ,
-@@ -109,3 +122,13 @@
+@@ -102,3 +115,13 @@ and
.Fn puts
conform to
.St -isoC .
* 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.
static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fputs.c,v 1.11 2002/10/12 16:13:37 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fputs.c,v 1.12 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <stdio.h>
-Index: fputs.c
-===================================================================
-RCS file: /cvs/root/Libc/stdio/FreeBSD/fputs.c,v
-retrieving revision 1.2
-diff -u -d -b -w -p -u -r1.2 fputs.c
---- fputs.c 2003/05/20 22:22:42 1.2
-+++ fputs.c 2004/12/31 22:46:58
-@@ -48,6 +48,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
+--- fputs.c.bsdnew 2009-11-11 13:33:08.000000000 -0800
++++ fputs.c 2009-11-11 13:33:08.000000000 -0800
+@@ -44,6 +44,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
#include "libc_private.h"
#include "local.h"
/*
* Write the given string to the given file.
*/
-@@ -60,6 +63,9 @@ fputs(s, fp)
+@@ -56,6 +59,9 @@ fputs(s, fp)
struct __suio uio;
struct __siov iov;
iov.iov_base = (void *)s;
iov.iov_len = uio.uio_resid = strlen(s);
uio.uio_iov = &iov;
-@@ -68,5 +74,9 @@ fputs(s, fp)
+@@ -64,5 +70,9 @@ fputs(s, fp)
ORIENT(fp, -1);
retval = __sfvwrite(fp, &uio);
FUNLOCKFILE(fp);
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fputwc.c,v 1.10 2004/07/20 08:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fputwc.c,v 1.11 2008/04/17 22:17:53 jhb Exp $");
#include "namespace.h"
#include <errno.h>
*buf = (unsigned char)wc;
len = 1;
} else {
- if ((len = __wcrtomb(buf, wc, &fp->_extra->mbstate)) ==
- (size_t)-1) {
+ if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
}
---- fputwc.c.orig 2004-11-25 11:38:34.000000000 -0800
-+++ fputwc.c 2005-02-23 17:21:10.000000000 -0800
+--- fputwc.c.orig 2009-11-11 13:33:08.000000000 -0800
++++ fputwc.c 2009-11-13 11:45:45.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/fputwc.c,v 1.10 2004/07/20 08:27:27 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/fputwc.c,v 1.11 2008/04/17 22:17:53 jhb Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <errno.h>
#include <limits.h>
-@@ -41,13 +43,14 @@
+@@ -41,13 +43,14 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
/*
* Non-MT-safe version.
*/
/*
* Assume single-byte locale with no special encoding.
* A more careful test would be to check
-@@ -56,7 +59,7 @@
+@@ -56,7 +59,7 @@ __fputwc(wchar_t wc, FILE *fp)
*buf = (unsigned char)wc;
len = 1;
} else {
-- if ((len = __wcrtomb(buf, wc, &fp->_extra->mbstate)) ==
-+ if ((len = xrl->__wcrtomb(buf, wc, &fp->_extra->mbstate, loc)) ==
- (size_t)-1) {
+- if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
++ if ((len = loc->__lc_ctype->__wcrtomb(buf, wc, &fp->_mbstate, loc)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
-@@ -80,7 +83,21 @@
+ }
+@@ -79,7 +82,21 @@ fputwc(wchar_t wc, FILE *fp)
FLOCKFILE(fp);
ORIENT(fp, 1);
.\" 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.
.\"
.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/stdio/fputs.3,v 1.8 2001/10/01 16:08:59 ru Exp
-.\" $FreeBSD: src/lib/libc/stdio/fputws.3,v 1.5 2003/05/22 13:02:27 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fputws.3,v 1.6 2007/01/09 00:28:06 imp Exp $
.\"
.Dd August 6, 2002
.Dt FPUTWS 3
---- _SB/Libc/stdio/FreeBSD/fputws.3 2003-07-24 12:42:14.000000000 -0700
-+++ _SB/Libc/stdio/FreeBSD/fputws.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -41,7 +41,8 @@
+--- fputws.3.bsdnew 2009-11-11 13:33:08.000000000 -0800
++++ fputws.3 2009-11-11 13:33:08.000000000 -0800
+@@ -37,7 +37,8 @@
.Dt FPUTWS 3
.Os
.Sh NAME
.Nd output a line of wide characters to a stream
.Sh LIBRARY
.Lb libc
-@@ -49,14 +50,34 @@
+@@ -45,14 +46,34 @@
.In stdio.h
.In wchar.h
.Ft int
.Sh RETURN VALUES
The
.Fn fputws
-@@ -69,7 +90,7 @@
+@@ -65,7 +86,7 @@ function will fail if:
.Bl -tag -width Er
.It Bq Er EBADF
The
argument supplied
is not a writable stream.
.El
-@@ -84,7 +105,8 @@
+@@ -80,7 +101,8 @@ for any of the errors specified for the
.Xr ferror 3 ,
.Xr fputs 3 ,
.Xr putwc 3 ,
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fputws.c,v 1.6 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fputws.c,v 1.8 2009/01/15 18:53:52 rdivacky Exp $");
#include "namespace.h"
#include <errno.h>
char buf[BUFSIZ];
struct __suio uio;
struct __siov iov;
+ const wchar_t *wsp;
FLOCKFILE(fp);
ORIENT(fp, 1);
uio.uio_iovcnt = 1;
iov.iov_base = buf;
do {
- nbytes = __wcsnrtombs(buf, &ws, SIZE_T_MAX, sizeof(buf),
- &fp->_extra->mbstate);
+ wsp = ws;
+ nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf),
+ &fp->_mbstate);
if (nbytes == (size_t)-1)
goto error;
iov.iov_len = uio.uio_resid = nbytes;
---- fputws.c.orig 2004-11-25 11:38:34.000000000 -0800
-+++ fputws.c 2005-02-23 17:23:49.000000000 -0800
+--- fputws.c.orig 2010-03-18 18:11:42.000000000 -0700
++++ fputws.c 2010-03-18 18:17:53.000000000 -0700
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/fputws.c,v 1.6 2004/07/21 10:54:57 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/fputws.c,v 1.8 2009/01/15 18:53:52 rdivacky Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <errno.h>
#include <limits.h>
-@@ -39,13 +41,17 @@
+@@ -39,14 +41,18 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f
#include "mblocal.h"
int
char buf[BUFSIZ];
struct __suio uio;
struct __siov iov;
+- const wchar_t *wsp;
++ const wchar_t *wsp = ws;
+ size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict, locale_t);
FLOCKFILE(fp);
ORIENT(fp, 1);
if (prepwrite(fp) != 0)
-@@ -55,7 +61,7 @@
+@@ -55,15 +61,14 @@ fputws(const wchar_t * __restrict ws, FI
+ uio.uio_iovcnt = 1;
iov.iov_base = buf;
do {
- nbytes = __wcsnrtombs(buf, &ws, SIZE_T_MAX, sizeof(buf),
-- &fp->_extra->mbstate);
-+ &fp->_extra->mbstate, loc);
+- wsp = ws;
+ nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf),
+- &fp->_mbstate);
++ &fp->_mbstate, loc);
if (nbytes == (size_t)-1)
goto error;
iov.iov_len = uio.uio_resid = nbytes;
-@@ -69,3 +75,9 @@
+ if (__sfvwrite(fp, &uio) != 0)
+ goto error;
+- } while (ws != NULL);
++ } while (wsp != NULL);
+ FUNLOCKFILE(fp);
+ return (0);
+
+@@ -71,3 +76,9 @@ error:
FUNLOCKFILE(fp);
return (-1);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fread.3 8.2 (Berkeley) 3/8/94
-.\" $FreeBSD: src/lib/libc/stdio/fread.3,v 1.9 2002/10/12 16:13:37 mike Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fread.3,v 1.10 2007/01/09 00:28:06 imp Exp $
.\"
.Dd March 8, 1994
.Dt FREAD 3
---- _SB/Libc/stdio/FreeBSD/fread.3 2003-05-20 15:22:42.000000000 -0700
-+++ _SB/Libc/stdio/FreeBSD/fread.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -48,14 +48,16 @@
+--- fread.3.bsdnew 2009-11-11 13:33:08.000000000 -0800
++++ fread.3 2009-11-11 13:33:09.000000000 -0800
+@@ -44,14 +44,16 @@
.Sh SYNOPSIS
.In stdio.h
.Ft size_t
objects, each
.Fa size
bytes long, from the stream pointed to by
-@@ -66,7 +68,7 @@
+@@ -62,7 +64,7 @@ storing them at the location given by
The function
.Fn fwrite
writes
objects, each
.Fa size
bytes long, to the stream pointed to by
-@@ -86,7 +88,7 @@
+@@ -82,7 +84,7 @@ the return value is a short object count
.Pp
The function
.Fn fread
must use
.Xr feof 3
and
-@@ -95,7 +97,7 @@
+@@ -91,7 +93,7 @@ to determine which occurred.
The function
.Fn fwrite
returns a value less than
* 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.
static char sccsid[] = "@(#)fread.c 8.2 (Berkeley) 12/11/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fread.c,v 1.12 2002/10/12 16:13:37 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fread.c,v 1.16 2009/07/12 13:09:43 ed Exp $");
#include "namespace.h"
#include <stdio.h>
#include "local.h"
#include "libc_private.h"
+/*
+ * MT-safe version
+ */
+
size_t
-fread(buf, size, count, fp)
- void * __restrict buf;
- size_t size, count;
- FILE * __restrict fp;
+fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
+{
+ size_t ret;
+
+ FLOCKFILE(fp);
+ ret = __fread(buf, size, count, fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+size_t
+__fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
{
size_t resid;
char *p;
size_t total;
/*
- * The ANSI standard requires a return value of 0 for a count
- * or a size of 0. Peculiarily, it imposes no such requirements
- * on fwrite; it only requires fread to be broken.
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
*/
if ((resid = count * size) == 0)
return (0);
- FLOCKFILE(fp);
ORIENT(fp, -1);
if (fp->_r < 0)
fp->_r = 0;
resid -= r;
if (__srefill(fp)) {
/* no more input: return partial result */
- FUNLOCKFILE(fp);
return ((total - resid) / size);
}
}
(void)memcpy((void *)p, (void *)fp->_p, resid);
fp->_r -= resid;
fp->_p += resid;
- FUNLOCKFILE(fp);
return (count);
}
---- fread.c.orig 2008-08-29 21:58:50.000000000 -0700
-+++ fread.c 2008-09-02 02:18:06.000000000 -0700
-@@ -55,7 +55,7 @@ fread(buf, size, count, fp)
+--- fread.c.bsdnew 2009-11-11 13:33:09.000000000 -0800
++++ fread.c 2009-11-11 14:14:22.000000000 -0800
+@@ -63,7 +63,7 @@ __fread(void * __restrict buf, size_t si
{
size_t resid;
char *p;
size_t total;
/*
-@@ -71,21 +71,70 @@ fread(buf, size, count, fp)
+@@ -76,19 +76,66 @@ __fread(void * __restrict buf, size_t si
fp->_r = 0;
total = resid;
p = buf;
+ break;
+ else if (ret) {
/* no more input: return partial result */
- FUNLOCKFILE(fp);
return ((total - resid) / size);
}
}
+ fp->_bf = save;
+ fp->_p = fp->_bf._base;
+ /* fp->_r = 0; already set in __srefill1 */
-+ FUNLOCKFILE(fp);
+ return ((total - resid) / size);
+ }
+ fp->_bf._base += fp->_r;
+ resid -= r;
+ if (__srefill1(fp)) {
+ /* no more input: return partial result */
-+ FUNLOCKFILE(fp);
+ return ((total - resid) / size);
+ }
+ }
+ fp->_r -= resid;
+ fp->_p += resid;
+ }
- FUNLOCKFILE(fp);
return (count);
}
* 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.
static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.13 2004/05/22 15:19:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.21 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
+#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int dflags, flags, isopen, oflags, sverrno, wantfd;
if ((flags = __sflags(mode, &oflags)) == 0) {
+ sverrno = errno;
(void) fclose(fp);
+ errno = sverrno;
return (NULL);
}
errno = EINVAL;
return (NULL);
}
+ if (fp->_flags & __SWR)
+ (void) __sflush(fp);
if ((oflags ^ dflags) & O_APPEND) {
dflags &= ~O_APPEND;
dflags |= oflags & O_APPEND;
}
}
if (oflags & O_TRUNC)
- ftruncate(fp->_file, 0);
- if (_fseeko(fp, 0, oflags & O_APPEND ? SEEK_END : SEEK_SET,
- 0) < 0 && errno != ESPIPE) {
- sverrno = errno;
- fclose(fp);
- FUNLOCKFILE(fp);
- errno = sverrno;
- return (NULL);
- }
+ (void) ftruncate(fp->_file, (off_t)0);
+ if (!(oflags & O_APPEND))
+ (void) _sseek(fp, (fpos_t)0, SEEK_SET);
f = fp->_file;
isopen = 0;
wantfd = -1;
if (HASLB(fp))
FREELB(fp);
fp->_lb._size = 0;
- fp->_extra->orientation = 0;
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
+ fp->_orientation = 0;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
if (f < 0) { /* did not get it after all */
fp->_flags = 0; /* set it free */
- errno = sverrno; /* restore in case _close clobbered */
FUNLOCKFILE(fp);
+ errno = sverrno; /* restore in case _close clobbered */
return (NULL);
}
}
}
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (f > SHRT_MAX) {
+ fp->_flags = 0; /* set it free */
+ FUNLOCKFILE(fp);
+ errno = EMFILE;
+ return (NULL);
+ }
+
fp->_flags = flags;
fp->_file = f;
fp->_cookie = fp;
fp->_write = __swrite;
fp->_seek = __sseek;
fp->_close = __sclose;
+ /*
+ * When opening in append mode, even though we use O_APPEND,
+ * we need to seek to the end so that ftell() gets the right
+ * answer. If the user then alters the seek pointer, or
+ * the file extends, this will fail, but there is not much
+ * we can do about this. (We could set __SAPP and check in
+ * fseek and ftell.)
+ */
+ if (oflags & O_APPEND)
+ (void) _sseek(fp, (fpos_t)0, SEEK_END);
FUNLOCKFILE(fp);
return (fp);
}
---- freopen.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ freopen.c 2009-02-15 14:26:16.000000000 -0800
-@@ -99,7 +99,7 @@ freopen(file, mode, fp)
+--- freopen.c.bsdnew 2009-11-11 13:33:09.000000000 -0800
++++ freopen.c 2009-11-11 14:45:57.000000000 -0800
+@@ -98,7 +98,7 @@ freopen(file, mode, fp)
(oflags & O_ACCMODE)) {
fclose(fp);
FUNLOCKFILE(fp);
+ errno = EBADF;
return (NULL);
}
- if ((oflags ^ dflags) & O_APPEND) {
-@@ -136,6 +136,8 @@ freopen(file, mode, fp)
+ if (fp->_flags & __SWR)
+@@ -131,6 +131,8 @@ freopen(file, mode, fp)
* descriptor (if any) was associated with it. If it was attached to
* a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
* should work. This is unnecessary if it was not a Unix file.
*/
if (fp->_flags == 0) {
fp->_flags = __SEOF; /* hold on to it */
-@@ -146,11 +148,18 @@ freopen(file, mode, fp)
+@@ -141,11 +143,18 @@ freopen(file, mode, fp)
if (fp->_flags & __SWR)
(void) __sflush(fp);
/* if close is NULL, closing is a no-op, hence pointless */
}
/* Get a new descriptor to refer to the new file. */
-@@ -191,7 +200,7 @@ finish:
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
+@@ -186,7 +195,7 @@ finish:
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
if (f < 0) { /* did not get it after all */
- fp->_flags = 0; /* set it free */
+ __sfprelease(fp); /* set it free */
+ FUNLOCKFILE(fp);
errno = sverrno; /* restore in case _close clobbered */
+ return (NULL);
+@@ -212,7 +221,7 @@ finish:
+ * open.
+ */
+ if (f > SHRT_MAX) {
+- fp->_flags = 0; /* set it free */
++ __sfprelease(fp); /* set it free */
FUNLOCKFILE(fp);
+ errno = EMFILE;
return (NULL);
* 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.
static char sccsid[] = "@(#)fscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fscanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fscanf.c,v 1.13 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <stdio.h>
---- fscanf.c.orig 2003-05-20 15:22:42.000000000 -0700
-+++ fscanf.c 2005-02-23 16:23:38.000000000 -0800
-@@ -40,6 +40,8 @@
+--- fscanf.c.bsdnew 2009-11-11 13:33:09.000000000 -0800
++++ fscanf.c 2009-11-11 13:33:09.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)fscanf.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/fscanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/fscanf.c,v 1.13 2007/01/09 00:28:06 imp Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <stdio.h>
#include <stdarg.h>
-@@ -55,7 +57,22 @@
+@@ -51,7 +53,22 @@ fscanf(FILE * __restrict fp, char const
va_start(ap, fmt);
FLOCKFILE(fp);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fseek.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fseek.3,v 1.25 2004/03/20 08:38:27 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fseek.3,v 1.27 2007/06/18 02:13:04 ache Exp $
.\"
.Dd March 19, 2004
.Dt FSEEK 3
.Fn fseeko ,
.Fn fsetpos ,
.Fn ftell ,
+.Fn ftello ,
and
-.Fn ftello
+.Fn rewind
may also fail and set
.Va errno
for any of the errors specified for the routines
---- fseek.3 2004-11-25 11:38:34.000000000 -0800
-+++ fseek.3.edit 2006-07-12 11:18:41.000000000 -0700
-@@ -53,20 +53,39 @@
+--- fseek.3.bsdnew 2009-11-11 13:33:09.000000000 -0800
++++ fseek.3 2009-11-11 13:33:09.000000000 -0800
+@@ -49,20 +49,39 @@
.Sh SYNOPSIS
.In stdio.h
.Ft int
.Sh DESCRIPTION
The
.Fn fseek
-@@ -246,12 +265,29 @@
+@@ -243,12 +262,29 @@ for any of the errors specified for the
.Xr lseek 2 ,
and
.Xr malloc 3 .
* 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.
static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fseek.c,v 1.41 2004/05/22 15:19:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fseek.c,v 1.44 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <sys/types.h>
*/
if (HASUB(fp)) {
curoff += fp->_r; /* kill off ungetc */
- n = fp->_extra->_up - fp->_bf._base;
+ n = fp->_up - fp->_bf._base;
curoff -= n;
n += fp->_ur;
} else {
if (HASUB(fp))
FREEUB(fp);
fp->_flags &= ~__SEOF;
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
return (0);
}
fp->_r -= n;
}
fp->_flags &= ~__SEOF;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
return (0);
/*
if (__sflush(fp) ||
(ret = _sseek(fp, (fpos_t)offset, whence)) == POS_ERR)
return (-1);
+ if (ltest && ret > LONG_MAX) {
+ fp->_flags |= __SERR;
+ errno = EOVERFLOW;
+ return (-1);
+ }
/* success: clear EOF indicator and discard ungetc() data */
if (HASUB(fp))
FREEUB(fp);
fp->_r = 0;
/* fp->_w = 0; */ /* unnecessary (I think...) */
fp->_flags &= ~__SEOF;
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
- if (ltest && ret > LONG_MAX) {
- fp->_flags |= __SERR;
- errno = EOVERFLOW;
- return (-1);
- }
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
return (0);
}
* 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.
static char sccsid[] = "@(#)fsetpos.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fsetpos.c,v 1.8 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fsetpos.c,v 1.9 2007/01/09 00:28:06 imp Exp $");
#include <sys/types.h>
#include <stdio.h>
* 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.
static char sccsid[] = "@(#)ftell.c 8.2 (Berkeley) 5/4/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/ftell.c,v 1.26 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/ftell.c,v 1.27 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
-Index: ftell.c
-===================================================================
-RCS file: /cvs/root/Libc/stdio/FreeBSD/ftell.c,v
-retrieving revision 1.2
-diff -u -d -b -w -p -p -r1.2 ftell.c
---- ftell.c 2003/05/20 22:22:42 1.2
-+++ ftell.c 2005/03/14 03:10:02
-@@ -105,6 +105,8 @@ _ftello(fp, offset)
+--- ftell.c.bsdnew 2009-11-11 13:33:10.000000000 -0800
++++ ftell.c 2009-11-11 13:33:10.000000000 -0800
+@@ -101,6 +101,8 @@ _ftello(fp, offset)
* Find offset of underlying I/O object, then
* adjust for buffered bytes.
*/
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)funopen.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/stdio/funopen.3,v 1.15 2004/07/03 22:30:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/funopen.3,v 1.16 2007/01/09 00:28:06 imp Exp $
.\"
.Dd March 19, 2004
.Dt FUNOPEN 3
* 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.
static char sccsid[] = "@(#)funopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/funopen.c,v 1.5 2002/05/28 16:59:39 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/funopen.c,v 1.7 2009/12/05 19:31:38 ed Exp $");
#include <stdio.h>
#include <errno.h>
#include "local.h"
FILE *
-funopen(cookie, readfn, writefn, seekfn, closefn)
- const void *cookie;
- int (*readfn)(), (*writefn)();
- fpos_t (*seekfn)(void *cookie, fpos_t off, int whence);
- int (*closefn)();
+funopen(const void *cookie,
+ int (*readfn)(void *, char *, int),
+ int (*writefn)(void *, const char *, int),
+ fpos_t (*seekfn)(void *, fpos_t, int),
+ int (*closefn)(void *))
{
FILE *fp;
int flags;
---- funopen.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ funopen.c 2009-02-15 14:02:06.000000000 -0800
-@@ -67,7 +67,8 @@ funopen(cookie, readfn, writefn, seekfn,
+--- funopen.c.bsdnew 2009-11-11 13:33:10.000000000 -0800
++++ funopen.c 2009-11-11 13:33:10.000000000 -0800
+@@ -63,7 +63,8 @@ funopen(cookie, readfn, writefn, seekfn,
else
flags = __SRW; /* read-write */
}
* 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.
static char sccsid[] = "@(#)fvwrite.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fvwrite.c,v 1.17 2004/06/08 05:45:48 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fvwrite.c,v 1.19 2009/11/25 04:21:42 wollman Exp $");
#include <stdio.h>
#include <stdlib.h>
char *nl;
int nlknown, nldist;
- if ((len = uio->uio_resid) == 0)
+ if (uio->uio_resid == 0)
return (0);
/* make sure we can write */
if (prepwrite(fp) != 0)
* 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.
* SUCH DAMAGE.
*
* @(#)fvwrite.h 8.1 (Berkeley) 6/4/93
- * $FreeBSD: src/lib/libc/stdio/fvwrite.h,v 1.3 2002/05/28 16:59:39 alfred Exp $
+ * $FreeBSD: src/lib/libc/stdio/fvwrite.h,v 1.4 2007/01/09 00:28:06 imp Exp $
*/
/*
* 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.
static char sccsid[] = "@(#)fwalk.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fwalk.c,v 1.9 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fwalk.c,v 1.10 2007/01/09 00:28:06 imp Exp $");
#include <sys/types.h>
#include <machine/atomic.h>
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fwide.c,v 1.1 2002/08/13 09:30:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fwide.c,v 1.2 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <errno.h>
FLOCKFILE(fp);
/* Only change the orientation if the stream is not oriented yet. */
- if (mode != 0 && fp->_extra->orientation == 0)
- fp->_extra->orientation = mode > 0 ? 1 : -1;
- m = fp->_extra->orientation;
+ if (mode != 0 && fp->_orientation == 0)
+ fp->_orientation = mode > 0 ? 1 : -1;
+ m = fp->_orientation;
FUNLOCKFILE(fp);
return (m);
* 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.
static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fwrite.c,v 1.11 2002/10/12 16:13:41 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fwrite.c,v 1.13 2009/07/12 13:09:43 ed Exp $");
#include "namespace.h"
#include <stdio.h>
struct __suio uio;
struct __siov iov;
+ /*
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+ */
+ n = count * size;
+ if (n == 0)
+ return (0);
+
iov.iov_base = (void *)buf;
- uio.uio_resid = iov.iov_len = n = count * size;
+ uio.uio_resid = iov.iov_len = n;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
---- fwrite.c.orig 2004-11-01 00:27:25.000000000 -0800
-+++ fwrite.c 2004-11-01 00:29:40.000000000 -0800
-@@ -63,6 +63,11 @@
-
- iov.iov_base = (void *)buf;
- uio.uio_resid = iov.iov_len = n = count * size;
-+
+--- fwrite.c.orig 2009-12-08 00:25:43.000000000 -0800
++++ fwrite.c 2009-12-08 00:25:12.000000000 -0800
+@@ -61,9 +61,10 @@ fwrite(buf, size, count, fp)
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+ */
+ n = count * size;
+#if __DARWIN_UNIX03
-+ if (n == 0) /* POSIX */
-+ return 0;
-+#endif /* __DARWIN_UNIX03 */
+ if (n == 0)
+ return (0);
+-
++#endif
+ iov.iov_base = (void *)buf;
+ uio.uio_resid = iov.iov_len = n;
uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
-
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/getc.3,v 1.19 2004/03/17 12:37:28 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/getc.3,v 1.21 2007/01/09 00:28:06 imp Exp $
.\"
.Dd January 10, 2003
.Dt GETC 3
.Ft int
.Fn getc_unlocked "FILE *stream"
.Ft int
-.Fn getchar
+.Fn getchar void
.Ft int
.Fn getchar_unlocked "void"
.Ft int
---- _SB/Libc/stdio/FreeBSD/getc.3 2004-11-25 11:38:34.000000000 -0800
-+++ _SB/Libc/stdio/FreeBSD/getc.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -58,7 +58,7 @@
+--- getc.3.bsdnew 2009-11-11 13:33:11.000000000 -0800
++++ getc.3 2009-11-11 14:52:54.000000000 -0800
+@@ -54,7 +54,7 @@
.Ft int
.Fn getc_unlocked "FILE *stream"
.Ft int
--.Fn getchar
+-.Fn getchar void
+.Fn getchar "void"
.Ft int
.Fn getchar_unlocked "void"
.Ft int
-@@ -145,7 +145,7 @@
+@@ -141,7 +141,7 @@ until the condition is cleared with
.Sh STANDARDS
The
.Fn fgetc ,
* 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.
static char sccsid[] = "@(#)getc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/getc.c,v 1.13 2004/03/19 09:04:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/getc.c,v 1.16 2008/05/05 16:03:52 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
#include "local.h"
#undef getc
+#undef getc_unlocked
int
getc(FILE *fp)
FUNLOCKFILE(fp);
return (retval);
}
+
+int
+getc_unlocked(FILE *fp)
+{
+
+ return (__sgetc(fp));
+}
* 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.
static char sccsid[] = "@(#)getchar.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/getchar.c,v 1.12 2004/03/19 09:04:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/getchar.c,v 1.15 2008/05/05 16:03:52 jhb Exp $");
/*
* A subroutine version of the macro getchar.
#include "libc_private.h"
#undef getchar
+#undef getchar_unlocked
int
getchar()
FUNLOCKFILE(stdin);
return (retval);
}
+
+int
+getchar_unlocked(void)
+{
+
+ return (__sgetc(stdin));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/getdelim.c,v 1.3 2009/10/04 19:43:36 das Exp $");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+
+static inline size_t
+p2roundup(size_t n)
+{
+
+ if (!powerof2(n)) {
+ n--;
+ n |= n >> 1;
+ n |= n >> 2;
+ n |= n >> 4;
+ n |= n >> 8;
+ n |= n >> 16;
+#if SIZE_T_MAX > 0xffffffffU
+ n |= n >> 32;
+#endif
+ n++;
+ }
+ return (n);
+}
+
+/*
+ * Expand *linep to hold len bytes (up to SSIZE_MAX + 1).
+ */
+static inline int
+expandtofit(char ** __restrict linep, size_t len, size_t * __restrict capp)
+{
+ char *newline;
+ size_t newcap;
+
+ if (len > (size_t)SSIZE_MAX + 1) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ if (len > *capp) {
+ if (len == (size_t)SSIZE_MAX + 1) /* avoid overflow */
+ newcap = (size_t)SSIZE_MAX + 1;
+ else
+ newcap = p2roundup(len);
+ newline = realloc(*linep, newcap);
+ if (newline == NULL)
+ return (-1);
+ *capp = newcap;
+ *linep = newline;
+ }
+ return (0);
+}
+
+/*
+ * Append the src buffer to the *dstp buffer. The buffers are of
+ * length srclen and *dstlenp, respectively, and dst has space for
+ * *dstlenp bytes. After the call, *dstlenp and *dstcapp are updated
+ * appropriately, and *dstp is reallocated if needed. Returns 0 on
+ * success, -1 on allocation failure.
+ */
+static int
+sappend(char ** __restrict dstp, size_t * __restrict dstlenp,
+ size_t * __restrict dstcapp, char * __restrict src, size_t srclen)
+{
+
+ /* ensure room for srclen + dstlen + terminating NUL */
+ if (expandtofit(dstp, srclen + *dstlenp + 1, dstcapp))
+ return (-1);
+ memcpy(*dstp + *dstlenp, src, srclen);
+ *dstlenp += srclen;
+ return (0);
+}
+
+ssize_t
+getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
+ FILE * __restrict fp)
+{
+ u_char *endp;
+ size_t linelen;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+
+ if (linep == NULL || linecapp == NULL) {
+ errno = EINVAL;
+ goto error;
+ }
+
+ if (*linep == NULL)
+ *linecapp = 0;
+
+ if (fp->_r <= 0 && __srefill(fp)) {
+ /* If fp is at EOF already, we just need space for the NUL. */
+ if (__sferror(fp) || expandtofit(linep, 1, linecapp))
+ goto error;
+ FUNLOCKFILE(fp);
+ (*linep)[0] = '\0';
+ return (-1);
+ }
+
+ linelen = 0;
+ while ((endp = memchr(fp->_p, delim, fp->_r)) == NULL) {
+ if (sappend(linep, &linelen, linecapp, fp->_p, fp->_r))
+ goto error;
+ if (__srefill(fp)) {
+ if (__sferror(fp))
+ goto error;
+ goto done; /* hit EOF */
+ }
+ }
+ endp++; /* snarf the delimiter, too */
+ if (sappend(linep, &linelen, linecapp, fp->_p, endp - fp->_p))
+ goto error;
+ fp->_r -= endp - fp->_p;
+ fp->_p = endp;
+done:
+ /* Invariant: *linep has space for at least linelen+1 bytes. */
+ (*linep)[linelen] = '\0';
+ FUNLOCKFILE(fp);
+ return (linelen);
+
+error:
+ fp->_flags |= __SERR;
+ FUNLOCKFILE(fp);
+ return (-1);
+}
--- /dev/null
+.\" Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libc/stdio/getline.3,v 1.2 2009/04/06 13:50:04 das Exp $
+.\"
+.Dd March 29, 2009
+.Dt GETLINE 3
+.Os
+.Sh NAME
+.Nm getdelim ,
+.Nm getline
+.Nd get a line from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd "#define _WITH_GETLINE"
+.In stdio.h
+.Ft ssize_t
+.Fn getdelim "char ** restrict linep" "size_t * restrict linecapp" "int delimiter" " FILE * restrict stream"
+.Ft ssize_t
+.Fn getline "char ** restrict linep" "size_t * restrict linecapp" " FILE * restrict stream"
+.Sh DESCRIPTION
+The
+.Fn getdelim
+function reads a line from
+.Fa stream ,
+delimited by the character
+.Fa delimiter .
+The
+.Fn getline
+function is equivalent to
+.Fn getdelim
+with the newline character as the delimiter.
+The delimiter character is included as part of the line, unless
+the end of the file is reached.
+The caller may provide a pointer to a malloc buffer for the line in
+.Fa *linep ,
+and the capacity of that buffer in
+.Fa *linecapp ;
+if
+.Fa *linecapp
+is 0, then
+.Fa *linep
+is treated as
+.Dv NULL .
+These functions may expand the buffer as needed, as if via
+.Fn realloc ,
+and update
+.Fa *linep
+and
+.Fa *linecapp
+accordingly.
+.Sh RETURN VALUES
+The
+.Fn getdelim
+and
+.Fn getline
+functions return the number of characters written, excluding the
+terminating
+.Dv NULL .
+The value \-1 is returned if an error occurs, or if end-of-file is reached.
+.Sh EXAMPLES
+The following code fragment reads lines from a file and
+writes them to standard output.
+The
+.Fn fwrite
+function is used in case the line contains embedded
+.Dv NUL
+characters.
+.Bd -literal -offset indent
+char *line = NULL;
+size_t linecap = 0;
+ssize_t linelen;
+while ((linelen = getline(&line, &linecap, fp)) > 0)
+ fwrite(line, linelen, 1, stdout);
+.Ed
+.Sh COMPATIBILITY
+Many application writers used the name
+.Va getline
+before the
+.Fn getline
+function was introduced in
+.St -p1003.1 ,
+so a prototype is not provided by default in order to avoid
+compatibility problems.
+Applications that wish to use the
+.Fn getline
+function described herein should either request a strict
+.St -p1003.1-2008
+environment by defining the macro
+.Dv _POSIX_C_SOURCE
+to the value 200809 or greater, or by defining the macro
+.Dv _WITH_GETLINE ,
+prior to the inclusion of
+.In stdio.h .
+For compatibility with GNU libc, defining either
+.Dv _BSD_SOURCE
+or
+.Dv _GNU_SOURCE
+prior to the inclusion of
+.In stdio.h
+will also make
+.Fn getline
+available.
+.Sh ERRORS
+These functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Either
+.Fa linep
+or
+.Fa linecapp
+is
+.Dv NULL .
+.It Bq Er EOVERFLOW
+No delimiter was found in the first
+.Dv SSIZE_MAX
+characters.
+.El
+.Pp
+These functions may also fail for any of the errors specified for
+.Fn fgets
+and
+.Fn malloc .
+.Sh SEE ALSO
+.Xr fgetln 3 ,
+.Xr fgets 3 ,
+.Xr malloc 3
+.Sh STANDARDS
+The
+.Fn getdelim
+and
+.Fn getline
+functions conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 8.0 .
+.Sh BUGS
+There are no wide character versions of
+.Fn getdelim
+or
+.Fn getline .
--- /dev/null
+--- getline.3.orig 2009-12-15 15:37:17.000000000 -0800
++++ getline.3 2009-12-15 15:37:57.000000000 -0800
+@@ -34,7 +34,6 @@
+ .Sh LIBRARY
+ .Lb libc
+ .Sh SYNOPSIS
+-.Fd "#define _WITH_GETLINE"
+ .In stdio.h
+ .Ft ssize_t
+ .Fn getdelim "char ** restrict linep" "size_t * restrict linecapp" "int delimiter" " FILE * restrict stream"
+@@ -95,34 +94,6 @@ ssize_t linelen;
+ while ((linelen = getline(&line, &linecap, fp)) > 0)
+ fwrite(line, linelen, 1, stdout);
+ .Ed
+-.Sh COMPATIBILITY
+-Many application writers used the name
+-.Va getline
+-before the
+-.Fn getline
+-function was introduced in
+-.St -p1003.1 ,
+-so a prototype is not provided by default in order to avoid
+-compatibility problems.
+-Applications that wish to use the
+-.Fn getline
+-function described herein should either request a strict
+-.St -p1003.1-2008
+-environment by defining the macro
+-.Dv _POSIX_C_SOURCE
+-to the value 200809 or greater, or by defining the macro
+-.Dv _WITH_GETLINE ,
+-prior to the inclusion of
+-.In stdio.h .
+-For compatibility with GNU libc, defining either
+-.Dv _BSD_SOURCE
+-or
+-.Dv _GNU_SOURCE
+-prior to the inclusion of
+-.In stdio.h
+-will also make
+-.Fn getline
+-available.
+ .Sh ERRORS
+ These functions may fail if:
+ .Bl -tag -width Er
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/getline.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#define _WITH_GETLINE
+#include <stdio.h>
+
+ssize_t
+getline(char ** __restrict linep, size_t * __restrict linecapp,
+ FILE * __restrict fp)
+{
+
+ return (getdelim(linep, linecapp, '\n', fp));
+}
* 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.
static char sccsid[] = "@(#)gets.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/gets.c,v 1.16 2003/01/30 23:32:53 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/gets.c,v 1.17 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <unistd.h>
* 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.
static char sccsid[] = "@(#)getw.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/getw.c,v 1.7 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/getw.c,v 1.8 2007/01/09 00:28:06 imp Exp $");
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/getwc.3,v 1.6 2004/03/16 13:30:11 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/getwc.3,v 1.8 2007/01/09 00:28:06 imp Exp $
.\"
.Dd March 3, 2004
.Dt GETWC 3
.Ft wint_t
.Fn getwc "FILE *stream"
.Ft wint_t
-.Fn getwchar
+.Fn getwchar void
.Sh DESCRIPTION
The
.Fn fgetwc
---- getwc.3 2004-11-25 11:38:35.000000000 -0800
-+++ getwc.3.edit 2006-08-09 13:40:43.000000000 -0700
-@@ -56,7 +56,7 @@
+--- getwc.3.bsdnew 2009-11-11 13:33:12.000000000 -0800
++++ getwc.3 2009-11-11 14:56:18.000000000 -0800
+@@ -52,7 +52,7 @@
.Ft wint_t
.Fn getwc "FILE *stream"
.Ft wint_t
--.Fn getwchar
-+.Fn getwchar void
+-.Fn getwchar void
++.Fn getwchar "void"
.Sh DESCRIPTION
The
.Fn fgetwc
-@@ -79,6 +79,12 @@
+@@ -75,6 +75,12 @@ is equivalent to
.Fn getwc
with the argument
.Dv stdin .
.Sh RETURN VALUES
If successful, these routines return the next wide character
from the
-@@ -104,13 +110,14 @@
+@@ -100,13 +106,14 @@ until the condition is cleared with
.Xr fopen 3 ,
.Xr fread 3 ,
.Xr getc 3 ,
-+.Xr getwc_l 3 ,
++.Xr getwc_l ,
.Xr putwc 3 ,
.Xr stdio 3 ,
.Xr ungetwc 3
* 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.
* SUCH DAMAGE.
*
* @(#)glue.h 8.1 (Berkeley) 6/4/93
- * $FreeBSD: src/lib/libc/stdio/glue.h,v 1.2 2002/03/22 23:42:01 obrien Exp $
+ * $FreeBSD: src/lib/libc/stdio/glue.h,v 1.4 2007/01/09 00:28:06 imp Exp $
*/
/*
struct glue *next;
int niobs;
FILE *iobs;
-} __sglue;
+};
+extern struct glue __sglue;
+++ /dev/null
---- glue.h.orig Fri Mar 22 15:42:01 2002
-+++ glue.h Sat May 3 14:38:31 2003
-@@ -45,4 +45,5 @@
- struct glue *next;
- int niobs;
- FILE *iobs;
--} __sglue;
-+};
-+extern struct glue __sglue;
* 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.
* SUCH DAMAGE.
*
* @(#)local.h 8.3 (Berkeley) 7/3/94
- * $FreeBSD: src/lib/libc/stdio/local.h,v 1.26 2004/07/16 05:52:51 tjr Exp $
+ * $FreeBSD: src/lib/libc/stdio/local.h,v 1.33 2008/05/05 16:03:52 jhb Exp $
*/
#include <sys/types.h> /* for off_t */
extern int _ftello(FILE *, fpos_t *);
extern int _fseeko(FILE *, off_t, int, int);
extern int __fflush(FILE *fp);
+extern void __fcloseall(void);
extern wint_t __fgetwc(FILE *);
extern wint_t __fputwc(wchar_t, FILE *);
extern int __sflush(FILE *);
extern int __sclose(void *);
extern void __sinit(void);
extern void _cleanup(void);
-extern void (*__cleanup)(void);
extern void __smakebuf(FILE *);
extern int __swhatbuf(FILE *, size_t *, int *);
extern int _fwalk(int (*)(FILE *));
extern int __vfwprintf(FILE *, const wchar_t *, __va_list);
extern int __vfwscanf(FILE * __restrict, const wchar_t * __restrict,
__va_list);
-
+extern size_t __fread(void * __restrict buf, size_t size, size_t count,
+ FILE * __restrict fp);
extern int __sdidinit;
-/* hold a buncha junk that would grow the ABI */
-struct __sFILEX {
- unsigned char *_up; /* saved _p when _p is doing ungetc data */
- pthread_mutex_t fl_mutex; /* used for MT-safety */
- pthread_t fl_owner; /* current owner */
- int fl_count; /* recursive lock count */
- int orientation; /* orientation for fwide() */
- mbstate_t mbstate; /* multibyte conversion state */
-};
-
/*
* Prepare the given FILE for writing, and return 0 iff it
* can be written now. Otherwise, return EOF and set errno.
(fp)->_lb._base = NULL; \
}
-#define INITEXTRA(fp) { \
- (fp)->_extra->_up = NULL; \
- (fp)->_extra->fl_mutex = PTHREAD_MUTEX_INITIALIZER; \
- (fp)->_extra->fl_owner = NULL; \
- (fp)->_extra->fl_count = 0; \
- (fp)->_extra->orientation = 0; \
- memset(&(fp)->_extra->mbstate, 0, sizeof(mbstate_t)); \
-}
-
/*
* Set the orientation for a stream. If o > 0, the stream has wide-
* orientation. If o < 0, the stream has byte-orientation.
*/
#define ORIENT(fp, o) do { \
- if ((fp)->_extra->orientation == 0) \
- (fp)->_extra->orientation = (o); \
+ if ((fp)->_orientation == 0) \
+ (fp)->_orientation = (o); \
} while (0)
---- local.h.orig 2009-02-15 03:11:22.000000000 -0800
-+++ local.h 2009-02-15 18:12:54.000000000 -0800
-@@ -37,8 +37,11 @@
- * $FreeBSD: src/lib/libc/stdio/local.h,v 1.26 2004/07/16 05:52:51 tjr Exp $
+--- local.h.orig 2011-02-15 10:44:57.000000000 -0800
++++ local.h 2011-02-15 11:16:59.000000000 -0800
+@@ -33,8 +33,11 @@
+ * $FreeBSD: src/lib/libc/stdio/local.h,v 1.33 2008/05/05 16:03:52 jhb Exp $
*/
+#include <sys/cdefs.h>
#include <string.h>
#include <wchar.h>
-@@ -53,12 +56,15 @@ extern fpos_t _sseek(FILE *, fpos_t, int
- extern int _ftello(FILE *, fpos_t *);
+@@ -50,36 +53,69 @@
extern int _fseeko(FILE *, off_t, int, int);
extern int __fflush(FILE *fp);
+ extern void __fcloseall(void);
-extern wint_t __fgetwc(FILE *);
-extern wint_t __fputwc(wchar_t, FILE *);
+extern wint_t __fgetwc(FILE *, locale_t);
+extern wint_t __fputwc(wchar_t, FILE *, locale_t);
extern int __sflush(FILE *);
-extern FILE *__sfp(void);
-+extern FILE *__sfp(int); /* arg is whether to count against STREAM_MAX or not */
++extern FILE *__sfp(int);
+extern void __sfprelease(FILE *); /* mark free and update count as needed */
extern int __slbexpand(FILE *, size_t);
extern int __srefill(FILE *);
extern int __sread(void *, char *, int);
extern int __swrite(void *, char const *, int);
extern fpos_t __sseek(void *, fpos_t, int);
-@@ -69,16 +75,16 @@ extern void (*__cleanup)(void);
+ extern int __sclose(void *);
+ extern void __sinit(void);
+ extern void _cleanup(void);
++extern void (*__cleanup)(void);
extern void __smakebuf(FILE *);
extern int __swhatbuf(FILE *, size_t *, int *);
extern int _fwalk(int (*)(FILE *));
+extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list) __DARWIN_LDBL_COMPAT(__vfwprintf);
+extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict,
+ __va_list) __DARWIN_LDBL_COMPAT(__vfwscanf);
-
+ extern size_t __fread(void * __restrict buf, size_t size, size_t count,
+ FILE * __restrict fp);
extern int __sdidinit;
-@@ -89,7 +95,8 @@ struct __sFILEX {
- pthread_mutex_t fl_mutex; /* used for MT-safety */
- pthread_t fl_owner; /* current owner */
- int fl_count; /* recursive lock count */
-- int orientation; /* orientation for fwide() */
+
++/* hold a buncha junk that would grow the ABI */
++struct __sFILEX {
++ unsigned char *up; /* saved _p when _p is doing ungetc data */
++ pthread_mutex_t fl_mutex; /* used for MT-safety */
++ pthread_t fl_owner; /* current owner */
++ int fl_count; /* recursive lock count */
+ int orientation:2; /* orientation for fwide() */
+ int counted:1; /* stream counted against STREAM_MAX */
- mbstate_t mbstate; /* multibyte conversion state */
- };
-
-@@ -124,7 +131,7 @@ struct __sFILEX {
-
- #define INITEXTRA(fp) { \
- (fp)->_extra->_up = NULL; \
-- (fp)->_extra->fl_mutex = PTHREAD_MUTEX_INITIALIZER; \
++ mbstate_t mbstate; /* multibyte conversion state */
++};
++
++#define _up _extra->up
++#define _fl_mutex _extra->fl_mutex
++#define _fl_owner _extra->fl_owner
++#define _fl_count _extra->fl_count
++#define _orientation _extra->orientation
++#define _mbstate _extra->mbstate
++#define _counted _extra->counted
++
++#define INITEXTRA(fp) do { \
++ (fp)->_extra->up = NULL; \
+ (fp)->_extra->fl_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; \
- (fp)->_extra->fl_owner = NULL; \
- (fp)->_extra->fl_count = 0; \
- (fp)->_extra->orientation = 0; \
++ (fp)->_extra->fl_owner = NULL; \
++ (fp)->_extra->fl_count = 0; \
++ (fp)->_extra->orientation = 0; \
++ memset(&(fp)->_extra->mbstate, 0, sizeof(mbstate_t)); \
++ (fp)->_extra->counted = 0; \
++} while(0);
++
+ /*
+ * Prepare the given FILE for writing, and return 0 iff it
+ * can be written now. Otherwise, return EOF and set errno.
* 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.
static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.4 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.6 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
-#include "local.h"
#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
/*
* Allocate a file buffer, or switch to unbuffered I/O.
* Per the ANSI C standard, ALL tty devices default to line buffered.
---- makebuf.c.orig 2008-08-28 17:18:09.000000000 -0700
-+++ makebuf.c 2008-09-04 14:20:48.000000000 -0700
-@@ -49,6 +49,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/m
+--- makebuf.c.bsdnew 2009-11-11 13:33:12.000000000 -0800
++++ makebuf.c 2009-11-11 13:33:13.000000000 -0800
+@@ -47,6 +47,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/m
+ #include "libc_private.h"
#include "local.h"
- #include "un-namespace.h"
+#define MAXBUFSIZE (1 << 16)
+#define TTYBUFSIZE 4096
/*
* Allocate a file buffer, or switch to unbuffered I/O.
* Per the ANSI C standard, ALL tty devices default to line buffered.
-@@ -71,6 +74,12 @@ __smakebuf(fp)
+@@ -69,6 +72,12 @@ __smakebuf(fp)
return;
}
flags = __swhatbuf(fp, &size, &couldbetty);
if ((p = malloc(size)) == NULL) {
fp->_flags |= __SNBF;
fp->_bf._base = fp->_p = fp->_nbuf;
-@@ -81,8 +90,6 @@ __smakebuf(fp)
+@@ -79,8 +88,6 @@ __smakebuf(fp)
flags |= __SMBF;
fp->_bf._base = fp->_p = p;
fp->_bf._size = size;
fp->_flags |= flags;
}
-@@ -115,8 +122,7 @@ __swhatbuf(fp, bufsize, couldbetty)
+@@ -113,8 +120,7 @@ __swhatbuf(fp, bufsize, couldbetty)
* __sseek is mainly paranoia.) It is safe to set _blksize
* unconditionally; it will only be used if __SOPT is also set.
*/
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)mktemp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/mktemp.3,v 1.20 2004/02/20 04:08:28 green Exp $
+.\" $FreeBSD: src/lib/libc/stdio/mktemp.3,v 1.22 2007/01/09 00:28:07 imp Exp $
.\"
.Dd February 11, 1998
.Dt MKTEMP 3
See
.Xr gcc 1
for more information.
+.Sh SEE ALSO
+.Xr chmod 2 ,
+.Xr getpid 2 ,
+.Xr mkdir 2 ,
+.Xr open 2 ,
+.Xr stat 2
+.Sh HISTORY
+A
+.Fn mktemp
+function appeared in
+.At v7 .
+The
+.Fn mkstemp
+function appeared in
+.Bx 4.4 .
+The
+.Fn mkdtemp
+function first appeared in
+.Ox 2.2 ,
+and later in
+.Fx 3.2 .
+The
+.Fn mkstemps
+function first appeared in
+.Ox 2.4 ,
+and later in
+.Fx 3.4 .
.Sh BUGS
This family of functions produces filenames which can be guessed,
though the risk is minimized when large numbers of
You must provide your own locking around this and other consumers of the
.Xr arc4random 3
API.
-.Sh SEE ALSO
-.Xr chmod 2 ,
-.Xr getpid 2 ,
-.Xr mkdir 2 ,
-.Xr open 2 ,
-.Xr stat 2
-.Sh HISTORY
-A
-.Fn mktemp
-function appeared in
-.At v7 .
-The
-.Fn mkstemp
-function appeared in
-.Bx 4.4 .
-The
-.Fn mkdtemp
-function first appeared in
-.Ox 2.2 ,
-and later in
-.Fx 3.2 .
-The
-.Fn mkstemps
-function first appeared in
-.Ox 2.4 ,
-and later in
-.Fx 3.4 .
---- mktemp.3.orig 2008-02-29 10:45:39.000000000 -0800
-+++ mktemp.3 2008-02-29 11:21:10.000000000 -0800
-@@ -36,20 +36,33 @@
+--- mktemp.3.orig 2010-04-28 23:38:47.000000000 -0700
++++ mktemp.3 2010-04-29 11:05:28.000000000 -0700
+@@ -32,6 +32,9 @@
.Dt MKTEMP 3
.Os
.Sh NAME
--.Nm mktemp
+.Nm mkdtemp ,
+.Nm mkstemp ,
-+.Nm mktemp ,
-+.Nm mktemps
++.Nm mkstemps ,
+ .Nm mktemp
.Nd make temporary file name (unique)
.Sh LIBRARY
- .Lb libc
+@@ -39,13 +42,23 @@
.Sh SYNOPSIS
.In unistd.h
.Ft char *
.Sh DESCRIPTION
The
.Fn mktemp
-@@ -137,7 +150,7 @@
+@@ -133,7 +146,7 @@ The pathname portion of the template is
.Pp
The
.Fn mkstemp ,
and
.Fn mkdtemp
functions
-@@ -171,7 +184,7 @@
+@@ -167,7 +180,7 @@ A common problem that results in a core
passes in a read-only string to
.Fn mktemp ,
.Fn mkstemp ,
or
.Fn mkdtemp .
This is common with programs that were developed before
-@@ -219,19 +232,19 @@
- This will ensure that the program does not continue blindly
- in the event that an attacker has already created the file
- with the intention of manipulating or reading its contents.
+@@ -186,12 +199,19 @@ so that it will store string constants i
+ See
+ .Xr gcc 1
+ for more information.
+.Sh LEGACY SYNOPSIS
+.Fd #include <unistd.h>
- .Pp
--The implementation of these functions calls
--.Xr arc4random 3 ,
--which is not reentrant.
--You must provide your own locking around this and other consumers of the
--.Xr arc4random 3
--API.
++.Pp
+The include file
+.In unistd.h
+is necessary and sufficient for all functions.
.Sh HISTORY
A
.Fn mktemp
+@@ -242,10 +262,3 @@ and the return status of the call should
+ This will ensure that the program does not continue blindly
+ in the event that an attacker has already created the file
+ with the intention of manipulating or reading its contents.
+-.Pp
+-The implementation of these functions calls
+-.Xr arc4random 3 ,
+-which is not reentrant.
+-You must provide your own locking around this and other consumers of the
+-.Xr arc4random 3
+-API.
* 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.
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/mktemp.c,v 1.28 2003/02/16 17:29:10 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/mktemp.c,v 1.32 2010/02/28 13:31:29 jh Exp $");
#include "namespace.h"
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int domkdir;
int slen;
{
- char *start, *trv, *suffp;
+ char *start, *trv, *suffp, *carryp;
char *pad;
struct stat sbuf;
int rval;
uint32_t rand;
+ char carrybuf[MAXPATHLEN];
- if (doopen != NULL && domkdir) {
+ if ((doopen != NULL && domkdir) || slen < 0) {
errno = EINVAL;
return (0);
}
for (trv = path; *trv != '\0'; ++trv)
;
+ if (trv - path >= MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ return (0);
+ }
trv -= slen;
suffp = trv;
--trv;
- if (trv < path) {
+ if (trv < path || NULL != strchr(suffp, '/')) {
errno = EINVAL;
return (0);
}
/* Fill space with random characters */
while (trv >= path && *trv == 'X') {
- rand = arc4random() % (sizeof(padchar) - 1);
+ rand = arc4random_uniform(sizeof(padchar) - 1);
*trv-- = padchar[rand];
}
start = trv + 1;
+ /* save first combination of random characters */
+ memcpy(carrybuf, start, suffp - start);
+
/*
* check the target directory.
*/
return (errno == ENOENT);
/* If we have a collision, cycle through the space of filenames */
- for (trv = start;;) {
- if (*trv == '\0' || trv == suffp)
- return (0);
+ for (trv = start, carryp = carrybuf;;) {
+ /* have we tried all possible permutations? */
+ if (trv == suffp)
+ return (0); /* yes - exit with EEXIST */
pad = strchr(padchar, *trv);
- if (pad == NULL || *++pad == '\0')
- *trv++ = padchar[0];
- else {
- *trv++ = *pad;
+ if (pad == NULL) {
+ /* this should never happen */
+ errno = EIO;
+ return (0);
+ }
+ /* increment character */
+ *trv = (*++pad == '\0') ? padchar[0] : *pad;
+ /* carry to next position? */
+ if (*trv == *carryp) {
+ /* increment position and loop */
+ ++trv;
+ ++carryp;
+ } else {
+ /* try with new name */
break;
}
}
---- mktemp.c.orig Tue Mar 30 22:56:07 2004
-+++ mktemp.c Tue Mar 30 23:39:22 2004
-@@ -40,6 +40,7 @@
- #include "namespace.h"
- #include <sys/types.h>
- #include <sys/stat.h>
-+#include <sys/syslimits.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <stdio.h>
-@@ -106,13 +107,14 @@
- int domkdir;
- int slen;
- {
-- char *start, *trv, *suffp;
-+ char *start, *trv, *suffp, *carryp;
- char *pad;
- struct stat sbuf;
- int rval;
- uint32_t rand;
-+ char carrybuf[NAME_MAX];
+--- mktemp.c.orig 2010-04-08 10:37:06.000000000 -0700
++++ mktemp.c 2010-04-08 10:40:05.000000000 -0700
+@@ -130,7 +130,7 @@ _gettemp(path, doopen, domkdir, slen)
-- if (doopen != NULL && domkdir) {
-+ if ((doopen != NULL && domkdir) || slen < 0) {
- errno = EINVAL;
- return (0);
- }
-@@ -122,7 +124,7 @@
- trv -= slen;
- suffp = trv;
- --trv;
-- if (trv < path) {
-+ if (trv < path || NULL != strchr(suffp, '/')) {
- errno = EINVAL;
- return (0);
- }
-@@ -134,6 +136,9 @@
+ /* Fill space with random characters */
+ while (trv >= path && *trv == 'X') {
+- rand = arc4random_uniform(sizeof(padchar) - 1);
++ rand = arc4random() % (sizeof(padchar) - 1);
+ *trv-- = padchar[rand];
}
start = trv + 1;
-
-+ /* save first combination of random characters */
-+ memcpy(carrybuf, start, suffp - start);
-+
- /*
- * check the target directory.
- */
-@@ -170,14 +175,25 @@
- return (errno == ENOENT);
-
- /* If we have a collision, cycle through the space of filenames */
-- for (trv = start;;) {
-- if (*trv == '\0' || trv == suffp)
-- return (0);
-+ for (trv = start, carryp = carrybuf;;) {
-+ /* have we tried all possible permutations? */
-+ if (trv == suffp)
-+ return (0); /* yes - exit with EEXIST */
- pad = strchr(padchar, *trv);
-- if (pad == NULL || *++pad == '\0')
-- *trv++ = padchar[0];
-- else {
-- *trv++ = *pad;
-+ if (pad == NULL) {
-+ /* this should never happen */
-+ errno = EIO;
-+ return (0);
-+ }
-+ /* increment character */
-+ *trv = (*++pad == '\0') ? padchar[0] : *pad;
-+ /* carry to next position? */
-+ if (*trv == *carryp) {
-+ /* increment position and loop */
-+ ++trv;
-+ ++carryp;
-+ } else {
-+ /* try with new name */
- break;
- }
- }
* 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.
static char sccsid[] = "@(#)perror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/perror.c,v 1.8 2002/12/19 09:53:26 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/perror.c,v 1.9 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
+++ /dev/null
---- perror.c.orig 2003-05-20 15:22:43.000000000 -0700
-+++ perror.c 2005-04-29 17:06:52.000000000 -0700
-@@ -73,6 +73,7 @@
- v->iov_base = "\n";
- v->iov_len = 1;
- FLOCKFILE(stderr);
-+ ORIENT(stderr, -1);
- __sflush(stderr);
- (void)_writev(stderr->_file, iov, (v - iov) + 1);
- stderr->_flags &= ~__SOFF;
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/printf-pos.c,v 1.6 2009/03/02 04:07:58 das Exp $");
+
+/*
+ * This is the code responsible for handling positional arguments
+ * (%m$ and %m$.n$) for vfprintf() and vfwprintf().
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "un-namespace.h"
+#include "printflocal.h"
+
+/*
+ * Type ids for argument type table.
+ */
+enum typeid {
+ T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
+ T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
+ T_PTRDIFFT, TP_PTRDIFFT, T_SSIZET, T_SIZET, TP_SSIZET,
+ T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
+ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
+};
+
+/* An expandable array of types. */
+struct typetable {
+ enum typeid *table; /* table of types */
+ enum typeid stattable[STATIC_ARG_TBL_SIZE];
+ int tablesize; /* current size of type table */
+ int tablemax; /* largest used index in table */
+ int nextarg; /* 1-based argument index */
+};
+
+static int __grow_type_table(struct typetable *);
+static void build_arg_table (struct typetable *, va_list, union arg **);
+
+/*
+ * Initialize a struct typetable.
+ */
+static inline void
+inittypes(struct typetable *types)
+{
+ int n;
+
+ types->table = types->stattable;
+ types->tablesize = STATIC_ARG_TBL_SIZE;
+ types->tablemax = 0;
+ types->nextarg = 1;
+ for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
+ types->table[n] = T_UNUSED;
+}
+
+/*
+ * struct typetable destructor.
+ */
+static inline void
+freetypes(struct typetable *types)
+{
+
+ if (types->table != types->stattable)
+ free (types->table);
+}
+
+/*
+ * Ensure that there is space to add a new argument type to the type table.
+ * Expand the table if necessary. Returns 0 on success.
+ */
+static inline int
+_ensurespace(struct typetable *types)
+{
+
+ if (types->nextarg >= types->tablesize) {
+ if (__grow_type_table(types))
+ return (-1);
+ }
+ if (types->nextarg > types->tablemax)
+ types->tablemax = types->nextarg;
+ return (0);
+}
+
+/*
+ * Add an argument type to the table, expanding if necessary.
+ * Returns 0 on success.
+ */
+static inline int
+addtype(struct typetable *types, enum typeid type)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ types->table[types->nextarg++] = type;
+ return (0);
+}
+
+static inline int
+addsarg(struct typetable *types, int flags)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ if (flags & INTMAXT)
+ types->table[types->nextarg++] = T_INTMAXT;
+ else if (flags & SIZET)
+ types->table[types->nextarg++] = T_SSIZET;
+ else if (flags & PTRDIFFT)
+ types->table[types->nextarg++] = T_PTRDIFFT;
+ else if (flags & LLONGINT)
+ types->table[types->nextarg++] = T_LLONG;
+ else if (flags & LONGINT)
+ types->table[types->nextarg++] = T_LONG;
+ else
+ types->table[types->nextarg++] = T_INT;
+ return (0);
+}
+
+static inline int
+adduarg(struct typetable *types, int flags)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ if (flags & INTMAXT)
+ types->table[types->nextarg++] = T_UINTMAXT;
+ else if (flags & SIZET)
+ types->table[types->nextarg++] = T_SIZET;
+ else if (flags & PTRDIFFT)
+ types->table[types->nextarg++] = T_SIZET;
+ else if (flags & LLONGINT)
+ types->table[types->nextarg++] = T_U_LLONG;
+ else if (flags & LONGINT)
+ types->table[types->nextarg++] = T_U_LONG;
+ else
+ types->table[types->nextarg++] = T_U_INT;
+ return (0);
+}
+
+/*
+ * Add * arguments to the type array.
+ */
+static inline int
+addaster(struct typetable *types, char **fmtp)
+{
+ char *cp;
+ int n2;
+
+ n2 = 0;
+ cp = *fmtp;
+ while (is_digit(*cp)) {
+ n2 = 10 * n2 + to_digit(*cp);
+ cp++;
+ }
+ if (*cp == '$') {
+ int hold = types->nextarg;
+ types->nextarg = n2;
+ if (addtype(types, T_INT))
+ return (-1);
+ types->nextarg = hold;
+ *fmtp = ++cp;
+ } else {
+ if (addtype(types, T_INT))
+ return (-1);
+ }
+ return (0);
+}
+
+static inline int
+addwaster(struct typetable *types, wchar_t **fmtp)
+{
+ wchar_t *cp;
+ int n2;
+
+ n2 = 0;
+ cp = *fmtp;
+ while (is_digit(*cp)) {
+ n2 = 10 * n2 + to_digit(*cp);
+ cp++;
+ }
+ if (*cp == '$') {
+ int hold = types->nextarg;
+ types->nextarg = n2;
+ if (addtype(types, T_INT))
+ return (-1);
+ types->nextarg = hold;
+ *fmtp = ++cp;
+ } else {
+ if (addtype(types, T_INT))
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Find all arguments when a positional parameter is encountered. Returns a
+ * table, indexed by argument number, of pointers to each arguments. The
+ * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
+ * It will be replaces with a malloc-ed one if it overflows.
+ * Returns 0 on success. On failure, returns nonzero and sets errno.
+ */
+int
+__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
+{
+ char *fmt; /* format string */
+ int ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ int error;
+ int flags; /* flags as above */
+ int width; /* width from format (%8d), or 0 */
+ struct typetable types; /* table of types */
+
+ fmt = (char *)fmt0;
+ inittypes(&types);
+ error = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ while ((ch = *fmt) != '\0' && ch != '%')
+ fmt++;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ width = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ goto rflag;
+ case '*':
+ if ((error = addaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ case '-':
+ case '+':
+ case '\'':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ if ((error = addaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ }
+ while (is_digit(ch)) {
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ types.nextarg = n;
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ error = addtype(&types,
+ (flags & LONGINT) ? T_WINT : T_INT);
+ if (error)
+ goto error;
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if ((error = addsarg(&types, flags)))
+ goto error;
+ break;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
+ (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
+ if (error)
+ goto error;
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ if (flags & INTMAXT)
+ error = addtype(&types, TP_INTMAXT);
+ else if (flags & PTRDIFFT)
+ error = addtype(&types, TP_PTRDIFFT);
+ else if (flags & SIZET)
+ error = addtype(&types, TP_SSIZET);
+ else if (flags & LLONGINT)
+ error = addtype(&types, TP_LLONG);
+ else if (flags & LONGINT)
+ error = addtype(&types, TP_LONG);
+ else if (flags & SHORTINT)
+ error = addtype(&types, TP_SHORT);
+ else if (flags & CHARINT)
+ error = addtype(&types, TP_SCHAR);
+ else
+ error = addtype(&types, TP_INT);
+ if (error)
+ goto error;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ case 'p':
+ if ((error = addtype(&types, TP_VOID)))
+ goto error;
+ break;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ error = addtype(&types,
+ (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
+ if (error)
+ goto error;
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ case 'X':
+ case 'x':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ build_arg_table(&types, ap, argtable);
+error:
+ freetypes(&types);
+ return (error || *argtable == NULL);
+}
+
+/* wchar version of __find_arguments. */
+int
+__find_warguments (const wchar_t *fmt0, va_list ap, union arg **argtable)
+{
+ wchar_t *fmt; /* format string */
+ wchar_t ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ int error;
+ int flags; /* flags as above */
+ int width; /* width from format (%8d), or 0 */
+ struct typetable types; /* table of types */
+
+ fmt = (wchar_t *)fmt0;
+ inittypes(&types);
+ error = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ while ((ch = *fmt) != '\0' && ch != '%')
+ fmt++;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ width = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ goto rflag;
+ case '*':
+ if ((error = addwaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ case '-':
+ case '+':
+ case '\'':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ if ((error = addwaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ }
+ while (is_digit(ch)) {
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ types.nextarg = n;
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ error = addtype(&types,
+ (flags & LONGINT) ? T_WINT : T_INT);
+ if (error)
+ goto error;
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if ((error = addsarg(&types, flags)))
+ goto error;
+ break;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
+ (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
+ if (error)
+ goto error;
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ if (flags & INTMAXT)
+ error = addtype(&types, TP_INTMAXT);
+ else if (flags & PTRDIFFT)
+ error = addtype(&types, TP_PTRDIFFT);
+ else if (flags & SIZET)
+ error = addtype(&types, TP_SSIZET);
+ else if (flags & LLONGINT)
+ error = addtype(&types, TP_LLONG);
+ else if (flags & LONGINT)
+ error = addtype(&types, TP_LONG);
+ else if (flags & SHORTINT)
+ error = addtype(&types, TP_SHORT);
+ else if (flags & CHARINT)
+ error = addtype(&types, TP_SCHAR);
+ else
+ error = addtype(&types, TP_INT);
+ if (error)
+ goto error;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ case 'p':
+ if ((error = addtype(&types, TP_VOID)))
+ goto error;
+ break;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ error = addtype(&types,
+ (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
+ if (error)
+ goto error;
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ case 'X':
+ case 'x':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ build_arg_table(&types, ap, argtable);
+error:
+ freetypes(&types);
+ return (error || *argtable == NULL);
+}
+
+/*
+ * Increase the size of the type table. Returns 0 on success.
+ */
+static int
+__grow_type_table(struct typetable *types)
+{
+ enum typeid *const oldtable = types->table;
+ const int oldsize = types->tablesize;
+ enum typeid *newtable;
+ int n, newsize = oldsize * 2;
+
+ if (newsize < types->nextarg + 1)
+ newsize = types->nextarg + 1;
+ if (oldsize == STATIC_ARG_TBL_SIZE) {
+ if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
+ return (-1);
+ bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
+ } else {
+ newtable = realloc(oldtable, newsize * sizeof(enum typeid));
+ if (newtable == NULL)
+ return (-1);
+ }
+ for (n = oldsize; n < newsize; n++)
+ newtable[n] = T_UNUSED;
+
+ types->table = newtable;
+ types->tablesize = newsize;
+
+ return (0);
+}
+
+/*
+ * Build the argument table from the completed type table.
+ * On malloc failure, *argtable is set to NULL.
+ */
+static void
+build_arg_table(struct typetable *types, va_list ap, union arg **argtable)
+{
+ int n;
+
+ if (types->tablemax >= STATIC_ARG_TBL_SIZE) {
+ *argtable = (union arg *)
+ malloc (sizeof (union arg) * (types->tablemax + 1));
+ if (*argtable == NULL)
+ return;
+ }
+
+ (*argtable) [0].intarg = 0;
+ for (n = 1; n <= types->tablemax; n++) {
+ switch (types->table[n]) {
+ case T_UNUSED: /* whoops! */
+ (*argtable) [n].intarg = va_arg (ap, int);
+ break;
+ case TP_SCHAR:
+ (*argtable) [n].pschararg = va_arg (ap, signed char *);
+ break;
+ case TP_SHORT:
+ (*argtable) [n].pshortarg = va_arg (ap, short *);
+ break;
+ case T_INT:
+ (*argtable) [n].intarg = va_arg (ap, int);
+ break;
+ case T_U_INT:
+ (*argtable) [n].uintarg = va_arg (ap, unsigned int);
+ break;
+ case TP_INT:
+ (*argtable) [n].pintarg = va_arg (ap, int *);
+ break;
+ case T_LONG:
+ (*argtable) [n].longarg = va_arg (ap, long);
+ break;
+ case T_U_LONG:
+ (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
+ break;
+ case TP_LONG:
+ (*argtable) [n].plongarg = va_arg (ap, long *);
+ break;
+ case T_LLONG:
+ (*argtable) [n].longlongarg = va_arg (ap, long long);
+ break;
+ case T_U_LLONG:
+ (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
+ break;
+ case TP_LLONG:
+ (*argtable) [n].plonglongarg = va_arg (ap, long long *);
+ break;
+ case T_PTRDIFFT:
+ (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
+ break;
+ case TP_PTRDIFFT:
+ (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
+ break;
+ case T_SIZET:
+ (*argtable) [n].sizearg = va_arg (ap, size_t);
+ break;
+ case T_SSIZET:
+ (*argtable) [n].sizearg = va_arg (ap, ssize_t);
+ break;
+ case TP_SSIZET:
+ (*argtable) [n].pssizearg = va_arg (ap, ssize_t *);
+ break;
+ case T_INTMAXT:
+ (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
+ break;
+ case T_UINTMAXT:
+ (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
+ break;
+ case TP_INTMAXT:
+ (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
+ break;
+ case T_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ (*argtable) [n].doublearg = va_arg (ap, double);
+#endif
+ break;
+ case T_LONG_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ (*argtable) [n].longdoublearg = va_arg (ap, long double);
+#endif
+ break;
+ case TP_CHAR:
+ (*argtable) [n].pchararg = va_arg (ap, char *);
+ break;
+ case TP_VOID:
+ (*argtable) [n].pvoidarg = va_arg (ap, void *);
+ break;
+ case T_WINT:
+ (*argtable) [n].wintarg = va_arg (ap, wint_t);
+ break;
+ case TP_WCHAR:
+ (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
+ break;
+ }
+ }
+}
--- /dev/null
+--- printf-pos.c.orig 2010-10-25 19:45:24.000000000 -0700
++++ printf-pos.c 2010-10-25 19:47:02.000000000 -0700
+@@ -63,7 +63,10 @@ enum typeid {
+ T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
+ T_PTRDIFFT, TP_PTRDIFFT, T_SSIZET, T_SIZET, TP_SSIZET,
+ T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
+- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
++ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR,
++#ifdef VECTORS
++ T_VECTOR,
++#endif
+ };
+
+ /* An expandable array of types. */
+@@ -240,7 +243,7 @@ addwaster(struct typetable *types, wchar
+ * It will be replaces with a malloc-ed one if it overflows.
+ * Returns 0 on success. On failure, returns nonzero and sets errno.
+ */
+-int
++__private_extern__ int
+ __find_arguments (const char *fmt0, va_list ap, union arg **argtable)
+ {
+ char *fmt; /* format string */
+@@ -342,7 +345,11 @@ reswitch: switch (ch) {
+ /*FALLTHROUGH*/
+ case 'c':
+ error = addtype(&types,
++#ifdef VECTORS
++ (flags & LONGINT) ? T_WINT : ((flags & VECTOR) ? T_VECTOR : T_INT));
++#else
+ (flags & LONGINT) ? T_WINT : T_INT);
++#endif
+ if (error)
+ goto error;
+ break;
+@@ -351,6 +358,12 @@ reswitch: switch (ch) {
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
++#ifdef VECTORS
++ if (flags & VECTOR) {
++ if ((error = addtype(&types, T_VECTOR)))
++ goto error;
++ } else
++#endif
+ if ((error = addsarg(&types, flags)))
+ goto error;
+ break;
+@@ -360,10 +373,15 @@ reswitch: switch (ch) {
+ case 'e':
+ case 'E':
+ case 'f':
++ case 'F':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
++#ifdef VECTORS
++ (flags & VECTOR) ? T_VECTOR : ((flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE));
++#else
+ (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
++#endif
+ if (error)
+ goto error;
+ break;
+@@ -392,11 +410,21 @@ reswitch: switch (ch) {
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
++#ifdef VECTORS
++ if (flags & VECTOR) {
++ if ((error = addtype(&types, T_VECTOR)))
++ goto error;
++ } else
++#endif
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ case 'p':
++#ifdef VECTORS
++ if ((error = addtype(&types, (flags & VECTOR) ? T_VECTOR : TP_VOID)))
++#else
+ if ((error = addtype(&types, TP_VOID)))
++#endif
+ goto error;
+ break;
+ case 'S':
+@@ -414,6 +442,12 @@ reswitch: switch (ch) {
+ case 'u':
+ case 'X':
+ case 'x':
++#ifdef VECTORS
++ if (flags & VECTOR) {
++ if ((error = addtype(&types, T_VECTOR)))
++ goto error;
++ } else
++#endif
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+@@ -431,7 +465,7 @@ error:
+ }
+
+ /* wchar version of __find_arguments. */
+-int
++__private_extern__ int
+ __find_warguments (const wchar_t *fmt0, va_list ap, union arg **argtable)
+ {
+ wchar_t *fmt; /* format string */
+@@ -551,6 +585,7 @@ reswitch: switch (ch) {
+ case 'e':
+ case 'E':
+ case 'f':
++ case 'F':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
+@@ -741,6 +776,11 @@ build_arg_table(struct typetable *types,
+ (*argtable) [n].longdoublearg = va_arg (ap, long double);
+ #endif
+ break;
++#ifdef VECTORS
++ case T_VECTOR:
++ (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
++ break;
++#endif /* VECTORS */
+ case TP_CHAR:
+ (*argtable) [n].pchararg = va_arg (ap, char *);
+ break;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/printf.3,v 1.58 2004/10/16 16:00:01 stefanf Exp $
+.\" $FreeBSD: src/lib/libc/stdio/printf.3,v 1.64 2009/12/02 07:51:25 brueffer Exp $
.\"
-.Dd October 16, 2004
+.Dd December 2, 2009
.Dt PRINTF 3
.Os
.Sh NAME
-.Nm printf , fprintf , sprintf , snprintf , asprintf ,
-.Nm vprintf , vfprintf, vsprintf , vsnprintf , vasprintf
+.Nm printf , fprintf , sprintf , snprintf , asprintf , dprintf ,
+.Nm vprintf , vfprintf, vsprintf , vsnprintf , vasprintf, vdprintf
.Nd formatted output conversion
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
+.Fd "#define _WITH_DPRINTF"
.In stdio.h
.Ft int
.Fn printf "const char * restrict format" ...
.Fn snprintf "char * restrict str" "size_t size" "const char * restrict format" ...
.Ft int
.Fn asprintf "char **ret" "const char *format" ...
+.Ft int
+.Fn dprintf "int fd" "const char * restrict format" ...
.In stdarg.h
.Ft int
.Fn vprintf "const char * restrict format" "va_list ap"
.Fn vsnprintf "char * restrict str" "size_t size" "const char * restrict format" "va_list ap"
.Ft int
.Fn vasprintf "char **ret" "const char *format" "va_list ap"
+.Ft int
+.Fn vdprintf "int fd" "const char * restrict format" "va_list ap"
.Sh DESCRIPTION
The
.Fn printf
.Fn vfprintf
write output to the given output
.Fa stream ;
+.Fn dprintf
+and
+.Fn vdprintf
+write output to the given file descriptor;
.Fn sprintf ,
.Fn snprintf ,
.Fn vsprintf ,
For
.Cm o
conversions, the precision of the number is increased to force the first
-character of the output string to a zero (except if a zero value is printed
-with an explicit precision of zero).
+character of the output string to a zero.
For
.Cm x
and
Note that there may be multiple valid ways to represent floating-point
numbers in this hexadecimal format.
For example,
-.Li 0x3.24p+0 , 0x6.48p-1
+.Li 0x1.92p+1 , 0x3.24p+0 , 0x6.48p-1 ,
and
.Li 0xc.9p-2
are all equivalent.
-The format chosen depends on the internal representation of the
-number, but the implementation guarantees that the length of the
-mantissa will be minimized.
+.Fx 8.0
+and later always prints finite non-zero numbers using
+.Ql 1
+as the digit before the hexadecimal point.
Zeroes are always represented with a mantissa of 0 (preceded by a
.Ql -
if appropriate) and an exponent of
Always use the proper secure idiom:
.Pp
.Dl "snprintf(buffer, sizeof(buffer), \*q%s\*q, string);"
+.Sh COMPATIBILITY
+Many application writers used the name
+.Va dprintf
+before the
+.Fn dprintf
+function was introduced in
+.St -p1003.1 ,
+so a prototype is not provided by default in order to avoid
+compatibility problems.
+Applications that wish to use the
+.Fn dprintf
+function described herein should either request a strict
+.St -p1003.1-2008
+environment by defining the macro
+.Dv _POSIX_C_SOURCE
+to the value 200809 or greater, or by defining the macro
+.Dv _WITH_DPRINTF ,
+prior to the inclusion of
+.In stdio.h .
+For compatibility with GNU libc, defining either
+.Dv _BSD_SOURCE
+or
+.Dv _GNU_SOURCE
+prior to the inclusion of
+.In stdio.h
+will also make
+.Fn dprintf
+available.
+.Pp
+The conversion formats
+.Cm \&%D , \&%O ,
+and
+.Cm %U
+are not standard and
+are provided only for backward compatibility.
+The effect of padding the
+.Cm %p
+format with zeros (either by the
+.Cm 0
+flag or by specifying a precision), and the benign effect (i.e., none)
+of the
+.Cm #
+flag on
+.Cm %n
+and
+.Cm %p
+conversions, as well as other
+nonsensical combinations such as
+.Cm %Ld ,
+are not standard; such combinations
+should be avoided.
.Sh ERRORS
In addition to the errors documented for the
.Xr write 2
.Xr scanf 3 ,
.Xr setlocale 3 ,
.Xr wprintf 3
-.Rs
-.%T "The FreeBSD Security Architecture"
-.Re
-(See
-.Pa "/usr/share/doc/{to be determined}" . )
.Sh STANDARDS
Subject to the caveats noted in the
.Sx BUGS
and
.Fn vsnprintf
functions conform to
-.St -isoC-99 .
+.St -isoC-99 ,
+while
+.Fn dprintf
+and
+.Fn vdprintf
+conform to
+.St -p1003.1-2008 .
.Sh HISTORY
The functions
.Fn asprintf
.An Todd C. Miller Aq Todd.Miller@courtesan.com
for
.Ox 2.3 .
-.Sh BUGS
-The conversion formats
-.Cm \&%D , \&%O ,
-and
-.Cm %U
-are not standard and
-are provided only for backward compatibility.
-The effect of padding the
-.Cm %p
-format with zeros (either by the
-.Cm 0
-flag or by specifying a precision), and the benign effect (i.e., none)
-of the
-.Cm #
-flag on
-.Cm %n
+The
+.Fn dprintf
and
-.Cm %p
-conversions, as well as other
-nonsensical combinations such as
-.Cm %Ld ,
-are not standard; such combinations
-should be avoided.
-.Pp
+.Fn vdprintf
+functions were added in
+.Fx 8.0 .
+.Sh BUGS
The
.Nm
family of functions do not correctly handle multibyte characters in the
---- printf.3.orig 2008-02-29 10:45:39.000000000 -0800
-+++ printf.3 2008-02-29 12:19:06.000000000 -0800
-@@ -40,39 +40,83 @@
- .Dt PRINTF 3
- .Os
- .Sh NAME
--.Nm printf , fprintf , sprintf , snprintf , asprintf ,
--.Nm vprintf , vfprintf, vsprintf , vsnprintf , vasprintf
-+.Nm asprintf ,
-+.Nm fprintf ,
-+.Nm printf ,
-+.Nm snprintf ,
-+.Nm sprintf ,
-+.Nm vasprintf ,
-+.Nm vfprintf,
-+.Nm vprintf ,
-+.Nm vsnprintf ,
-+.Nm vsprintf
- .Nd formatted output conversion
+--- printf.3.orig 2009-12-15 17:50:20.000000000 -0800
++++ printf.3 2009-12-15 17:58:46.000000000 -0800
+@@ -42,7 +42,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
+-.Fd "#define _WITH_DPRINTF"
.In stdio.h
.Ft int
--.Fn printf "const char * restrict format" ...
-+.Fo asprintf
-+.Fa "char **ret"
-+.Fa "const char *format" ...
-+.Fc
- .Ft int
--.Fn fprintf "FILE * restrict stream" "const char * restrict format" ...
-+.Fo fprintf
-+.Fa "FILE *restrict stream"
-+.Fa "const char *restrict format" ...
-+.Fc
- .Ft int
--.Fn sprintf "char * restrict str" "const char * restrict format" ...
-+.Fo printf
-+.Fa "const char *restrict format" ...
-+.Fc
- .Ft int
--.Fn snprintf "char * restrict str" "size_t size" "const char * restrict format" ...
-+.Fo snprintf
-+.Fa "char *restrict s"
-+.Fa "size_t n"
-+.Fa "const char *restrict format" ...
-+.Fc
- .Ft int
--.Fn asprintf "char **ret" "const char *format" ...
-+.Fo sprintf
-+.Fa "char *restrict s"
-+.Fa "const char *restrict format" ...
-+.Fc
- .In stdarg.h
-+.In stdio.h
- .Ft int
--.Fn vprintf "const char * restrict format" "va_list ap"
-+.Fo vasprintf
-+.Fa "char **ret"
-+.Fa "const char *format"
-+.Fa "va_list ap"
-+.Fc
- .Ft int
--.Fn vfprintf "FILE * restrict stream" "const char * restrict format" "va_list ap"
-+.Fo vfprintf
-+.Fa "FILE *restrict stream"
-+.Fa "const char *restrict format"
-+.Fa "va_list ap"
-+.Fc
- .Ft int
--.Fn vsprintf "char * restrict str" "const char * restrict format" "va_list ap"
-+.Fo vprintf
-+.Fa "const char *restrict format"
-+.Fa "va_list ap"
-+.Fc
- .Ft int
--.Fn vsnprintf "char * restrict str" "size_t size" "const char * restrict format" "va_list ap"
-+.Fo vsnprintf
-+.Fa "char *restrict s"
-+.Fa "size_t n"
-+.Fa "const char *restrict format"
-+.Fa "va_list ap"
-+.Fc
- .Ft int
--.Fn vasprintf "char **ret" "const char *format" "va_list ap"
-+.Fo vsprintf
-+.Fa "char *restrict s"
-+.Fa "const char *restrict format"
-+.Fa "va_list ap"
-+.Fc
- .Sh DESCRIPTION
- The
- .Fn printf
- family of functions produces output according to a
--.Fa format
-+.Fa format ,
- as described below.
- The
- .Fn printf
-@@ -93,7 +137,7 @@
+ .Fn printf "const char * restrict format" ...
+@@ -98,7 +97,7 @@ write output to the given file descripto
and
.Fn vsnprintf
write to the character string
and
.Fn asprintf
and
-@@ -101,6 +145,12 @@
+@@ -106,6 +105,12 @@ and
dynamically allocate a new string with
.Xr malloc 3 .
.Pp
These functions write the output under the control of a
.Fa format
string that specifies how subsequent arguments
-@@ -117,7 +167,7 @@
+@@ -122,7 +127,7 @@ except for
and
.Fn vsnprintf ,
which return the number of characters that would have been printed if the
were unlimited
(again, not including the final
.Ql \e0 ) .
-@@ -149,14 +199,14 @@
+@@ -154,14 +159,14 @@ and
.Fn vsnprintf
functions
will write at most
argument, the string was too short
and some of the printed characters were discarded.
The output is always null-terminated.
-@@ -167,7 +217,11 @@
+@@ -172,7 +177,11 @@ and
.Fn vsprintf
functions
effectively assume an infinite
.Pp
The format string is composed of zero or more directives:
ordinary
-@@ -287,6 +341,20 @@
+@@ -291,6 +300,20 @@ the non-monetary separator returned by
.Xr localeconv 3 .
.El
.It
An optional decimal digit string specifying a minimum field width.
If the converted value has fewer characters than the field width, it will
be padded with spaces on the left (or right, if the left-adjustment
-@@ -379,6 +447,34 @@
+@@ -383,6 +406,34 @@ conversion:
.It Sy Modifier Ta Cm c Ta Cm s
.It Cm l No (ell) Ta Vt wint_t Ta Vt "wchar_t *"
.El
.It
A character that specifies the type of conversion to be applied.
.El
-@@ -790,14 +886,11 @@
+@@ -561,10 +612,9 @@ For example,
+ and
+ .Li 0xc.9p-2
+ are all equivalent.
+-.Fx 8.0
+-and later always prints finite non-zero numbers using
+-.Ql 1
+-as the digit before the hexadecimal point.
++The format chosen depends on the internal representation of the
++number, but the implementation guarantees that the length of the
++mantissa will be minimized.
+ Zeroes are always represented with a mantissa of 0 (preceded by a
+ .Ql -
+ if appropriate) and an exponent of
+@@ -781,34 +831,6 @@ Always use the proper secure idiom:
+ .Pp
+ .Dl "snprintf(buffer, sizeof(buffer), \*q%s\*q, string);"
+ .Sh COMPATIBILITY
+-Many application writers used the name
+-.Va dprintf
+-before the
+-.Fn dprintf
+-function was introduced in
+-.St -p1003.1 ,
+-so a prototype is not provided by default in order to avoid
+-compatibility problems.
+-Applications that wish to use the
+-.Fn dprintf
+-function described herein should either request a strict
+-.St -p1003.1-2008
+-environment by defining the macro
+-.Dv _POSIX_C_SOURCE
+-to the value 200809 or greater, or by defining the macro
+-.Dv _WITH_DPRINTF ,
+-prior to the inclusion of
+-.In stdio.h .
+-For compatibility with GNU libc, defining either
+-.Dv _BSD_SOURCE
+-or
+-.Dv _GNU_SOURCE
+-prior to the inclusion of
+-.In stdio.h
+-will also make
+-.Fn dprintf
+-available.
+-.Pp
+ The conversion formats
+ .Cm \&%D , \&%O ,
+ and
+@@ -845,9 +867,11 @@ Insufficient storage space is available.
+ .El
.Sh SEE ALSO
.Xr printf 1 ,
- .Xr fmtcheck 3 ,
+.Xr printf_l 3 ,
+ .Xr fmtcheck 3 ,
.Xr scanf 3 ,
.Xr setlocale 3 ,
+.Xr stdarg 3 ,
.Xr wprintf 3
--.Rs
--.%T "The FreeBSD Security Architecture"
--.Re
--(See
--.Pa "/usr/share/doc/{to be determined}" . )
.Sh STANDARDS
Subject to the caveats noted in the
- .Sx BUGS
* 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.
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/printf.c,v 1.10 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/printf.c,v 1.11 2007/01/09 00:28:07 imp Exp $");
#include <stdio.h>
#include <stdarg.h>
---- printf.c.orig 2003-05-20 15:22:43.000000000 -0700
-+++ printf.c 2005-02-23 16:34:28.000000000 -0800
-@@ -40,6 +40,8 @@
+--- printf.c.bsdnew 2009-11-11 13:33:13.000000000 -0800
++++ printf.c 2009-11-11 13:33:13.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)printf.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/printf.c,v 1.10 2002/09/06 11:23:55 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/printf.c,v 1.11 2007/01/09 00:28:07 imp Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
#include <stdarg.h>
-@@ -50,7 +52,20 @@
+@@ -46,7 +48,20 @@ printf(char const * __restrict fmt, ...)
va_list ap;
va_start(ap, fmt);
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ *
+ * $FreeBSD: src/lib/libc/stdio/printfcommon.h,v 1.4 2009/01/22 08:14:28 das Exp $
+ */
+
+/*
+ * This file defines common routines used by both printf and wprintf.
+ * You must define CHAR to either char or wchar_t prior to including this.
+ */
+
+
+#ifndef NO_FLOATING_POINT
+
+#define dtoa __dtoa
+#define freedtoa __freedtoa
+
+#include <float.h>
+#include <math.h>
+#include "floatio.h"
+#include "gdtoa.h"
+
+#define DEFPREC 6
+
+static int exponent(CHAR *, int, CHAR);
+
+#endif /* !NO_FLOATING_POINT */
+
+static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
+static CHAR *__ultoa(u_long, CHAR *, int, int, const char *);
+
+#define NIOV 8
+struct io_state {
+ FILE *fp;
+ struct __suio uio; /* output information: summary */
+ struct __siov iov[NIOV];/* ... and individual io vectors */
+};
+
+static inline void
+io_init(struct io_state *iop, FILE *fp)
+{
+
+ iop->uio.uio_iov = iop->iov;
+ iop->uio.uio_resid = 0;
+ iop->uio.uio_iovcnt = 0;
+ iop->fp = fp;
+}
+
+/*
+ * WARNING: The buffer passed to io_print() is not copied immediately; it must
+ * remain valid until io_flush() is called.
+ */
+static inline int
+io_print(struct io_state *iop, const CHAR * __restrict ptr, int len)
+{
+
+ iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr;
+ iop->iov[iop->uio.uio_iovcnt].iov_len = len;
+ iop->uio.uio_resid += len;
+ if (++iop->uio.uio_iovcnt >= NIOV)
+ return (__sprint(iop->fp, &iop->uio));
+ else
+ return (0);
+}
+
+/*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+static const CHAR blanks[PADSIZE] =
+{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+static const CHAR zeroes[PADSIZE] =
+{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+/*
+ * Pad with blanks or zeroes. 'with' should point to either the blanks array
+ * or the zeroes array.
+ */
+static inline int
+io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
+{
+ int n;
+
+ while (howmany > 0) {
+ n = (howmany >= PADSIZE) ? PADSIZE : howmany;
+ if (io_print(iop, with, n))
+ return (-1);
+ howmany -= n;
+ }
+ return (0);
+}
+
+/*
+ * Print exactly len characters of the string spanning p to ep, truncating
+ * or padding with 'with' as necessary.
+ */
+static inline int
+io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
+ int len, const CHAR * __restrict with)
+{
+ int p_len;
+
+ p_len = ep - p;
+ if (p_len > len)
+ p_len = len;
+ if (p_len > 0) {
+ if (io_print(iop, p, p_len))
+ return (-1);
+ } else {
+ p_len = 0;
+ }
+ return (io_pad(iop, len - p_len, with));
+}
+
+static inline int
+io_flush(struct io_state *iop)
+{
+
+ return (__sprint(iop->fp, &iop->uio));
+}
+
+/*
+ * Convert an unsigned long to ASCII for printf purposes, returning
+ * a pointer to the first character of the string representation.
+ * Octal numbers can be forced to have a leading zero; hex numbers
+ * use the given digits.
+ */
+static CHAR *
+__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ long sval;
+
+ /*
+ * Handle the three cases separately, in the hope of getting
+ * better/faster code.
+ */
+ switch (base) {
+ case 10:
+ if (val < 10) { /* many numbers are 1 digit */
+ *--cp = to_char(val);
+ return (cp);
+ }
+ /*
+ * On many machines, unsigned arithmetic is harder than
+ * signed arithmetic, so we do at most one unsigned mod and
+ * divide; this is sufficient to reduce the range of
+ * the incoming value to where signed arithmetic works.
+ */
+ if (val > LONG_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default: /* oops */
+ abort();
+ }
+ return (cp);
+}
+
+/* Identical to __ultoa, but for intmax_t. */
+static CHAR *
+__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ intmax_t sval;
+
+ /* quick test for small values; __ultoa is typically much faster */
+ /* (perhaps instead we should run until small, then call __ultoa?) */
+ if (val <= ULONG_MAX)
+ return (__ultoa((u_long)val, endp, base, octzero, xdigs));
+ switch (base) {
+ case 10:
+ if (val < 10) {
+ *--cp = to_char(val % 10);
+ return (cp);
+ }
+ if (val > INTMAX_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default:
+ abort();
+ }
+ return (cp);
+}
+
+#ifndef NO_FLOATING_POINT
+
+static int
+exponent(CHAR *p0, int exp, CHAR fmtch)
+{
+ CHAR *p, *t;
+ CHAR expbuf[MAXEXPDIG];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + MAXEXPDIG;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
+ }
+ else {
+ /*
+ * Exponents for decimal floating point conversions
+ * (%[eEgG]) must be at least two characters long,
+ * whereas exponents for hexadecimal conversions can
+ * be only one character long.
+ */
+ if (fmtch == 'e' || fmtch == 'E')
+ *p++ = '0';
+ *p++ = to_char(exp);
+ }
+ return (p - p0);
+}
+
+#endif /* !NO_FLOATING_POINT */
--- /dev/null
+--- printfcommon.h.orig 2009-11-12 13:29:57.000000000 -0800
++++ printfcommon.h 2009-11-12 23:50:26.000000000 -0800
+@@ -79,14 +79,14 @@ io_init(struct io_state *iop, FILE *fp)
+ * remain valid until io_flush() is called.
+ */
+ static inline int
+-io_print(struct io_state *iop, const CHAR * __restrict ptr, int len)
++io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t loc)
+ {
+
+ iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr;
+ iop->iov[iop->uio.uio_iovcnt].iov_len = len;
+ iop->uio.uio_resid += len;
+ if (++iop->uio.uio_iovcnt >= NIOV)
+- return (__sprint(iop->fp, &iop->uio));
++ return (__sprint(iop->fp, loc, &iop->uio));
+ else
+ return (0);
+ }
+@@ -107,13 +107,13 @@ static const CHAR zeroes[PADSIZE] =
+ * or the zeroes array.
+ */
+ static inline int
+-io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
++io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, locale_t loc)
+ {
+ int n;
+
+ while (howmany > 0) {
+ n = (howmany >= PADSIZE) ? PADSIZE : howmany;
+- if (io_print(iop, with, n))
++ if (io_print(iop, with, n, loc))
+ return (-1);
+ howmany -= n;
+ }
+@@ -126,7 +126,7 @@ io_pad(struct io_state *iop, int howmany
+ */
+ static inline int
+ io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
+- int len, const CHAR * __restrict with)
++ int len, const CHAR * __restrict with, locale_t loc)
+ {
+ int p_len;
+
+@@ -134,19 +134,19 @@ io_printandpad(struct io_state *iop, con
+ if (p_len > len)
+ p_len = len;
+ if (p_len > 0) {
+- if (io_print(iop, p, p_len))
++ if (io_print(iop, p, p_len, loc))
+ return (-1);
+ } else {
+ p_len = 0;
+ }
+- return (io_pad(iop, len - p_len, with));
++ return (io_pad(iop, len - p_len, with, loc));
+ }
+
+ static inline int
+-io_flush(struct io_state *iop)
++io_flush(struct io_state *iop, locale_t loc)
+ {
+
+- return (__sprint(iop->fp, &iop->uio));
++ return (__sprint(iop->fp, loc, &iop->uio));
+ }
+
+ /*
+@@ -205,7 +205,7 @@ __ultoa(u_long val, CHAR *endp, int base
+ break;
+
+ default: /* oops */
+- abort();
++ LIBC_ABORT("__ultoa: invalid base=%d", base);
+ }
+ return (cp);
+ }
+@@ -255,7 +255,7 @@ __ujtoa(uintmax_t val, CHAR *endp, int b
+ break;
+
+ default:
+- abort();
++ LIBC_ABORT("__ujtoa: invalid base=%d", base);
+ }
+ return (cp);
+ }
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ *
+ * $FreeBSD: src/lib/libc/stdio/printflocal.h,v 1.3 2009/03/02 04:07:58 das Exp $
+ */
+
+/*
+ * Flags used during conversion.
+ */
+#define ALT 0x001 /* alternate form */
+#define LADJUST 0x004 /* left adjustment */
+#define LONGDBL 0x008 /* long double */
+#define LONGINT 0x010 /* long integer */
+#define LLONGINT 0x020 /* long long integer */
+#define SHORTINT 0x040 /* short integer */
+#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
+#define FPT 0x100 /* Floating point number */
+#define GROUPING 0x200 /* use grouping ("'" flag) */
+ /* C99 additional size modifiers: */
+#define SIZET 0x400 /* size_t */
+#define PTRDIFFT 0x800 /* ptrdiff_t */
+#define INTMAXT 0x1000 /* intmax_t */
+#define CHARINT 0x2000 /* print char using int format */
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) ((unsigned)to_digit(c) <= 9)
+#define to_char(n) ((n) + '0')
+
+/* Size of the static argument table. */
+#define STATIC_ARG_TBL_SIZE 8
+
+union arg {
+ int intarg;
+ u_int uintarg;
+ long longarg;
+ u_long ulongarg;
+ long long longlongarg;
+ unsigned long long ulonglongarg;
+ ptrdiff_t ptrdiffarg;
+ size_t sizearg;
+ intmax_t intmaxarg;
+ uintmax_t uintmaxarg;
+ void *pvoidarg;
+ char *pchararg;
+ signed char *pschararg;
+ short *pshortarg;
+ int *pintarg;
+ long *plongarg;
+ long long *plonglongarg;
+ ptrdiff_t *pptrdiffarg;
+ ssize_t *pssizearg;
+ intmax_t *pintmaxarg;
+#ifndef NO_FLOATING_POINT
+ double doublearg;
+ long double longdoublearg;
+#endif
+ wint_t wintarg;
+ wchar_t *pwchararg;
+};
+
+/* Handle positional parameters. */
+int __find_arguments(const char *, va_list, union arg **);
+int __find_warguments(const wchar_t *, va_list, union arg **);
--- /dev/null
+--- printflocal.h.orig 2009-11-12 13:40:46.000000000 -0800
++++ printflocal.h 2009-11-12 23:06:25.000000000 -0800
+@@ -32,6 +32,11 @@
+ * $FreeBSD: src/lib/libc/stdio/printflocal.h,v 1.3 2009/03/02 04:07:58 das Exp $
+ */
+
++/*
++ * Defining here VECTORS for all files that include this header (<rdar://problem/8466056>)
++ */
++#define VECTORS
++
+ /*
+ * Flags used during conversion.
+ */
+@@ -49,6 +49,9 @@
+ #define PTRDIFFT 0x800 /* ptrdiff_t */
+ #define INTMAXT 0x1000 /* intmax_t */
+ #define CHARINT 0x2000 /* print char using int format */
++#ifdef VECTORS
++#define VECTOR 0x4000 /* Altivec or SSE vector */
++#endif /* VECTORS */
+
+ /*
+ * Macros for converting digits to letters and vice versa
+@@ -60,6 +63,13 @@
+ /* Size of the static argument table. */
+ #define STATIC_ARG_TBL_SIZE 8
+
++#ifdef VECTORS
++typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
++#ifdef __SSE2__
++#define V64TYPE
++#endif /* __SSE2__ */
++#endif /* VECTORS */
++
+ union arg {
+ int intarg;
+ u_int uintarg;
+@@ -87,6 +97,21 @@ union arg {
+ #endif
+ wint_t wintarg;
+ wchar_t *pwchararg;
++#ifdef VECTORS
++ VECTORTYPE vectorarg;
++ unsigned char vuchararg[16];
++ signed char vchararg[16];
++ unsigned short vushortarg[8];
++ signed short vshortarg[8];
++ unsigned int vuintarg[4];
++ signed int vintarg[4];
++ float vfloatarg[4];
++#ifdef V64TYPE
++ double vdoublearg[2];
++ unsigned long long vulonglongarg[2];
++ long long vlonglongarg[2];
++#endif /* V64TYPE */
++#endif /* VECTORS */
+ };
+
+ /* Handle positional parameters. */
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/putc.3,v 1.15 2004/03/17 12:46:17 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/putc.3,v 1.16 2007/01/09 00:28:07 imp Exp $
.\"
.Dd January 10, 2003
.Dt PUTC 3
---- _SB/Libc/stdio/FreeBSD/putc.3 2004-11-25 11:38:35.000000000 -0800
-+++ _SB/Libc/stdio/FreeBSD/putc.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -52,17 +52,33 @@
+--- putc.3.bsdnew 2009-11-11 13:33:13.000000000 -0800
++++ putc.3 2009-11-11 13:33:14.000000000 -0800
+@@ -48,17 +48,33 @@
.Sh SYNOPSIS
.In stdio.h
.Ft int
.Sh DESCRIPTION
The
.Fn fputc
-@@ -121,7 +137,7 @@
+@@ -117,7 +133,7 @@ The functions,
.Fn fputc ,
.Fn putc ,
.Fn putchar ,
* 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.
static char sccsid[] = "@(#)putc.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/putc.c,v 1.13 2004/03/19 09:04:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/putc.c,v 1.16 2008/05/05 16:03:52 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
#include "libc_private.h"
#undef putc
+#undef putc_unlocked
int
putc(c, fp)
FUNLOCKFILE(fp);
return (retval);
}
+
+int
+putc_unlocked(int ch, FILE *fp)
+{
+
+ return (__sputc(ch, fp));
+}
* 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.
static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/putchar.c,v 1.13 2004/03/19 09:04:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/putchar.c,v 1.16 2008/05/05 16:03:52 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
#include "libc_private.h"
#undef putchar
+#undef putchar_unlocked
/*
* A subroutine version of the macro putchar
FUNLOCKFILE(so);
return (retval);
}
+
+int
+putchar_unlocked(int ch)
+{
+
+ return (__sputc(ch, stdout));
+}
* 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.
static char sccsid[] = "@(#)puts.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/puts.c,v 1.10 2004/03/10 09:15:38 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/puts.c,v 1.11 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <stdio.h>
---- /Volumes/XDisk/tmp/Libc/stdio/FreeBSD/puts.c.orig 2004-03-10 01:15:38.000000000 -0800
-+++ /Volumes/XDisk/tmp/Libc/stdio/FreeBSD/puts.c 2004-10-24 17:08:31.000000000 -0700
-@@ -48,6 +48,9 @@
+--- puts.c.bsdnew 2009-11-11 13:33:14.000000000 -0800
++++ puts.c 2009-11-11 13:33:14.000000000 -0800
+@@ -44,6 +44,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/p
#include "libc_private.h"
#include "local.h"
/*
* Write the given string to stdout, appending a newline.
*/
-@@ -56,12 +59,15 @@
+@@ -52,12 +55,15 @@ puts(s)
char const *s;
{
int retval;
* 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.
static char sccsid[] = "@(#)putw.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/putw.c,v 1.9 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/putw.c,v 1.10 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/putwc.3,v 1.7 2004/03/16 13:30:11 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/putwc.3,v 1.8 2007/01/09 00:28:07 imp Exp $
.\"
.Dd March 3, 2004
.Dt PUTWC 3
---- putwc.3 2004-11-25 11:38:35.000000000 -0800
-+++ putwc.3.edit 2006-08-09 13:41:39.000000000 -0700
-@@ -52,11 +52,19 @@
+--- putwc.3.bsdnew 2009-11-11 13:33:14.000000000 -0800
++++ putwc.3 2009-11-11 13:33:14.000000000 -0800
+@@ -48,11 +48,19 @@
.In stdio.h
.In wchar.h
.Ft wint_t
.Sh DESCRIPTION
The
.Fn fputwc
-@@ -79,6 +87,12 @@
+@@ -75,6 +83,12 @@ is identical to
.Fn putwc
with an output stream of
.Dv stdout .
.Sh RETURN VALUES
The
.Fn fputwc ,
-@@ -95,6 +109,7 @@
+@@ -91,6 +105,7 @@ is returned.
.Xr fopen 3 ,
.Xr getwc 3 ,
.Xr putc 3 ,
* 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.
static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/refill.c,v 1.18 2002/08/13 09:30:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/refill.c,v 1.20 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <errno.h>
if (HASUB(fp)) {
FREEUB(fp);
if ((fp->_r = fp->_ur) != 0) {
- fp->_p = fp->_extra->_up;
+ fp->_p = fp->_up;
return (0);
}
}
---- refill.c.orig 2008-01-24 17:13:42.000000000 -0800
-+++ refill.c 2008-02-17 13:19:27.000000000 -0800
-@@ -68,8 +68,8 @@ lflush(FILE *fp)
+--- refill.c.bsdnew 2009-11-11 13:33:14.000000000 -0800
++++ refill.c 2009-11-11 13:33:14.000000000 -0800
+@@ -64,8 +64,8 @@ lflush(FILE *fp)
* Refill a stdio buffer.
* Return EOF on eof or error, 0 otherwise.
*/
{
/* make sure stdio is set up */
-@@ -134,6 +134,13 @@ __srefill(FILE *fp)
+@@ -130,6 +130,13 @@ __srefill(FILE *fp)
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
__sflush(fp);
}
fp->_p = fp->_bf._base;
fp->_r = _sread(fp, (char *)fp->_p, fp->_bf._size);
fp->_flags &= ~__SMOD; /* buffer contents are again pristine */
-@@ -148,3 +155,13 @@ __srefill(FILE *fp)
+@@ -144,3 +151,13 @@ __srefill(FILE *fp)
}
return (0);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)remove.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/remove.3,v 1.9 2001/10/01 16:08:59 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/remove.3,v 1.10 2007/01/09 00:28:07 imp Exp $
.\"
.Dd June 4, 1993
.Dt REMOVE 3
---- _SB/Libc/stdio/FreeBSD/remove.3 2003-05-20 15:22:43.000000000 -0700
-+++ _SB/Libc/stdio/FreeBSD/remove.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -72,7 +72,7 @@
+--- remove.3.bsdnew 2009-11-11 13:33:15.000000000 -0800
++++ remove.3 2009-11-11 13:33:15.000000000 -0800
+@@ -68,7 +68,7 @@ may fail and set
.Va errno
for any of the errors specified for the routines
.Xr lstat 2 ,
* 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.
static char sccsid[] = "@(#)remove.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/remove.c,v 1.8 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/remove.c,v 1.9 2007/01/09 00:28:07 imp Exp $");
#include <sys/types.h>
#include <sys/stat.h>
* 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.
static char sccsid[] = "@(#)rewind.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/rewind.c,v 1.11 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/rewind.c,v 1.12 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <errno.h>
-Index: rewind.c
-===================================================================
-RCS file: /cvs/root/Libc/stdio/FreeBSD/rewind.c,v
-retrieving revision 1.2
-diff -u -d -b -w -p -u -r1.2 rewind.c
---- rewind.c 2003/05/20 22:22:43 1.2
-+++ rewind.c 2004/10/27 05:51:34
-@@ -58,8 +58,8 @@ rewind(FILE *fp)
+--- rewind.c.bsdnew 2009-11-11 13:33:15.000000000 -0800
++++ rewind.c 2009-11-11 13:33:15.000000000 -0800
+@@ -54,8 +54,8 @@ rewind(FILE *fp)
FLOCKFILE(fp);
if (_fseeko(fp, (off_t)0, SEEK_SET, 1) == 0) {
* 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.
static char sccsid[] = "@(#)rget.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/rget.c,v 1.5 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/rget.c,v 1.6 2007/01/09 00:28:07 imp Exp $");
#include <stdio.h>
#include "local.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/stdio/scanf.3,v 1.24 2003/06/28 09:03:25 das Exp $
+.\" $FreeBSD: src/lib/libc/stdio/scanf.3,v 1.25 2007/01/09 00:28:07 imp Exp $
.\"
.Dd January 4, 2003
.Dt SCANF 3
---- scanf.3.orig 2008-07-30 01:54:48.000000000 -0700
-+++ scanf.3 2008-07-30 02:06:07.000000000 -0700
-@@ -40,35 +40,55 @@
+--- scanf.3.bsdnew 2009-11-11 13:33:15.000000000 -0800
++++ scanf.3 2009-11-11 13:33:15.000000000 -0800
+@@ -36,35 +36,55 @@
.Dt SCANF 3
.Os
.Sh NAME
as described below.
This format may contain
.Em conversion specifiers ;
-@@ -87,7 +107,8 @@
+@@ -83,7 +103,8 @@ reads input from the stream pointer
and
.Fn sscanf
reads its input from the character string pointed to by
The
.Fn vfscanf
function
-@@ -108,7 +129,8 @@
+@@ -104,7 +125,8 @@ the
.Fn vprintf
and
.Fn vsprintf
Each successive
.Em pointer
argument must correspond properly with
-@@ -132,10 +154,16 @@
+@@ -128,10 +150,16 @@ Scanning stops
when an input character does not match such a format character.
Scanning also stops
when an input conversion cannot be made (see below).
there may be a number of
.Em flag
characters, as follows:
-@@ -415,7 +443,8 @@
+@@ -411,7 +439,8 @@ Matches a pointer value (as printed by
in
.Xr printf 3 ) ;
the next pointer must be a pointer to
.It Cm n
Nothing is expected;
instead, the number of characters consumed thus far from the input
-@@ -440,13 +469,10 @@
+@@ -436,13 +465,10 @@ of
causes an immediate return of
.Dv EOF .
.Sh RETURN VALUES
no conversions were assigned;
typically this is due to an invalid input character,
such as an alphabetic character for a
-@@ -463,6 +489,7 @@
+@@ -459,6 +485,7 @@ the number of conversions which were suc
.Xr getc 3 ,
.Xr mbrtowc 3 ,
.Xr printf 3 ,
.Xr strtod 3 ,
.Xr strtol 3 ,
.Xr strtoul 3 ,
-@@ -473,7 +500,7 @@
+@@ -469,7 +496,7 @@ The functions
.Fn scanf ,
.Fn sscanf ,
.Fn vfscanf ,
* 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.
static char sccsid[] = "@(#)scanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/scanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/scanf.c,v 1.13 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <stdio.h>
---- scanf.c.orig 2003-05-20 15:22:43.000000000 -0700
-+++ scanf.c 2005-02-23 16:37:59.000000000 -0800
-@@ -40,6 +40,8 @@
+--- scanf.c.bsdnew 2009-11-11 13:33:15.000000000 -0800
++++ scanf.c 2009-11-11 13:33:15.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)scanf.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/scanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/scanf.c,v 1.13 2007/01/09 00:28:07 imp Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <stdio.h>
#include <stdarg.h>
-@@ -55,7 +57,22 @@
+@@ -51,7 +53,22 @@ scanf(char const * __restrict fmt, ...)
va_start(ap, fmt);
FLOCKFILE(stdin);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)setbuf.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/setbuf.3,v 1.15 2004/08/24 21:48:21 alfred Exp $
+.\" $FreeBSD: src/lib/libc/stdio/setbuf.3,v 1.17 2007/01/09 00:28:07 imp Exp $
.\"
.Dd June 4, 1993
.Dt SETBUF 3
this buffer will be used instead of the current buffer.
If
.Fa buf
-is not NULL, it is the caller's responsibility to
+is not
+.Dv NULL ,
+it is the caller's responsibility to
.Xr free 3
this buffer after closing the stream.
(If the
---- _SB/Libc/stdio/FreeBSD/setbuf.3 2004-11-25 11:38:35.000000000 -0800
-+++ _SB/Libc/stdio/FreeBSD/setbuf.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -50,21 +50,37 @@
+--- setbuf.3.bsdnew 2009-11-11 13:33:15.000000000 -0800
++++ setbuf.3 2009-11-11 13:33:15.000000000 -0800
+@@ -46,21 +46,37 @@
.Sh SYNOPSIS
.In stdio.h
.Ft void
(typically
.Dv stdin ) .
The function
-@@ -73,17 +89,16 @@
+@@ -69,17 +85,16 @@ may be used to force the block out early
(See
.Xr fclose 3 . )
.Pp
The standard error stream
.Dv stderr
is always unbuffered.
-@@ -93,7 +108,7 @@
+@@ -89,7 +104,7 @@ The
function
may be used to alter the buffering behavior of a stream.
The
* 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.
static char sccsid[] = "@(#)setbuf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/setbuf.c,v 1.4 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/setbuf.c,v 1.5 2007/01/09 00:28:07 imp Exp $");
#include <stdio.h>
#include "local.h"
* 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.
static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/setbuffer.c,v 1.7 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/setbuffer.c,v 1.8 2007/01/09 00:28:07 imp Exp $");
#include <stdio.h>
* 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.
static char sccsid[] = "@(#)setvbuf.c 8.2 (Berkeley) 11/16/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/setvbuf.c,v 1.13 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/setvbuf.c,v 1.14 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <stdio.h>
* 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.
static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/snprintf.c,v 1.20 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/snprintf.c,v 1.22 2008/04/17 22:17:54 jhb Exp $");
#include <limits.h>
#include <stdio.h>
int ret;
va_list ap;
FILE f;
- struct __sFILEX ext;
on = n;
if (n != 0)
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfprintf(&f, fmt, ap);
if (on > 0)
*f._p = '\0';
---- snprintf.c.orig 2003-05-20 15:22:43.000000000 -0700
-+++ snprintf.c 2005-02-23 16:39:33.000000000 -0800
-@@ -40,6 +40,8 @@
+--- snprintf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ snprintf.c 2009-12-02 16:48:44.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)snprintf.c 8
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/snprintf.c,v 1.20 2002/09/06 11:23:55 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/snprintf.c,v 1.22 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
-@@ -67,7 +69,37 @@
- f._bf._size = f._w = n;
- f._extra = &ext;
- INITEXTRA(&f);
+@@ -45,26 +47,24 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/s
+ int
+ snprintf(char * __restrict str, size_t n, char const * __restrict fmt, ...)
+ {
+- size_t on;
+ int ret;
+ va_list ap;
+- FILE f;
+
+- on = n;
+- if (n != 0)
+- n--;
+- if (n > INT_MAX)
+- n = INT_MAX;
+ va_start(ap, fmt);
+- f._file = -1;
+- f._flags = __SWR | __SSTR;
+- f._bf._base = f._p = (unsigned char *)str;
+- f._bf._size = f._w = n;
+- f._orientation = 0;
+- memset(&f._mbstate, 0, sizeof(mbstate_t));
- ret = __vfprintf(&f, fmt, ap);
-+ ret = __vfprintf(&f, __current_locale(), fmt, ap);
-+ if (on > 0)
-+ *f._p = '\0';
+- if (on > 0)
+- *f._p = '\0';
++ ret = vsnprintf_l(str, n, __current_locale(), fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+snprintf_l(char * __restrict str, size_t n, locale_t loc,
+ char const * __restrict fmt, ...)
+{
-+ size_t on;
+ int ret;
+ va_list ap;
-+ FILE f;
-+ struct __sFILEX ext;
+
-+ NORMALIZE_LOCALE(loc);
-+ on = n;
-+ if (n != 0)
-+ n--;
-+ if (n > INT_MAX)
-+ n = INT_MAX;
+ va_start(ap, fmt);
-+ f._file = -1;
-+ f._flags = __SWR | __SSTR;
-+ f._bf._base = f._p = (unsigned char *)str;
-+ f._bf._size = f._w = n;
-+ f._extra = &ext;
-+ INITEXTRA(&f);
-+ ret = __vfprintf(&f, loc, fmt, ap);
- if (on > 0)
- *f._p = '\0';
++ ret = vsnprintf_l(str, n, loc, fmt, ap);
va_end(ap);
+ return (ret);
+ }
* 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.
static char sccsid[] = "@(#)sprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/sprintf.c,v 1.14 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/sprintf.c,v 1.16 2008/04/17 22:17:54 jhb Exp $");
#include <stdio.h>
#include <stdarg.h>
int ret;
va_list ap;
FILE f;
- struct __sFILEX ext;
f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
va_start(ap, fmt);
ret = __vfprintf(&f, fmt, ap);
va_end(ap);
---- sprintf.c.orig 2003-05-20 15:22:43.000000000 -0700
-+++ sprintf.c 2005-02-23 16:40:52.000000000 -0800
-@@ -40,6 +40,8 @@
+--- sprintf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ sprintf.c 2009-12-02 16:49:29.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)sprintf.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/sprintf.c,v 1.14 2002/09/06 11:23:55 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/sprintf.c,v 1.16 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
-@@ -60,7 +62,29 @@
- f._extra = &ext;
- INITEXTRA(&f);
+@@ -46,17 +48,21 @@ sprintf(char * __restrict str, char cons
+ {
+ int ret;
+ va_list ap;
+- FILE f;
+
+- f._file = -1;
+- f._flags = __SWR | __SSTR;
+- f._bf._base = f._p = (unsigned char *)str;
+- f._bf._size = f._w = INT_MAX;
+- f._orientation = 0;
+- memset(&f._mbstate, 0, sizeof(mbstate_t));
va_start(ap, fmt);
- ret = __vfprintf(&f, fmt, ap);
-+ ret = __vfprintf(&f, __current_locale(), fmt, ap);
++ ret = vsprintf_l(str, __current_locale(), fmt, ap);
+ va_end(ap);
-+ *f._p = 0;
+ return (ret);
+}
+
+{
+ int ret;
+ va_list ap;
-+ FILE f;
-+ struct __sFILEX ext;
+
-+ NORMALIZE_LOCALE(loc);
-+ f._file = -1;
-+ f._flags = __SWR | __SSTR;
-+ f._bf._base = f._p = (unsigned char *)str;
-+ f._bf._size = f._w = INT_MAX;
-+ f._extra = &ext;
-+ INITEXTRA(&f);
+ va_start(ap, fmt);
-+ ret = __vfprintf(&f, loc, fmt, ap);
++ ret = vsprintf_l(str, loc, fmt, ap);
va_end(ap);
- *f._p = 0;
+- *f._p = 0;
return (ret);
+ }
* 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.
static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/sscanf.c,v 1.11 2002/10/12 16:13:41 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/sscanf.c,v 1.13 2008/04/17 22:17:54 jhb Exp $");
#include <stdio.h>
#include <string.h>
{
int ret;
va_list ap;
- struct __sFILEX extra;
FILE f;
f._file = -1;
f._read = eofread;
f._ub._base = NULL;
f._lb._base = NULL;
- f._extra = &extra;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
va_start(ap, fmt);
ret = __svfscanf(&f, fmt, ap);
va_end(ap);
---- sscanf.c.orig 2003-05-20 15:22:44.000000000 -0700
-+++ sscanf.c 2005-02-23 16:42:49.000000000 -0800
-@@ -40,6 +40,8 @@
+--- sscanf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ sscanf.c 2009-12-02 16:50:00.000000000 -0800
+@@ -36,42 +36,33 @@ static char sccsid[] = "@(#)sscanf.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/sscanf.c,v 1.11 2002/10/12 16:13:41 mike Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/sscanf.c,v 1.13 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
-@@ -76,7 +78,31 @@
- f._extra = &extra;
- INITEXTRA(&f);
- va_start(ap, fmt);
-- ret = __svfscanf(&f, fmt, ap);
-+ ret = __svfscanf_l(&f, __current_locale(), fmt, ap);
-+ va_end(ap);
-+ return (ret);
-+}
-+
+ #include "local.h"
+
+-static int eofread(void *, char *, int);
+-
+-/* ARGSUSED */
+-static int
+-eofread(cookie, buf, len)
+- void *cookie;
+- char *buf;
+- int len;
+int
-+sscanf_l(const char * __restrict str, locale_t loc, char const * __restrict fmt, ...)
-+{
++sscanf(const char * __restrict str, char const * __restrict fmt, ...)
+ {
+ int ret;
+ va_list ap;
-+ struct __sFILEX extra;
-+ FILE f;
-+
-+ NORMALIZE_LOCALE(loc);
-+ f._file = -1;
-+ f._flags = __SRD;
-+ f._bf._base = f._p = (unsigned char *)str;
-+ f._bf._size = f._r = strlen(str);
-+ f._read = eofread;
-+ f._ub._base = NULL;
-+ f._lb._base = NULL;
-+ f._extra = &extra;
-+ INITEXTRA(&f);
+
+- return (0);
+ va_start(ap, fmt);
-+ ret = __svfscanf_l(&f, loc, fmt, ap);
++ ret = vsscanf_l(str, __current_locale(), fmt, ap);
++ va_end(ap);
++ return (ret);
+ }
+
+ int
+-sscanf(const char * __restrict str, char const * __restrict fmt, ...)
++sscanf_l(const char * __restrict str, locale_t loc, char const * __restrict fmt, ...)
+ {
+ int ret;
+ va_list ap;
+- FILE f;
+
+- f._file = -1;
+- f._flags = __SRD;
+- f._bf._base = f._p = (unsigned char *)str;
+- f._bf._size = f._r = strlen(str);
+- f._read = eofread;
+- f._ub._base = NULL;
+- f._lb._base = NULL;
+- f._orientation = 0;
+- memset(&f._mbstate, 0, sizeof(mbstate_t));
+ va_start(ap, fmt);
+- ret = __svfscanf(&f, fmt, ap);
++ ret = vsscanf_l(str, loc, fmt, ap);
va_end(ap);
return (ret);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)stdio.3 8.7 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/stdio/stdio.3,v 1.26 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/stdio.3,v 1.30 2009/03/04 03:38:51 das Exp $
.\"
-.Dd January 10, 2003
+.Dd March 3, 2009
.Dt STDIO 3
.Os
.Sh NAME
.Xr open 2 ,
.Xr read 2 ,
.Xr write 2
-.Sh BUGS
-The standard buffered functions do not interact well with certain other
-library and system functions, especially
-.Xr vfork 2 .
.Sh STANDARDS
The
.Nm
.It Sy "Function Description"
.It "asprintf formatted output conversion"
.It "clearerr check and reset stream status"
+.It "dprintf formatted output conversion"
.It "fclose close a stream"
.It "fdopen stream open functions"
.It "feof check and reset stream status"
.It "fwrite binary stream input/output"
.It "getc get next character or word from input stream"
.It "getchar get next character or word from input stream"
+.It "getdelim get a line from a stream"
+.It "getline get a line from a stream"
.It "gets get a line from a stream"
.It "getw get next character or word from input stream"
.It "getwc get next wide character from input stream"
.It "ungetc un-get character from input stream"
.It "ungetwc un-get wide character from input stream"
.It "vasprintf formatted output conversion"
+.It "vdprintf formatted output conversion"
.It "vfprintf formatted output conversion"
.It "vfscanf input format conversion"
.It "vfwprintf formatted wide character output conversion"
.It "vwprintf formatted wide character output conversion"
.It "wprintf formatted wide character output conversion"
.El
+.Sh BUGS
+The standard buffered functions do not interact well with certain other
+library and system functions, especially
+.Xr vfork 2 .
---- stdio.3 2004-11-25 11:38:35.000000000 -0800
-+++ stdio.3.edit 2006-09-06 16:18:21.000000000 -0700
-@@ -45,6 +45,20 @@
+--- stdio.3.bsdnew 2009-11-11 13:33:16.000000000 -0800
++++ stdio.3 2009-11-11 15:14:22.000000000 -0800
+@@ -41,6 +41,20 @@
.Vt FILE *stdin ;
.Vt FILE *stdout ;
.Vt FILE *stderr ;
.Sh DESCRIPTION
The standard
.Tn I/O
-@@ -232,11 +246,21 @@
+@@ -228,11 +242,21 @@ and
.Dv putchar_unlocked
exist and will be used if the macro
definitions are explicitly removed.
-.Xr write 2
+.Xr write 2 ,
+.Xr compat 5
- .Sh BUGS
- The standard buffered functions do not interact well with certain other
- library and system functions, especially
-@@ -250,7 +274,9 @@
+ .Sh STANDARDS
+ The
+ .Nm
+@@ -242,8 +266,9 @@ library conforms to
.Bl -column "Description"
.It Sy "Function Description"
.It "asprintf formatted output conversion"
+.It ""
.It "clearerr check and reset stream status"
+-.It "dprintf formatted output conversion"
+.It ""
.It "fclose close a stream"
.It "fdopen stream open functions"
.It "feof check and reset stream status"
-@@ -282,15 +308,18 @@
+@@ -275,6 +300,7 @@ library conforms to
.It "fwopen open a stream"
.It "fwprintf formatted wide character output conversion"
.It "fwrite binary stream input/output"
+.It ""
.It "getc get next character or word from input stream"
.It "getchar get next character or word from input stream"
- .It "gets get a line from a stream"
+ .It "getdelim get a line from a stream"
+@@ -283,9 +309,11 @@ library conforms to
.It "getw get next character or word from input stream"
.It "getwc get next wide character from input stream"
.It "getwchar get next wide character from input stream"
.It "perror system error messages"
.It "printf formatted output conversion"
.It "putc output a character or word to a stream"
-@@ -299,8 +328,10 @@
+@@ -294,8 +322,10 @@ library conforms to
.It "putw output a character or word to a stream"
.It "putwc output a wide character to a stream"
.It "putwchar output a wide character to a stream"
.It "scanf input format conversion"
.It "setbuf stream buffering operations"
.It "setbuffer stream buffering operations"
-@@ -313,11 +344,14 @@
+@@ -308,13 +338,15 @@ library conforms to
.It "swprintf formatted wide character output conversion"
.It "sys_errlist system error messages"
.It "sys_nerr system error messages"
.It "ungetwc un-get wide character from input stream"
+.It ""
.It "vasprintf formatted output conversion"
+-.It "vdprintf formatted output conversion"
.It "vfprintf formatted output conversion"
.It "vfscanf input format conversion"
-@@ -329,5 +363,6 @@
+ .It "vfwprintf formatted wide character output conversion"
+@@ -325,6 +357,7 @@ library conforms to
.It "vsscanf input format conversion"
.It "vswprintf formatted wide character output conversion"
.It "vwprintf formatted wide character output conversion"
+.It ""
.It "wprintf formatted wide character output conversion"
.El
+ .Sh BUGS
* 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.
static char sccsid[] = "@(#)stdio.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/stdio.c,v 1.24 2003/01/07 06:17:13 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/stdio.c,v 1.28 2008/05/05 16:14:02 jhb Exp $");
#include "namespace.h"
#include <errno.h>
* 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.
static char sccsid[] = "@(#)tempnam.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/tempnam.c,v 1.10 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/tempnam.c,v 1.11 2007/01/09 00:28:07 imp Exp $");
#include <sys/param.h>
#include <errno.h>
---- tempnam.c.orig 2008-11-12 17:08:45.000000000 -0800
-+++ tempnam.c 2008-11-12 17:41:23.000000000 -0800
-@@ -57,35 +57,68 @@ tempnam(dir, pfx)
+--- tempnam.c.orig 2010-10-25 19:45:24.000000000 -0700
++++ tempnam.c 2010-10-25 22:01:51.000000000 -0700
+@@ -53,35 +53,60 @@ tempnam(dir, pfx)
int sverrno;
char *f, *name;
+ }
+#endif /* __DARWIN_UNIX03 */
f = _PATH_TMP;
-+#if __DARWIN_UNIX03
-+ if (access(f, W_OK) < 0) {
-+ f = "./"; /* directory inaccessible */
-+ if (access(f, W_OK) < 0) {
-+ return(NULL);
-+ }
-+ }
-+#endif /* __DARWIN_UNIX03 */
(void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
- if ((f = _mktemp(name)))
+ if ((f = _mktemp(name))) {
* 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.
static char sccsid[] = "@(#)tmpfile.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/tmpfile.c,v 1.9 2003/02/06 01:08:19 mtm Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/tmpfile.c,v 1.10 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)tmpnam.3 8.2 (Berkeley) 11/17/93
-.\" $FreeBSD: src/lib/libc/stdio/tmpnam.3,v 1.16 2004/06/21 19:38:25 mpp Exp $
+.\" $FreeBSD: src/lib/libc/stdio/tmpnam.3,v 1.20 2007/03/16 21:46:24 maxim Exp $
.\"
-.Dd November 17, 1993
+.Dd March 18, 2007
.Dt TMPFILE 3
.Os
.Sh NAME
.Dv NULL
pointer
on error.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev TMPDIR
+.Pf [ Fn tempnam
+only]
+If set,
+the directory in which the temporary file is stored.
+.Ev TMPDIR
+is ignored for processes
+for which
+.Xr issetugid 2
+is true.
+.El
+.Sh COMPATIBILITY
+These interfaces are provided from System V and
+.Tn ANSI
+compatibility only.
+.Pp
+Most historic implementations of these functions provide
+only a limited number of possible temporary file names
+(usually 26)
+before file names will start being recycled.
+System V implementations of these functions
+(and of
+.Xr mktemp 3 )
+use the
+.Xr access 2
+system call to determine whether or not the temporary file
+may be created.
+This has obvious ramifications for setuid or setgid programs,
+complicating the portable use of these interfaces in such programs.
+.Pp
+The
+.Fn tmpfile
+interface should not be used in software expected to be used on other systems
+if there is any possibility that the user does not wish the temporary file to
+be publicly readable and writable.
.Sh ERRORS
The
.Fn tmpfile
be used in place of these functions.
(See
the FSA.)
-.Sh COMPATIBILITY
-These interfaces are provided from System V and
-.Tn ANSI
-compatibility only.
-.Pp
-Most historic implementations of these functions provide
-only a limited number of possible temporary file names
-(usually 26)
-before file names will start being recycled.
-System V implementations of these functions
-(and of
-.Xr mktemp 3 )
-use the
-.Xr access 2
-system call to determine whether or not the temporary file
-may be created.
-This has obvious ramifications for setuid or setgid programs,
-complicating the portable use of these interfaces in such programs.
-.Pp
-The
-.Fn tmpfile
-interface should not be used in software expected to be used on other systems
-if there is any possibility that the user does not wish the temporary file to
-be publicly readable and writable.
.Sh SEE ALSO
.Xr mkstemp 3 ,
.Xr mktemp 3
-.Rs
-.%T "The FreeBSD Security Architecture"
-.Re
-(See
-.Pa "/usr/share/doc/{to be determined}" . )
.Sh STANDARDS
The
.Fn tmpfile
---- tmpnam.3.orig 2008-11-13 16:39:10.000000000 -0800
-+++ tmpnam.3 2008-11-13 16:45:15.000000000 -0800
-@@ -36,7 +36,7 @@
+--- tmpnam.3.bsdnew 2009-11-11 13:33:17.000000000 -0800
++++ tmpnam.3 2009-11-11 15:17:16.000000000 -0800
+@@ -32,7 +32,7 @@
.\" @(#)tmpnam.3 8.2 (Berkeley) 11/17/93
- .\" $FreeBSD: src/lib/libc/stdio/tmpnam.3,v 1.16 2004/06/21 19:38:25 mpp Exp $
+ .\" $FreeBSD: src/lib/libc/stdio/tmpnam.3,v 1.20 2007/03/16 21:46:24 maxim Exp $
.\"
--.Dd November 17, 1993
+-.Dd March 18, 2007
+.Dd November 12, 2008
.Dt TMPFILE 3
.Os
.Sh NAME
-@@ -49,11 +49,18 @@
+@@ -45,11 +45,18 @@
.Sh SYNOPSIS
.In stdio.h
.Ft FILE *
-.Fn tmpfile void
+.Fo tmpfile
-+.Fa void
++.Fa "void"
+.Fc
.Ft char *
-.Fn tmpnam "char *str"
.Sh DESCRIPTION
The
.Fn tmpfile
-@@ -67,12 +74,13 @@
+@@ -63,12 +70,13 @@ returns, causing the file to be automati
reference to it is closed.
The file is opened with the access value
.Ql w+ .
.Pa /tmp .
.Pp
The
-@@ -87,7 +95,7 @@
+@@ -83,7 +91,7 @@ past.
is defined in the include file
.In stdio.h .
If the argument
is
.Pf non- Dv NULL ,
the file name is copied to the buffer it references.
-@@ -97,7 +105,7 @@
+@@ -93,7 +101,7 @@ In either case,
returns a pointer to the file name.
.Pp
The buffer referenced by
is expected to be at least
.Dv L_tmpnam
bytes in length.
-@@ -113,21 +121,23 @@
+@@ -109,21 +117,23 @@ is similar to
but provides the ability to specify the directory which will
contain the temporary file and the file name prefix.
.Pp
if
.Pf non- Dv NULL ,
is used to specify a file name prefix, which will be the
-@@ -226,14 +236,15 @@
- interface should not be used in software expected to be used on other systems
- if there is any possibility that the user does not wish the temporary file to
- be publicly readable and writable.
+@@ -235,6 +245,12 @@ It is strongly suggested that
+ be used in place of these functions.
+ (See
+ the FSA.)
+.Sh LEGACY DESCRIPTION
+In legacy mode, the order directories are tried by the
+.Fn tempnam
.Sh SEE ALSO
.Xr mkstemp 3 ,
.Xr mktemp 3
--.Rs
--.%T "The FreeBSD Security Architecture"
--.Re
--(See
--.Pa "/usr/share/doc/{to be determined}" . )
- .Sh STANDARDS
- The
- .Fn tmpfile
* 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.
static char sccsid[] = "@(#)tmpnam.c 8.3 (Berkeley) 3/28/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/tmpnam.c,v 1.5 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/tmpnam.c,v 1.6 2007/01/09 00:28:07 imp Exp $");
#include <sys/types.h>
--- /dev/null
+--- tmpnam.c.orig 2010-07-06 16:02:20.000000000 -0700
++++ tmpnam.c 2010-07-06 16:32:52.000000000 -0700
+@@ -40,21 +40,35 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/t
+
+ #include <stdio.h>
+ #include <unistd.h>
++#include <pthread.h>
++#include <stdlib.h>
+
+ __warn_references(tmpnam,
+ "warning: tmpnam() possibly used unsafely; consider using mkstemp()");
+
+ extern char *_mktemp(char *);
+
++static char *tmpnam_buf = NULL;
++static pthread_once_t tmpnam_buf_control = PTHREAD_ONCE_INIT;
++
++static void tmpnam_buf_allocate(void)
++{
++ tmpnam_buf = malloc(L_tmpnam);
++}
++
+ char *
+ tmpnam(s)
+ char *s;
+ {
+ static u_long tmpcount;
+- static char buf[L_tmpnam];
+
+- if (s == NULL)
+- s = buf;
++ if (s == NULL) {
++ if (pthread_once(&tmpnam_buf_control, tmpnam_buf_allocate)
++ || !tmpnam_buf) {
++ return NULL;
++ }
++ s = tmpnam_buf;
++ }
+ (void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXX", P_tmpdir, tmpcount);
+ ++tmpcount;
+ return (_mktemp(s));
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ungetc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/ungetc.3,v 1.13 2002/10/10 04:12:40 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/ungetc.3,v 1.14 2007/01/09 00:28:07 imp Exp $
.\"
.Dd June 4, 1993
.Dt UNGETC 3
---- _SB/Libc/stdio/FreeBSD/ungetc.3 2003-05-20 15:22:44.000000000 -0700
-+++ _SB/Libc/stdio/FreeBSD/ungetc.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -47,7 +47,10 @@
+--- ungetc.3.bsdnew 2009-11-11 13:33:17.000000000 -0800
++++ ungetc.3 2009-11-11 13:33:18.000000000 -0800
+@@ -43,7 +43,10 @@
.Sh SYNOPSIS
.In stdio.h
.Ft int
.Sh DESCRIPTION
The
.Fn ungetc
-@@ -56,20 +59,20 @@
+@@ -52,20 +55,20 @@ function pushes the character
(converted to an unsigned char)
back onto the input stream pointed to by
.Fa stream .
* 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.
static char sccsid[] = "@(#)ungetc.c 8.2 (Berkeley) 11/3/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/ungetc.c,v 1.16 2004/03/10 12:41:11 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/ungetc.c,v 1.18 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <stdio.h>
* Initially, we will use the `reserve' buffer.
*/
fp->_ur = fp->_r;
- fp->_extra->_up = fp->_p;
+ fp->_up = fp->_p;
fp->_ub._base = fp->_ubuf;
fp->_ub._size = sizeof(fp->_ubuf);
fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ungetc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/ungetwc.3,v 1.5 2004/03/16 13:30:11 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/ungetwc.3,v 1.6 2007/01/09 00:28:07 imp Exp $
.\"
.Dd March 3, 2004
.Dt UNGETWC 3
---- _SB/Libc/stdio/FreeBSD/ungetwc.3 2004-11-25 11:38:35.000000000 -0800
-+++ _SB/Libc/stdio/FreeBSD/ungetwc.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -42,7 +42,8 @@
+--- ungetwc.3.bsdnew 2009-11-11 13:33:18.000000000 -0800
++++ ungetwc.3 2009-11-11 13:33:18.000000000 -0800
+@@ -38,7 +38,8 @@
.Dt UNGETWC 3
.Os
.Sh NAME
.Nd un-get wide character from input stream
.Sh LIBRARY
.Lb libc
-@@ -50,7 +51,19 @@
+@@ -46,7 +47,19 @@
.In stdio.h
.In wchar.h
.Ft wint_t
.Sh DESCRIPTION
The
.Fn ungetwc
-@@ -60,22 +73,31 @@
+@@ -56,22 +69,31 @@ function pushes the wide character
.Vt wchar_t )
back onto the input stream pointed to by
.Fa stream .
.Sh RETURN VALUES
The
.Fn ungetwc
-@@ -91,7 +113,8 @@
+@@ -87,7 +109,8 @@ character equals
the operation will fail and the stream will remain unchanged.
.Sh SEE ALSO
.Xr fseek 3 ,
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/ungetwc.c,v 1.9 2004/07/20 08:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/ungetwc.c,v 1.11 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
if (wc == WEOF)
return (WEOF);
- if ((len = __wcrtomb(buf, wc, &fp->_extra->mbstate)) == (size_t)-1) {
+ if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
}
---- ungetwc.c.orig 2004-11-25 11:38:35.000000000 -0800
-+++ ungetwc.c 2005-02-23 17:38:14.000000000 -0800
+--- ungetwc.c.bsdnew 2009-11-11 13:33:18.000000000 -0800
++++ ungetwc.c 2009-11-11 16:30:36.000000000 -0800
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/ungetwc.c,v 1.9 2004/07/20 08:27:27 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/ungetwc.c,v 1.11 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <errno.h>
- #include <stdio.h>
-@@ -41,14 +43,14 @@
+ #include <limits.h>
+@@ -42,14 +44,14 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/u
* Non-MT-safe version.
*/
wint_t
if (wc == WEOF)
return (WEOF);
-- if ((len = __wcrtomb(buf, wc, &fp->_extra->mbstate)) == (size_t)-1) {
-+ if ((len = loc->__lc_ctype->__wcrtomb(buf, wc, &fp->_extra->mbstate, loc)) == (size_t)-1) {
+- if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
++ if ((len = loc->__lc_ctype->__wcrtomb(buf, wc, &fp->_mbstate, loc)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
}
-@@ -69,7 +71,21 @@
+@@ -70,7 +72,21 @@ ungetwc(wint_t wc, FILE *fp)
FLOCKFILE(fp);
ORIENT(fp, 1);
+++ /dev/null
-/*-
- * Copyright (c) 2003 Tim J. Robbins.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/unlocked.c,v 1.1 2003/01/10 04:35:08 tjr Exp $");
-
-#include <stdio.h>
-
-#undef getchar_unlocked
-int
-getchar_unlocked(void)
-{
-
- return (__sgetc(stdin));
-}
-
-#undef getc_unlocked
-int
-getc_unlocked(FILE *fp)
-{
-
- return (__sgetc(fp));
-}
-
-#undef putchar_unlocked
-int
-putchar_unlocked(int ch)
-{
-
- return (__sputc(ch, stdout));
-}
-
-#undef putc_unlocked
-int
-putc_unlocked(int ch, FILE *fp)
-{
-
- return (__sputc(ch, fp));
-}
-
-#undef feof_unlocked
-int
-feof_unlocked(FILE *fp)
-{
-
- return (__sfeof(fp));
-}
-
-#undef ferror_unlocked
-int
-ferror_unlocked(FILE *fp)
-{
-
- return (__sferror(fp));
-}
-
-#undef clearerr_unlocked
-void
-clearerr_unlocked(FILE *fp)
-{
-
- __sclearerr(fp);
-}
-
-#undef fileno_unlocked
-int
-fileno_unlocked(FILE *fp)
-{
-
- return (__sfileno(fp));
-}
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.18 2002/09/26 13:11:24 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.19 2008/04/17 22:17:54 jhb Exp $");
#include <stdio.h>
#include <stdlib.h>
{
int ret;
FILE f;
- struct __sFILEX ext;
f._file = -1;
f._flags = __SWR | __SSTR | __SALC;
return (-1);
}
f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfprintf(&f, fmt, ap);
if (ret < 0) {
free(f._bf._base);
---- vasprintf.c.orig 2003-05-20 15:22:44.000000000 -0700
-+++ vasprintf.c 2005-02-23 18:55:18.000000000 -0800
-@@ -30,6 +30,8 @@
+--- vasprintf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ vasprintf.c 2009-12-03 15:19:16.000000000 -0800
+@@ -30,20 +30,27 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.18 2002/09/26 13:11:24 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.19 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
-@@ -56,7 +58,42 @@
- f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
-- ret = __vfprintf(&f, fmt, ap);
-+ ret = __vfprintf(&f, __current_locale(), fmt, ap);
-+ if (ret < 0) {
-+ free(f._bf._base);
-+ *str = NULL;
-+ errno = ENOMEM;
-+ return (-1);
-+ }
-+ *f._p = '\0';
-+ *str = (char *)f._bf._base;
-+ return (ret);
-+}
-+
-+int
+ #include "local.h"
+
+ int
+-vasprintf(str, fmt, ap)
+vasprintf_l(str, loc, fmt, ap)
-+ char **str;
+ char **str;
+ locale_t loc;
-+ const char *fmt;
-+ __va_list ap;
-+{
-+ int ret;
-+ FILE f;
+ const char *fmt;
+ __va_list ap;
+ {
+ int ret;
+ FILE f;
+-
+ struct __sFILEX ext;
-+
-+ NORMALIZE_LOCALE(loc);
-+ f._file = -1;
-+ f._flags = __SWR | __SSTR | __SALC;
-+ f._bf._base = f._p = (unsigned char *)malloc(128);
-+ if (f._bf._base == NULL) {
-+ *str = NULL;
-+ errno = ENOMEM;
-+ return (-1);
-+ }
-+ f._bf._size = f._w = 127; /* Leave room for the NUL */
+ f._extra = &ext;
+ INITEXTRA(&f);
++
++ NORMALIZE_LOCALE(loc);
+ f._file = -1;
+ f._flags = __SWR | __SSTR | __SALC;
+ f._bf._base = f._p = (unsigned char *)malloc(128);
+@@ -55,7 +62,7 @@ vasprintf(str, fmt, ap)
+ f._bf._size = f._w = 127; /* Leave room for the NUL */
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
+- ret = __vfprintf(&f, fmt, ap);
+ ret = __vfprintf(&f, loc, fmt, ap);
if (ret < 0) {
free(f._bf._base);
*str = NULL;
+@@ -66,3 +73,12 @@ vasprintf(str, fmt, ap)
+ *str = (char *)f._bf._base;
+ return (ret);
+ }
++
++int
++vasprintf(str, fmt, ap)
++ char **str;
++ const char *fmt;
++ __va_list ap;
++{
++ return vasprintf_l(str, __current_locale(), fmt, ap);
++}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vdprintf.c,v 1.1 2009/03/04 03:38:51 das Exp $");
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "un-namespace.h"
+
+#include "local.h"
+
+int
+vdprintf(int fd, const char * __restrict fmt, va_list ap)
+{
+ FILE f;
+ unsigned char buf[BUFSIZ];
+ int ret;
+
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+ return (EOF);
+ }
+
+ f._p = buf;
+ f._w = sizeof(buf);
+ f._flags = __SWR;
+ f._file = fd;
+ f._cookie = &f;
+ f._write = __swrite;
+ f._bf._base = buf;
+ f._bf._size = sizeof(buf);
+ f._orientation = 0;
+ bzero(&f._mbstate, sizeof(f._mbstate));
+
+ if ((ret = __vfprintf(&f, fmt, ap)) < 0)
+ return (ret);
+
+ return (__fflush(&f) ? EOF : ret);
+}
--- /dev/null
+--- vdprintf.c.orig 2009-12-15 17:43:09.000000000 -0800
++++ vdprintf.c 2009-12-15 18:09:12.000000000 -0800
+@@ -27,6 +27,8 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vdprintf.c,v 1.1 2009/03/04 03:38:51 das Exp $");
+
++#include "xlocale_private.h"
++
+ #include "namespace.h"
+ #include <errno.h>
+ #include <limits.h>
+@@ -37,11 +39,16 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
+ #include "local.h"
+
+ int
+-vdprintf(int fd, const char * __restrict fmt, va_list ap)
++vdprintf_l(int fd, locale_t loc, const char * __restrict fmt, va_list ap)
+ {
+ FILE f;
+ unsigned char buf[BUFSIZ];
+ int ret;
++ struct __sFILEX ext;
++ f._extra = &ext;
++ INITEXTRA(&f);
++
++ NORMALIZE_LOCALE(loc);
+
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+@@ -59,8 +66,13 @@ vdprintf(int fd, const char * __restrict
+ f._orientation = 0;
+ bzero(&f._mbstate, sizeof(f._mbstate));
+
+- if ((ret = __vfprintf(&f, fmt, ap)) < 0)
++ if ((ret = __vfprintf(&f, loc, fmt, ap)) < 0)
+ return (ret);
+
+ return (__fflush(&f) ? EOF : ret);
+ }
++
++int
++vdprintf(int fd, const char * __restrict fmt, va_list ap) {
++ return vdprintf_l(fd, __current_locale(), fmt, ap);
++}
* 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.
static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.68 2004/08/26 06:25:28 des Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $");
/*
* Actual printf innards.
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#include <printf.h>
#include <stdarg.h>
#include "un-namespace.h"
#include "libc_private.h"
#include "local.h"
#include "fvwrite.h"
+#include "printflocal.h"
-union arg {
- int intarg;
- u_int uintarg;
- long longarg;
- u_long ulongarg;
- long long longlongarg;
- unsigned long long ulonglongarg;
- ptrdiff_t ptrdiffarg;
- size_t sizearg;
- intmax_t intmaxarg;
- uintmax_t uintmaxarg;
- void *pvoidarg;
- char *pchararg;
- signed char *pschararg;
- short *pshortarg;
- int *pintarg;
- long *plongarg;
- long long *plonglongarg;
- ptrdiff_t *pptrdiffarg;
- size_t *psizearg;
- intmax_t *pintmaxarg;
-#ifndef NO_FLOATING_POINT
- double doublearg;
- long double longdoublearg;
-#endif
- wint_t wintarg;
- wchar_t *pwchararg;
+static int __sprint(FILE *, struct __suio *);
+static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0)
+ __noinline;
+static char *__wcsconv(wchar_t *, int);
+
+#define CHAR char
+#include "printfcommon.h"
+
+struct grouping_state {
+ char *thousands_sep; /* locale-specific thousands separator */
+ int thousep_len; /* length of thousands_sep */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
};
/*
- * Type ids for argument type table.
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of bytes that will be needed.
*/
-enum typeid {
- T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
- T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
- T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
- T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-};
+static int
+grouping_init(struct grouping_state *gs, int ndigits)
+{
+ struct lconv *locale;
+
+ locale = localeconv();
+ gs->grouping = locale->grouping;
+ gs->thousands_sep = locale->thousands_sep;
+ gs->thousep_len = strlen(gs->thousands_sep);
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
+}
-static int __sprint(FILE *, struct __suio *);
-static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
-static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char,
- const char *);
-static char *__ultoa(u_long, char *, int, int, const char *, int, char,
- const char *);
-static char *__wcsconv(wchar_t *, int);
-static void __find_arguments(const char *, va_list, union arg **);
-static void __grow_type_table(int, enum typeid **, int *);
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, gs->thousands_sep, gs->thousep_len))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
/*
* Flush out all the vectors defined by the given uio,
FILE fake;
unsigned char buf[BUFSIZ];
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
/* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
- fake._extra = fp->_extra;
+ fake._orientation = fp->_orientation;
+ fake._mbstate = fp->_mbstate;
/* set up the buffer */
fake._bf._base = fake._p = buf;
return (ret);
}
-/*
- * Macros for converting digits to letters and vice versa
- */
-#define to_digit(c) ((c) - '0')
-#define is_digit(c) ((unsigned)to_digit(c) <= 9)
-#define to_char(n) ((n) + '0')
-
-/*
- * Convert an unsigned long to ASCII for printf purposes, returning
- * a pointer to the first character of the string representation.
- * Octal numbers can be forced to have a leading zero; hex numbers
- * use the given digits.
- */
-static char *
-__ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- char *cp = endp;
- long sval;
- int ndig;
-
- /*
- * Handle the three cases separately, in the hope of getting
- * better/faster code.
- */
- switch (base) {
- case 10:
- if (val < 10) { /* many numbers are 1 digit */
- *--cp = to_char(val);
- return (cp);
- }
- ndig = 0;
- /*
- * On many machines, unsigned arithmetic is harder than
- * signed arithmetic, so we do at most one unsigned mod and
- * divide; this is sufficient to reduce the range of
- * the incoming value to where signed arithmetic works.
- */
- if (val > LONG_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && ndig == *grp && *grp != CHAR_MAX
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default: /* oops */
- abort();
- }
- return (cp);
-}
-
-/* Identical to __ultoa, but for intmax_t. */
-static char *
-__ujtoa(uintmax_t val, char *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- char *cp = endp;
- intmax_t sval;
- int ndig;
-
- /* quick test for small values; __ultoa is typically much faster */
- /* (perhaps instead we should run until small, then call __ultoa?) */
- if (val <= ULONG_MAX)
- return (__ultoa((u_long)val, endp, base, octzero, xdigs,
- needgrp, thousep, grp));
- switch (base) {
- case 10:
- if (val < 10) {
- *--cp = to_char(val % 10);
- return (cp);
- }
- ndig = 0;
- if (val > INTMAX_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && *grp != CHAR_MAX && ndig == *grp
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default:
- abort();
- }
- return (cp);
-}
-
/*
* Convert a wide character string argument for the %ls format to a multibyte
- * string representation. ``prec'' specifies the maximum number of bytes
- * to output. If ``prec'' is greater than or equal to zero, we can't assume
- * that the wide char. string ends in a null character.
+ * string representation. If not -1, prec specifies the maximum number of
+ * bytes to output, and also means that we can't assume that the wide char.
+ * string ends is null-terminated.
*/
static char *
__wcsconv(wchar_t *wcsarg, int prec)
mbstate_t mbs;
char buf[MB_LEN_MAX];
wchar_t *p;
- char *convbuf, *mbp;
+ char *convbuf;
size_t clen, nbytes;
- /*
- * Determine the number of bytes to output and allocate space for
- * the output.
- */
- if (prec >= 0) {
- nbytes = 0;
- p = wcsarg;
- mbs = initial;
- for (;;) {
- clen = wcrtomb(buf, *p++, &mbs);
- if (clen == 0 || clen == (size_t)-1 ||
- nbytes + clen > prec)
- break;
- nbytes += clen;
- }
- } else {
+ /* Allocate space for the maximum number of bytes we could output. */
+ if (prec < 0) {
p = wcsarg;
mbs = initial;
nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
if (nbytes == (size_t)-1)
return (NULL);
+ } else {
+ /*
+ * Optimisation: if the output precision is small enough,
+ * just allocate enough memory for the maximum instead of
+ * scanning the string.
+ */
+ if (prec < 128)
+ nbytes = prec;
+ else {
+ nbytes = 0;
+ p = wcsarg;
+ mbs = initial;
+ for (;;) {
+ clen = wcrtomb(buf, *p++, &mbs);
+ if (clen == 0 || clen == (size_t)-1 ||
+ nbytes + clen > prec)
+ break;
+ nbytes += clen;
+ }
+ }
}
if ((convbuf = malloc(nbytes + 1)) == NULL)
return (NULL);
- /*
- * Fill the output buffer with the multibyte representations of as
- * many wide characters as will fit.
- */
- mbp = convbuf;
+ /* Fill the output buffer. */
p = wcsarg;
mbs = initial;
- while (mbp - convbuf < nbytes) {
- clen = wcrtomb(mbp, *p++, &mbs);
- if (clen == 0 || clen == (size_t)-1)
- break;
- mbp += clen;
- }
- if (clen == (size_t)-1) {
+ if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
+ nbytes, &mbs)) == (size_t)-1) {
free(convbuf);
return (NULL);
}
- *mbp = '\0';
-
+ convbuf[nbytes] = '\0';
return (convbuf);
}
int ret;
FLOCKFILE(fp);
- ret = __vfprintf(fp, fmt0, ap);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, fmt0, ap);
+ else
+ ret = __vfprintf(fp, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
-#ifndef NO_FLOATING_POINT
-
-#define dtoa __dtoa
-#define freedtoa __freedtoa
-
-#include <float.h>
-#include <math.h>
-#include "floatio.h"
-#include "gdtoa.h"
-
-#define DEFPREC 6
-
-static int exponent(char *, int, int);
-
-#endif /* !NO_FLOATING_POINT */
-
/*
* The size of the buffer we use as scratch space for integer
- * conversions, among other things. Technically, we would need the
- * most space for base 10 conversions with thousands' grouping
- * characters between each pair of digits. 100 bytes is a
- * conservative overestimate even for a 128-bit uintmax_t.
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
*/
-#define BUF 100
-
-#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
-
-/*
- * Flags used during conversion.
- */
-#define ALT 0x001 /* alternate form */
-#define LADJUST 0x004 /* left adjustment */
-#define LONGDBL 0x008 /* long double */
-#define LONGINT 0x010 /* long integer */
-#define LLONGINT 0x020 /* long long integer */
-#define SHORTINT 0x040 /* short integer */
-#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
-#define FPT 0x100 /* Floating point number */
-#define GROUPING 0x200 /* use grouping ("'" flag) */
- /* C99 additional size modifiers: */
-#define SIZET 0x400 /* size_t */
-#define PTRDIFFT 0x800 /* ptrdiff_t */
-#define INTMAXT 0x1000 /* intmax_t */
-#define CHARINT 0x2000 /* print char using int format */
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
/*
* Non-MT-safe version
int ch; /* character from fmt */
int n, n2; /* handy integer (short term usage) */
char *cp; /* handy char pointer (short term usage) */
- struct __siov *iovp; /* for PRINT macro */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
char sign; /* sign prefix (' ', '+', '-', or \0) */
- char thousands_sep; /* locale specific thousands separator */
- const char *grouping; /* locale specific numeric grouping rules */
+ struct grouping_state gs; /* thousands' grouping info */
+
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
* F: at least two digits for decimal, at least one digit for hex
*/
char *decimal_point; /* locale specific decimal point */
+ int decpt_len; /* length of decimal_point */
int signflag; /* true if float is negative */
union { /* floating point arguments %[aAeEfFgG] */
double dbl;
char expchar; /* exponent character: [eEpP\0] */
char *dtoaend; /* pointer to end of converted digits */
int expsize; /* character count for expstr */
- int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
char *dtoaresult; /* buffer allocated by dtoa */
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
#endif
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int size; /* size of converted field or string */
int prsize; /* max size of printed field */
const char *xdigs; /* digits for %[xX] conversion */
-#define NIOV 8
- struct __suio uio; /* output information: summary */
- struct __siov iov[NIOV];/* ... and individual io vectors */
+ struct io_state io; /* I/O buffering state */
char buf[BUF]; /* buffer with space for digits of uintmax_t */
char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
union arg *argtable; /* args, built due to positional arg */
va_list orgap; /* original argument pointer */
char *convbuf; /* wide to multibyte conversion result */
- /*
- * Choose PADSIZE to trade efficiency vs. size. If larger printf
- * fields occur frequently, increase PADSIZE and make the initialisers
- * below longer.
- */
-#define PADSIZE 16 /* pad chunk size */
- static char blanks[PADSIZE] =
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static char zeroes[PADSIZE] =
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
-
static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF";
- /*
- * BEWARE, these `goto error' on error, and PAD uses `n'.
- */
+ /* BEWARE, these `goto error' on error. */
#define PRINT(ptr, len) { \
- iovp->iov_base = (ptr); \
- iovp->iov_len = (len); \
- uio.uio_resid += (len); \
- iovp++; \
- if (++uio.uio_iovcnt >= NIOV) { \
- if (__sprint(fp, &uio)) \
- goto error; \
- iovp = iov; \
- } \
+ if (io_print(&io, (ptr), (len))) \
+ goto error; \
}
#define PAD(howmany, with) { \
- if ((n = (howmany)) > 0) { \
- while (n > PADSIZE) { \
- PRINT(with, PADSIZE); \
- n -= PADSIZE; \
- } \
- PRINT(with, n); \
- } \
+ if (io_pad(&io, (howmany), (with))) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with))) \
+ goto error; \
}
-#define PRINTANDPAD(p, ep, len, with) do { \
- n2 = (ep) - (p); \
- if (n2 > (len)) \
- n2 = (len); \
- if (n2 > 0) \
- PRINT((p), n2); \
- PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
-} while(0)
#define FLUSH() { \
- if (uio.uio_resid && __sprint(fp, &uio)) \
+ if (io_flush(&io)) \
goto error; \
- uio.uio_iovcnt = 0; \
- iovp = iov; \
}
/*
#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
#define SJARG() \
(flags&INTMAXT ? GETARG(intmax_t) : \
- flags&SIZET ? (intmax_t)GETARG(size_t) : \
+ flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
(intmax_t)GETARG(long long))
#define UJARG() \
int hold = nextarg; \
if (argtable == NULL) { \
argtable = statargtable; \
- __find_arguments (fmt0, orgap, &argtable); \
+ if (__find_arguments (fmt0, orgap, &argtable)) { \
+ ret = EOF; \
+ goto error; \
+ } \
} \
nextarg = n2; \
val = GETARG (int); \
val = GETARG (int); \
}
+ if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
+ __use_xprintf = 1;
+ if (__use_xprintf > 0)
+ return (__xvprintf(fp, fmt0, ap));
- thousands_sep = '\0';
- grouping = NULL;
- convbuf = NULL;
-#ifndef NO_FLOATING_POINT
- dtoaresult = NULL;
- decimal_point = localeconv()->decimal_point;
-#endif
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
if (prepwrite(fp) != 0)
return (EOF);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
- return (__sbprintf(fp, fmt0, ap));
-
+ convbuf = NULL;
fmt = (char *)fmt0;
argtable = NULL;
nextarg = 1;
va_copy(orgap, ap);
- uio.uio_iov = iovp = iov;
- uio.uio_resid = 0;
- uio.uio_iovcnt = 0;
+ io_init(&io, fp);
ret = 0;
+#ifndef NO_FLOATING_POINT
+ dtoaresult = NULL;
+ decimal_point = localeconv()->decimal_point;
+ /* The overwhelmingly common case is decpt_len == 1. */
+ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
+#endif
/*
* Scan the format for conversions (`%' character).
dprec = 0;
width = 0;
prec = -1;
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
goto rflag;
case '\'':
flags |= GROUPING;
- thousands_sep = *(localeconv()->thousands_sep);
- grouping = localeconv()->grouping;
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
nextarg = n;
if (argtable == NULL) {
argtable = statargtable;
- __find_arguments (fmt0, orgap,
- &argtable);
+ if (__find_arguments (fmt0, orgap,
+ &argtable)) {
+ ret = EOF;
+ goto error;
+ }
}
goto rflag;
}
} else
cp = (ch >= 'a') ? "inf" : "INF";
size = 3;
+ flags &= ~ZEROPAD;
break;
}
flags |= FPT;
expsize = exponent(expstr, expt - 1, expchar);
size = expsize + prec;
if (prec > 1 || flags & ALT)
- ++size;
+ size += decpt_len;
} else {
/* space for digits before decimal point */
if (expt > 0)
size = 1;
/* space for decimal pt and following digits */
if (prec || flags & ALT)
- size += prec + 1;
- if (grouping && expt > 0) {
- /* space for thousands' grouping */
- nseps = nrepeats = 0;
- lead = expt;
- while (*grouping != CHAR_MAX) {
- if (lead <= *grouping)
- break;
- lead -= *grouping;
- if (*(grouping+1)) {
- nseps++;
- grouping++;
- } else
- nrepeats++;
- }
- size += nseps + nrepeats;
- } else
- lead = expt;
+ size += prec + decpt_len;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt);
}
break;
#endif /* !NO_FLOATING_POINT */
}
} else if ((cp = GETARG(char *)) == NULL)
cp = "(null)";
- if (prec >= 0) {
- /*
- * can't use strlen; can only look for the
- * NUL in the first `prec' characters, and
- * strlen() will go further.
- */
- char *p = memchr(cp, 0, (size_t)prec);
-
- if (p != NULL) {
- size = p - cp;
- if (size > prec)
- size = prec;
- } else
- size = prec;
- } else
- size = strlen(cp);
+ size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
sign = '\0';
break;
case 'U':
* ``The result of converting a zero value with an
* explicit precision of zero is no characters.''
* -- ANSI X3J11
+ *
+ * ``The C Standard is clear enough as is. The call
+ * printf("%#.0o", 0) should print 0.''
+ * -- Defect Report #151
*/
cp = buf + BUF;
if (flags & INTMAX_SIZE) {
- if (ujval != 0 || prec != 0)
+ if (ujval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ujtoa(ujval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
} else {
- if (ulval != 0 || prec != 0)
+ if (ulval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
abort();
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size);
break;
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD(width - realsz, zeroes);
- /* leading zeroes from decimal precision */
- PAD(dprec - size, zeroes);
-
/* the string or number proper */
#ifndef NO_FLOATING_POINT
if ((flags & FPT) == 0) {
- PRINT(cp, size);
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
} else { /* glue together f_p fragments */
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
if (expt <= 0) {
PRINT(zeroes, 1);
if (prec || flags & ALT)
- PRINT(decimal_point, 1);
+ PRINT(decimal_point,decpt_len);
PAD(-expt, zeroes);
/* already handled initial 0's */
prec += expt;
} else {
- PRINTANDPAD(cp, dtoaend, lead, zeroes);
- cp += lead;
- if (grouping) {
- while (nseps>0 || nrepeats>0) {
- if (nrepeats > 0)
- nrepeats--;
- else {
- grouping--;
- nseps--;
- }
- PRINT(&thousands_sep,
- 1);
- PRINTANDPAD(cp,dtoaend,
- *grouping, zeroes);
- cp += *grouping;
- }
- if (cp > dtoaend)
- cp = dtoaend;
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, dtoaend);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, dtoaend,
+ expt, zeroes);
+ cp += expt;
}
if (prec || flags & ALT)
- PRINT(decimal_point,1);
+ PRINT(decimal_point,decpt_len);
}
PRINTANDPAD(cp, dtoaend, prec, zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
if (prec > 1 || flags & ALT) {
- buf[0] = *cp++;
- buf[1] = *decimal_point;
- PRINT(buf, 2);
+ PRINT(cp++, 1);
+ PRINT(decimal_point, decpt_len);
PRINT(cp, ndig-1);
PAD(prec - ndig, zeroes);
} else /* XeYYY */
PRINT(expstr, expsize);
}
}
-#else
- PRINT(cp, size);
#endif
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
/* NOTREACHED */
}
-/*
- * Find all arguments when a positional parameter is encountered. Returns a
- * table, indexed by argument number, of pointers to each arguments. The
- * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
- * It will be replaces with a malloc-ed one if it overflows.
- */
-static void
-__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
-{
- char *fmt; /* format string */
- int ch; /* character from fmt */
- int n, n2; /* handy integer (short term usage) */
- char *cp; /* handy char pointer (short term usage) */
- int flags; /* flags as above */
- int width; /* width from format (%8d), or 0 */
- enum typeid *typetable; /* table of types */
- enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
- int tablesize; /* current size of type table */
- int tablemax; /* largest used index in table */
- int nextarg; /* 1-based argument index */
-
- /*
- * Add an argument type to the table, expanding if necessary.
- */
-#define ADDTYPE(type) \
- ((nextarg >= tablesize) ? \
- __grow_type_table(nextarg, &typetable, &tablesize) : (void)0, \
- (nextarg > tablemax) ? tablemax = nextarg : 0, \
- typetable[nextarg++] = type)
-
-#define ADDSARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
-
-#define ADDUARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
-
- /*
- * Add * arguments to the type array.
- */
-#define ADDASTER() \
- n2 = 0; \
- cp = fmt; \
- while (is_digit(*cp)) { \
- n2 = 10 * n2 + to_digit(*cp); \
- cp++; \
- } \
- if (*cp == '$') { \
- int hold = nextarg; \
- nextarg = n2; \
- ADDTYPE (T_INT); \
- nextarg = hold; \
- fmt = ++cp; \
- } else { \
- ADDTYPE (T_INT); \
- }
- fmt = (char *)fmt0;
- typetable = stattypetable;
- tablesize = STATIC_ARG_TBL_SIZE;
- tablemax = 0;
- nextarg = 1;
- for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
- typetable[n] = T_UNUSED;
-
- /*
- * Scan the format for conversions (`%' character).
- */
- for (;;) {
- for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
- /* void */;
- if (ch == '\0')
- goto done;
- fmt++; /* skip over '%' */
-
- flags = 0;
- width = 0;
-
-rflag: ch = *fmt++;
-reswitch: switch (ch) {
- case ' ':
- case '#':
- goto rflag;
- case '*':
- ADDASTER ();
- goto rflag;
- case '-':
- case '+':
- case '\'':
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- ADDASTER ();
- goto rflag;
- }
- while (is_digit(ch)) {
- ch = *fmt++;
- }
- goto reswitch;
- case '0':
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- } while (is_digit(ch));
- if (ch == '$') {
- nextarg = n;
- goto rflag;
- }
- width = n;
- goto reswitch;
-#ifndef NO_FLOATING_POINT
- case 'L':
- flags |= LONGDBL;
- goto rflag;
-#endif
- case 'h':
- if (flags & SHORTINT) {
- flags &= ~SHORTINT;
- flags |= CHARINT;
- } else
- flags |= SHORTINT;
- goto rflag;
- case 'j':
- flags |= INTMAXT;
- goto rflag;
- case 'l':
- if (flags & LONGINT) {
- flags &= ~LONGINT;
- flags |= LLONGINT;
- } else
- flags |= LONGINT;
- goto rflag;
- case 'q':
- flags |= LLONGINT; /* not necessarily */
- goto rflag;
- case 't':
- flags |= PTRDIFFT;
- goto rflag;
- case 'z':
- flags |= SIZET;
- goto rflag;
- case 'C':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'c':
- if (flags & LONGINT)
- ADDTYPE(T_WINT);
- else
- ADDTYPE(T_INT);
- break;
- case 'D':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
- ADDSARG();
- break;
-#ifndef NO_FLOATING_POINT
- case 'a':
- case 'A':
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- if (flags & LONGDBL)
- ADDTYPE(T_LONG_DOUBLE);
- else
- ADDTYPE(T_DOUBLE);
- break;
-#endif /* !NO_FLOATING_POINT */
- case 'n':
- if (flags & INTMAXT)
- ADDTYPE(TP_INTMAXT);
- else if (flags & PTRDIFFT)
- ADDTYPE(TP_PTRDIFFT);
- else if (flags & SIZET)
- ADDTYPE(TP_SIZET);
- else if (flags & LLONGINT)
- ADDTYPE(TP_LLONG);
- else if (flags & LONGINT)
- ADDTYPE(TP_LONG);
- else if (flags & SHORTINT)
- ADDTYPE(TP_SHORT);
- else if (flags & CHARINT)
- ADDTYPE(TP_SCHAR);
- else
- ADDTYPE(TP_INT);
- continue; /* no output */
- case 'O':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
- ADDUARG();
- break;
- case 'p':
- ADDTYPE(TP_VOID);
- break;
- case 'S':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 's':
- if (flags & LONGINT)
- ADDTYPE(TP_WCHAR);
- else
- ADDTYPE(TP_CHAR);
- break;
- case 'U':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'u':
- case 'X':
- case 'x':
- ADDUARG();
- break;
- default: /* "%?" prints ?, unless ? is NUL */
- if (ch == '\0')
- goto done;
- break;
- }
- }
-done:
- /*
- * Build the argument table.
- */
- if (tablemax >= STATIC_ARG_TBL_SIZE) {
- *argtable = (union arg *)
- malloc (sizeof (union arg) * (tablemax + 1));
- }
-
- (*argtable) [0].intarg = 0;
- for (n = 1; n <= tablemax; n++) {
- switch (typetable [n]) {
- case T_UNUSED: /* whoops! */
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case TP_SCHAR:
- (*argtable) [n].pschararg = va_arg (ap, signed char *);
- break;
- case TP_SHORT:
- (*argtable) [n].pshortarg = va_arg (ap, short *);
- break;
- case T_INT:
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case T_U_INT:
- (*argtable) [n].uintarg = va_arg (ap, unsigned int);
- break;
- case TP_INT:
- (*argtable) [n].pintarg = va_arg (ap, int *);
- break;
- case T_LONG:
- (*argtable) [n].longarg = va_arg (ap, long);
- break;
- case T_U_LONG:
- (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
- break;
- case TP_LONG:
- (*argtable) [n].plongarg = va_arg (ap, long *);
- break;
- case T_LLONG:
- (*argtable) [n].longlongarg = va_arg (ap, long long);
- break;
- case T_U_LLONG:
- (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
- break;
- case TP_LLONG:
- (*argtable) [n].plonglongarg = va_arg (ap, long long *);
- break;
- case T_PTRDIFFT:
- (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
- break;
- case TP_PTRDIFFT:
- (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
- break;
- case T_SIZET:
- (*argtable) [n].sizearg = va_arg (ap, size_t);
- break;
- case TP_SIZET:
- (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
- break;
- case T_INTMAXT:
- (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
- break;
- case T_UINTMAXT:
- (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
- break;
- case TP_INTMAXT:
- (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
- break;
-#ifndef NO_FLOATING_POINT
- case T_DOUBLE:
- (*argtable) [n].doublearg = va_arg (ap, double);
- break;
- case T_LONG_DOUBLE:
- (*argtable) [n].longdoublearg = va_arg (ap, long double);
- break;
-#endif
- case TP_CHAR:
- (*argtable) [n].pchararg = va_arg (ap, char *);
- break;
- case TP_VOID:
- (*argtable) [n].pvoidarg = va_arg (ap, void *);
- break;
- case T_WINT:
- (*argtable) [n].wintarg = va_arg (ap, wint_t);
- break;
- case TP_WCHAR:
- (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
- break;
- }
- }
-
- if ((typetable != NULL) && (typetable != stattypetable))
- free (typetable);
-}
-
-/*
- * Increase the size of the type table.
- */
-static void
-__grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
-{
- enum typeid *const oldtable = *typetable;
- const int oldsize = *tablesize;
- enum typeid *newtable;
- int n, newsize = oldsize * 2;
-
- if (newsize < nextarg + 1)
- newsize = nextarg + 1;
- if (oldsize == STATIC_ARG_TBL_SIZE) {
- if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
- abort(); /* XXX handle better */
- bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
- } else {
- newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
- if (newtable == NULL)
- abort(); /* XXX handle better */
- }
- for (n = oldsize; n < newsize; n++)
- newtable[n] = T_UNUSED;
-
- *typetable = newtable;
- *tablesize = newsize;
-}
-
-
-#ifndef NO_FLOATING_POINT
-
-static int
-exponent(char *p0, int exp, int fmtch)
-{
- char *p, *t;
- char expbuf[MAXEXPDIG];
-
- p = p0;
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- }
- else
- *p++ = '+';
- t = expbuf + MAXEXPDIG;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
- }
- else {
- /*
- * Exponents for decimal floating point conversions
- * (%[eEgG]) must be at least two characters long,
- * whereas exponents for hexadecimal conversions can
- * be only one character long.
- */
- if (fmtch == 'e' || fmtch == 'E')
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p - p0);
-}
-#endif /* !NO_FLOATING_POINT */
---- vfprintf.c.orig 2008-09-07 11:37:54.000000000 -0700
-+++ vfprintf.c 2008-09-07 17:33:16.000000000 -0700
-@@ -40,6 +40,8 @@ static char sccsid[] = "@(#)vfprintf.c 8
+--- vfprintf.c.orig 2010-11-22 22:37:24.000000000 -0800
++++ vfprintf.c 2010-11-22 22:38:38.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)vfprintf.c 8
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.68 2004/08/26 06:25:28 des Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $");
+#include "xlocale_private.h"
+
/*
* Actual printf innards.
*
-@@ -58,6 +60,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
+@@ -54,7 +56,10 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
++#if 0 // xprintf pending API review
+ #include <printf.h>
++#endif
+#include <errno.h>
#include <stdarg.h>
#include "un-namespace.h"
-@@ -66,6 +69,13 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
- #include "local.h"
+@@ -64,10 +69,11 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
#include "fvwrite.h"
+ #include "printflocal.h"
-+#ifdef VECTORS
-+typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
-+#ifdef __SSE2__
-+#define V64TYPE
-+#endif /* __SSE2__ */
-+#endif /* VECTORS */
+-static int __sprint(FILE *, struct __suio *);
+-static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0)
+- __noinline;
+-static char *__wcsconv(wchar_t *, int);
++static int __sprint(FILE *, locale_t, struct __suio *);
++static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
++static char *__wcsconv(wchar_t *, int, locale_t);
+
- union arg {
- int intarg;
- u_int uintarg;
-@@ -93,6 +103,21 @@ union arg {
- #endif
- wint_t wintarg;
- wchar_t *pwchararg;
-+#ifdef VECTORS
-+ VECTORTYPE vectorarg;
-+ unsigned char vuchararg[16];
-+ signed char vchararg[16];
-+ unsigned short vushortarg[8];
-+ signed short vshortarg[8];
-+ unsigned int vuintarg[4];
-+ signed int vintarg[4];
-+ float vfloatarg[4];
-+#ifdef V64TYPE
-+ double vdoublearg[2];
-+ unsigned long long vulonglongarg[2];
-+ long long vlonglongarg[2];
-+#endif /* V64TYPE */
-+#endif /* VECTORS */
- };
++__private_extern__ const char *__fix_nogrouping(const char *);
- /*
-@@ -103,16 +128,20 @@ enum typeid {
- T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
- T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
- T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
-+#ifdef VECTORS
-+ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
-+#else /* ! VECTORS */
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-+#endif /* VECTORS */
- };
+ #define CHAR char
+ #include "printfcommon.h"
+@@ -87,12 +93,12 @@ struct grouping_state {
+ * of bytes that will be needed.
+ */
+ static int
+-grouping_init(struct grouping_state *gs, int ndigits)
++grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
+ {
+ struct lconv *locale;
- static int __sprint(FILE *, struct __suio *);
--static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
-+static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
- static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char,
- const char *);
- static char *__ultoa(u_long, char *, int, int, const char *, int, char,
- const char *);
--static char *__wcsconv(wchar_t *, int);
-+static char *__wcsconv(wchar_t *, int, locale_t);
- static void __find_arguments(const char *, va_list, union arg **);
- static void __grow_type_table(int, enum typeid **, int *);
+- locale = localeconv();
+- gs->grouping = locale->grouping;
++ locale = localeconv_l(loc);
++ gs->grouping = __fix_nogrouping(locale->grouping);
+ gs->thousands_sep = locale->thousands_sep;
+ gs->thousep_len = strlen(gs->thousands_sep);
+
+@@ -116,11 +122,11 @@ grouping_init(struct grouping_state *gs,
+ */
+ static int
+ grouping_print(struct grouping_state *gs, struct io_state *iop,
+- const CHAR *cp, const CHAR *ep)
++ const CHAR *cp, const CHAR *ep, locale_t loc)
+ {
+ const CHAR *cp0 = cp;
+
+- if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
++ if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+@@ -130,9 +136,9 @@ grouping_print(struct grouping_state *gs
+ gs->grouping--;
+ gs->nseps--;
+ }
+- if (io_print(iop, gs->thousands_sep, gs->thousep_len))
++ if (io_print(iop, gs->thousands_sep, gs->thousep_len, loc))
+ return (-1);
+- if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
++ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
+ return (-1);
+ cp += *gs->grouping;
+ }
+@@ -146,7 +152,7 @@ grouping_print(struct grouping_state *gs
+ * then reset it so that it can be reused.
+ */
+ static int
+-__sprint(FILE *fp, struct __suio *uio)
++__sprint(FILE *fp, locale_t loc __unused, struct __suio *uio)
+ {
+ int err;
-@@ -141,7 +170,7 @@ __sprint(FILE *fp, struct __suio *uio)
+@@ -166,11 +172,14 @@ __sprint(FILE *fp, struct __suio *uio)
* worries about ungetc buffers and so forth.
*/
static int
{
int ret;
FILE fake;
-@@ -160,7 +189,7 @@ __sbprintf(FILE *fp, const char *fmt, va
+ unsigned char buf[BUFSIZ];
++ struct __sFILEX ext;
++ fake._extra = &ext;
++ INITEXTRA(&fake);
+
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+@@ -190,7 +199,7 @@ __sbprintf(FILE *fp, const char *fmt, va
fake._lbfsize = 0; /* not actually used, but Just In Case */
/* do the work, then copy any error status */
if (ret >= 0 && __fflush(&fake))
ret = EOF;
if (fake._flags & __SERR)
-@@ -252,7 +281,7 @@ __ultoa(u_long val, char *endp, int base
- break;
-
- default: /* oops */
-- abort();
-+ LIBC_ABORT("base = %d", base);
- }
- return (cp);
- }
-@@ -324,7 +353,7 @@ __ujtoa(uintmax_t val, char *endp, int b
- break;
-
- default:
-- abort();
-+ LIBC_ABORT("base = %d", base);
- }
- return (cp);
- }
-@@ -336,14 +365,14 @@ __ujtoa(uintmax_t val, char *endp, int b
- * that the wide char. string ends in a null character.
+@@ -205,7 +214,7 @@ __sbprintf(FILE *fp, const char *fmt, va
+ * string ends is null-terminated.
*/
static char *
-__wcsconv(wchar_t *wcsarg, int prec)
{
static const mbstate_t initial;
mbstate_t mbs;
- char buf[MB_LEN_MAX];
- wchar_t *p;
- char *convbuf, *mbp;
-- size_t clen, nbytes;
-+ size_t clen = 0, nbytes;
-
- /*
- * Determine the number of bytes to output and allocate space for
-@@ -354,7 +383,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
- p = wcsarg;
- mbs = initial;
- for (;;) {
-- clen = wcrtomb(buf, *p++, &mbs);
-+ clen = wcrtomb_l(buf, *p++, &mbs, loc);
- if (clen == 0 || clen == (size_t)-1 ||
- nbytes + clen > prec)
- break;
-@@ -363,7 +392,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
- } else {
+@@ -218,7 +227,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
+ if (prec < 0) {
p = wcsarg;
mbs = initial;
- nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
+ nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
if (nbytes == (size_t)-1)
return (NULL);
- }
-@@ -378,7 +407,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
+ } else {
+@@ -234,7 +243,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
+ p = wcsarg;
+ mbs = initial;
+ for (;;) {
+- clen = wcrtomb(buf, *p++, &mbs);
++ clen = wcrtomb_l(buf, *p++, &mbs, loc);
+ if (clen == 0 || clen == (size_t)-1 ||
+ nbytes + clen > prec)
+ break;
+@@ -248,8 +257,8 @@ __wcsconv(wchar_t *wcsarg, int prec)
+ /* Fill the output buffer. */
p = wcsarg;
mbs = initial;
- while (mbp - convbuf < nbytes) {
-- clen = wcrtomb(mbp, *p++, &mbs);
-+ clen = wcrtomb_l(mbp, *p++, &mbs, loc);
- if (clen == 0 || clen == (size_t)-1)
- break;
- mbp += clen;
-@@ -395,6 +424,8 @@ __wcsconv(wchar_t *wcsarg, int prec)
- /*
+- if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
+- nbytes, &mbs)) == (size_t)-1) {
++ if ((nbytes = wcsrtombs_l(convbuf, (const wchar_t **)&p,
++ nbytes, &mbs, loc)) == (size_t)-1) {
+ free(convbuf);
+ return (NULL);
+ }
+@@ -261,22 +270,30 @@ __wcsconv(wchar_t *wcsarg, int prec)
* MT-safe version
*/
-+__private_extern__ const char *__fix_nogrouping(const char *);
-+
int
- vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
+-vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
++vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
-@@ -402,7 +433,21 @@ vfprintf(FILE * __restrict fp, const cha
+ {
int ret;
- FLOCKFILE(fp);
-- ret = __vfprintf(fp, fmt0, ap);
-+ ret = __vfprintf(fp, __current_locale(), fmt0, ap);
-+ FUNLOCKFILE(fp);
-+ return (ret);
-+}
-+
-+int
-+vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0,
-+ va_list ap)
-+
-+{
-+ int ret;
-+
+ NORMALIZE_LOCALE(loc);
-+ FLOCKFILE(fp);
-+ ret = __vfprintf(fp, loc, fmt0, ap);
+ FLOCKFILE(fp);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+- ret = __sbprintf(fp, fmt0, ap);
++ ret = __sbprintf(fp, loc, fmt0, ap);
+ else
+- ret = __vfprintf(fp, fmt0, ap);
++ ret = __vfprintf(fp, loc, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
-@@ -451,12 +496,15 @@ static int exponent(char *, int, int);
- #define PTRDIFFT 0x800 /* ptrdiff_t */
- #define INTMAXT 0x1000 /* intmax_t */
- #define CHARINT 0x2000 /* print char using int format */
-+#ifdef VECTORS
-+#define VECTOR 0x4000 /* Altivec or SSE vector */
-+#endif /* VECTORS */
++int
++vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
++
++{
++ return vfprintf_l(fp, __current_locale(), fmt0, ap);
++}
++
+ /*
+ * The size of the buffer we use as scratch space for integer
+ * conversions, among other things. We need enough space to
+@@ -291,8 +308,8 @@ vfprintf(FILE * __restrict fp, const cha
/*
* Non-MT-safe version
*/
{
char *fmt; /* format string */
int ch; /* character from fmt */
-@@ -502,6 +550,11 @@ __vfprintf(FILE *fp, const char *fmt0, v
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
+@@ -335,6 +352,11 @@ __vfprintf(FILE *fp, const char *fmt0, v
+ char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
+ char *dtoaresult; /* buffer allocated by dtoa */
#endif
+#ifdef VECTORS
+ union arg vval; /* Vector argument. */
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int base; /* base for [diouxX] conversion */
-@@ -599,13 +652,13 @@ __vfprintf(FILE *fp, const char *fmt0, v
- #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
- #define SJARG() \
- (flags&INTMAXT ? GETARG(intmax_t) : \
-- flags&SIZET ? (intmax_t)GETARG(size_t) : \
-+ flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
- flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
- (intmax_t)GETARG(long long))
+@@ -357,19 +379,19 @@ __vfprintf(FILE *fp, const char *fmt0, v
+
+ /* BEWARE, these `goto error' on error. */
+ #define PRINT(ptr, len) { \
+- if (io_print(&io, (ptr), (len))) \
++ if (io_print(&io, (ptr), (len), loc)) \
+ goto error; \
+ }
+ #define PAD(howmany, with) { \
+- if (io_pad(&io, (howmany), (with))) \
++ if (io_pad(&io, (howmany), (with), loc)) \
+ goto error; \
+ }
+ #define PRINTANDPAD(p, ep, len, with) { \
+- if (io_printandpad(&io, (p), (ep), (len), (with))) \
++ if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \
+ goto error; \
+ }
+ #define FLUSH() { \
+- if (io_flush(&io)) \
++ if (io_flush(&io, loc)) \
+ goto error; \
+ }
+
+@@ -405,7 +427,7 @@ __vfprintf(FILE *fp, const char *fmt0, v
#define UJARG() \
(flags&INTMAXT ? GETARG(uintmax_t) : \
flags&SIZET ? (uintmax_t)GETARG(size_t) : \
- flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
-+ flags&PTRDIFFT ? (uintmax_t)(unsigned)GETARG(ptrdiff_t) : \
++ flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
(uintmax_t)GETARG(unsigned long long))
/*
-@@ -633,22 +686,24 @@ __vfprintf(FILE *fp, const char *fmt0, v
+@@ -436,14 +458,19 @@ __vfprintf(FILE *fp, const char *fmt0, v
val = GETARG (int); \
}
--
- thousands_sep = '\0';
- grouping = NULL;
- convbuf = NULL;
- #ifndef NO_FLOATING_POINT
- dtoaresult = NULL;
-- decimal_point = localeconv()->decimal_point;
-+ decimal_point = localeconv_l(loc)->decimal_point;
- #endif
++#if 0 // xprintf pending API review
+ if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
+ __use_xprintf = 1;
+ if (__use_xprintf > 0)
+- return (__xvprintf(fp, fmt0, ap));
++ return (__xvprintf(fp, loc, fmt0, ap));
++#endif
+
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
- if (prepwrite(fp) != 0)
+ if (prepwrite(fp) != 0) {
+ }
+ ORIENT(fp, -1);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
-- return (__sbprintf(fp, fmt0, ap));
-+ return (__sbprintf(fp, loc, fmt0, ap));
-
+ convbuf = NULL;
fmt = (char *)fmt0;
- argtable = NULL;
-@@ -675,6 +730,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
+@@ -454,7 +481,7 @@ __vfprintf(FILE *fp, const char *fmt0, v
+ ret = 0;
+ #ifndef NO_FLOATING_POINT
+ dtoaresult = NULL;
+- decimal_point = localeconv()->decimal_point;
++ decimal_point = localeconv_l(loc)->decimal_point;
+ /* The overwhelmingly common case is decpt_len == 1. */
+ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
+ #endif
+@@ -475,6 +502,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
}
if (ch == '\0')
goto done;
fmt++; /* skip over '%' */
flags = 0;
-@@ -683,6 +741,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
- prec = -1;
+@@ -484,6 +514,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
+#ifdef VECTORS
rflag: ch = *fmt++;
reswitch: switch (ch) {
-@@ -698,6 +759,11 @@ reswitch: switch (ch) {
+@@ -499,6 +532,11 @@ reswitch: switch (ch) {
case '#':
flags |= ALT;
goto rflag;
case '*':
/*-
* ``A negative field width argument is taken as a
-@@ -718,8 +784,8 @@ reswitch: switch (ch) {
- goto rflag;
- case '\'':
- flags |= GROUPING;
-- thousands_sep = *(localeconv()->thousands_sep);
-- grouping = localeconv()->grouping;
-+ thousands_sep = *(localeconv_l(loc)->thousands_sep);
-+ grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
-@@ -793,14 +859,18 @@ reswitch: switch (ch) {
+@@ -595,14 +633,18 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'c':
if (mbseqlen == (size_t)-1) {
fp->_flags |= __SERR;
goto error;
-@@ -817,6 +887,10 @@ reswitch: switch (ch) {
+@@ -619,6 +661,10 @@ reswitch: switch (ch) {
/*FALLTHROUGH*/
case 'd':
case 'i':
if (flags & INTMAX_SIZE) {
ujval = SJARG();
if ((intmax_t)ujval < 0) {
-@@ -835,6 +909,12 @@ reswitch: switch (ch) {
+@@ -637,6 +683,12 @@ reswitch: switch (ch) {
#ifndef NO_FLOATING_POINT
case 'a':
case 'A':
if (ch == 'a') {
ox[1] = 'x';
xdigs = xdigs_lower;
-@@ -848,6 +928,12 @@ reswitch: switch (ch) {
+@@ -650,6 +702,12 @@ reswitch: switch (ch) {
prec++;
if (dtoaresult != NULL)
freedtoa(dtoaresult);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult = cp =
-@@ -859,6 +945,7 @@ reswitch: switch (ch) {
+@@ -661,6 +719,7 @@ reswitch: switch (ch) {
__hdtoa(fparg.dbl, xdigs, prec,
&expt, &signflag, &dtoaend);
}
if (prec < 0)
prec = dtoaend - cp;
if (expt == INT_MAX)
-@@ -866,6 +953,12 @@ reswitch: switch (ch) {
+@@ -668,6 +727,12 @@ reswitch: switch (ch) {
goto fp_common;
case 'e':
case 'E':
expchar = ch;
if (prec < 0) /* account for digit before decpt */
prec = DEFPREC + 1;
-@@ -874,10 +967,22 @@ reswitch: switch (ch) {
+@@ -676,10 +741,22 @@ reswitch: switch (ch) {
goto fp_begin;
case 'f':
case 'F':
expchar = ch - ('g' - 'e');
if (prec == 0)
prec = 1;
-@@ -886,6 +991,14 @@ fp_begin:
+@@ -688,6 +765,14 @@ fp_begin:
prec = DEFPREC;
if (dtoaresult != NULL)
freedtoa(dtoaresult);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult = cp =
-@@ -899,6 +1012,7 @@ fp_begin:
+@@ -701,6 +786,7 @@ fp_begin:
if (expt == 9999)
expt = INT_MAX;
}
fp_common:
if (signflag)
sign = '-';
-@@ -993,6 +1107,10 @@ fp_common:
+@@ -750,37 +836,46 @@ fp_common:
+ if (prec || flags & ALT)
+ size += prec + decpt_len;
+ if ((flags & GROUPING) && expt > 0)
+- size += grouping_init(&gs, expt);
++ size += grouping_init(&gs, expt, loc);
+ }
+ break;
+ #endif /* !NO_FLOATING_POINT */
+ case 'n':
++ {
+ /*
+ * Assignment-like behavior is specified if the
+ * value overflows or is otherwise unrepresentable.
+ * C99 says to use `signed char' for %hhn conversions.
+ */
+- if (flags & LLONGINT)
+- *GETARG(long long *) = ret;
++ void *ptr = GETARG(void *);
++ if (ptr == NULL)
++ continue;
++ else if (flags & LLONGINT)
++ *(long long *)ptr = ret;
+ else if (flags & SIZET)
+- *GETARG(ssize_t *) = (ssize_t)ret;
++ *(ssize_t *)ptr = (ssize_t)ret;
+ else if (flags & PTRDIFFT)
+- *GETARG(ptrdiff_t *) = ret;
++ *(ptrdiff_t *)ptr = ret;
+ else if (flags & INTMAXT)
+- *GETARG(intmax_t *) = ret;
++ *(intmax_t *)ptr = ret;
+ else if (flags & LONGINT)
+- *GETARG(long *) = ret;
++ *(long *)ptr = ret;
+ else if (flags & SHORTINT)
+- *GETARG(short *) = ret;
++ *(short *)ptr = ret;
+ else if (flags & CHARINT)
+- *GETARG(signed char *) = ret;
++ *(signed char *)ptr = ret;
+ else
+- *GETARG(int *) = ret;
++ *(int *)ptr = ret;
+ continue; /* no output */
++ }
+ case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1007,6 +1125,10 @@ fp_common:
+@@ -795,6 +890,10 @@ fp_common:
* defined manner.''
* -- ANSI X3J11
*/
ujval = (uintmax_t)(uintptr_t)GETARG(void *);
base = 16;
xdigs = xdigs_lower;
-@@ -1025,7 +1147,7 @@ fp_common:
+@@ -813,7 +912,7 @@ fp_common:
if ((wcp = GETARG(wchar_t *)) == NULL)
cp = "(null)";
else {
if (convbuf == NULL) {
fp->_flags |= __SERR;
goto error;
-@@ -1056,6 +1178,10 @@ fp_common:
+@@ -829,6 +928,10 @@ fp_common:
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1068,6 +1194,10 @@ fp_common:
+@@ -841,6 +944,10 @@ fp_common:
case 'x':
xdigs = xdigs_lower;
hex:
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1093,6 +1223,7 @@ number: if ((dprec = prec) >= 0)
- * ``The result of converting a zero value with an
- * explicit precision of zero is no characters.''
+@@ -858,6 +965,7 @@ nosign: sign = '\0';
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
* -- ANSI X3J11
+ * except for %#.0o and zero value
*/
- cp = buf + BUF;
- if (flags & INTMAX_SIZE) {
-@@ -1102,7 +1233,7 @@ number: if ((dprec = prec) >= 0)
- flags & GROUPING, thousands_sep,
- grouping);
- } else {
-- if (ulval != 0 || prec != 0)
-+ if (ulval != 0 || prec != 0 || (flags & ALT))
- cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
-@@ -1110,8 +1241,13 @@ number: if ((dprec = prec) >= 0)
+ number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+@@ -885,10 +993,15 @@ number: if ((dprec = prec) >= 0)
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
- abort();
-+ LIBC_ABORT("size %d > BUF %d", size, BUF);
++ LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
+ if ((flags & GROUPING) && size != 0)
+- size += grouping_init(&gs, size);
++ size += grouping_init(&gs, size, loc);
break;
+#ifdef VECTORS
+ case 'v':
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
-@@ -1123,6 +1259,290 @@ number: if ((dprec = prec) >= 0)
+@@ -900,6 +1013,290 @@ number: if ((dprec = prec) >= 0)
break;
}
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
+ break; \
+ case V_PCHAR: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
+ break; \
+ case V_SHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
+ break; \
+ case V_PSHORT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
+ break; \
+ case V_INT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
+ break; \
+ case V_PINT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
+ break; \
+ case V_LONGLONG: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
+ break; \
+ case V_PLONGLONG: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
+ break; \
+ case V_FLOAT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
+ break; \
+ case V_PCHAR: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
+ break; \
+ case V_SHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
+ break; \
+ case V_PSHORT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
+ break; \
+ case V_INT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
+ break; \
+ case V_PINT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
+ break; \
+ case V_FLOAT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
/*
* All reasonable formats wind up here. At this point, `cp'
* points to a string which (if not flags&LADJUST) should be
-@@ -1178,7 +1598,7 @@ number: if ((dprec = prec) >= 0)
- if (expt <= 0) {
- PRINT(zeroes, 1);
- if (prec || flags & ALT)
-- PRINT(decimal_point, 1);
-+ PRINT(decimal_point, strlen(decimal_point));
- PAD(-expt, zeroes);
- /* already handled initial 0's */
- prec += expt;
-@@ -1203,14 +1623,14 @@ number: if ((dprec = prec) >= 0)
- cp = dtoaend;
- }
- if (prec || flags & ALT)
-- PRINT(decimal_point,1);
-+ PRINT(decimal_point, strlen(decimal_point));
- }
- PRINTANDPAD(cp, dtoaend, prec, zeroes);
- } else { /* %[eE] or sufficiently long %[gG] */
- if (prec > 1 || flags & ALT) {
- buf[0] = *cp++;
-- buf[1] = *decimal_point;
-- PRINT(buf, 2);
-+ PRINT(buf, 1);
-+ PRINT(decimal_point, strlen(decimal_point));
- PRINT(cp, ndig-1);
- PAD(prec - ndig, zeroes);
- } else /* XeYYY */
-@@ -1406,6 +1826,11 @@ reswitch: switch (ch) {
- if (flags & LONGINT)
- ADDTYPE(T_WINT);
- else
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDTYPE(T_INT);
- break;
- case 'D':
-@@ -1413,6 +1838,11 @@ reswitch: switch (ch) {
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif
- ADDSARG();
- break;
- #ifndef NO_FLOATING_POINT
-@@ -1421,8 +1851,14 @@ reswitch: switch (ch) {
- case 'e':
- case 'E':
- case 'f':
-+ case 'F':
- case 'g':
- case 'G':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- if (flags & LONGDBL)
- ADDTYPE(T_LONG_DOUBLE);
- else
-@@ -1451,9 +1887,19 @@ reswitch: switch (ch) {
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDUARG();
- break;
- case 'p':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDTYPE(TP_VOID);
- break;
- case 'S':
-@@ -1471,6 +1917,11 @@ reswitch: switch (ch) {
- case 'u':
- case 'X':
- case 'x':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDUARG();
- break;
- default: /* "%?" prints ?, unless ? is NUL */
-@@ -1537,7 +1988,7 @@ done:
- (*argtable) [n].sizearg = va_arg (ap, size_t);
- break;
- case TP_SIZET:
-- (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
-+ (*argtable) [n].psizearg = va_arg (ap, size_t *);
- break;
- case T_INTMAXT:
- (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
-@@ -1556,6 +2007,11 @@ done:
- (*argtable) [n].longdoublearg = va_arg (ap, long double);
- break;
- #endif
-+#ifdef VECTORS
-+ case T_VECTOR:
-+ (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
-+ break;
-+#endif /* VECTORS */
- case TP_CHAR:
- (*argtable) [n].pchararg = va_arg (ap, char *);
- break;
-@@ -1590,12 +2046,12 @@ __grow_type_table (int nextarg, enum typ
- newsize = nextarg + 1;
- if (oldsize == STATIC_ARG_TBL_SIZE) {
- if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
-- abort(); /* XXX handle better */
-+ LIBC_ABORT("malloc: %s", strerror(errno)); /* XXX handle better */
- bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
- } else {
- newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
- if (newtable == NULL)
-- abort(); /* XXX handle better */
-+ LIBC_ABORT("reallocf: %s", strerror(errno)); /* XXX handle better */
- }
- for (n = oldsize; n < newsize; n++)
- newtable[n] = T_UNUSED;
+@@ -950,7 +1347,7 @@ number: if ((dprec = prec) >= 0)
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+- if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
++ if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+@@ -968,7 +1365,7 @@ number: if ((dprec = prec) >= 0)
+ } else {
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+- cp, dtoaend);
++ cp, dtoaend, loc);
+ if (n < 0)
+ goto error;
+ cp += n;
* 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.
static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.37 2004/05/02 10:55:05 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.43 2009/01/19 06:19:51 das Exp $");
#include "namespace.h"
#include <ctype.h>
#define CT_FLOAT 4 /* %[efgEFG] conversion */
static const u_char *__sccl(char *, const u_char *);
+#ifndef NO_FLOATING_POINT
static int parsefloat(FILE *, char *, char *);
-
-int __scanfdebug = 0;
+#endif
__weak_reference(__vfscanf, vfscanf);
char ccltab[256]; /* character class table for %[...] */
char buf[BUF]; /* buffer for numeric and mb conversions */
wchar_t *wcp; /* handy wide character pointer */
- wchar_t *wcp0; /* saves original value of wcp */
size_t nconv; /* length of multibyte sequence converted */
static const mbstate_t initial;
mbstate_t mbs;
}
nread += sum;
} else {
- size_t r = fread((void *)va_arg(ap, char *), 1,
+ size_t r = __fread((void *)va_arg(ap, char *), 1,
width, fp);
if (r == 0)
int nchars;
if ((flags & SUPPRESS) == 0)
- wcp = wcp0 = va_arg(ap, wchar_t *);
+ wcp = va_arg(ap, wchar_t *);
else
- wcp = wcp0 = &twc;
+ wcp = &twc;
n = 0;
nchars = 0;
while (width != 0) {
float res = strtof(buf, &p);
*va_arg(ap, float *) = res;
}
- if (__scanfdebug && p - buf != width)
- abort();
nassigned++;
}
nread += width;
parsefloat(FILE *fp, char *buf, char *end)
{
char *commit, *p;
- int infnanpos = 0;
+ int infnanpos = 0, decptpos = 0;
enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
- S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
+ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
unsigned char c;
- char decpt = *localeconv()->decimal_point;
+ const char *decpt = localeconv()->decimal_point;
_Bool gotmantdig = 0, ishex = 0;
/*
break;
case S_NAN:
switch (infnanpos) {
- case -1: /* XXX kludge to deal with nan(...) */
- goto parsedone;
case 0:
if (c != 'A' && c != 'a')
goto parsedone;
default:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
} else if (!isalnum(c) && c != '_')
goto parsedone;
break;
}
infnanpos++;
break;
+ case S_DONE:
+ goto parsedone;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x') {
goto reswitch;
}
case S_DIGITS:
- if ((ishex && isxdigit(c)) || isdigit(c))
+ if ((ishex && isxdigit(c)) || isdigit(c)) {
gotmantdig = 1;
- else {
+ commit = p;
+ break;
+ } else {
+ state = S_DECPT;
+ goto reswitch;
+ }
+ case S_DECPT:
+ if (c == decpt[decptpos]) {
+ if (decpt[++decptpos] == '\0') {
+ /* We read the complete decpt seq. */
+ state = S_FRAC;
+ if (gotmantdig)
+ commit = p;
+ }
+ break;
+ } else if (!decptpos) {
+ /* We didn't read any decpt characters. */
state = S_FRAC;
- if (c != decpt)
- goto reswitch;
+ goto reswitch;
+ } else {
+ /*
+ * We read part of a multibyte decimal point,
+ * but the rest is invalid, so bail.
+ */
+ goto parsedone;
}
- if (gotmantdig)
- commit = p;
- break;
case S_FRAC:
if (((c == 'E' || c == 'e') && !ishex) ||
((c == 'P' || c == 'p') && ishex)) {
---- vfscanf.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ vfscanf.c 2009-02-16 00:22:06.000000000 -0800
-@@ -40,6 +40,8 @@ static char sccsid[] = "@(#)vfscanf.c 8.
+--- vfscanf.c.orig 2010-07-15 10:03:36.000000000 -0700
++++ vfscanf.c 2010-07-15 10:18:58.000000000 -0700
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)vfscanf.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.37 2004/05/02 10:55:05 das Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.43 2009/01/19 06:19:51 das Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <ctype.h>
#include <inttypes.h>
-@@ -50,6 +52,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
+@@ -46,6 +48,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include "un-namespace.h"
#include "collate.h"
-@@ -97,10 +100,21 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
+@@ -93,9 +96,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
#define CT_INT 3 /* %[dioupxX] conversion */
#define CT_FLOAT 4 /* %[efgEFG] conversion */
-static const u_char *__sccl(char *, const u_char *);
--static int parsefloat(FILE *, char *, char *);
+static const u_char *__sccl(char *, const u_char *, locale_t);
-+#ifndef NO_FLOATING_POINT
+ #ifndef NO_FLOATING_POINT
+-static int parsefloat(FILE *, char *, char *);
+static int parsefloat(FILE *, char **, size_t, locale_t);
-+#endif /* !NO_FLOATING_POINT */
-
-+/*
-+ * For ppc, we need to have the 64-bit long double version defining storage for
-+ * __scanfdebug, to be compatible with 10.3. For ppc64 and i386, we want the
-+ * storage defined in the only version.
-+ */
-+#if defined(__ppc__) && !defined(BUILDING_VARIANT)
-+extern int __scanfdebug;
-+#else /* !__ppc__ || BUILDING_VARIANT */
- int __scanfdebug = 0;
-+#endif /* __ppc__ && !BUILDING_VARIANT */
+ #endif
__weak_reference(__vfscanf, vfscanf);
-
-@@ -108,12 +122,24 @@ __weak_reference(__vfscanf, vfscanf);
+@@ -104,12 +107,24 @@ __weak_reference(__vfscanf, vfscanf);
* __vfscanf - MT-safe version
*/
int
FUNLOCKFILE(fp);
return (ret);
}
-@@ -121,8 +147,8 @@ __vfscanf(FILE *fp, char const *fmt0, va
+@@ -117,8 +132,8 @@ __vfscanf(FILE *fp, char const *fmt0, va
/*
* __svfscanf - non-MT-safe version of __vfscanf
*/
{
const u_char *fmt = (const u_char *)fmt0;
int c; /* character from format, or conversion */
-@@ -132,7 +158,6 @@ __svfscanf(FILE *fp, const char *fmt0, v
+@@ -128,36 +143,43 @@ __svfscanf(FILE *fp, const char *fmt0, v
int flags; /* flags as defined above */
char *p0; /* saves original value of p when necessary */
int nassigned; /* number of fields assigned */
int nread; /* number of characters consumed from fp */
int base; /* base argument to conversion function */
char ccltab[256]; /* character class table for %[...] */
-@@ -140,29 +165,37 @@ __svfscanf(FILE *fp, const char *fmt0, v
+ char buf[BUF]; /* buffer for numeric and mb conversions */
wchar_t *wcp; /* handy wide character pointer */
- wchar_t *wcp0; /* saves original value of wcp */
size_t nconv; /* length of multibyte sequence converted */
+ int index; /* %index$, zero if unset */
+ va_list ap_orig; /* to reset ap to first argument */
width = 0;
flags = 0;
/*
-@@ -172,15 +205,35 @@ __svfscanf(FILE *fp, const char *fmt0, v
+@@ -167,15 +189,35 @@ __svfscanf(FILE *fp, const char *fmt0, v
again: c = *fmt++;
switch (c) {
case '%':
case '*':
flags |= SUPPRESS;
goto again;
-@@ -267,7 +320,7 @@ literal:
+@@ -262,7 +304,7 @@ literal:
break;
case '[':
flags |= NOSKIP;
c = CT_CCL;
break;
-@@ -288,7 +341,6 @@ literal:
+@@ -283,27 +325,28 @@ literal:
break;
case 'n':
- nconversions++;
- if (flags & SUPPRESS) /* ??? */
+- if (flags & SUPPRESS) /* ??? */
++ {
++ void *ptr = va_arg(ap, void *);
++ if ((ptr == NULL) || (flags & SUPPRESS)) /* ??? */
continue;
- if (flags & SHORTSHORT)
-@@ -330,7 +382,7 @@ literal:
+- if (flags & SHORTSHORT)
+- *va_arg(ap, char *) = nread;
++ else if (flags & SHORTSHORT)
++ *(char *)ptr = nread;
+ else if (flags & SHORT)
+- *va_arg(ap, short *) = nread;
++ *(short *)ptr = nread;
+ else if (flags & LONG)
+- *va_arg(ap, long *) = nread;
++ *(long *)ptr = nread;
+ else if (flags & LONGLONG)
+- *va_arg(ap, long long *) = nread;
++ *(long long *)ptr = nread;
+ else if (flags & INTMAXT)
+- *va_arg(ap, intmax_t *) = nread;
++ *(intmax_t *)ptr = nread;
+ else if (flags & SIZET)
+- *va_arg(ap, size_t *) = nread;
++ *(size_t *)ptr = nread;
+ else if (flags & PTRDIFFT)
+- *va_arg(ap, ptrdiff_t *) = nread;
++ *(ptrdiff_t *)ptr = nread;
+ else
+- *va_arg(ap, int *) = nread;
++ *(int *)ptr = nread;
+ continue;
+-
++ }
+ default:
+ goto match_failure;
+
+@@ -325,7 +368,7 @@ literal:
* that suppress this.
*/
if ((flags & NOSKIP) == 0) {
nread++;
if (--fp->_r > 0)
fp->_p++;
-@@ -360,7 +412,7 @@ literal:
+@@ -355,7 +398,7 @@ literal:
wcp = NULL;
n = 0;
while (width != 0) {
fp->_flags |= __SERR;
goto input_failure;
}
-@@ -368,7 +420,7 @@ literal:
+@@ -363,7 +406,7 @@ literal:
fp->_p++;
fp->_r--;
mbs = initial;
if (nconv == (size_t)-1) {
fp->_flags |= __SERR;
goto input_failure;
-@@ -421,7 +473,6 @@ literal:
+@@ -416,7 +459,6 @@ literal:
nread += r;
nassigned++;
}
break;
case CT_CCL:
-@@ -440,7 +491,7 @@ literal:
+@@ -435,7 +477,7 @@ literal:
n = 0;
nchars = 0;
while (width != 0) {
fp->_flags |= __SERR;
goto input_failure;
}
-@@ -448,7 +499,7 @@ literal:
+@@ -443,7 +485,7 @@ literal:
fp->_p++;
fp->_r--;
mbs = initial;
if (nconv == (size_t)-1) {
fp->_flags |= __SERR;
goto input_failure;
-@@ -456,8 +507,8 @@ literal:
+@@ -451,8 +493,8 @@ literal:
if (nconv == 0)
*wcp = L'\0';
if (nconv != (size_t)-2) {
while (n != 0) {
n--;
__ungetc(buf[n],
-@@ -525,7 +576,6 @@ literal:
+@@ -520,7 +562,6 @@ literal:
nassigned++;
}
nread += n;
break;
case CT_STRING:
-@@ -540,8 +590,8 @@ literal:
+@@ -535,8 +576,8 @@ literal:
else
wcp = &twc;
n = 0;
fp->_flags |= __SERR;
goto input_failure;
}
-@@ -549,7 +599,7 @@ literal:
+@@ -544,7 +585,7 @@ literal:
fp->_p++;
fp->_r--;
mbs = initial;
if (nconv == (size_t)-1) {
fp->_flags |= __SERR;
goto input_failure;
-@@ -557,7 +607,7 @@ literal:
+@@ -552,7 +593,7 @@ literal:
if (nconv == 0)
*wcp = L'\0';
if (nconv != (size_t)-2) {
while (n != 0) {
n--;
__ungetc(buf[n],
-@@ -585,7 +635,7 @@ literal:
+@@ -580,7 +621,7 @@ literal:
}
} else if (flags & SUPPRESS) {
n = 0;
n++, fp->_r--, fp->_p++;
if (--width == 0)
break;
-@@ -595,7 +645,7 @@ literal:
+@@ -590,7 +631,7 @@ literal:
nread += n;
} else {
p0 = p = va_arg(ap, char *);
fp->_r--;
*p++ = *fp->_p++;
if (--width == 0)
-@@ -607,7 +657,6 @@ literal:
+@@ -602,7 +643,6 @@ literal:
nread += p - p0;
nassigned++;
}
continue;
case CT_INT:
-@@ -738,9 +787,9 @@ literal:
+@@ -733,9 +773,9 @@ literal:
*p = 0;
if ((flags & UNSIGNED) == 0)
if (flags & POINTER)
*va_arg(ap, void **) =
(void *)(uintptr_t)res;
-@@ -763,43 +812,48 @@ literal:
+@@ -758,41 +798,46 @@ literal:
nassigned++;
}
nread += p - buf;
+ float res = strtof_l(pbuf, &p, loc);
*va_arg(ap, float *) = res;
}
-- if (__scanfdebug && p - buf != width)
-- abort();
-+ if (__scanfdebug && p - pbuf != width)
-+ LIBC_ABORT("p - pbuf %ld != width %ld", (long)(p - pbuf), width);
nassigned++;
}
nread += width;
/*
* Fill in the given table from the scanset at the given format
* (just after `['). Return a pointer to the character past the
-@@ -807,9 +861,10 @@ match_failure:
+@@ -800,9 +845,10 @@ match_failure:
* considered part of the scanset.
*/
static const u_char *
{
int c, n, v, i;
-@@ -845,6 +900,7 @@ doswitch:
+@@ -838,6 +884,7 @@ doswitch:
return (fmt - 1);
case '-':
/*
* A scanset of the form
* [01+-]
-@@ -865,8 +921,8 @@ doswitch:
+@@ -858,8 +905,8 @@ doswitch:
*/
n = *fmt;
if (n == ']'
)
) {
c = '-';
-@@ -874,14 +930,14 @@ doswitch:
+@@ -867,14 +914,14 @@ doswitch:
}
fmt++;
/* fill in the range */
)
tab[i] = v;
}
-@@ -901,7 +957,7 @@ doswitch:
+@@ -894,7 +941,7 @@ doswitch:
return (fmt);
#endif
break;
case ']': /* end of scanset */
return (fmt);
-@@ -914,19 +970,75 @@ doswitch:
+@@ -907,8 +954,54 @@ doswitch:
}
#ifndef NO_FLOATING_POINT
+parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
{
char *commit, *p;
- int infnanpos = 0;
- enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
-- S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
-+ S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS, S_DECIMAL_POINT
+ int infnanpos = 0, decptpos = 0;
+@@ -917,9 +1010,18 @@ parsefloat(FILE *fp, char *buf, char *en
+ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
unsigned char c;
-- char decpt = *localeconv()->decimal_point;
-+ unsigned char *decpt = (unsigned char *)localeconv_l(loc)->decimal_point;
-+ char *decpt_start;
+- const char *decpt = localeconv()->decimal_point;
++ const char *decpt = localeconv_l(loc)->decimal_point;
_Bool gotmantdig = 0, ishex = 0;
-
+ char *b;
/*
* We set commit = p whenever the string we have read so far
* constitutes a valid representation of a floating point
-@@ -936,8 +1048,8 @@ parsefloat(FILE *fp, char *buf, char *en
+@@ -929,8 +1031,8 @@ parsefloat(FILE *fp, char *buf, char *en
* always necessary to read at least one character that doesn't
* match; thus, we can't short-circuit "infinity" or "nan(...)".
*/
c = *fp->_p;
reswitch:
switch (state) {
-@@ -997,7 +1109,7 @@ reswitch:
+@@ -988,7 +1090,7 @@ reswitch:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
- } else if (!isalnum(c) && c != '_')
+ } else if (!isalnum_l(c, loc) && c != '_')
goto parsedone;
break;
}
-@@ -1013,16 +1125,33 @@ reswitch:
+@@ -1006,7 +1108,7 @@ reswitch:
goto reswitch;
}
case S_DIGITS:
-- if ((ishex && isxdigit(c)) || isdigit(c))
-+ if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc))
+- if ((ishex && isxdigit(c)) || isdigit(c)) {
++ if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
gotmantdig = 1;
- else {
-- state = S_FRAC;
-- if (c != decpt)
-- goto reswitch;
-+ state = S_DECIMAL_POINT;
-+ decpt_start = p;
-+ goto reswitch;
- }
- if (gotmantdig)
commit = p;
- break;
-+ case S_DECIMAL_POINT:
-+ if (*decpt == 0) {
-+ if (gotmantdig)
-+ commit = p - 1;
-+ state = S_FRAC;
-+ goto reswitch;
-+ }
-+ if (*decpt++ == c)
-+ break;
-+ /* not decimal point */
-+ state = S_FRAC;
-+ if (decpt_start == p)
-+ goto reswitch;
-+ while (decpt_start < --p)
-+ __ungetc(*(u_char *)p, fp);
-+ c = *(u_char *)p;
-+ goto reswitch;
- case S_FRAC:
- if (((c == 'E' || c == 'e') && !ishex) ||
- ((c == 'P' || c == 'p') && ishex)) {
-@@ -1030,7 +1159,7 @@ reswitch:
+ break;
+@@ -1041,7 +1143,7 @@ reswitch:
goto parsedone;
else
state = S_EXP;
commit = p;
gotmantdig = 1;
} else
-@@ -1043,13 +1172,26 @@ reswitch:
+@@ -1054,13 +1156,26 @@ reswitch:
else
goto reswitch;
case S_EXPDIGITS:
}
*p++ = c;
if (--fp->_r > 0)
-@@ -1062,6 +1204,7 @@ parsedone:
+@@ -1073,6 +1188,7 @@ parsedone:
while (commit < --p)
__ungetc(*(u_char *)p, fp);
*++commit = '\0';
* 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.
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.23 2004/08/26 06:25:28 des Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.42 2009/11/25 04:27:55 wollman Exp $");
/*
* Actual wprintf innards.
#include "libc_private.h"
#include "local.h"
#include "fvwrite.h"
+#include "printflocal.h"
-union arg {
- int intarg;
- u_int uintarg;
- long longarg;
- u_long ulongarg;
- long long longlongarg;
- unsigned long long ulonglongarg;
- ptrdiff_t ptrdiffarg;
- size_t sizearg;
- intmax_t intmaxarg;
- uintmax_t uintmaxarg;
- void *pvoidarg;
- char *pchararg;
- signed char *pschararg;
- short *pshortarg;
- int *pintarg;
- long *plongarg;
- long long *plonglongarg;
- ptrdiff_t *pptrdiffarg;
- size_t *psizearg;
- intmax_t *pintmaxarg;
-#ifndef NO_FLOATING_POINT
- double doublearg;
- long double longdoublearg;
-#endif
- wint_t wintarg;
- wchar_t *pwchararg;
+static int __sprint(FILE *, struct __suio *);
+static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline;
+static wint_t __xfputwc(wchar_t, FILE *);
+static wchar_t *__mbsconv(char *, int);
+
+#define CHAR wchar_t
+#include "printfcommon.h"
+
+struct grouping_state {
+ wchar_t thousands_sep; /* locale-specific thousands separator */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
};
+static const mbstate_t initial_mbs;
+
+static inline wchar_t
+get_decpt(void)
+{
+ mbstate_t mbs;
+ wchar_t decpt;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+ return (decpt);
+}
+
+static inline wchar_t
+get_thousep(void)
+{
+ mbstate_t mbs;
+ wchar_t thousep;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc(&thousep, localeconv()->thousands_sep,
+ MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ thousep = '\0'; /* failsafe */
+ return (thousep);
+}
+
/*
- * Type ids for argument type table.
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of wide characters that will be printed.
*/
-enum typeid {
- T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
- T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
- T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
- T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-};
+static int
+grouping_init(struct grouping_state *gs, int ndigits)
+{
-static int __sbprintf(FILE *, const wchar_t *, va_list);
-static wint_t __xfputwc(wchar_t, FILE *);
-static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int,
- char, const char *);
-static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int,
- char, const char *);
-static wchar_t *__mbsconv(char *, int);
-static void __find_arguments(const wchar_t *, va_list, union arg **);
-static void __grow_type_table(int, enum typeid **, int *);
+ gs->grouping = localeconv()->grouping;
+ gs->thousands_sep = get_thousep();
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return (gs->nseps + gs->nrepeats);
+}
+
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, &gs->thousands_sep, 1))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
+
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ *
+ * XXX The fact that we do this a character at a time and convert to a
+ * multibyte character sequence even if the destination is a wide
+ * string eclipses the benefits of buffering.
+ */
+static int
+__sprint(FILE *fp, struct __suio *uio)
+{
+ struct __siov *iov;
+ wchar_t *p;
+ int i, len;
+
+ iov = uio->uio_iov;
+ for (; uio->uio_resid != 0; uio->uio_resid -= len, iov++) {
+ p = (wchar_t *)iov->iov_base;
+ len = iov->iov_len;
+ for (i = 0; i < len; i++) {
+ if (__xfputwc(p[i], fp) == WEOF)
+ return (-1);
+ }
+ }
+ uio->uio_iovcnt = 0;
+ return (0);
+}
/*
* Helper function for `fprintf to unbuffered unix file': creates a
FILE fake;
unsigned char buf[BUFSIZ];
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
/* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
- fake._extra = fp->_extra;
+ fake._orientation = fp->_orientation;
+ fake._mbstate = fp->_mbstate;
/* set up the buffer */
fake._bf._base = fake._p = buf;
static wint_t
__xfputwc(wchar_t wc, FILE *fp)
{
- static const mbstate_t initial;
mbstate_t mbs;
char buf[MB_LEN_MAX];
struct __suio uio;
if ((fp->_flags & __SSTR) == 0)
return (__fputwc(wc, fp));
- mbs = initial;
+ mbs = initial_mbs;
if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF);
}
-/*
- * Macros for converting digits to letters and vice versa
- */
-#define to_digit(c) ((c) - '0')
-#define is_digit(c) ((unsigned)to_digit(c) <= 9)
-#define to_char(n) ((n) + '0')
-
-/*
- * Convert an unsigned long to ASCII for printf purposes, returning
- * a pointer to the first character of the string representation.
- * Octal numbers can be forced to have a leading zero; hex numbers
- * use the given digits.
- */
-static wchar_t *
-__ultoa(u_long val, wchar_t *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- wchar_t *cp = endp;
- long sval;
- int ndig;
-
- /*
- * Handle the three cases separately, in the hope of getting
- * better/faster code.
- */
- switch (base) {
- case 10:
- if (val < 10) { /* many numbers are 1 digit */
- *--cp = to_char(val);
- return (cp);
- }
- ndig = 0;
- /*
- * On many machines, unsigned arithmetic is harder than
- * signed arithmetic, so we do at most one unsigned mod and
- * divide; this is sufficient to reduce the range of
- * the incoming value to where signed arithmetic works.
- */
- if (val > LONG_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && ndig == *grp && *grp != CHAR_MAX
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default: /* oops */
- abort();
- }
- return (cp);
-}
-
-/* Identical to __ultoa, but for intmax_t. */
-static wchar_t *
-__ujtoa(uintmax_t val, wchar_t *endp, int base, int octzero,
- const char *xdigs, int needgrp, char thousep, const char *grp)
-{
- wchar_t *cp = endp;
- intmax_t sval;
- int ndig;
-
- /* quick test for small values; __ultoa is typically much faster */
- /* (perhaps instead we should run until small, then call __ultoa?) */
- if (val <= ULONG_MAX)
- return (__ultoa((u_long)val, endp, base, octzero, xdigs,
- needgrp, thousep, grp));
- switch (base) {
- case 10:
- if (val < 10) {
- *--cp = to_char(val % 10);
- return (cp);
- }
- ndig = 0;
- if (val > INTMAX_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && *grp != CHAR_MAX && ndig == *grp
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default:
- abort();
- }
- return (cp);
-}
-
/*
* Convert a multibyte character string argument for the %s format to a wide
* string representation. ``prec'' specifies the maximum number of bytes
static wchar_t *
__mbsconv(char *mbsarg, int prec)
{
- static const mbstate_t initial;
mbstate_t mbs;
wchar_t *convbuf, *wcp;
const char *p;
* number of characters to print.
*/
p = mbsarg;
- insize = nchars = 0;
- mbs = initial;
+ insize = nchars = nconv = 0;
+ mbs = initial_mbs;
while (nchars != (size_t)prec) {
nconv = mbrlen(p, MB_CUR_MAX, &mbs);
if (nconv == 0 || nconv == (size_t)-1 ||
}
if (nconv == (size_t)-1 || nconv == (size_t)-2)
return (NULL);
- } else
+ } else {
insize = strlen(mbsarg);
+ nconv = 0;
+ }
/*
* Allocate buffer for the result and perform the conversion,
return (NULL);
wcp = convbuf;
p = mbsarg;
- mbs = initial;
+ mbs = initial_mbs;
while (insize != 0) {
nconv = mbrtowc(wcp, p, insize, &mbs);
if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
int ret;
FLOCKFILE(fp);
- ret = __vfwprintf(fp, fmt0, ap);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, fmt0, ap);
+ else
+ ret = __vfwprintf(fp, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
-#ifndef NO_FLOATING_POINT
-
-#define dtoa __dtoa
-#define freedtoa __freedtoa
-
-#include <float.h>
-#include <math.h>
-#include "floatio.h"
-#include "gdtoa.h"
-
-#define DEFPREC 6
-
-static int exponent(wchar_t *, int, wchar_t);
-
-#endif /* !NO_FLOATING_POINT */
-
/*
* The size of the buffer we use as scratch space for integer
- * conversions, among other things. Technically, we would need the
- * most space for base 10 conversions with thousands' grouping
- * characters between each pair of digits. 100 bytes is a
- * conservative overestimate even for a 128-bit uintmax_t.
- */
-#define BUF 100
-
-#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
-
-/*
- * Flags used during conversion.
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
*/
-#define ALT 0x001 /* alternate form */
-#define LADJUST 0x004 /* left adjustment */
-#define LONGDBL 0x008 /* long double */
-#define LONGINT 0x010 /* long integer */
-#define LLONGINT 0x020 /* long long integer */
-#define SHORTINT 0x040 /* short integer */
-#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
-#define FPT 0x100 /* Floating point number */
-#define GROUPING 0x200 /* use grouping ("'" flag) */
- /* C99 additional size modifiers: */
-#define SIZET 0x400 /* size_t */
-#define PTRDIFFT 0x800 /* ptrdiff_t */
-#define INTMAXT 0x1000 /* intmax_t */
-#define CHARINT 0x2000 /* print char using int format */
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
/*
* Non-MT-safe version
{
wchar_t *fmt; /* format string */
wchar_t ch; /* character from fmt */
- int n, n2, n3; /* handy integer (short term usage) */
+ int n, n2; /* handy integer (short term usage) */
wchar_t *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
- char thousands_sep; /* locale specific thousands separator */
- const char *grouping; /* locale specific numeric grouping rules */
+ struct grouping_state gs; /* thousands' grouping info */
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
* D: expchar holds this character; '\0' if no exponent, e.g. %f
* F: at least two digits for decimal, at least one digit for hex
*/
- char *decimal_point; /* locale specific decimal point */
+ wchar_t decimal_point; /* locale specific decimal point */
int signflag; /* true if float is negative */
union { /* floating point arguments %[aAeEfFgG] */
double dbl;
char expchar; /* exponent character: [eEpP\0] */
char *dtoaend; /* pointer to end of converted digits */
int expsize; /* character count for expstr */
- int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
char *dtoaresult; /* buffer allocated by dtoa */
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
#endif
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int size; /* size of converted field or string */
int prsize; /* max size of printed field */
const char *xdigs; /* digits for [xX] conversion */
+ struct io_state io; /* I/O buffering state */
wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */
wchar_t ox[2]; /* space for 0x hex-prefix */
union arg *argtable; /* args, built due to positional arg */
va_list orgap; /* original argument pointer */
wchar_t *convbuf; /* multibyte to wide conversion result */
- /*
- * Choose PADSIZE to trade efficiency vs. size. If larger printf
- * fields occur frequently, increase PADSIZE and make the initialisers
- * below longer.
- */
-#define PADSIZE 16 /* pad chunk size */
- static wchar_t blanks[PADSIZE] =
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static wchar_t zeroes[PADSIZE] =
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
-
static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF";
- /*
- * BEWARE, these `goto error' on error, PRINT uses `n2' and
- * PAD uses `n'.
- */
+ /* BEWARE, these `goto error' on error. */
#define PRINT(ptr, len) do { \
- for (n3 = 0; n3 < (len); n3++) \
- __xfputwc((ptr)[n3], fp); \
-} while (0)
-#define PAD(howmany, with) do { \
- if ((n = (howmany)) > 0) { \
- while (n > PADSIZE) { \
- PRINT(with, PADSIZE); \
- n -= PADSIZE; \
- } \
- PRINT(with, n); \
- } \
+ if (io_print(&io, (ptr), (len))) \
+ goto error; \
} while (0)
-#define PRINTANDPAD(p, ep, len, with) do { \
- n2 = (ep) - (p); \
- if (n2 > (len)) \
- n2 = (len); \
- if (n2 > 0) \
- PRINT((p), n2); \
- PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
-} while(0)
+#define PAD(howmany, with) { \
+ if (io_pad(&io, (howmany), (with))) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with))) \
+ goto error; \
+}
+#define FLUSH() { \
+ if (io_flush(&io)) \
+ goto error; \
+}
/*
* Get the argument indexed by nextarg. If the argument table is
#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
#define SJARG() \
(flags&INTMAXT ? GETARG(intmax_t) : \
- flags&SIZET ? (intmax_t)GETARG(size_t) : \
+ flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
(intmax_t)GETARG(long long))
#define UJARG() \
int hold = nextarg; \
if (argtable == NULL) { \
argtable = statargtable; \
- __find_arguments (fmt0, orgap, &argtable); \
+ if (__find_warguments (fmt0, orgap, &argtable)) { \
+ ret = EOF; \
+ goto error; \
+ } \
} \
nextarg = n2; \
val = GETARG (int); \
}
- thousands_sep = '\0';
- grouping = NULL;
-#ifndef NO_FLOATING_POINT
- decimal_point = localeconv()->decimal_point;
-#endif
- convbuf = NULL;
/* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
if (prepwrite(fp) != 0)
return (EOF);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
- return (__sbprintf(fp, fmt0, ap));
-
+ convbuf = NULL;
fmt = (wchar_t *)fmt0;
argtable = NULL;
nextarg = 1;
va_copy(orgap, ap);
+ io_init(&io, fp);
ret = 0;
+#ifndef NO_FLOATING_POINT
+ decimal_point = get_decpt();
+#endif
/*
* Scan the format for conversions (`%' character).
dprec = 0;
width = 0;
prec = -1;
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
goto rflag;
case '\'':
flags |= GROUPING;
- thousands_sep = *(localeconv()->thousands_sep);
- grouping = localeconv()->grouping;
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
nextarg = n;
if (argtable == NULL) {
argtable = statargtable;
- __find_arguments (fmt0, orgap,
- &argtable);
+ if (__find_warguments (fmt0, orgap,
+ &argtable)) {
+ ret = EOF;
+ goto error;
+ }
}
goto rflag;
}
} else
cp = (ch >= 'a') ? L"inf" : L"INF";
size = 3;
+ flags &= ~ZEROPAD;
break;
}
flags |= FPT;
/* space for decimal pt and following digits */
if (prec || flags & ALT)
size += prec + 1;
- if (grouping && expt > 0) {
- /* space for thousands' grouping */
- nseps = nrepeats = 0;
- lead = expt;
- while (*grouping != CHAR_MAX) {
- if (lead <= *grouping)
- break;
- lead -= *grouping;
- if (*(grouping+1)) {
- nseps++;
- grouping++;
- } else
- nrepeats++;
- }
- size += nseps + nrepeats;
- } else
- lead = expt;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt);
}
break;
#endif /* !NO_FLOATING_POINT */
cp = convbuf;
}
}
-
- if (prec >= 0) {
- /*
- * can't use wcslen; can only look for the
- * NUL in the first `prec' characters, and
- * wcslen() will go further.
- */
- wchar_t *p = wmemchr(cp, 0, (size_t)prec);
-
- if (p != NULL) {
- size = p - cp;
- if (size > prec)
- size = prec;
- } else
- size = prec;
- } else
- size = wcslen(cp);
+ size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp);
sign = '\0';
break;
case 'U':
* ``The result of converting a zero value with an
* explicit precision of zero is no characters.''
* -- ANSI X3J11
+ *
+ * ``The C Standard is clear enough as is. The call
+ * printf("%#.0o", 0) should print 0.''
+ * -- Defect Report #151
*/
cp = buf + BUF;
if (flags & INTMAX_SIZE) {
- if (ujval != 0 || prec != 0)
+ if (ujval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ujtoa(ujval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
} else {
- if (ulval != 0 || prec != 0)
+ if (ulval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
abort();
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size);
break;
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD(width - realsz, zeroes);
- /* leading zeroes from decimal precision */
- PAD(dprec - size, zeroes);
-
/* the string or number proper */
#ifndef NO_FLOATING_POINT
if ((flags & FPT) == 0) {
- PRINT(cp, size);
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
} else { /* glue together f_p fragments */
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
if (expt <= 0) {
PRINT(zeroes, 1);
if (prec || flags & ALT)
- PRINT(decimal_point, 1);
+ PRINT(&decimal_point, 1);
PAD(-expt, zeroes);
/* already handled initial 0's */
prec += expt;
} else {
- PRINTANDPAD(cp, convbuf + ndig, lead, zeroes);
- cp += lead;
- if (grouping) {
- while (nseps>0 || nrepeats>0) {
- if (nrepeats > 0)
- nrepeats--;
- else {
- grouping--;
- nseps--;
- }
- PRINT(&thousands_sep,
- 1);
- PRINTANDPAD(cp,
- convbuf + ndig,
- *grouping, zeroes);
- cp += *grouping;
- }
- if (cp > convbuf + ndig)
- cp = convbuf + ndig;
- }
- if (prec || flags & ALT) {
- buf[0] = *decimal_point;
- PRINT(buf, 1);
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, convbuf + ndig);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, convbuf + ndig,
+ expt, zeroes);
+ cp += expt;
}
+ if (prec || flags & ALT)
+ PRINT(&decimal_point, 1);
}
PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
if (prec > 1 || flags & ALT) {
buf[0] = *cp++;
- buf[1] = *decimal_point;
+ buf[1] = decimal_point;
PRINT(buf, 2);
PRINT(cp, ndig-1);
PAD(prec - ndig, zeroes);
PRINT(expstr, expsize);
}
}
-#else
- PRINT(cp, size);
#endif
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
/* finally, adjust ret */
ret += prsize;
+
+ FLUSH(); /* copy out the I/O vectors */
}
done:
+ FLUSH();
error:
va_end(orgap);
if (convbuf != NULL)
return (ret);
/* NOTREACHED */
}
-
-/*
- * Find all arguments when a positional parameter is encountered. Returns a
- * table, indexed by argument number, of pointers to each arguments. The
- * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
- * It will be replaces with a malloc-ed one if it overflows.
- */
-static void
-__find_arguments (const wchar_t *fmt0, va_list ap, union arg **argtable)
-{
- wchar_t *fmt; /* format string */
- wchar_t ch; /* character from fmt */
- int n, n2; /* handy integer (short term usage) */
- wchar_t *cp; /* handy char pointer (short term usage) */
- int flags; /* flags as above */
- int width; /* width from format (%8d), or 0 */
- enum typeid *typetable; /* table of types */
- enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
- int tablesize; /* current size of type table */
- int tablemax; /* largest used index in table */
- int nextarg; /* 1-based argument index */
-
- /*
- * Add an argument type to the table, expanding if necessary.
- */
-#define ADDTYPE(type) \
- ((nextarg >= tablesize) ? \
- __grow_type_table(nextarg, &typetable, &tablesize) : (void)0, \
- (nextarg > tablemax) ? tablemax = nextarg : 0, \
- typetable[nextarg++] = type)
-
-#define ADDSARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
-
-#define ADDUARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
-
- /*
- * Add * arguments to the type array.
- */
-#define ADDASTER() \
- n2 = 0; \
- cp = fmt; \
- while (is_digit(*cp)) { \
- n2 = 10 * n2 + to_digit(*cp); \
- cp++; \
- } \
- if (*cp == '$') { \
- int hold = nextarg; \
- nextarg = n2; \
- ADDTYPE (T_INT); \
- nextarg = hold; \
- fmt = ++cp; \
- } else { \
- ADDTYPE (T_INT); \
- }
- fmt = (wchar_t *)fmt0;
- typetable = stattypetable;
- tablesize = STATIC_ARG_TBL_SIZE;
- tablemax = 0;
- nextarg = 1;
- for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
- typetable[n] = T_UNUSED;
-
- /*
- * Scan the format for conversions (`%' character).
- */
- for (;;) {
- for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
- /* void */;
- if (ch == '\0')
- goto done;
- fmt++; /* skip over '%' */
-
- flags = 0;
- width = 0;
-
-rflag: ch = *fmt++;
-reswitch: switch (ch) {
- case ' ':
- case '#':
- goto rflag;
- case '*':
- ADDASTER ();
- goto rflag;
- case '-':
- case '+':
- case '\'':
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- ADDASTER ();
- goto rflag;
- }
- while (is_digit(ch)) {
- ch = *fmt++;
- }
- goto reswitch;
- case '0':
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- } while (is_digit(ch));
- if (ch == '$') {
- nextarg = n;
- goto rflag;
- }
- width = n;
- goto reswitch;
-#ifndef NO_FLOATING_POINT
- case 'L':
- flags |= LONGDBL;
- goto rflag;
-#endif
- case 'h':
- if (flags & SHORTINT) {
- flags &= ~SHORTINT;
- flags |= CHARINT;
- } else
- flags |= SHORTINT;
- goto rflag;
- case 'j':
- flags |= INTMAXT;
- goto rflag;
- case 'l':
- if (flags & LONGINT) {
- flags &= ~LONGINT;
- flags |= LLONGINT;
- } else
- flags |= LONGINT;
- goto rflag;
- case 'q':
- flags |= LLONGINT; /* not necessarily */
- goto rflag;
- case 't':
- flags |= PTRDIFFT;
- goto rflag;
- case 'z':
- flags |= SIZET;
- goto rflag;
- case 'C':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'c':
- if (flags & LONGINT)
- ADDTYPE(T_WINT);
- else
- ADDTYPE(T_INT);
- break;
- case 'D':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
- ADDSARG();
- break;
-#ifndef NO_FLOATING_POINT
- case 'a':
- case 'A':
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- if (flags & LONGDBL)
- ADDTYPE(T_LONG_DOUBLE);
- else
- ADDTYPE(T_DOUBLE);
- break;
-#endif /* !NO_FLOATING_POINT */
- case 'n':
- if (flags & INTMAXT)
- ADDTYPE(TP_INTMAXT);
- else if (flags & PTRDIFFT)
- ADDTYPE(TP_PTRDIFFT);
- else if (flags & SIZET)
- ADDTYPE(TP_SIZET);
- else if (flags & LLONGINT)
- ADDTYPE(TP_LLONG);
- else if (flags & LONGINT)
- ADDTYPE(TP_LONG);
- else if (flags & SHORTINT)
- ADDTYPE(TP_SHORT);
- else if (flags & CHARINT)
- ADDTYPE(TP_SCHAR);
- else
- ADDTYPE(TP_INT);
- continue; /* no output */
- case 'O':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
- ADDUARG();
- break;
- case 'p':
- ADDTYPE(TP_VOID);
- break;
- case 'S':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 's':
- if (flags & LONGINT)
- ADDTYPE(TP_WCHAR);
- else
- ADDTYPE(TP_CHAR);
- break;
- case 'U':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'u':
- case 'X':
- case 'x':
- ADDUARG();
- break;
- default: /* "%?" prints ?, unless ? is NUL */
- if (ch == '\0')
- goto done;
- break;
- }
- }
-done:
- /*
- * Build the argument table.
- */
- if (tablemax >= STATIC_ARG_TBL_SIZE) {
- *argtable = (union arg *)
- malloc (sizeof (union arg) * (tablemax + 1));
- }
-
- (*argtable) [0].intarg = 0;
- for (n = 1; n <= tablemax; n++) {
- switch (typetable [n]) {
- case T_UNUSED: /* whoops! */
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case TP_SCHAR:
- (*argtable) [n].pschararg = va_arg (ap, signed char *);
- break;
- case TP_SHORT:
- (*argtable) [n].pshortarg = va_arg (ap, short *);
- break;
- case T_INT:
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case T_U_INT:
- (*argtable) [n].uintarg = va_arg (ap, unsigned int);
- break;
- case TP_INT:
- (*argtable) [n].pintarg = va_arg (ap, int *);
- break;
- case T_LONG:
- (*argtable) [n].longarg = va_arg (ap, long);
- break;
- case T_U_LONG:
- (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
- break;
- case TP_LONG:
- (*argtable) [n].plongarg = va_arg (ap, long *);
- break;
- case T_LLONG:
- (*argtable) [n].longlongarg = va_arg (ap, long long);
- break;
- case T_U_LLONG:
- (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
- break;
- case TP_LLONG:
- (*argtable) [n].plonglongarg = va_arg (ap, long long *);
- break;
- case T_PTRDIFFT:
- (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
- break;
- case TP_PTRDIFFT:
- (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
- break;
- case T_SIZET:
- (*argtable) [n].sizearg = va_arg (ap, size_t);
- break;
- case TP_SIZET:
- (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
- break;
- case T_INTMAXT:
- (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
- break;
- case T_UINTMAXT:
- (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
- break;
- case TP_INTMAXT:
- (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
- break;
-#ifndef NO_FLOATING_POINT
- case T_DOUBLE:
- (*argtable) [n].doublearg = va_arg (ap, double);
- break;
- case T_LONG_DOUBLE:
- (*argtable) [n].longdoublearg = va_arg (ap, long double);
- break;
-#endif
- case TP_CHAR:
- (*argtable) [n].pchararg = va_arg (ap, char *);
- break;
- case TP_VOID:
- (*argtable) [n].pvoidarg = va_arg (ap, void *);
- break;
- case T_WINT:
- (*argtable) [n].wintarg = va_arg (ap, wint_t);
- break;
- case TP_WCHAR:
- (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
- break;
- }
- }
-
- if ((typetable != NULL) && (typetable != stattypetable))
- free (typetable);
-}
-
-/*
- * Increase the size of the type table.
- */
-static void
-__grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
-{
- enum typeid *const oldtable = *typetable;
- const int oldsize = *tablesize;
- enum typeid *newtable;
- int n, newsize = oldsize * 2;
-
- if (newsize < nextarg + 1)
- newsize = nextarg + 1;
- if (oldsize == STATIC_ARG_TBL_SIZE) {
- if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
- abort(); /* XXX handle better */
- bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
- } else {
- newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
- if (newtable == NULL)
- abort(); /* XXX handle better */
- }
- for (n = oldsize; n < newsize; n++)
- newtable[n] = T_UNUSED;
-
- *typetable = newtable;
- *tablesize = newsize;
-}
-
-
-#ifndef NO_FLOATING_POINT
-
-static int
-exponent(wchar_t *p0, int exp, wchar_t fmtch)
-{
- wchar_t *p, *t;
- wchar_t expbuf[MAXEXPDIG];
-
- p = p0;
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- }
- else
- *p++ = '+';
- t = expbuf + MAXEXPDIG;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
- }
- else {
- /*
- * Exponents for decimal floating point conversions
- * (%[eEgG]) must be at least two characters long,
- * whereas exponents for hexadecimal conversions can
- * be only one character long.
- */
- if (fmtch == 'e' || fmtch == 'E')
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p - p0);
-}
-#endif /* !NO_FLOATING_POINT */
---- vfwprintf.c.orig 2008-09-07 11:37:54.000000000 -0700
-+++ vfwprintf.c 2008-09-07 17:47:18.000000000 -0700
-@@ -42,6 +42,8 @@ static char sccsid[] = "@(#)vfprintf.c 8
+--- vfwprintf.c.orig 2010-07-15 10:03:36.000000000 -0700
++++ vfwprintf.c 2010-07-15 10:49:02.000000000 -0700
+@@ -38,6 +38,8 @@ static char sccsid[] = "@(#)vfprintf.c 8
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.23 2004/08/26 06:25:28 des Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.42 2009/11/25 04:27:55 wollman Exp $");
+#include "xlocale_private.h"
+
/*
* Actual wprintf innards.
*
-@@ -63,12 +65,20 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
+@@ -59,6 +61,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include "un-namespace.h"
#include "libc_private.h"
- #include "local.h"
+@@ -66,10 +69,11 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
#include "fvwrite.h"
+ #include "printflocal.h"
-+#ifdef VECTORS
-+typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
-+#ifdef __SSE2__
-+#define V64TYPE
-+#endif /* __SSE2__ */
-+#endif /* VECTORS */
-+
- union arg {
- int intarg;
- u_int uintarg;
-@@ -96,6 +106,21 @@ union arg {
- #endif
- wint_t wintarg;
- wchar_t *pwchararg;
-+#ifdef VECTORS
-+ VECTORTYPE vectorarg;
-+ unsigned char vuchararg[16];
-+ signed char vchararg[16];
-+ unsigned short vushortarg[8];
-+ signed short vshortarg[8];
-+ unsigned int vuintarg[4];
-+ signed int vintarg[4];
-+ float vfloatarg[4];
-+#ifdef V64TYPE
-+ double vdoublearg[2];
-+ unsigned long long vulonglongarg[2];
-+ long long vlonglongarg[2];
-+#endif /* V64TYPE */
-+#endif /* VECTORS */
- };
-
- /*
-@@ -106,16 +131,20 @@ enum typeid {
- T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
- T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
- T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
-+#ifdef VECTORS
-+ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
-+#else /* ! VECTORS */
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-+#endif /* VECTORS */
- };
-
--static int __sbprintf(FILE *, const wchar_t *, va_list);
+-static int __sprint(FILE *, struct __suio *);
+-static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline;
-static wint_t __xfputwc(wchar_t, FILE *);
+-static wchar_t *__mbsconv(char *, int);
++static int __sprint(FILE *, locale_t, struct __suio *);
+static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list);
+static wint_t __xfputwc(wchar_t, FILE *, locale_t);
- static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int,
- char, const char *);
- static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int,
- char, const char *);
--static wchar_t *__mbsconv(char *, int);
+static wchar_t *__mbsconv(char *, int, locale_t);
- static void __find_arguments(const wchar_t *, va_list, union arg **);
- static void __grow_type_table(int, enum typeid **, int *);
++__private_extern__ const char *__fix_nogrouping(const char *);
-@@ -125,7 +154,7 @@ static void __grow_type_table(int, enum
+ #define CHAR wchar_t
+ #include "printfcommon.h"
+@@ -85,29 +89,29 @@ struct grouping_state {
+ static const mbstate_t initial_mbs;
+
+ static inline wchar_t
+-get_decpt(void)
++get_decpt(locale_t loc)
+ {
+ mbstate_t mbs;
+ wchar_t decpt;
+ int nconv;
+
+ mbs = initial_mbs;
+- nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
++ nconv = mbrtowc_l(&decpt, localeconv_l(loc)->decimal_point, MB_CUR_MAX_L(loc), &mbs, loc);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+ return (decpt);
+ }
+
+ static inline wchar_t
+-get_thousep(void)
++get_thousep(locale_t loc)
+ {
+ mbstate_t mbs;
+ wchar_t thousep;
+ int nconv;
+
+ mbs = initial_mbs;
+- nconv = mbrtowc(&thousep, localeconv()->thousands_sep,
+- MB_CUR_MAX, &mbs);
++ nconv = mbrtowc_l(&thousep, localeconv_l(loc)->thousands_sep,
++ MB_CUR_MAX_L(loc), &mbs, loc);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ thousep = '\0'; /* failsafe */
+ return (thousep);
+@@ -119,11 +123,11 @@ get_thousep(void)
+ * of wide characters that will be printed.
+ */
+ static int
+-grouping_init(struct grouping_state *gs, int ndigits)
++grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
+ {
+
+- gs->grouping = localeconv()->grouping;
+- gs->thousands_sep = get_thousep();
++ gs->grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
++ gs->thousands_sep = get_thousep(loc);
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+@@ -145,11 +149,11 @@ grouping_init(struct grouping_state *gs,
+ */
+ static int
+ grouping_print(struct grouping_state *gs, struct io_state *iop,
+- const CHAR *cp, const CHAR *ep)
++ const CHAR *cp, const CHAR *ep, locale_t loc)
+ {
+ const CHAR *cp0 = cp;
+
+- if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
++ if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+@@ -159,9 +163,9 @@ grouping_print(struct grouping_state *gs
+ gs->grouping--;
+ gs->nseps--;
+ }
+- if (io_print(iop, &gs->thousands_sep, 1))
++ if (io_print(iop, &gs->thousands_sep, 1, loc))
+ return (-1);
+- if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
++ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
+ return (-1);
+ cp += *gs->grouping;
+ }
+@@ -180,7 +184,7 @@ grouping_print(struct grouping_state *gs
+ * string eclipses the benefits of buffering.
+ */
+ static int
+-__sprint(FILE *fp, struct __suio *uio)
++__sprint(FILE *fp, locale_t loc, struct __suio *uio)
+ {
+ struct __siov *iov;
+ wchar_t *p;
+@@ -191,7 +195,7 @@ __sprint(FILE *fp, struct __suio *uio)
+ p = (wchar_t *)iov->iov_base;
+ len = iov->iov_len;
+ for (i = 0; i < len; i++) {
+- if (__xfputwc(p[i], fp) == WEOF)
++ if (__xfputwc(p[i], fp, loc) == WEOF)
+ return (-1);
+ }
+ }
+@@ -205,11 +209,14 @@ __sprint(FILE *fp, struct __suio *uio)
* worries about ungetc buffers and so forth.
*/
static int
{
int ret;
FILE fake;
-@@ -144,7 +173,7 @@ __sbprintf(FILE *fp, const wchar_t *fmt,
+ unsigned char buf[BUFSIZ];
++ struct __sFILEX ext;
++ fake._extra = &ext;
++ INITEXTRA(&fake);
+
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+@@ -229,7 +236,7 @@ __sbprintf(FILE *fp, const wchar_t *fmt,
fake._lbfsize = 0; /* not actually used, but Just In Case */
/* do the work, then copy any error status */
if (ret >= 0 && __fflush(&fake))
ret = WEOF;
if (fake._flags & __SERR)
-@@ -157,7 +186,7 @@ __sbprintf(FILE *fp, const wchar_t *fmt,
+@@ -242,7 +249,7 @@ __sbprintf(FILE *fp, const wchar_t *fmt,
* File must already be locked.
*/
static wint_t
-__xfputwc(wchar_t wc, FILE *fp)
+__xfputwc(wchar_t wc, FILE *fp, locale_t loc)
{
- static const mbstate_t initial;
mbstate_t mbs;
-@@ -167,10 +196,10 @@ __xfputwc(wchar_t wc, FILE *fp)
+ char buf[MB_LEN_MAX];
+@@ -251,10 +258,10 @@ __xfputwc(wchar_t wc, FILE *fp)
size_t len;
if ((fp->_flags & __SSTR) == 0)
- return (__fputwc(wc, fp));
+ return (__fputwc(wc, fp, loc));
- mbs = initial;
+ mbs = initial_mbs;
- if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
+ if ((len = wcrtomb_l(buf, wc, &mbs, loc)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
}
-@@ -266,7 +295,7 @@ __ultoa(u_long val, wchar_t *endp, int b
- break;
-
- default: /* oops */
-- abort();
-+ LIBC_ABORT("base = %d", base);
- }
- return (cp);
- }
-@@ -338,7 +367,7 @@ __ujtoa(uintmax_t val, wchar_t *endp, in
- break;
-
- default:
-- abort();
-+ LIBC_ABORT("base = %d", base);
- }
- return (cp);
- }
-@@ -350,13 +379,14 @@ __ujtoa(uintmax_t val, wchar_t *endp, in
+@@ -273,12 +280,13 @@ __xfputwc(wchar_t wc, FILE *fp)
* that the multibyte char. string ends in a null character.
*/
static wchar_t *
-__mbsconv(char *mbsarg, int prec)
+__mbsconv(char *mbsarg, int prec, locale_t loc)
{
- static const mbstate_t initial;
mbstate_t mbs;
wchar_t *convbuf, *wcp;
const char *p;
if (mbsarg == NULL)
return (NULL);
-@@ -374,7 +404,7 @@ __mbsconv(char *mbsarg, int prec)
- insize = nchars = 0;
- mbs = initial;
+@@ -296,7 +304,7 @@ __mbsconv(char *mbsarg, int prec)
+ insize = nchars = nconv = 0;
+ mbs = initial_mbs;
while (nchars != (size_t)prec) {
- nconv = mbrlen(p, MB_CUR_MAX, &mbs);
+ nconv = mbrlen_l(p, mb_cur_max, &mbs, loc);
if (nconv == 0 || nconv == (size_t)-1 ||
nconv == (size_t)-2)
break;
-@@ -399,7 +429,7 @@ __mbsconv(char *mbsarg, int prec)
+@@ -323,7 +331,7 @@ __mbsconv(char *mbsarg, int prec)
p = mbsarg;
- mbs = initial;
+ mbs = initial_mbs;
while (insize != 0) {
- nconv = mbrtowc(wcp, p, insize, &mbs);
+ nconv = mbrtowc_l(wcp, p, insize, &mbs, loc);
if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
break;
wcp++;
-@@ -418,6 +448,8 @@ __mbsconv(char *mbsarg, int prec)
- /*
+@@ -343,22 +351,28 @@ __mbsconv(char *mbsarg, int prec)
* MT-safe version
*/
-+__private_extern__ const char *__fix_nogrouping(const char *);
-+
int
- vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
-
-@@ -425,7 +457,21 @@ vfwprintf(FILE * __restrict fp, const wc
+-vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
+-
++vfwprintf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt0, va_list ap)
+ {
int ret;
- FLOCKFILE(fp);
-- ret = __vfwprintf(fp, fmt0, ap);
-+ ret = __vfwprintf(fp, __current_locale(), fmt0, ap);
-+ FUNLOCKFILE(fp);
-+ return (ret);
-+}
-+
-+int
-+vfwprintf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt0,
-+ va_list ap)
-+
-+{
-+ int ret;
-+
+ NORMALIZE_LOCALE(loc);
-+ FLOCKFILE(fp);
-+ ret = __vfwprintf(fp, loc, fmt0, ap);
+ FLOCKFILE(fp);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+- ret = __sbprintf(fp, fmt0, ap);
++ ret = __sbprintf(fp, loc, fmt0, ap);
+ else
+- ret = __vfwprintf(fp, fmt0, ap);
++ ret = __vfwprintf(fp, loc, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
-@@ -474,12 +520,15 @@ static int exponent(wchar_t *, int, wcha
- #define PTRDIFFT 0x800 /* ptrdiff_t */
- #define INTMAXT 0x1000 /* intmax_t */
- #define CHARINT 0x2000 /* print char using int format */
-+#ifdef VECTORS
-+#define VECTOR 0x4000 /* Altivec or SSE vector */
-+#endif /* VECTORS */
++int
++vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
++{
++ return vfwprintf_l(fp, __current_locale(), fmt0, ap);
++}
++
+ /*
+ * The size of the buffer we use as scratch space for integer
+ * conversions, among other things. We need enough space to
+@@ -373,8 +387,8 @@ vfwprintf(FILE * __restrict fp, const wc
/*
* Non-MT-safe version
*/
{
wchar_t *fmt; /* format string */
wchar_t ch; /* character from fmt */
-@@ -507,7 +556,8 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
- * D: expchar holds this character; '\0' if no exponent, e.g. %f
- * F: at least two digits for decimal, at least one digit for hex
- */
-- char *decimal_point; /* locale specific decimal point */
-+ wchar_t decimal_point; /* locale specific decimal point */
-+ char *decimal_point_mb; /* multibyte decimal point */
- int signflag; /* true if float is negative */
- union { /* floating point arguments %[aAeEfFgG] */
- double dbl;
-@@ -524,6 +574,11 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
+@@ -415,6 +429,11 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
+ wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
+ char *dtoaresult; /* buffer allocated by dtoa */
#endif
+#ifdef VECTORS
+ union arg vval; /* Vector argument. */
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int base; /* base for [diouxX] conversion */
-@@ -560,7 +615,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
- */
+@@ -437,19 +456,19 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
+
+ /* BEWARE, these `goto error' on error. */
#define PRINT(ptr, len) do { \
- for (n3 = 0; n3 < (len); n3++) \
-- __xfputwc((ptr)[n3], fp); \
-+ __xfputwc((ptr)[n3], fp, loc); \
+- if (io_print(&io, (ptr), (len))) \
++ if (io_print(&io, (ptr), (len), loc)) \
+ goto error; \
} while (0)
- #define PAD(howmany, with) do { \
- if ((n = (howmany)) > 0) { \
-@@ -606,13 +661,13 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
- #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
- #define SJARG() \
- (flags&INTMAXT ? GETARG(intmax_t) : \
-- flags&SIZET ? (intmax_t)GETARG(size_t) : \
-+ flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
- flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
- (intmax_t)GETARG(long long))
+ #define PAD(howmany, with) { \
+- if (io_pad(&io, (howmany), (with))) \
++ if (io_pad(&io, (howmany), (with), loc)) \
+ goto error; \
+ }
+ #define PRINTANDPAD(p, ep, len, with) { \
+- if (io_printandpad(&io, (p), (ep), (len), (with))) \
++ if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \
+ goto error; \
+ }
+ #define FLUSH() { \
+- if (io_flush(&io)) \
++ if (io_flush(&io, loc)) \
+ goto error; \
+ }
+
+@@ -485,7 +504,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
#define UJARG() \
(flags&INTMAXT ? GETARG(uintmax_t) : \
flags&SIZET ? (uintmax_t)GETARG(size_t) : \
- flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
-+ flags&PTRDIFFT ? (uintmax_t)(unsigned)GETARG(ptrdiff_t) : \
++ flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
(uintmax_t)GETARG(unsigned long long))
/*
-@@ -640,21 +695,24 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
- val = GETARG (int); \
- }
+@@ -518,8 +537,11 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
+
--
- thousands_sep = '\0';
- grouping = NULL;
- #ifndef NO_FLOATING_POINT
-- decimal_point = localeconv()->decimal_point;
-+ decimal_point_mb = localeconv_l(loc)->decimal_point;
-+ mbtowc_l(&decimal_point, decimal_point_mb, strlen(decimal_point_mb), loc);
- #endif
- convbuf = NULL;
/* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
- if (prepwrite(fp) != 0)
+ if (prepwrite(fp) != 0) {
+ }
+ ORIENT(fp, 1);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
-- return (__sbprintf(fp, fmt0, ap));
-+ return (__sbprintf(fp, loc, fmt0, ap));
-
+ convbuf = NULL;
fmt = (wchar_t *)fmt0;
- argtable = NULL;
-@@ -678,6 +736,9 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
+@@ -529,7 +551,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
+ io_init(&io, fp);
+ ret = 0;
+ #ifndef NO_FLOATING_POINT
+- decimal_point = get_decpt();
++ decimal_point = get_decpt(loc);
+ #endif
+
+ /*
+@@ -548,6 +570,9 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
}
if (ch == '\0')
goto done;
fmt++; /* skip over '%' */
flags = 0;
-@@ -686,6 +747,9 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
- prec = -1;
+@@ -557,6 +582,9 @@ __vfwprintf(FILE *fp, const wchar_t *fmt
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
+#ifdef VECTORS
rflag: ch = *fmt++;
reswitch: switch (ch) {
-@@ -701,6 +765,11 @@ reswitch: switch (ch) {
+@@ -572,6 +600,11 @@ reswitch: switch (ch) {
case '#':
flags |= ALT;
goto rflag;
case '*':
/*-
* ``A negative field width argument is taken as a
-@@ -721,8 +790,8 @@ reswitch: switch (ch) {
- goto rflag;
- case '\'':
- flags |= GROUPING;
-- thousands_sep = *(localeconv()->thousands_sep);
-- grouping = localeconv()->grouping;
-+ thousands_sep = *(localeconv_l(loc)->thousands_sep);
-+ grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
-@@ -796,10 +865,14 @@ reswitch: switch (ch) {
+@@ -668,10 +701,14 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'c':
size = 1;
sign = '\0';
break;
-@@ -808,6 +881,10 @@ reswitch: switch (ch) {
+@@ -680,6 +717,10 @@ reswitch: switch (ch) {
/*FALLTHROUGH*/
case 'd':
case 'i':
if (flags & INTMAX_SIZE) {
ujval = SJARG();
if ((intmax_t)ujval < 0) {
-@@ -826,6 +903,12 @@ reswitch: switch (ch) {
+@@ -698,6 +739,12 @@ reswitch: switch (ch) {
#ifndef NO_FLOATING_POINT
case 'a':
case 'A':
if (ch == 'a') {
ox[1] = 'x';
xdigs = xdigs_lower;
-@@ -837,6 +920,12 @@ reswitch: switch (ch) {
+@@ -709,6 +756,12 @@ reswitch: switch (ch) {
}
if (prec >= 0)
prec++;
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult =
-@@ -848,6 +937,7 @@ reswitch: switch (ch) {
+@@ -720,6 +773,7 @@ reswitch: switch (ch) {
__hdtoa(fparg.dbl, xdigs, prec,
&expt, &signflag, &dtoaend);
}
if (prec < 0)
prec = dtoaend - dtoaresult;
if (expt == INT_MAX)
-@@ -855,11 +945,17 @@ reswitch: switch (ch) {
+@@ -727,11 +781,17 @@ reswitch: switch (ch) {
if (convbuf != NULL)
free(convbuf);
ndig = dtoaend - dtoaresult;
expchar = ch;
if (prec < 0) /* account for digit before decpt */
prec = DEFPREC + 1;
-@@ -868,10 +964,22 @@ reswitch: switch (ch) {
+@@ -740,10 +800,22 @@ reswitch: switch (ch) {
goto fp_begin;
case 'f':
case 'F':
expchar = ch - ('g' - 'e');
if (prec == 0)
prec = 1;
-@@ -880,6 +988,14 @@ fp_begin:
+@@ -752,6 +824,14 @@ fp_begin:
prec = DEFPREC;
if (convbuf != NULL)
free(convbuf);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult =
-@@ -893,8 +1009,9 @@ fp_begin:
+@@ -765,8 +845,9 @@ fp_begin:
if (expt == 9999)
expt = INT_MAX;
}
freedtoa(dtoaresult);
fp_common:
if (signflag)
-@@ -989,6 +1106,10 @@ fp_common:
+@@ -816,37 +897,46 @@ fp_common:
+ if (prec || flags & ALT)
+ size += prec + 1;
+ if ((flags & GROUPING) && expt > 0)
+- size += grouping_init(&gs, expt);
++ size += grouping_init(&gs, expt, loc);
+ }
+ break;
+ #endif /* !NO_FLOATING_POINT */
+ case 'n':
++ {
+ /*
+ * Assignment-like behavior is specified if the
+ * value overflows or is otherwise unrepresentable.
+ * C99 says to use `signed char' for %hhn conversions.
+ */
+- if (flags & LLONGINT)
+- *GETARG(long long *) = ret;
++ void *ptr = GETARG(void *);
++ if (ptr == NULL)
++ continue;
++ else if (flags & LLONGINT)
++ *(long long *)ptr = ret;
+ else if (flags & SIZET)
+- *GETARG(ssize_t *) = (ssize_t)ret;
++ *(ssize_t *)ptr = (ssize_t)ret;
+ else if (flags & PTRDIFFT)
+- *GETARG(ptrdiff_t *) = ret;
++ *(ptrdiff_t *)ptr = ret;
+ else if (flags & INTMAXT)
+- *GETARG(intmax_t *) = ret;
++ *(intmax_t *)ptr = ret;
+ else if (flags & LONGINT)
+- *GETARG(long *) = ret;
++ *(long *)ptr = ret;
+ else if (flags & SHORTINT)
+- *GETARG(short *) = ret;
++ *(short *)ptr = ret;
+ else if (flags & CHARINT)
+- *GETARG(signed char *) = ret;
++ *(signed char *)ptr = ret;
+ else
+- *GETARG(int *) = ret;
++ *(int *)ptr = ret;
+ continue; /* no output */
++ }
+ case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1003,6 +1124,10 @@ fp_common:
+@@ -861,6 +951,10 @@ fp_common:
* defined manner.''
* -- ANSI X3J11
*/
ujval = (uintmax_t)(uintptr_t)GETARG(void *);
base = 16;
xdigs = xdigs_lower;
-@@ -1024,7 +1149,7 @@ fp_common:
+@@ -882,7 +976,7 @@ fp_common:
if ((mbp = GETARG(char *)) == NULL)
cp = L"(null)";
else {
if (convbuf == NULL) {
fp->_flags |= __SERR;
goto error;
-@@ -1055,6 +1180,10 @@ fp_common:
+@@ -890,13 +984,23 @@ fp_common:
+ cp = convbuf;
+ }
+ }
++#if 0 // wcsnlen needs API review first
+ size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp);
++#else
++ size = wcslen(cp);
++ if(prec >= 0 && prec < size)
++ size = prec;
++#endif
+ sign = '\0';
+ break;
+ case 'U':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1067,6 +1196,10 @@ fp_common:
+@@ -909,6 +1013,10 @@ fp_common:
case 'x':
xdigs = xdigs_lower;
hex:
if (flags & INTMAX_SIZE)
ujval = UJARG();
else
-@@ -1092,6 +1225,7 @@ number: if ((dprec = prec) >= 0)
- * ``The result of converting a zero value with an
- * explicit precision of zero is no characters.''
+@@ -926,6 +1034,7 @@ nosign: sign = '\0';
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
* -- ANSI X3J11
+ * except for %#.0o and zero value
*/
- cp = buf + BUF;
- if (flags & INTMAX_SIZE) {
-@@ -1101,7 +1235,7 @@ number: if ((dprec = prec) >= 0)
- flags & GROUPING, thousands_sep,
- grouping);
- } else {
-- if (ulval != 0 || prec != 0)
-+ if (ulval != 0 || prec != 0 || (flags & ALT))
- cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
-@@ -1109,8 +1243,13 @@ number: if ((dprec = prec) >= 0)
+ number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+@@ -953,10 +1062,15 @@ number: if ((dprec = prec) >= 0)
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
- abort();
-+ LIBC_ABORT("size %d > BUF %d", size, BUF);
++ LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
+ if ((flags & GROUPING) && size != 0)
+- size += grouping_init(&gs, size);
++ size += grouping_init(&gs, size, loc);
break;
+#ifdef VECTORS
+ case 'v':
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
-@@ -1122,6 +1261,288 @@ number: if ((dprec = prec) >= 0)
+@@ -968,6 +1082,288 @@ number: if ((dprec = prec) >= 0)
break;
}
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
+ break; \
+ case V_PCHAR: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
+ break; \
+ case V_SHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
+ break; \
+ case V_PSHORT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
+ break; \
+ case V_INT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
+ break; \
+ case V_PINT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
+ break; \
+ case V_LONGLONG: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
+ break; \
+ case V_PLONGLONG: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
+ break; \
+ case V_FLOAT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
+ break; \
+ case V_PCHAR: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
+ break; \
+ case V_SHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
+ break; \
+ case V_PSHORT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
+ break; \
+ case V_INT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
+ break; \
+ case V_PINT: \
-+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
++ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
+ break; \
+ case V_FLOAT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
/*
* All reasonable formats wind up here. At this point, `cp'
* points to a string which (if not flags&LADJUST) should be
-@@ -1177,7 +1598,7 @@ number: if ((dprec = prec) >= 0)
- if (expt <= 0) {
- PRINT(zeroes, 1);
- if (prec || flags & ALT)
-- PRINT(decimal_point, 1);
-+ PRINT(&decimal_point, 1);
- PAD(-expt, zeroes);
- /* already handled initial 0's */
- prec += expt;
-@@ -1203,15 +1624,14 @@ number: if ((dprec = prec) >= 0)
- cp = convbuf + ndig;
- }
- if (prec || flags & ALT) {
-- buf[0] = *decimal_point;
-- PRINT(buf, 1);
-+ PRINT(&decimal_point, 1);
- }
- }
- PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
- } else { /* %[eE] or sufficiently long %[gG] */
- if (prec > 1 || flags & ALT) {
- buf[0] = *cp++;
-- buf[1] = *decimal_point;
-+ buf[1] = decimal_point;
- PRINT(buf, 2);
- PRINT(cp, ndig-1);
- PAD(prec - ndig, zeroes);
-@@ -1401,6 +1821,11 @@ reswitch: switch (ch) {
- if (flags & LONGINT)
- ADDTYPE(T_WINT);
- else
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDTYPE(T_INT);
- break;
- case 'D':
-@@ -1408,6 +1833,11 @@ reswitch: switch (ch) {
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDSARG();
- break;
- #ifndef NO_FLOATING_POINT
-@@ -1416,8 +1846,14 @@ reswitch: switch (ch) {
- case 'e':
- case 'E':
- case 'f':
-+ case 'F':
- case 'g':
- case 'G':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- if (flags & LONGDBL)
- ADDTYPE(T_LONG_DOUBLE);
- else
-@@ -1446,9 +1882,19 @@ reswitch: switch (ch) {
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDUARG();
- break;
- case 'p':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDTYPE(TP_VOID);
- break;
- case 'S':
-@@ -1466,6 +1912,11 @@ reswitch: switch (ch) {
- case 'u':
- case 'X':
- case 'x':
-+#ifdef VECTORS
-+ if (flags & VECTOR)
-+ ADDTYPE(T_VECTOR);
-+ else
-+#endif /* VECTORS */
- ADDUARG();
- break;
- default: /* "%?" prints ?, unless ? is NUL */
-@@ -1532,7 +1983,7 @@ done:
- (*argtable) [n].sizearg = va_arg (ap, size_t);
- break;
- case TP_SIZET:
-- (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
-+ (*argtable) [n].psizearg = va_arg (ap, size_t *);
- break;
- case T_INTMAXT:
- (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
-@@ -1551,6 +2002,11 @@ done:
- (*argtable) [n].longdoublearg = va_arg (ap, long double);
- break;
- #endif
-+#ifdef VECTORS
-+ case T_VECTOR:
-+ (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
-+ break;
-+#endif /* VECTORS */
- case TP_CHAR:
- (*argtable) [n].pchararg = va_arg (ap, char *);
- break;
-@@ -1585,12 +2041,12 @@ __grow_type_table (int nextarg, enum typ
- newsize = nextarg + 1;
- if (oldsize == STATIC_ARG_TBL_SIZE) {
- if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
-- abort(); /* XXX handle better */
-+ LIBC_ABORT("malloc: %s", strerror(errno)); /* XXX handle better */
- bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
- } else {
- newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
- if (newtable == NULL)
-- abort(); /* XXX handle better */
-+ LIBC_ABORT("reallocf: %s", strerror(errno)); /* XXX handle better */
- }
- for (n = oldsize; n < newsize; n++)
- newtable[n] = T_UNUSED;
+@@ -1018,7 +1414,7 @@ number: if ((dprec = prec) >= 0)
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+- if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
++ if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+@@ -1036,7 +1432,7 @@ number: if ((dprec = prec) >= 0)
+ } else {
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+- cp, convbuf + ndig);
++ cp, convbuf + ndig, loc);
+ if (n < 0)
+ goto error;
+ cp += n;
* 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.
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.12 2004/05/02 20:13:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.17 2009/01/19 06:19:51 das Exp $");
#include "namespace.h"
#include <ctype.h>
#include <inttypes.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#define CT_INT 3 /* %[dioupxX] conversion */
#define CT_FLOAT 4 /* %[efgEFG] conversion */
+#ifndef NO_FLOATING_POINT
static int parsefloat(FILE *, wchar_t *, wchar_t *);
-
-extern int __scanfdebug;
+#endif
#define INCCL(_c) \
(cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \
(wmemchr(ccls, (_c), ccle - ccls) != NULL))
+static const mbstate_t initial_mbs;
+
/*
* MT-safe version.
*/
char *mbp; /* multibyte string pointer for %c %s %[ */
size_t nconv; /* number of bytes in mb. conversion */
char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
- static const mbstate_t initial;
mbstate_t mbs;
/* `basefix' is used to avoid `if' tests in the integer scanner */
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while (width != 0 &&
(wi = __fgetwc(fp)) != WEOF) {
if (width >= MB_CUR_MAX &&
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp)) != WEOF &&
width != 0 && INCCL(wi)) {
if (width >= MB_CUR_MAX &&
} else {
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp)) != WEOF &&
width != 0 &&
!iswspace(wi)) {
float res = wcstof(buf, &p);
*va_arg(ap, float *) = res;
}
- if (__scanfdebug && p - buf != width)
- abort();
nassigned++;
}
nread += width;
static int
parsefloat(FILE *fp, wchar_t *buf, wchar_t *end)
{
+ mbstate_t mbs;
+ size_t nconv;
wchar_t *commit, *p;
int infnanpos = 0;
enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
wchar_t c;
- wchar_t decpt = (wchar_t)(unsigned char)*localeconv()->decimal_point;
+ wchar_t decpt;
_Bool gotmantdig = 0, ishex = 0;
+ mbs = initial_mbs;
+ nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+
/*
* We set commit = p whenever the string we have read so far
* constitutes a valid representation of a floating point
break;
case S_NAN:
switch (infnanpos) {
- case -1: /* XXX kludge to deal with nan(...) */
- goto parsedone;
case 0:
if (c != 'A' && c != 'a')
goto parsedone;
default:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
} else if (!iswalnum(c) && c != '_')
goto parsedone;
break;
}
infnanpos++;
break;
+ case S_DONE:
+ goto parsedone;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x') {
---- vfwscanf.c.orig 2009-02-15 03:11:22.000000000 -0800
-+++ vfwscanf.c 2009-02-16 00:10:06.000000000 -0800
-@@ -42,6 +42,8 @@ static char sccsid[] = "@(#)vfscanf.c 8.
+Index: vfwscanf.c
+===================================================================
+--- vfwscanf.c (revision 55443)
++++ vfwscanf.c (working copy)
+@@ -38,6 +38,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.12 2004/05/02 20:13:29 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.17 2009/01/19 06:19:51 das Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <ctype.h>
#include <inttypes.h>
-@@ -98,7 +100,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
- #define CT_INT 3 /* %[dioupxX] conversion */
+@@ -96,7 +98,7 @@
#define CT_FLOAT 4 /* %[efgEFG] conversion */
+ #ifndef NO_FLOATING_POINT
-static int parsefloat(FILE *, wchar_t *, wchar_t *);
-+#ifndef NO_FLOATING_POINT
+static int parsefloat(FILE *, wchar_t **, size_t, locale_t loc);
-+#endif /* !NO_FLOATING_POINT */
-
- extern int __scanfdebug;
+ #endif
-@@ -116,7 +120,21 @@ vfwscanf(FILE * __restrict fp, const wch
+ #define INCCL(_c) \
+@@ -115,16 +117,31 @@
FLOCKFILE(fp);
ORIENT(fp, 1);
- ret = __vfwscanf(fp, fmt, ap);
+ ret = __vfwscanf(fp, __current_locale(), fmt, ap);
-+ FUNLOCKFILE(fp);
-+ return (ret);
-+}
-+
+ FUNLOCKFILE(fp);
+ return (ret);
+ }
+
+int
+vfwscanf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt,
+ va_list ap)
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+ ret = __vfwscanf(fp, loc, fmt, ap);
- FUNLOCKFILE(fp);
- return (ret);
- }
-@@ -124,8 +142,9 @@ vfwscanf(FILE * __restrict fp, const wch
++ FUNLOCKFILE(fp);
++ return (ret);
++}
++
/*
* Non-MT-safe version.
*/
{
wint_t c; /* character from format, or conversion */
size_t width; /* field width, or 0 */
-@@ -134,7 +153,6 @@ __vfwscanf(FILE * __restrict fp, const w
+@@ -133,7 +150,6 @@
int flags; /* flags as defined above */
wchar_t *p0; /* saves original value of p when necessary */
int nassigned; /* number of fields assigned */
int nread; /* number of characters consumed from fp */
int base; /* base argument to conversion function */
wchar_t buf[BUF]; /* buffer for numeric conversions */
-@@ -145,31 +163,37 @@ __vfwscanf(FILE * __restrict fp, const w
+@@ -144,30 +160,36 @@
char *mbp; /* multibyte string pointer for %c %s %[ */
size_t nconv; /* number of bytes in mb. conversion */
char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
+ int index; /* for %index$ */
+ va_list ap_orig; /* to reset ap to first argument */
- static const mbstate_t initial;
mbstate_t mbs;
+ int mb_cur_max = MB_CUR_MAX_L(loc);
width = 0;
flags = 0;
/*
-@@ -179,16 +203,34 @@ __vfwscanf(FILE * __restrict fp, const w
+@@ -177,16 +199,34 @@
again: c = *fmt++;
switch (c) {
case '%':
case '*':
flags |= SUPPRESS;
goto again;
-@@ -307,7 +349,6 @@ literal:
+@@ -305,27 +345,28 @@
break;
case 'n':
- nconversions++;
- if (flags & SUPPRESS) /* ??? */
+- if (flags & SUPPRESS) /* ??? */
++ {
++ void *ptr = va_arg(ap, void *);
++ if ((ptr == NULL) || (flags & SUPPRESS)) /* ??? */
continue;
- if (flags & SHORTSHORT)
-@@ -343,11 +384,11 @@ literal:
+- if (flags & SHORTSHORT)
+- *va_arg(ap, char *) = nread;
++ else if (flags & SHORTSHORT)
++ *(char *)ptr = nread;
+ else if (flags & SHORT)
+- *va_arg(ap, short *) = nread;
++ *(short *)ptr = nread;
+ else if (flags & LONG)
+- *va_arg(ap, long *) = nread;
++ *(long *)ptr = nread;
+ else if (flags & LONGLONG)
+- *va_arg(ap, long long *) = nread;
++ *(long long *)ptr = nread;
+ else if (flags & INTMAXT)
+- *va_arg(ap, intmax_t *) = nread;
++ *(intmax_t *)ptr = nread;
+ else if (flags & SIZET)
+- *va_arg(ap, size_t *) = nread;
++ *(size_t *)ptr = nread;
+ else if (flags & PTRDIFFT)
+- *va_arg(ap, ptrdiff_t *) = nread;
++ *(ptrdiff_t *)ptr = nread;
+ else
+- *va_arg(ap, int *) = nread;
++ *(int *)ptr = nread;
+ continue;
+-
++ }
+ default:
+ goto match_failure;
+
+@@ -341,11 +382,11 @@
* that suppress this.
*/
if ((flags & NOSKIP) == 0) {
}
/*
-@@ -364,7 +405,7 @@ literal:
+@@ -362,7 +403,7 @@
p = va_arg(ap, wchar_t *);
n = 0;
while (width-- != 0 &&
if (!(flags & SUPPRESS))
*p++ = (wchar_t)wi;
n++;
-@@ -380,19 +421,19 @@ literal:
+@@ -378,19 +419,19 @@
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while (width != 0 &&
- (wi = __fgetwc(fp)) != WEOF) {
- if (width >= MB_CUR_MAX &&
break;
}
if (!(flags & SUPPRESS))
-@@ -410,7 +451,6 @@ literal:
+@@ -408,7 +449,6 @@
if (!(flags & SUPPRESS))
nassigned++;
}
break;
case CT_CCL:
-@@ -420,20 +460,20 @@ literal:
+@@ -418,20 +458,20 @@
/* take only those things in the class */
if ((flags & SUPPRESS) && (flags & LONG)) {
n = 0;
n = p - p0;
if (n == 0)
goto match_failure;
-@@ -444,16 +484,16 @@ literal:
+@@ -442,16 +482,16 @@
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
- while ((wi = __fgetwc(fp)) != WEOF &&
+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
width != 0 && INCCL(wi)) {
if (nconv == (size_t)-1)
goto input_failure;
if (nconv > width)
-@@ -468,14 +508,15 @@ literal:
+@@ -466,14 +506,15 @@
n++;
}
if (wi != WEOF)
break;
case CT_STRING:
-@@ -483,39 +524,39 @@ literal:
+@@ -481,39 +522,39 @@
if (width == 0)
width = (size_t)~0;
if ((flags & SUPPRESS) && (flags & LONG)) {
} else {
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
- mbs = initial;
+ mbs = initial_mbs;
- while ((wi = __fgetwc(fp)) != WEOF &&
+ while ((wi = __fgetwc(fp, loc)) != WEOF &&
width != 0 &&
if (nconv == (size_t)-1)
goto input_failure;
if (nconv > width)
-@@ -530,13 +571,12 @@ literal:
+@@ -528,13 +569,12 @@
nread++;
}
if (wi != WEOF)
continue;
case CT_INT:
-@@ -546,7 +586,7 @@ literal:
+@@ -544,7 +584,7 @@
width = sizeof(buf) / sizeof(*buf) - 1;
flags |= SIGNOK | NDIGITS | NZDIGITS;
for (p = buf; width; width--) {
/*
* Switch on the character; `goto ok'
* if we accept it as a part of number.
-@@ -630,7 +670,7 @@ literal:
+@@ -628,7 +668,7 @@
* for a number. Stop accumulating digits.
*/
if (c != WEOF)
break;
ok:
/*
-@@ -646,22 +686,22 @@ literal:
+@@ -644,22 +684,22 @@
*/
if (flags & NDIGITS) {
if (p > buf)
if (flags & POINTER)
*va_arg(ap, void **) =
(void *)(uintptr_t)res;
-@@ -684,47 +724,47 @@ literal:
+@@ -682,45 +722,45 @@
nassigned++;
}
nread += p - buf;
+ float res = wcstof_l(pbuf, &p, loc);
*va_arg(ap, float *) = res;
}
-- if (__scanfdebug && p - buf != width)
-- abort();
-+ if (__scanfdebug && p - pbuf != width)
-+ LIBC_ABORT("p - pbuf %ld != width %ld", (long)(p - pbuf), width);
nassigned++;
}
nread += width;
-parsefloat(FILE *fp, wchar_t *buf, wchar_t *end)
+parsefloat(FILE *fp, wchar_t **buf, size_t width, locale_t loc)
{
- wchar_t *commit, *p;
- int infnanpos = 0;
-@@ -733,9 +773,19 @@ parsefloat(FILE *fp, wchar_t *buf, wchar
- S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
- } state = S_START;
+ mbstate_t mbs;
+ size_t nconv;
+@@ -733,12 +773,22 @@
wchar_t c;
-- wchar_t decpt = (wchar_t)(unsigned char)*localeconv()->decimal_point;
-+ char *decimal_point;
-+ wchar_t decpt;
+ wchar_t decpt;
_Bool gotmantdig = 0, ishex = 0;
--
+ wchar_t *b;
+ wchar_t *e;
+ size_t s;
+
+ mbs = initial_mbs;
+- nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
+
++ nconv = mbrtowc_l(&decpt, localeconv()->decimal_point, MB_CUR_MAX_L(loc), &mbs, loc);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+- decpt = '.'; /* failsafe */
++ decpt = '.'; /* failsafe */
+
+ s = (width == 0 ? BUF : (width + 1));
+ if ((b = (wchar_t *)__parsefloat_buf(s * sizeof(wchar_t))) == NULL) {
+ *buf = NULL;
/*
* We set commit = p whenever the string we have read so far
* constitutes a valid representation of a floating point
-@@ -745,10 +795,12 @@ parsefloat(FILE *fp, wchar_t *buf, wchar
+@@ -748,10 +798,10 @@
* always necessary to read at least one character that doesn't
* match; thus, we can't short-circuit "infinity" or "nan(...)".
*/
c = WEOF;
- for (p = buf; p < end; ) {
- if ((c = __fgetwc(fp)) == WEOF)
-+ decimal_point = localeconv_l(loc)->decimal_point;
-+ mbtowc_l(&decpt, decimal_point, strlen(decimal_point), loc);
+ for (p = b; width == 0 || p < e; ) {
+ if ((c = __fgetwc(fp, loc)) == WEOF)
break;
reswitch:
switch (state) {
-@@ -808,7 +860,7 @@ reswitch:
+@@ -809,7 +859,7 @@
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
- } else if (!iswalnum(c) && c != '_')
+ } else if (!iswalnum_l(c, loc) && c != '_')
goto parsedone;
break;
}
-@@ -824,7 +876,7 @@ reswitch:
+@@ -827,7 +877,7 @@
goto reswitch;
}
case S_DIGITS:
gotmantdig = 1;
else {
state = S_FRAC;
-@@ -841,7 +893,7 @@ reswitch:
+@@ -844,7 +894,7 @@
goto parsedone;
else
state = S_EXP;
commit = p;
gotmantdig = 1;
} else
-@@ -854,13 +906,26 @@ reswitch:
+@@ -857,24 +907,38 @@
else
goto reswitch;
case S_EXPDIGITS:
default:
- abort();
+ LIBC_ABORT("unknown state %d", state);
-+ }
+ }
+ if (p >= e) {
+ ssize_t diff = (p - b);
+ ssize_t com = (commit - b);
+ e = b + (s - 1);
+ p = b + diff;
+ commit = b + com;
- }
++ }
*p++ = c;
c = WEOF;
-@@ -868,10 +933,11 @@ reswitch:
+ }
parsedone:
if (c != WEOF)
* 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.
static char sccsid[] = "@(#)vprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vprintf.c,v 1.10 2002/09/06 11:23:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vprintf.c,v 1.11 2007/01/09 00:28:08 imp Exp $");
#include <stdio.h>
---- vprintf.c.orig 2003-05-20 15:22:44.000000000 -0700
-+++ vprintf.c 2005-02-23 16:51:20.000000000 -0800
-@@ -40,11 +40,21 @@
+--- vprintf.c.bsdnew 2009-11-11 13:33:19.000000000 -0800
++++ vprintf.c 2009-11-11 13:33:19.000000000 -0800
+@@ -36,11 +36,21 @@ static char sccsid[] = "@(#)vprintf.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vprintf.c,v 1.10 2002/09/06 11:23:56 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vprintf.c,v 1.11 2007/01/09 00:28:08 imp Exp $");
+#include "xlocale_private.h"
+
* 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.
static char sccsid[] = "@(#)vscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vscanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vscanf.c,v 1.13 2007/01/09 00:28:08 imp Exp $");
#include "namespace.h"
#include <stdio.h>
---- vscanf.c.orig 2003-05-20 15:22:44.000000000 -0700
-+++ vscanf.c 2005-02-23 19:11:44.000000000 -0800
-@@ -40,6 +40,8 @@
+--- vscanf.c.bsdnew 2009-11-11 13:33:19.000000000 -0800
++++ vscanf.c 2009-11-11 13:33:19.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)vscanf.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vscanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vscanf.c,v 1.13 2007/01/09 00:28:08 imp Exp $");
+#include "xlocale_private.h"
+
#include "namespace.h"
#include <stdio.h>
#include "un-namespace.h"
-@@ -54,7 +56,22 @@
+@@ -50,7 +52,22 @@ vscanf(fmt, ap)
int retval;
FLOCKFILE(stdin);
* 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.
static char sccsid[] = "@(#)vsnprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vsnprintf.c,v 1.22 2003/07/02 07:08:44 jkh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vsnprintf.c,v 1.24 2008/04/17 22:17:54 jhb Exp $");
#include <limits.h>
#include <stdio.h>
int ret;
char dummy[2];
FILE f;
- struct __sFILEX ext;
on = n;
if (n != 0)
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfprintf(&f, fmt, ap);
if (on > 0)
*f._p = '\0';
---- vsnprintf.c.orig 2003-07-24 12:42:14.000000000 -0700
-+++ vsnprintf.c 2005-02-23 16:54:44.000000000 -0800
-@@ -40,6 +40,8 @@
+--- vsnprintf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ vsnprintf.c 2009-12-03 15:20:43.000000000 -0800
+@@ -36,19 +36,25 @@ static char sccsid[] = "@(#)vsnprintf.c
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vsnprintf.c,v 1.22 2003/07/02 07:08:44 jkh Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vsnprintf.c,v 1.24 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <stdio.h>
#include "local.h"
-@@ -72,7 +74,42 @@
- f._bf._size = f._w = n;
- f._extra = &ext;
- INITEXTRA(&f);
-- ret = __vfprintf(&f, fmt, ap);
-+ ret = __vfprintf(&f, __current_locale(), fmt, ap);
-+ if (on > 0)
-+ *f._p = '\0';
-+ return (ret);
-+}
-+
-+int
-+vsnprintf_l(char * __restrict str, size_t n, locale_t loc,
-+ const char * __restrict fmt, __va_list ap)
-+{
-+ size_t on;
-+ int ret;
-+ char dummy[2];
-+ FILE f;
+
+ int
+-vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt,
++vsnprintf_l(char * __restrict str, size_t n, locale_t loc, const char * __restrict fmt,
+ __va_list ap)
+ {
+ size_t on;
+ int ret;
+ char dummy[2];
+ FILE f;
+ struct __sFILEX ext;
-+
-+ NORMALIZE_LOCALE(loc);
-+ on = n;
-+ if (n != 0)
-+ n--;
-+ if (n > INT_MAX)
-+ n = INT_MAX;
-+ /* Stdio internals do not deal correctly with zero length buffer */
-+ if (n == 0) {
-+ if (on > 0)
-+ *str = '\0';
-+ str = dummy;
-+ n = 1;
-+ }
-+ f._file = -1;
-+ f._flags = __SWR | __SSTR;
-+ f._bf._base = f._p = (unsigned char *)str;
-+ f._bf._size = f._w = n;
+ f._extra = &ext;
+ INITEXTRA(&f);
+
++ NORMALIZE_LOCALE(loc);
+ on = n;
+ if (n != 0)
+ n--;
+@@ -67,8 +73,15 @@ vsnprintf(char * __restrict str, size_t
+ f._bf._size = f._w = n;
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
+- ret = __vfprintf(&f, fmt, ap);
+ ret = __vfprintf(&f, loc, fmt, ap);
if (on > 0)
*f._p = '\0';
return (ret);
+ }
++
++int
++vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt,
++ __va_list ap)
++{
++ return vsnprintf_l(str, n, __current_locale(), fmt, ap);
++}
* 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.
static char sccsid[] = "@(#)vsprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vsprintf.c,v 1.14 2002/09/06 11:23:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vsprintf.c,v 1.16 2008/04/17 22:17:54 jhb Exp $");
#include <stdio.h>
#include <limits.h>
{
int ret;
FILE f;
- struct __sFILEX ext;
f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfprintf(&f, fmt, ap);
*f._p = 0;
return (ret);
---- vsprintf.c.orig 2003-05-20 15:22:44.000000000 -0700
-+++ vsprintf.c 2005-02-23 16:56:03.000000000 -0800
-@@ -40,6 +40,8 @@
+--- vsprintf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ vsprintf.c 2009-12-03 15:20:55.000000000 -0800
+@@ -36,23 +36,35 @@ static char sccsid[] = "@(#)vsprintf.c 8
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vsprintf.c,v 1.14 2002/09/06 11:23:56 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vsprintf.c,v 1.16 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
#include <limits.h>
#include "local.h"
-@@ -57,7 +59,27 @@
- f._bf._size = f._w = INT_MAX;
- f._extra = &ext;
- INITEXTRA(&f);
-- ret = __vfprintf(&f, fmt, ap);
-+ ret = __vfprintf(&f, __current_locale(), fmt, ap);
-+ *f._p = 0;
-+ return (ret);
-+}
-+
-+int
-+vsprintf_l(char * __restrict str, locale_t loc, const char * __restrict fmt,
-+ __va_list ap)
-+{
-+ int ret;
-+ FILE f;
+
+ int
+-vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap)
++vsprintf_l(char * __restrict str, locale_t loc, const char * __restrict fmt, __va_list ap)
+ {
+ int ret;
+ FILE f;
+ struct __sFILEX ext;
-+
-+ NORMALIZE_LOCALE(loc);
-+ f._file = -1;
-+ f._flags = __SWR | __SSTR;
-+ f._bf._base = f._p = (unsigned char *)str;
-+ f._bf._size = f._w = INT_MAX;
+ f._extra = &ext;
+ INITEXTRA(&f);
+
++ NORMALIZE_LOCALE(loc);
+ f._file = -1;
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = INT_MAX;
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
+- ret = __vfprintf(&f, fmt, ap);
+ ret = __vfprintf(&f, loc, fmt, ap);
*f._p = 0;
return (ret);
}
++
++int
++vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap)
++{
++ return vsprintf_l(str, __current_locale(), fmt, ap);
++}
* 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.
static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.12 2002/10/12 16:13:41 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.14 2008/04/17 22:17:54 jhb Exp $");
#include <stdio.h>
#include <string.h>
__va_list ap;
{
FILE f;
- struct __sFILEX ext;
f._file = -1;
f._flags = __SRD;
f._read = eofread;
f._ub._base = NULL;
f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
return (__svfscanf(&f, fmt, ap));
}
---- vsscanf.c.orig 2003-05-20 15:22:44.000000000 -0700
-+++ vsscanf.c 2005-02-23 16:57:18.000000000 -0800
-@@ -40,6 +40,8 @@
+--- vsscanf.c.orig 2011-03-01 17:54:44.000000000 -0800
++++ vsscanf.c 2011-03-01 18:03:46.000000000 -0800
+@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)vsscanf.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.12 2002/10/12 16:13:41 mike Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.14 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <stdio.h>
#include <string.h>
#include "local.h"
-@@ -76,5 +78,28 @@
+@@ -55,12 +57,16 @@ eofread(cookie, buf, len)
+ }
+
+ int
+-vsscanf(str, fmt, ap)
++vsscanf_l(str, loc, fmt, ap)
+ const char * __restrict str;
++ locale_t loc;
+ const char * __restrict fmt;
+ __va_list ap;
+ {
+ FILE f;
++ struct __sFILEX ext;
++ f._extra = &ext;
++ INITEXTRA(&f);
+
+ f._file = -1;
+ f._flags = __SRD;
+@@ -71,5 +77,15 @@ vsscanf(str, fmt, ap)
f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
- return (__svfscanf(&f, fmt, ap));
-+ return (__svfscanf_l(&f, __current_locale(), fmt, ap));
-+}
++ return (__svfscanf_l(&f, loc, fmt, ap));
+ }
+
+int
-+vsscanf_l(str, loc, fmt, ap)
++vsscanf(str, fmt, ap)
+ const char * __restrict str;
-+ locale_t loc;
+ const char * __restrict fmt;
+ __va_list ap;
+{
-+ FILE f;
-+ struct __sFILEX ext;
++ return vsscanf_l(str, __current_locale(), fmt, ap);
++}
+
-+ NORMALIZE_LOCALE(loc);
-+ f._file = -1;
-+ f._flags = __SRD;
-+ f._bf._base = f._p = (unsigned char *)str;
-+ f._bf._size = f._r = strlen(str);
-+ f._read = eofread;
-+ f._ub._base = NULL;
-+ f._lb._base = NULL;
-+ f._extra = &ext;
-+ INITEXTRA(&f);
-+ return (__svfscanf_l(&f, loc, fmt, ap));
- }
#if 0
__FBSDID("FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.16 2002/08/21 16:19:57 mike Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.5 2004/04/07 09:55:05 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.7 2008/04/17 22:17:54 jhb Exp $");
#include <errno.h>
#include <stdio.h>
static const mbstate_t initial;
mbstate_t mbs;
FILE f;
- struct __sFILEX ext;
char *mbp;
int ret, sverrno;
+ size_t nwc;
if (n == 0) {
errno = EINVAL;
return (-1);
}
f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfwprintf(&f, fmt, ap);
if (ret < 0) {
sverrno = errno;
* fputwc() did in __vfwprintf().
*/
mbs = initial;
- if (mbsrtowcs(s, (const char **)&mbp, n, &mbs) == (size_t)-1) {
- free(f._bf._base);
+ nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs);
+ free(f._bf._base);
+ if (nwc == (size_t)-1) {
errno = EILSEQ;
return (-1);
}
- free(f._bf._base);
- if (s[n - 1] != L'\0') {
+ if (nwc == n) {
s[n - 1] = L'\0';
errno = EOVERFLOW;
return (-1);
---- vswprintf.c.orig 2004-11-25 11:38:36.000000000 -0800
-+++ vswprintf.c 2005-02-24 15:20:20.000000000 -0800
-@@ -33,6 +33,8 @@
+--- vswprintf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ vswprintf.c 2009-12-03 15:21:59.000000000 -0800
+@@ -33,6 +33,8 @@ __FBSDID("FreeBSD: src/lib/libc/stdio/va
#endif
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.5 2004/04/07 09:55:05 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.7 2008/04/17 22:17:54 jhb Exp $");
+#include "xlocale_private.h"
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-@@ -49,7 +51,66 @@
- struct __sFILEX ext;
+@@ -40,8 +42,8 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
+ #include "local.h"
+
+ int
+-vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt,
+- __va_list ap)
++vswprintf_l(wchar_t * __restrict s, size_t n, locale_t loc,
++ const wchar_t * __restrict fmt, __va_list ap)
+ {
+ static const mbstate_t initial;
+ mbstate_t mbs;
+@@ -49,7 +51,11 @@ vswprintf(wchar_t * __restrict s, size_t
char *mbp;
int ret, sverrno;
-+ size_t conv;
-+ locale_t loc = __current_locale();
-+
-+ if (n == 0) {
-+ errno = EINVAL;
-+ return (-1);
-+ }
-+
-+ f._file = -1;
-+ f._flags = __SWR | __SSTR | __SALC;
-+ f._bf._base = f._p = (unsigned char *)malloc(128);
-+ if (f._bf._base == NULL) {
-+ errno = ENOMEM;
-+ return (-1);
-+ }
-+ f._bf._size = f._w = 127; /* Leave room for the NUL */
+ size_t nwc;
++ struct __sFILEX ext;
+ f._extra = &ext;
+ INITEXTRA(&f);
-+ ret = __vfwprintf(&f, loc, fmt, ap);
-+ if (ret < 0) {
-+ sverrno = errno;
-+ free(f._bf._base);
-+ errno = sverrno;
-+ return (-1);
-+ }
-+ *f._p = '\0';
-+ mbp = (char *)f._bf._base;
-+ /*
-+ * XXX Undo the conversion from wide characters to multibyte that
-+ * fputwc() did in __vfwprintf().
-+ */
-+ mbs = initial;
-+ if ((conv = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc)) == (size_t)-1) {
-+ free(f._bf._base);
-+ errno = EILSEQ;
-+ return (-1);
-+ }
-+ free(f._bf._base);
-+ if (conv >= n) {
-+ s[n - 1] = L'\0';
-+ errno = EOVERFLOW;
-+ return (-1);
-+ }
-+
-+ return (ret);
-+}
-+
-+int
-+vswprintf_l(wchar_t * __restrict s, size_t n, locale_t loc,
-+ const wchar_t * __restrict fmt, __va_list ap)
-+{
-+ static const mbstate_t initial;
-+ mbstate_t mbs;
-+ FILE f;
-+ struct __sFILEX ext;
-+ char *mbp;
-+ int ret, sverrno;
-+ size_t conv;
+ NORMALIZE_LOCALE(loc);
if (n == 0) {
errno = EINVAL;
return (-1);
-@@ -65,7 +126,7 @@
+@@ -65,7 +71,7 @@ vswprintf(wchar_t * __restrict s, size_t
f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
- ret = __vfwprintf(&f, fmt, ap);
+ ret = __vfwprintf(&f, loc, fmt, ap);
if (ret < 0) {
sverrno = errno;
free(f._bf._base);
-@@ -73,19 +134,19 @@
- return (-1);
- }
- *f._p = '\0';
-- mbp = f._bf._base;
-+ mbp = (char *)f._bf._base;
- /*
- * XXX Undo the conversion from wide characters to multibyte that
+@@ -79,7 +85,7 @@ vswprintf(wchar_t * __restrict s, size_t
* fputwc() did in __vfwprintf().
*/
mbs = initial;
-- if (mbsrtowcs(s, (const char **)&mbp, n, &mbs) == (size_t)-1) {
-+ if ((conv = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc)) == (size_t)-1) {
- free(f._bf._base);
- errno = EILSEQ;
- return (-1);
- }
+- nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs);
++ nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc);
free(f._bf._base);
-- if (s[n - 1] != L'\0') {
-+ if (conv >= n) {
- s[n - 1] = L'\0';
- errno = EOVERFLOW;
- return (-1);
+ if (nwc == (size_t)-1) {
+ errno = EILSEQ;
+@@ -93,3 +99,10 @@ vswprintf(wchar_t * __restrict s, size_t
+
+ return (ret);
+ }
++
++int
++vswprintf(wchar_t * __restrict s, size_t n,
++ const wchar_t * __restrict fmt, __va_list ap)
++{
++ return vswprintf_l(s, n, __current_locale(), fmt, ap);
++}
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.11 2002/08/21 16:19:57 mike Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vswscanf.c,v 1.3 2004/04/07 09:55:05 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vswscanf.c,v 1.6 2009/01/15 18:53:52 rdivacky Exp $");
#include <limits.h>
#include <stdarg.h>
static const mbstate_t initial;
mbstate_t mbs;
FILE f;
- struct __sFILEX ext;
char *mbstr;
size_t mlen;
int r;
+ const wchar_t *strp;
/*
* XXX Convert the wide character string to multibyte, which
if ((mbstr = malloc(wcslen(str) * MB_CUR_MAX + 1)) == NULL)
return (EOF);
mbs = initial;
- if ((mlen = wcsrtombs(mbstr, &str, SIZE_T_MAX, &mbs)) == (size_t)-1) {
+ strp = str;
+ if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) {
free(mbstr);
return (EOF);
}
f._read = eofread;
f._ub._base = NULL;
f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
r = __vfwscanf(&f, fmt, ap);
free(mbstr);
---- vswscanf.c.orig 2004-11-25 11:38:36.000000000 -0800
-+++ vswscanf.c 2005-02-23 17:03:30.000000000 -0800
-@@ -43,6 +43,8 @@
+--- vswscanf.c.orig 2009-11-30 16:15:30.000000000 -0800
++++ vswscanf.c 2009-12-03 15:21:47.000000000 -0800
+@@ -39,6 +39,8 @@ __FBSDID("FreeBSD: src/lib/libc/stdio/vs
#endif
- __FBSDID("$FreeBSD: src/lib/libc/stdio/vswscanf.c,v 1.3 2004/04/07 09:55:05 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/vswscanf.c,v 1.6 2009/01/15 18:53:52 rdivacky Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
-@@ -71,15 +73,55 @@
- char *mbstr;
+@@ -57,7 +59,7 @@ eofread(void *cookie, char *buf, int len
+ }
+
+ int
+-vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
++vswscanf_l(const wchar_t * __restrict str, locale_t loc, const wchar_t * __restrict fmt,
+ va_list ap)
+ {
+ static const mbstate_t initial;
+@@ -67,16 +69,20 @@ vswscanf(const wchar_t * __restrict str,
size_t mlen;
int r;
-+ locale_t loc = __current_locale();
-+
-+ /*
-+ * XXX Convert the wide character string to multibyte, which
-+ * __vfwscanf() will convert back to wide characters.
-+ */
-+ if ((mbstr = malloc(wcslen(str) * MB_CUR_MAX_L(loc) + 1)) == NULL)
-+ return (EOF);
-+ mbs = initial;
-+ if ((mlen = wcsrtombs_l(mbstr, &str, SIZE_T_MAX, &mbs, loc)) == (size_t)-1) {
-+ free(mbstr);
-+ return (EOF);
-+ }
-+ f._file = -1;
-+ f._flags = __SRD;
-+ f._bf._base = f._p = (unsigned char *)mbstr;
-+ f._bf._size = f._r = mlen;
-+ f._read = eofread;
-+ f._ub._base = NULL;
-+ f._lb._base = NULL;
+ const wchar_t *strp;
++ struct __sFILEX ext;
+ f._extra = &ext;
+ INITEXTRA(&f);
-+ r = __vfwscanf(&f, loc, fmt, ap);
-+ free(mbstr);
-+
-+ return (r);
-+}
-+
-+int
-+vswscanf_l(const wchar_t * __restrict str, locale_t loc,
-+ const wchar_t * __restrict fmt, va_list ap)
-+{
-+ static const mbstate_t initial;
-+ mbstate_t mbs;
-+ FILE f;
-+ struct __sFILEX ext;
-+ char *mbstr;
-+ size_t mlen;
-+ int r;
+ NORMALIZE_LOCALE(loc);
/*
+ if ((mbstr = malloc(wcslen(str) * MB_CUR_MAX_L(loc) + 1)) == NULL)
return (EOF);
mbs = initial;
-- if ((mlen = wcsrtombs(mbstr, &str, SIZE_T_MAX, &mbs)) == (size_t)-1) {
-+ if ((mlen = wcsrtombs_l(mbstr, &str, SIZE_T_MAX, &mbs, loc)) == (size_t)-1) {
+ strp = str;
+- if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) {
++ if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, loc)) == (size_t)-1) {
free(mbstr);
return (EOF);
}
-@@ -92,7 +134,7 @@
+@@ -89,8 +95,16 @@ vswscanf(const wchar_t * __restrict str,
f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
- r = __vfwscanf(&f, fmt, ap);
+ r = __vfwscanf(&f, loc, fmt, ap);
free(mbstr);
return (r);
+ }
++
++int
++vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
++ va_list ap)
++{
++ return vswscanf_l(str, __current_locale(), fmt, ap);
++}
++
* 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.
static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/wbuf.c,v 1.11 2004/06/08 05:45:32 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/wbuf.c,v 1.12 2007/01/09 00:28:08 imp Exp $");
#include <stdio.h>
#include "local.h"
---- wbuf.c.orig 2004-06-07 22:45:32.000000000 -0700
-+++ wbuf.c 2004-10-25 00:49:10.000000000 -0700
-@@ -41,6 +41,7 @@
- __FBSDID("$FreeBSD: src/lib/libc/stdio/wbuf.c,v 1.11 2004/06/08 05:45:32 das Exp $");
+--- wbuf.c.bsdnew 2009-11-11 13:33:20.000000000 -0800
++++ wbuf.c 2009-11-11 13:33:22.000000000 -0800
+@@ -37,6 +37,7 @@ static char sccsid[] = "@(#)wbuf.c 8.1 (
+ __FBSDID("$FreeBSD: src/lib/libc/stdio/wbuf.c,v 1.12 2007/01/09 00:28:08 imp Exp $");
#include <stdio.h>
+#include <errno.h>
#include "local.h"
/*
-@@ -65,8 +66,10 @@
+@@ -61,8 +62,10 @@ __swbuf(c, fp)
* calls might wrap _w from negative to positive.
*/
fp->_w = fp->_lbfsize;
.\" 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.
.\"
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/stdio/printf.3,v 1.47 2002/09/06 11:23:55 tjr Exp
-.\" $FreeBSD: src/lib/libc/stdio/wprintf.3,v 1.5 2003/07/05 07:55:34 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/wprintf.3,v 1.6 2007/01/09 00:28:08 imp Exp $
.\"
.Dd July 5, 2003
.Dt WPRINTF 3
---- wprintf.3.orig 2007-04-08 18:49:37.000000000 -0700
-+++ wprintf.3 2007-04-08 20:12:12.000000000 -0700
-@@ -41,8 +41,12 @@
+--- wprintf.3.bsdnew 2009-11-11 13:33:22.000000000 -0800
++++ wprintf.3 2009-11-11 13:33:22.000000000 -0800
+@@ -37,8 +37,12 @@
.Dt WPRINTF 3
.Os
.Sh NAME
.Nd formatted wide character output conversion
.Sh LIBRARY
.Lb libc
-@@ -50,23 +54,49 @@
+@@ -46,23 +50,49 @@
.In stdio.h
.In wchar.h
.Ft int
as described below.
The
.Fn wprintf
-@@ -87,6 +117,12 @@
+@@ -83,6 +113,12 @@ and
write to the wide character string
.Fa ws .
.Pp
These functions write the output under the control of a
.Fa format
string that specifies how subsequent arguments
-@@ -96,7 +132,7 @@
+@@ -92,7 +128,7 @@ are converted for output.
.Pp
These functions return the number of characters printed
(not including the trailing
used to end output to strings).
.Pp
The
-@@ -602,6 +638,7 @@
+@@ -598,6 +634,7 @@ Refer to
.Xr putwc 3 ,
.Xr setlocale 3 ,
.Xr wcsrtombs 3 ,
.Xr wscanf 3
.Sh STANDARDS
Subject to the caveats noted in the
-@@ -614,7 +651,7 @@
+@@ -610,7 +647,7 @@ the
.Fn fwprintf ,
.Fn swprintf ,
.Fn vwprintf ,
.\" 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.
.\"
.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
.\" FreeBSD: src/lib/libc/stdio/scanf.3,v 1.24 2003/06/28 09:03:25 das Exp
-.\" $FreeBSD: src/lib/libc/stdio/wscanf.3,v 1.6 2003/07/05 07:47:55 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/wscanf.3,v 1.7 2007/01/09 00:28:08 imp Exp $
.\"
.Dd July 5, 2003
.Dt WSCANF 3
---- wscanf.3.orig 2007-04-08 18:49:37.000000000 -0700
-+++ wscanf.3 2007-04-08 20:05:10.000000000 -0700
-@@ -41,12 +41,12 @@
+--- wscanf.3.bsdnew 2009-11-11 13:33:22.000000000 -0800
++++ wscanf.3 2009-11-11 13:33:22.000000000 -0800
+@@ -37,12 +37,12 @@
.Dt WSCANF 3
.Os
.Sh NAME
.Nd wide character input format conversion
.Sh LIBRARY
.Lb libc
-@@ -54,22 +54,46 @@
+@@ -50,22 +50,46 @@
.In stdio.h
.In wchar.h
.Ft int
.Fa format
as described below.
This format may contain
-@@ -89,7 +113,8 @@
+@@ -85,7 +109,8 @@ reads input from the stream pointer
and
.Fn swscanf
reads its input from the wide character string pointed to by
The
.Fn vfwscanf
function
-@@ -121,6 +146,7 @@
+@@ -117,6 +142,7 @@ conversion below).
All conversions are introduced by the
.Cm %
(percent sign) character.
The
.Fa format
string
-@@ -134,10 +160,16 @@
+@@ -130,10 +156,16 @@ Scanning stops
when an input character does not match such a format character.
Scanning also stops
when an input conversion cannot be made (see below).
there may be a number of
.Em flag
characters, as follows:
-@@ -433,15 +465,12 @@
+@@ -429,15 +461,12 @@ of
causes an immediate return of
.Dv EOF .
.Sh RETURN VALUES
such as an alphabetic character for a
.Ql %d
conversion.
-@@ -459,14 +488,15 @@
+@@ -455,14 +484,15 @@ the number of conversions which were suc
.Xr wcstod 3 ,
.Xr wcstol 3 ,
.Xr wcstoul 3 ,
* 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.
static char sccsid[] = "@(#)wsetup.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/wsetup.c,v 1.9 2004/06/08 05:44:52 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/wsetup.c,v 1.11 2009/01/08 06:38:06 das Exp $");
#include <errno.h>
#include <stdio.h>
if ((fp->_flags & __SWR) == 0) {
if ((fp->_flags & __SRW) == 0) {
errno = EBADF;
+ fp->_flags |= __SERR;
return (EOF);
}
if (fp->_flags & __SRD) {
CWD := ${.CURDIR}/stdio
.include "Makefile.fbsd_begin"
-FBSDMISRCS= _flock_stub.c asprintf.c clrerr.c fclose.c fdopen.c feof.c ferror.c \
- fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetwc.c fgetws.c \
+FBSDMISRCS= _flock_stub.c asprintf.c clrerr.c dprintf.c fclose.c fdopen.c feof.c ferror.c \
+ fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetwc.c fgetwln.c fgetws.c \
fileno.c findfp.c flags.c fopen.c fprintf.c fpurge.c fputc.c fputs.c \
fputwc.c fputws.c fread.c freopen.c fscanf.c fseek.c fsetpos.c \
ftell.c funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwscanf.c \
- fwrite.c getc.c getchar.c gets.c getw.c getwc.c getwchar.c makebuf.c \
- mktemp.c perror.c printf.c putc.c putchar.c puts.c putw.c putwc.c \
+ fwrite.c getc.c getchar.c getdelim.c getline.c gets.c getw.c getwc.c getwchar.c makebuf.c \
+ mktemp.c perror.c printf.c printf-pos.c putc.c putchar.c puts.c putw.c putwc.c \
putwchar.c refill.c remove.c rewind.c rget.c scanf.c setbuf.c \
setbuffer.c setvbuf.c snprintf.c sprintf.c sscanf.c stdio.c \
swprintf.c swscanf.c tempnam.c tmpfile.c tmpnam.c ungetc.c ungetwc.c \
- unlocked.c vasprintf.c vfprintf.c vfscanf.c vfwprintf.c vfwscanf.c \
+ vasprintf.c vdprintf.c vfprintf.c vfscanf.c vfwprintf.c vfwscanf.c \
vprintf.c vscanf.c vsnprintf.c vsprintf.c vsscanf.c vswprintf.c \
vswscanf.c vwprintf.c vwscanf.c wbuf.c wprintf.c wscanf.c wsetup.c
-FBSDHDRS= floatio.h fvwrite.h glue.h local.h
+FBSDHDRS= floatio.h fvwrite.h glue.h local.h printfcommon.h printflocal.h
.include "Makefile.fbsd_end"
# also build 64-bit long double versions (ppc only)
-LDBLSRCS += asprintf.c fprintf.c fscanf.c fwprintf.c fwscanf.c printf.c \
+LDBLSRCS += asprintf.c dprintf.c fprintf.c fscanf.c fwprintf.c fwscanf.c printf.c \
scanf.c snprintf.c sprintf.c sscanf.c swprintf.c swscanf.c \
- vasprintf.c vfprintf.c vfscanf.c vfwprintf.c vfwscanf.c \
+ vasprintf.c vdprintf.c vfprintf.c vfscanf.c vfwprintf.c vfwscanf.c \
vprintf.c vscanf.c vsnprintf.c vsprintf.c vsscanf.c vswprintf.c \
vswscanf.c vwprintf.c vwscanf.c wprintf.c wscanf.c
-.for _src in vfprintf-fbsd.c vfwprintf-fbsd.c
-CFLAGS-${_src} += -fshort-enums -DVECTORS
-.endfor
-
LEGACYSRCS+= fdopen.c fopen.c fputs.c freopen.c fwrite.c tempnam.c
DARWINEXTSNSRCS+= fdopen.c fopen.c
MAN3+= getwc_l.3 putwc_l.3 printf_l.3 scanf_l.3 wprintf_l.3 wscanf_l.3
.include "Makefile.fbsd_begin"
-FBSDMAN3= fclose.3 ferror.3 fflush.3 fgetln.3 fgets.3 fgetws.3 flockfile.3 \
+FBSDMAN3= fclose.3 ferror.3 fflush.3 fgetln.3 fgets.3 fgetwln.3 fgetws.3 flockfile.3 \
fopen.3 fputs.3 fputws.3 fread.3 fseek.3 funopen.3 fwide.3 getc.3 \
- getwc.3 mktemp.3 printf.3 putc.3 putwc.3 remove.3 scanf.3 setbuf.3 \
+ getline.3 getwc.3 mktemp.3 printf.3 putc.3 putwc.3 remove.3 scanf.3 setbuf.3 \
stdio.3 tmpnam.3 ungetc.3 ungetwc.3 wprintf.3 wscanf.3
.include "Makefile.fbsd_end"
MLINKS+= fgets.3 gets.3
+MLINKS+= fgetwln.3 fgetwln_l.3
+
MLINKS+= fgetws.3 fgetws_l.3
MLINKS+= flockfile.3 ftrylockfile.3 \
MLINKS+= funopen.3 fropen.3 \
funopen.3 fwopen.3
+MLINKS+= getline.3 getdelim.3
+
MLINKS+= getc.3 fgetc.3 \
getc.3 getc_unlocked.3 \
getc.3 getchar.3 \
mktemp.3 mkstemps.3
MLINKS+= printf.3 asprintf.3 \
+ printf.3 dprintf.3 \
printf.3 fprintf.3 \
printf.3 snprintf.3 \
printf.3 sprintf.3 \
printf.3 vasprintf.3 \
+ printf.3 vdprintf.3 \
printf.3 vfprintf.3 \
printf.3 vprintf.3 \
printf.3 vsnprintf.3 \
-/* $OpenBSD: asprintf.c,v 1.8 2002/02/19 19:39:36 millert Exp $ */
-
-/*
- * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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.
+ * 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 ``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.
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/asprintf.c,v 1.13 2002/09/26 13:09:48 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/asprintf.c,v 1.15 2009/03/02 04:11:42 das Exp $");
#include "xlocale_private.h"
#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
#include <stdarg.h>
-#include "local.h"
-
int
-asprintf(char **str, char const *fmt, ...)
+asprintf(char ** __restrict s, char const * __restrict fmt, ...)
{
int ret;
va_list ap;
- FILE f;
- struct __sFILEX ext;
- f._file = -1;
- f._flags = __SWR | __SSTR | __SALC;
- f._bf._base = f._p = (unsigned char *)malloc(128);
- if (f._bf._base == NULL) {
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
va_start(ap, fmt);
- ret = __vfprintf(&f, __current_locale(), fmt, ap); /* Use unlocked __vfprintf */
+ ret = vasprintf_l(s, __current_locale(), fmt, ap);
va_end(ap);
- if (ret < 0) {
- free(f._bf._base);
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- *f._p = '\0';
- *str = (char *)f._bf._base;
return (ret);
}
int
-asprintf_l(char **str, locale_t loc, char const *fmt, ...)
+asprintf_l(char ** __restrict s, locale_t loc, char const * __restrict fmt, ...)
{
int ret;
va_list ap;
- FILE f;
- struct __sFILEX ext;
- NORMALIZE_LOCALE(loc);
- f._file = -1;
- f._flags = __SWR | __SSTR | __SALC;
- f._bf._base = f._p = (unsigned char *)malloc(128);
- if (f._bf._base == NULL) {
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
va_start(ap, fmt);
- ret = __vfprintf(&f, loc, fmt, ap); /* Use unlocked __vfprintf */
+ ret = vasprintf_l(s, loc, fmt, ap);
va_end(ap);
- if (ret < 0) {
- free(f._bf._base);
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- *f._p = '\0';
- *str = (char *)f._bf._base;
return (ret);
}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/dprintf.c,v 1.1 2009/03/04 03:38:51 das Exp $");
+
+#include "xlocale_private.h"
+
+#include "namespace.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include "un-namespace.h"
+
+int
+dprintf(int fd, const char * __restrict fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vdprintf_l(fd, __current_locale(), fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+
+int
+dprintf_l(int fd, locale_t loc, const char * __restrict fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vdprintf_l(fd, loc, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
* 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.
static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fclose.c,v 1.11 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fclose.c,v 1.12 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <errno.h>
* 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.
static char sccsid[] = "@(#)fdopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fdopen.c,v 1.7 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fdopen.c,v 1.11 2008/05/10 18:39:20 antoine Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <limits.h>
#include "un-namespace.h"
#include "local.h"
const char *mode;
{
FILE *fp;
- static int nofile;
int flags, oflags, fdflags, tmp;
- if (nofile == 0)
- nofile = getdtablesize();
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+ return (NULL);
+ }
if ((flags = __sflags(mode, &oflags)) == 0)
return (NULL);
* 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.
static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fflush.c,v 1.13 2004/07/04 20:17:00 cperciva Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fflush.c,v 1.14 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <errno.h>
+++ /dev/null
-./fgetln.c
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetln.c,v 1.11 2007/01/09 00:28:06 imp Exp $");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+/*
+ * Expand the line buffer. Return -1 on error.
+#ifdef notdef
+ * The `new size' does not account for a terminating '\0',
+ * so we add 1 here.
+#endif
+ */
+int
+__slbexpand(FILE *fp, size_t newsize)
+{
+ void *p;
+
+#ifdef notdef
+ ++newsize;
+#endif
+ if (fp->_lb._size >= newsize)
+ return (0);
+ if (newsize > INT_MAX) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+ return (-1);
+ fp->_lb._base = p;
+ fp->_lb._size = newsize;
+ return (0);
+}
+
+/*
+ * Get an input line. The returned pointer often (but not always)
+ * points into a stdio buffer. Fgetln does not alter the text of
+ * the returned line (which is thus not a C string because it will
+ * not necessarily end with '\0'), but does allow callers to modify
+ * it if they wish. Thus, we set __SMOD in case the caller does.
+ */
+char *
+fgetln(FILE *fp, size_t *lenp)
+{
+ unsigned char *p;
+ size_t len;
+ size_t off;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+ /* make sure there is input */
+ if (fp->_r <= 0 && __srefill(fp)) {
+ *lenp = 0;
+ FUNLOCKFILE(fp);
+ return (NULL);
+ }
+
+ /* look for a newline in the input */
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
+ char *ret;
+
+ /*
+ * Found one. Flag buffer as modified to keep fseek from
+ * `optimising' a backward seek, in case the user stomps on
+ * the text.
+ */
+ p++; /* advance over it */
+ ret = (char *)fp->_p;
+ *lenp = len = p - fp->_p;
+ fp->_flags |= __SMOD;
+ fp->_r -= len;
+ fp->_p = p;
+ FUNLOCKFILE(fp);
+ return (ret);
+ }
+
+ /*
+ * We have to copy the current buffered data to the line buffer.
+ * As a bonus, though, we can leave off the __SMOD.
+ *
+ * OPTIMISTIC is length that we (optimistically) expect will
+ * accomodate the `rest' of the string, on each trip through the
+ * loop below.
+ */
+#define OPTIMISTIC 80
+
+ for (len = fp->_r, off = 0;; len += fp->_r) {
+ size_t diff;
+
+ /*
+ * Make sure there is room for more bytes. Copy data from
+ * file buffer to line buffer, refill file and look for
+ * newline. The loop stops only when we find a newline.
+ */
+ if (__slbexpand(fp, len + OPTIMISTIC))
+ goto error;
+ (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+ len - off);
+ off = len;
+ if (__srefill(fp))
+ break; /* EOF or error: return partial line */
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
+ continue;
+
+ /* got it: finish up the line (like code above) */
+ p++;
+ diff = p - fp->_p;
+ len += diff;
+ if (__slbexpand(fp, len))
+ goto error;
+ (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+ diff);
+ fp->_r -= diff;
+ fp->_p = p;
+ break;
+ }
+ *lenp = len;
+#ifdef notdef
+ fp->_lb._base[len] = 0;
+#endif
+ FUNLOCKFILE(fp);
+ return ((char *)fp->_lb._base);
+
+error:
+ *lenp = 0; /* ??? */
+ fp->_flags |= __SERR;
+ FUNLOCKFILE(fp);
+ return (NULL); /* ??? */
+}
+++ /dev/null
-./fgetln.3
\ No newline at end of file
--- /dev/null
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 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.
+.\"
+.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD: src/lib/libc/stdio/fgetln.3,v 1.10 2009/02/28 06:00:58 das Exp $
+.\"
+.Dd April 19, 1994
+.Dt FGETLN 3
+.Os
+.Sh NAME
+.Nm fgetln
+.Nd get a line from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft char *
+.Fn fgetln "FILE *stream" "size_t *len"
+.Sh DESCRIPTION
+The
+.Fn fgetln
+function
+returns a pointer to the next line from the stream referenced by
+.Fa stream .
+This line is
+.Em not
+a C string as it does not end with a terminating
+.Dv NUL
+character.
+The length of the line, including the final newline,
+is stored in the memory location to which
+.Fa len
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
+.Sh RETURN VALUES
+Upon successful completion a pointer is returned;
+this pointer becomes invalid after the next
+.Tn I/O
+operation on
+.Fa stream
+(whether successful or not)
+or as soon as the stream is closed.
+Otherwise,
+.Dv NULL
+is returned.
+The
+.Fn fgetln
+function
+does not distinguish between end-of-file and error; the routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used
+to determine which occurred.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv NULL
+until the condition is
+cleared with
+.Xr clearerr 3 .
+.Pp
+The text to which the returned pointer points may be modified,
+provided that no changes are made beyond the returned size.
+These changes are lost as soon as the pointer becomes invalid.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa stream
+is not a stream open for reading.
+.It Bq Er ENOMEM
+The internal line buffer could not be expanded due to lack of available memory,
+or because it would need to expand beyond INT_MAX in size.
+.El
+.Pp
+The
+.Fn fgetln
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr fflush 3 ,
+.Xr malloc 3 ,
+.Xr read 2 ,
+.Xr stat 2 ,
+or
+.Xr realloc 3 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgets 3 ,
+.Xr fgetwln 3 ,
+.Xr fopen 3 ,
+.Xr getline 3 ,
+.Xr putc 3
+.Sh HISTORY
+The
+.Fn fgetln
+function first appeared in
+.Bx 4.4 .
+++ /dev/null
-.\" Copyright (c) 1990, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" This code is derived from software contributed to Berkeley by
-.\" Chris Torek and the American National Standards Committee X3,
-.\" on Information Processing Systems.
-.\"
-.\" 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.
-.\"
-.\" @(#)fgets.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fgets.3,v 1.19 2002/12/04 18:57:45 ru Exp $
-.\"
-.Dd June 4, 1993
-.Dt FGETS 3
-.Os
-.Sh NAME
-.Nm fgets ,
-.Nm gets
-.Nd get a line from a stream
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In stdio.h
-.Ft char *
-.Fn fgets "char *restrict s" "int n" "FILE *restrict stream"
-.Ft char *
-.Fn gets "char *s"
-.Sh DESCRIPTION
-The
-.Fn fgets
-function
-reads at most one less than the number of characters specified by
-.Fa n
-from the given
-.Fa stream
-and stores them in the string
-.Fa s .
-Reading stops when a newline character is found,
-at end-of-file or error.
-The newline, if any, is retained.
-If any characters are read and there is no error, a
-.Ql \e0
-character is appended to end the string.
-.Pp
-The
-.Fn gets
-function
-is equivalent to
-.Fn fgets
-with an infinite
-.Fa n
-and a
-.Fa stream
-of
-.Dv stdin ,
-except that the newline character (if any) is not stored in the string.
-It is the caller's responsibility to ensure that the input line,
-if any, is sufficiently short to fit in the string.
-.Sh RETURN VALUES
-Upon successful completion,
-.Fn fgets
-and
-.Fn gets
-return
-a pointer to the string.
-If end-of-file occurs before any characters are read,
-they return
-.Dv NULL
-and the buffer contents remain unchanged.
-If an error occurs,
-they return
-.Dv NULL
-and the buffer contents are indeterminate.
-The
-.Fn fgets
-and
-.Fn gets
-functions
-do not distinguish between end-of-file and error; callers must use
-.Xr feof 3
-and
-.Xr ferror 3
-to determine which occurred.
-.Sh ERRORS
-.Bl -tag -width Er
-.It Bq Er EBADF
-The given
-.Fa stream
-is not a readable stream.
-.El
-.Pp
-The function
-.Fn fgets
-may also fail and set
-.Va errno
-for any of the errors specified for the routines
-.Xr fflush 3 ,
-.Xr fstat 2 ,
-.Xr read 2 ,
-or
-.Xr malloc 3 .
-.Pp
-The function
-.Fn gets
-may also fail and set
-.Va errno
-for any of the errors specified for the routine
-.Xr getchar 3 .
-.Sh SECURITY CONSIDERATIONS
-The
-.Fn gets
-function cannot be used securely.
-Because of its lack of bounds checking,
-and the inability for the calling program
-to reliably determine the length of the next incoming line,
-the use of this function enables malicious users
-to arbitrarily change a running program's functionality through
-a buffer overflow attack.
-It is strongly suggested that the
-.Fn fgets
-function be used in all cases.
-(See
-the FSA.)
-.Sh SEE ALSO
-.Xr feof 3 ,
-.Xr ferror 3 ,
-.Xr fgetln 3 ,
-.Xr fgetws 3
-.Sh STANDARDS
-The functions
-.Fn fgets
-and
-.Fn gets
-conform to
-.St -isoC-99 .
--- /dev/null
+./fgets.3
\ No newline at end of file
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwc.c,v 1.12 2004/07/20 08:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwc.c,v 1.13 2008/04/17 22:17:53 jhb Exp $");
#include "xlocale_private.h"
return (wc);
}
do {
- nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_extra->mbstate, loc);
+ nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate, loc);
if (nconv == (size_t)-1)
break;
else if (nconv == (size_t)-2)
--- /dev/null
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwln.c,v 1.2 2004/08/06 17:00:09 tjr Exp $");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+wchar_t *
+fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t loc)
+{
+ wint_t wc;
+ size_t len;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+
+ len = 0;
+ while ((wc = __fgetwc(fp, loc)) != WEOF) {
+#define GROW 512
+ if (len * sizeof(wchar_t) >= fp->_lb._size &&
+ __slbexpand(fp, (len + GROW) * sizeof(wchar_t)))
+ goto error;
+ *((wchar_t *)fp->_lb._base + len++) = wc;
+ if (wc == L'\n')
+ break;
+ }
+ if (len == 0)
+ goto error;
+
+ FUNLOCKFILE(fp);
+ *lenp = len;
+ return ((wchar_t *)fp->_lb._base);
+
+error:
+ FUNLOCKFILE(fp);
+ *lenp = 0;
+ return (NULL);
+}
+
+wchar_t *
+fgetwln(FILE * __restrict fp, size_t *lenp)
+{
+ return fgetwln_l(fp, lenp, __current_locale());
+}
--- /dev/null
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 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.
+.\"
+.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD: src/lib/libc/stdio/fgetwln.3,v 1.3 2007/01/09 00:28:06 imp Exp $
+.\"
+.Dd July 16, 2004
+.Dt FGETWLN 3
+.Os
+.Sh NAME
+.Nm fgetwln ,
+.Nm fgetwln_l
+.Nd get a line of wide characters from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft wchar_t *
+.Fn fgetwln "FILE * restrict stream" "size_t * restrict len"
+.In xlocale.h
+.Ft wchar_t *
+.Fn fgetwln_l "FILE * restrict stream" "size_t * restrict len" "locale_t loc"
+.Sh DESCRIPTION
+The
+.Fn fgetwln
+function
+returns a pointer to the next line from the stream referenced by
+.Fa stream .
+This line is
+.Em not
+a standard wide character string as it does not end with a terminating
+null wide character.
+The length of the line, including the final newline,
+is stored in the memory location to which
+.Fa len
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
+.Pp
+While the
+.Fn fgetwln
+function uses the current locale, the
+.Fn fgetwln_l
+function may be passed a locale directly. See
+.Xr xlocale 3
+for more information.
+.Sh RETURN VALUES
+Upon successful completion a pointer is returned;
+this pointer becomes invalid after the next
+.Tn I/O
+operation on
+.Fa stream
+(whether successful or not)
+or as soon as the stream is closed.
+Otherwise,
+.Dv NULL
+is returned.
+The
+.Fn fgetwln
+function
+does not distinguish between end-of-file and error; the routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used
+to determine which occurred.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv NULL
+until the condition is
+cleared with
+.Xr clearerr 3 .
+.Pp
+The text to which the returned pointer points may be modified,
+provided that no changes are made beyond the returned size.
+These changes are lost as soon as the pointer becomes invalid.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa stream
+is not a stream open for reading.
+.El
+.Pp
+The
+.Fn fgetwln
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr mbrtowc 3 ,
+.Xr realloc 3 ,
+or
+.Xr read 2 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgetln 3 ,
+.Xr fgetws 3 ,
+.Xr fopen 3 ,
+.Xr xlocale 3
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.6 2004/10/03 15:48:32 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.8 2009/11/25 04:45:45 wollman Exp $");
#include "xlocale_private.h"
nl = memchr(fp->_p, '\n', fp->_r);
nconv = __mbsnrtowcs(wsp, &src,
nl != NULL ? (nl - fp->_p + 1) : fp->_r,
- n - 1, &fp->_extra->mbstate, loc);
+ n - 1, &fp->_mbstate, loc);
if (nconv == (size_t)-1)
/* Conversion error */
goto error;
if (wsp == ws)
/* EOF */
goto error;
- if (!rl->__mbsinit(&fp->_extra->mbstate, loc))
+ if (!rl->__mbsinit(&fp->_mbstate, loc))
/* Incomplete character */
goto error;
- *wsp++ = L'\0';
+ *wsp = L'\0';
FUNLOCKFILE(fp);
return (ws);
.\" 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.
.\"
.\" @(#)fgets.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/stdio/fgets.3,v 1.16 2002/05/31 05:01:17 archie Exp
-.\" $FreeBSD: src/lib/libc/stdio/fgetws.3,v 1.3 2003/03/09 02:56:54 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fgetws.3,v 1.4 2007/01/09 00:28:06 imp Exp $
.\"
.Dd August 6, 2002
.Dt FGETWS 3
* 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.
static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/findfp.c,v 1.29 2004/05/22 15:19:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/findfp.c,v 1.34 2009/12/05 19:31:38 ed Exp $");
+
+#include <TargetConditionals.h>
#include <sys/param.h>
#include <machine/atomic.h>
int __sdidinit;
+#if !TARGET_OS_EMBEDDED
#define NDYNAMIC 10 /* add ten more whenever necessary */
+#else
+#define NDYNAMIC 1 /* add one at a time on embedded */
+#endif
-#define std(flags, file) \
- {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
- {0}, __sFX + file}
- /* p r w flags file _bf z cookie close read seek write */
- /* _ub _extra */
-#define __sFXInit {0, PTHREAD_MUTEX_INITIALIZER}
+#define std(flags, file) { \
+ ._flags = (flags), \
+ ._file = (file), \
+ ._cookie = __sF + (file), \
+ ._close = __sclose, \
+ ._read = __sread, \
+ ._seek = __sseek, \
+ ._write = __swrite, \
+ ._extra = __sFX + file, \
+}
+#define __sFXInit {.fl_mutex = PTHREAD_MUTEX_INITIALIZER}
/* set counted */
-#define __sFXInit3 {0, PTHREAD_MUTEX_INITIALIZER, 0, 0, 0, 1}
- /* the usual - (stdin + stdout + stderr) */
+#define __sFXInit3 {.fl_mutex = PTHREAD_MUTEX_INITIALIZER, .counted = 1}
static int __scounted; /* streams counted against STREAM_MAX */
static int __stream_max;
+#if !TARGET_OS_EMBEDDED
+/* usual and usual_extra are data pigs. See 7929728. For embedded we should
+ * always allocate dynamically, and probably should for desktop too. */
+ /* the usual - (stdin + stdout + stderr) */
static FILE usual[FOPEN_MAX - 3];
static struct __sFILEX usual_extra[FOPEN_MAX - 3];
static struct glue uglue = { NULL, FOPEN_MAX - 3, usual };
+#endif /* !TARGET_OS_EMBEDDED */
static struct __sFILEX __sFX[3] = {__sFXInit3, __sFXInit3, __sFXInit3};
/*
- * We can't make this 'static' until 6.0-current due to binary
- * compatibility concerns. This also means we cannot change the
- * sizeof(FILE) until that time either and must continue to use the
- * __sFILEX stuff to add to FILE.
+ * We can't make this 'static' due to binary compatibility concerns.
+ * This also means we cannot change the sizeof(FILE) and must continue to
+ * use the __sFILEX stuff to add to FILE.
*/
FILE __sF[3] = {
std(__SRD, STDIN_FILENO),
std(__SWR|__SNBF, STDERR_FILENO)
};
-/*
- * The following kludge is done to ensure enough binary compatibility
- * with future versions of libc. Or rather it allows us to work with
- * libraries that have been built with a newer libc that defines these
- * symbols and expects libc to provide them. We only have need to support
- * i386 and alpha because they are the only "old" systems we have deployed.
- */
FILE *__stdinp = &__sF[0];
FILE *__stdoutp = &__sF[1];
FILE *__stderrp = &__sF[2];
+#if !TARGET_OS_EMBEDDED
struct glue __sglue = { &uglue, 3, __sF };
static struct glue *lastglue = &uglue;
+#else
+struct glue __sglue = { NULL, 3, __sF };
+static struct glue *lastglue = &__sglue;
+#endif
static struct glue * moreglue(int);
{
struct glue *g;
static FILE empty;
- static struct __sFILEX emptyx = __sFXInit;
FILE *p;
+ static struct __sFILEX emptyx = __sFXInit;
struct __sFILEX *fx;
g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE) +
g->next = NULL;
g->niobs = n;
g->iobs = p;
+
while (--n >= 0) {
*p = empty;
p->_extra = fx;
fp->_lb._base = NULL; /* no line buffer */
fp->_lb._size = 0;
/* fp->_lock = NULL; */ /* once set always set (reused) */
- fp->_extra->fl_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
- fp->_extra->orientation = 0;
+ INITEXTRA(fp);
fp->_extra->counted = count ? 1 : 0;
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
return (fp);
}
__private_extern__ void
__sfprelease(FILE *fp)
{
- if (fp->_extra->counted) {
+ if (fp->_counted) {
OSAtomicDecrement32(&__scounted);
- fp->_extra->counted = 0;
+ fp->_counted = 0;
}
fp->_flags = 0;
}
"warning: this program uses f_prealloc(), which is not recommended.");
void
-f_prealloc()
+f_prealloc(void)
{
struct glue *g;
int n;
void
__sinit()
{
- int i;
-
THREAD_LOCK();
if (__sdidinit == 0) {
- /* Set _extra for the usual suspects. */
- for (i = 0; i < FOPEN_MAX - 3; i++)
- usual[i]._extra = &usual_extra[i];
-
+#if !TARGET_OS_EMBEDDED
+ int i;
+#endif
/* Make sure we clean up on exit. */
__cleanup = _cleanup; /* conservative */
- __sdidinit = 1;
__stream_max = sysconf(_SC_STREAM_MAX);
__scounted = 3; /* std{in,out,err} already exists */
+
+#if !TARGET_OS_EMBEDDED
+ /* Set _extra for the usual suspects. */
+ for (i = 0; i < FOPEN_MAX - 3; i++) {
+ usual[i]._extra = &usual_extra[i];
+ INITEXTRA(&usual[i]);
+ }
+#endif
+
+ __sdidinit = 1;
}
THREAD_UNLOCK();
}
* 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.
static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/flags.c,v 1.9 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/flags.c,v 1.10 2007/01/09 00:28:06 imp Exp $");
#include <sys/types.h>
#include <sys/file.h>
* 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.
static char sccsid[] = "@(#)fopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fopen.c,v 1.10 2002/10/12 16:13:37 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fopen.c,v 1.14 2008/04/22 17:03:32 jhb Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <limits.h>
#include "un-namespace.h"
#include "local.h"
__sfprelease(fp); /* release */
return (NULL);
}
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (f > SHRT_MAX) {
+ fp->_flags = 0; /* release */
+ _close(f);
+ errno = EMFILE;
+ return (NULL);
+ }
fp->_file = f;
fp->_flags = flags;
fp->_cookie = fp;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fopen.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fopen.3,v 1.18 2003/01/26 10:01:59 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fopen.3,v 1.21 2009/09/09 19:38:19 ed Exp $
.\"
.Dd January 26, 2003
.Dt FOPEN 3
Open for reading and writing.
The stream is positioned at the beginning of the file.
.It Dq Li w
-Truncate file to zero length or create text file for writing.
+Truncate to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
.It Dq Li w+
Open for reading and writing.
.Pp
The
.Fa mode
-string can also include the letter ``b'' either as a third character or
+string can also include the letter ``b'' either as last character or
as a character between the characters in any of the two-character strings
described above.
This is strictly for compatibility with
* 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.
static char sccsid[] = "@(#)fprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fprintf.c,v 1.10 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fprintf.c,v 1.11 2007/01/09 00:28:06 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fputs.c,v 1.11 2002/10/12 16:13:37 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fputs.c,v 1.12 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fputs.3,v 1.11 2002/12/19 09:40:24 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fputs.3,v 1.14 2007/04/19 14:01:04 phk Exp $
.\"
.Dd June 4, 1993
.Dt FPUTS 3
to the stream
.Dv stdout .
.Sh RETURN VALUES
-The
+The functions
.Fn fputs
-function
-returns 0 on success and
-.Dv EOF
-on error;
+and
.Fn puts
-returns a nonnegative integer on success and
+return a nonnegative integer on success and
.Dv EOF
on error.
.Sh ERRORS
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fputwc.c,v 1.10 2004/07/20 08:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fputwc.c,v 1.11 2008/04/17 22:17:53 jhb Exp $");
#include "xlocale_private.h"
*buf = (unsigned char)wc;
len = 1;
} else {
- if ((len = xrl->__wcrtomb(buf, wc, &fp->_extra->mbstate, loc)) ==
- (size_t)-1) {
+ if ((len = loc->__lc_ctype->__wcrtomb(buf, wc, &fp->_mbstate, loc)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
}
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fputws.c,v 1.6 2004/07/21 10:54:57 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fputws.c,v 1.8 2009/01/15 18:53:52 rdivacky Exp $");
#include "xlocale_private.h"
char buf[BUFSIZ];
struct __suio uio;
struct __siov iov;
+ const wchar_t *wsp = ws;
size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict, locale_t);
uio.uio_iovcnt = 1;
iov.iov_base = buf;
do {
- nbytes = __wcsnrtombs(buf, &ws, SIZE_T_MAX, sizeof(buf),
- &fp->_extra->mbstate, loc);
+ nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf),
+ &fp->_mbstate, loc);
if (nbytes == (size_t)-1)
goto error;
iov.iov_len = uio.uio_resid = nbytes;
if (__sfvwrite(fp, &uio) != 0)
goto error;
- } while (ws != NULL);
+ } while (wsp != NULL);
FUNLOCKFILE(fp);
return (0);
.\" 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.
.\"
.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/stdio/fputs.3,v 1.8 2001/10/01 16:08:59 ru Exp
-.\" $FreeBSD: src/lib/libc/stdio/fputws.3,v 1.5 2003/05/22 13:02:27 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fputws.3,v 1.6 2007/01/09 00:28:06 imp Exp $
.\"
.Dd August 6, 2002
.Dt FPUTWS 3
* 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.
static char sccsid[] = "@(#)fread.c 8.2 (Berkeley) 12/11/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fread.c,v 1.12 2002/10/12 16:13:37 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fread.c,v 1.16 2009/07/12 13:09:43 ed Exp $");
#include "namespace.h"
#include <stdio.h>
#include "local.h"
#include "libc_private.h"
+/*
+ * MT-safe version
+ */
+
size_t
-fread(buf, size, count, fp)
- void * __restrict buf;
- size_t size, count;
- FILE * __restrict fp;
+fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
+{
+ size_t ret;
+
+ FLOCKFILE(fp);
+ ret = __fread(buf, size, count, fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+size_t
+__fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
{
size_t resid;
char *p;
size_t total;
/*
- * The ANSI standard requires a return value of 0 for a count
- * or a size of 0. Peculiarily, it imposes no such requirements
- * on fwrite; it only requires fread to be broken.
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
*/
if ((resid = count * size) == 0)
return (0);
- FLOCKFILE(fp);
ORIENT(fp, -1);
if (fp->_r < 0)
fp->_r = 0;
break;
else if (ret) {
/* no more input: return partial result */
- FUNLOCKFILE(fp);
return ((total - resid) / size);
}
}
fp->_bf = save;
fp->_p = fp->_bf._base;
/* fp->_r = 0; already set in __srefill1 */
- FUNLOCKFILE(fp);
return ((total - resid) / size);
}
fp->_bf._base += fp->_r;
resid -= r;
if (__srefill1(fp)) {
/* no more input: return partial result */
- FUNLOCKFILE(fp);
return ((total - resid) / size);
}
}
fp->_r -= resid;
fp->_p += resid;
}
- FUNLOCKFILE(fp);
return (count);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fread.3 8.2 (Berkeley) 3/8/94
-.\" $FreeBSD: src/lib/libc/stdio/fread.3,v 1.9 2002/10/12 16:13:37 mike Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fread.3,v 1.10 2007/01/09 00:28:06 imp Exp $
.\"
.Dd March 8, 1994
.Dt FREAD 3
* 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.
static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.13 2004/05/22 15:19:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.21 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
+#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int dflags, flags, isopen, oflags, sverrno, wantfd;
if ((flags = __sflags(mode, &oflags)) == 0) {
+ sverrno = errno;
(void) fclose(fp);
+ errno = sverrno;
return (NULL);
}
errno = EBADF;
return (NULL);
}
+ if (fp->_flags & __SWR)
+ (void) __sflush(fp);
if ((oflags ^ dflags) & O_APPEND) {
dflags &= ~O_APPEND;
dflags |= oflags & O_APPEND;
}
}
if (oflags & O_TRUNC)
- ftruncate(fp->_file, 0);
- if (_fseeko(fp, 0, oflags & O_APPEND ? SEEK_END : SEEK_SET,
- 0) < 0 && errno != ESPIPE) {
- sverrno = errno;
- fclose(fp);
- FUNLOCKFILE(fp);
- errno = sverrno;
- return (NULL);
- }
+ (void) ftruncate(fp->_file, (off_t)0);
+ if (!(oflags & O_APPEND))
+ (void) _sseek(fp, (fpos_t)0, SEEK_SET);
f = fp->_file;
isopen = 0;
wantfd = -1;
if (HASLB(fp))
FREELB(fp);
fp->_lb._size = 0;
- fp->_extra->orientation = 0;
- memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
+ fp->_orientation = 0;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
if (f < 0) { /* did not get it after all */
__sfprelease(fp); /* set it free */
- errno = sverrno; /* restore in case _close clobbered */
FUNLOCKFILE(fp);
+ errno = sverrno; /* restore in case _close clobbered */
return (NULL);
}
}
}
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (f > SHRT_MAX) {
+ __sfprelease(fp); /* set it free */
+ FUNLOCKFILE(fp);
+ errno = EMFILE;
+ return (NULL);
+ }
+
fp->_flags = flags;
fp->_file = f;
fp->_cookie = fp;
fp->_write = __swrite;
fp->_seek = __sseek;
fp->_close = __sclose;
+ /*
+ * When opening in append mode, even though we use O_APPEND,
+ * we need to seek to the end so that ftell() gets the right
+ * answer. If the user then alters the seek pointer, or
+ * the file extends, this will fail, but there is not much
+ * we can do about this. (We could set __SAPP and check in
+ * fseek and ftell.)
+ */
+ if (oflags & O_APPEND)
+ (void) _sseek(fp, (fpos_t)0, SEEK_END);
FUNLOCKFILE(fp);
return (fp);
}
* 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.
static char sccsid[] = "@(#)fscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fscanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fscanf.c,v 1.13 2007/01/09 00:28:06 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)fseek.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fseek.3,v 1.25 2004/03/20 08:38:27 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/fseek.3,v 1.27 2007/06/18 02:13:04 ache Exp $
.\"
.Dd March 19, 2004
.Dt FSEEK 3
.Fn fseeko ,
.Fn fsetpos ,
.Fn ftell ,
+.Fn ftello ,
and
-.Fn ftello
+.Fn rewind
may also fail and set
.Va errno
for any of the errors specified for the routines
* 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.
static char sccsid[] = "@(#)ftell.c 8.2 (Berkeley) 5/4/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/ftell.c,v 1.26 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/ftell.c,v 1.27 2007/01/09 00:28:06 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
* 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.
static char sccsid[] = "@(#)funopen.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/funopen.c,v 1.5 2002/05/28 16:59:39 alfred Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/funopen.c,v 1.7 2009/12/05 19:31:38 ed Exp $");
#include <stdio.h>
#include <errno.h>
#include "local.h"
FILE *
-funopen(cookie, readfn, writefn, seekfn, closefn)
- const void *cookie;
- int (*readfn)(), (*writefn)();
- fpos_t (*seekfn)(void *cookie, fpos_t off, int whence);
- int (*closefn)();
+funopen(const void *cookie,
+ int (*readfn)(void *, char *, int),
+ int (*writefn)(void *, const char *, int),
+ fpos_t (*seekfn)(void *, fpos_t, int),
+ int (*closefn)(void *))
{
FILE *fp;
int flags;
* 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.
static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/fwrite.c,v 1.11 2002/10/12 16:13:41 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/fwrite.c,v 1.13 2009/07/12 13:09:43 ed Exp $");
#include "namespace.h"
#include <stdio.h>
struct __suio uio;
struct __siov iov;
- iov.iov_base = (void *)buf;
- uio.uio_resid = iov.iov_len = n = count * size;
-
+ /*
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+ */
+ n = count * size;
#if __DARWIN_UNIX03
- if (n == 0) /* POSIX */
- return 0;
-#endif /* __DARWIN_UNIX03 */
+ if (n == 0)
+ return (0);
+#endif
+ iov.iov_base = (void *)buf;
+ uio.uio_resid = iov.iov_len = n;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/getc.3,v 1.19 2004/03/17 12:37:28 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/getc.3,v 1.21 2007/01/09 00:28:06 imp Exp $
.\"
.Dd January 10, 2003
.Dt GETC 3
--- /dev/null
+./getdelim.c
\ No newline at end of file
--- /dev/null
+./getline.c
\ No newline at end of file
--- /dev/null
+.\" Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libc/stdio/getline.3,v 1.2 2009/04/06 13:50:04 das Exp $
+.\"
+.Dd March 29, 2009
+.Dt GETLINE 3
+.Os
+.Sh NAME
+.Nm getdelim ,
+.Nm getline
+.Nd get a line from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft ssize_t
+.Fn getdelim "char ** restrict linep" "size_t * restrict linecapp" "int delimiter" " FILE * restrict stream"
+.Ft ssize_t
+.Fn getline "char ** restrict linep" "size_t * restrict linecapp" " FILE * restrict stream"
+.Sh DESCRIPTION
+The
+.Fn getdelim
+function reads a line from
+.Fa stream ,
+delimited by the character
+.Fa delimiter .
+The
+.Fn getline
+function is equivalent to
+.Fn getdelim
+with the newline character as the delimiter.
+The delimiter character is included as part of the line, unless
+the end of the file is reached.
+The caller may provide a pointer to a malloc buffer for the line in
+.Fa *linep ,
+and the capacity of that buffer in
+.Fa *linecapp ;
+if
+.Fa *linecapp
+is 0, then
+.Fa *linep
+is treated as
+.Dv NULL .
+These functions may expand the buffer as needed, as if via
+.Fn realloc ,
+and update
+.Fa *linep
+and
+.Fa *linecapp
+accordingly.
+.Sh RETURN VALUES
+The
+.Fn getdelim
+and
+.Fn getline
+functions return the number of characters written, excluding the
+terminating
+.Dv NULL .
+The value \-1 is returned if an error occurs, or if end-of-file is reached.
+.Sh EXAMPLES
+The following code fragment reads lines from a file and
+writes them to standard output.
+The
+.Fn fwrite
+function is used in case the line contains embedded
+.Dv NUL
+characters.
+.Bd -literal -offset indent
+char *line = NULL;
+size_t linecap = 0;
+ssize_t linelen;
+while ((linelen = getline(&line, &linecap, fp)) > 0)
+ fwrite(line, linelen, 1, stdout);
+.Ed
+.Sh ERRORS
+These functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Either
+.Fa linep
+or
+.Fa linecapp
+is
+.Dv NULL .
+.It Bq Er EOVERFLOW
+No delimiter was found in the first
+.Dv SSIZE_MAX
+characters.
+.El
+.Pp
+These functions may also fail for any of the errors specified for
+.Fn fgets
+and
+.Fn malloc .
+.Sh SEE ALSO
+.Xr fgetln 3 ,
+.Xr fgets 3 ,
+.Xr malloc 3
+.Sh STANDARDS
+The
+.Fn getdelim
+and
+.Fn getline
+functions conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 8.0 .
+.Sh BUGS
+There are no wide character versions of
+.Fn getdelim
+or
+.Fn getline .
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/getwc.3,v 1.6 2004/03/16 13:30:11 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/getwc.3,v 1.8 2007/01/09 00:28:06 imp Exp $
.\"
.Dd March 3, 2004
.Dt GETWC 3
.Ft wint_t
.Fn getwc "FILE *stream"
.Ft wint_t
-.Fn getwchar void
+.Fn getwchar "void"
.Sh DESCRIPTION
The
.Fn fgetwc
.Xr fopen 3 ,
.Xr fread 3 ,
.Xr getc 3 ,
-.Xr getwc_l 3 ,
+.Xr getwc_l ,
.Xr putwc 3 ,
.Xr stdio 3 ,
.Xr ungetwc 3
+++ /dev/null
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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.
- *
- * @(#)glue.h 8.1 (Berkeley) 6/4/93
- * $FreeBSD: src/lib/libc/stdio/glue.h,v 1.2 2002/03/22 23:42:01 obrien Exp $
- */
-
-/*
- * The first few FILEs are statically allocated; others are dynamically
- * allocated and linked in via this glue structure.
- */
-struct glue {
- struct glue *next;
- int niobs;
- FILE *iobs;
-};
-extern struct glue __sglue;
--- /dev/null
+./glue.h
\ No newline at end of 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.
- * 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.
* SUCH DAMAGE.
*
* @(#)local.h 8.3 (Berkeley) 7/3/94
- * $FreeBSD: src/lib/libc/stdio/local.h,v 1.26 2004/07/16 05:52:51 tjr Exp $
+ * $FreeBSD: src/lib/libc/stdio/local.h,v 1.33 2008/05/05 16:03:52 jhb Exp $
*/
#include <sys/cdefs.h>
extern int _ftello(FILE *, fpos_t *);
extern int _fseeko(FILE *, off_t, int, int);
extern int __fflush(FILE *fp);
+extern void __fcloseall(void);
extern wint_t __fgetwc(FILE *, locale_t);
extern wint_t __fputwc(wchar_t, FILE *, locale_t);
extern int __sflush(FILE *);
-extern FILE *__sfp(int); /* arg is whether to count against STREAM_MAX or not */
+extern FILE *__sfp(int);
extern void __sfprelease(FILE *); /* mark free and update count as needed */
extern int __slbexpand(FILE *, size_t);
extern int __srefill(FILE *);
extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list) __DARWIN_LDBL_COMPAT(__vfwprintf);
extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict,
__va_list) __DARWIN_LDBL_COMPAT(__vfwscanf);
-
+extern size_t __fread(void * __restrict buf, size_t size, size_t count,
+ FILE * __restrict fp);
extern int __sdidinit;
/* hold a buncha junk that would grow the ABI */
struct __sFILEX {
- unsigned char *_up; /* saved _p when _p is doing ungetc data */
+ unsigned char *up; /* saved _p when _p is doing ungetc data */
pthread_mutex_t fl_mutex; /* used for MT-safety */
pthread_t fl_owner; /* current owner */
int fl_count; /* recursive lock count */
mbstate_t mbstate; /* multibyte conversion state */
};
+#define _up _extra->up
+#define _fl_mutex _extra->fl_mutex
+#define _fl_owner _extra->fl_owner
+#define _fl_count _extra->fl_count
+#define _orientation _extra->orientation
+#define _mbstate _extra->mbstate
+#define _counted _extra->counted
+
+#define INITEXTRA(fp) do { \
+ (fp)->_extra->up = NULL; \
+ (fp)->_extra->fl_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; \
+ (fp)->_extra->fl_owner = NULL; \
+ (fp)->_extra->fl_count = 0; \
+ (fp)->_extra->orientation = 0; \
+ memset(&(fp)->_extra->mbstate, 0, sizeof(mbstate_t)); \
+ (fp)->_extra->counted = 0; \
+} while(0);
+
/*
* Prepare the given FILE for writing, and return 0 iff it
* can be written now. Otherwise, return EOF and set errno.
(fp)->_lb._base = NULL; \
}
-#define INITEXTRA(fp) { \
- (fp)->_extra->_up = NULL; \
- (fp)->_extra->fl_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; \
- (fp)->_extra->fl_owner = NULL; \
- (fp)->_extra->fl_count = 0; \
- (fp)->_extra->orientation = 0; \
- memset(&(fp)->_extra->mbstate, 0, sizeof(mbstate_t)); \
-}
-
/*
* Set the orientation for a stream. If o > 0, the stream has wide-
* orientation. If o < 0, the stream has byte-orientation.
*/
#define ORIENT(fp, o) do { \
- if ((fp)->_extra->orientation == 0) \
- (fp)->_extra->orientation = (o); \
+ if ((fp)->_orientation == 0) \
+ (fp)->_orientation = (o); \
} while (0)
* 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.
static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.4 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/makebuf.c,v 1.6 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
-#include "local.h"
#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
#define MAXBUFSIZE (1 << 16)
#define TTYBUFSIZE 4096
* 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.
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/mktemp.c,v 1.28 2003/02/16 17:29:10 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/mktemp.c,v 1.32 2010/02/28 13:31:29 jh Exp $");
#include "namespace.h"
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/stat.h>
-#include <sys/syslimits.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
struct stat sbuf;
int rval;
uint32_t rand;
- char carrybuf[NAME_MAX];
+ char carrybuf[MAXPATHLEN];
if ((doopen != NULL && domkdir) || slen < 0) {
errno = EINVAL;
for (trv = path; *trv != '\0'; ++trv)
;
+ if (trv - path >= MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ return (0);
+ }
trv -= slen;
suffp = trv;
--trv;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)mktemp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/mktemp.3,v 1.20 2004/02/20 04:08:28 green Exp $
+.\" $FreeBSD: src/lib/libc/stdio/mktemp.3,v 1.22 2007/01/09 00:28:07 imp Exp $
.\"
.Dd February 11, 1998
.Dt MKTEMP 3
.Sh NAME
.Nm mkdtemp ,
.Nm mkstemp ,
-.Nm mktemp ,
-.Nm mktemps
+.Nm mkstemps ,
+.Nm mktemp
.Nd make temporary file name (unique)
.Sh LIBRARY
.Lb libc
See
.Xr gcc 1
for more information.
-.Sh BUGS
-This family of functions produces filenames which can be guessed,
-though the risk is minimized when large numbers of
-.Ql X Ns s
-are used to
-increase the number of possible temporary filenames.
-This makes the race in
-.Fn mktemp ,
-between testing for a file's existence (in the
-.Fn mktemp
-function call)
-and opening it for use
-(later in the user application)
-particularly dangerous from a security perspective.
-Whenever it is possible,
-.Fn mkstemp
-should be used instead, since it does not have the race condition.
-If
-.Fn mkstemp
-cannot be used, the filename created by
-.Fn mktemp
-should be created using the
-.Dv O_EXCL
-flag to
-.Xr open 2
-and the return status of the call should be tested for failure.
-This will ensure that the program does not continue blindly
-in the event that an attacker has already created the file
-with the intention of manipulating or reading its contents.
.Sh LEGACY SYNOPSIS
.Fd #include <unistd.h>
.Pp
.Ox 2.4 ,
and later in
.Fx 3.4 .
+.Sh BUGS
+This family of functions produces filenames which can be guessed,
+though the risk is minimized when large numbers of
+.Ql X Ns s
+are used to
+increase the number of possible temporary filenames.
+This makes the race in
+.Fn mktemp ,
+between testing for a file's existence (in the
+.Fn mktemp
+function call)
+and opening it for use
+(later in the user application)
+particularly dangerous from a security perspective.
+Whenever it is possible,
+.Fn mkstemp
+should be used instead, since it does not have the race condition.
+If
+.Fn mkstemp
+cannot be used, the filename created by
+.Fn mktemp
+should be created using the
+.Dv O_EXCL
+flag to
+.Xr open 2
+and the return status of the call should be tested for failure.
+This will ensure that the program does not continue blindly
+in the event that an attacker has already created the file
+with the intention of manipulating or reading its contents.
+++ /dev/null
-/*
- * 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.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)perror.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/perror.c,v 1.8 2002/12/19 09:53:26 tjr Exp $");
-
-#include "namespace.h"
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include "un-namespace.h"
-#include "libc_private.h"
-#include "local.h"
-
-void
-perror(s)
- const char *s;
-{
- char msgbuf[NL_TEXTMAX];
- struct iovec *v;
- struct iovec iov[4];
-
- v = iov;
- if (s != NULL && *s != '\0') {
- v->iov_base = (char *)s;
- v->iov_len = strlen(s);
- v++;
- v->iov_base = ": ";
- v->iov_len = 2;
- v++;
- }
- strerror_r(errno, msgbuf, sizeof(msgbuf));
- v->iov_base = msgbuf;
- v->iov_len = strlen(v->iov_base);
- v++;
- v->iov_base = "\n";
- v->iov_len = 1;
- FLOCKFILE(stderr);
- ORIENT(stderr, -1);
- __sflush(stderr);
- (void)_writev(stderr->_file, iov, (v - iov) + 1);
- stderr->_flags &= ~__SOFF;
- FUNLOCKFILE(stderr);
-}
--- /dev/null
+./perror.c
\ No newline at end of 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.
- * 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.
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/printf.c,v 1.10 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/printf.c,v 1.11 2007/01/09 00:28:07 imp Exp $");
#include "xlocale_private.h"
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/printf-pos.c,v 1.6 2009/03/02 04:07:58 das Exp $");
+
+/*
+ * This is the code responsible for handling positional arguments
+ * (%m$ and %m$.n$) for vfprintf() and vfwprintf().
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "un-namespace.h"
+#include "printflocal.h"
+
+/*
+ * Type ids for argument type table.
+ */
+enum typeid {
+ T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
+ T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
+ T_PTRDIFFT, TP_PTRDIFFT, T_SSIZET, T_SIZET, TP_SSIZET,
+ T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
+ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR,
+#ifdef VECTORS
+ T_VECTOR,
+#endif
+};
+
+/* An expandable array of types. */
+struct typetable {
+ enum typeid *table; /* table of types */
+ enum typeid stattable[STATIC_ARG_TBL_SIZE];
+ int tablesize; /* current size of type table */
+ int tablemax; /* largest used index in table */
+ int nextarg; /* 1-based argument index */
+};
+
+static int __grow_type_table(struct typetable *);
+static void build_arg_table (struct typetable *, va_list, union arg **);
+
+/*
+ * Initialize a struct typetable.
+ */
+static inline void
+inittypes(struct typetable *types)
+{
+ int n;
+
+ types->table = types->stattable;
+ types->tablesize = STATIC_ARG_TBL_SIZE;
+ types->tablemax = 0;
+ types->nextarg = 1;
+ for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
+ types->table[n] = T_UNUSED;
+}
+
+/*
+ * struct typetable destructor.
+ */
+static inline void
+freetypes(struct typetable *types)
+{
+
+ if (types->table != types->stattable)
+ free (types->table);
+}
+
+/*
+ * Ensure that there is space to add a new argument type to the type table.
+ * Expand the table if necessary. Returns 0 on success.
+ */
+static inline int
+_ensurespace(struct typetable *types)
+{
+
+ if (types->nextarg >= types->tablesize) {
+ if (__grow_type_table(types))
+ return (-1);
+ }
+ if (types->nextarg > types->tablemax)
+ types->tablemax = types->nextarg;
+ return (0);
+}
+
+/*
+ * Add an argument type to the table, expanding if necessary.
+ * Returns 0 on success.
+ */
+static inline int
+addtype(struct typetable *types, enum typeid type)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ types->table[types->nextarg++] = type;
+ return (0);
+}
+
+static inline int
+addsarg(struct typetable *types, int flags)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ if (flags & INTMAXT)
+ types->table[types->nextarg++] = T_INTMAXT;
+ else if (flags & SIZET)
+ types->table[types->nextarg++] = T_SSIZET;
+ else if (flags & PTRDIFFT)
+ types->table[types->nextarg++] = T_PTRDIFFT;
+ else if (flags & LLONGINT)
+ types->table[types->nextarg++] = T_LLONG;
+ else if (flags & LONGINT)
+ types->table[types->nextarg++] = T_LONG;
+ else
+ types->table[types->nextarg++] = T_INT;
+ return (0);
+}
+
+static inline int
+adduarg(struct typetable *types, int flags)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ if (flags & INTMAXT)
+ types->table[types->nextarg++] = T_UINTMAXT;
+ else if (flags & SIZET)
+ types->table[types->nextarg++] = T_SIZET;
+ else if (flags & PTRDIFFT)
+ types->table[types->nextarg++] = T_SIZET;
+ else if (flags & LLONGINT)
+ types->table[types->nextarg++] = T_U_LLONG;
+ else if (flags & LONGINT)
+ types->table[types->nextarg++] = T_U_LONG;
+ else
+ types->table[types->nextarg++] = T_U_INT;
+ return (0);
+}
+
+/*
+ * Add * arguments to the type array.
+ */
+static inline int
+addaster(struct typetable *types, char **fmtp)
+{
+ char *cp;
+ int n2;
+
+ n2 = 0;
+ cp = *fmtp;
+ while (is_digit(*cp)) {
+ n2 = 10 * n2 + to_digit(*cp);
+ cp++;
+ }
+ if (*cp == '$') {
+ int hold = types->nextarg;
+ types->nextarg = n2;
+ if (addtype(types, T_INT))
+ return (-1);
+ types->nextarg = hold;
+ *fmtp = ++cp;
+ } else {
+ if (addtype(types, T_INT))
+ return (-1);
+ }
+ return (0);
+}
+
+static inline int
+addwaster(struct typetable *types, wchar_t **fmtp)
+{
+ wchar_t *cp;
+ int n2;
+
+ n2 = 0;
+ cp = *fmtp;
+ while (is_digit(*cp)) {
+ n2 = 10 * n2 + to_digit(*cp);
+ cp++;
+ }
+ if (*cp == '$') {
+ int hold = types->nextarg;
+ types->nextarg = n2;
+ if (addtype(types, T_INT))
+ return (-1);
+ types->nextarg = hold;
+ *fmtp = ++cp;
+ } else {
+ if (addtype(types, T_INT))
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Find all arguments when a positional parameter is encountered. Returns a
+ * table, indexed by argument number, of pointers to each arguments. The
+ * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
+ * It will be replaces with a malloc-ed one if it overflows.
+ * Returns 0 on success. On failure, returns nonzero and sets errno.
+ */
+__private_extern__ int
+__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
+{
+ char *fmt; /* format string */
+ int ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ int error;
+ int flags; /* flags as above */
+ int width; /* width from format (%8d), or 0 */
+ struct typetable types; /* table of types */
+
+ fmt = (char *)fmt0;
+ inittypes(&types);
+ error = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ while ((ch = *fmt) != '\0' && ch != '%')
+ fmt++;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ width = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ goto rflag;
+ case '*':
+ if ((error = addaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ case '-':
+ case '+':
+ case '\'':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ if ((error = addaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ }
+ while (is_digit(ch)) {
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ types.nextarg = n;
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ error = addtype(&types,
+#ifdef VECTORS
+ (flags & LONGINT) ? T_WINT : ((flags & VECTOR) ? T_VECTOR : T_INT));
+#else
+ (flags & LONGINT) ? T_WINT : T_INT);
+#endif
+ if (error)
+ goto error;
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+#ifdef VECTORS
+ if (flags & VECTOR) {
+ if ((error = addtype(&types, T_VECTOR)))
+ goto error;
+ } else
+#endif
+ if ((error = addsarg(&types, flags)))
+ goto error;
+ break;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
+#ifdef VECTORS
+ (flags & VECTOR) ? T_VECTOR : ((flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE));
+#else
+ (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
+#endif
+ if (error)
+ goto error;
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ if (flags & INTMAXT)
+ error = addtype(&types, TP_INTMAXT);
+ else if (flags & PTRDIFFT)
+ error = addtype(&types, TP_PTRDIFFT);
+ else if (flags & SIZET)
+ error = addtype(&types, TP_SSIZET);
+ else if (flags & LLONGINT)
+ error = addtype(&types, TP_LLONG);
+ else if (flags & LONGINT)
+ error = addtype(&types, TP_LONG);
+ else if (flags & SHORTINT)
+ error = addtype(&types, TP_SHORT);
+ else if (flags & CHARINT)
+ error = addtype(&types, TP_SCHAR);
+ else
+ error = addtype(&types, TP_INT);
+ if (error)
+ goto error;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+#ifdef VECTORS
+ if (flags & VECTOR) {
+ if ((error = addtype(&types, T_VECTOR)))
+ goto error;
+ } else
+#endif
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ case 'p':
+#ifdef VECTORS
+ if ((error = addtype(&types, (flags & VECTOR) ? T_VECTOR : TP_VOID)))
+#else
+ if ((error = addtype(&types, TP_VOID)))
+#endif
+ goto error;
+ break;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ error = addtype(&types,
+ (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
+ if (error)
+ goto error;
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ case 'X':
+ case 'x':
+#ifdef VECTORS
+ if (flags & VECTOR) {
+ if ((error = addtype(&types, T_VECTOR)))
+ goto error;
+ } else
+#endif
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ build_arg_table(&types, ap, argtable);
+error:
+ freetypes(&types);
+ return (error || *argtable == NULL);
+}
+
+/* wchar version of __find_arguments. */
+__private_extern__ int
+__find_warguments (const wchar_t *fmt0, va_list ap, union arg **argtable)
+{
+ wchar_t *fmt; /* format string */
+ wchar_t ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ int error;
+ int flags; /* flags as above */
+ int width; /* width from format (%8d), or 0 */
+ struct typetable types; /* table of types */
+
+ fmt = (wchar_t *)fmt0;
+ inittypes(&types);
+ error = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ while ((ch = *fmt) != '\0' && ch != '%')
+ fmt++;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ width = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ goto rflag;
+ case '*':
+ if ((error = addwaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ case '-':
+ case '+':
+ case '\'':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ if ((error = addwaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ }
+ while (is_digit(ch)) {
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ types.nextarg = n;
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ error = addtype(&types,
+ (flags & LONGINT) ? T_WINT : T_INT);
+ if (error)
+ goto error;
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if ((error = addsarg(&types, flags)))
+ goto error;
+ break;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
+ (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
+ if (error)
+ goto error;
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ if (flags & INTMAXT)
+ error = addtype(&types, TP_INTMAXT);
+ else if (flags & PTRDIFFT)
+ error = addtype(&types, TP_PTRDIFFT);
+ else if (flags & SIZET)
+ error = addtype(&types, TP_SSIZET);
+ else if (flags & LLONGINT)
+ error = addtype(&types, TP_LLONG);
+ else if (flags & LONGINT)
+ error = addtype(&types, TP_LONG);
+ else if (flags & SHORTINT)
+ error = addtype(&types, TP_SHORT);
+ else if (flags & CHARINT)
+ error = addtype(&types, TP_SCHAR);
+ else
+ error = addtype(&types, TP_INT);
+ if (error)
+ goto error;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ case 'p':
+ if ((error = addtype(&types, TP_VOID)))
+ goto error;
+ break;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ error = addtype(&types,
+ (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
+ if (error)
+ goto error;
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ case 'X':
+ case 'x':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ build_arg_table(&types, ap, argtable);
+error:
+ freetypes(&types);
+ return (error || *argtable == NULL);
+}
+
+/*
+ * Increase the size of the type table. Returns 0 on success.
+ */
+static int
+__grow_type_table(struct typetable *types)
+{
+ enum typeid *const oldtable = types->table;
+ const int oldsize = types->tablesize;
+ enum typeid *newtable;
+ int n, newsize = oldsize * 2;
+
+ if (newsize < types->nextarg + 1)
+ newsize = types->nextarg + 1;
+ if (oldsize == STATIC_ARG_TBL_SIZE) {
+ if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
+ return (-1);
+ bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
+ } else {
+ newtable = realloc(oldtable, newsize * sizeof(enum typeid));
+ if (newtable == NULL)
+ return (-1);
+ }
+ for (n = oldsize; n < newsize; n++)
+ newtable[n] = T_UNUSED;
+
+ types->table = newtable;
+ types->tablesize = newsize;
+
+ return (0);
+}
+
+/*
+ * Build the argument table from the completed type table.
+ * On malloc failure, *argtable is set to NULL.
+ */
+static void
+build_arg_table(struct typetable *types, va_list ap, union arg **argtable)
+{
+ int n;
+
+ if (types->tablemax >= STATIC_ARG_TBL_SIZE) {
+ *argtable = (union arg *)
+ malloc (sizeof (union arg) * (types->tablemax + 1));
+ if (*argtable == NULL)
+ return;
+ }
+
+ (*argtable) [0].intarg = 0;
+ for (n = 1; n <= types->tablemax; n++) {
+ switch (types->table[n]) {
+ case T_UNUSED: /* whoops! */
+ (*argtable) [n].intarg = va_arg (ap, int);
+ break;
+ case TP_SCHAR:
+ (*argtable) [n].pschararg = va_arg (ap, signed char *);
+ break;
+ case TP_SHORT:
+ (*argtable) [n].pshortarg = va_arg (ap, short *);
+ break;
+ case T_INT:
+ (*argtable) [n].intarg = va_arg (ap, int);
+ break;
+ case T_U_INT:
+ (*argtable) [n].uintarg = va_arg (ap, unsigned int);
+ break;
+ case TP_INT:
+ (*argtable) [n].pintarg = va_arg (ap, int *);
+ break;
+ case T_LONG:
+ (*argtable) [n].longarg = va_arg (ap, long);
+ break;
+ case T_U_LONG:
+ (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
+ break;
+ case TP_LONG:
+ (*argtable) [n].plongarg = va_arg (ap, long *);
+ break;
+ case T_LLONG:
+ (*argtable) [n].longlongarg = va_arg (ap, long long);
+ break;
+ case T_U_LLONG:
+ (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
+ break;
+ case TP_LLONG:
+ (*argtable) [n].plonglongarg = va_arg (ap, long long *);
+ break;
+ case T_PTRDIFFT:
+ (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
+ break;
+ case TP_PTRDIFFT:
+ (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
+ break;
+ case T_SIZET:
+ (*argtable) [n].sizearg = va_arg (ap, size_t);
+ break;
+ case T_SSIZET:
+ (*argtable) [n].sizearg = va_arg (ap, ssize_t);
+ break;
+ case TP_SSIZET:
+ (*argtable) [n].pssizearg = va_arg (ap, ssize_t *);
+ break;
+ case T_INTMAXT:
+ (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
+ break;
+ case T_UINTMAXT:
+ (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
+ break;
+ case TP_INTMAXT:
+ (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
+ break;
+ case T_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ (*argtable) [n].doublearg = va_arg (ap, double);
+#endif
+ break;
+ case T_LONG_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ (*argtable) [n].longdoublearg = va_arg (ap, long double);
+#endif
+ break;
+#ifdef VECTORS
+ case T_VECTOR:
+ (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
+ break;
+#endif /* VECTORS */
+ case TP_CHAR:
+ (*argtable) [n].pchararg = va_arg (ap, char *);
+ break;
+ case TP_VOID:
+ (*argtable) [n].pvoidarg = va_arg (ap, void *);
+ break;
+ case T_WINT:
+ (*argtable) [n].wintarg = va_arg (ap, wint_t);
+ break;
+ case TP_WCHAR:
+ (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
+ break;
+ }
+ }
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/printf.3,v 1.58 2004/10/16 16:00:01 stefanf Exp $
+.\" $FreeBSD: src/lib/libc/stdio/printf.3,v 1.64 2009/12/02 07:51:25 brueffer Exp $
.\"
-.Dd October 16, 2004
+.Dd December 2, 2009
.Dt PRINTF 3
.Os
.Sh NAME
-.Nm asprintf ,
-.Nm fprintf ,
-.Nm printf ,
-.Nm snprintf ,
-.Nm sprintf ,
-.Nm vasprintf ,
-.Nm vfprintf,
-.Nm vprintf ,
-.Nm vsnprintf ,
-.Nm vsprintf
+.Nm printf , fprintf , sprintf , snprintf , asprintf , dprintf ,
+.Nm vprintf , vfprintf, vsprintf , vsnprintf , vasprintf, vdprintf
.Nd formatted output conversion
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In stdio.h
.Ft int
-.Fo asprintf
-.Fa "char **ret"
-.Fa "const char *format" ...
-.Fc
+.Fn printf "const char * restrict format" ...
.Ft int
-.Fo fprintf
-.Fa "FILE *restrict stream"
-.Fa "const char *restrict format" ...
-.Fc
+.Fn fprintf "FILE * restrict stream" "const char * restrict format" ...
.Ft int
-.Fo printf
-.Fa "const char *restrict format" ...
-.Fc
+.Fn sprintf "char * restrict str" "const char * restrict format" ...
.Ft int
-.Fo snprintf
-.Fa "char *restrict s"
-.Fa "size_t n"
-.Fa "const char *restrict format" ...
-.Fc
+.Fn snprintf "char * restrict str" "size_t size" "const char * restrict format" ...
.Ft int
-.Fo sprintf
-.Fa "char *restrict s"
-.Fa "const char *restrict format" ...
-.Fc
+.Fn asprintf "char **ret" "const char *format" ...
+.Ft int
+.Fn dprintf "int fd" "const char * restrict format" ...
.In stdarg.h
-.In stdio.h
.Ft int
-.Fo vasprintf
-.Fa "char **ret"
-.Fa "const char *format"
-.Fa "va_list ap"
-.Fc
+.Fn vprintf "const char * restrict format" "va_list ap"
.Ft int
-.Fo vfprintf
-.Fa "FILE *restrict stream"
-.Fa "const char *restrict format"
-.Fa "va_list ap"
-.Fc
+.Fn vfprintf "FILE * restrict stream" "const char * restrict format" "va_list ap"
.Ft int
-.Fo vprintf
-.Fa "const char *restrict format"
-.Fa "va_list ap"
-.Fc
+.Fn vsprintf "char * restrict str" "const char * restrict format" "va_list ap"
.Ft int
-.Fo vsnprintf
-.Fa "char *restrict s"
-.Fa "size_t n"
-.Fa "const char *restrict format"
-.Fa "va_list ap"
-.Fc
+.Fn vsnprintf "char * restrict str" "size_t size" "const char * restrict format" "va_list ap"
.Ft int
-.Fo vsprintf
-.Fa "char *restrict s"
-.Fa "const char *restrict format"
-.Fa "va_list ap"
-.Fc
+.Fn vasprintf "char **ret" "const char *format" "va_list ap"
+.Ft int
+.Fn vdprintf "int fd" "const char * restrict format" "va_list ap"
.Sh DESCRIPTION
The
.Fn printf
family of functions produces output according to a
-.Fa format ,
+.Fa format
as described below.
The
.Fn printf
.Fn vfprintf
write output to the given output
.Fa stream ;
+.Fn dprintf
+and
+.Fn vdprintf
+write output to the given file descriptor;
.Fn sprintf ,
.Fn snprintf ,
.Fn vsprintf ,
For
.Cm o
conversions, the precision of the number is increased to force the first
-character of the output string to a zero (except if a zero value is printed
-with an explicit precision of zero).
+character of the output string to a zero.
For
.Cm x
and
Note that there may be multiple valid ways to represent floating-point
numbers in this hexadecimal format.
For example,
-.Li 0x3.24p+0 , 0x6.48p-1
+.Li 0x1.92p+1 , 0x3.24p+0 , 0x6.48p-1 ,
and
.Li 0xc.9p-2
are all equivalent.
Always use the proper secure idiom:
.Pp
.Dl "snprintf(buffer, sizeof(buffer), \*q%s\*q, string);"
+.Sh COMPATIBILITY
+The conversion formats
+.Cm \&%D , \&%O ,
+and
+.Cm %U
+are not standard and
+are provided only for backward compatibility.
+The effect of padding the
+.Cm %p
+format with zeros (either by the
+.Cm 0
+flag or by specifying a precision), and the benign effect (i.e., none)
+of the
+.Cm #
+flag on
+.Cm %n
+and
+.Cm %p
+conversions, as well as other
+nonsensical combinations such as
+.Cm %Ld ,
+are not standard; such combinations
+should be avoided.
.Sh ERRORS
In addition to the errors documented for the
.Xr write 2
.El
.Sh SEE ALSO
.Xr printf 1 ,
-.Xr fmtcheck 3 ,
.Xr printf_l 3 ,
+.Xr fmtcheck 3 ,
.Xr scanf 3 ,
.Xr setlocale 3 ,
.Xr stdarg 3 ,
and
.Fn vsnprintf
functions conform to
-.St -isoC-99 .
+.St -isoC-99 ,
+while
+.Fn dprintf
+and
+.Fn vdprintf
+conform to
+.St -p1003.1-2008 .
.Sh HISTORY
The functions
.Fn asprintf
.An Todd C. Miller Aq Todd.Miller@courtesan.com
for
.Ox 2.3 .
-.Sh BUGS
-The conversion formats
-.Cm \&%D , \&%O ,
-and
-.Cm %U
-are not standard and
-are provided only for backward compatibility.
-The effect of padding the
-.Cm %p
-format with zeros (either by the
-.Cm 0
-flag or by specifying a precision), and the benign effect (i.e., none)
-of the
-.Cm #
-flag on
-.Cm %n
+The
+.Fn dprintf
and
-.Cm %p
-conversions, as well as other
-nonsensical combinations such as
-.Cm %Ld ,
-are not standard; such combinations
-should be avoided.
-.Pp
+.Fn vdprintf
+functions were added in
+.Fx 8.0 .
+.Sh BUGS
The
.Nm
family of functions do not correctly handle multibyte characters in the
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD: src/lib/libc/stdio/printf.3,v 1.58 2004/10/16 16:00:01 stefanf Exp $
.\"
-.Dd March 11, 2005
+.Dd December 15, 2009
.Dt PRINTF_L 3
.Os
.Sh NAME
.Nm asprintf_l ,
+.Nm dprintf_l ,
.Nm fprintf_l ,
.Nm printf_l ,
.Nm snprintf_l ,
.Nm sprintf_l ,
.Nm vasprintf_l ,
+.Nm vdprintf_l ,
.Nm vfprintf_l ,
.Nm vprintf_l ,
.Nm vsnprintf_l ,
.Fa ...
.Fc
.Ft int
+.Fo dprintf_l
+.Fa "int fd"
+.Fa "locale_t loc"
+.Fa "const char * restrict format"
+.Fa ...
+.Fc
+.Ft int
.Fo fprintf_l
.Fa "FILE * restrict stream"
.Fa "locale_t loc"
.Fa "va_list ap"
.Fc
.Ft int
+.Fo vdprintf_l
+.Fa "int fd"
+.Fa "locale_t loc"
+.Fa "const char * restrict format"
+.Fa "va_list ap"
+.Fc
+.Ft int
.Fo vfprintf_l
.Fa "FILE * restrict stream"
.Fa "locale_t loc"
.Sh DESCRIPTION
The
.Fn printf_l ,
+.Fn dprintf_l ,
.Fn fprintf_l ,
.Fn sprintf_l ,
.Fn snprintf_l ,
.Fn asprintf_l ,
.Fn vprintf_l ,
+.Fn vdprintf_l ,
.Fn vfprintf_l ,
.Fn vsprintf_l ,
.Fn vsnprintf_l ,
.Fn vasprintf_l
functions are extended locale versions of the
.Fn printf ,
+.Fn dprintf ,
.Fn fprintf ,
.Fn sprintf ,
.Fn snprintf ,
.Fn asprintf ,
.Fn vprintf ,
+.Fn vdprintf ,
.Fn vfprintf ,
.Fn vsprintf ,
.Fn vsnprintf ,
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ *
+ * $FreeBSD: src/lib/libc/stdio/printfcommon.h,v 1.4 2009/01/22 08:14:28 das Exp $
+ */
+
+/*
+ * This file defines common routines used by both printf and wprintf.
+ * You must define CHAR to either char or wchar_t prior to including this.
+ */
+
+
+#ifndef NO_FLOATING_POINT
+
+#define dtoa __dtoa
+#define freedtoa __freedtoa
+
+#include <float.h>
+#include <math.h>
+#include "floatio.h"
+#include "gdtoa.h"
+
+#define DEFPREC 6
+
+static int exponent(CHAR *, int, CHAR);
+
+#endif /* !NO_FLOATING_POINT */
+
+static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
+static CHAR *__ultoa(u_long, CHAR *, int, int, const char *);
+
+#define NIOV 8
+struct io_state {
+ FILE *fp;
+ struct __suio uio; /* output information: summary */
+ struct __siov iov[NIOV];/* ... and individual io vectors */
+};
+
+static inline void
+io_init(struct io_state *iop, FILE *fp)
+{
+
+ iop->uio.uio_iov = iop->iov;
+ iop->uio.uio_resid = 0;
+ iop->uio.uio_iovcnt = 0;
+ iop->fp = fp;
+}
+
+/*
+ * WARNING: The buffer passed to io_print() is not copied immediately; it must
+ * remain valid until io_flush() is called.
+ */
+static inline int
+io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t loc)
+{
+
+ iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr;
+ iop->iov[iop->uio.uio_iovcnt].iov_len = len;
+ iop->uio.uio_resid += len;
+ if (++iop->uio.uio_iovcnt >= NIOV)
+ return (__sprint(iop->fp, loc, &iop->uio));
+ else
+ return (0);
+}
+
+/*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+static const CHAR blanks[PADSIZE] =
+{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+static const CHAR zeroes[PADSIZE] =
+{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+/*
+ * Pad with blanks or zeroes. 'with' should point to either the blanks array
+ * or the zeroes array.
+ */
+static inline int
+io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, locale_t loc)
+{
+ int n;
+
+ while (howmany > 0) {
+ n = (howmany >= PADSIZE) ? PADSIZE : howmany;
+ if (io_print(iop, with, n, loc))
+ return (-1);
+ howmany -= n;
+ }
+ return (0);
+}
+
+/*
+ * Print exactly len characters of the string spanning p to ep, truncating
+ * or padding with 'with' as necessary.
+ */
+static inline int
+io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
+ int len, const CHAR * __restrict with, locale_t loc)
+{
+ int p_len;
+
+ p_len = ep - p;
+ if (p_len > len)
+ p_len = len;
+ if (p_len > 0) {
+ if (io_print(iop, p, p_len, loc))
+ return (-1);
+ } else {
+ p_len = 0;
+ }
+ return (io_pad(iop, len - p_len, with, loc));
+}
+
+static inline int
+io_flush(struct io_state *iop, locale_t loc)
+{
+
+ return (__sprint(iop->fp, loc, &iop->uio));
+}
+
+/*
+ * Convert an unsigned long to ASCII for printf purposes, returning
+ * a pointer to the first character of the string representation.
+ * Octal numbers can be forced to have a leading zero; hex numbers
+ * use the given digits.
+ */
+static CHAR *
+__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ long sval;
+
+ /*
+ * Handle the three cases separately, in the hope of getting
+ * better/faster code.
+ */
+ switch (base) {
+ case 10:
+ if (val < 10) { /* many numbers are 1 digit */
+ *--cp = to_char(val);
+ return (cp);
+ }
+ /*
+ * On many machines, unsigned arithmetic is harder than
+ * signed arithmetic, so we do at most one unsigned mod and
+ * divide; this is sufficient to reduce the range of
+ * the incoming value to where signed arithmetic works.
+ */
+ if (val > LONG_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default: /* oops */
+ LIBC_ABORT("__ultoa: invalid base=%d", base);
+ }
+ return (cp);
+}
+
+/* Identical to __ultoa, but for intmax_t. */
+static CHAR *
+__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ intmax_t sval;
+
+ /* quick test for small values; __ultoa is typically much faster */
+ /* (perhaps instead we should run until small, then call __ultoa?) */
+ if (val <= ULONG_MAX)
+ return (__ultoa((u_long)val, endp, base, octzero, xdigs));
+ switch (base) {
+ case 10:
+ if (val < 10) {
+ *--cp = to_char(val % 10);
+ return (cp);
+ }
+ if (val > INTMAX_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default:
+ LIBC_ABORT("__ujtoa: invalid base=%d", base);
+ }
+ return (cp);
+}
+
+#ifndef NO_FLOATING_POINT
+
+static int
+exponent(CHAR *p0, int exp, CHAR fmtch)
+{
+ CHAR *p, *t;
+ CHAR expbuf[MAXEXPDIG];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + MAXEXPDIG;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
+ }
+ else {
+ /*
+ * Exponents for decimal floating point conversions
+ * (%[eEgG]) must be at least two characters long,
+ * whereas exponents for hexadecimal conversions can
+ * be only one character long.
+ */
+ if (fmtch == 'e' || fmtch == 'E')
+ *p++ = '0';
+ *p++ = to_char(exp);
+ }
+ return (p - p0);
+}
+
+#endif /* !NO_FLOATING_POINT */
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ *
+ * $FreeBSD: src/lib/libc/stdio/printflocal.h,v 1.3 2009/03/02 04:07:58 das Exp $
+ */
+
+/*
+ * Defining here VECTORS for all files that include this header (<rdar://problem/8466056>)
+ */
+#define VECTORS
+
+/*
+ * Flags used during conversion.
+ */
+#define ALT 0x001 /* alternate form */
+#define LADJUST 0x004 /* left adjustment */
+#define LONGDBL 0x008 /* long double */
+#define LONGINT 0x010 /* long integer */
+#define LLONGINT 0x020 /* long long integer */
+#define SHORTINT 0x040 /* short integer */
+#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
+#define FPT 0x100 /* Floating point number */
+#define GROUPING 0x200 /* use grouping ("'" flag) */
+ /* C99 additional size modifiers: */
+#define SIZET 0x400 /* size_t */
+#define PTRDIFFT 0x800 /* ptrdiff_t */
+#define INTMAXT 0x1000 /* intmax_t */
+#define CHARINT 0x2000 /* print char using int format */
+#ifdef VECTORS
+#define VECTOR 0x4000 /* Altivec or SSE vector */
+#endif /* VECTORS */
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) ((unsigned)to_digit(c) <= 9)
+#define to_char(n) ((n) + '0')
+
+/* Size of the static argument table. */
+#define STATIC_ARG_TBL_SIZE 8
+
+#ifdef VECTORS
+typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
+#ifdef __SSE2__
+#define V64TYPE
+#endif /* __SSE2__ */
+#endif /* VECTORS */
+
+union arg {
+ int intarg;
+ u_int uintarg;
+ long longarg;
+ u_long ulongarg;
+ long long longlongarg;
+ unsigned long long ulonglongarg;
+ ptrdiff_t ptrdiffarg;
+ size_t sizearg;
+ intmax_t intmaxarg;
+ uintmax_t uintmaxarg;
+ void *pvoidarg;
+ char *pchararg;
+ signed char *pschararg;
+ short *pshortarg;
+ int *pintarg;
+ long *plongarg;
+ long long *plonglongarg;
+ ptrdiff_t *pptrdiffarg;
+ ssize_t *pssizearg;
+ intmax_t *pintmaxarg;
+#ifndef NO_FLOATING_POINT
+ double doublearg;
+ long double longdoublearg;
+#endif
+ wint_t wintarg;
+ wchar_t *pwchararg;
+#ifdef VECTORS
+ VECTORTYPE vectorarg;
+ unsigned char vuchararg[16];
+ signed char vchararg[16];
+ unsigned short vushortarg[8];
+ signed short vshortarg[8];
+ unsigned int vuintarg[4];
+ signed int vintarg[4];
+ float vfloatarg[4];
+#ifdef V64TYPE
+ double vdoublearg[2];
+ unsigned long long vulonglongarg[2];
+ long long vlonglongarg[2];
+#endif /* V64TYPE */
+#endif /* VECTORS */
+};
+
+/* Handle positional parameters. */
+int __find_arguments(const char *, va_list, union arg **);
+int __find_warguments(const wchar_t *, va_list, union arg **);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/putc.3,v 1.15 2004/03/17 12:46:17 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/putc.3,v 1.16 2007/01/09 00:28:07 imp Exp $
.\"
.Dd January 10, 2003
.Dt PUTC 3
* 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.
static char sccsid[] = "@(#)puts.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/puts.c,v 1.10 2004/03/10 09:15:38 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/puts.c,v 1.11 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/putwc.3,v 1.7 2004/03/16 13:30:11 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/putwc.3,v 1.8 2007/01/09 00:28:07 imp Exp $
.\"
.Dd March 3, 2004
.Dt PUTWC 3
* 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.
static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/refill.c,v 1.18 2002/08/13 09:30:41 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/refill.c,v 1.20 2008/04/17 22:17:54 jhb Exp $");
#include "namespace.h"
#include <errno.h>
if (HASUB(fp)) {
FREEUB(fp);
if ((fp->_r = fp->_ur) != 0) {
- fp->_p = fp->_extra->_up;
+ fp->_p = fp->_up;
return (0);
}
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)remove.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/remove.3,v 1.9 2001/10/01 16:08:59 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/remove.3,v 1.10 2007/01/09 00:28:07 imp Exp $
.\"
.Dd June 4, 1993
.Dt REMOVE 3
* 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.
static char sccsid[] = "@(#)rewind.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/rewind.c,v 1.11 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/rewind.c,v 1.12 2007/01/09 00:28:07 imp Exp $");
#include "namespace.h"
#include <errno.h>
* 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.
static char sccsid[] = "@(#)scanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/scanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/scanf.c,v 1.13 2007/01/09 00:28:07 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/stdio/scanf.3,v 1.24 2003/06/28 09:03:25 das Exp $
+.\" $FreeBSD: src/lib/libc/stdio/scanf.3,v 1.25 2007/01/09 00:28:07 imp Exp $
.\"
.Dd January 4, 2003
.Dt SCANF 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)setbuf.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/setbuf.3,v 1.15 2004/08/24 21:48:21 alfred Exp $
+.\" $FreeBSD: src/lib/libc/stdio/setbuf.3,v 1.17 2007/01/09 00:28:07 imp Exp $
.\"
.Dd June 4, 1993
.Dt SETBUF 3
this buffer will be used instead of the current buffer.
If
.Fa buf
-is not NULL, it is the caller's responsibility to
+is not
+.Dv NULL ,
+it is the caller's responsibility to
.Xr free 3
this buffer after closing the stream.
(If the
* 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.
static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/snprintf.c,v 1.20 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/snprintf.c,v 1.22 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
int
snprintf(char * __restrict str, size_t n, char const * __restrict fmt, ...)
{
- size_t on;
int ret;
va_list ap;
- FILE f;
- struct __sFILEX ext;
- on = n;
- if (n != 0)
- n--;
- if (n > INT_MAX)
- n = INT_MAX;
va_start(ap, fmt);
- f._file = -1;
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = n;
- f._extra = &ext;
- INITEXTRA(&f);
- ret = __vfprintf(&f, __current_locale(), fmt, ap);
- if (on > 0)
- *f._p = '\0';
+ ret = vsnprintf_l(str, n, __current_locale(), fmt, ap);
va_end(ap);
return (ret);
}
snprintf_l(char * __restrict str, size_t n, locale_t loc,
char const * __restrict fmt, ...)
{
- size_t on;
int ret;
va_list ap;
- FILE f;
- struct __sFILEX ext;
- NORMALIZE_LOCALE(loc);
- on = n;
- if (n != 0)
- n--;
- if (n > INT_MAX)
- n = INT_MAX;
va_start(ap, fmt);
- f._file = -1;
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = n;
- f._extra = &ext;
- INITEXTRA(&f);
- ret = __vfprintf(&f, loc, fmt, ap);
- if (on > 0)
- *f._p = '\0';
+ ret = vsnprintf_l(str, n, loc, fmt, ap);
va_end(ap);
return (ret);
}
* 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.
static char sccsid[] = "@(#)sprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/sprintf.c,v 1.14 2002/09/06 11:23:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/sprintf.c,v 1.16 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
{
int ret;
va_list ap;
- FILE f;
- struct __sFILEX ext;
- f._file = -1;
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = INT_MAX;
- f._extra = &ext;
- INITEXTRA(&f);
va_start(ap, fmt);
- ret = __vfprintf(&f, __current_locale(), fmt, ap);
+ ret = vsprintf_l(str, __current_locale(), fmt, ap);
va_end(ap);
- *f._p = 0;
return (ret);
}
{
int ret;
va_list ap;
- FILE f;
- struct __sFILEX ext;
- NORMALIZE_LOCALE(loc);
- f._file = -1;
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = INT_MAX;
- f._extra = &ext;
- INITEXTRA(&f);
va_start(ap, fmt);
- ret = __vfprintf(&f, loc, fmt, ap);
+ ret = vsprintf_l(str, loc, fmt, ap);
va_end(ap);
- *f._p = 0;
return (ret);
}
* 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.
static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/sscanf.c,v 1.11 2002/10/12 16:13:41 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/sscanf.c,v 1.13 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
#include <stdarg.h>
#include "local.h"
-static int eofread(void *, char *, int);
-
-/* ARGSUSED */
-static int
-eofread(cookie, buf, len)
- void *cookie;
- char *buf;
- int len;
-{
-
- return (0);
-}
-
int
sscanf(const char * __restrict str, char const * __restrict fmt, ...)
{
int ret;
va_list ap;
- struct __sFILEX extra;
- FILE f;
- f._file = -1;
- f._flags = __SRD;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._r = strlen(str);
- f._read = eofread;
- f._ub._base = NULL;
- f._lb._base = NULL;
- f._extra = &extra;
- INITEXTRA(&f);
va_start(ap, fmt);
- ret = __svfscanf_l(&f, __current_locale(), fmt, ap);
+ ret = vsscanf_l(str, __current_locale(), fmt, ap);
va_end(ap);
return (ret);
}
{
int ret;
va_list ap;
- struct __sFILEX extra;
- FILE f;
- NORMALIZE_LOCALE(loc);
- f._file = -1;
- f._flags = __SRD;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._r = strlen(str);
- f._read = eofread;
- f._ub._base = NULL;
- f._lb._base = NULL;
- f._extra = &extra;
- INITEXTRA(&f);
va_start(ap, fmt);
- ret = __svfscanf_l(&f, loc, fmt, ap);
+ ret = vsscanf_l(str, loc, fmt, ap);
va_end(ap);
return (ret);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)stdio.3 8.7 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/stdio/stdio.3,v 1.26 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdio/stdio.3,v 1.30 2009/03/04 03:38:51 das Exp $
.\"
-.Dd January 10, 2003
+.Dd March 3, 2009
.Dt STDIO 3
.Os
.Sh NAME
.Xr read 2 ,
.Xr write 2 ,
.Xr compat 5
-.Sh BUGS
-The standard buffered functions do not interact well with certain other
-library and system functions, especially
-.Xr vfork 2 .
.Sh STANDARDS
The
.Nm
.It ""
.It "getc get next character or word from input stream"
.It "getchar get next character or word from input stream"
+.It "getdelim get a line from a stream"
+.It "getline get a line from a stream"
.It "gets get a line from a stream"
.It "getw get next character or word from input stream"
.It "getwc get next wide character from input stream"
.It ""
.It "wprintf formatted wide character output conversion"
.El
+.Sh BUGS
+The standard buffered functions do not interact well with certain other
+library and system functions, especially
+.Xr vfork 2 .
* 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.
static char sccsid[] = "@(#)tempnam.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/tempnam.c,v 1.10 2002/03/22 21:53:04 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/tempnam.c,v 1.11 2007/01/09 00:28:07 imp Exp $");
#include <sys/param.h>
#include <errno.h>
}
#endif /* __DARWIN_UNIX03 */
f = _PATH_TMP;
-#if __DARWIN_UNIX03
- if (access(f, W_OK) < 0) {
- f = "./"; /* directory inaccessible */
- if (access(f, W_OK) < 0) {
- return(NULL);
- }
- }
-#endif /* __DARWIN_UNIX03 */
(void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
if ((f = _mktemp(name))) {
return(f);
+++ /dev/null
-./tmpnam.c
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tmpnam.c 8.3 (Berkeley) 3/28/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/tmpnam.c,v 1.6 2007/01/09 00:28:07 imp Exp $");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+__warn_references(tmpnam,
+ "warning: tmpnam() possibly used unsafely; consider using mkstemp()");
+
+extern char *_mktemp(char *);
+
+static char *tmpnam_buf = NULL;
+static pthread_once_t tmpnam_buf_control = PTHREAD_ONCE_INIT;
+
+static void tmpnam_buf_allocate(void)
+{
+ tmpnam_buf = malloc(L_tmpnam);
+}
+
+char *
+tmpnam(s)
+ char *s;
+{
+ static u_long tmpcount;
+
+ if (s == NULL) {
+ if (pthread_once(&tmpnam_buf_control, tmpnam_buf_allocate)
+ || !tmpnam_buf) {
+ return NULL;
+ }
+ s = tmpnam_buf;
+ }
+ (void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXX", P_tmpdir, tmpcount);
+ ++tmpcount;
+ return (_mktemp(s));
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)tmpnam.3 8.2 (Berkeley) 11/17/93
-.\" $FreeBSD: src/lib/libc/stdio/tmpnam.3,v 1.16 2004/06/21 19:38:25 mpp Exp $
+.\" $FreeBSD: src/lib/libc/stdio/tmpnam.3,v 1.20 2007/03/16 21:46:24 maxim Exp $
.\"
.Dd November 12, 2008
.Dt TMPFILE 3
.In stdio.h
.Ft FILE *
.Fo tmpfile
-.Fa void
+.Fa "void"
.Fc
.Ft char *
.Fo tmpnam
.Dv NULL
pointer
on error.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev TMPDIR
+.Pf [ Fn tempnam
+only]
+If set,
+the directory in which the temporary file is stored.
+.Ev TMPDIR
+is ignored for processes
+for which
+.Xr issetugid 2
+is true.
+.El
+.Sh COMPATIBILITY
+These interfaces are provided from System V and
+.Tn ANSI
+compatibility only.
+.Pp
+Most historic implementations of these functions provide
+only a limited number of possible temporary file names
+(usually 26)
+before file names will start being recycled.
+System V implementations of these functions
+(and of
+.Xr mktemp 3 )
+use the
+.Xr access 2
+system call to determine whether or not the temporary file
+may be created.
+This has obvious ramifications for setuid or setgid programs,
+complicating the portable use of these interfaces in such programs.
+.Pp
+The
+.Fn tmpfile
+interface should not be used in software expected to be used on other systems
+if there is any possibility that the user does not wish the temporary file to
+be publicly readable and writable.
.Sh ERRORS
The
.Fn tmpfile
be used in place of these functions.
(See
the FSA.)
-.Sh COMPATIBILITY
-These interfaces are provided from System V and
-.Tn ANSI
-compatibility only.
-.Pp
-Most historic implementations of these functions provide
-only a limited number of possible temporary file names
-(usually 26)
-before file names will start being recycled.
-System V implementations of these functions
-(and of
-.Xr mktemp 3 )
-use the
-.Xr access 2
-system call to determine whether or not the temporary file
-may be created.
-This has obvious ramifications for setuid or setgid programs,
-complicating the portable use of these interfaces in such programs.
-.Pp
-The
-.Fn tmpfile
-interface should not be used in software expected to be used on other systems
-if there is any possibility that the user does not wish the temporary file to
-be publicly readable and writable.
.Sh LEGACY DESCRIPTION
In legacy mode, the order directories are tried by the
.Fn tempnam
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ungetc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/ungetc.3,v 1.13 2002/10/10 04:12:40 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/ungetc.3,v 1.14 2007/01/09 00:28:07 imp Exp $
.\"
.Dd June 4, 1993
.Dt UNGETC 3
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/ungetwc.c,v 1.9 2004/07/20 08:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/ungetwc.c,v 1.11 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
#include "namespace.h"
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
if (wc == WEOF)
return (WEOF);
- if ((len = loc->__lc_ctype->__wcrtomb(buf, wc, &fp->_extra->mbstate, loc)) == (size_t)-1) {
+ if ((len = loc->__lc_ctype->__wcrtomb(buf, wc, &fp->_mbstate, loc)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ungetc.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/ungetwc.3,v 1.5 2004/03/16 13:30:11 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/ungetwc.3,v 1.6 2007/01/09 00:28:07 imp Exp $
.\"
.Dd March 3, 2004
.Dt UNGETWC 3
+++ /dev/null
-./unlocked.c
\ No newline at end of file
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.18 2002/09/26 13:11:24 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.19 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
#include "local.h"
int
-vasprintf(str, fmt, ap)
+vasprintf_l(str, loc, fmt, ap)
char **str;
+ locale_t loc;
const char *fmt;
__va_list ap;
{
int ret;
FILE f;
struct __sFILEX ext;
-
+ f._extra = &ext;
+ INITEXTRA(&f);
+
+ NORMALIZE_LOCALE(loc);
f._file = -1;
f._flags = __SWR | __SSTR | __SALC;
f._bf._base = f._p = (unsigned char *)malloc(128);
return (-1);
}
f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
- ret = __vfprintf(&f, __current_locale(), fmt, ap);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
+ ret = __vfprintf(&f, loc, fmt, ap);
if (ret < 0) {
free(f._bf._base);
*str = NULL;
}
int
-vasprintf_l(str, loc, fmt, ap)
+vasprintf(str, fmt, ap)
char **str;
- locale_t loc;
const char *fmt;
__va_list ap;
{
- int ret;
- FILE f;
- struct __sFILEX ext;
-
- NORMALIZE_LOCALE(loc);
- f._file = -1;
- f._flags = __SWR | __SSTR | __SALC;
- f._bf._base = f._p = (unsigned char *)malloc(128);
- if (f._bf._base == NULL) {
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
- ret = __vfprintf(&f, loc, fmt, ap);
- if (ret < 0) {
- free(f._bf._base);
- *str = NULL;
- errno = ENOMEM;
- return (-1);
- }
- *f._p = '\0';
- *str = (char *)f._bf._base;
- return (ret);
+ return vasprintf_l(str, __current_locale(), fmt, ap);
}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vdprintf.c,v 1.1 2009/03/04 03:38:51 das Exp $");
+
+#include "xlocale_private.h"
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "un-namespace.h"
+
+#include "local.h"
+
+int
+vdprintf_l(int fd, locale_t loc, const char * __restrict fmt, va_list ap)
+{
+ FILE f;
+ unsigned char buf[BUFSIZ];
+ int ret;
+ struct __sFILEX ext;
+ f._extra = &ext;
+ INITEXTRA(&f);
+
+ NORMALIZE_LOCALE(loc);
+
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+ return (EOF);
+ }
+
+ f._p = buf;
+ f._w = sizeof(buf);
+ f._flags = __SWR;
+ f._file = fd;
+ f._cookie = &f;
+ f._write = __swrite;
+ f._bf._base = buf;
+ f._bf._size = sizeof(buf);
+ f._orientation = 0;
+ bzero(&f._mbstate, sizeof(f._mbstate));
+
+ if ((ret = __vfprintf(&f, loc, fmt, ap)) < 0)
+ return (ret);
+
+ return (__fflush(&f) ? EOF : ret);
+}
+
+int
+vdprintf(int fd, const char * __restrict fmt, va_list ap) {
+ return vdprintf_l(fd, __current_locale(), fmt, ap);
+}
* 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.
static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.68 2004/08/26 06:25:28 des Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $");
#include "xlocale_private.h"
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#if 0 // xprintf pending API review
+#include <printf.h>
+#endif
#include <errno.h>
#include <stdarg.h>
#include "libc_private.h"
#include "local.h"
#include "fvwrite.h"
+#include "printflocal.h"
-#ifdef VECTORS
-typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
-#ifdef __SSE2__
-#define V64TYPE
-#endif /* __SSE2__ */
-#endif /* VECTORS */
+static int __sprint(FILE *, locale_t, struct __suio *);
+static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
+static char *__wcsconv(wchar_t *, int, locale_t);
-union arg {
- int intarg;
- u_int uintarg;
- long longarg;
- u_long ulongarg;
- long long longlongarg;
- unsigned long long ulonglongarg;
- ptrdiff_t ptrdiffarg;
- size_t sizearg;
- intmax_t intmaxarg;
- uintmax_t uintmaxarg;
- void *pvoidarg;
- char *pchararg;
- signed char *pschararg;
- short *pshortarg;
- int *pintarg;
- long *plongarg;
- long long *plonglongarg;
- ptrdiff_t *pptrdiffarg;
- size_t *psizearg;
- intmax_t *pintmaxarg;
-#ifndef NO_FLOATING_POINT
- double doublearg;
- long double longdoublearg;
-#endif
- wint_t wintarg;
- wchar_t *pwchararg;
-#ifdef VECTORS
- VECTORTYPE vectorarg;
- unsigned char vuchararg[16];
- signed char vchararg[16];
- unsigned short vushortarg[8];
- signed short vshortarg[8];
- unsigned int vuintarg[4];
- signed int vintarg[4];
- float vfloatarg[4];
-#ifdef V64TYPE
- double vdoublearg[2];
- unsigned long long vulonglongarg[2];
- long long vlonglongarg[2];
-#endif /* V64TYPE */
-#endif /* VECTORS */
+__private_extern__ const char *__fix_nogrouping(const char *);
+
+#define CHAR char
+#include "printfcommon.h"
+
+struct grouping_state {
+ char *thousands_sep; /* locale-specific thousands separator */
+ int thousep_len; /* length of thousands_sep */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
};
/*
- * Type ids for argument type table.
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of bytes that will be needed.
*/
-enum typeid {
- T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
- T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
- T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
- T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
-#ifdef VECTORS
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
-#else /* ! VECTORS */
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-#endif /* VECTORS */
-};
+static int
+grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
+{
+ struct lconv *locale;
-static int __sprint(FILE *, struct __suio *);
-static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
-static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char,
- const char *);
-static char *__ultoa(u_long, char *, int, int, const char *, int, char,
- const char *);
-static char *__wcsconv(wchar_t *, int, locale_t);
-static void __find_arguments(const char *, va_list, union arg **);
-static void __grow_type_table(int, enum typeid **, int *);
+ locale = localeconv_l(loc);
+ gs->grouping = __fix_nogrouping(locale->grouping);
+ gs->thousands_sep = locale->thousands_sep;
+ gs->thousep_len = strlen(gs->thousands_sep);
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
+}
+
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep, locale_t loc)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, gs->thousands_sep, gs->thousep_len, loc))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
/*
* Flush out all the vectors defined by the given uio,
* then reset it so that it can be reused.
*/
static int
-__sprint(FILE *fp, struct __suio *uio)
+__sprint(FILE *fp, locale_t loc __unused, struct __suio *uio)
{
int err;
int ret;
FILE fake;
unsigned char buf[BUFSIZ];
+ struct __sFILEX ext;
+ fake._extra = &ext;
+ INITEXTRA(&fake);
+
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
/* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
- fake._extra = fp->_extra;
+ fake._orientation = fp->_orientation;
+ fake._mbstate = fp->_mbstate;
/* set up the buffer */
fake._bf._base = fake._p = buf;
return (ret);
}
-/*
- * Macros for converting digits to letters and vice versa
- */
-#define to_digit(c) ((c) - '0')
-#define is_digit(c) ((unsigned)to_digit(c) <= 9)
-#define to_char(n) ((n) + '0')
-
-/*
- * Convert an unsigned long to ASCII for printf purposes, returning
- * a pointer to the first character of the string representation.
- * Octal numbers can be forced to have a leading zero; hex numbers
- * use the given digits.
- */
-static char *
-__ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- char *cp = endp;
- long sval;
- int ndig;
-
- /*
- * Handle the three cases separately, in the hope of getting
- * better/faster code.
- */
- switch (base) {
- case 10:
- if (val < 10) { /* many numbers are 1 digit */
- *--cp = to_char(val);
- return (cp);
- }
- ndig = 0;
- /*
- * On many machines, unsigned arithmetic is harder than
- * signed arithmetic, so we do at most one unsigned mod and
- * divide; this is sufficient to reduce the range of
- * the incoming value to where signed arithmetic works.
- */
- if (val > LONG_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && ndig == *grp && *grp != CHAR_MAX
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default: /* oops */
- LIBC_ABORT("base = %d", base);
- }
- return (cp);
-}
-
-/* Identical to __ultoa, but for intmax_t. */
-static char *
-__ujtoa(uintmax_t val, char *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- char *cp = endp;
- intmax_t sval;
- int ndig;
-
- /* quick test for small values; __ultoa is typically much faster */
- /* (perhaps instead we should run until small, then call __ultoa?) */
- if (val <= ULONG_MAX)
- return (__ultoa((u_long)val, endp, base, octzero, xdigs,
- needgrp, thousep, grp));
- switch (base) {
- case 10:
- if (val < 10) {
- *--cp = to_char(val % 10);
- return (cp);
- }
- ndig = 0;
- if (val > INTMAX_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && *grp != CHAR_MAX && ndig == *grp
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default:
- LIBC_ABORT("base = %d", base);
- }
- return (cp);
-}
-
/*
* Convert a wide character string argument for the %ls format to a multibyte
- * string representation. ``prec'' specifies the maximum number of bytes
- * to output. If ``prec'' is greater than or equal to zero, we can't assume
- * that the wide char. string ends in a null character.
+ * string representation. If not -1, prec specifies the maximum number of
+ * bytes to output, and also means that we can't assume that the wide char.
+ * string ends is null-terminated.
*/
static char *
__wcsconv(wchar_t *wcsarg, int prec, locale_t loc)
mbstate_t mbs;
char buf[MB_LEN_MAX];
wchar_t *p;
- char *convbuf, *mbp;
- size_t clen = 0, nbytes;
+ char *convbuf;
+ size_t clen, nbytes;
- /*
- * Determine the number of bytes to output and allocate space for
- * the output.
- */
- if (prec >= 0) {
- nbytes = 0;
- p = wcsarg;
- mbs = initial;
- for (;;) {
- clen = wcrtomb_l(buf, *p++, &mbs, loc);
- if (clen == 0 || clen == (size_t)-1 ||
- nbytes + clen > prec)
- break;
- nbytes += clen;
- }
- } else {
+ /* Allocate space for the maximum number of bytes we could output. */
+ if (prec < 0) {
p = wcsarg;
mbs = initial;
nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
if (nbytes == (size_t)-1)
return (NULL);
+ } else {
+ /*
+ * Optimisation: if the output precision is small enough,
+ * just allocate enough memory for the maximum instead of
+ * scanning the string.
+ */
+ if (prec < 128)
+ nbytes = prec;
+ else {
+ nbytes = 0;
+ p = wcsarg;
+ mbs = initial;
+ for (;;) {
+ clen = wcrtomb_l(buf, *p++, &mbs, loc);
+ if (clen == 0 || clen == (size_t)-1 ||
+ nbytes + clen > prec)
+ break;
+ nbytes += clen;
+ }
+ }
}
if ((convbuf = malloc(nbytes + 1)) == NULL)
return (NULL);
- /*
- * Fill the output buffer with the multibyte representations of as
- * many wide characters as will fit.
- */
- mbp = convbuf;
+ /* Fill the output buffer. */
p = wcsarg;
mbs = initial;
- while (mbp - convbuf < nbytes) {
- clen = wcrtomb_l(mbp, *p++, &mbs, loc);
- if (clen == 0 || clen == (size_t)-1)
- break;
- mbp += clen;
- }
- if (clen == (size_t)-1) {
+ if ((nbytes = wcsrtombs_l(convbuf, (const wchar_t **)&p,
+ nbytes, &mbs, loc)) == (size_t)-1) {
free(convbuf);
return (NULL);
}
- *mbp = '\0';
-
+ convbuf[nbytes] = '\0';
return (convbuf);
}
/*
* MT-safe version
*/
-__private_extern__ const char *__fix_nogrouping(const char *);
-
int
-vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
+vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
{
int ret;
+ NORMALIZE_LOCALE(loc);
FLOCKFILE(fp);
- ret = __vfprintf(fp, __current_locale(), fmt0, ap);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, loc, fmt0, ap);
+ else
+ ret = __vfprintf(fp, loc, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
int
-vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0,
- va_list ap)
+vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
{
- int ret;
-
- NORMALIZE_LOCALE(loc);
- FLOCKFILE(fp);
- ret = __vfprintf(fp, loc, fmt0, ap);
- FUNLOCKFILE(fp);
- return (ret);
+ return vfprintf_l(fp, __current_locale(), fmt0, ap);
}
-#ifndef NO_FLOATING_POINT
-
-#define dtoa __dtoa
-#define freedtoa __freedtoa
-
-#include <float.h>
-#include <math.h>
-#include "floatio.h"
-#include "gdtoa.h"
-
-#define DEFPREC 6
-
-static int exponent(char *, int, int);
-
-#endif /* !NO_FLOATING_POINT */
-
/*
* The size of the buffer we use as scratch space for integer
- * conversions, among other things. Technically, we would need the
- * most space for base 10 conversions with thousands' grouping
- * characters between each pair of digits. 100 bytes is a
- * conservative overestimate even for a 128-bit uintmax_t.
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
*/
-#define BUF 100
-
-#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
-
-/*
- * Flags used during conversion.
- */
-#define ALT 0x001 /* alternate form */
-#define LADJUST 0x004 /* left adjustment */
-#define LONGDBL 0x008 /* long double */
-#define LONGINT 0x010 /* long integer */
-#define LLONGINT 0x020 /* long long integer */
-#define SHORTINT 0x040 /* short integer */
-#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
-#define FPT 0x100 /* Floating point number */
-#define GROUPING 0x200 /* use grouping ("'" flag) */
- /* C99 additional size modifiers: */
-#define SIZET 0x400 /* size_t */
-#define PTRDIFFT 0x800 /* ptrdiff_t */
-#define INTMAXT 0x1000 /* intmax_t */
-#define CHARINT 0x2000 /* print char using int format */
-#ifdef VECTORS
-#define VECTOR 0x4000 /* Altivec or SSE vector */
-#endif /* VECTORS */
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
/*
* Non-MT-safe version
int ch; /* character from fmt */
int n, n2; /* handy integer (short term usage) */
char *cp; /* handy char pointer (short term usage) */
- struct __siov *iovp; /* for PRINT macro */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
char sign; /* sign prefix (' ', '+', '-', or \0) */
- char thousands_sep; /* locale specific thousands separator */
- const char *grouping; /* locale specific numeric grouping rules */
+ struct grouping_state gs; /* thousands' grouping info */
+
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
* F: at least two digits for decimal, at least one digit for hex
*/
char *decimal_point; /* locale specific decimal point */
+ int decpt_len; /* length of decimal_point */
int signflag; /* true if float is negative */
union { /* floating point arguments %[aAeEfFgG] */
double dbl;
char expchar; /* exponent character: [eEpP\0] */
char *dtoaend; /* pointer to end of converted digits */
int expsize; /* character count for expstr */
- int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
char *dtoaresult; /* buffer allocated by dtoa */
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
#endif
#ifdef VECTORS
union arg vval; /* Vector argument. */
int size; /* size of converted field or string */
int prsize; /* max size of printed field */
const char *xdigs; /* digits for %[xX] conversion */
-#define NIOV 8
- struct __suio uio; /* output information: summary */
- struct __siov iov[NIOV];/* ... and individual io vectors */
+ struct io_state io; /* I/O buffering state */
char buf[BUF]; /* buffer with space for digits of uintmax_t */
char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
union arg *argtable; /* args, built due to positional arg */
va_list orgap; /* original argument pointer */
char *convbuf; /* wide to multibyte conversion result */
- /*
- * Choose PADSIZE to trade efficiency vs. size. If larger printf
- * fields occur frequently, increase PADSIZE and make the initialisers
- * below longer.
- */
-#define PADSIZE 16 /* pad chunk size */
- static char blanks[PADSIZE] =
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static char zeroes[PADSIZE] =
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
-
static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF";
- /*
- * BEWARE, these `goto error' on error, and PAD uses `n'.
- */
+ /* BEWARE, these `goto error' on error. */
#define PRINT(ptr, len) { \
- iovp->iov_base = (ptr); \
- iovp->iov_len = (len); \
- uio.uio_resid += (len); \
- iovp++; \
- if (++uio.uio_iovcnt >= NIOV) { \
- if (__sprint(fp, &uio)) \
- goto error; \
- iovp = iov; \
- } \
+ if (io_print(&io, (ptr), (len), loc)) \
+ goto error; \
}
#define PAD(howmany, with) { \
- if ((n = (howmany)) > 0) { \
- while (n > PADSIZE) { \
- PRINT(with, PADSIZE); \
- n -= PADSIZE; \
- } \
- PRINT(with, n); \
- } \
+ if (io_pad(&io, (howmany), (with), loc)) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \
+ goto error; \
}
-#define PRINTANDPAD(p, ep, len, with) do { \
- n2 = (ep) - (p); \
- if (n2 > (len)) \
- n2 = (len); \
- if (n2 > 0) \
- PRINT((p), n2); \
- PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
-} while(0)
#define FLUSH() { \
- if (uio.uio_resid && __sprint(fp, &uio)) \
+ if (io_flush(&io, loc)) \
goto error; \
- uio.uio_iovcnt = 0; \
- iovp = iov; \
}
/*
#define UJARG() \
(flags&INTMAXT ? GETARG(uintmax_t) : \
flags&SIZET ? (uintmax_t)GETARG(size_t) : \
- flags&PTRDIFFT ? (uintmax_t)(unsigned)GETARG(ptrdiff_t) : \
+ flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
(uintmax_t)GETARG(unsigned long long))
/*
int hold = nextarg; \
if (argtable == NULL) { \
argtable = statargtable; \
- __find_arguments (fmt0, orgap, &argtable); \
+ if (__find_arguments (fmt0, orgap, &argtable)) { \
+ ret = EOF; \
+ goto error; \
+ } \
} \
nextarg = n2; \
val = GETARG (int); \
val = GETARG (int); \
}
- thousands_sep = '\0';
- grouping = NULL;
- convbuf = NULL;
-#ifndef NO_FLOATING_POINT
- dtoaresult = NULL;
- decimal_point = localeconv_l(loc)->decimal_point;
+#if 0 // xprintf pending API review
+ if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
+ __use_xprintf = 1;
+ if (__use_xprintf > 0)
+ return (__xvprintf(fp, loc, fmt0, ap));
#endif
+
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
if (prepwrite(fp) != 0) {
errno = EBADF;
}
ORIENT(fp, -1);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
- return (__sbprintf(fp, loc, fmt0, ap));
-
+ convbuf = NULL;
fmt = (char *)fmt0;
argtable = NULL;
nextarg = 1;
va_copy(orgap, ap);
- uio.uio_iov = iovp = iov;
- uio.uio_resid = 0;
- uio.uio_iovcnt = 0;
+ io_init(&io, fp);
ret = 0;
+#ifndef NO_FLOATING_POINT
+ dtoaresult = NULL;
+ decimal_point = localeconv_l(loc)->decimal_point;
+ /* The overwhelmingly common case is decpt_len == 1. */
+ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
+#endif
/*
* Scan the format for conversions (`%' character).
dprec = 0;
width = 0;
prec = -1;
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
#ifdef VECTORS
goto rflag;
case '\'':
flags |= GROUPING;
- thousands_sep = *(localeconv_l(loc)->thousands_sep);
- grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
nextarg = n;
if (argtable == NULL) {
argtable = statargtable;
- __find_arguments (fmt0, orgap,
- &argtable);
+ if (__find_arguments (fmt0, orgap,
+ &argtable)) {
+ ret = EOF;
+ goto error;
+ }
}
goto rflag;
}
} else
cp = (ch >= 'a') ? "inf" : "INF";
size = 3;
+ flags &= ~ZEROPAD;
break;
}
flags |= FPT;
expsize = exponent(expstr, expt - 1, expchar);
size = expsize + prec;
if (prec > 1 || flags & ALT)
- ++size;
+ size += decpt_len;
} else {
/* space for digits before decimal point */
if (expt > 0)
size = 1;
/* space for decimal pt and following digits */
if (prec || flags & ALT)
- size += prec + 1;
- if (grouping && expt > 0) {
- /* space for thousands' grouping */
- nseps = nrepeats = 0;
- lead = expt;
- while (*grouping != CHAR_MAX) {
- if (lead <= *grouping)
- break;
- lead -= *grouping;
- if (*(grouping+1)) {
- nseps++;
- grouping++;
- } else
- nrepeats++;
- }
- size += nseps + nrepeats;
- } else
- lead = expt;
+ size += prec + decpt_len;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt, loc);
}
break;
#endif /* !NO_FLOATING_POINT */
case 'n':
+ {
/*
* Assignment-like behavior is specified if the
* value overflows or is otherwise unrepresentable.
* C99 says to use `signed char' for %hhn conversions.
*/
- if (flags & LLONGINT)
- *GETARG(long long *) = ret;
+ void *ptr = GETARG(void *);
+ if (ptr == NULL)
+ continue;
+ else if (flags & LLONGINT)
+ *(long long *)ptr = ret;
else if (flags & SIZET)
- *GETARG(ssize_t *) = (ssize_t)ret;
+ *(ssize_t *)ptr = (ssize_t)ret;
else if (flags & PTRDIFFT)
- *GETARG(ptrdiff_t *) = ret;
+ *(ptrdiff_t *)ptr = ret;
else if (flags & INTMAXT)
- *GETARG(intmax_t *) = ret;
+ *(intmax_t *)ptr = ret;
else if (flags & LONGINT)
- *GETARG(long *) = ret;
+ *(long *)ptr = ret;
else if (flags & SHORTINT)
- *GETARG(short *) = ret;
+ *(short *)ptr = ret;
else if (flags & CHARINT)
- *GETARG(signed char *) = ret;
+ *(signed char *)ptr = ret;
else
- *GETARG(int *) = ret;
+ *(int *)ptr = ret;
continue; /* no output */
+ }
case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
}
} else if ((cp = GETARG(char *)) == NULL)
cp = "(null)";
- if (prec >= 0) {
- /*
- * can't use strlen; can only look for the
- * NUL in the first `prec' characters, and
- * strlen() will go further.
- */
- char *p = memchr(cp, 0, (size_t)prec);
-
- if (p != NULL) {
- size = p - cp;
- if (size > prec)
- size = prec;
- } else
- size = prec;
- } else
- size = strlen(cp);
+ size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
sign = '\0';
break;
case 'U':
* ``... diouXx conversions ... if a precision is
* specified, the 0 flag will be ignored.''
* -- ANSI X3J11
+ * except for %#.0o and zero value
*/
number: if ((dprec = prec) >= 0)
flags &= ~ZEROPAD;
* ``The result of converting a zero value with an
* explicit precision of zero is no characters.''
* -- ANSI X3J11
- * except for %#.0o and zero value
+ *
+ * ``The C Standard is clear enough as is. The call
+ * printf("%#.0o", 0) should print 0.''
+ * -- Defect Report #151
*/
cp = buf + BUF;
if (flags & INTMAX_SIZE) {
- if (ujval != 0 || prec != 0)
+ if (ujval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ujtoa(ujval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
} else {
- if (ulval != 0 || prec != 0 || (flags & ALT))
+ if (ulval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
- LIBC_ABORT("size %d > BUF %d", size, BUF);
+ LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size, loc);
break;
#ifdef VECTORS
case 'v':
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
break; \
case V_PCHAR: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
break; \
case V_SHORT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
break; \
case V_PSHORT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
break; \
case V_INT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
break; \
case V_PINT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
break; \
case V_LONGLONG: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
break; \
case V_PLONGLONG: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
break; \
case V_FLOAT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
break; \
case V_PCHAR: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
break; \
case V_SHORT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
break; \
case V_PSHORT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
break; \
case V_INT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
break; \
case V_PINT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
break; \
case V_FLOAT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD(width - realsz, zeroes);
- /* leading zeroes from decimal precision */
- PAD(dprec - size, zeroes);
-
/* the string or number proper */
#ifndef NO_FLOATING_POINT
if ((flags & FPT) == 0) {
- PRINT(cp, size);
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
} else { /* glue together f_p fragments */
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
if (expt <= 0) {
PRINT(zeroes, 1);
if (prec || flags & ALT)
- PRINT(decimal_point, strlen(decimal_point));
+ PRINT(decimal_point,decpt_len);
PAD(-expt, zeroes);
/* already handled initial 0's */
prec += expt;
} else {
- PRINTANDPAD(cp, dtoaend, lead, zeroes);
- cp += lead;
- if (grouping) {
- while (nseps>0 || nrepeats>0) {
- if (nrepeats > 0)
- nrepeats--;
- else {
- grouping--;
- nseps--;
- }
- PRINT(&thousands_sep,
- 1);
- PRINTANDPAD(cp,dtoaend,
- *grouping, zeroes);
- cp += *grouping;
- }
- if (cp > dtoaend)
- cp = dtoaend;
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, dtoaend, loc);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, dtoaend,
+ expt, zeroes);
+ cp += expt;
}
if (prec || flags & ALT)
- PRINT(decimal_point, strlen(decimal_point));
+ PRINT(decimal_point,decpt_len);
}
PRINTANDPAD(cp, dtoaend, prec, zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
if (prec > 1 || flags & ALT) {
- buf[0] = *cp++;
- PRINT(buf, 1);
- PRINT(decimal_point, strlen(decimal_point));
+ PRINT(cp++, 1);
+ PRINT(decimal_point, decpt_len);
PRINT(cp, ndig-1);
PAD(prec - ndig, zeroes);
} else /* XeYYY */
PRINT(expstr, expsize);
}
}
-#else
- PRINT(cp, size);
#endif
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
/* NOTREACHED */
}
-/*
- * Find all arguments when a positional parameter is encountered. Returns a
- * table, indexed by argument number, of pointers to each arguments. The
- * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
- * It will be replaces with a malloc-ed one if it overflows.
- */
-static void
-__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
-{
- char *fmt; /* format string */
- int ch; /* character from fmt */
- int n, n2; /* handy integer (short term usage) */
- char *cp; /* handy char pointer (short term usage) */
- int flags; /* flags as above */
- int width; /* width from format (%8d), or 0 */
- enum typeid *typetable; /* table of types */
- enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
- int tablesize; /* current size of type table */
- int tablemax; /* largest used index in table */
- int nextarg; /* 1-based argument index */
-
- /*
- * Add an argument type to the table, expanding if necessary.
- */
-#define ADDTYPE(type) \
- ((nextarg >= tablesize) ? \
- __grow_type_table(nextarg, &typetable, &tablesize) : (void)0, \
- (nextarg > tablemax) ? tablemax = nextarg : 0, \
- typetable[nextarg++] = type)
-
-#define ADDSARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
-
-#define ADDUARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
-
- /*
- * Add * arguments to the type array.
- */
-#define ADDASTER() \
- n2 = 0; \
- cp = fmt; \
- while (is_digit(*cp)) { \
- n2 = 10 * n2 + to_digit(*cp); \
- cp++; \
- } \
- if (*cp == '$') { \
- int hold = nextarg; \
- nextarg = n2; \
- ADDTYPE (T_INT); \
- nextarg = hold; \
- fmt = ++cp; \
- } else { \
- ADDTYPE (T_INT); \
- }
- fmt = (char *)fmt0;
- typetable = stattypetable;
- tablesize = STATIC_ARG_TBL_SIZE;
- tablemax = 0;
- nextarg = 1;
- for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
- typetable[n] = T_UNUSED;
-
- /*
- * Scan the format for conversions (`%' character).
- */
- for (;;) {
- for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
- /* void */;
- if (ch == '\0')
- goto done;
- fmt++; /* skip over '%' */
-
- flags = 0;
- width = 0;
-
-rflag: ch = *fmt++;
-reswitch: switch (ch) {
- case ' ':
- case '#':
- goto rflag;
- case '*':
- ADDASTER ();
- goto rflag;
- case '-':
- case '+':
- case '\'':
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- ADDASTER ();
- goto rflag;
- }
- while (is_digit(ch)) {
- ch = *fmt++;
- }
- goto reswitch;
- case '0':
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- } while (is_digit(ch));
- if (ch == '$') {
- nextarg = n;
- goto rflag;
- }
- width = n;
- goto reswitch;
-#ifndef NO_FLOATING_POINT
- case 'L':
- flags |= LONGDBL;
- goto rflag;
-#endif
- case 'h':
- if (flags & SHORTINT) {
- flags &= ~SHORTINT;
- flags |= CHARINT;
- } else
- flags |= SHORTINT;
- goto rflag;
- case 'j':
- flags |= INTMAXT;
- goto rflag;
- case 'l':
- if (flags & LONGINT) {
- flags &= ~LONGINT;
- flags |= LLONGINT;
- } else
- flags |= LONGINT;
- goto rflag;
- case 'q':
- flags |= LLONGINT; /* not necessarily */
- goto rflag;
- case 't':
- flags |= PTRDIFFT;
- goto rflag;
- case 'z':
- flags |= SIZET;
- goto rflag;
- case 'C':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'c':
- if (flags & LONGINT)
- ADDTYPE(T_WINT);
- else
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDTYPE(T_INT);
- break;
- case 'D':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif
- ADDSARG();
- break;
-#ifndef NO_FLOATING_POINT
- case 'a':
- case 'A':
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- if (flags & LONGDBL)
- ADDTYPE(T_LONG_DOUBLE);
- else
- ADDTYPE(T_DOUBLE);
- break;
-#endif /* !NO_FLOATING_POINT */
- case 'n':
- if (flags & INTMAXT)
- ADDTYPE(TP_INTMAXT);
- else if (flags & PTRDIFFT)
- ADDTYPE(TP_PTRDIFFT);
- else if (flags & SIZET)
- ADDTYPE(TP_SIZET);
- else if (flags & LLONGINT)
- ADDTYPE(TP_LLONG);
- else if (flags & LONGINT)
- ADDTYPE(TP_LONG);
- else if (flags & SHORTINT)
- ADDTYPE(TP_SHORT);
- else if (flags & CHARINT)
- ADDTYPE(TP_SCHAR);
- else
- ADDTYPE(TP_INT);
- continue; /* no output */
- case 'O':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDUARG();
- break;
- case 'p':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDTYPE(TP_VOID);
- break;
- case 'S':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 's':
- if (flags & LONGINT)
- ADDTYPE(TP_WCHAR);
- else
- ADDTYPE(TP_CHAR);
- break;
- case 'U':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'u':
- case 'X':
- case 'x':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDUARG();
- break;
- default: /* "%?" prints ?, unless ? is NUL */
- if (ch == '\0')
- goto done;
- break;
- }
- }
-done:
- /*
- * Build the argument table.
- */
- if (tablemax >= STATIC_ARG_TBL_SIZE) {
- *argtable = (union arg *)
- malloc (sizeof (union arg) * (tablemax + 1));
- }
-
- (*argtable) [0].intarg = 0;
- for (n = 1; n <= tablemax; n++) {
- switch (typetable [n]) {
- case T_UNUSED: /* whoops! */
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case TP_SCHAR:
- (*argtable) [n].pschararg = va_arg (ap, signed char *);
- break;
- case TP_SHORT:
- (*argtable) [n].pshortarg = va_arg (ap, short *);
- break;
- case T_INT:
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case T_U_INT:
- (*argtable) [n].uintarg = va_arg (ap, unsigned int);
- break;
- case TP_INT:
- (*argtable) [n].pintarg = va_arg (ap, int *);
- break;
- case T_LONG:
- (*argtable) [n].longarg = va_arg (ap, long);
- break;
- case T_U_LONG:
- (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
- break;
- case TP_LONG:
- (*argtable) [n].plongarg = va_arg (ap, long *);
- break;
- case T_LLONG:
- (*argtable) [n].longlongarg = va_arg (ap, long long);
- break;
- case T_U_LLONG:
- (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
- break;
- case TP_LLONG:
- (*argtable) [n].plonglongarg = va_arg (ap, long long *);
- break;
- case T_PTRDIFFT:
- (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
- break;
- case TP_PTRDIFFT:
- (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
- break;
- case T_SIZET:
- (*argtable) [n].sizearg = va_arg (ap, size_t);
- break;
- case TP_SIZET:
- (*argtable) [n].psizearg = va_arg (ap, size_t *);
- break;
- case T_INTMAXT:
- (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
- break;
- case T_UINTMAXT:
- (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
- break;
- case TP_INTMAXT:
- (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
- break;
-#ifndef NO_FLOATING_POINT
- case T_DOUBLE:
- (*argtable) [n].doublearg = va_arg (ap, double);
- break;
- case T_LONG_DOUBLE:
- (*argtable) [n].longdoublearg = va_arg (ap, long double);
- break;
-#endif
-#ifdef VECTORS
- case T_VECTOR:
- (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
- break;
-#endif /* VECTORS */
- case TP_CHAR:
- (*argtable) [n].pchararg = va_arg (ap, char *);
- break;
- case TP_VOID:
- (*argtable) [n].pvoidarg = va_arg (ap, void *);
- break;
- case T_WINT:
- (*argtable) [n].wintarg = va_arg (ap, wint_t);
- break;
- case TP_WCHAR:
- (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
- break;
- }
- }
-
- if ((typetable != NULL) && (typetable != stattypetable))
- free (typetable);
-}
-
-/*
- * Increase the size of the type table.
- */
-static void
-__grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
-{
- enum typeid *const oldtable = *typetable;
- const int oldsize = *tablesize;
- enum typeid *newtable;
- int n, newsize = oldsize * 2;
-
- if (newsize < nextarg + 1)
- newsize = nextarg + 1;
- if (oldsize == STATIC_ARG_TBL_SIZE) {
- if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
- LIBC_ABORT("malloc: %s", strerror(errno)); /* XXX handle better */
- bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
- } else {
- newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
- if (newtable == NULL)
- LIBC_ABORT("reallocf: %s", strerror(errno)); /* XXX handle better */
- }
- for (n = oldsize; n < newsize; n++)
- newtable[n] = T_UNUSED;
-
- *typetable = newtable;
- *tablesize = newsize;
-}
-
-
-#ifndef NO_FLOATING_POINT
-
-static int
-exponent(char *p0, int exp, int fmtch)
-{
- char *p, *t;
- char expbuf[MAXEXPDIG];
-
- p = p0;
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- }
- else
- *p++ = '+';
- t = expbuf + MAXEXPDIG;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
- }
- else {
- /*
- * Exponents for decimal floating point conversions
- * (%[eEgG]) must be at least two characters long,
- * whereas exponents for hexadecimal conversions can
- * be only one character long.
- */
- if (fmtch == 'e' || fmtch == 'E')
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p - p0);
-}
-#endif /* !NO_FLOATING_POINT */
* 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.
static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.37 2004/05/02 10:55:05 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.43 2009/01/19 06:19:51 das Exp $");
#include "xlocale_private.h"
static const u_char *__sccl(char *, const u_char *, locale_t);
#ifndef NO_FLOATING_POINT
static int parsefloat(FILE *, char **, size_t, locale_t);
-#endif /* !NO_FLOATING_POINT */
-
-/*
- * For ppc, we need to have the 64-bit long double version defining storage for
- * __scanfdebug, to be compatible with 10.3. For ppc64 and i386, we want the
- * storage defined in the only version.
- */
-#if defined(__ppc__) && !defined(BUILDING_VARIANT)
-extern int __scanfdebug;
-#else /* !__ppc__ || BUILDING_VARIANT */
-int __scanfdebug = 0;
-#endif /* __ppc__ && !BUILDING_VARIANT */
+#endif
__weak_reference(__vfscanf, vfscanf);
char ccltab[256]; /* character class table for %[...] */
char buf[BUF]; /* buffer for numeric and mb conversions */
wchar_t *wcp; /* handy wide character pointer */
- wchar_t *wcp0; /* saves original value of wcp */
size_t nconv; /* length of multibyte sequence converted */
int index; /* %index$, zero if unset */
va_list ap_orig; /* to reset ap to first argument */
break;
case 'n':
- if (flags & SUPPRESS) /* ??? */
+ {
+ void *ptr = va_arg(ap, void *);
+ if ((ptr == NULL) || (flags & SUPPRESS)) /* ??? */
continue;
- if (flags & SHORTSHORT)
- *va_arg(ap, char *) = nread;
+ else if (flags & SHORTSHORT)
+ *(char *)ptr = nread;
else if (flags & SHORT)
- *va_arg(ap, short *) = nread;
+ *(short *)ptr = nread;
else if (flags & LONG)
- *va_arg(ap, long *) = nread;
+ *(long *)ptr = nread;
else if (flags & LONGLONG)
- *va_arg(ap, long long *) = nread;
+ *(long long *)ptr = nread;
else if (flags & INTMAXT)
- *va_arg(ap, intmax_t *) = nread;
+ *(intmax_t *)ptr = nread;
else if (flags & SIZET)
- *va_arg(ap, size_t *) = nread;
+ *(size_t *)ptr = nread;
else if (flags & PTRDIFFT)
- *va_arg(ap, ptrdiff_t *) = nread;
+ *(ptrdiff_t *)ptr = nread;
else
- *va_arg(ap, int *) = nread;
+ *(int *)ptr = nread;
continue;
-
+ }
default:
goto match_failure;
}
nread += sum;
} else {
- size_t r = fread((void *)va_arg(ap, char *), 1,
+ size_t r = __fread((void *)va_arg(ap, char *), 1,
width, fp);
if (r == 0)
int nchars;
if ((flags & SUPPRESS) == 0)
- wcp = wcp0 = va_arg(ap, wchar_t *);
+ wcp = va_arg(ap, wchar_t *);
else
- wcp = wcp0 = &twc;
+ wcp = &twc;
n = 0;
nchars = 0;
while (width != 0) {
float res = strtof_l(pbuf, &p, loc);
*va_arg(ap, float *) = res;
}
- if (__scanfdebug && p - pbuf != width)
- LIBC_ABORT("p - pbuf %ld != width %ld", (long)(p - pbuf), width);
nassigned++;
}
nread += width;
parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
{
char *commit, *p;
- int infnanpos = 0;
+ int infnanpos = 0, decptpos = 0;
enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
- S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS, S_DECIMAL_POINT
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
+ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
unsigned char c;
- unsigned char *decpt = (unsigned char *)localeconv_l(loc)->decimal_point;
- char *decpt_start;
+ const char *decpt = localeconv_l(loc)->decimal_point;
_Bool gotmantdig = 0, ishex = 0;
char *b;
char *e;
break;
case S_NAN:
switch (infnanpos) {
- case -1: /* XXX kludge to deal with nan(...) */
- goto parsedone;
case 0:
if (c != 'A' && c != 'a')
goto parsedone;
default:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
} else if (!isalnum_l(c, loc) && c != '_')
goto parsedone;
break;
}
infnanpos++;
break;
+ case S_DONE:
+ goto parsedone;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x') {
goto reswitch;
}
case S_DIGITS:
- if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc))
+ if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
gotmantdig = 1;
- else {
- state = S_DECIMAL_POINT;
- decpt_start = p;
- goto reswitch;
- }
- if (gotmantdig)
commit = p;
- break;
- case S_DECIMAL_POINT:
- if (*decpt == 0) {
- if (gotmantdig)
- commit = p - 1;
- state = S_FRAC;
+ break;
+ } else {
+ state = S_DECPT;
goto reswitch;
}
- if (*decpt++ == c)
+ case S_DECPT:
+ if (c == decpt[decptpos]) {
+ if (decpt[++decptpos] == '\0') {
+ /* We read the complete decpt seq. */
+ state = S_FRAC;
+ if (gotmantdig)
+ commit = p;
+ }
break;
- /* not decimal point */
- state = S_FRAC;
- if (decpt_start == p)
+ } else if (!decptpos) {
+ /* We didn't read any decpt characters. */
+ state = S_FRAC;
goto reswitch;
- while (decpt_start < --p)
- __ungetc(*(u_char *)p, fp);
- c = *(u_char *)p;
- goto reswitch;
+ } else {
+ /*
+ * We read part of a multibyte decimal point,
+ * but the rest is invalid, so bail.
+ */
+ goto parsedone;
+ }
case S_FRAC:
if (((c == 'E' || c == 'e') && !ishex) ||
((c == 'P' || c == 'p') && ishex)) {
* 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.
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.23 2004/08/26 06:25:28 des Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.42 2009/11/25 04:27:55 wollman Exp $");
#include "xlocale_private.h"
#include "libc_private.h"
#include "local.h"
#include "fvwrite.h"
+#include "printflocal.h"
-#ifdef VECTORS
-typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
-#ifdef __SSE2__
-#define V64TYPE
-#endif /* __SSE2__ */
-#endif /* VECTORS */
+static int __sprint(FILE *, locale_t, struct __suio *);
+static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list);
+static wint_t __xfputwc(wchar_t, FILE *, locale_t);
+static wchar_t *__mbsconv(char *, int, locale_t);
+__private_extern__ const char *__fix_nogrouping(const char *);
-union arg {
- int intarg;
- u_int uintarg;
- long longarg;
- u_long ulongarg;
- long long longlongarg;
- unsigned long long ulonglongarg;
- ptrdiff_t ptrdiffarg;
- size_t sizearg;
- intmax_t intmaxarg;
- uintmax_t uintmaxarg;
- void *pvoidarg;
- char *pchararg;
- signed char *pschararg;
- short *pshortarg;
- int *pintarg;
- long *plongarg;
- long long *plonglongarg;
- ptrdiff_t *pptrdiffarg;
- size_t *psizearg;
- intmax_t *pintmaxarg;
-#ifndef NO_FLOATING_POINT
- double doublearg;
- long double longdoublearg;
-#endif
- wint_t wintarg;
- wchar_t *pwchararg;
-#ifdef VECTORS
- VECTORTYPE vectorarg;
- unsigned char vuchararg[16];
- signed char vchararg[16];
- unsigned short vushortarg[8];
- signed short vshortarg[8];
- unsigned int vuintarg[4];
- signed int vintarg[4];
- float vfloatarg[4];
-#ifdef V64TYPE
- double vdoublearg[2];
- unsigned long long vulonglongarg[2];
- long long vlonglongarg[2];
-#endif /* V64TYPE */
-#endif /* VECTORS */
+#define CHAR wchar_t
+#include "printfcommon.h"
+
+struct grouping_state {
+ wchar_t thousands_sep; /* locale-specific thousands separator */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
};
+static const mbstate_t initial_mbs;
+
+static inline wchar_t
+get_decpt(locale_t loc)
+{
+ mbstate_t mbs;
+ wchar_t decpt;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc_l(&decpt, localeconv_l(loc)->decimal_point, MB_CUR_MAX_L(loc), &mbs, loc);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+ return (decpt);
+}
+
+static inline wchar_t
+get_thousep(locale_t loc)
+{
+ mbstate_t mbs;
+ wchar_t thousep;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc_l(&thousep, localeconv_l(loc)->thousands_sep,
+ MB_CUR_MAX_L(loc), &mbs, loc);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ thousep = '\0'; /* failsafe */
+ return (thousep);
+}
+
/*
- * Type ids for argument type table.
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of wide characters that will be printed.
*/
-enum typeid {
- T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
- T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
- T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
- T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
-#ifdef VECTORS
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
-#else /* ! VECTORS */
- T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
-#endif /* VECTORS */
-};
+static int
+grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
+{
-static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list);
-static wint_t __xfputwc(wchar_t, FILE *, locale_t);
-static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int,
- char, const char *);
-static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int,
- char, const char *);
-static wchar_t *__mbsconv(char *, int, locale_t);
-static void __find_arguments(const wchar_t *, va_list, union arg **);
-static void __grow_type_table(int, enum typeid **, int *);
+ gs->grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
+ gs->thousands_sep = get_thousep(loc);
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return (gs->nseps + gs->nrepeats);
+}
+
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep, locale_t loc)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, &gs->thousands_sep, 1, loc))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
+
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ *
+ * XXX The fact that we do this a character at a time and convert to a
+ * multibyte character sequence even if the destination is a wide
+ * string eclipses the benefits of buffering.
+ */
+static int
+__sprint(FILE *fp, locale_t loc, struct __suio *uio)
+{
+ struct __siov *iov;
+ wchar_t *p;
+ int i, len;
+
+ iov = uio->uio_iov;
+ for (; uio->uio_resid != 0; uio->uio_resid -= len, iov++) {
+ p = (wchar_t *)iov->iov_base;
+ len = iov->iov_len;
+ for (i = 0; i < len; i++) {
+ if (__xfputwc(p[i], fp, loc) == WEOF)
+ return (-1);
+ }
+ }
+ uio->uio_iovcnt = 0;
+ return (0);
+}
/*
* Helper function for `fprintf to unbuffered unix file': creates a
int ret;
FILE fake;
unsigned char buf[BUFSIZ];
+ struct __sFILEX ext;
+ fake._extra = &ext;
+ INITEXTRA(&fake);
+
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
/* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
- fake._extra = fp->_extra;
+ fake._orientation = fp->_orientation;
+ fake._mbstate = fp->_mbstate;
/* set up the buffer */
fake._bf._base = fake._p = buf;
static wint_t
__xfputwc(wchar_t wc, FILE *fp, locale_t loc)
{
- static const mbstate_t initial;
mbstate_t mbs;
char buf[MB_LEN_MAX];
struct __suio uio;
if ((fp->_flags & __SSTR) == 0)
return (__fputwc(wc, fp, loc));
- mbs = initial;
+ mbs = initial_mbs;
if ((len = wcrtomb_l(buf, wc, &mbs, loc)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF);
}
-/*
- * Macros for converting digits to letters and vice versa
- */
-#define to_digit(c) ((c) - '0')
-#define is_digit(c) ((unsigned)to_digit(c) <= 9)
-#define to_char(n) ((n) + '0')
-
-/*
- * Convert an unsigned long to ASCII for printf purposes, returning
- * a pointer to the first character of the string representation.
- * Octal numbers can be forced to have a leading zero; hex numbers
- * use the given digits.
- */
-static wchar_t *
-__ultoa(u_long val, wchar_t *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- wchar_t *cp = endp;
- long sval;
- int ndig;
-
- /*
- * Handle the three cases separately, in the hope of getting
- * better/faster code.
- */
- switch (base) {
- case 10:
- if (val < 10) { /* many numbers are 1 digit */
- *--cp = to_char(val);
- return (cp);
- }
- ndig = 0;
- /*
- * On many machines, unsigned arithmetic is harder than
- * signed arithmetic, so we do at most one unsigned mod and
- * divide; this is sufficient to reduce the range of
- * the incoming value to where signed arithmetic works.
- */
- if (val > LONG_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && ndig == *grp && *grp != CHAR_MAX
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default: /* oops */
- LIBC_ABORT("base = %d", base);
- }
- return (cp);
-}
-
-/* Identical to __ultoa, but for intmax_t. */
-static wchar_t *
-__ujtoa(uintmax_t val, wchar_t *endp, int base, int octzero,
- const char *xdigs, int needgrp, char thousep, const char *grp)
-{
- wchar_t *cp = endp;
- intmax_t sval;
- int ndig;
-
- /* quick test for small values; __ultoa is typically much faster */
- /* (perhaps instead we should run until small, then call __ultoa?) */
- if (val <= ULONG_MAX)
- return (__ultoa((u_long)val, endp, base, octzero, xdigs,
- needgrp, thousep, grp));
- switch (base) {
- case 10:
- if (val < 10) {
- *--cp = to_char(val % 10);
- return (cp);
- }
- ndig = 0;
- if (val > INTMAX_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && *grp != CHAR_MAX && ndig == *grp
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default:
- LIBC_ABORT("base = %d", base);
- }
- return (cp);
-}
-
/*
* Convert a multibyte character string argument for the %s format to a wide
* string representation. ``prec'' specifies the maximum number of bytes
static wchar_t *
__mbsconv(char *mbsarg, int prec, locale_t loc)
{
- static const mbstate_t initial;
mbstate_t mbs;
wchar_t *convbuf, *wcp;
const char *p;
* number of characters to print.
*/
p = mbsarg;
- insize = nchars = 0;
- mbs = initial;
+ insize = nchars = nconv = 0;
+ mbs = initial_mbs;
while (nchars != (size_t)prec) {
nconv = mbrlen_l(p, mb_cur_max, &mbs, loc);
if (nconv == 0 || nconv == (size_t)-1 ||
}
if (nconv == (size_t)-1 || nconv == (size_t)-2)
return (NULL);
- } else
+ } else {
insize = strlen(mbsarg);
+ nconv = 0;
+ }
/*
* Allocate buffer for the result and perform the conversion,
return (NULL);
wcp = convbuf;
p = mbsarg;
- mbs = initial;
+ mbs = initial_mbs;
while (insize != 0) {
nconv = mbrtowc_l(wcp, p, insize, &mbs, loc);
if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
/*
* MT-safe version
*/
-__private_extern__ const char *__fix_nogrouping(const char *);
-
int
-vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
-
+vfwprintf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt0, va_list ap)
{
int ret;
+ NORMALIZE_LOCALE(loc);
FLOCKFILE(fp);
- ret = __vfwprintf(fp, __current_locale(), fmt0, ap);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, loc, fmt0, ap);
+ else
+ ret = __vfwprintf(fp, loc, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
int
-vfwprintf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt0,
- va_list ap)
-
+vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
{
- int ret;
-
- NORMALIZE_LOCALE(loc);
- FLOCKFILE(fp);
- ret = __vfwprintf(fp, loc, fmt0, ap);
- FUNLOCKFILE(fp);
- return (ret);
+ return vfwprintf_l(fp, __current_locale(), fmt0, ap);
}
-#ifndef NO_FLOATING_POINT
-
-#define dtoa __dtoa
-#define freedtoa __freedtoa
-
-#include <float.h>
-#include <math.h>
-#include "floatio.h"
-#include "gdtoa.h"
-
-#define DEFPREC 6
-
-static int exponent(wchar_t *, int, wchar_t);
-
-#endif /* !NO_FLOATING_POINT */
-
/*
* The size of the buffer we use as scratch space for integer
- * conversions, among other things. Technically, we would need the
- * most space for base 10 conversions with thousands' grouping
- * characters between each pair of digits. 100 bytes is a
- * conservative overestimate even for a 128-bit uintmax_t.
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
*/
-#define BUF 100
-
-#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
-
-/*
- * Flags used during conversion.
- */
-#define ALT 0x001 /* alternate form */
-#define LADJUST 0x004 /* left adjustment */
-#define LONGDBL 0x008 /* long double */
-#define LONGINT 0x010 /* long integer */
-#define LLONGINT 0x020 /* long long integer */
-#define SHORTINT 0x040 /* short integer */
-#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
-#define FPT 0x100 /* Floating point number */
-#define GROUPING 0x200 /* use grouping ("'" flag) */
- /* C99 additional size modifiers: */
-#define SIZET 0x400 /* size_t */
-#define PTRDIFFT 0x800 /* ptrdiff_t */
-#define INTMAXT 0x1000 /* intmax_t */
-#define CHARINT 0x2000 /* print char using int format */
-#ifdef VECTORS
-#define VECTOR 0x4000 /* Altivec or SSE vector */
-#endif /* VECTORS */
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
/*
* Non-MT-safe version
{
wchar_t *fmt; /* format string */
wchar_t ch; /* character from fmt */
- int n, n2, n3; /* handy integer (short term usage) */
+ int n, n2; /* handy integer (short term usage) */
wchar_t *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
- char thousands_sep; /* locale specific thousands separator */
- const char *grouping; /* locale specific numeric grouping rules */
+ struct grouping_state gs; /* thousands' grouping info */
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
* F: at least two digits for decimal, at least one digit for hex
*/
wchar_t decimal_point; /* locale specific decimal point */
- char *decimal_point_mb; /* multibyte decimal point */
int signflag; /* true if float is negative */
union { /* floating point arguments %[aAeEfFgG] */
double dbl;
char expchar; /* exponent character: [eEpP\0] */
char *dtoaend; /* pointer to end of converted digits */
int expsize; /* character count for expstr */
- int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
char *dtoaresult; /* buffer allocated by dtoa */
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
#endif
#ifdef VECTORS
union arg vval; /* Vector argument. */
int size; /* size of converted field or string */
int prsize; /* max size of printed field */
const char *xdigs; /* digits for [xX] conversion */
+ struct io_state io; /* I/O buffering state */
wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */
wchar_t ox[2]; /* space for 0x hex-prefix */
union arg *argtable; /* args, built due to positional arg */
va_list orgap; /* original argument pointer */
wchar_t *convbuf; /* multibyte to wide conversion result */
- /*
- * Choose PADSIZE to trade efficiency vs. size. If larger printf
- * fields occur frequently, increase PADSIZE and make the initialisers
- * below longer.
- */
-#define PADSIZE 16 /* pad chunk size */
- static wchar_t blanks[PADSIZE] =
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static wchar_t zeroes[PADSIZE] =
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
-
static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF";
- /*
- * BEWARE, these `goto error' on error, PRINT uses `n2' and
- * PAD uses `n'.
- */
+ /* BEWARE, these `goto error' on error. */
#define PRINT(ptr, len) do { \
- for (n3 = 0; n3 < (len); n3++) \
- __xfputwc((ptr)[n3], fp, loc); \
-} while (0)
-#define PAD(howmany, with) do { \
- if ((n = (howmany)) > 0) { \
- while (n > PADSIZE) { \
- PRINT(with, PADSIZE); \
- n -= PADSIZE; \
- } \
- PRINT(with, n); \
- } \
+ if (io_print(&io, (ptr), (len), loc)) \
+ goto error; \
} while (0)
-#define PRINTANDPAD(p, ep, len, with) do { \
- n2 = (ep) - (p); \
- if (n2 > (len)) \
- n2 = (len); \
- if (n2 > 0) \
- PRINT((p), n2); \
- PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
-} while(0)
+#define PAD(howmany, with) { \
+ if (io_pad(&io, (howmany), (with), loc)) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \
+ goto error; \
+}
+#define FLUSH() { \
+ if (io_flush(&io, loc)) \
+ goto error; \
+}
/*
* Get the argument indexed by nextarg. If the argument table is
#define UJARG() \
(flags&INTMAXT ? GETARG(uintmax_t) : \
flags&SIZET ? (uintmax_t)GETARG(size_t) : \
- flags&PTRDIFFT ? (uintmax_t)(unsigned)GETARG(ptrdiff_t) : \
+ flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
(uintmax_t)GETARG(unsigned long long))
/*
int hold = nextarg; \
if (argtable == NULL) { \
argtable = statargtable; \
- __find_arguments (fmt0, orgap, &argtable); \
+ if (__find_warguments (fmt0, orgap, &argtable)) { \
+ ret = EOF; \
+ goto error; \
+ } \
} \
nextarg = n2; \
val = GETARG (int); \
val = GETARG (int); \
}
- thousands_sep = '\0';
- grouping = NULL;
-#ifndef NO_FLOATING_POINT
- decimal_point_mb = localeconv_l(loc)->decimal_point;
- mbtowc_l(&decimal_point, decimal_point_mb, strlen(decimal_point_mb), loc);
-#endif
- convbuf = NULL;
+
/* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
if (prepwrite(fp) != 0) {
errno = EBADF;
}
ORIENT(fp, 1);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
- return (__sbprintf(fp, loc, fmt0, ap));
-
+ convbuf = NULL;
fmt = (wchar_t *)fmt0;
argtable = NULL;
nextarg = 1;
va_copy(orgap, ap);
+ io_init(&io, fp);
ret = 0;
+#ifndef NO_FLOATING_POINT
+ decimal_point = get_decpt(loc);
+#endif
/*
* Scan the format for conversions (`%' character).
dprec = 0;
width = 0;
prec = -1;
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
#ifdef VECTORS
goto rflag;
case '\'':
flags |= GROUPING;
- thousands_sep = *(localeconv_l(loc)->thousands_sep);
- grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
nextarg = n;
if (argtable == NULL) {
argtable = statargtable;
- __find_arguments (fmt0, orgap,
- &argtable);
+ if (__find_warguments (fmt0, orgap,
+ &argtable)) {
+ ret = EOF;
+ goto error;
+ }
}
goto rflag;
}
} else
cp = (ch >= 'a') ? L"inf" : L"INF";
size = 3;
+ flags &= ~ZEROPAD;
break;
}
flags |= FPT;
/* space for decimal pt and following digits */
if (prec || flags & ALT)
size += prec + 1;
- if (grouping && expt > 0) {
- /* space for thousands' grouping */
- nseps = nrepeats = 0;
- lead = expt;
- while (*grouping != CHAR_MAX) {
- if (lead <= *grouping)
- break;
- lead -= *grouping;
- if (*(grouping+1)) {
- nseps++;
- grouping++;
- } else
- nrepeats++;
- }
- size += nseps + nrepeats;
- } else
- lead = expt;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt, loc);
}
break;
#endif /* !NO_FLOATING_POINT */
case 'n':
+ {
/*
* Assignment-like behavior is specified if the
* value overflows or is otherwise unrepresentable.
* C99 says to use `signed char' for %hhn conversions.
*/
- if (flags & LLONGINT)
- *GETARG(long long *) = ret;
+ void *ptr = GETARG(void *);
+ if (ptr == NULL)
+ continue;
+ else if (flags & LLONGINT)
+ *(long long *)ptr = ret;
else if (flags & SIZET)
- *GETARG(ssize_t *) = (ssize_t)ret;
+ *(ssize_t *)ptr = (ssize_t)ret;
else if (flags & PTRDIFFT)
- *GETARG(ptrdiff_t *) = ret;
+ *(ptrdiff_t *)ptr = ret;
else if (flags & INTMAXT)
- *GETARG(intmax_t *) = ret;
+ *(intmax_t *)ptr = ret;
else if (flags & LONGINT)
- *GETARG(long *) = ret;
+ *(long *)ptr = ret;
else if (flags & SHORTINT)
- *GETARG(short *) = ret;
+ *(short *)ptr = ret;
else if (flags & CHARINT)
- *GETARG(signed char *) = ret;
+ *(signed char *)ptr = ret;
else
- *GETARG(int *) = ret;
+ *(int *)ptr = ret;
continue; /* no output */
+ }
case 'O':
flags |= LONGINT;
/*FALLTHROUGH*/
cp = convbuf;
}
}
-
- if (prec >= 0) {
- /*
- * can't use wcslen; can only look for the
- * NUL in the first `prec' characters, and
- * wcslen() will go further.
- */
- wchar_t *p = wmemchr(cp, 0, (size_t)prec);
-
- if (p != NULL) {
- size = p - cp;
- if (size > prec)
- size = prec;
- } else
- size = prec;
- } else
- size = wcslen(cp);
+#if 0 // wcsnlen needs API review first
+ size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp);
+#else
+ size = wcslen(cp);
+ if(prec >= 0 && prec < size)
+ size = prec;
+#endif
sign = '\0';
break;
case 'U':
* ``... diouXx conversions ... if a precision is
* specified, the 0 flag will be ignored.''
* -- ANSI X3J11
+ * except for %#.0o and zero value
*/
number: if ((dprec = prec) >= 0)
flags &= ~ZEROPAD;
* ``The result of converting a zero value with an
* explicit precision of zero is no characters.''
* -- ANSI X3J11
- * except for %#.0o and zero value
+ *
+ * ``The C Standard is clear enough as is. The call
+ * printf("%#.0o", 0) should print 0.''
+ * -- Defect Report #151
*/
cp = buf + BUF;
if (flags & INTMAX_SIZE) {
- if (ujval != 0 || prec != 0)
+ if (ujval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ujtoa(ujval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
} else {
- if (ulval != 0 || prec != 0 || (flags & ALT))
+ if (ulval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
- LIBC_ABORT("size %d > BUF %d", size, BUF);
+ LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size, loc);
break;
#ifdef VECTORS
case 'v':
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
break; \
case V_PCHAR: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
break; \
case V_SHORT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
break; \
case V_PSHORT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
break; \
case V_INT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
break; \
case V_PINT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
break; \
case V_LONGLONG: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
break; \
case V_PLONGLONG: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
break; \
case V_FLOAT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
break; \
case V_PCHAR: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
break; \
case V_SHORT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
break; \
case V_PSHORT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
break; \
case V_INT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
break; \
case V_PINT: \
- vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
break; \
case V_FLOAT: \
vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD(width - realsz, zeroes);
- /* leading zeroes from decimal precision */
- PAD(dprec - size, zeroes);
-
/* the string or number proper */
#ifndef NO_FLOATING_POINT
if ((flags & FPT) == 0) {
- PRINT(cp, size);
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
} else { /* glue together f_p fragments */
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
if (expt <= 0) {
/* already handled initial 0's */
prec += expt;
} else {
- PRINTANDPAD(cp, convbuf + ndig, lead, zeroes);
- cp += lead;
- if (grouping) {
- while (nseps>0 || nrepeats>0) {
- if (nrepeats > 0)
- nrepeats--;
- else {
- grouping--;
- nseps--;
- }
- PRINT(&thousands_sep,
- 1);
- PRINTANDPAD(cp,
- convbuf + ndig,
- *grouping, zeroes);
- cp += *grouping;
- }
- if (cp > convbuf + ndig)
- cp = convbuf + ndig;
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, convbuf + ndig, loc);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, convbuf + ndig,
+ expt, zeroes);
+ cp += expt;
}
- if (prec || flags & ALT) {
+ if (prec || flags & ALT)
PRINT(&decimal_point, 1);
- }
}
PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
PRINT(expstr, expsize);
}
}
-#else
- PRINT(cp, size);
#endif
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
/* finally, adjust ret */
ret += prsize;
+
+ FLUSH(); /* copy out the I/O vectors */
}
done:
+ FLUSH();
error:
va_end(orgap);
if (convbuf != NULL)
return (ret);
/* NOTREACHED */
}
-
-/*
- * Find all arguments when a positional parameter is encountered. Returns a
- * table, indexed by argument number, of pointers to each arguments. The
- * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
- * It will be replaces with a malloc-ed one if it overflows.
- */
-static void
-__find_arguments (const wchar_t *fmt0, va_list ap, union arg **argtable)
-{
- wchar_t *fmt; /* format string */
- wchar_t ch; /* character from fmt */
- int n, n2; /* handy integer (short term usage) */
- wchar_t *cp; /* handy char pointer (short term usage) */
- int flags; /* flags as above */
- int width; /* width from format (%8d), or 0 */
- enum typeid *typetable; /* table of types */
- enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
- int tablesize; /* current size of type table */
- int tablemax; /* largest used index in table */
- int nextarg; /* 1-based argument index */
-
- /*
- * Add an argument type to the table, expanding if necessary.
- */
-#define ADDTYPE(type) \
- ((nextarg >= tablesize) ? \
- __grow_type_table(nextarg, &typetable, &tablesize) : (void)0, \
- (nextarg > tablemax) ? tablemax = nextarg : 0, \
- typetable[nextarg++] = type)
-
-#define ADDSARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
-
-#define ADDUARG() \
- ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
- ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
- ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
-
- /*
- * Add * arguments to the type array.
- */
-#define ADDASTER() \
- n2 = 0; \
- cp = fmt; \
- while (is_digit(*cp)) { \
- n2 = 10 * n2 + to_digit(*cp); \
- cp++; \
- } \
- if (*cp == '$') { \
- int hold = nextarg; \
- nextarg = n2; \
- ADDTYPE (T_INT); \
- nextarg = hold; \
- fmt = ++cp; \
- } else { \
- ADDTYPE (T_INT); \
- }
- fmt = (wchar_t *)fmt0;
- typetable = stattypetable;
- tablesize = STATIC_ARG_TBL_SIZE;
- tablemax = 0;
- nextarg = 1;
- for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
- typetable[n] = T_UNUSED;
-
- /*
- * Scan the format for conversions (`%' character).
- */
- for (;;) {
- for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
- /* void */;
- if (ch == '\0')
- goto done;
- fmt++; /* skip over '%' */
-
- flags = 0;
- width = 0;
-
-rflag: ch = *fmt++;
-reswitch: switch (ch) {
- case ' ':
- case '#':
- goto rflag;
- case '*':
- ADDASTER ();
- goto rflag;
- case '-':
- case '+':
- case '\'':
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- ADDASTER ();
- goto rflag;
- }
- while (is_digit(ch)) {
- ch = *fmt++;
- }
- goto reswitch;
- case '0':
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- } while (is_digit(ch));
- if (ch == '$') {
- nextarg = n;
- goto rflag;
- }
- width = n;
- goto reswitch;
-#ifndef NO_FLOATING_POINT
- case 'L':
- flags |= LONGDBL;
- goto rflag;
-#endif
- case 'h':
- if (flags & SHORTINT) {
- flags &= ~SHORTINT;
- flags |= CHARINT;
- } else
- flags |= SHORTINT;
- goto rflag;
- case 'j':
- flags |= INTMAXT;
- goto rflag;
- case 'l':
- if (flags & LONGINT) {
- flags &= ~LONGINT;
- flags |= LLONGINT;
- } else
- flags |= LONGINT;
- goto rflag;
- case 'q':
- flags |= LLONGINT; /* not necessarily */
- goto rflag;
- case 't':
- flags |= PTRDIFFT;
- goto rflag;
- case 'z':
- flags |= SIZET;
- goto rflag;
- case 'C':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'c':
- if (flags & LONGINT)
- ADDTYPE(T_WINT);
- else
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDTYPE(T_INT);
- break;
- case 'D':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDSARG();
- break;
-#ifndef NO_FLOATING_POINT
- case 'a':
- case 'A':
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- if (flags & LONGDBL)
- ADDTYPE(T_LONG_DOUBLE);
- else
- ADDTYPE(T_DOUBLE);
- break;
-#endif /* !NO_FLOATING_POINT */
- case 'n':
- if (flags & INTMAXT)
- ADDTYPE(TP_INTMAXT);
- else if (flags & PTRDIFFT)
- ADDTYPE(TP_PTRDIFFT);
- else if (flags & SIZET)
- ADDTYPE(TP_SIZET);
- else if (flags & LLONGINT)
- ADDTYPE(TP_LLONG);
- else if (flags & LONGINT)
- ADDTYPE(TP_LONG);
- else if (flags & SHORTINT)
- ADDTYPE(TP_SHORT);
- else if (flags & CHARINT)
- ADDTYPE(TP_SCHAR);
- else
- ADDTYPE(TP_INT);
- continue; /* no output */
- case 'O':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDUARG();
- break;
- case 'p':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDTYPE(TP_VOID);
- break;
- case 'S':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 's':
- if (flags & LONGINT)
- ADDTYPE(TP_WCHAR);
- else
- ADDTYPE(TP_CHAR);
- break;
- case 'U':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'u':
- case 'X':
- case 'x':
-#ifdef VECTORS
- if (flags & VECTOR)
- ADDTYPE(T_VECTOR);
- else
-#endif /* VECTORS */
- ADDUARG();
- break;
- default: /* "%?" prints ?, unless ? is NUL */
- if (ch == '\0')
- goto done;
- break;
- }
- }
-done:
- /*
- * Build the argument table.
- */
- if (tablemax >= STATIC_ARG_TBL_SIZE) {
- *argtable = (union arg *)
- malloc (sizeof (union arg) * (tablemax + 1));
- }
-
- (*argtable) [0].intarg = 0;
- for (n = 1; n <= tablemax; n++) {
- switch (typetable [n]) {
- case T_UNUSED: /* whoops! */
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case TP_SCHAR:
- (*argtable) [n].pschararg = va_arg (ap, signed char *);
- break;
- case TP_SHORT:
- (*argtable) [n].pshortarg = va_arg (ap, short *);
- break;
- case T_INT:
- (*argtable) [n].intarg = va_arg (ap, int);
- break;
- case T_U_INT:
- (*argtable) [n].uintarg = va_arg (ap, unsigned int);
- break;
- case TP_INT:
- (*argtable) [n].pintarg = va_arg (ap, int *);
- break;
- case T_LONG:
- (*argtable) [n].longarg = va_arg (ap, long);
- break;
- case T_U_LONG:
- (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
- break;
- case TP_LONG:
- (*argtable) [n].plongarg = va_arg (ap, long *);
- break;
- case T_LLONG:
- (*argtable) [n].longlongarg = va_arg (ap, long long);
- break;
- case T_U_LLONG:
- (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
- break;
- case TP_LLONG:
- (*argtable) [n].plonglongarg = va_arg (ap, long long *);
- break;
- case T_PTRDIFFT:
- (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
- break;
- case TP_PTRDIFFT:
- (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
- break;
- case T_SIZET:
- (*argtable) [n].sizearg = va_arg (ap, size_t);
- break;
- case TP_SIZET:
- (*argtable) [n].psizearg = va_arg (ap, size_t *);
- break;
- case T_INTMAXT:
- (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
- break;
- case T_UINTMAXT:
- (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
- break;
- case TP_INTMAXT:
- (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
- break;
-#ifndef NO_FLOATING_POINT
- case T_DOUBLE:
- (*argtable) [n].doublearg = va_arg (ap, double);
- break;
- case T_LONG_DOUBLE:
- (*argtable) [n].longdoublearg = va_arg (ap, long double);
- break;
-#endif
-#ifdef VECTORS
- case T_VECTOR:
- (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
- break;
-#endif /* VECTORS */
- case TP_CHAR:
- (*argtable) [n].pchararg = va_arg (ap, char *);
- break;
- case TP_VOID:
- (*argtable) [n].pvoidarg = va_arg (ap, void *);
- break;
- case T_WINT:
- (*argtable) [n].wintarg = va_arg (ap, wint_t);
- break;
- case TP_WCHAR:
- (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
- break;
- }
- }
-
- if ((typetable != NULL) && (typetable != stattypetable))
- free (typetable);
-}
-
-/*
- * Increase the size of the type table.
- */
-static void
-__grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
-{
- enum typeid *const oldtable = *typetable;
- const int oldsize = *tablesize;
- enum typeid *newtable;
- int n, newsize = oldsize * 2;
-
- if (newsize < nextarg + 1)
- newsize = nextarg + 1;
- if (oldsize == STATIC_ARG_TBL_SIZE) {
- if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
- LIBC_ABORT("malloc: %s", strerror(errno)); /* XXX handle better */
- bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
- } else {
- newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
- if (newtable == NULL)
- LIBC_ABORT("reallocf: %s", strerror(errno)); /* XXX handle better */
- }
- for (n = oldsize; n < newsize; n++)
- newtable[n] = T_UNUSED;
-
- *typetable = newtable;
- *tablesize = newsize;
-}
-
-
-#ifndef NO_FLOATING_POINT
-
-static int
-exponent(wchar_t *p0, int exp, wchar_t fmtch)
-{
- wchar_t *p, *t;
- wchar_t expbuf[MAXEXPDIG];
-
- p = p0;
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- }
- else
- *p++ = '+';
- t = expbuf + MAXEXPDIG;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
- }
- else {
- /*
- * Exponents for decimal floating point conversions
- * (%[eEgG]) must be at least two characters long,
- * whereas exponents for hexadecimal conversions can
- * be only one character long.
- */
- if (fmtch == 'e' || fmtch == 'E')
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p - p0);
-}
-#endif /* !NO_FLOATING_POINT */
* 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.
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.12 2004/05/02 20:13:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.17 2009/01/19 06:19:51 das Exp $");
#include "xlocale_private.h"
#include "namespace.h"
#include <ctype.h>
#include <inttypes.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#ifndef NO_FLOATING_POINT
static int parsefloat(FILE *, wchar_t **, size_t, locale_t loc);
-#endif /* !NO_FLOATING_POINT */
-
-extern int __scanfdebug;
+#endif
#define INCCL(_c) \
(cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \
(wmemchr(ccls, (_c), ccle - ccls) != NULL))
+static const mbstate_t initial_mbs;
+
/*
* MT-safe version.
*/
char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
int index; /* for %index$ */
va_list ap_orig; /* to reset ap to first argument */
- static const mbstate_t initial;
mbstate_t mbs;
int mb_cur_max = MB_CUR_MAX_L(loc);
break;
case 'n':
- if (flags & SUPPRESS) /* ??? */
+ {
+ void *ptr = va_arg(ap, void *);
+ if ((ptr == NULL) || (flags & SUPPRESS)) /* ??? */
continue;
- if (flags & SHORTSHORT)
- *va_arg(ap, char *) = nread;
+ else if (flags & SHORTSHORT)
+ *(char *)ptr = nread;
else if (flags & SHORT)
- *va_arg(ap, short *) = nread;
+ *(short *)ptr = nread;
else if (flags & LONG)
- *va_arg(ap, long *) = nread;
+ *(long *)ptr = nread;
else if (flags & LONGLONG)
- *va_arg(ap, long long *) = nread;
+ *(long long *)ptr = nread;
else if (flags & INTMAXT)
- *va_arg(ap, intmax_t *) = nread;
+ *(intmax_t *)ptr = nread;
else if (flags & SIZET)
- *va_arg(ap, size_t *) = nread;
+ *(size_t *)ptr = nread;
else if (flags & PTRDIFFT)
- *va_arg(ap, ptrdiff_t *) = nread;
+ *(ptrdiff_t *)ptr = nread;
else
- *va_arg(ap, int *) = nread;
+ *(int *)ptr = nread;
continue;
-
+ }
default:
goto match_failure;
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while (width != 0 &&
(wi = __fgetwc(fp, loc)) != WEOF) {
if (width >= mb_cur_max &&
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp, loc)) != WEOF &&
width != 0 && INCCL(wi)) {
if (width >= mb_cur_max &&
} else {
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp, loc)) != WEOF &&
width != 0 &&
!iswspace_l(wi, loc)) {
float res = wcstof_l(pbuf, &p, loc);
*va_arg(ap, float *) = res;
}
- if (__scanfdebug && p - pbuf != width)
- LIBC_ABORT("p - pbuf %ld != width %ld", (long)(p - pbuf), width);
nassigned++;
}
nread += width;
static int
parsefloat(FILE *fp, wchar_t **buf, size_t width, locale_t loc)
{
+ mbstate_t mbs;
+ size_t nconv;
wchar_t *commit, *p;
int infnanpos = 0;
enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
wchar_t c;
- char *decimal_point;
wchar_t decpt;
_Bool gotmantdig = 0, ishex = 0;
wchar_t *b;
wchar_t *e;
size_t s;
+ mbs = initial_mbs;
+
+ nconv = mbrtowc_l(&decpt, localeconv()->decimal_point, MB_CUR_MAX_L(loc), &mbs, loc);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+
s = (width == 0 ? BUF : (width + 1));
if ((b = (wchar_t *)__parsefloat_buf(s * sizeof(wchar_t))) == NULL) {
*buf = NULL;
*/
commit = b - 1;
c = WEOF;
- decimal_point = localeconv_l(loc)->decimal_point;
- mbtowc_l(&decpt, decimal_point, strlen(decimal_point), loc);
for (p = b; width == 0 || p < e; ) {
if ((c = __fgetwc(fp, loc)) == WEOF)
break;
break;
case S_NAN:
switch (infnanpos) {
- case -1: /* XXX kludge to deal with nan(...) */
- goto parsedone;
case 0:
if (c != 'A' && c != 'a')
goto parsedone;
default:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
} else if (!iswalnum_l(c, loc) && c != '_')
goto parsedone;
break;
}
infnanpos++;
break;
+ case S_DONE:
+ goto parsedone;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x') {
* 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.
static char sccsid[] = "@(#)vprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vprintf.c,v 1.10 2002/09/06 11:23:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vprintf.c,v 1.11 2007/01/09 00:28:08 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)vscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vscanf.c,v 1.12 2003/01/03 23:27:27 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vscanf.c,v 1.13 2007/01/09 00:28:08 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)vsnprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vsnprintf.c,v 1.22 2003/07/02 07:08:44 jkh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vsnprintf.c,v 1.24 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
#include "local.h"
int
-vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt,
+vsnprintf_l(char * __restrict str, size_t n, locale_t loc, const char * __restrict fmt,
__va_list ap)
{
size_t on;
char dummy[2];
FILE f;
struct __sFILEX ext;
-
- on = n;
- if (n != 0)
- n--;
- if (n > INT_MAX)
- n = INT_MAX;
- /* Stdio internals do not deal correctly with zero length buffer */
- if (n == 0) {
- if (on > 0)
- *str = '\0';
- str = dummy;
- n = 1;
- }
- f._file = -1;
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = n;
f._extra = &ext;
INITEXTRA(&f);
- ret = __vfprintf(&f, __current_locale(), fmt, ap);
- if (on > 0)
- *f._p = '\0';
- return (ret);
-}
-
-int
-vsnprintf_l(char * __restrict str, size_t n, locale_t loc,
- const char * __restrict fmt, __va_list ap)
-{
- size_t on;
- int ret;
- char dummy[2];
- FILE f;
- struct __sFILEX ext;
NORMALIZE_LOCALE(loc);
on = n;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfprintf(&f, loc, fmt, ap);
if (on > 0)
*f._p = '\0';
return (ret);
}
+
+int
+vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt,
+ __va_list ap)
+{
+ return vsnprintf_l(str, n, __current_locale(), fmt, ap);
+}
* 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.
static char sccsid[] = "@(#)vsprintf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vsprintf.c,v 1.14 2002/09/06 11:23:56 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vsprintf.c,v 1.16 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
#include "local.h"
int
-vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap)
+vsprintf_l(char * __restrict str, locale_t loc, const char * __restrict fmt, __va_list ap)
{
int ret;
FILE f;
struct __sFILEX ext;
-
- f._file = -1;
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = INT_MAX;
f._extra = &ext;
INITEXTRA(&f);
- ret = __vfprintf(&f, __current_locale(), fmt, ap);
- *f._p = 0;
- return (ret);
-}
-
-int
-vsprintf_l(char * __restrict str, locale_t loc, const char * __restrict fmt,
- __va_list ap)
-{
- int ret;
- FILE f;
- struct __sFILEX ext;
NORMALIZE_LOCALE(loc);
f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfprintf(&f, loc, fmt, ap);
*f._p = 0;
return (ret);
}
+
+int
+vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap)
+{
+ return vsprintf_l(str, __current_locale(), fmt, ap);
+}
* 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.
static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.12 2002/10/12 16:13:41 mike Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.14 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
}
int
-vsscanf(str, fmt, ap)
+vsscanf_l(str, loc, fmt, ap)
const char * __restrict str;
+ locale_t loc;
const char * __restrict fmt;
__va_list ap;
{
FILE f;
struct __sFILEX ext;
+ f._extra = &ext;
+ INITEXTRA(&f);
f._file = -1;
f._flags = __SRD;
f._read = eofread;
f._ub._base = NULL;
f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
- return (__svfscanf_l(&f, __current_locale(), fmt, ap));
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
+ return (__svfscanf_l(&f, loc, fmt, ap));
}
int
-vsscanf_l(str, loc, fmt, ap)
+vsscanf(str, fmt, ap)
const char * __restrict str;
- locale_t loc;
const char * __restrict fmt;
__va_list ap;
{
- FILE f;
- struct __sFILEX ext;
-
- NORMALIZE_LOCALE(loc);
- f._file = -1;
- f._flags = __SRD;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._r = strlen(str);
- f._read = eofread;
- f._ub._base = NULL;
- f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
- return (__svfscanf_l(&f, loc, fmt, ap));
+ return vsscanf_l(str, __current_locale(), fmt, ap);
}
+
#if 0
__FBSDID("FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.16 2002/08/21 16:19:57 mike Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.5 2004/04/07 09:55:05 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.7 2008/04/17 22:17:54 jhb Exp $");
#include "xlocale_private.h"
#include "local.h"
int
-vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt,
- __va_list ap)
+vswprintf_l(wchar_t * __restrict s, size_t n, locale_t loc,
+ const wchar_t * __restrict fmt, __va_list ap)
{
static const mbstate_t initial;
mbstate_t mbs;
FILE f;
- struct __sFILEX ext;
char *mbp;
int ret, sverrno;
- size_t conv;
- locale_t loc = __current_locale();
+ size_t nwc;
+ struct __sFILEX ext;
+ f._extra = &ext;
+ INITEXTRA(&f);
+ NORMALIZE_LOCALE(loc);
if (n == 0) {
errno = EINVAL;
return (-1);
return (-1);
}
f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
ret = __vfwprintf(&f, loc, fmt, ap);
if (ret < 0) {
sverrno = errno;
return (-1);
}
*f._p = '\0';
- mbp = (char *)f._bf._base;
+ mbp = f._bf._base;
/*
* XXX Undo the conversion from wide characters to multibyte that
* fputwc() did in __vfwprintf().
*/
mbs = initial;
- if ((conv = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc)) == (size_t)-1) {
- free(f._bf._base);
+ nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc);
+ free(f._bf._base);
+ if (nwc == (size_t)-1) {
errno = EILSEQ;
return (-1);
}
- free(f._bf._base);
- if (conv >= n) {
+ if (nwc == n) {
s[n - 1] = L'\0';
errno = EOVERFLOW;
return (-1);
}
int
-vswprintf_l(wchar_t * __restrict s, size_t n, locale_t loc,
+vswprintf(wchar_t * __restrict s, size_t n,
const wchar_t * __restrict fmt, __va_list ap)
{
- static const mbstate_t initial;
- mbstate_t mbs;
- FILE f;
- struct __sFILEX ext;
- char *mbp;
- int ret, sverrno;
- size_t conv;
-
- NORMALIZE_LOCALE(loc);
- if (n == 0) {
- errno = EINVAL;
- return (-1);
- }
-
- f._file = -1;
- f._flags = __SWR | __SSTR | __SALC;
- f._bf._base = f._p = (unsigned char *)malloc(128);
- if (f._bf._base == NULL) {
- errno = ENOMEM;
- return (-1);
- }
- f._bf._size = f._w = 127; /* Leave room for the NUL */
- f._extra = &ext;
- INITEXTRA(&f);
- ret = __vfwprintf(&f, loc, fmt, ap);
- if (ret < 0) {
- sverrno = errno;
- free(f._bf._base);
- errno = sverrno;
- return (-1);
- }
- *f._p = '\0';
- mbp = (char *)f._bf._base;
- /*
- * XXX Undo the conversion from wide characters to multibyte that
- * fputwc() did in __vfwprintf().
- */
- mbs = initial;
- if ((conv = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, loc)) == (size_t)-1) {
- free(f._bf._base);
- errno = EILSEQ;
- return (-1);
- }
- free(f._bf._base);
- if (conv >= n) {
- s[n - 1] = L'\0';
- errno = EOVERFLOW;
- return (-1);
- }
-
- return (ret);
+ return vswprintf_l(s, n, __current_locale(), fmt, ap);
}
* 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.
#endif /* LIBC_SCCS and not lint */
__FBSDID("FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.11 2002/08/21 16:19:57 mike Exp ");
#endif
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vswscanf.c,v 1.3 2004/04/07 09:55:05 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vswscanf.c,v 1.6 2009/01/15 18:53:52 rdivacky Exp $");
#include "xlocale_private.h"
}
int
-vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
+vswscanf_l(const wchar_t * __restrict str, locale_t loc, const wchar_t * __restrict fmt,
va_list ap)
{
static const mbstate_t initial;
mbstate_t mbs;
FILE f;
- struct __sFILEX ext;
char *mbstr;
size_t mlen;
int r;
- locale_t loc = __current_locale();
+ const wchar_t *strp;
+ struct __sFILEX ext;
+ f._extra = &ext;
+ INITEXTRA(&f);
+ NORMALIZE_LOCALE(loc);
/*
* XXX Convert the wide character string to multibyte, which
* __vfwscanf() will convert back to wide characters.
if ((mbstr = malloc(wcslen(str) * MB_CUR_MAX_L(loc) + 1)) == NULL)
return (EOF);
mbs = initial;
- if ((mlen = wcsrtombs_l(mbstr, &str, SIZE_T_MAX, &mbs, loc)) == (size_t)-1) {
+ strp = str;
+ if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, loc)) == (size_t)-1) {
free(mbstr);
return (EOF);
}
f._read = eofread;
f._ub._base = NULL;
f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
+ f._orientation = 0;
+ memset(&f._mbstate, 0, sizeof(mbstate_t));
r = __vfwscanf(&f, loc, fmt, ap);
free(mbstr);
}
int
-vswscanf_l(const wchar_t * __restrict str, locale_t loc,
- const wchar_t * __restrict fmt, va_list ap)
+vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
+ va_list ap)
{
- static const mbstate_t initial;
- mbstate_t mbs;
- FILE f;
- struct __sFILEX ext;
- char *mbstr;
- size_t mlen;
- int r;
-
- NORMALIZE_LOCALE(loc);
- /*
- * XXX Convert the wide character string to multibyte, which
- * __vfwscanf() will convert back to wide characters.
- */
- if ((mbstr = malloc(wcslen(str) * MB_CUR_MAX_L(loc) + 1)) == NULL)
- return (EOF);
- mbs = initial;
- if ((mlen = wcsrtombs_l(mbstr, &str, SIZE_T_MAX, &mbs, loc)) == (size_t)-1) {
- free(mbstr);
- return (EOF);
- }
- f._file = -1;
- f._flags = __SRD;
- f._bf._base = f._p = (unsigned char *)mbstr;
- f._bf._size = f._r = mlen;
- f._read = eofread;
- f._ub._base = NULL;
- f._lb._base = NULL;
- f._extra = &ext;
- INITEXTRA(&f);
- r = __vfwscanf(&f, loc, fmt, ap);
- free(mbstr);
-
- return (r);
+ return vswscanf_l(str, __current_locale(), fmt, ap);
}
+
* 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.
static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/wbuf.c,v 1.11 2004/06/08 05:45:32 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/wbuf.c,v 1.12 2007/01/09 00:28:08 imp Exp $");
#include <stdio.h>
#include <errno.h>
.\" 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.
.\"
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/stdio/printf.3,v 1.47 2002/09/06 11:23:55 tjr Exp
-.\" $FreeBSD: src/lib/libc/stdio/wprintf.3,v 1.5 2003/07/05 07:55:34 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/wprintf.3,v 1.6 2007/01/09 00:28:08 imp Exp $
.\"
.Dd July 5, 2003
.Dt WPRINTF 3
.\" 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.
.\"
.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
.\" FreeBSD: src/lib/libc/stdio/scanf.3,v 1.24 2003/06/28 09:03:25 das Exp
-.\" $FreeBSD: src/lib/libc/stdio/wscanf.3,v 1.6 2003/07/05 07:47:55 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdio/wscanf.3,v 1.7 2007/01/09 00:28:08 imp Exp $
.\"
.Dd July 5, 2003
.Dt WSCANF 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)abort.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/abort.3,v 1.9 2001/09/09 18:52:00 asmodai Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/abort.3,v 1.10 2007/01/09 00:28:09 imp Exp $
.\"
.Dd June 4, 1993
.Dt ABORT 3
--- /dev/null
+--- abort.3.orig 2010-02-22 12:52:54.000000000 -0800
++++ abort.3 2010-02-22 12:56:29.000000000 -0800
+@@ -58,6 +58,13 @@ The
+ .Fn abort
+ function is thread-safe.
+ It is unknown if it is async-cancel-safe.
++.Pp
++The
++.Fn abort
++function causes a report to be generated by Crash Reporter. If you wish to
++terminate without generating a crash report, use
++.Xr exit 3
++instead.
+ .Sh RETURN VALUES
+ The
+ .Fn abort
* 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.
static char sccsid[] = "@(#)abort.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.9 2003/08/16 11:43:57 davidxu Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.11 2007/01/09 00:28:09 imp Exp $");
#include "namespace.h"
#include <signal.h>
#include <pthread.h>
#include "un-namespace.h"
-void (*__cleanup)();
+#include "libc_private.h"
void
abort()
---- abort.c.orig 2008-09-07 11:37:51.000000000 -0700
-+++ abort.c 2008-09-07 11:56:01.000000000 -0700
-@@ -39,19 +39,26 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
+--- abort.c.orig 2010-09-07 22:42:56.000000000 -0700
++++ abort.c 2010-09-07 22:46:29.000000000 -0700
+@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include "namespace.h"
#include <signal.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
- #include <pthread.h>
- #include "un-namespace.h"
+@@ -43,11 +44,22 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
--void (*__cleanup)();
+ #include "libc_private.h"
+
++#include "CrashReporterClient.h"
++#include "_simple.h"
++
+extern void (*__cleanup)();
+extern void __abort(void) __dead2;
-+extern const char *__crashreporter_info__;
+
+#define TIMEOUT 10000 /* 10 milliseconds */
-
++
void
abort()
{
struct sigaction act;
-+ if (!__crashreporter_info__)
-+ __crashreporter_info__ = "abort() called";
++ if (!CRGetCrashLogMessage())
++ CRSetCrashLogMessage("abort() called");
++
/*
* POSIX requires we flush stdio buffers on abort.
* XXX ISO C requires that abort() be async-signal-safe.
-@@ -67,11 +74,22 @@ abort()
+@@ -61,19 +73,90 @@ abort()
+ * any errors -- ISO C doesn't allow abort to return anyway.
+ */
sigdelset(&act.sa_mask, SIGABRT);
- (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
- (void)raise(SIGABRT);
+- (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
+- (void)raise(SIGABRT);
++
++ /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread
++ * This helps gdb focus on the thread calling abort()
++ */
++ if (__is_threaded) {
++ /* Block all signals on all other threads */
++ sigset_t fullmask;
++ sigfillset(&fullmask);
++ (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
++
++ /* <rdar://problem/8400096> Set the workqueue killable */
++ __pthread_workqueue_setkill(1);
++
++ (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
++ (void)pthread_kill(pthread_self(), SIGABRT);
++ } else {
++ (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
++ (void)kill(getpid(), SIGABRT);
++ }
+ usleep(TIMEOUT); /* give time for signal to happen */
/*
+{
+ struct sigaction act;
+
-+ if (!__crashreporter_info__)
-+ __crashreporter_info__ = "__abort() called";
++ if (!CRGetCrashLogMessage())
++ CRSetCrashLogMessage("__abort() called");
act.sa_handler = SIG_DFL;
act.sa_flags = 0;
sigfillset(&act.sa_mask);
-@@ -79,5 +97,19 @@ abort()
+ (void)_sigaction(SIGABRT, &act, NULL);
sigdelset(&act.sa_mask, SIGABRT);
++
++ /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread
++ * This helps gdb focus on the thread calling abort()
++ */
++ if (__is_threaded) {
++ /* Block all signals on all other threads */
++ sigset_t fullmask;
++ sigfillset(&fullmask);
++ (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
++
++ /* <rdar://problem/8400096> Set the workqueue killable */
++ __pthread_workqueue_setkill(1);
++
++ (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
++ (void)pthread_kill(pthread_self(), SIGABRT);
++ } else {
++ (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
++ (void)kill(getpid(), SIGABRT);
++ }
++ usleep(TIMEOUT); /* give time for signal to happen */
++
++ /* If for some reason SIGABRT was not delivered, we exit using __builtin_trap
++ * which generates an illegal instruction on i386: <rdar://problem/8400958>
++ * and SIGTRAP on arm.
++ */
++ sigfillset(&act.sa_mask);
++ sigdelset(&act.sa_mask, SIGILL);
++ sigdelset(&act.sa_mask, SIGTRAP);
(void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
- (void)raise(SIGABRT);
+- (void)raise(SIGABRT);
- exit(1);
-+ usleep(TIMEOUT); /* give time for signal to happen */
-+ __builtin_trap(); /* never exit normally */
++ __builtin_trap();
+}
+
+__private_extern__ void
+abort_report_np(const char *fmt, ...)
+{
-+ char *str;
++ _SIMPLE_STRING s;
+ va_list ap;
+
-+ va_start(ap, fmt);
-+ vasprintf(&str, fmt, ap);
-+ va_end(ap);
-+ __crashreporter_info__ = str ? str : fmt;
++ if ((s = _simple_salloc()) != NULL) {
++ va_start(ap, fmt);
++ _simple_vsprintf(s, fmt, ap);
++ va_end(ap);
++ CRSetCrashLogMessage(_simple_string(s));
++ } else
++ CRSetCrashLogMessage(fmt); /* the format string is better than nothing */
+ abort();
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)abs.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/abs.3,v 1.12 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/abs.3,v 1.13 2007/01/09 00:28:09 imp Exp $
.\"
.Dd November 14, 2001
.Dt ABS 3
---- abs.3 2003-05-20 15:23:24.000000000 -0700
-+++ abs.3.edit 2006-09-27 18:20:25.000000000 -0700
-@@ -47,14 +47,12 @@
+--- abs.3.bsdnew 2009-11-13 14:11:46.000000000 -0800
++++ abs.3 2009-11-13 14:11:46.000000000 -0800
+@@ -43,14 +43,12 @@
.Sh SYNOPSIS
.In stdlib.h
.Ft int
* 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.
static char sccsid[] = "@(#)abs.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/abs.c,v 1.2 2002/03/22 21:53:09 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/abs.c,v 1.3 2007/01/09 00:28:09 imp Exp $");
#include <stdlib.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)alloca.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/alloca.3,v 1.11 2003/06/28 22:12:30 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/alloca.3,v 1.13 2007/01/09 00:28:09 imp Exp $
.\"
-.Dd June 4, 1993
+.Dd September 5, 2006
.Dt ALLOCA 3
.Os
.Sh NAME
The
.Fn alloca
function returns a pointer to the beginning of the allocated space.
-If the allocation failed, a
-.Dv NULL
-pointer is returned.
.Sh SEE ALSO
.Xr brk 2 ,
.Xr calloc 3 ,
function
is machine and compiler dependent;
its use is discouraged.
+.Pp
+The
+.Fn alloca
+function is slightly unsafe because it cannot ensure that the pointer
+returned points to a valid and usable block of memory.
+The allocation made may exceed the bounds of the stack, or even go
+further into other objects in memory, and
+.Fn alloca
+cannot determine such an error.
+Avoid
+.Fn alloca
+with large unbounded allocations.
---- /Volumes/XDisk/tmp/Libc/stdlib/FreeBSD/alloca.3.orig 2003-06-28 15:12:30.000000000 -0700
-+++ /Volumes/XDisk/tmp/Libc/stdlib/FreeBSD/alloca.3 2004-10-24 17:08:31.000000000 -0700
-@@ -41,6 +41,9 @@
- .Sh LIBRARY
- .Lb libc
+--- alloca.3.orig 2010-02-22 12:44:05.000000000 -0800
++++ alloca.3 2010-02-22 12:50:53.000000000 -0800
+@@ -34,25 +34,25 @@
+ .Sh NAME
+ .Nm alloca
+ .Nd memory allocator
+-.Sh LIBRARY
+-.Lb libc
.Sh SYNOPSIS
+.In alloca.h
+or
.In stdlib.h
.Ft void *
.Fn alloca "size_t size"
+ .Sh DESCRIPTION
+ The
+ .Fn alloca
+-function
++macro
+ allocates
+ .Fa size
+ bytes of space in the stack frame of the caller.
+ This temporary space is automatically freed on
+ return.
+ .Sh RETURN VALUES
+-The
+ .Fn alloca
+-function returns a pointer to the beginning of the allocated space.
++returns a pointer to the beginning of the allocated space.
+ .Sh SEE ALSO
+ .Xr brk 2 ,
+ .Xr calloc 3 ,
+@@ -60,24 +60,20 @@ function returns a pointer to the beginn
+ .Xr malloc 3 ,
+ .Xr realloc 3
+ .Sh HISTORY
+-The
+ .Fn alloca
+-function appeared in
++appeared in
+ .At 32v .
+ .\" .Bx ?? .
+ .\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
+ .\" The first man page (or link to a man page that I can find at the
+ .\" moment is 4.3...
+ .Sh BUGS
+-The
+ .Fn alloca
+-function
+ is machine and compiler dependent;
+ its use is discouraged.
+ .Pp
+-The
+ .Fn alloca
+-function is slightly unsafe because it cannot ensure that the pointer
++is slightly unsafe because it cannot ensure that the pointer
+ returned points to a valid and usable block of memory.
+ The allocation made may exceed the bounds of the stack, or even go
+ further into other objects in memory, and
+@@ -86,3 +82,8 @@ cannot determine such an error.
+ Avoid
+ .Fn alloca
+ with large unbounded allocations.
++.Pp
++The use of C99 variable-length arrays and
++.Fn alloca
++in the same function will cause the lifetime of alloca's storage to be limited to the block containing the
++.Fn alloca
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atexit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.10 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.11 2007/01/09 00:28:09 imp Exp $
.\"
.Dd September 6, 2002
.Dt ATEXIT 3
---- atexit.3.orig 2009-05-12 11:21:33.000000000 -0700
-+++ atexit.3 2009-05-20 14:13:00.000000000 -0700
-@@ -36,46 +36,69 @@
+--- atexit.3.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ atexit.3 2009-11-13 14:11:47.000000000 -0800
+@@ -32,46 +32,69 @@
.\" @(#)atexit.3 8.1 (Berkeley) 6/4/93
- .\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.10 2002/12/18 13:33:03 ru Exp $
+ .\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.11 2007/01/09 00:28:09 imp Exp $
.\"
-.Dd September 6, 2002
+.Dd May 20, 2008
* 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.
static char sccsid[] = "@(#)atexit.c 8.2 (Berkeley) 7/3/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.7 2003/12/19 17:11:20 kan Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.8 2007/01/09 00:28:09 imp Exp $");
#include "namespace.h"
#include <stddef.h>
---- atexit.c.orig 2009-05-12 11:21:33.000000000 -0700
-+++ atexit.c 2009-05-23 13:46:33.000000000 -0700
-@@ -45,14 +45,23 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
+--- atexit.c.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ atexit.c 2009-11-13 14:11:47.000000000 -0800
+@@ -41,14 +41,23 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
-+#if defined(__DYNAMIC__)
++#if defined(__DYNAMIC__) || defined (__BLOCKS__)
+#include <dlfcn.h>
+#endif /* defined(__DYNAMIC__) */
#include "atexit.h"
static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
-@@ -67,6 +76,9 @@ struct atexit {
+@@ -63,6 +72,9 @@ struct atexit {
union {
void (*std_func)(void);
void (*cxa_func)(void *);
} fn_ptr; /* function pointer */
void *fn_arg; /* argument for CXA callback */
void *fn_dso; /* shared module handle */
-@@ -74,6 +86,7 @@ struct atexit {
+@@ -70,6 +82,7 @@ struct atexit {
};
static struct atexit *__atexit; /* points to head of LIFO stack */
/*
* Register the function described by 'fptr' to be called at application
-@@ -109,6 +122,7 @@ atexit_register(struct atexit_fn *fptr)
+@@ -105,6 +118,7 @@ atexit_register(struct atexit_fn *fptr)
__atexit = p;
}
p->fns[p->ind++] = *fptr;
_MUTEX_UNLOCK(&atexit_mutex);
return 0;
}
-@@ -120,17 +134,50 @@ int
+@@ -116,17 +130,50 @@ int
atexit(void (*func)(void))
{
struct atexit_fn fn;
/*
* Register a function to be performed at exit or when an shared object
* with given dso handle is unloaded dynamically.
-@@ -156,13 +203,14 @@ __cxa_atexit(void (*func)(void *), void
+@@ -152,13 +199,14 @@ __cxa_atexit(void (*func)(void *), void
* handlers are called.
*/
void
for (p = __atexit; p; p = p->next) {
for (n = p->ind; --n >= 0;) {
if (p->fns[n].fn_type == ATEXIT_FN_EMPTY)
-@@ -175,6 +223,7 @@ __cxa_finalize(void *dso)
+@@ -171,6 +219,7 @@ __cxa_finalize(void *dso)
has already been called.
*/
p->fns[n].fn_type = ATEXIT_FN_EMPTY;
_MUTEX_UNLOCK(&atexit_mutex);
/* Call the function of correct type. */
-@@ -182,7 +231,13 @@ __cxa_finalize(void *dso)
+@@ -178,7 +227,13 @@ __cxa_finalize(void *dso)
fn.fn_ptr.cxa_func(fn.fn_arg);
else if (fn.fn_type == ATEXIT_FN_STD)
fn.fn_ptr.std_func();
* 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.
* SUCH DAMAGE.
*
* @(#)atexit.h 8.2 (Berkeley) 7/3/94
- * $FreeBSD: src/lib/libc/stdlib/atexit.h,v 1.3 2003/12/19 17:11:20 kan Exp $
+ * $FreeBSD: src/lib/libc/stdlib/atexit.h,v 1.4 2007/01/09 00:28:09 imp Exp $
*/
/* must be at least 32 to guarantee ANSI conformance */
---- atexit.h.orig 2004-03-11 13:16:53.000000000 -0800
-+++ atexit.h 2004-09-15 00:15:16.000000000 -0700
-@@ -37,4 +37,4 @@
+--- atexit.h.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ atexit.h 2009-11-13 14:11:47.000000000 -0800
+@@ -33,4 +33,4 @@
/* must be at least 32 to guarantee ANSI conformance */
#define ATEXIT_SIZE 32
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atof.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atof.3,v 1.16 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atof.3,v 1.17 2007/01/09 00:28:09 imp Exp $
.\"
.Dd June 4, 1993
.Dt ATOF 3
---- atof.3.orig 2007-04-08 18:49:34.000000000 -0700
-+++ atof.3 2007-04-08 19:18:24.000000000 -0700
-@@ -40,7 +40,8 @@
+--- atof.3.orig 2010-02-08 16:26:10.000000000 -0800
++++ atof.3 2010-02-13 20:58:26.000000000 -0800
+@@ -36,7 +36,8 @@
.Dt ATOF 3
.Os
.Sh NAME
.Nd convert
.Tn ASCII
string to double
-@@ -49,24 +50,35 @@
+@@ -45,33 +46,50 @@ string to double
.Sh SYNOPSIS
.In stdlib.h
.Ft double
.Sh IMPLEMENTATION NOTES
The
.Fn atof
-@@ -88,7 +100,8 @@
+-function is not thread-safe and also not async-cancel-safe.
++and
++.Fn atof_l
++functions are thread-safe and async-cancel-safe.
+ .Pp
+ The
+ .Fn atof
+-function has been deprecated by
++and
++.Fn atof_l
++functions have been deprecated by
+ .Fn strtod
++and
++.Fn strtod_l
+ and should not be used in new code.
+ .Sh ERRORS
+ The function
+@@ -84,7 +102,8 @@ on an error.
.Xr atol 3 ,
.Xr strtod 3 ,
.Xr strtol 3 ,
* 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.
static char sccsid[] = "@(#)atof.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atof.c,v 1.5 2004/02/10 20:42:32 cperciva Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atof.c,v 1.6 2007/01/09 00:28:09 imp Exp $");
#include <stdlib.h>
---- atof.c.orig 2004-11-25 11:38:41.000000000 -0800
-+++ atof.c 2005-02-23 18:31:38.000000000 -0800
-@@ -37,11 +37,22 @@
+--- atof.c.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ atof.c 2009-11-13 14:11:47.000000000 -0800
+@@ -33,11 +33,22 @@ static char sccsid[] = "@(#)atof.c 8.1 (
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/atof.c,v 1.5 2004/02/10 20:42:32 cperciva Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/atof.c,v 1.6 2007/01/09 00:28:09 imp Exp $");
+#include "xlocale_private.h"
+
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atoi.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atoi.3,v 1.12 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atoi.3,v 1.14 2007/10/19 06:23:39 davidxu Exp $
.\"
.Dd June 4, 1993
.Dt ATOI 3
.Bd -literal -offset indent
(int)strtol(nptr, (char **)NULL, 10);
.Ed
-.Sh IMPLEMENTATION NOTES
-The
-.Fn atoi
-function is not thread-safe and also not async-cancel safe.
.Pp
The
.Fn atoi
---- atoi.3.orig 2007-04-08 18:49:34.000000000 -0700
-+++ atoi.3 2007-04-08 19:19:59.000000000 -0700
-@@ -40,7 +40,8 @@
+--- atoi.3.orig 2010-02-08 16:26:10.000000000 -0800
++++ atoi.3 2010-02-13 20:59:41.000000000 -0800
+@@ -36,7 +36,8 @@
.Dt ATOI 3
.Os
.Sh NAME
.Nd convert
.Tn ASCII
string to integer
-@@ -49,20 +50,31 @@
+@@ -45,25 +46,46 @@ string to integer
.Sh SYNOPSIS
.In stdlib.h
.Ft int
-(int)strtol(nptr, (char **)NULL, 10);
+(int)strtol(str, (char **)NULL, 10);
.Ed
-+.Pp
+ .Pp
+While the
+.Fn atoi
+function uses the current locale, the
+function may be passed a locale directly. See
+.Xr xlocale 3
+for more information.
- .Sh IMPLEMENTATION NOTES
++.Sh IMPLEMENTATION NOTES
++The
++.Fn atoi
++and
++.Fn atoi_l
++functions are thread-safe and async-cancel-safe.
++.Pp
The
.Fn atoi
-@@ -84,7 +96,8 @@
+-function has been deprecated by
++and
++.Fn atoi_l
++functions have been deprecated by
+ .Fn strtol
++and
++.Fn strtol_l
+ and should not be used in new code.
+ .Sh ERRORS
+ The function
+@@ -76,7 +98,8 @@ on an error.
.Xr atol 3 ,
.Xr strtod 3 ,
.Xr strtol 3 ,
* 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.
static char sccsid[] = "@(#)atoi.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoi.c,v 1.5 2002/03/22 21:53:09 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoi.c,v 1.6 2007/01/09 00:28:09 imp Exp $");
#include <stdlib.h>
---- atoi.c.orig 2003-05-20 15:23:24.000000000 -0700
-+++ atoi.c 2005-02-23 18:32:57.000000000 -0800
-@@ -37,11 +37,22 @@
+--- atoi.c.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ atoi.c 2009-11-13 14:11:47.000000000 -0800
+@@ -33,11 +33,22 @@ static char sccsid[] = "@(#)atoi.c 8.1 (
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/atoi.c,v 1.5 2002/03/22 21:53:09 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/atoi.c,v 1.6 2007/01/09 00:28:09 imp Exp $");
+#include "xlocale_private.h"
+
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atol.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atol.3,v 1.13 2002/01/09 14:03:54 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atol.3,v 1.16 2009/03/01 05:44:28 delphij Exp $
.\"
-.Dd November 28, 2001
+.Dd February 1, 2009
.Dt ATOL 3
.Os
.Sh NAME
It is equivalent to:
.Pp
.Dl "strtoll(nptr, (char **)NULL, 10);"
+.Sh COMPATIBILITY
+The
+.Fx
+implementations of the
+.Fn atol
+and
+.Fn atoll
+functions are thin wrappers around
+.Fn strtol
+and
+.Fn stroll
+respectively, so these functions will affect the value of
+.Va errno
+in the same way that the
+.Fn strtol
+and
+.Fn stroll
+functions are able to.
+This behavior of
+.Fn atol
+and
+.Fn atoll
+is not required by
+.St -isoC
+or
+.St -isoC-99 ,
+but it is allowed by all of
+.St -isoC , St -isoC-99
+and
+.St -p1003.1-2001 .
.Sh ERRORS
The functions
.Fn atol
and
.Fn atoll
-need not
-affect the value of
+may affect the value of
.Va errno
on an error.
.Sh SEE ALSO
---- atol.3.orig 2007-04-08 18:49:34.000000000 -0700
-+++ atol.3 2007-04-08 19:21:38.000000000 -0700
-@@ -40,7 +40,8 @@
+--- atol.3.orig 2010-02-08 16:26:10.000000000 -0800
++++ atol.3 2010-02-13 21:01:28.000000000 -0800
+@@ -36,7 +36,8 @@
.Dt ATOL 3
.Os
.Sh NAME
.Nd convert
.Tn ASCII
string to
-@@ -53,14 +54,19 @@
+@@ -49,14 +50,19 @@ integer
.Sh SYNOPSIS
.In stdlib.h
.Ft long
to
.Vt long
integer
-@@ -68,12 +74,12 @@
+@@ -64,12 +70,12 @@ representation.
.Pp
It is equivalent to:
.Pp
to
.Vt "long long"
integer
-@@ -81,7 +87,19 @@
+@@ -77,8 +83,28 @@ representation.
.Pp
It is equivalent to:
.Pp
-.Dl "strtoll(nptr, (char **)NULL, 10);"
+-.Sh COMPATIBILITY
+.Dl "strtoll(str, (char **)NULL, 10);"
+.Pp
+While the
+functions may be passed locales directly. See
+.Xr xlocale 3
+for more information.
- .Sh ERRORS
- The functions
- .Fn atol
-@@ -96,7 +114,8 @@
++.Sh IMPLEMENTATION NOTES
++The
++.Fn atol ,
++.Fn atoll ,
++.Fn atol_l ,
++and
++.Fn atoll_l
++functions are thread-safe and async-cancel-safe.
++.Pp
+ The
+ .Fx
+ implementations of the
+@@ -121,7 +147,8 @@ on an error.
.Xr atoi 3 ,
.Xr strtod 3 ,
.Xr strtol 3 ,
* 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.
static char sccsid[] = "@(#)atol.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atol.c,v 1.4 2002/03/22 21:53:09 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atol.c,v 1.5 2007/01/09 00:28:09 imp Exp $");
#include <stdlib.h>
---- atol.c.orig 2003-05-20 15:23:24.000000000 -0700
-+++ atol.c 2005-02-23 18:33:54.000000000 -0800
-@@ -37,11 +37,22 @@
+--- atol.c.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ atol.c 2009-11-13 14:11:47.000000000 -0800
+@@ -33,11 +33,22 @@ static char sccsid[] = "@(#)atol.c 8.1 (
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/atol.c,v 1.4 2002/03/22 21:53:09 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/atol.c,v 1.5 2007/01/09 00:28:09 imp Exp $");
+#include "xlocale_private.h"
+
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoll.c,v 1.4 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoll.c,v 1.5 2007/01/09 00:28:09 imp Exp $");
#include <stdlib.h>
---- atoll.c.orig 2003-05-20 15:23:24.000000000 -0700
-+++ atoll.c 2005-02-23 18:35:02.000000000 -0800
-@@ -34,11 +34,22 @@
+--- atoll.c.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ atoll.c 2009-11-13 14:11:47.000000000 -0800
+@@ -30,11 +30,22 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/atoll.c,v 1.4 2002/03/22 21:53:10 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/atoll.c,v 1.5 2007/01/09 00:28:09 imp Exp $");
+#include "xlocale_private.h"
+
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.8 2001/09/07 14:46:35 asmodai Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.9 2007/01/09 00:28:09 imp Exp $
.\"
.Dd April 19, 1994
.Dt BSEARCH 3
---- bsearch.3.orig 2009-05-12 11:21:33.000000000 -0700
-+++ bsearch.3 2009-05-20 14:53:48.000000000 -0700
-@@ -36,30 +36,37 @@
+--- bsearch.3.bsdnew 2009-11-13 14:11:47.000000000 -0800
++++ bsearch.3 2009-11-13 14:11:48.000000000 -0800
+@@ -32,30 +32,37 @@
.\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94
- .\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.8 2001/09/07 14:46:35 asmodai Exp $
+ .\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.9 2007/01/09 00:28:09 imp Exp $
.\"
-.Dd April 19, 1994
+.Dd May 20, 2008
.Pp
The contents of the array should be in ascending sorted order according
to the comparison function referenced by
-@@ -70,15 +77,33 @@
+@@ -66,15 +73,33 @@ routine
is expected to have
two arguments which point to the
.Fa key
* 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.
static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/bsearch.c,v 1.3 2002/03/21 22:48:41 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/bsearch.c,v 1.4 2007/01/09 00:28:09 imp Exp $");
#include <stddef.h>
#include <stdlib.h>
---- bsearch.c.orig 2009-05-12 11:21:33.000000000 -0700
-+++ bsearch.c 2009-05-20 13:11:05.000000000 -0700
-@@ -81,3 +81,31 @@ bsearch(key, base0, nmemb, size, compar)
+--- bsearch.c.bsdnew 2009-11-13 14:11:48.000000000 -0800
++++ bsearch.c 2009-11-13 14:11:48.000000000 -0800
+@@ -77,3 +77,31 @@ bsearch(key, base0, nmemb, size, compar)
}
return (NULL);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)div.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/div.3,v 1.8 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/div.3,v 1.9 2007/01/09 00:28:09 imp Exp $
.\"
.Dd November 14, 2001
.Dt DIV 3
---- _SB/Libc/stdlib/FreeBSD/div.3 2003-05-20 15:23:24.000000000 -0700
-+++ _SB/Libc/stdlib/FreeBSD/div.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -45,21 +45,23 @@
+--- div.3.bsdnew 2009-11-13 14:11:48.000000000 -0800
++++ div.3 2009-11-13 14:11:48.000000000 -0800
+@@ -41,21 +41,23 @@
.Sh SYNOPSIS
.In stdlib.h
.Ft div_t
* 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.
static char sccsid[] = "@(#)div.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/div.c,v 1.2 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/div.c,v 1.3 2007/01/09 00:28:09 imp Exp $");
#include <stdlib.h> /* div_t */
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)exit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/exit.3,v 1.15 2004/07/04 20:55:48 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/exit.3,v 1.16 2007/01/09 00:28:09 imp Exp $
.\"
.Dd September 9, 2002
.Dt EXIT 3
* 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.
static char sccsid[] = "@(#)exit.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/exit.c,v 1.7 2003/12/19 17:11:20 kan Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/exit.c,v 1.9 2007/01/09 00:28:09 imp Exp $");
#include "namespace.h"
#include <stdlib.h>
#include <unistd.h>
#include "un-namespace.h"
+
#include "atexit.h"
+#include "libc_private.h"
-void (*__cleanup)();
+void (*__cleanup)(void);
/*
* This variable is zero until a process has created a thread.
---- exit.c.orig 2006-08-08 16:13:56.000000000 -0700
-+++ exit.c 2006-08-11 22:12:56.000000000 -0700
-@@ -44,15 +44,7 @@
- #include "atexit.h"
+--- exit.c.bsdnew 2009-11-13 14:11:48.000000000 -0800
++++ exit.c 2009-11-13 14:47:07.000000000 -0800
+@@ -42,15 +42,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
+ #include "libc_private.h"
- void (*__cleanup)();
+ void (*__cleanup)(void);
-
-/*
- * This variable is zero until a process has created a thread.
/*
* Exit, flushing stdio buffers if necessary.
-@@ -61,13 +53,8 @@
+@@ -59,13 +51,8 @@ void
exit(status)
int status;
{
* 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.
static char sccsid[] = "@(#)getenv.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/getenv.c,v 1.4 2002/03/21 22:48:41 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/getenv.c,v 1.8 2007/05/01 16:02:41 ache Exp $");
#include <stdlib.h>
#include <stddef.h>
---- getenv.c.orig 2006-08-29 00:12:28.000000000 -0700
-+++ getenv.c 2006-08-29 00:13:31.000000000 -0700
-@@ -40,8 +40,9 @@
+--- getenv.c.bsdnew 2009-11-13 15:14:36.000000000 -0800
++++ getenv.c 2009-11-13 15:14:50.000000000 -0800
+@@ -36,8 +36,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
/*
* __findenv --
-@@ -52,12 +53,12 @@
+@@ -48,12 +49,12 @@ inline char *__findenv(const char *, int
*
* This routine *should* be a static; don't use it.
*/
int len, i;
const char *np;
char **p, *cp;
-@@ -80,6 +81,19 @@
+@@ -76,6 +77,19 @@ __findenv(name, offset)
}
/*
* getenv --
* Returns ptr to value associated with name, if any, else NULL.
*/
-@@ -89,5 +103,5 @@
+@@ -85,5 +99,5 @@ getenv(name)
{
int offset;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
-.\" $FreeBSD: src/lib/libc/stdlib/getopt.3,v 1.25 2004/07/31 01:00:50 imp Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/getopt.3,v 1.26 2007/01/09 00:28:10 imp Exp $
.\"
.Dd April 27, 1995
.Dt GETOPT 3
* 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.
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.7 2004/03/06 17:05:45 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.8 2007/01/09 00:28:10 imp Exp $");
#include "namespace.h"
#include <stdio.h>
---- ../Libc/stdlib/FreeBSD/getopt.c 2004-11-25 11:38:41.000000000 -0800
-+++ getopt.c 2005-01-26 19:27:09.000000000 -0800
-@@ -48,16 +48,24 @@
+--- getopt.c.bsdnew 2009-11-13 14:11:48.000000000 -0800
++++ getopt.c 2009-11-13 14:11:48.000000000 -0800
+@@ -44,16 +44,24 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include "libc_private.h"
/*
* getopt --
* Parse argc/argv argument vector.
-@@ -103,8 +111,8 @@
+@@ -99,8 +107,8 @@ getopt(nargc, nargv, ostr)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
return (BADCH);
}
-@@ -123,13 +131,19 @@
+@@ -119,13 +127,19 @@ getopt(nargc, nargv, ostr)
optarg = nargv[optind];
else {
/* option-argument absent */
.\" SUCH DAMAGE.
.\"
.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
-.\" $FreeBSD: src/lib/libc/stdlib/getopt_long.3,v 1.11 2004/03/06 14:47:49 ache Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/getopt_long.3,v 1.13 2005/01/20 09:17:04 ru Exp $
.\"
.Dd April 1, 2000
.Dt GETOPT_LONG 3
no argument to the option is expect
.It Dv required_argument
an argument to the option is required
-.It Li optional_argument
+.It Dv optional_argument
an argument to the option may be presented.
.El
.Pp
If the
.Fa flag
field in
-.Li struct option
+.Vt "struct option"
is
.Dv NULL ,
.Fn getopt_long
.Ql \&?
if the user specified an unknown or ambiguous option, and
\-1 when the argument list has been exhausted.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev POSIXLY_CORRECT"
+.It Ev POSIXLY_CORRECT
+If set, option processing stops when the first non-option is found and
+a leading
+.Ql -
+or
+.Ql +
+in the
+.Fa optstring
+is ignored.
+.El
.Sh EXAMPLES
.Bd -literal -compact
int bflag, ch, fd;
to current positions) are the same, though.
(We do fewer variable swaps.)
.El
-.Sh ENVIRONMENT
-.Bl -tag -width POSIXLY_CORRECT
-.It Ev POSIXLY_CORRECT
-If set, option processing stops when the first non-option is found and
-a leading
-.Ql -
-or
-.Ql +
-in the
-.Ar optstring
-is ignored.
-.El
.Sh SEE ALSO
.Xr getopt 3
.Sh HISTORY
.Fx 5.2 .
.Sh BUGS
The
-.Ar argv
+.Fa argv
argument is not really
-.Dv const
+.Vt const
as its elements may be permuted (unless
.Ev POSIXLY_CORRECT
is set).
-/* $OpenBSD: getopt_long.c,v 1.17 2004/06/03 18:46:52 millert Exp $ */
+/* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.12 2004/07/06 13:58:45 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.15 2006/09/23 14:48:31 ache Exp $");
#include <err.h>
#include <errno.h>
#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
-#ifndef GNU_COMPATIBLE
+#if 0 /* we prefer to keep our getopt(3) */
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
#endif
{
char *oli; /* option letter list index */
int optchar, short_too;
- int posixly_correct;
+ int posixly_correct; /* no static, can be changed on the fly */
if (options == NULL)
return (-1);
optarg = NULL;
if (*place) /* no white space */
optarg = place;
- /* XXX: disable test for :: if PC? (GNU doesn't) */
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
return (BADARG);
} else
optarg = nargv[optind];
- } else if (!(flags & FLAG_PERMUTE)) {
- /*
- * If permutation is disabled, we can accept an
- * optional arg separated by whitespace so long
- * as it does not start with a dash (-).
- */
- if (optind + 1 < nargc && *nargv[optind + 1] != '-')
- optarg = nargv[++optind];
}
place = EMSG;
++optind;
* Parse argc/argv argument vector.
*/
int
-getopt_long(nargc, nargv, options, long_options, idx)
- int nargc;
- char * const *nargv;
- const char *options;
- const struct option *long_options;
- int *idx;
+getopt_long(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
* Parse argc/argv argument vector.
*/
int
-getopt_long_only(nargc, nargv, options, long_options, idx)
- int nargc;
- char * const *nargv;
- const char *options;
- const struct option *long_options;
- int *idx;
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/stdlib/getsubopt.3,v 1.10 2004/02/23 03:32:10 ache Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/getsubopt.3,v 1.11 2007/01/09 00:28:10 imp Exp $
.\"
.Dd June 9, 1993
.Dt GETSUBOPT 3
---- _SB/Libc/stdlib/FreeBSD/getsubopt.3 2004-11-25 11:38:41.000000000 -0800
-+++ _SB/Libc/stdlib/FreeBSD/getsubopt.3.edit 2006-06-28 16:55:52.000000000 -0700
-@@ -44,23 +44,27 @@
+--- getsubopt.3.bsdnew 2009-11-13 14:11:48.000000000 -0800
++++ getsubopt.3 2009-11-13 14:11:48.000000000 -0800
+@@ -40,23 +40,27 @@
.In stdlib.h
.Vt extern char *suboptarg ;
.Ft int
is a pointer to a
.Dv NULL Ns -terminated
array of pointers to strings.
-@@ -69,10 +73,10 @@
+@@ -65,10 +69,10 @@ The
.Fn getsubopt
function
returns the zero-based offset of the pointer in the
does not contain a matching string.
.Pp
If the token is of the form ``name=value'', the location referenced by
-@@ -97,7 +101,7 @@
+@@ -93,7 +97,7 @@ will be set to point to the ``value'' po
if no ``value'' portion was present.
.Sh EXAMPLES
.Bd -literal -compact
#define ONE 0
"one",
#define TWO 1
-@@ -118,7 +122,7 @@
+@@ -114,7 +118,7 @@ while ((ch = getopt(argc, argv, "ab:"))
case 'b':
options = optarg;
while (*options) {
* 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.
static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/getsubopt.c,v 1.6 2004/02/23 03:30:02 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/getsubopt.c,v 1.7 2007/01/09 00:28:10 imp Exp $");
#include <stdlib.h>
#include <string.h>
-.\" $FreeBSD: src/lib/libc/stdlib/hcreate.3,v 1.4 2003/09/08 19:57:15 ru Exp $
+.\"-
+.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
+.\" All rights reserved.
.\"
-.Dd May 8, 2001
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Klaus Klein.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libc/stdlib/hcreate.3,v 1.7 2008/07/06 17:03:37 danger Exp $
+.\"
+.Dd July 6, 2008
.Os
.Dt HCREATE 3
.Sh NAME
.Sh RETURN VALUES
The
.Fn hcreate
-function returns 0 if it cannot allocate sufficient space for the table;
-otherwise, it returns non-zero.
+function returns 0 if the table creation failed and the global variable
+.Va errno
+is set to indicate the error;
+otherwise, a non-zero value is returned.
.Pp
The
.Fn hdestroy
is
.Dv ENTER
and the table is full.
-.Sh ERRORS
-The
-.Fn hcreate
-and
-.Fn hsearch
-functions may fail if:
-.Bl -tag -width Er
-.It Bq Er ENOMEM
-Insufficient storage space is available.
-.El
.Sh EXAMPLES
The following example reads in strings followed by two numbers
and stores them in a hash table, discarding duplicates.
return 0;
}
.Ed
+.Sh ERRORS
+The
+.Fn hcreate
+and
+.Fn hsearch
+functions may fail if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient storage space is available.
+.It Bq Er EINVAL
+A table already exists.
+.El
.Sh SEE ALSO
.Xr bsearch 3 ,
.Xr lsearch 3 ,
__RCSID("$NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/hcreate.c,v 1.3 2002/06/27 13:18:27 deischen Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/hcreate.c,v 1.4 2008/07/06 11:31:20 danger Exp $");
#include <sys/types.h>
#include <sys/queue.h>
size_t idx;
unsigned int p2;
- /* Make sure this this isn't called when a table already exists. */
+ /* Make sure this is not called when a table already exists. */
if (htable != NULL) {
errno = EINVAL;
return 0;
if (nel < MIN_BUCKETS)
nel = MIN_BUCKETS;
- /* If it's too large, cap it. */
+ /* If it is too large, cap it. */
if (nel > MAX_BUCKETS)
nel = MAX_BUCKETS;
- /* If it's is not a power of two in size, round up. */
+ /* If it is not a power of two in size, round up. */
if ((nel & (nel - 1)) != 0) {
for (p2 = 0; nel != 0; p2++)
nel >>= 1;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)labs.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/labs.3,v 1.9 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/labs.3,v 1.10 2007/01/09 00:28:10 imp Exp $
.\"
.Dd November 14, 2001
.Dt LABS 3
---- _SB/Libc/stdlib/FreeBSD/labs.3 2003-05-20 15:23:24.000000000 -0700
-+++ _SB/Libc/stdlib/FreeBSD/labs.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,13 +47,13 @@
+--- labs.3.bsdnew 2009-11-13 14:11:49.000000000 -0800
++++ labs.3 2009-11-13 14:11:49.000000000 -0800
+@@ -43,13 +43,13 @@
.Sh SYNOPSIS
.In stdlib.h
.Ft long
* 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.
static char sccsid[] = "@(#)labs.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/labs.c,v 1.2 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/labs.c,v 1.3 2007/01/09 00:28:10 imp Exp $");
#include <stdlib.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ldiv.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/ldiv.3,v 1.9 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/ldiv.3,v 1.10 2007/01/09 00:28:10 imp Exp $
.\"
.Dd November 14, 2001
.Dt LDIV 3
---- _SB/Libc/stdlib/FreeBSD/ldiv.3 2003-05-20 15:23:24.000000000 -0700
-+++ _SB/Libc/stdlib/FreeBSD/ldiv.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,14 +47,15 @@
+--- ldiv.3.bsdnew 2009-11-13 14:11:49.000000000 -0800
++++ ldiv.3 2009-11-13 14:11:49.000000000 -0800
+@@ -43,14 +43,15 @@
.Sh SYNOPSIS
.In stdlib.h
.Ft ldiv_t
* 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.
static char sccsid[] = "@(#)ldiv.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/ldiv.c,v 1.2 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/ldiv.c,v 1.3 2007/01/09 00:28:10 imp Exp $");
#include <stdlib.h> /* ldiv_t */
.\" As long as the above copyright statement and this notice remain
.\" unchanged, you can do what ever you want with this file.
.\"
-.\" $FreeBSD: src/lib/libc/stdlib/lsearch.3,v 1.4 2002/12/19 09:40:24 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/lsearch.3,v 1.5 2005/01/20 09:17:04 ru Exp $
.\"
.Dd October 11, 2002
.Dt LSEARCH 3
.Xr bsearch 3 ,
.Xr hsearch 3 ,
.Xr tsearch 3
+.Sh STANDARDS
+The
+.Fn lsearch
+and
+.Fn lfind
+functions conform to
+.St -p1003.1-2001 .
.Sh HISTORY
The
.Fn lsearch
.Fx 5.0 ,
they reappeared conforming to
.St -p1003.1-2001 .
-.Sh STANDARDS
-The
-.Fn lsearch
-and
-.Fn lfind
-functions conform to
-.St -p1003.1-2001 .
---- _SB/Libc/stdlib/FreeBSD/lsearch.3 2003-05-20 15:23:25.000000000 -0700
-+++ _SB/Libc/stdlib/FreeBSD/lsearch.3.edit 2006-06-28 16:55:53.000000000 -0700
+--- lsearch.3.bsdnew 2009-11-13 14:11:50.000000000 -0800
++++ lsearch.3 2009-11-13 14:11:50.000000000 -0800
@@ -12,21 +12,21 @@
.Dt LSEARCH 3
.Os
.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]"
.Fc
.Sh DESCRIPTION
-@@ -34,8 +34,8 @@
+@@ -34,8 +34,8 @@ The
.Fn lsearch
and
.Fn lfind
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memory.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/memory.3,v 1.11 2001/09/07 14:46:35 asmodai Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/memory.3,v 1.12 2007/01/09 00:28:10 imp Exp $
.\"
.Dd June 4, 1993
.Dt MEMORY 3
---- memory.3 2003-05-20 15:23:25.000000000 -0700
-+++ memory.3.edit 2006-07-13 09:26:29.000000000 -0700
-@@ -36,42 +36,101 @@
+--- memory.3.bsdnew 2009-11-13 14:11:50.000000000 -0800
++++ memory.3 2009-11-13 14:11:50.000000000 -0800
+@@ -32,42 +32,101 @@
.Dt MEMORY 3
.Os
.Sh NAME
* 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.
static char sccsid[] = "@(#)putenv.c 8.2 (Berkeley) 3/27/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/putenv.c,v 1.2 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/putenv.c,v 1.6 2007/05/01 16:02:41 ache Exp $");
#include <stdlib.h>
#include <string.h>
---- putenv.c.orig 2006-10-05 11:57:06.000000000 -0700
-+++ putenv.c 2006-11-02 11:15:33.000000000 -0800
-@@ -39,22 +39,65 @@
+--- putenv.c.orig 2011-04-12 22:08:20.000000000 -0700
++++ putenv.c 2011-04-13 14:33:50.000000000 -0700
+@@ -35,22 +35,81 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include <stdlib.h>
#include <string.h>
+#include <crt_externs.h>
+#include <malloc/malloc.h>
+#include <errno.h>
-
++
+extern malloc_zone_t *__zone0;
-+extern void __malloc_check_env_name(const char *);
++#ifdef LEGACY_CRT1_ENVIRON
++extern char **_saved_environ;
++#endif /* LEGACY_CRT1_ENVIRON */
+
++extern void __malloc_check_env_name(const char *);
+__private_extern__ int __setenv(const char *, const char *, int, int, char ***, malloc_zone_t *);
+
+#ifndef BUILDING_VARIANT
+ * have been created with malloc) and an env state, created by _allocenvstate().
+ * Returns ptr to value associated with name, if any, else NULL.
+ */
- int
--putenv(str)
-- const char *str;
++int
+_putenvp(char *str, char ***envp, void *state)
- {
-- char *p, *equal;
-- int rval;
++{
+ /* insure __zone0 is set up */
+ if (!__zone0) {
+ __zone0 = malloc_create_zone(0, 0);
+}
+#endif /* BUILDING_VARIANT */
-- if ((p = strdup(str)) == NULL)
-+int
-+putenv(str)
+ int
+ putenv(str)
+- const char *str;
+ char *str;
-+{
+ {
+- char *p, *equal;
+- int rval;
++#ifdef LEGACY_CRT1_ENVIRON
++ int ret;
++#endif /* LEGACY_CRT1_ENVIRON */
+
+- if ((p = strdup(str)) == NULL)
+#if __DARWIN_UNIX03
+ if (str == NULL || *str == 0 || index(str, '=') == NULL) {
+ errno = EINVAL;
- (void)free(p);
- return (rval);
+ __malloc_check_env_name(str); /* see if we are changing a malloc environment variable */
-+ return (__setenv(str, NULL, 1,
++#ifdef LEGACY_CRT1_ENVIRON
++ ret =
++#else /* !LEGACY_CRT1_ENVIRON */
++ return
++#endif /* !LEGACY_CRT1_ENVIRON */
++ __setenv(str, NULL, 1,
+#if __DARWIN_UNIX03
+ 0,
+#else /* !__DARWIN_UNIX03 */
+ -1,
+#endif /* __DARWIN_UNIX03 */
-+ _NSGetEnviron(), __zone0));
++ _NSGetEnviron(), __zone0);
++#ifdef LEGACY_CRT1_ENVIRON
++ _saved_environ = *_NSGetEnviron();
++ return ret;
++#endif /* LEGACY_CRT1_ENVIRON */
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)qsort.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.15 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.17 2007/01/09 00:28:10 imp Exp $
.\"
.Dd September 30, 2003
.Dt QSORT 3
return no value.
.Pp
.Rv -std heapsort mergesort
+.Sh COMPATIBILITY
+Previous versions of
+.Fn qsort
+did not permit the comparison routine itself to call
+.Fn qsort 3 .
+This is no longer true.
.Sh ERRORS
The
.Fn heapsort
functions
were unable to allocate memory.
.El
-.Sh COMPATIBILITY
-Previous versions of
-.Fn qsort
-did not permit the comparison routine itself to call
-.Fn qsort 3 .
-This is no longer true.
.Sh SEE ALSO
.Xr sort 1 ,
.Xr radixsort 3
---- qsort.3.orig 2009-05-12 11:21:33.000000000 -0700
-+++ qsort.3 2009-05-20 15:00:21.000000000 -0700
-@@ -40,41 +40,78 @@
+--- qsort.3.orig 2010-10-07 21:23:04.000000000 -0700
++++ qsort.3 2010-10-07 21:24:45.000000000 -0700
+@@ -36,41 +36,78 @@
.Dt QSORT 3
.Os
.Sh NAME
.Ft int
-.Fo mergesort
+.Fo mergesort_b
- .Fa "void *base"
--.Fa "size_t nmemb"
--.Fa "size_t size"
++.Fa "void *base"
+.Fa "size_t nel"
+.Fa "size_t width"
+.Fa "int \*[lp]^compar\*[rp]\*[lp]const void *, const void *\*[rp]"
+#endif
+.Ft void
+.Fo qsort
-+.Fa "void *base"
+ .Fa "void *base"
+-.Fa "size_t nmemb"
+-.Fa "size_t size"
+.Fa "size_t nel"
+.Fa "size_t width"
.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]"
.Sh DESCRIPTION
The
.Fn qsort
-@@ -84,7 +121,7 @@
+@@ -80,7 +117,7 @@
function is a modified selection sort.
The
.Fn mergesort
intended for sorting data with pre-existing order.
.Pp
The
-@@ -92,19 +129,19 @@
+@@ -88,19 +125,19 @@
and
.Fn heapsort
functions sort an array of
.Dq "sizeof(void *) / 2" .
.Pp
The contents of the array
-@@ -139,7 +176,7 @@
+@@ -135,7 +172,7 @@
.Fn heapsort
are
.Em not
the sorted array is undefined.
The
.Fn mergesort
-@@ -183,8 +220,8 @@
+@@ -179,8 +216,8 @@
The function
.Fn mergesort
requires additional memory of size
bytes; it should be used only when space is not at a premium.
The
.Fn mergesort
-@@ -195,42 +232,83 @@
- Normally,
+@@ -192,19 +229,40 @@
.Fn qsort
is faster than
--.Fn mergesort
+ .Fn mergesort
-is faster than
-+.Fn mergesort ,
+which is faster than
.Fn heapsort .
Memory availability and pre-existing order in the data can make this
+.ds MERGESORT_B mergesort_b
+#endif
+.Rv -std heapsort \*[HEAPSORT_B] mergesort \*[MERGESORT_B]
+ .Sh COMPATIBILITY
+ Previous versions of
+ .Fn qsort
+@@ -213,26 +271,46 @@
+ This is no longer true.
.Sh ERRORS
The
+#ifdef UNIFDEF_BLOCKS
+.Fn heapsort ,
+.Fn heapsort_b ,
-+.Fn mergesort
++.Fn mergesort ,
+and
+.Fn mergesort_b
+#else
+#ifdef UNIFDEF_BLOCKS
+.Fn heapsort ,
+.Fn heapsort_b ,
-+.Fn mergesort
-+and
++.Fn mergesort ,
++or
+.Fn mergesort_b
+#else
.Fn heapsort
--or
-+and
+ or
.Fn mergesort
+#endif
functions
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)radixsort.3 8.2 (Berkeley) 1/27/94
-.\" $FreeBSD: src/lib/libc/stdlib/radixsort.3,v 1.11 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/radixsort.3,v 1.12 2007/01/09 00:28:10 imp Exp $
.\"
.Dd January 27, 1994
.Dt RADIXSORT 3
* 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.
static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/radixsort.c,v 1.7 2003/11/11 04:59:23 kientzle Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/radixsort.c,v 1.8 2007/01/09 00:28:10 imp Exp $");
/*
* Radixsort routines.
---- radixsort.c.orig 2004-12-01 20:08:48.000000000 -0800
-+++ radixsort.c 2004-12-01 20:11:23.000000000 -0800
-@@ -64,7 +64,7 @@
+--- radixsort.c.orig 2010-06-21 14:05:02.000000000 -0700
++++ radixsort.c 2010-06-21 14:26:55.000000000 -0700
+@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
+ #include <stdlib.h>
+ #include <stddef.h>
+ #include <errno.h>
++#include <pthread.h>
+
+ typedef struct {
+ const u_char **sa;
+@@ -60,11 +61,17 @@ typedef struct {
} stack;
static inline void simplesort
static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
static void r_sort_b(const u_char **, const u_char **, int, int,
const u_char *, u_int);
+
++static int *r_sort_a_count;
++static int *r_sort_b_count;
++
++static void r_sort_count_allocate(void);
++static pthread_once_t r_sort_count_control = PTHREAD_ONCE_INIT;
++
+ #define THRESHOLD 20 /* Divert to simplesort(). */
+ #define SIZE 512 /* Default stack size. */
+
+@@ -124,6 +131,12 @@ sradixsort(a, n, tab, endch)
+ return (0);
+ }
+
++static void r_sort_count_allocate(void)
++{
++ r_sort_a_count = calloc(256, sizeof(int));
++ r_sort_b_count = calloc(256, sizeof(int));
++}
++
+ #define empty(s) (s >= sp)
+ #define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
+ #define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
+@@ -137,13 +150,19 @@ r_sort_a(a, n, i, tr, endch)
+ const u_char *tr;
+ u_int endch;
+ {
+- static int count[256], nc, bmin;
++ static int *count, nc, bmin;
+ int c;
+ const u_char **ak, *r;
+ stack s[SIZE], *sp, *sp0, *sp1, temp;
+ int *cp, bigc;
+ const u_char **an, *t, **aj, **top[256];
+
++ if (pthread_once(&r_sort_count_control, r_sort_count_allocate)) {
++ return;
++ }
++
++ count = r_sort_a_count;
++
+ /* Set up stack. */
+ sp = s;
+ push(a, n, i);
+@@ -239,13 +258,19 @@ r_sort_b(a, ta, n, i, tr, endch)
+ const u_char *tr;
+ u_int endch;
+ {
+- static int count[256], nc, bmin;
++ static int *count, nc, bmin;
+ int c;
+ const u_char **ak, **ai;
+ stack s[512], *sp, *sp0, *sp1, temp;
+ const u_char **top[256];
+ int *cp, bigc;
+
++ if (pthread_once(&r_sort_count_control, r_sort_count_allocate)) {
++ return;
++ }
++
++ count = r_sort_b_count;
++
+ sp = s;
+ push(a, n, i);
+ while (!empty(s)) {
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)rand.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/rand.3,v 1.14 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/rand.3,v 1.16 2007/01/09 00:28:10 imp Exp $
.\"
.Dd May 25, 1999
.Dt RAND 3
.Fn sranddev
function initializes a seed using the
.Xr random 4
-random number device which returns good random numbers,
-suitable for cryptographic use.
+random number device which returns good random numbers.
+However, the
+.Fn rand
+function still remains unsuitable for cryptographic use.
.Pp
The
.Fn rand_r
---- _SB/Libc/stdlib/FreeBSD/rand.3 2004-11-25 11:38:42.000000000 -0800
-+++ _SB/Libc/stdlib/FreeBSD/rand.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -41,22 +41,30 @@
+--- rand.3.bsdnew 2009-11-13 14:11:50.000000000 -0800
++++ rand.3 2009-11-13 14:11:50.000000000 -0800
+@@ -37,22 +37,30 @@
.Os
.Sh NAME
.Nm rand ,
.Sh DESCRIPTION
.Bf -symbolic
These interfaces are obsoleted by
-@@ -89,7 +97,7 @@
+@@ -85,7 +93,7 @@ seeded with a value of 1.
.Pp
The
.Fn sranddev
-function initializes a seed using the
+function initializes a seed, using the
.Xr random 4
- random number device which returns good random numbers,
- suitable for cryptographic use.
-@@ -100,7 +108,7 @@
+ random number device which returns good random numbers.
+ However, the
+@@ -98,7 +106,7 @@ function
provides the same functionality as
.Fn rand .
A pointer to the context value
* 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.
static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/rand.c,v 1.15 2003/02/17 03:52:35 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/rand.c,v 1.17 2007/12/11 20:39:32 ache Exp $");
#include "namespace.h"
#include <sys/time.h> /* for sranddev() */
#else /* !USE_WEAK_SEEDING */
/*
* Compute x = (7^5 * x) mod (2^31 - 1)
- * wihout overflowing 31 bits:
+ * without overflowing 31 bits:
* (2^31 - 1) = 127773 * (7^5) + 2836
* From "Random number generators: good ones are hard to find",
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)random.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/random.3,v 1.20 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/random.3,v 1.22 2007/01/09 00:28:10 imp Exp $
.\"
.Dd June 4, 1993
.Dt RANDOM 3
.if t 2\u\s769\s10\d,
.if n 2**69
which should be sufficient for most purposes.
-.Sh AUTHORS
-.An Earl T. Cohen
.Sh DIAGNOSTICS
If
.Fn initstate
These
functions appeared in
.Bx 4.2 .
+.Sh AUTHORS
+.An Earl T. Cohen
.Sh BUGS
About 2/3 the speed of
.Xr rand 3 .
---- random.3 2004-11-25 11:38:42.000000000 -0800
-+++ random.3.edit 2006-07-12 11:25:20.000000000 -0700
-@@ -36,32 +36,45 @@
+--- random.3.orig 2010-04-28 23:38:47.000000000 -0700
++++ random.3 2010-04-29 09:47:13.000000000 -0700
+@@ -32,32 +32,45 @@
.Dt RANDOM 3
.Os
.Sh NAME
numbers in the range from 0 to
.if t 2\u\s731\s10\d\(mi1.
.if n (2**31)\(mi1.
-@@ -82,7 +95,7 @@
+@@ -78,7 +91,7 @@ The difference is that
.Xr rand 3
produces a much less random sequence \(em in fact, the low dozen bits
generated by rand go through a cyclic pattern.
.Fn random
are usable.
For example,
-@@ -102,7 +115,7 @@
+@@ -87,18 +100,21 @@ will produce a random binary
+ value.
+ .Pp
+ Like
++.Xr srand 3 ,
++.Fn srandom
++sets the initial seed value for future calls to
++.Fn random .
++Like
+ .Xr rand 3 ,
+ .Fn random
+ will by default produce a sequence of numbers that can be duplicated
+ by calling
+ .Fn srandom
+-with
+-.Ql 1
+-as the seed.
++with the same seed.
.Pp
The
.Fn srandomdev
.Xr random 4
random number device which returns good random numbers,
suitable for cryptographic use.
-@@ -127,7 +140,7 @@
+@@ -123,7 +139,7 @@ more state, the better the random number
the nearest known amount.
Using less than 8 bytes will cause an error.)
The seed for the initialization (which specifies a starting point for
point) is also an argument.
The
.Fn initstate
-@@ -166,7 +179,7 @@
+@@ -162,7 +178,7 @@ it is initialized.
With 256 bytes of state information, the period of the random number
generator is greater than
.if t 2\u\s769\s10\d,
-.if n 2**69
+.if n 2**69 ,
which should be sufficient for most purposes.
- .Sh AUTHORS
- .An Earl T. Cohen
-@@ -177,11 +190,36 @@
+ .Sh DIAGNOSTICS
+ If
+@@ -171,11 +187,36 @@ is called with less than 8 bytes of stat
.Fn setstate
detects that the state information has been garbled, error
messages are printed on the standard error output.
* 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.
static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.24 2004/01/20 03:02:18 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.25 2007/01/09 00:28:10 imp Exp $");
#include "namespace.h"
#include <sys/time.h> /* for srandomdev() */
---- random.c.org 2006-09-08 18:48:58.000000000 -0700
-+++ random.c 2006-09-08 18:50:03.000000000 -0700
-@@ -37,6 +37,14 @@
+--- random.c.bsdnew 2009-11-13 14:11:50.000000000 -0800
++++ random.c 2009-11-13 14:11:51.000000000 -0800
+@@ -33,6 +33,14 @@ static char sccsid[] = "@(#)random.c 8.2
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.24 2004/01/20 03:02:18 das Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.25 2007/01/09 00:28:10 imp Exp $");
+/*
+ * We always compile with __DARWIN_UNIX03 set to one, relying on the fact that
#include "namespace.h"
#include <sys/time.h> /* for srandomdev() */
#include <fcntl.h> /* for srandomdev() */
-@@ -220,7 +228,7 @@
+@@ -216,7 +224,7 @@ static int rand_deg = DEG_3;
static int rand_sep = SEP_3;
static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
static inline uint32_t good_rand (x)
int32_t x;
-@@ -269,7 +277,7 @@
+@@ -265,7 +273,7 @@ static inline uint32_t good_rand (x)
*/
void
srandom(x)
{
int i, lim;
-@@ -357,9 +365,9 @@
+@@ -353,9 +361,9 @@ srandomdev()
*/
char *
initstate(seed, arg_state, n)
{
char *ostate = (char *)(&state[-1]);
uint32_t *int_arg_state = (uint32_t *)arg_state;
-@@ -425,7 +433,7 @@
+@@ -421,7 +429,7 @@ initstate(seed, arg_state, n)
*/
char *
setstate(arg_state)
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
-.\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.13 2003/03/27 20:48:53 fjoe Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.14 2007/01/09 00:28:10 imp Exp $
.\"
.Dd February 16, 1994
.Dt REALPATH 3
---- realpath.3.orig 2008-04-05 00:03:06.000000000 -0700
-+++ realpath.3 2008-04-05 17:42:41.000000000 -0700
-@@ -35,63 +35,73 @@
+--- realpath.3.bsdnew 2009-11-13 14:11:51.000000000 -0800
++++ realpath.3 2009-11-13 14:11:51.000000000 -0800
+@@ -31,63 +31,73 @@
.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
- .\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.13 2003/03/27 20:48:53 fjoe Exp $
+ .\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.14 2007/01/09 00:28:10 imp Exp $
.\"
-.Dd February 16, 1994
+.Dd April 5, 2008
contains the pathname which caused the problem.
.Sh ERRORS
The function
-@@ -99,24 +109,44 @@
+@@ -95,24 +105,44 @@ The function
may fail and set the external variable
.Va errno
for any of the errors specified for the library functions
---- realpath.c.orig 2008-04-04 14:39:39.000000000 -0700
-+++ realpath.c 2008-04-04 19:59:19.000000000 -0700
+--- realpath.c.orig 2010-06-24 17:32:55.000000000 -0700
++++ realpath.c 2010-06-25 13:46:50.000000000 -0700
@@ -35,13 +35,41 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include "namespace.h"
#include <sys/param.h>
/*
* char *realpath(const char *path, char resolved[PATH_MAX]);
*
-@@ -50,26 +78,67 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
+@@ -50,36 +78,89 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
* in which case the path which caused trouble is left in (resolved).
*/
char *
+#endif /* __DARWIN_UNIX03 */
+ /*
+ * Extension to the standard; if inresolved == NULL, allocate memory
-+ * (first on the stack, then use strdup())
+ */
+ if (!inresolved) {
-+ if ((resolved = alloca(PATH_MAX)) == NULL) return (NULL);
++ if ((resolved = malloc(PATH_MAX)) == NULL) return (NULL);
+ } else {
+ resolved = inresolved;
+ }
+ if (!rootdev_inited) {
+ rootdev_inited = 1;
+ if (stat("/", &sb) < 0) {
-+ return (NULL);
++error_return:
++ if (!inresolved) {
++ int e = errno;
++ free(resolved);
++ errno = e;
+ }
++ return (NULL);
++ }
+ rootdev = sb.st_dev;
+ }
serrno = errno;
+#endif /* !VARIANT_DARWINEXTSN && __DARWIN_UNIX03 */
+ {
strlcpy(resolved, ".", PATH_MAX);
- return (NULL);
+- return (NULL);
++ goto error_return;
}
-@@ -80,6 +149,13 @@ realpath(const char *path, char resolved
+ resolved_len = strlen(resolved);
+ left_len = strlcpy(left, path, sizeof(left));
+ }
+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+- return (NULL);
++ goto error_return;
}
+ if (resolved_len > 1) {
+ if (stat(resolved, &sb) < 0) {
-+ return (NULL);
++ goto error_return;
+ }
+ lastdev = sb.st_dev;
+ } else
/*
* Iterate over path components in `left'.
-@@ -127,6 +203,13 @@ realpath(const char *path, char resolved
+@@ -93,7 +174,7 @@ realpath(const char *path, char resolved
+ s = p ? p : left + left_len;
+ if (s - left >= sizeof(next_token)) {
+ errno = ENAMETOOLONG;
+- return (NULL);
++ goto error_return;
+ }
+ memcpy(next_token, left, s - left);
+ next_token[s - left] = '\0';
+@@ -103,7 +184,7 @@ realpath(const char *path, char resolved
+ if (resolved[resolved_len - 1] != '/') {
+ if (resolved_len + 1 >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+- return (NULL);
++ goto error_return;
+ }
+ resolved[resolved_len++] = '/';
+ resolved[resolved_len] = '\0';
+@@ -127,6 +208,13 @@ realpath(const char *path, char resolved
}
/*
* Append the next path component and lstat() it. If
* lstat() fails we still can return successfully if
* there are no more path components left.
-@@ -136,25 +219,87 @@ realpath(const char *path, char resolved
+@@ -134,27 +222,89 @@ realpath(const char *path, char resolved
+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
+ if (resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+- return (NULL);
++ goto error_return;
}
- if (lstat(resolved, &sb) != 0) {
+ if (getattrlist(resolved, &_rp_alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) {
errno = serrno;
return (resolved);
}
+- return (NULL);
+#endif /* !__DARWIN_UNIX03 */
- return (NULL);
++ goto error_return;
}
- if (S_ISLNK(sb.st_mode)) {
+ if (dev != lastdev) {
+ if (islink) {
if (symlinks++ > MAXSYMLINKS) {
errno = ELOOP;
- return (NULL);
+- return (NULL);
++ goto error_return;
}
slen = readlink(resolved, symlink, sizeof(symlink) - 1);
- if (slen < 0)
+- return (NULL);
+ if (slen < 0) {
- return (NULL);
++ goto error_return;
+ }
symlink[slen] = '\0';
if (symlink[0] == '/') {
} else if (resolved_len > 1) {
/* Strip the last path component. */
resolved[resolved_len - 1] = '\0';
-@@ -184,7 +329,30 @@ realpath(const char *path, char resolved
+@@ -172,7 +322,7 @@ realpath(const char *path, char resolved
+ if (symlink[slen - 1] != '/') {
+ if (slen + 1 >= sizeof(symlink)) {
+ errno = ENAMETOOLONG;
+- return (NULL);
++ goto error_return;
+ }
+ symlink[slen] = '/';
+ symlink[slen + 1] = 0;
+@@ -180,11 +330,34 @@ realpath(const char *path, char resolved
+ left_len = strlcat(symlink, left, sizeof(left));
+ if (left_len >= sizeof(left)) {
+ errno = ENAMETOOLONG;
+- return (NULL);
++ goto error_return;
}
}
left_len = strlcpy(left, symlink, sizeof(left));
+ resolved_len = strlcat(resolved, (const char *)&attrs.name + attrs.name.attr_dataoffset, PATH_MAX);
+ if (resolved_len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
-+ return (NULL);
++ goto error_return;
+ }
}
+ /*
}
/*
-@@ -193,5 +361,6 @@ realpath(const char *path, char resolved
- */
- if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
- resolved[resolved_len - 1] = '\0';
-+ if (!inresolved) resolved = strdup(resolved);
- return (resolved);
- }
* 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.
static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/setenv.c,v 1.9 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/setenv.c,v 1.14 2007/05/01 16:02:41 ache Exp $");
#include <stddef.h>
#include <stdlib.h>
-Index: setenv.c
-===================================================================
---- setenv.c (revision 41051)
-+++ setenv.c (working copy)
-@@ -40,32 +40,79 @@
+--- setenv.c.orig 2011-04-13 01:21:14.000000000 -0700
++++ setenv.c 2011-04-13 14:44:04.000000000 -0700
+@@ -36,32 +36,115 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
-char *__findenv(const char *, int *);
+#define ZONE_OWNS_PTR(zone, ptr) (malloc_zone_from_ptr((ptr)) == zone)
-
++
+extern malloc_zone_t *__zone0;
+extern void __malloc_check_env_name(const char *);
+
+__private_extern__ char *__findenv(const char *, int *, char **);
+__private_extern__ int __setenv(const char *, const char *, int, int, char ***, malloc_zone_t *);
+__private_extern__ void __unsetenv(const char *, char **, malloc_zone_t *);
-+
-+#ifndef BUILDING_VARIANT
++__private_extern__ int init__zone0(int);
+
/*
- * setenv --
- * Set the value of the environmental variable "name" to be
- * "value". If rewrite is set, replace any current value.
-+ * Create the environment malloc zone and give it a recognizable name.
++ * _cthread_init_routine used to be called from crt1.o to initialize threads.
++ * This is no longer needed, as initialization happens in dylib initializers,
++ * but is provided to maintain backwards compatibility. Normally, for 10.5
++ * or greater, _cthread_init_routine does nothing.
++ *
++ * Before 10.5, the _start routine in crt1.o clobbers environ with the original
++ * stack value, which effectively undoes any environment changes made in
++ * initializers. When LEGACY_CRT1_ENVIRON is defined, we replace the
++ * do-nothing routine with one that attempts to restore the environ value.
++ * But this only works if the setenv (and family) routines were used
++ * exclusively, (no direct manipulation of environ). Note that according to
++ * SUSv3, direct manipulation of environ may result in undefined behavior in
++ * setenv and family, so we don't support that (on less than 10.5).
*/
-int
-setenv(name, value, rewrite)
++#ifdef BUILDING_VARIANT
++# ifdef LEGACY_CRT1_ENVIRON
++extern char **_saved_environ;
++# endif /* LEGACY_CRT1_ENVIRON */
++#else /* !BUILDING_VARIANT */
++# ifdef LEGACY_CRT1_ENVIRON
++__private_extern__ char **_saved_environ = NULL;
++
++static int
++_legacy_crt1_environ(void)
++{
++ if (_saved_environ) *_NSGetEnviron() = _saved_environ;
++ return 0;
++}
++int (*_cthread_init_routine)(void) = _legacy_crt1_environ;
++
++# else /* !LEGACY_CRT1_ENVIRON */
++static int _do_nothing(void) { return 0; }
++int (*_cthread_init_routine)(void) = _do_nothing;
++# endif /* !LEGACY_CRT1_ENVIRON */
++
++/*
++ * Create the environment malloc zone and give it a recognizable name.
++ */
+__private_extern__ int
+init__zone0(int should_set_errno)
+{
while ( (*c++ = *value++) );
return (0);
}
-@@ -73,48 +120,225 @@
+@@ -69,48 +152,235 @@ setenv(name, value, rewrite)
int cnt;
char **p;
+}
+
+/****************************************************************************/
- /*
++/*
+ * _allocenvstate -- SPI that creates a new state (opaque)
+ */
+void *
+ const char *value;
+ int rewrite;
+{
++#ifdef LEGACY_CRT1_ENVIRON
++ int ret;
++#endif /* LEGACY_CRT1_ENVIRON */
++
+ /* no null ptr or empty str */
+ if(name == NULL || *name == 0) {
+ errno = EINVAL;
+ /* insure __zone0 is set up before calling __malloc_check_env_name */
+ if (init__zone0(1)) return (-1);
+ __malloc_check_env_name(name); /* see if we are changing a malloc environment variable */
++#ifdef LEGACY_CRT1_ENVIRON
++ ret = __setenv(name, value, rewrite, 1, _NSGetEnviron(), __zone0);
++ _saved_environ = *_NSGetEnviron();
++ return ret;
++#else /* !LEGACY_CRT1_ENVIRON */
+ return (__setenv(name, value, rewrite, 1, _NSGetEnviron(), __zone0));
++#endif /* !LEGACY_CRT1_ENVIRON */
+}
+
-+/*
+ /*
* unsetenv(name) --
* Delete environmental variable "name".
*/
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strtod.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/strtod.3,v 1.19 2003/05/22 13:02:28 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/strtod.3,v 1.22 2007/12/16 21:19:28 das Exp $
.\"
.Dd March 2, 2003
.Dt STRTOD 3
of 2.
.Pp
Alternatively, if the portion of the string following the optional
-plus or minus sign begins with ``INFINITY'' or ``NAN'', ignoring
-case, it is interpreted as an infinity or a quiet NaN, respectively.
+plus or minus sign begins with
+.Dq INFINITY
+or
+.Dq NAN ,
+ignoring case, it is interpreted as an infinity or a quiet \*(Na,
+respectively.
+The syntax
+.Dq Xo Pf NAN( Ar "s" ) Xc ,
+where
+.Ar s
+is an alphanumeric string, produces the same value as the call
+.Fo nan
+.Qq Ar s Ns
+.Fc
+(respectively,
+.Fo nanf
+.Qq Ar s Ns
+.Fc
+and
+.Fo nanl
+.Qq Ar s Ns
+.Fc . )
.Pp
In any of the above cases, leading white-space characters in the
string (as defined by the
.Xr atof 3 ,
.Xr atoi 3 ,
.Xr atol 3 ,
+.Xr nan 3 ,
.Xr strtol 3 ,
.Xr strtoul 3 ,
.Xr wcstod 3
conforms to
.St -isoC-99 ,
with the exception of the bug noted below.
-.Sh BUGS
-These routines do not recognize the C99 ``NaN(...)'' syntax.
.Sh AUTHORS
The author of this software is
.An David M. Gay .
---- strtod.3 2004-11-25 11:38:42.000000000 -0800
-+++ strtod.3.edit 2006-08-09 13:42:36.000000000 -0700
-@@ -49,11 +49,20 @@
+--- strtod.3.orig 2010-04-29 10:40:21.000000000 -0700
++++ strtod.3 2010-04-29 10:40:42.000000000 -0700
+@@ -45,11 +45,20 @@ string to floating point
.Sh SYNOPSIS
.In stdlib.h
.Ft double
.Sh DESCRIPTION
These conversion
functions convert the initial portion of the string
-@@ -66,16 +75,17 @@
+@@ -62,16 +71,17 @@ and
.Vt "long double"
representation, respectively.
.Pp
.El
.Pp
In both cases, the significand may be optionally followed by an
-@@ -100,6 +110,12 @@
+@@ -116,6 +126,12 @@ function) are skipped.
The decimal point
character is defined in the program's locale (category
.Dv LC_NUMERIC ) .
.Sh RETURN VALUES
The
.Fn strtod ,
-@@ -144,6 +160,7 @@
- .Xr atof 3 ,
+@@ -161,6 +177,7 @@ Overflow or underflow occurred.
.Xr atoi 3 ,
.Xr atol 3 ,
+ .Xr nan 3 ,
+.Xr strtod_l 3 ,
.Xr strtol 3 ,
.Xr strtoul 3 ,
.Xr wcstod 3
+@@ -169,8 +186,7 @@ The
+ .Fn strtod
+ function
+ conforms to
+-.St -isoC-99 ,
+-with the exception of the bug noted below.
++.St -isoC-99 .
+ .Sh AUTHORS
+ The author of this software is
+ .An David M. Gay .
* 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.
static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.9 2003/01/01 18:48:43 schweikh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
#include <ctype.h>
#include <errno.h>
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
---- strtoimax.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtoimax.c 2005-02-23 13:20:23.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtoimax.c.bsdnew 2009-11-13 14:11:51.000000000 -0800
++++ strtoimax.c 2009-11-13 14:11:51.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "from @(#)strtol.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.9 2003/01/01 18:48:43 schweikh Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
-@@ -49,7 +51,8 @@
+@@ -45,7 +47,8 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
* alphabets and digits are each contiguous.
*/
intmax_t
{
const char *s;
uintmax_t acc;
-@@ -57,6 +60,7 @@
+@@ -53,6 +56,7 @@ strtoimax(const char * __restrict nptr,
uintmax_t cutoff;
int neg, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
-@@ -65,7 +69,7 @@
+@@ -61,7 +65,7 @@ strtoimax(const char * __restrict nptr,
s = nptr;
do {
c = *s++;
if (c == '-') {
neg = 1;
c = *s++;
-@@ -139,3 +143,9 @@
+@@ -138,3 +142,9 @@ noconv:
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strtol.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/strtol.3,v 1.20 2005/01/22 18:02:58 ache Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/strtol.3,v 1.23 2007/04/10 11:17:00 ru Exp $
.\"
.Dd November 28, 2001
.Dt STRTOL 3
.Er ERANGE
and the function return value is clamped according
to the following table.
-.Bl -column -offset indent ".Fn strtoimax" ".Sy overflow" ".Sy underflow"
-.It Sy Function Ta Sy overflow Ta Sy underflow
+.Bl -column -offset indent ".Fn strtoimax" ".Sy underflow" ".Sy overflow"
+.It Sy Function Ta Sy underflow Ta Sy overflow
.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX
.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX
.It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX
.Xr atoi 3 ,
.Xr atol 3 ,
.Xr strtod 3 ,
+.Xr strtonum 3 ,
.Xr strtoul 3 ,
.Xr wcstol 3
.Sh STANDARDS
---- strtol.3 2006-02-14 14:41:58.000000000 -0800
-+++ strtol.3.edit 2006-08-09 13:42:57.000000000 -0700
-@@ -40,7 +40,10 @@
+--- strtol.3.bsdnew 2009-11-13 14:11:51.000000000 -0800
++++ strtol.3 2009-11-13 14:33:25.000000000 -0800
+@@ -36,7 +36,10 @@
.Dt STRTOL 3
.Os
.Sh NAME
.Nd "convert a string value to a"
.Vt long , "long long" , intmax_t
or
-@@ -49,26 +52,41 @@
+@@ -45,26 +48,41 @@ integer
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
to a
.Vt long
value.
-@@ -76,7 +94,7 @@
+@@ -72,7 +90,7 @@ The
.Fn strtoll
function
converts the string in
to a
.Vt "long long"
value.
-@@ -84,7 +102,7 @@
+@@ -80,7 +98,7 @@ The
.Fn strtoimax
function
converts the string in
to an
.Vt intmax_t
value.
-@@ -92,7 +110,7 @@
+@@ -88,7 +106,7 @@ The
.Fn strtoq
function
converts the string in
to a
.Vt quad_t
value.
-@@ -147,11 +165,11 @@
+@@ -143,11 +161,11 @@ stores the address of the first invalid
If there were no digits at all, however,
.Fn strtol
stores the original value of
is not
.Ql \e0
but
-@@ -159,11 +177,17 @@
+@@ -155,11 +173,17 @@ but
is
.Ql \e0
on return, the entire string was valid.)
and
.Fn strtoq
functions
-@@ -181,8 +205,8 @@
+@@ -177,7 +201,7 @@ is set to
.Er ERANGE
and the function return value is clamped according
to the following table.
--.Bl -column -offset indent ".Fn strtoimax" ".Sy overflow" ".Sy underflow"
--.It Sy Function Ta Sy overflow Ta Sy underflow
+-.Bl -column -offset indent ".Fn strtoimax" ".Sy underflow" ".Sy overflow"
+.Bl -column -offset indent ".Fn strtoimax" ".Dv INTMAX_MIN" ".Dv INTMAX_MAX"
-+.It Sy Function Ta Sy underflow Ta Sy overflow
+ .It Sy Function Ta Sy underflow Ta Sy overflow
.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX
.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX
- .It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX
-@@ -199,13 +223,25 @@
+@@ -195,14 +219,25 @@ no conversion could be performed
.It Bq Er ERANGE
The given string was out of range; the value converted has been clamped.
.El
.Xr atoi 3 ,
.Xr atol 3 ,
.Xr strtod 3 ,
+-.Xr strtonum 3 ,
+.Xr strtol_l 3 ,
.Xr strtoul 3 ,
-.Xr wcstol 3
* 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.
static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtol.c,v 1.17 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtol.c,v 1.20 2007/01/09 00:28:10 imp Exp $");
#include <limits.h>
#include <ctype.h>
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
---- strtol.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtol.c 2005-02-17 00:43:42.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtol.c.bsdnew 2009-11-13 14:11:51.000000000 -0800
++++ strtol.c 2009-11-13 14:11:51.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)strtol.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtol.c,v 1.17 2002/09/06 11:23:59 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtol.c,v 1.20 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <ctype.h>
#include <errno.h>
-@@ -50,7 +52,8 @@
+@@ -46,7 +48,8 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
* alphabets and digits are each contiguous.
*/
long
{
const char *s;
unsigned long acc;
-@@ -58,6 +61,7 @@
+@@ -54,6 +57,7 @@ strtol(const char * __restrict nptr, cha
unsigned long cutoff;
int neg, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
-@@ -66,7 +70,7 @@
+@@ -62,7 +66,7 @@ strtol(const char * __restrict nptr, cha
s = nptr;
do {
c = *s++;
if (c == '-') {
neg = 1;
c = *s++;
-@@ -139,3 +143,9 @@
+@@ -138,3 +142,9 @@ noconv:
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
* 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.
static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.22 2007/01/09 00:28:10 imp Exp $");
#include <limits.h>
#include <errno.h>
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
---- strtoll.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtoll.c 2005-02-17 00:46:45.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtoll.c.bsdnew 2009-11-13 14:11:51.000000000 -0800
++++ strtoll.c 2009-11-13 14:11:51.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)strtoq.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.22 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <errno.h>
#include <ctype.h>
-@@ -49,7 +51,8 @@
+@@ -45,7 +47,8 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
* alphabets and digits are each contiguous.
*/
long long
{
const char *s;
unsigned long long acc;
-@@ -57,6 +60,7 @@
+@@ -53,6 +56,7 @@ strtoll(const char * __restrict nptr, ch
unsigned long long cutoff;
int neg, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
-@@ -65,7 +69,7 @@
+@@ -61,7 +65,7 @@ strtoll(const char * __restrict nptr, ch
s = nptr;
do {
c = *s++;
if (c == '-') {
neg = 1;
c = *s++;
-@@ -139,3 +143,9 @@
+@@ -138,3 +142,9 @@ noconv:
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
* 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.
static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.11 2002/08/15 09:25:04 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
#include <sys/types.h>
---- strtoq.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtoq.c 2005-02-23 18:26:32.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtoq.c.bsdnew 2009-11-13 14:11:51.000000000 -0800
++++ strtoq.c 2009-11-13 14:11:51.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)strtoq.c 8.1
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.11 2002/08/15 09:25:04 robert Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <sys/types.h>
#include <stdlib.h>
-@@ -48,5 +50,13 @@
+@@ -44,5 +46,13 @@ quad_t
strtoq(const char *nptr, char **endptr, int base)
{
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strtoul.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/strtoul.3,v 1.20 2002/10/10 04:31:57 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/strtoul.3,v 1.23 2007/01/09 00:28:10 imp Exp $
.\"
.Dd November 28, 2001
.Dt STRTOUL 3
the global variable
.Va errno
is set to
-.Er EINVAL .
+.Er EINVAL
+(the last feature is not portable across all platforms).
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EINVAL
The value of
.Fa base
is not supported or
-no conversion could be performed.
+no conversion could be performed
+(the last feature is not portable across all platforms).
.It Bq Er ERANGE
The given string was out of range; the value converted has been clamped.
.El
.Sh SEE ALSO
.Xr strtol 3 ,
+.Xr strtonum 3 ,
.Xr wcstoul 3
.Sh STANDARDS
The
---- strtoul.3 2003-05-20 15:23:25.000000000 -0700
-+++ strtoul.3.edit 2006-08-09 13:43:16.000000000 -0700
-@@ -40,7 +40,10 @@
+--- strtoul.3.bsdnew 2009-11-13 14:11:51.000000000 -0800
++++ strtoul.3 2009-11-13 14:40:07.000000000 -0800
+@@ -36,7 +36,10 @@
.Dt STRTOUL 3
.Os
.Sh NAME
.Nd "convert a string to an"
.Vt "unsigned long" , "unsigned long long" , uintmax_t ,
or
-@@ -50,25 +53,40 @@
+@@ -46,25 +49,40 @@ integer
.Lb libc
.Sh SYNOPSIS
.In stdlib.h
to an
.Vt "unsigned long"
value.
-@@ -76,7 +94,7 @@
+@@ -72,7 +90,7 @@ The
.Fn strtoull
function
converts the string in
to an
.Vt "unsigned long long"
value.
-@@ -84,7 +102,7 @@
+@@ -80,7 +98,7 @@ The
.Fn strtoumax
function
converts the string in
to an
.Vt uintmax_t
value.
-@@ -92,7 +110,7 @@
+@@ -88,7 +106,7 @@ The
.Fn strtouq
function
converts the string in
to a
.Vt u_quad_t
value.
-@@ -146,11 +164,11 @@
+@@ -142,11 +160,11 @@ stores the address of the first invalid
If there were no digits at all, however,
.Fn strtoul
stores the original value of
is not
.Ql \e0
but
-@@ -203,9 +221,21 @@
+@@ -201,10 +219,22 @@ no conversion could be performed
.It Bq Er ERANGE
The given string was out of range; the value converted has been clamped.
.El
+functions.
.Sh SEE ALSO
.Xr strtol 3 ,
--.Xr wcstoul 3
+.Xr strtol_l 3 ,
+ .Xr strtonum 3 ,
+-.Xr wcstoul 3
+.Xr wcstoul 3 ,
+.Xr compat 5
.Sh STANDARDS
* 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.
static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoul.c,v 1.16 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoul.c,v 1.19 2007/01/09 00:28:10 imp Exp $");
#include <limits.h>
#include <ctype.h>
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
---- strtoul.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtoul.c 2005-02-17 12:52:46.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtoul.c.bsdnew 2009-11-13 14:11:52.000000000 -0800
++++ strtoul.c 2009-11-13 14:11:52.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)strtoul.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoul.c,v 1.16 2002/09/06 11:23:59 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoul.c,v 1.19 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <ctype.h>
#include <errno.h>
-@@ -49,7 +51,8 @@
+@@ -45,7 +47,8 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
* alphabets and digits are each contiguous.
*/
unsigned long
{
const char *s;
unsigned long acc;
-@@ -57,13 +60,14 @@
+@@ -53,13 +56,14 @@ strtoul(const char * __restrict nptr, ch
unsigned long cutoff;
int neg, any, cutlim;
if (c == '-') {
neg = 1;
c = *s++;
-@@ -117,3 +121,9 @@
+@@ -116,3 +120,9 @@ noconv:
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
* 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.
static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.21 2007/01/09 00:28:10 imp Exp $");
#include <limits.h>
#include <errno.h>
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
---- strtoull.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtoull.c 2005-02-17 00:52:41.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtoull.c.bsdnew 2009-11-13 14:11:52.000000000 -0800
++++ strtoull.c 2009-11-13 14:11:52.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)strtouq.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.21 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <limits.h>
#include <errno.h>
#include <ctype.h>
-@@ -49,7 +51,8 @@
+@@ -45,7 +47,8 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
* alphabets and digits are each contiguous.
*/
unsigned long long
{
const char *s;
unsigned long long acc;
-@@ -57,13 +60,14 @@
+@@ -53,13 +56,14 @@ strtoull(const char * __restrict nptr, c
unsigned long long cutoff;
int neg, any, cutlim;
if (c == '-') {
neg = 1;
c = *s++;
-@@ -117,3 +121,9 @@
+@@ -116,3 +120,9 @@ noconv:
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
* 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.
static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.11 2007/01/09 00:28:10 imp Exp $");
#include <ctype.h>
#include <errno.h>
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
---- strtoumax.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtoumax.c 2005-02-23 13:24:30.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtoumax.c.bsdnew 2009-11-13 14:11:52.000000000 -0800
++++ strtoumax.c 2009-11-13 14:11:52.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "from @(#)strtoul
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.11 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
-@@ -49,7 +51,8 @@
+@@ -45,7 +47,8 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
* alphabets and digits are each contiguous.
*/
uintmax_t
{
const char *s;
uintmax_t acc;
-@@ -57,13 +60,14 @@
+@@ -53,13 +56,14 @@ strtoumax(const char * __restrict nptr,
uintmax_t cutoff;
int neg, any, cutlim;
if (c == '-') {
neg = 1;
c = *s++;
-@@ -117,3 +121,9 @@
+@@ -116,3 +120,9 @@ noconv:
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}
* 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.
static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.11 2002/08/15 09:25:04 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
#include <sys/types.h>
---- strtouq.c.orig 2003-05-20 15:23:25.000000000 -0700
-+++ strtouq.c 2005-02-23 18:29:05.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strtouq.c.bsdnew 2009-11-13 14:11:52.000000000 -0800
++++ strtouq.c 2009-11-13 14:11:52.000000000 -0800
+@@ -33,6 +33,8 @@ static char sccsid[] = "@(#)strtouq.c 8.
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.11 2002/08/15 09:25:04 robert Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
+#include "xlocale_private.h"
+
#include <sys/types.h>
#include <stdlib.h>
-@@ -48,5 +50,13 @@
+@@ -44,5 +46,13 @@ u_quad_t
strtouq(const char *nptr, char **endptr, int base)
{
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)system.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/system.3,v 1.11 2002/05/27 03:45:27 dd Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/system.3,v 1.13 2008/06/26 08:24:59 danger Exp $
.\"
.Dd June 4, 1993
.Dt SYSTEM 3
will return non-zero if the command interpreter
.Xr sh 1
is available, and zero if it is not.
-.Pp
+.Sh RETURN VALUES
The
.Fn system
function
---- _SB/Libc/stdlib/FreeBSD/system.3 2003-05-20 15:23:25.000000000 -0700
-+++ _SB/Libc/stdlib/FreeBSD/system.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,13 +47,13 @@
+--- system.3.bsdnew 2009-11-13 14:11:52.000000000 -0800
++++ system.3 2009-11-13 14:11:52.000000000 -0800
+@@ -43,13 +43,13 @@
.Sh SYNOPSIS
.In stdlib.h
.Ft int
to the command interpreter
.Xr sh 1 .
The calling process waits for the shell
-@@ -66,7 +66,7 @@
+@@ -62,7 +62,7 @@ and blocking
.Dv SIGCHLD .
.Pp
If
* 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.
static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/system.c,v 1.10 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/system.c,v 1.11 2007/01/09 00:28:10 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
---- system.c.orig 2008-08-28 02:12:39.000000000 -0700
-+++ system.c 2008-08-28 02:15:08.000000000 -0700
-@@ -44,23 +44,61 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
+--- system.c.bsdnew 2009-11-13 14:11:52.000000000 -0800
++++ system.c 2009-11-13 14:11:52.000000000 -0800
+@@ -40,23 +40,61 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
/*
* Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save
* existing signal dispositions.
-@@ -69,33 +107,45 @@ __system(command)
+@@ -65,33 +103,45 @@ __system(command)
(void)sigemptyset(&ign.sa_mask);
ign.sa_flags = 0;
(void)_sigaction(SIGINT, &ign, &intact);
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" OpenBSD: tsearch.3,v 1.2 1998/06/21 22:13:49 millert Exp
-.\" $FreeBSD: src/lib/libc/stdlib/tsearch.3,v 1.13 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/tsearch.3,v 1.15 2006/06/23 13:36:33 keramida Exp $
.\"
.Dd June 15, 1997
.Dt TSEARCH 3
.Ft void *
.Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
.Ft void
-.Fn twalk "const void *root" "void (*compar) (const void *, VISIT, int)"
+.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)"
.Sh DESCRIPTION
The
.Fn tdelete ,
.Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;"
specifying the traversal type, and a node level (where level
zero is the root of the tree).
-.Sh SEE ALSO
-.Xr bsearch 3 ,
-.Xr hsearch 3 ,
-.Xr lsearch 3
.Sh RETURN VALUES
The
.Fn tsearch
The
.Fn twalk
function returns no value.
+.Sh SEE ALSO
+.Xr bsearch 3 ,
+.Xr hsearch 3 ,
+.Xr lsearch 3
---- tsearch.3.orig 2007-03-06 15:44:54.000000000 -0800
-+++ tsearch.3 2007-03-06 16:04:48.000000000 -0800
+--- tsearch.3.bsdnew 2009-11-13 14:11:52.000000000 -0800
++++ tsearch.3 2009-11-13 14:42:09.000000000 -0800
@@ -31,18 +31,36 @@
.Dt TSEARCH 3
.Os
+.Fa "int (*compar) (const void *key1, const void *key2)"
+.Fc
.Ft void
--.Fn twalk "const void *root" "void (*compar) (const void *, VISIT, int)"
+-.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)"
+.Fo twalk
+.Fa "const void *root"
-+.Fa "void (*compar) (const void *node, VISIT order, int level)"
++.Fa "void (*action) (const void *node, VISIT order, int level)"
+.Fc
.Sh DESCRIPTION
The
.Fn tdelete ,
-@@ -50,39 +68,46 @@
+@@ -50,39 +68,46 @@ The
.Fn tsearch ,
and
.Fn twalk
It takes the same arguments as
.Fn tfind
and
-@@ -93,20 +118,44 @@
+@@ -93,20 +118,44 @@ will be adjusted.
.Pp
The
.Fn twalk
+to what would typically be referred to as in-order, and the
+traversal type "endorder" corresponds to what would typically
+be referred to as post-order.
- .Sh SEE ALSO
- .Xr bsearch 3 ,
- .Xr hsearch 3 ,
-@@ -125,7 +174,7 @@
+ .Sh RETURN VALUES
+ The
+ .Fn tsearch
+@@ -121,7 +170,7 @@ and
functions
return NULL if
.Fa rootp
LEGACYSRCS+= getopt.c putenv.c realpath.c setenv.c system.c
DARWINEXTSNSRCS += realpath.c
CANCELABLESRCS += system.c
+DYLDSRCS += atexit.c exit.c gettimeofday.c heapsort.c merge.c qsort.c reallocf.c realpath.c
# set the LIBC_ALIAS_* macros so we can decorate the symbol independent
# of other macro settings
---- strfmon.3.orig 2008-04-05 20:02:08.000000000 -0700
-+++ strfmon.3 2008-04-05 20:05:49.000000000 -0700
+--- strfmon.3.orig 2010-02-08 16:26:10.000000000 -0800
++++ strfmon.3 2010-02-08 17:57:07.000000000 -0800
@@ -30,25 +30,49 @@
.Dt STRFMON 3
.Os
The format string is composed of zero or more directives:
ordinary characters (not
.Cm % ) ,
-@@ -116,9 +140,9 @@
+@@ -116,9 +140,9 @@ character is written.
.El
.El
.Sh RETURN VALUES
.Fa maxsize ,
.Fn strfmon
returns the number of bytes placed into the array pointed to by
-@@ -144,7 +168,8 @@
+@@ -143,8 +167,23 @@ The format string is invalid.
+ .It Bq Er ENOMEM
Not enough memory for temporary buffers.
.El
++.Sh EXAMPLE
++.Bd -literal -offset indent -compact
++ #include <stdio.h>
++ #include <monetary.h>
++ #include <locale.h>
++
++ int main() {
++ char buf[200];
++ setlocale(LC_ALL, "en_US");
++ (void)strfmon (buf, sizeof(buf)-1, "%n" , 123456.78);
++ printf("%s\n", buf);
++ }
++.Ed
++.Pp
.Sh SEE ALSO
-.Xr localeconv 3
+.Xr localeconv 3 ,
-/* $NetBSD: strfmon.c,v 1.6 2008/03/27 21:50:30 christos Exp $ */
+/* $NetBSD: strfmon.c,v 1.7 2009/01/30 23:46:03 lukem Exp $ */
/*-
* Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
#if 0
__FBSDID("$FreeBSD: src/lib/libc/stdlib/strfmon.c,v 1.14 2003/03/20 08:18:55 ache Exp $");
#else
-__RCSID("$NetBSD: strfmon.c,v 1.6 2008/03/27 21:50:30 christos Exp $");
+__RCSID("$NetBSD: strfmon.c,v 1.7 2009/01/30 23:46:03 lukem Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
* required width ?
*/
- if (d + width >= maxsize)
+ if ((size_t)(d + width) >= maxsize)
goto e2big_error;
}
-.\" $OpenBSD: ecvt.3,v 1.7 2004/01/25 14:48:32 jmc Exp $
+.\" $OpenBSD: ecvt.3,v 1.8 2007/05/31 19:19:31 jmc Exp $
.\"
.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
.\"
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
-.Dd December 1, 2002
+.Dd $Mdocdate: May 31 2007 $
.Dt ECVT 3
.Os
.Sh NAME
-/* $OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $ */
+/* $OpenBSD: ecvt.c,v 1.7 2009/10/16 12:15:03 martynas Exp $ */
/*
- * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char *__dtoa(double, int, int, int *, int *, char **);
+extern void __freedtoa(char *);
static char *__cvt(double, int, int *, int *, int, int);
static char *
__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
{
static char *s;
- char *p, *rve;
+ char *p, *rve, c;
size_t siz;
if (ndigit == 0) {
*rve = '\0';
} else {
p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
+ if (p == NULL)
+ return (NULL);
if (*decpt == 9999) {
- /* Nan or Infinity */
+ /* Infinity or Nan, convert to inf or nan like printf */
*decpt = 0;
- return(p);
+ c = *p;
+ __freedtoa(p);
+ return(c == 'I' ? "inf" : "nan");
}
- /* make a local copy and adjust rve to be in terms of s */
+ /* Make a local copy and adjust rve to be in terms of s */
if (pad && fmode)
siz += *decpt;
- if ((s = (char *)malloc(siz)) == NULL)
+ if ((s = (char *)malloc(siz)) == NULL) {
+ __freedtoa(p);
return(NULL);
+ }
(void) strlcpy(s, p, siz);
rve = s + (rve - p);
+ __freedtoa(p);
}
- /* Add trailing zeros (unless we got NaN or Inf) */
- if (pad && *decpt != 9999) {
+ /* Add trailing zeros */
+ if (pad) {
siz -= rve - s;
while (--siz)
*rve++ = '0';
---- ecvt.c.orig Thu Jul 8 16:06:45 2004
-+++ ecvt.c Fri Jul 9 12:23:51 2004
+--- ecvt.c.orig 2009-11-06 00:43:00.000000000 -0800
++++ ecvt.c 2009-11-06 00:45:11.000000000 -0800
@@ -20,6 +20,7 @@
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
+#include <sys/cdefs.h>
- #if defined(LIBC_SCCS) && !defined(lint)
- static char rcsid[] = "$OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $";
- #endif /* LIBC_SCCS and not lint */
-@@ -29,10 +30,11 @@
+ #include <stdio.h>
+ #include <stdlib.h>
#include <string.h>
-
- extern char *__dtoa(double, int, int, int *, int *, char **);
-+extern void __freedtoa(char *); /* special gdtoa free function */
+@@ -29,7 +30,7 @@ extern void __freedtoa(char *);
static char *__cvt(double, int, int *, int *, int, int);
static char *
+__cvt(double value, int ndigit, int * __restrict decpt, int * __restrict sign, int fmode, int pad)
{
static char *s;
- char *p, *rve;
-@@ -68,15 +70,20 @@
- if (*decpt == 9999) {
- /* Nan or Infinity */
- *decpt = 0;
-- return(p);
-+ rve = (*p == 'N') ? "nan" : "inf";
-+ __freedtoa(p);
-+ return(rve);
- }
- /* make a local copy and adjust rve to be in terms of s */
- if (pad && fmode)
- siz += *decpt;
-- if ((s = (char *)malloc(siz)) == NULL)
-+ if ((s = (char *)malloc(siz)) == NULL) {
-+ __freedtoa(p);
- return(NULL);
-+ }
- (void) strlcpy(s, p, siz);
- rve = s + (rve - p);
-+ __freedtoa(p);
- }
-
- /* Add trailing zeros (unless we got NaN or Inf) */
-@@ -91,13 +98,13 @@
+ char *p, *rve, c;
+@@ -95,13 +96,13 @@ __cvt(double value, int ndigit, int *dec
}
char *
-/* $OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $ */
+/* $OpenBSD: gcvt.c,v 1.11 2009/10/16 12:15:03 martynas Exp $ */
/*
- * Copyright (c) 2002, 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2002, 2003, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
-
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char *__dtoa(double, int, int, int *, int *, char **);
+extern void __freedtoa(char *);
char *
gcvt(double value, int ndigit, char *buf)
{
char *digits, *dst, *src;
int i, decpt, sign;
+ struct lconv *lconv;
+ lconv = localeconv();
if (ndigit == 0) {
buf[0] = '\0';
return (buf);
}
digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
+ if (digits == NULL)
+ return (NULL);
if (decpt == 9999) {
- /* Infinity or NaN, assume buffer is at least ndigit long. */
- strlcpy(buf, digits, ndigit + 1);
+ /*
+ * Infinity or NaN, convert to inf or nan with sign.
+ * We assume the buffer is at least ndigit long.
+ */
+ snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "",
+ *digits == 'I' ? "inf" : "nan");
+ __freedtoa(digits);
return (buf);
}
*dst++ = '-';
if (decpt < 0 || decpt > ndigit) {
- /* exponential format */
+ /* exponential format (e.g. 1.2345e+13) */
if (--decpt < 0) {
sign = 1;
decpt = -decpt;
} else
sign = 0;
- for (src = digits; *src != '\0'; )
+ src = digits;
+ *dst++ = *src++;
+ *dst++ = *lconv->decimal_point;
+ while (*src != '\0')
*dst++ = *src++;
*dst++ = 'e';
if (sign)
} else {
/* XXX - optimize */
for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
- sign /= 10;
+ continue;
+ dst[i + 1] = '\0';
while (decpt != 0) {
dst[i--] = '0' + decpt % 10;
decpt /= 10;
*dst++ = '0';
}
if (*src != '\0') {
- *dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */
+ if (src == digits)
+ *dst++ = '0'; /* zero before decimal point */
+ *dst++ = *lconv->decimal_point;
for (i = decpt; digits[i] != '\0'; i++) {
*dst++ = digits[i];
}
}
*dst = '\0';
}
+ __freedtoa(digits);
return (buf);
}
---- gcvt.c.orig Thu Jul 8 16:06:45 2004
-+++ gcvt.c Fri Jul 9 12:16:25 2004
-@@ -27,14 +27,17 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-+#include <locale.h>
-
- extern char *__dtoa(double, int, int, int *, int *, char **);
-+extern void __freedtoa(char *);
-
- char *
- gcvt(double value, int ndigit, char *buf)
- {
- char *digits, *dst, *src;
- int i, decpt, sign;
-+ char *decimal_point = localeconv()->decimal_point;
-
- if (ndigit == 0) {
- buf[0] = '\0';
-@@ -43,8 +46,12 @@
-
- digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
- if (decpt == 9999) {
-- /* Infinity or NaN, assume buffer is at least ndigit long. */
-- strlcpy(buf, digits, ndigit + 1);
-+ /* Infinity or NaN, assume buffer is long enough. */
-+ dst = buf;
-+ if (sign)
-+ *dst++ = '-';
-+ strcpy(dst, (*digits == 'N') ? "nan" : "inf");
-+ __freedtoa(digits);
- return (buf);
- }
-
-@@ -59,7 +66,10 @@
- decpt = -decpt;
- } else
+--- gcvt.c.orig 2009-11-06 00:45:45.000000000 -0800
++++ gcvt.c 2009-11-06 00:52:51.000000000 -0800
+@@ -68,7 +68,7 @@ gcvt(double value, int ndigit, char *buf
sign = 0;
-- for (src = digits; *src != '\0'; )
-+ src = digits;
-+ *dst++ = *src++;
-+ dst = stpcpy(dst, decimal_point);
-+ while (*src != '\0')
+ src = digits;
+ *dst++ = *src++;
+- *dst++ = *lconv->decimal_point;
++ dst = stpcpy(dst, lconv->decimal_point);
+ while (*src != '\0')
*dst++ = *src++;
*dst++ = 'e';
- if (sign)
-@@ -72,8 +82,8 @@
- *dst = '\0';
- } else {
- /* XXX - optimize */
-- for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
-- sign /= 10;
-+ for (sign = decpt, i = 0; (sign /= 10) != 0; i++) {}
-+ dst[i + 1] = '\0';
- while (decpt != 0) {
- dst[i--] = '0' + decpt % 10;
- decpt /= 10;
-@@ -88,12 +98,15 @@
- *dst++ = '0';
- }
+@@ -101,7 +101,7 @@ gcvt(double value, int ndigit, char *buf
if (*src != '\0') {
-- *dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */
-+ if (src == digits) /* need leading zero */
-+ *dst++ = '0';
-+ dst = stpcpy(dst, decimal_point);
+ if (src == digits)
+ *dst++ = '0'; /* zero before decimal point */
+- *dst++ = *lconv->decimal_point;
++ dst = stpcpy(dst, lconv->decimal_point);
for (i = decpt; digits[i] != '\0'; i++) {
*dst++ = digits[i];
}
- }
- *dst = '\0';
- }
-+ __freedtoa(digits);
- return (buf);
- }
* 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.
static char sccsid[] = "@(#)abort.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.9 2003/08/16 11:43:57 davidxu Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.11 2007/01/09 00:28:09 imp Exp $");
#include "namespace.h"
#include <signal.h>
#include <pthread.h>
#include "un-namespace.h"
+#include "libc_private.h"
+
+#include "CrashReporterClient.h"
+#include "_simple.h"
+
extern void (*__cleanup)();
extern void __abort(void) __dead2;
-extern const char *__crashreporter_info__;
#define TIMEOUT 10000 /* 10 milliseconds */
{
struct sigaction act;
- if (!__crashreporter_info__)
- __crashreporter_info__ = "abort() called";
+ if (!CRGetCrashLogMessage())
+ CRSetCrashLogMessage("abort() called");
+
/*
* POSIX requires we flush stdio buffers on abort.
* XXX ISO C requires that abort() be async-signal-safe.
* any errors -- ISO C doesn't allow abort to return anyway.
*/
sigdelset(&act.sa_mask, SIGABRT);
- (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
- (void)raise(SIGABRT);
+
+ /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread
+ * This helps gdb focus on the thread calling abort()
+ */
+ if (__is_threaded) {
+ /* Block all signals on all other threads */
+ sigset_t fullmask;
+ sigfillset(&fullmask);
+ (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
+
+ /* <rdar://problem/8400096> Set the workqueue killable */
+ __pthread_workqueue_setkill(1);
+
+ (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
+ (void)pthread_kill(pthread_self(), SIGABRT);
+ } else {
+ (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
+ (void)kill(getpid(), SIGABRT);
+ }
usleep(TIMEOUT); /* give time for signal to happen */
/*
{
struct sigaction act;
- if (!__crashreporter_info__)
- __crashreporter_info__ = "__abort() called";
+ if (!CRGetCrashLogMessage())
+ CRSetCrashLogMessage("__abort() called");
act.sa_handler = SIG_DFL;
act.sa_flags = 0;
sigfillset(&act.sa_mask);
(void)_sigaction(SIGABRT, &act, NULL);
sigdelset(&act.sa_mask, SIGABRT);
- (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
- (void)raise(SIGABRT);
+
+ /* <rdar://problem/7397932> abort() should call pthread_kill to deliver a signal to the aborting thread
+ * This helps gdb focus on the thread calling abort()
+ */
+ if (__is_threaded) {
+ /* Block all signals on all other threads */
+ sigset_t fullmask;
+ sigfillset(&fullmask);
+ (void)_sigprocmask(SIG_SETMASK, &fullmask, NULL);
+
+ /* <rdar://problem/8400096> Set the workqueue killable */
+ __pthread_workqueue_setkill(1);
+
+ (void)pthread_sigmask(SIG_SETMASK, &act.sa_mask, NULL);
+ (void)pthread_kill(pthread_self(), SIGABRT);
+ } else {
+ (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
+ (void)kill(getpid(), SIGABRT);
+ }
usleep(TIMEOUT); /* give time for signal to happen */
- __builtin_trap(); /* never exit normally */
+
+ /* If for some reason SIGABRT was not delivered, we exit using __builtin_trap
+ * which generates an illegal instruction on i386: <rdar://problem/8400958>
+ * and SIGTRAP on arm.
+ */
+ sigfillset(&act.sa_mask);
+ sigdelset(&act.sa_mask, SIGILL);
+ sigdelset(&act.sa_mask, SIGTRAP);
+ (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
+ __builtin_trap();
}
__private_extern__ void
abort_report_np(const char *fmt, ...)
{
- char *str;
+ _SIMPLE_STRING s;
va_list ap;
- va_start(ap, fmt);
- vasprintf(&str, fmt, ap);
- va_end(ap);
- __crashreporter_info__ = str ? str : fmt;
+ if ((s = _simple_salloc()) != NULL) {
+ va_start(ap, fmt);
+ _simple_vsprintf(s, fmt, ap);
+ va_end(ap);
+ CRSetCrashLogMessage(_simple_string(s));
+ } else
+ CRSetCrashLogMessage(fmt); /* the format string is better than nothing */
abort();
}
+++ /dev/null
-./abort.3
\ No newline at end of file
--- /dev/null
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" 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.
+.\" 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.
+.\"
+.\" @(#)abort.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD: src/lib/libc/stdlib/abort.3,v 1.10 2007/01/09 00:28:09 imp Exp $
+.\"
+.Dd June 4, 1993
+.Dt ABORT 3
+.Os
+.Sh NAME
+.Nm abort
+.Nd cause abnormal program termination
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void
+.Fn abort void
+.Sh DESCRIPTION
+The
+.Fn abort
+function causes abnormal program termination to occur, unless the
+signal
+.Dv SIGABRT
+is being caught and the signal handler does not return.
+.Pp
+Any open streams are flushed and closed.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn abort
+function is thread-safe.
+It is unknown if it is async-cancel-safe.
+.Pp
+The
+.Fn abort
+function causes a report to be generated by Crash Reporter. If you wish to
+terminate without generating a crash report, use
+.Xr exit 3
+instead.
+.Sh RETURN VALUES
+The
+.Fn abort
+function
+never returns.
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr exit 3
+.Sh STANDARDS
+The
+.Fn abort
+function
+conforms to
+.St -p1003.1-90 .
+The
+.Fn abort
+function also conforms to
+.St -isoC-99
+with the implementation specific details as noted above.
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)abs.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/abs.3,v 1.12 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/abs.3,v 1.13 2007/01/09 00:28:09 imp Exp $
.\"
.Dd November 14, 2001
.Dt ABS 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)alloca.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/alloca.3,v 1.11 2003/06/28 22:12:30 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/alloca.3,v 1.13 2007/01/09 00:28:09 imp Exp $
.\"
-.Dd June 4, 1993
+.Dd September 5, 2006
.Dt ALLOCA 3
.Os
.Sh NAME
.Nm alloca
.Nd memory allocator
-.Sh LIBRARY
-.Lb libc
.Sh SYNOPSIS
.In alloca.h
or
.Sh DESCRIPTION
The
.Fn alloca
-function
+macro
allocates
.Fa size
bytes of space in the stack frame of the caller.
This temporary space is automatically freed on
return.
.Sh RETURN VALUES
-The
.Fn alloca
-function returns a pointer to the beginning of the allocated space.
-If the allocation failed, a
-.Dv NULL
-pointer is returned.
+returns a pointer to the beginning of the allocated space.
.Sh SEE ALSO
.Xr brk 2 ,
.Xr calloc 3 ,
.Xr malloc 3 ,
.Xr realloc 3
.Sh HISTORY
-The
.Fn alloca
-function appeared in
+appeared in
.At 32v .
.\" .Bx ?? .
.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
.\" The first man page (or link to a man page that I can find at the
.\" moment is 4.3...
.Sh BUGS
-The
.Fn alloca
-function
is machine and compiler dependent;
its use is discouraged.
+.Pp
+.Fn alloca
+is slightly unsafe because it cannot ensure that the pointer
+returned points to a valid and usable block of memory.
+The allocation made may exceed the bounds of the stack, or even go
+further into other objects in memory, and
+.Fn alloca
+cannot determine such an error.
+Avoid
+.Fn alloca
+with large unbounded allocations.
+.Pp
+The use of C99 variable-length arrays and
+.Fn alloca
+in the same function will cause the lifetime of alloca's storage to be limited to the block containing the
+.Fn alloca
* 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.
static char sccsid[] = "@(#)atexit.c 8.2 (Berkeley) 7/3/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.7 2003/12/19 17:11:20 kan Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.8 2007/01/09 00:28:09 imp Exp $");
#include "namespace.h"
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
-#if defined(__DYNAMIC__)
+#if defined(__DYNAMIC__) || defined (__BLOCKS__)
#include <dlfcn.h>
#endif /* defined(__DYNAMIC__) */
#include "atexit.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atexit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.10 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.11 2007/01/09 00:28:09 imp Exp $
.\"
.Dd May 20, 2008
.Dt ATEXIT 3
* 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.
* SUCH DAMAGE.
*
* @(#)atexit.h 8.2 (Berkeley) 7/3/94
- * $FreeBSD: src/lib/libc/stdlib/atexit.h,v 1.3 2003/12/19 17:11:20 kan Exp $
+ * $FreeBSD: src/lib/libc/stdlib/atexit.h,v 1.4 2007/01/09 00:28:09 imp Exp $
*/
/* must be at least 32 to guarantee ANSI conformance */
* 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.
static char sccsid[] = "@(#)atof.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atof.c,v 1.5 2004/02/10 20:42:32 cperciva Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atof.c,v 1.6 2007/01/09 00:28:09 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atof.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atof.3,v 1.16 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atof.3,v 1.17 2007/01/09 00:28:09 imp Exp $
.\"
.Dd June 4, 1993
.Dt ATOF 3
.Sh IMPLEMENTATION NOTES
The
.Fn atof
-function is not thread-safe and also not async-cancel-safe.
+and
+.Fn atof_l
+functions are thread-safe and async-cancel-safe.
.Pp
The
.Fn atof
-function has been deprecated by
+and
+.Fn atof_l
+functions have been deprecated by
.Fn strtod
+and
+.Fn strtod_l
and should not be used in new code.
.Sh ERRORS
The function
* 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.
static char sccsid[] = "@(#)atoi.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoi.c,v 1.5 2002/03/22 21:53:09 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoi.c,v 1.6 2007/01/09 00:28:09 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atoi.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atoi.3,v 1.12 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atoi.3,v 1.14 2007/10/19 06:23:39 davidxu Exp $
.\"
.Dd June 4, 1993
.Dt ATOI 3
.Sh IMPLEMENTATION NOTES
The
.Fn atoi
-function is not thread-safe and also not async-cancel safe.
+and
+.Fn atoi_l
+functions are thread-safe and async-cancel-safe.
.Pp
The
.Fn atoi
-function has been deprecated by
+and
+.Fn atoi_l
+functions have been deprecated by
.Fn strtol
+and
+.Fn strtol_l
and should not be used in new code.
.Sh ERRORS
The function
* 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.
static char sccsid[] = "@(#)atol.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atol.c,v 1.4 2002/03/22 21:53:09 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atol.c,v 1.5 2007/01/09 00:28:09 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)atol.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atol.3,v 1.13 2002/01/09 14:03:54 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/atol.3,v 1.16 2009/03/01 05:44:28 delphij Exp $
.\"
-.Dd November 28, 2001
+.Dd February 1, 2009
.Dt ATOL 3
.Os
.Sh NAME
functions may be passed locales directly. See
.Xr xlocale 3
for more information.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn atol ,
+.Fn atoll ,
+.Fn atol_l ,
+and
+.Fn atoll_l
+functions are thread-safe and async-cancel-safe.
+.Pp
+The
+.Fx
+implementations of the
+.Fn atol
+and
+.Fn atoll
+functions are thin wrappers around
+.Fn strtol
+and
+.Fn stroll
+respectively, so these functions will affect the value of
+.Va errno
+in the same way that the
+.Fn strtol
+and
+.Fn stroll
+functions are able to.
+This behavior of
+.Fn atol
+and
+.Fn atoll
+is not required by
+.St -isoC
+or
+.St -isoC-99 ,
+but it is allowed by all of
+.St -isoC , St -isoC-99
+and
+.St -p1003.1-2001 .
.Sh ERRORS
The functions
.Fn atol
and
.Fn atoll
-need not
-affect the value of
+may affect the value of
.Va errno
on an error.
.Sh SEE ALSO
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoll.c,v 1.4 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/atoll.c,v 1.5 2007/01/09 00:28:09 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/bsearch.c,v 1.3 2002/03/21 22:48:41 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/bsearch.c,v 1.4 2007/01/09 00:28:09 imp Exp $");
#include <stddef.h>
#include <stdlib.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.8 2001/09/07 14:46:35 asmodai Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/bsearch.3,v 1.9 2007/01/09 00:28:09 imp Exp $
.\"
.Dd May 20, 2008
.Dt BSEARCH 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)div.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/div.3,v 1.8 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/div.3,v 1.9 2007/01/09 00:28:09 imp Exp $
.\"
.Dd November 14, 2001
.Dt DIV 3
-/* $OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $ */
+/* $OpenBSD: ecvt.c,v 1.7 2009/10/16 12:15:03 martynas Exp $ */
/*
- * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
*/
#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char *__dtoa(double, int, int, int *, int *, char **);
-extern void __freedtoa(char *); /* special gdtoa free function */
+extern void __freedtoa(char *);
static char *__cvt(double, int, int *, int *, int, int);
static char *
__cvt(double value, int ndigit, int * __restrict decpt, int * __restrict sign, int fmode, int pad)
{
static char *s;
- char *p, *rve;
+ char *p, *rve, c;
size_t siz;
if (ndigit == 0) {
*rve = '\0';
} else {
p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
+ if (p == NULL)
+ return (NULL);
if (*decpt == 9999) {
- /* Nan or Infinity */
+ /* Infinity or Nan, convert to inf or nan like printf */
*decpt = 0;
- rve = (*p == 'N') ? "nan" : "inf";
+ c = *p;
__freedtoa(p);
- return(rve);
+ return(c == 'I' ? "inf" : "nan");
}
- /* make a local copy and adjust rve to be in terms of s */
+ /* Make a local copy and adjust rve to be in terms of s */
if (pad && fmode)
siz += *decpt;
if ((s = (char *)malloc(siz)) == NULL) {
__freedtoa(p);
}
- /* Add trailing zeros (unless we got NaN or Inf) */
- if (pad && *decpt != 9999) {
+ /* Add trailing zeros */
+ if (pad) {
siz -= rve - s;
while (--siz)
*rve++ = '0';
-.\" $OpenBSD: ecvt.3,v 1.7 2004/01/25 14:48:32 jmc Exp $
+.\" $OpenBSD: ecvt.3,v 1.8 2007/05/31 19:19:31 jmc Exp $
.\"
.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
.\"
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
-.Dd December 1, 2002
+.Dd $Mdocdate: May 31 2007 $
.Dt ECVT 3
.Os
.Sh NAME
* 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.
static char sccsid[] = "@(#)exit.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/exit.c,v 1.7 2003/12/19 17:11:20 kan Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/exit.c,v 1.9 2007/01/09 00:28:09 imp Exp $");
#include "namespace.h"
#include <stdlib.h>
#include <unistd.h>
#include "un-namespace.h"
+
#include "atexit.h"
+#include "libc_private.h"
-void (*__cleanup)();
+void (*__cleanup)(void);
extern void __exit(int);
/*
-/* $OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $ */
+/* $OpenBSD: gcvt.c,v 1.11 2009/10/16 12:15:03 martynas Exp $ */
/*
- * Copyright (c) 2002, 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2002, 2003, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
-
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <locale.h>
extern char *__dtoa(double, int, int, int *, int *, char **);
-extern void __freedtoa(char *);
+extern void __freedtoa(char *);
char *
gcvt(double value, int ndigit, char *buf)
{
char *digits, *dst, *src;
int i, decpt, sign;
- char *decimal_point = localeconv()->decimal_point;
+ struct lconv *lconv;
+ lconv = localeconv();
if (ndigit == 0) {
buf[0] = '\0';
return (buf);
}
digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
+ if (digits == NULL)
+ return (NULL);
if (decpt == 9999) {
- /* Infinity or NaN, assume buffer is long enough. */
- dst = buf;
- if (sign)
- *dst++ = '-';
- strcpy(dst, (*digits == 'N') ? "nan" : "inf");
+ /*
+ * Infinity or NaN, convert to inf or nan with sign.
+ * We assume the buffer is at least ndigit long.
+ */
+ snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "",
+ *digits == 'I' ? "inf" : "nan");
__freedtoa(digits);
return (buf);
}
*dst++ = '-';
if (decpt < 0 || decpt > ndigit) {
- /* exponential format */
+ /* exponential format (e.g. 1.2345e+13) */
if (--decpt < 0) {
sign = 1;
decpt = -decpt;
sign = 0;
src = digits;
*dst++ = *src++;
- dst = stpcpy(dst, decimal_point);
+ dst = stpcpy(dst, lconv->decimal_point);
while (*src != '\0')
*dst++ = *src++;
*dst++ = 'e';
*dst = '\0';
} else {
/* XXX - optimize */
- for (sign = decpt, i = 0; (sign /= 10) != 0; i++) {}
+ for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
+ continue;
dst[i + 1] = '\0';
while (decpt != 0) {
dst[i--] = '0' + decpt % 10;
*dst++ = '0';
}
if (*src != '\0') {
- if (src == digits) /* need leading zero */
- *dst++ = '0';
- dst = stpcpy(dst, decimal_point);
+ if (src == digits)
+ *dst++ = '0'; /* zero before decimal point */
+ dst = stpcpy(dst, lconv->decimal_point);
for (i = decpt; digits[i] != '\0'; i++) {
*dst++ = digits[i];
}
* 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.
static char sccsid[] = "@(#)getenv.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/getenv.c,v 1.4 2002/03/21 22:48:41 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/getenv.c,v 1.8 2007/05/01 16:02:41 ache Exp $");
#include <stdlib.h>
#include <stddef.h>
* 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.
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.7 2004/03/06 17:05:45 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.8 2007/01/09 00:28:10 imp Exp $");
#include "namespace.h"
#include <stdio.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/stdlib/getsubopt.3,v 1.10 2004/02/23 03:32:10 ache Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/getsubopt.3,v 1.11 2007/01/09 00:28:10 imp Exp $
.\"
.Dd June 9, 1993
.Dt GETSUBOPT 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)labs.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/labs.3,v 1.9 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/labs.3,v 1.10 2007/01/09 00:28:10 imp Exp $
.\"
.Dd November 14, 2001
.Dt LABS 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ldiv.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/ldiv.3,v 1.9 2002/12/18 13:33:03 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/ldiv.3,v 1.10 2007/01/09 00:28:10 imp Exp $
.\"
.Dd November 14, 2001
.Dt LDIV 3
.\" As long as the above copyright statement and this notice remain
.\" unchanged, you can do what ever you want with this file.
.\"
-.\" $FreeBSD: src/lib/libc/stdlib/lsearch.3,v 1.4 2002/12/19 09:40:24 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/lsearch.3,v 1.5 2005/01/20 09:17:04 ru Exp $
.\"
.Dd October 11, 2002
.Dt LSEARCH 3
.Xr bsearch 3 ,
.Xr hsearch 3 ,
.Xr tsearch 3
+.Sh STANDARDS
+The
+.Fn lsearch
+and
+.Fn lfind
+functions conform to
+.St -p1003.1-2001 .
.Sh HISTORY
The
.Fn lsearch
.Fx 5.0 ,
they reappeared conforming to
.St -p1003.1-2001 .
-.Sh STANDARDS
-The
-.Fn lsearch
-and
-.Fn lfind
-functions conform to
-.St -p1003.1-2001 .
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memory.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/memory.3,v 1.11 2001/09/07 14:46:35 asmodai Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/memory.3,v 1.12 2007/01/09 00:28:10 imp Exp $
.\"
.Dd June 4, 1993
.Dt MEMORY 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)qsort.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.15 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.17 2007/01/09 00:28:10 imp Exp $
.\"
.Dd Nov 25, 2008
.Dt PSORT 3
return no value.
.Sh SEE ALSO
.Xr qsort 3
+.Sh SEE ALSO
+.Xr sort 1 ,
+.Xr radixsort 3
+.Rs
+.%A Hoare, C.A.R.
+.%D 1962
+.%T "Quicksort"
+.%J "The Computer Journal"
+.%V 5:1
+.%P pp. 10-15
+.Re
+.Rs
+.%A Williams, J.W.J
+.%D 1964
+.%T "Heapsort"
+.%J "Communications of the ACM"
+.%V 7:1
+.%P pp. 347-348
+.Re
+.Rs
+.%A Knuth, D.E.
+.%D 1968
+.%B "The Art of Computer Programming"
+.%V Vol. 3
+.%T "Sorting and Searching"
+.%P pp. 114-123, 145-149
+.Re
+.Rs
+.%A McIlroy, P.M.
+.%T "Optimistic Sorting and Information Theoretic Complexity"
+.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
+.%V January 1992
+.Re
+.Rs
+.%A Bentley, J.L.
+.%A McIlroy, M.D.
+.%T "Engineering a Sort Function"
+.%J "Software--Practice and Experience"
+.%V Vol. 23(11)
+.%P pp. 1249-1265
+.%D November\ 1993
+.Re
+.Sh STANDARDS
+The
+.Fn qsort
+function
+conforms to
+.St -isoC .
---- psort.3.orig 2009-05-20 15:59:00.000000000 -0700
-+++ psort.3 2009-05-20 16:08:34.000000000 -0700
-@@ -36,60 +36,20 @@
+--- psort.3.orig 2010-10-07 21:34:52.000000000 -0700
++++ psort.3 2010-10-07 21:45:11.000000000 -0700
+@@ -32,60 +32,20 @@
.\" @(#)qsort.3 8.1 (Berkeley) 6/4/93
- .\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.15 2004/07/02 23:52:12 ru Exp $
+ .\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.17 2007/01/09 00:28:10 imp Exp $
.\"
-.Dd September 30, 2003
-.Dt QSORT 3
.Fa "void *base"
.Fa "size_t nel"
.Fa "size_t width"
-@@ -97,7 +57,7 @@
+@@ -93,7 +53,7 @@
.Fc
#ifdef UNIFDEF_BLOCKS
.Ft void
.Fa "void *base"
.Fa "size_t nel"
.Fa "size_t width"
-@@ -105,7 +65,7 @@
+@@ -101,7 +61,7 @@
.Fc
#endif
.Ft void
.Fa "void *base"
.Fa "size_t nel"
.Fa "size_t width"
-@@ -114,255 +74,60 @@
+@@ -110,210 +70,63 @@
.Fc
.Sh DESCRIPTION
The
-Normally,
-.Fn qsort
-is faster than
--.Fn mergesort ,
+-.Fn mergesort
-which is faster than
-.Fn heapsort .
-Memory availability and pre-existing order in the data can make this
-untrue.
--#ifdef UNIFDEF_BLOCKS
+ #ifdef UNIFDEF_BLOCKS
-.Pp
-The
-.Fn heapsort_b ,
-that the
-.Fa compar
-callback is a block pointer instead of a function pointer.
--#endif
--.Sh RETURN VALUES
--The
- #ifdef UNIFDEF_BLOCKS
--.Fn qsort ,
--.Fn qsort_b
+.Fn psort ,
+.Fn psort_b ,
- #else
--.Fn qsort
++#else
+.Fn psort
#endif
- and
--.Fn qsort_r
--functions
--return no value.
--.Pp
--#ifdef UNIFDEF_BLOCKS
--.ds HEAPSORT_B heapsort_b
--.ds MERGESORT_B mergesort_b
--#endif
--.Rv -std heapsort \*[HEAPSORT_B] mergesort \*[MERGESORT_B]
--.Sh ERRORS
++and
+.Fn psort_r
+functions are parallel sort routines that are drop-in compatible with the
+corresponding
+Like
+.Xr qsort 3 ,
+the sort is not stable.
-+.Sh RETURN VALUES
+ .Sh RETURN VALUES
The
#ifdef UNIFDEF_BLOCKS
+-.Fn qsort ,
+-.Fn qsort_b
++.Fn psort ,
++.Fn psort_b
+ #else
+-.Fn qsort
++.Fn psort
+ #endif
+ and
+-.Fn qsort_r
++.Fn psort_r
+ functions
+ return no value.
+-.Pp
+-#ifdef UNIFDEF_BLOCKS
+-.ds HEAPSORT_B heapsort_b
+-.ds MERGESORT_B mergesort_b
+-#endif
+-.Rv -std heapsort \*[HEAPSORT_B] mergesort \*[MERGESORT_B]
+-.Sh COMPATIBILITY
+-Previous versions of
+-.Fn qsort
+-did not permit the comparison routine itself to call
+-.Fn qsort 3 .
+-This is no longer true.
+-.Sh ERRORS
+-The
+-#ifdef UNIFDEF_BLOCKS
-.Fn heapsort ,
-.Fn heapsort_b ,
--.Fn mergesort
+-.Fn mergesort ,
-and
-.Fn mergesort_b
-+.Fn psort ,
-+.Fn psort_b
- #else
+-#else
-.Fn heapsort
-and
-.Fn mergesort
-#ifdef UNIFDEF_BLOCKS
-or
-.Fn mergesort_b
-+.Fn psort
- #endif
+-#endif
-is less than
-.Dq "sizeof(void *) / 2" .
-.It Bq Er ENOMEM
-#ifdef UNIFDEF_BLOCKS
-.Fn heapsort ,
-.Fn heapsort_b ,
--.Fn mergesort
--and
+-.Fn mergesort ,
+-or
-.Fn mergesort_b
-#else
-.Fn heapsort
- and
+-or
-.Fn mergesort
-#endif
-+.Fn psort_r
- functions
+-functions
-were unable to allocate memory.
-.El
--.Sh COMPATIBILITY
--Previous versions of
--.Fn qsort
--did not permit the comparison routine itself to call
--.Fn qsort 3 .
--This is no longer true.
-+return no value.
- .Sh SEE ALSO
--.Xr sort 1 ,
--.Xr radixsort 3
--.Rs
--.%A Hoare, C.A.R.
--.%D 1962
--.%T "Quicksort"
--.%J "The Computer Journal"
--.%V 5:1
--.%P pp. 10-15
--.Re
--.Rs
--.%A Williams, J.W.J
--.%D 1964
--.%T "Heapsort"
--.%J "Communications of the ACM"
--.%V 7:1
--.%P pp. 347-348
--.Re
--.Rs
--.%A Knuth, D.E.
--.%D 1968
--.%B "The Art of Computer Programming"
--.%V Vol. 3
--.%T "Sorting and Searching"
--.%P pp. 114-123, 145-149
--.Re
--.Rs
--.%A McIlroy, P.M.
--.%T "Optimistic Sorting and Information Theoretic Complexity"
--.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
--.%V January 1992
--.Re
--.Rs
--.%A Bentley, J.L.
--.%A McIlroy, M.D.
--.%T "Engineering a Sort Function"
--.%J "Software--Practice and Experience"
--.%V Vol. 23(11)
--.%P pp. 1249-1265
--.%D November\ 1993
--.Re
--.Sh STANDARDS
--The
--.Fn qsort
--function
--conforms to
--.St -isoC .
++.Sh SEE ALSO
+.Xr qsort 3
+ .Sh SEE ALSO
+ .Xr sort 1 ,
+ .Xr radixsort 3
* 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.
static char sccsid[] = "@(#)putenv.c 8.2 (Berkeley) 3/27/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/putenv.c,v 1.2 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/putenv.c,v 1.6 2007/05/01 16:02:41 ache Exp $");
#include <stdlib.h>
#include <string.h>
#include <errno.h>
extern malloc_zone_t *__zone0;
-extern void __malloc_check_env_name(const char *);
+#ifdef LEGACY_CRT1_ENVIRON
+extern char **_saved_environ;
+#endif /* LEGACY_CRT1_ENVIRON */
+extern void __malloc_check_env_name(const char *);
__private_extern__ int __setenv(const char *, const char *, int, int, char ***, malloc_zone_t *);
#ifndef BUILDING_VARIANT
putenv(str)
char *str;
{
+#ifdef LEGACY_CRT1_ENVIRON
+ int ret;
+#endif /* LEGACY_CRT1_ENVIRON */
+
#if __DARWIN_UNIX03
if (str == NULL || *str == 0 || index(str, '=') == NULL) {
errno = EINVAL;
}
}
__malloc_check_env_name(str); /* see if we are changing a malloc environment variable */
- return (__setenv(str, NULL, 1,
+#ifdef LEGACY_CRT1_ENVIRON
+ ret =
+#else /* !LEGACY_CRT1_ENVIRON */
+ return
+#endif /* !LEGACY_CRT1_ENVIRON */
+ __setenv(str, NULL, 1,
#if __DARWIN_UNIX03
0,
#else /* !__DARWIN_UNIX03 */
-1,
#endif /* __DARWIN_UNIX03 */
- _NSGetEnviron(), __zone0));
+ _NSGetEnviron(), __zone0);
+#ifdef LEGACY_CRT1_ENVIRON
+ _saved_environ = *_NSGetEnviron();
+ return ret;
+#endif /* LEGACY_CRT1_ENVIRON */
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)qsort.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.15 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.17 2007/01/09 00:28:10 imp Exp $
.\"
.Dd September 30, 2003
.Dt QSORT 3
Normally,
.Fn qsort
is faster than
-.Fn mergesort ,
+.Fn mergesort
which is faster than
.Fn heapsort .
Memory availability and pre-existing order in the data can make this
.ds MERGESORT_B mergesort_b
#endif
.Rv -std heapsort \*[HEAPSORT_B] mergesort \*[MERGESORT_B]
+.Sh COMPATIBILITY
+Previous versions of
+.Fn qsort
+did not permit the comparison routine itself to call
+.Fn qsort 3 .
+This is no longer true.
.Sh ERRORS
The
#ifdef UNIFDEF_BLOCKS
.Fn heapsort ,
.Fn heapsort_b ,
-.Fn mergesort
+.Fn mergesort ,
and
.Fn mergesort_b
#else
#ifdef UNIFDEF_BLOCKS
.Fn heapsort ,
.Fn heapsort_b ,
-.Fn mergesort
-and
+.Fn mergesort ,
+or
.Fn mergesort_b
#else
.Fn heapsort
-and
+or
.Fn mergesort
#endif
functions
were unable to allocate memory.
.El
-.Sh COMPATIBILITY
-Previous versions of
-.Fn qsort
-did not permit the comparison routine itself to call
-.Fn qsort 3 .
-This is no longer true.
.Sh SEE ALSO
.Xr sort 1 ,
.Xr radixsort 3
* 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.
static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/radixsort.c,v 1.7 2003/11/11 04:59:23 kientzle Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/radixsort.c,v 1.8 2007/01/09 00:28:10 imp Exp $");
/*
* Radixsort routines.
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
+#include <pthread.h>
typedef struct {
const u_char **sa;
static void r_sort_b(const u_char **, const u_char **, int, int,
const u_char *, u_int);
+static int *r_sort_a_count;
+static int *r_sort_b_count;
+
+static void r_sort_count_allocate(void);
+static pthread_once_t r_sort_count_control = PTHREAD_ONCE_INIT;
+
#define THRESHOLD 20 /* Divert to simplesort(). */
#define SIZE 512 /* Default stack size. */
return (0);
}
+static void r_sort_count_allocate(void)
+{
+ r_sort_a_count = calloc(256, sizeof(int));
+ r_sort_b_count = calloc(256, sizeof(int));
+}
+
#define empty(s) (s >= sp)
#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
const u_char *tr;
u_int endch;
{
- static int count[256], nc, bmin;
+ static int *count, nc, bmin;
int c;
const u_char **ak, *r;
stack s[SIZE], *sp, *sp0, *sp1, temp;
int *cp, bigc;
const u_char **an, *t, **aj, **top[256];
+ if (pthread_once(&r_sort_count_control, r_sort_count_allocate)) {
+ return;
+ }
+
+ count = r_sort_a_count;
+
/* Set up stack. */
sp = s;
push(a, n, i);
const u_char *tr;
u_int endch;
{
- static int count[256], nc, bmin;
+ static int *count, nc, bmin;
int c;
const u_char **ak, **ai;
stack s[512], *sp, *sp0, *sp1, temp;
const u_char **top[256];
int *cp, bigc;
+ if (pthread_once(&r_sort_count_control, r_sort_count_allocate)) {
+ return;
+ }
+
+ count = r_sort_b_count;
+
sp = s;
push(a, n, i);
while (!empty(s)) {
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)rand.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/rand.3,v 1.14 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/rand.3,v 1.16 2007/01/09 00:28:10 imp Exp $
.\"
.Dd May 25, 1999
.Dt RAND 3
.Fn sranddev
function initializes a seed, using the
.Xr random 4
-random number device which returns good random numbers,
-suitable for cryptographic use.
+random number device which returns good random numbers.
+However, the
+.Fn rand
+function still remains unsuitable for cryptographic use.
.Pp
The
.Fn rand_r
* 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.
static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.24 2004/01/20 03:02:18 das Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/random.c,v 1.25 2007/01/09 00:28:10 imp Exp $");
/*
* We always compile with __DARWIN_UNIX03 set to one, relying on the fact that
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)random.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/random.3,v 1.20 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/random.3,v 1.22 2007/01/09 00:28:10 imp Exp $
.\"
.Dd June 4, 1993
.Dt RANDOM 3
value.
.Pp
Like
+.Xr srand 3 ,
+.Fn srandom
+sets the initial seed value for future calls to
+.Fn random .
+Like
.Xr rand 3 ,
.Fn random
will by default produce a sequence of numbers that can be duplicated
by calling
.Fn srandom
-with
-.Ql 1
-as the seed.
+with the same seed.
.Pp
The
.Fn srandomdev
.if t 2\u\s769\s10\d,
.if n 2**69 ,
which should be sufficient for most purposes.
-.Sh AUTHORS
-.An Earl T. Cohen
.Sh DIAGNOSTICS
If
.Fn initstate
These
functions appeared in
.Bx 4.2 .
+.Sh AUTHORS
+.An Earl T. Cohen
.Sh BUGS
About 2/3 the speed of
.Xr rand 3 .
#endif /* __DARWIN_UNIX03 */
/*
* Extension to the standard; if inresolved == NULL, allocate memory
- * (first on the stack, then use strdup())
*/
if (!inresolved) {
- if ((resolved = alloca(PATH_MAX)) == NULL) return (NULL);
+ if ((resolved = malloc(PATH_MAX)) == NULL) return (NULL);
} else {
resolved = inresolved;
}
if (!rootdev_inited) {
rootdev_inited = 1;
if (stat("/", &sb) < 0) {
- return (NULL);
+error_return:
+ if (!inresolved) {
+ int e = errno;
+ free(resolved);
+ errno = e;
}
+ return (NULL);
+ }
rootdev = sb.st_dev;
}
serrno = errno;
#endif /* !VARIANT_DARWINEXTSN && __DARWIN_UNIX03 */
{
strlcpy(resolved, ".", PATH_MAX);
- return (NULL);
+ goto error_return;
}
resolved_len = strlen(resolved);
left_len = strlcpy(left, path, sizeof(left));
}
if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto error_return;
}
if (resolved_len > 1) {
if (stat(resolved, &sb) < 0) {
- return (NULL);
+ goto error_return;
}
lastdev = sb.st_dev;
} else
s = p ? p : left + left_len;
if (s - left >= sizeof(next_token)) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto error_return;
}
memcpy(next_token, left, s - left);
next_token[s - left] = '\0';
if (resolved[resolved_len - 1] != '/') {
if (resolved_len + 1 >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto error_return;
}
resolved[resolved_len++] = '/';
resolved[resolved_len] = '\0';
resolved_len = strlcat(resolved, next_token, PATH_MAX);
if (resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto error_return;
}
if (getattrlist(resolved, &_rp_alist, &attrs, sizeof(attrs), FSOPT_NOFOLLOW) == 0) {
useattrs = 1;
return (resolved);
}
#endif /* !__DARWIN_UNIX03 */
- return (NULL);
+ goto error_return;
}
if (dev != lastdev) {
/*
if (islink) {
if (symlinks++ > MAXSYMLINKS) {
errno = ELOOP;
- return (NULL);
+ goto error_return;
}
slen = readlink(resolved, symlink, sizeof(symlink) - 1);
if (slen < 0) {
- return (NULL);
+ goto error_return;
}
symlink[slen] = '\0';
if (symlink[0] == '/') {
if (symlink[slen - 1] != '/') {
if (slen + 1 >= sizeof(symlink)) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto error_return;
}
symlink[slen] = '/';
symlink[slen + 1] = 0;
left_len = strlcat(symlink, left, sizeof(left));
if (left_len >= sizeof(left)) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto error_return;
}
}
left_len = strlcpy(left, symlink, sizeof(left));
resolved_len = strlcat(resolved, (const char *)&attrs.name + attrs.name.attr_dataoffset, PATH_MAX);
if (resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto error_return;
}
}
/*
*/
if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
resolved[resolved_len - 1] = '\0';
- if (!inresolved) resolved = strdup(resolved);
return (resolved);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
-.\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.13 2003/03/27 20:48:53 fjoe Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/realpath.3,v 1.14 2007/01/09 00:28:10 imp Exp $
.\"
.Dd April 5, 2008
.Dt REALPATH 3
* 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.
static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/setenv.c,v 1.9 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/setenv.c,v 1.14 2007/05/01 16:02:41 ache Exp $");
#include <stddef.h>
#include <stdlib.h>
__private_extern__ char *__findenv(const char *, int *, char **);
__private_extern__ int __setenv(const char *, const char *, int, int, char ***, malloc_zone_t *);
__private_extern__ void __unsetenv(const char *, char **, malloc_zone_t *);
+__private_extern__ int init__zone0(int);
+
+/*
+ * _cthread_init_routine used to be called from crt1.o to initialize threads.
+ * This is no longer needed, as initialization happens in dylib initializers,
+ * but is provided to maintain backwards compatibility. Normally, for 10.5
+ * or greater, _cthread_init_routine does nothing.
+ *
+ * Before 10.5, the _start routine in crt1.o clobbers environ with the original
+ * stack value, which effectively undoes any environment changes made in
+ * initializers. When LEGACY_CRT1_ENVIRON is defined, we replace the
+ * do-nothing routine with one that attempts to restore the environ value.
+ * But this only works if the setenv (and family) routines were used
+ * exclusively, (no direct manipulation of environ). Note that according to
+ * SUSv3, direct manipulation of environ may result in undefined behavior in
+ * setenv and family, so we don't support that (on less than 10.5).
+ */
+#ifdef BUILDING_VARIANT
+# ifdef LEGACY_CRT1_ENVIRON
+extern char **_saved_environ;
+# endif /* LEGACY_CRT1_ENVIRON */
+#else /* !BUILDING_VARIANT */
+# ifdef LEGACY_CRT1_ENVIRON
+__private_extern__ char **_saved_environ = NULL;
+
+static int
+_legacy_crt1_environ(void)
+{
+ if (_saved_environ) *_NSGetEnviron() = _saved_environ;
+ return 0;
+}
+int (*_cthread_init_routine)(void) = _legacy_crt1_environ;
+
+# else /* !LEGACY_CRT1_ENVIRON */
+static int _do_nothing(void) { return 0; }
+int (*_cthread_init_routine)(void) = _do_nothing;
+# endif /* !LEGACY_CRT1_ENVIRON */
-#ifndef BUILDING_VARIANT
/*
* Create the environment malloc zone and give it a recognizable name.
*/
const char *value;
int rewrite;
{
+#ifdef LEGACY_CRT1_ENVIRON
+ int ret;
+#endif /* LEGACY_CRT1_ENVIRON */
+
/* no null ptr or empty str */
if(name == NULL || *name == 0) {
errno = EINVAL;
/* insure __zone0 is set up before calling __malloc_check_env_name */
if (init__zone0(1)) return (-1);
__malloc_check_env_name(name); /* see if we are changing a malloc environment variable */
+#ifdef LEGACY_CRT1_ENVIRON
+ ret = __setenv(name, value, rewrite, 1, _NSGetEnviron(), __zone0);
+ _saved_environ = *_NSGetEnviron();
+ return ret;
+#else /* !LEGACY_CRT1_ENVIRON */
return (__setenv(name, value, rewrite, 1, _NSGetEnviron(), __zone0));
+#endif /* !LEGACY_CRT1_ENVIRON */
}
/*
-/* $NetBSD: strfmon.c,v 1.6 2008/03/27 21:50:30 christos Exp $ */
+/* $NetBSD: strfmon.c,v 1.7 2009/01/30 23:46:03 lukem Exp $ */
/*-
* Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
#if 0
__FBSDID("$FreeBSD: src/lib/libc/stdlib/strfmon.c,v 1.14 2003/03/20 08:18:55 ache Exp $");
#else
-__RCSID("$NetBSD: strfmon.c,v 1.6 2008/03/27 21:50:30 christos Exp $");
+__RCSID("$NetBSD: strfmon.c,v 1.7 2009/01/30 23:46:03 lukem Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
* required width ?
*/
- if (d + width >= maxsize)
+ if ((size_t)(d + width) >= maxsize)
goto e2big_error;
}
.It Bq Er ENOMEM
Not enough memory for temporary buffers.
.El
+.Sh EXAMPLE
+.Bd -literal -offset indent -compact
+ #include <stdio.h>
+ #include <monetary.h>
+ #include <locale.h>
+
+ int main() {
+ char buf[200];
+ setlocale(LC_ALL, "en_US");
+ (void)strfmon (buf, sizeof(buf)-1, "%n" , 123456.78);
+ printf("%s\n", buf);
+ }
+.Ed
+.Pp
.Sh SEE ALSO
.Xr localeconv 3 ,
.Xr xlocale 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strtod.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/strtod.3,v 1.19 2003/05/22 13:02:28 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/strtod.3,v 1.22 2007/12/16 21:19:28 das Exp $
.\"
.Dd March 2, 2003
.Dt STRTOD 3
of 2.
.Pp
Alternatively, if the portion of the string following the optional
-plus or minus sign begins with ``INFINITY'' or ``NAN'', ignoring
-case, it is interpreted as an infinity or a quiet NaN, respectively.
+plus or minus sign begins with
+.Dq INFINITY
+or
+.Dq NAN ,
+ignoring case, it is interpreted as an infinity or a quiet \*(Na,
+respectively.
+The syntax
+.Dq Xo Pf NAN( Ar "s" ) Xc ,
+where
+.Ar s
+is an alphanumeric string, produces the same value as the call
+.Fo nan
+.Qq Ar s Ns
+.Fc
+(respectively,
+.Fo nanf
+.Qq Ar s Ns
+.Fc
+and
+.Fo nanl
+.Qq Ar s Ns
+.Fc . )
.Pp
In any of the above cases, leading white-space characters in the
string (as defined by the
.Xr atof 3 ,
.Xr atoi 3 ,
.Xr atol 3 ,
+.Xr nan 3 ,
.Xr strtod_l 3 ,
.Xr strtol 3 ,
.Xr strtoul 3 ,
.Fn strtod
function
conforms to
-.St -isoC-99 ,
-with the exception of the bug noted below.
-.Sh BUGS
-These routines do not recognize the C99 ``NaN(...)'' syntax.
+.St -isoC-99 .
.Sh AUTHORS
The author of this software is
.An David M. Gay .
* 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.
static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.9 2003/01/01 18:48:43 schweikh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
* 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.
static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtol.c,v 1.17 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtol.c,v 1.20 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strtol.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/strtol.3,v 1.20 2005/01/22 18:02:58 ache Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/strtol.3,v 1.23 2007/04/10 11:17:00 ru Exp $
.\"
.Dd November 28, 2001
.Dt STRTOL 3
* 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.
static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.22 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
* 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.
static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.11 2002/08/15 09:25:04 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoq.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoul.c,v 1.16 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoul.c,v 1.19 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strtoul.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/strtoul.3,v 1.20 2002/10/10 04:31:57 tjr Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/strtoul.3,v 1.23 2007/01/09 00:28:10 imp Exp $
.\"
.Dd November 28, 2001
.Dt STRTOUL 3
the global variable
.Va errno
is set to
-.Er EINVAL .
+.Er EINVAL
+(the last feature is not portable across all platforms).
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EINVAL
The value of
.Fa base
is not supported or
-no conversion could be performed.
+no conversion could be performed
+(the last feature is not portable across all platforms).
.It Bq Er ERANGE
The given string was out of range; the value converted has been clamped.
.El
.Sh SEE ALSO
.Xr strtol 3 ,
.Xr strtol_l 3 ,
+.Xr strtonum 3 ,
.Xr wcstoul 3 ,
.Xr compat 5
.Sh STANDARDS
* 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.
static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.21 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
* 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.
static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.11 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
c = *s++;
}
if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
c = s[1];
s += 2;
base = 16;
* 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.
static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.11 2002/08/15 09:25:04 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/strtouq.c,v 1.12 2007/01/09 00:28:10 imp Exp $");
#include "xlocale_private.h"
* 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.
static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/system.c,v 1.10 2002/03/22 21:53:10 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdlib/system.c,v 1.11 2007/01/09 00:28:10 imp Exp $");
#include "namespace.h"
#include <sys/types.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)system.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/system.3,v 1.11 2002/05/27 03:45:27 dd Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/system.3,v 1.13 2008/06/26 08:24:59 danger Exp $
.\"
.Dd June 4, 1993
.Dt SYSTEM 3
will return non-zero if the command interpreter
.Xr sh 1
is available, and zero if it is not.
-.Pp
+.Sh RETURN VALUES
The
.Fn system
function
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" OpenBSD: tsearch.3,v 1.2 1998/06/21 22:13:49 millert Exp
-.\" $FreeBSD: src/lib/libc/stdlib/tsearch.3,v 1.13 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdlib/tsearch.3,v 1.15 2006/06/23 13:36:33 keramida Exp $
.\"
.Dd June 15, 1997
.Dt TSEARCH 3
.Ft void
.Fo twalk
.Fa "const void *root"
-.Fa "void (*compar) (const void *node, VISIT order, int level)"
+.Fa "void (*action) (const void *node, VISIT order, int level)"
.Fc
.Sh DESCRIPTION
The
to what would typically be referred to as in-order, and the
traversal type "endorder" corresponds to what would typically
be referred to as post-order.
-.Sh SEE ALSO
-.Xr bsearch 3 ,
-.Xr hsearch 3 ,
-.Xr lsearch 3
.Sh RETURN VALUES
The
.Fn tsearch
The
.Fn twalk
function returns no value.
+.Sh SEE ALSO
+.Xr bsearch 3 ,
+.Xr hsearch 3 ,
+.Xr lsearch 3
/*
** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+** 1996-06-05 by Arthur David Olson.
+*/
+
+/*
+** Avoid the temptation to punt entirely to strftime;
+** the output of strftime is supposed to be locale specific
+** whereas the output of asctime is supposed to be constant.
*/
#include <sys/cdefs.h>
#ifndef lint
#ifndef NOID
-static char elsieid[] __unused = "@(#)asctime.c 7.9";
+static char elsieid[] __unused = "@(#)asctime.c 8.2";
#endif /* !defined NOID */
#endif /* !defined lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/asctime.c,v 1.12 2004/06/14 10:31:52 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/asctime.c,v 1.13 2009/05/23 06:31:50 edwin Exp $");
/*LINTLIBRARY*/
#include "tzfile.h"
/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12.
+** Some systems only handle "%.2d"; others only handle "%02d";
+** "%02.2d" makes (most) everybody happy.
+** At least some versions of gcc warn about the %02.2d;
+** we conditionalize below to avoid the warning.
+*/
+/*
+** All years associated with 32-bit time_t values are exactly four digits long;
+** some years associated with 64-bit time_t values are not.
+** Vintage programs are coded for years that are always four digits long
+** and may assume that the newline always lands in the same place.
+** For years that are less than four digits, we pad the output with
+** leading zeroes to get the newline in the traditional place.
+** The -4 ensures that we get four characters of output even if
+** we call a strftime variant that produces fewer characters for some years.
+** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
+** but many implementations pad anyway; most likely the standards are buggy.
+*/
+#ifdef __GNUC__
+#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
+#else /* !defined __GNUC__ */
+#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
+#endif /* !defined __GNUC__ */
+/*
+** For years that are more than four digits we put extra spaces before the year
+** so that code trying to overwrite the newline won't end up overwriting
+** a digit within a year and truncating the year (operating on the assumption
+** that no output is better than wrong output).
+*/
+#ifdef __GNUC__
+#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n"
+#else /* !defined __GNUC__ */
+#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n"
+#endif /* !defined __GNUC__ */
+
+#define STD_ASCTIME_BUF_SIZE 26
+/*
+** Big enough for something such as
+** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
+** (two three-character abbreviations, five strings denoting integers,
+** seven explicit spaces, two explicit colons, a newline,
+** and a trailing ASCII nul).
+** The values above are for systems where an int is 32 bits and are provided
+** as an example; the define below calculates the maximum for the system at
+** hand.
+*/
+#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1)
+
+static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
+
+/*
+** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
*/
char *
};
const char * wn;
const char * mn;
+ char year[INT_STRLEN_MAXIMUM(int) + 2];
+ char result[MAX_ASCTIME_BUF_SIZE];
if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
wn = "???";
mn = "???";
else mn = mon_name[timeptr->tm_mon];
/*
- ** The X3J11-suggested format is
- ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
- ** Since the .2 in 02.2d is ignored, we drop it.
+ ** Use strftime's %Y to generate the year, to avoid overflow problems
+ ** when computing timeptr->tm_year + TM_YEAR_BASE.
+ ** Assume that strftime is unaffected by other out-of-range members
+ ** (e.g., timeptr->tm_mday) when processing "%Y".
*/
- (void) sprintf(buf, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
+ (void) strftime(year, sizeof year, "%Y", timeptr);
+ /*
+ ** We avoid using snprintf since it's not available on all systems.
+ */
+ (void) sprintf(result,
+ ((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
wn, mn,
timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec,
- TM_YEAR_BASE + timeptr->tm_year);
- return buf;
+ year);
+ if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime) {
+ (void) strcpy(buf, result);
+ return buf;
+ } else {
+#ifdef EOVERFLOW
+ errno = EOVERFLOW;
+#else /* !defined EOVERFLOW */
+ errno = EINVAL;
+#endif /* !defined EOVERFLOW */
+ return NULL;
+ }
}
/*
-** A la X3J11, with core dump avoidance.
+** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
*/
char *
asctime(timeptr)
const struct tm * timeptr;
{
- /*
- ** Big enough for something such as
- ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
- ** (two three-character abbreviations, five strings denoting integers,
- ** three explicit spaces, two explicit colons, a newline,
- ** and a trailing ASCII nul).
- */
- static char result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) +
- 3 + 2 + 1 + 1];
-
- return asctime_r(timeptr, result);
+ return asctime_r(timeptr, buf_asctime);
}
---- asctime.c.orig 2008-12-15 11:41:07.000000000 -0800
-+++ asctime.c 2009-01-21 17:09:27.000000000 -0800
-@@ -22,10 +22,10 @@ __FBSDID("$FreeBSD: src/lib/libc/stdtime
- ** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12.
+--- asctime.c.bsdnew 2009-11-14 13:55:43.000000000 -0800
++++ asctime.c 2009-11-14 14:04:38.000000000 -0800
+@@ -79,9 +79,7 @@ static char buf_asctime[MAX_ASCTIME_BUF_
*/
-+#define EXPECTEDLEN 26
-+
char *
-asctime_r(timeptr, buf)
-const struct tm * timeptr;
{
static const char wday_name[][3] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-@@ -36,6 +36,8 @@ char * buf;
- };
- const char * wn;
- const char * mn;
-+ int len;
-+ char tmp[EXPECTEDLEN];
-
- if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
- wn = "???";
-@@ -48,31 +50,28 @@ char * buf;
- ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
- ** Since the .2 in 02.2d is ignored, we drop it.
- */
-- (void) sprintf(buf, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
-+ /*
-+ ** Because various values in the tm structure may cause the
-+ ** resulting string to be longer than the 26-bytes that is
-+ ** specified in the spec, we should return NULL rather than
-+ ** possibly overwrite beyond the string.
-+ */
-+ len = snprintf(tmp, EXPECTEDLEN, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
- wn, mn,
- timeptr->tm_mday, timeptr->tm_hour,
- timeptr->tm_min, timeptr->tm_sec,
- TM_YEAR_BASE + timeptr->tm_year);
-+ if (len >= EXPECTEDLEN)
-+ return NULL;
-+ strcpy(buf, tmp);
- return buf;
- }
-
--/*
--** A la X3J11, with core dump avoidance.
--*/
--
- char *
- asctime(timeptr)
- const struct tm * timeptr;
- {
-- /*
-- ** Big enough for something such as
-- ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
-- ** (two three-character abbreviations, five strings denoting integers,
-- ** three explicit spaces, two explicit colons, a newline,
-- ** and a trailing ASCII nul).
-- */
-- static char result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) +
-- 3 + 2 + 1 + 1];
-+ static char result[EXPECTEDLEN];
-
- return asctime_r(timeptr, result);
- }
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)ctime.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdtime/ctime.3,v 1.22 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdtime/ctime.3,v 1.24 2007/01/09 00:28:11 imp Exp $
.\"
.Dd January 2, 1999
.Dt CTIME 3
.Fa tzname
to a pointer to an
.Tn ASCII
-string that's the time zone abbreviation to be
+string that is the time zone abbreviation to be
used with
.Fn localtime Ns 's
return value.
---- _SB/Libc/stdtime/FreeBSD/ctime.3 2004-11-25 11:38:44.000000000 -0800
-+++ _SB/Libc/stdtime/FreeBSD/ctime.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -56,31 +56,31 @@
+--- ctime.3.bsdnew 2009-11-14 13:55:43.000000000 -0800
++++ ctime.3 2009-11-14 14:01:29.000000000 -0800
+@@ -52,31 +52,31 @@
.In time.h
.Vt extern char *tzname[2] ;
.Ft char *
and
.Fn localtime
all take as an argument a time value representing the time in seconds since
-@@ -92,10 +92,10 @@
+@@ -88,10 +88,10 @@ January 1, 1970; see
The function
.Fn localtime
converts the time value pointed at by
the broken-out time information for the value after adjusting for the current
time zone (and any other factors such as Daylight Saving Time).
Time zone adjustments are performed as specified by the
-@@ -106,7 +106,7 @@
+@@ -102,7 +102,7 @@ The function
.Fn localtime
uses
.Xr tzset 3
.Xr tzset 3
has not already been called by the process.
.Pp
-@@ -118,36 +118,36 @@
+@@ -114,36 +114,36 @@ element of
.Fa tzname
to a pointer to an
.Tn ASCII
--string that's the time zone abbreviation to be
+-string that is the time zone abbreviation to be
+string containing the time zone abbreviation to be
used with
.Fn localtime Ns 's
The
.Fn localtime_r
and
-@@ -156,17 +156,17 @@
+@@ -152,17 +152,17 @@ functions
provide the same functionality as
.Fn localtime
and
to the form
shown in the example above.
.Pp
-@@ -174,17 +174,19 @@
+@@ -170,17 +170,19 @@ The
.Fn asctime_r
function
provides the same functionality as
values returned by the
.Xr time 3
function (that is, seconds from the Epoch,
-@@ -197,17 +199,17 @@
+@@ -193,17 +195,17 @@ interprets the input structure according
.Xr tzset 3 ) .
The
.Fn timegm
For example,
October 40 is changed into November 9,
a
-@@ -223,7 +225,7 @@
+@@ -219,7 +221,7 @@ of \-2 means 2 months before January of
causes
.Fn mktime
to presume initially that summer time (for example, Daylight Saving Time)
A negative value for
.Fa tm_isdst
causes the
-@@ -265,7 +267,8 @@
+@@ -261,7 +263,8 @@ returns the difference between two calen
.Fa time0 ) ,
expressed in seconds.
.Pp
.In time.h
include file.
The tm structure includes at least the following fields:
-@@ -286,14 +289,14 @@
+@@ -282,14 +285,14 @@ long tm_gmtoff; /\(** offset from UTC in
The
field
.Fa tm_isdst
/*
** This file is in the public domain, so clarified as of
-** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
+** 1996-06-05 by Arthur David Olson.
*/
#include <sys/cdefs.h>
#ifndef lint
#ifndef NOID
-static char elsieid[] __unused = "@(#)difftime.c 7.9";
+static char elsieid[] __unused = "@(#)difftime.c 8.1";
#endif /* !defined NOID */
#endif /* !defined lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/difftime.c,v 1.8 2004/06/14 10:31:52 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/difftime.c,v 1.9 2009/05/23 06:31:50 edwin Exp $");
/*LINTLIBRARY*/
#include "namespace.h"
-#include "private.h"
+#include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */
#include "un-namespace.h"
-/*
-** Algorithm courtesy Paul Eggert (eggert@twinsun.com).
-*/
-
-#ifdef HAVE_LONG_DOUBLE
-#define long_double long double
-#endif /* defined HAVE_LONG_DOUBLE */
-#ifndef HAVE_LONG_DOUBLE
-#define long_double double
-#endif /* !defined HAVE_LONG_DOUBLE */
-
double
difftime(time1, time0)
const time_t time1;
const time_t time0;
{
- time_t delta;
- time_t hibit;
-
- {
- time_t tt;
- double d;
- long_double ld;
-
- if (sizeof tt < sizeof d)
- return (double) time1 - (double) time0;
- if (sizeof tt < sizeof ld)
- return (long_double) time1 - (long_double) time0;
+ /*
+ ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
+ ** (assuming that the larger type has more precision).
+ ** This is the common real-world case circa 2004.
+ */
+ if (sizeof (double) > sizeof (time_t))
+ return (double) time1 - (double) time0;
+ if (!TYPE_INTEGRAL(time_t)) {
+ /*
+ ** time_t is floating.
+ */
+ return time1 - time0;
+ }
+ if (!TYPE_SIGNED(time_t)) {
+ /*
+ ** time_t is integral and unsigned.
+ ** The difference of two unsigned values can't overflow
+ ** if the minuend is greater than or equal to the subtrahend.
+ */
+ if (time1 >= time0)
+ return time1 - time0;
+ else return -((double) (time0 - time1));
}
- if (time1 < time0)
- return -difftime(time0, time1);
/*
- ** As much as possible, avoid loss of precision
- ** by computing the difference before converting to double.
+ ** time_t is integral and signed.
+ ** Handle cases where both time1 and time0 have the same sign
+ ** (meaning that their difference cannot overflow).
*/
- delta = time1 - time0;
- if (delta >= 0)
- return delta;
+ if ((time1 < 0) == (time0 < 0))
+ return time1 - time0;
/*
- ** Repair delta overflow.
+ ** time1 and time0 have opposite signs.
+ ** Punt if unsigned long is too narrow.
*/
- hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1);
+ if (sizeof (unsigned long) < sizeof (time_t))
+ return (double) time1 - (double) time0;
/*
- ** The following expression rounds twice, which means
- ** the result may not be the closest to the true answer.
- ** For example, suppose time_t is 64-bit signed int,
- ** long_double is IEEE 754 double with default rounding,
- ** time1 = 9223372036854775807 and time0 = -1536.
- ** Then the true difference is 9223372036854777343,
- ** which rounds to 9223372036854777856
- ** with a total error of 513.
- ** But delta overflows to -9223372036854774273,
- ** which rounds to -9223372036854774784, and correcting
- ** this by subtracting 2 * (long_double) hibit
- ** (i.e. by adding 2**64 = 18446744073709551616)
- ** yields 9223372036854776832, which
- ** rounds to 9223372036854775808
- ** with a total error of 1535 instead.
- ** This problem occurs only with very large differences.
- ** It's too painful to fix this portably.
- ** We are not alone in this problem;
- ** some C compilers round twice when converting
- ** large unsigned types to small floating types,
- ** so if time_t is unsigned the "return delta" above
- ** has the same double-rounding problem with those compilers.
+ ** Stay calm...decent optimizers will eliminate the complexity below.
*/
- return delta - 2 * (long_double) hibit;
+ if (time1 >= 0 /* && time0 < 0 */)
+ return (unsigned long) time1 +
+ (unsigned long) (-(time0 + 1)) + 1;
+ return -(double) ((unsigned long) time0 +
+ (unsigned long) (-(time1 + 1)) + 1);
}
static char elsieid[] __unused = "@(#)localtime.c 7.78";
#endif /* !defined NOID */
#endif /* !defined lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.40 2004/08/24 00:15:37 peter Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.43 2008/04/01 06:56:11 davidxu Exp $");
/*
** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
+#define _RWLOCK_RDLOCK(x) \
+ do { \
+ if (__isthreaded) _pthread_rwlock_rdlock(x); \
+ } while (0)
+
+#define _RWLOCK_WRLOCK(x) \
+ do { \
+ if (__isthreaded) _pthread_rwlock_wrlock(x); \
+ } while (0)
+
+#define _RWLOCK_UNLOCK(x) \
+ do { \
+ if (__isthreaded) _pthread_rwlock_unlock(x); \
+ } while (0)
+
/*
** SunOS 4.1.1 headers lack O_BINARY.
*/
static char lcl_TZname[TZ_STRLEN_MAX + 1];
static int lcl_is_set;
static int gmt_is_set;
-static pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
char * tzname[2] = {
}
static void
-tzsetwall_basic(void)
+tzsetwall_basic(int rdlocked)
{
- if (lcl_is_set < 0)
+ if (!rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ if (lcl_is_set < 0) {
+ if (!rdlocked)
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return;
+ }
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ _RWLOCK_WRLOCK(&lcl_rwlock);
lcl_is_set = -1;
#ifdef ALL_STATE
lclptr = (struct state *) malloc(sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
return;
}
}
if (tzload((char *) NULL, lclptr) != 0)
gmtload(lclptr);
settzname();
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
}
void
tzsetwall(void)
{
- _MUTEX_LOCK(&lcl_mutex);
- tzsetwall_basic();
- _MUTEX_UNLOCK(&lcl_mutex);
+ tzsetwall_basic(0);
}
static void
-tzset_basic(void)
+tzset_basic(int rdlocked)
{
const char * name;
name = getenv("TZ");
if (name == NULL) {
- tzsetwall_basic();
+ tzsetwall_basic(rdlocked);
return;
}
- if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
+ if (!rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
+ if (!rdlocked)
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return;
+ }
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ _RWLOCK_WRLOCK(&lcl_rwlock);
lcl_is_set = strlen(name) < sizeof lcl_TZname;
if (lcl_is_set)
(void) strcpy(lcl_TZname, name);
lclptr = (struct state *) malloc(sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
return;
}
}
if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
(void) gmtload(lclptr);
settzname();
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
}
void
tzset(void)
{
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
- _MUTEX_UNLOCK(&lcl_mutex);
+ tzset_basic(0);
}
/*
struct tm *p_tm;
if (__isthreaded != 0) {
- _pthread_mutex_lock(&localtime_mutex);
if (localtime_key < 0) {
- if (_pthread_key_create(&localtime_key, free) < 0) {
- _pthread_mutex_unlock(&localtime_mutex);
- return(NULL);
+ _pthread_mutex_lock(&localtime_mutex);
+ if (localtime_key < 0) {
+ if (_pthread_key_create(&localtime_key, free) < 0) {
+ _pthread_mutex_unlock(&localtime_mutex);
+ return(NULL);
+ }
}
+ _pthread_mutex_unlock(&localtime_mutex);
}
- _pthread_mutex_unlock(&localtime_mutex);
p_tm = _pthread_getspecific(localtime_key);
if (p_tm == NULL) {
if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
return(NULL);
_pthread_setspecific(localtime_key, p_tm);
}
- _pthread_mutex_lock(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
localsub(timep, 0L, p_tm);
- _pthread_mutex_unlock(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return(p_tm);
} else {
- tzset_basic();
+ tzset_basic(0);
localsub(timep, 0L, &tm);
return(&tm);
}
const time_t * const timep;
struct tm * tm;
{
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
localsub(timep, 0L, tm);
- _MUTEX_UNLOCK(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return tm;
}
const long offset;
struct tm * const tmp;
{
- _MUTEX_LOCK(&gmt_mutex);
if (!gmt_is_set) {
- gmt_is_set = TRUE;
+ _MUTEX_LOCK(&gmt_mutex);
+ if (!gmt_is_set) {
#ifdef ALL_STATE
- gmtptr = (struct state *) malloc(sizeof *gmtptr);
- if (gmtptr != NULL)
+ gmtptr = (struct state *) malloc(sizeof *gmtptr);
+ if (gmtptr != NULL)
#endif /* defined ALL_STATE */
- gmtload(gmtptr);
+ gmtload(gmtptr);
+ gmt_is_set = TRUE;
+ }
+ _MUTEX_UNLOCK(&gmt_mutex);
}
- _MUTEX_UNLOCK(&gmt_mutex);
timesub(timep, offset, gmtptr, tmp);
#ifdef TM_ZONE
/*
struct tm *p_tm;
if (__isthreaded != 0) {
- _pthread_mutex_lock(&gmtime_mutex);
if (gmtime_key < 0) {
- if (_pthread_key_create(&gmtime_key, free) < 0) {
- _pthread_mutex_unlock(&gmtime_mutex);
- return(NULL);
+ _pthread_mutex_lock(&gmtime_mutex);
+ if (gmtime_key < 0) {
+ if (_pthread_key_create(&gmtime_key, free) < 0) {
+ _pthread_mutex_unlock(&gmtime_mutex);
+ return(NULL);
+ }
}
+ _pthread_mutex_unlock(&gmtime_mutex);
}
- _pthread_mutex_unlock(&gmtime_mutex);
/*
* Changed to follow POSIX.1 threads standard, which
* is what BSD currently has.
** If we have more than this, we will overflow tm_year for tmcomp().
** We should really return an error if we cannot represent it.
*/
- if (bits > 56)
- bits = 56;
+ if (bits > 48)
+ bits = 48;
/*
** If time_t is signed, then 0 is just above the median,
** assuming two's complement arithmetic.
struct tm * const tmp;
{
time_t mktime_return_value;
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
mktime_return_value = time1(tmp, localsub, 0L);
- _MUTEX_UNLOCK(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return(mktime_return_value);
}
---- localtime.c.orig 2008-12-15 11:41:07.000000000 -0800
-+++ localtime.c 2009-01-21 15:43:59.000000000 -0800
+--- localtime.c.orig 2011-05-02 23:14:13.000000000 -0700
++++ localtime.c 2011-05-03 17:12:02.000000000 -0700
@@ -22,8 +22,22 @@ __FBSDID("$FreeBSD: src/lib/libc/stdtime
#include "namespace.h"
#include <sys/types.h>
#include "private.h"
#include "un-namespace.h"
-@@ -135,40 +149,96 @@ struct rule {
+@@ -150,40 +164,94 @@ struct rule {
#define DAY_OF_YEAR 1 /* n - day of year */
#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
+ long offset,
+ int unix03);
+__private_extern__
-+void tzset_basic(void);
++void tzset_basic(int);
-+#define lcl_mutex _st_lcl_mutex
-+
+#if !BUILDING_VARIANT
static long detzcode(const char * codep);
-static const char * getzname(const char * strp);
static int tmcomp(const struct tm * atmp,
const struct tm * btmp);
static time_t transtime(time_t janfirst, int year,
-@@ -194,10 +264,15 @@ static struct state gmtmem;
+@@ -209,9 +277,14 @@ static struct state gmtmem;
#endif /* !defined TZ_STRLEN_MAX */
static char lcl_TZname[TZ_STRLEN_MAX + 1];
+#ifdef NOTIFY_TZ
-+#define lcl_is_set (lcl_notify.is_set)
-+#define gmt_is_set (gmt_notify.is_set)
++#define lcl_is_set (lcl_notify.is_set)
++#define gmt_is_set (gmt_notify.is_set)
+#else /* ! NOTIFY_TZ */
static int lcl_is_set;
static int gmt_is_set;
--static pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER;
--static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
+-static pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+#endif /* NOTIFY_TZ */
-+__private_extern__ pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER;
-+static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
++__private_extern__ pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+ static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
char * tzname[2] = {
- wildabbr,
-@@ -214,15 +289,62 @@ char * tzname[2] = {
+@@ -229,15 +302,62 @@ char * tzname[2] = {
static struct tm tm;
static long
detzcode(codep)
const char * const codep;
-@@ -246,14 +368,14 @@ settzname(void)
+@@ -255,51 +375,203 @@ static void
+ settzname(void)
+ {
+ struct state * sp = lclptr;
+- int i;
++ int i, need;
++ unsigned char * types;
++#define NEED_STD 1
++#define NEED_DST 2
++#define NEED_DAYLIGHT 4
++#define NEED_ALL (NEED_STD | NEED_DST | NEED_DAYLIGHT)
+
+ tzname[0] = wildabbr;
tzname[1] = wildabbr;
#ifdef USG_COMPAT
daylight = 0;
return;
}
#endif /* defined ALL_STATE */
-@@ -266,7 +388,7 @@ settzname(void)
- if (ttisp->tt_isdst)
+- for (i = 0; i < sp->typecnt; ++i) {
+- const struct ttinfo * const ttisp = &sp->ttis[i];
++ /*
++ * PR-3765457: The original settzname went sequentially through the ttis
++ * array, rather than correctly indexing via the types array, to get
++ * the real order of the timezone changes. In addition, as a speed up,
++ * we start at the end of the changes, and work back, so that most of
++ * the time, we don't have to look through the entire array.
++ */
++ if (sp->timecnt == 0 && sp->typecnt == 1) {
++ /*
++ * Unfortunately, there is an edge case when typecnt == 1 and
++ * timecnt == 0, which would cause the loop to never run. So
++ * in that case, we fudge things up so that it is as if
++ * timecnt == 1.
++ */
++ i = 0;
++ types = (unsigned char *)""; /* we use the null as index */
++ } else {
++ /* the usual case */
++ i = sp->timecnt - 1;
++ types = sp->types;
++ }
++ need = NEED_ALL;
++ for (; i >= 0 && need; --i) {
++ const struct ttinfo * const ttisp = &sp->ttis[types[i]];
+
+- tzname[ttisp->tt_isdst] =
+- &sp->chars[ttisp->tt_abbrind];
+ #ifdef USG_COMPAT
+- if (ttisp->tt_isdst)
++ if ((need & NEED_DAYLIGHT) && ttisp->tt_isdst) {
++ need &= ~NEED_DAYLIGHT;
daylight = 1;
- if (i == 0 || !ttisp->tt_isdst)
+- if (i == 0 || !ttisp->tt_isdst)
- timezone = -(ttisp->tt_gmtoff);
-+ _st_set_timezone(-(ttisp->tt_gmtoff));
++ }
#endif /* defined USG_COMPAT */
++ if (ttisp->tt_isdst) {
++ if (need & NEED_DST) {
++ need &= ~NEED_DST;
++ tzname[1] = &sp->chars[ttisp->tt_abbrind];
#ifdef ALTZONE
- if (i == 0 || ttisp->tt_isdst)
-@@ -286,6 +408,119 @@ settzname(void)
+- if (i == 0 || ttisp->tt_isdst)
+- altzone = -(ttisp->tt_gmtoff);
++ altzone = -(ttisp->tt_gmtoff);
+ #endif /* defined ALTZONE */
++ }
++ } else if (need & NEED_STD) {
++ need &= ~NEED_STD;
++ tzname[0] = &sp->chars[ttisp->tt_abbrind];
++#ifdef USG_COMPAT
++ _st_set_timezone(-(ttisp->tt_gmtoff));
++#endif /* defined USG_COMPAT */
++ }
++#if defined(ALTZONE) || defined(USG_COMPAT)
++ if (i == 0) {
++#endif /* defined(ALTZONE) || defined(USG_COMPAT) */
++#ifdef ALTZONE
++ if (need & NEED_DST)
++ altzone = -(ttisp->tt_gmtoff);
++#endif /* defined ALTZONE */
++#ifdef USG_COMPAT
++ if (need & NEED_STD)
++ _st_set_timezone(-(ttisp->tt_gmtoff));
++#endif /* defined USG_COMPAT */
++#if defined(ALTZONE) || defined(USG_COMPAT)
++ }
++#endif /* defined(ALTZONE) || defined(USG_COMPAT) */
}
- }
-
+- /*
+- ** And to get the latest zone names into tzname. . .
+- */
+- for (i = 0; i < sp->timecnt; ++i) {
+- const struct ttinfo * const ttisp =
+- &sp->ttis[
+- sp->types[i]];
++}
++
+#ifdef NOTIFY_TZ
+static void
+notify_check_tz(notify_tz_t *p)
+ char *name;
+ unsigned int nstat;
+ int ncheck;
-+
+
+- tzname[ttisp->tt_isdst] =
+- &sp->chars[ttisp->tt_abbrind];
+ if (__notify_78945668_info__ < 0)
+ return;
+ /*----------------------------------------------------------------
+#endif /* NOTIFY_TZ_LOG */
+ return;
+ }
-+ }
+ }
+ notify_check(p->token, &ncheck); /* this always returns true */
-+}
+ }
+#endif /* NOTIFY_TZ */
-+
+
static int
tzload(name, sp)
- const char * name;
-@@ -295,6 +530,9 @@ struct state * const sp;
+@@ -310,6 +582,9 @@ struct state * const sp;
int i;
int fid;
/* XXX The following is from OpenBSD, and I'm not sure it is correct */
if (name != NULL && issetugid() != 0)
if ((name[0] == ':' && name[1] == '/') ||
-@@ -312,7 +550,15 @@ struct state * const sp;
+@@ -327,7 +602,15 @@ struct state * const sp;
** to hold the longest file name string that the implementation
** guarantees can be opened."
*/
if (name[0] == ':')
++name;
-@@ -320,7 +566,11 @@ struct state * const sp;
+@@ -335,7 +618,11 @@ struct state * const sp;
if (!doaccess) {
if ((p = TZDIR) == NULL)
return -1;
return -1;
(void) strcpy(fullname, p);
(void) strcat(fullname, "/");
-@@ -332,6 +582,10 @@ struct state * const sp;
+@@ -347,6 +634,10 @@ struct state * const sp;
doaccess = TRUE;
name = fullname;
}
if (doaccess && access(name, R_OK) != 0)
return -1;
if ((fid = _open(name, OPEN_MODE)) == -1)
-@@ -350,6 +604,9 @@ struct state * const sp;
+@@ -365,6 +656,9 @@ struct state * const sp;
int ttisstdcnt;
int ttisgmtcnt;
i = _read(fid, u.buf, sizeof u.buf);
if (_close(fid) != 0)
return -1;
-@@ -456,14 +713,24 @@ static const int year_lengths[2] = {
+@@ -471,14 +765,24 @@ static const int year_lengths[2] = {
*/
static const char *
return strp;
}
-@@ -743,16 +1010,15 @@ const int lastditch;
+@@ -758,16 +1062,15 @@ const int lastditch;
int load_result;
INITIALIZE(dstname);
if (stdlen < 3)
return -1;
if (*name == '\0')
-@@ -764,12 +1030,14 @@ const int lastditch;
+@@ -779,12 +1082,14 @@ const int lastditch;
}
}
load_result = tzload(TZDEFRULES, sp);
if (dstlen < 3)
return -1;
if (*name != '\0' && *name != ',' && *name != ';') {
-@@ -951,8 +1219,19 @@ struct state * const sp;
+@@ -966,13 +1271,37 @@ struct state * const sp;
static void
- tzsetwall_basic(void)
+ tzsetwall_basic(int rdlocked)
{
+#ifdef NOTIFY_TZ
+ notify_check_tz(&lcl_notify);
++#else
++ if (TZDEFAULT) {
++ static struct timespec last_mtimespec = {0, 0};
++ struct stat statbuf;
++
++ if (lstat(TZDEFAULT, &statbuf) == 0) {
++ if (statbuf.st_mtimespec.tv_sec > last_mtimespec.tv_sec ||
++ (statbuf.st_mtimespec.tv_sec == last_mtimespec.tv_sec &&
++ statbuf.st_mtimespec.tv_nsec > last_mtimespec.tv_nsec)) {
++ /* Trigger resetting the local TZ */
++ lcl_is_set = 0;
++ }
++ last_mtimespec = statbuf.st_mtimespec;
++ }
++ }
+#endif /* NOTIFY_TZ */
+ if (!rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ if (lcl_is_set < 0) {
+#ifdef NOTIFY_TZ_DEBUG
-+ if (lcl_is_set < 0) {
+ NOTIFY_TZ_PRINTF("tzsetwall_basic lcl_is_set < 0\n");
-+ return;
-+ }
-+ NOTIFY_TZ_PRINTF("tzsetwall_basic not set\n");
-+#else /* ! NOTIFY_TZ_DEBUG */
- if (lcl_is_set < 0)
++#endif
+ if (!rdlocked)
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return;
-+#endif /* NOTIFY_TZ_DEBUG */
- lcl_is_set = -1;
+ }
++#ifdef NOTIFY_TZ_DEBUG
++ NOTIFY_TZ_PRINTF("tzsetwall_basic not set\n");
++#endif
+ _RWLOCK_UNLOCK(&lcl_rwlock);
- #ifdef ALL_STATE
-@@ -966,18 +1245,24 @@ tzsetwall_basic(void)
+ _RWLOCK_WRLOCK(&lcl_rwlock);
+@@ -992,6 +1321,9 @@ tzsetwall_basic(int rdlocked)
#endif /* defined ALL_STATE */
if (tzload((char *) NULL, lclptr) != 0)
gmtload(lclptr);
+ notify_register_tz(fullname, &lcl_notify);
+#endif /* NOTIFY_TZ */
settzname();
- }
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+@@ -1002,10 +1334,13 @@ tzsetwall_basic(int rdlocked)
void
tzsetwall(void)
{
+#ifdef NOTIFY_TZ_DEBUG
+ NOTIFY_TZ_PRINTF("tzsetwall called\n");
+#endif /* NOTIFY_TZ_DEBUG */
- _MUTEX_LOCK(&lcl_mutex);
- tzsetwall_basic();
- _MUTEX_UNLOCK(&lcl_mutex);
+ tzsetwall_basic(0);
}
-static void
+__private_extern__ void
- tzset_basic(void)
+ tzset_basic(int rdlocked)
{
const char * name;
-@@ -988,8 +1273,18 @@ tzset_basic(void)
+@@ -1016,11 +1351,17 @@ tzset_basic(int rdlocked)
return;
}
+#ifdef NOTIFY_TZ
+ notify_check_tz(&lcl_notify);
+#endif /* NOTIFY_TZ */
+ if (!rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
+ if (!rdlocked)
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+#ifdef NOTIFY_TZ_DEBUG
-+ if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
+ NOTIFY_TZ_PRINTF("tzset_basic matched %s\n", lcl_TZname);
-+ return;
-+ }
-+#else /* ! NOTIFY_TZ_DEBUG */
- if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
++#endif
return;
-+#endif /* NOTIFY_TZ_DEBUG */
- lcl_is_set = strlen(name) < sizeof lcl_TZname;
- if (lcl_is_set)
- (void) strcpy(lcl_TZname, name);
-@@ -1014,15 +1309,25 @@ tzset_basic(void)
+ }
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+@@ -1053,9 +1394,16 @@ tzset_basic(int rdlocked)
lclptr->ttis[0].tt_gmtoff = 0;
lclptr->ttis[0].tt_abbrind = 0;
(void) strcpy(lclptr->chars, gmt);
+ notify_register_tz(fullname, &lcl_notify);
+#endif /* NOTIFY_TZ */
settzname();
- }
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+@@ -1066,6 +1414,9 @@ tzset_basic(int rdlocked)
void
tzset(void)
{
+#ifdef NOTIFY_TZ_DEBUG
+ NOTIFY_TZ_PRINTF("tzset called TZ=%s\n", getenv("TZ"));
+#endif /* NOTIFY_TZ_DEBUG */
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
- _MUTEX_UNLOCK(&lcl_mutex);
-@@ -1038,7 +1343,11 @@ tzset(void)
+ tzset_basic(0);
+ }
+
+@@ -1079,7 +1430,11 @@ tzset(void)
*/
/*ARGSUSED*/
localsub(timep, offset, tmp)
const time_t * const timep;
const long offset;
-@@ -1049,11 +1358,18 @@ struct tm * const tmp;
+@@ -1090,11 +1445,18 @@ struct tm * const tmp;
int i;
const time_t t = *timep;
}
#endif /* defined ALL_STATE */
if (sp->timecnt == 0 || t < sp->ats[0]) {
-@@ -1076,12 +1392,20 @@ struct tm * const tmp;
+@@ -1117,12 +1479,20 @@ struct tm * const tmp;
** t += ttisp->tt_gmtoff;
** timesub(&t, 0L, sp, tmp);
*/
}
struct tm *
-@@ -1094,8 +1418,9 @@ const time_t * const timep;
+@@ -1134,10 +1504,11 @@ const time_t * const timep;
+ struct tm *p_tm;
if (__isthreaded != 0) {
- _pthread_mutex_lock(&localtime_mutex);
- if (localtime_key < 0) {
-- if (_pthread_key_create(&localtime_key, free) < 0) {
+ if (localtime_key == (pthread_key_t)-1) {
-+ localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
-+ if (pthread_key_init_np(localtime_key, free) < 0) {
- _pthread_mutex_unlock(&localtime_mutex);
- return(NULL);
- }
-@@ -1110,13 +1435,21 @@ const time_t * const timep;
+ _pthread_mutex_lock(&localtime_mutex);
+- if (localtime_key < 0) {
+- if (_pthread_key_create(&localtime_key, free) < 0) {
++ if (localtime_key == (pthread_key_t)-1) {
++ localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
++ if (pthread_key_init_np(localtime_key, free) < 0) {
+ _pthread_mutex_unlock(&localtime_mutex);
+ return(NULL);
+ }
+@@ -1153,13 +1524,21 @@ const time_t * const timep;
}
- _pthread_mutex_lock(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
+#ifdef __LP64__
+ p_tm = localsub(timep, 0L, p_tm);
+#else /* !__LP64__ */
localsub(timep, 0L, p_tm);
+#endif /* __LP64__ */
- _pthread_mutex_unlock(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return(p_tm);
} else {
- tzset_basic();
+ tzset_basic(0);
+#ifdef __LP64__
+ return localsub(timep, 0L, &tm);
+#else /* !__LP64__ */
}
}
-@@ -1125,13 +1458,15 @@ const time_t * const timep;
+@@ -1168,13 +1547,15 @@ const time_t * const timep;
*/
struct tm *
-struct tm * tm;
+localtime_r(const time_t * const __restrict timep, struct tm * __restrict tm)
{
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
+#ifdef __LP64__
+ tm = localsub(timep, 0L, tm);
+#else /* !__LP64__ */
localsub(timep, 0L, tm);
+#endif /* __LP64__ */
- _MUTEX_UNLOCK(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return tm;
}
-@@ -1140,23 +1475,48 @@ struct tm * tm;
+@@ -1183,25 +1564,52 @@ struct tm * tm;
** gmtsub is to gmtime as localsub is to localtime.
*/
+#ifdef NOTIFY_TZ_DEBUG
+ NOTIFY_TZ_PRINTF("gmtsub called\n");
+#endif /* NOTIFY_TZ_DEBUG */
- _MUTEX_LOCK(&gmt_mutex);
+#ifdef NOTIFY_TZ
+ notify_check_tz(&gmt_notify);
+#endif /* NOTIFY_TZ */
if (!gmt_is_set) {
- gmt_is_set = TRUE;
+ _MUTEX_LOCK(&gmt_mutex);
+ if (!gmt_is_set) {
#ifdef ALL_STATE
-- gmtptr = (struct state *) malloc(sizeof *gmtptr);
+- gmtptr = (struct state *) malloc(sizeof *gmtptr);
+#ifdef NOTIFY_TZ
-+ if (gmtptr == NULL)
++ if (gmtptr == NULL)
+#endif /* NOTIFY_TZ */
-+ gmtptr = (struct state *) malloc(sizeof *gmtptr);
- if (gmtptr != NULL)
++ gmtptr = (struct state *) malloc(sizeof *gmtptr);
+ if (gmtptr != NULL)
+#ifdef NOTIFY_TZ
-+ {
++ {
+#endif /* NOTIFY_TZ */
#endif /* defined ALL_STATE */
- gmtload(gmtptr);
+ gmtload(gmtptr);
+#ifdef NOTIFY_TZ
-+ notify_register_tz(fullname, &gmt_notify);
-+ }
++ notify_register_tz(fullname, &gmt_notify);
++#ifdef ALL_STATE
++ }
++#endif
+#endif /* NOTIFY_TZ */
+ gmt_is_set = TRUE;
+ }
+ _MUTEX_UNLOCK(&gmt_mutex);
}
- _MUTEX_UNLOCK(&gmt_mutex);
+#ifdef __LP64__
+ if(timesub(timep, offset, gmtptr, tmp) == NULL)
+ return NULL;
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
-@@ -1168,7 +1528,7 @@ struct tm * const tmp;
+@@ -1213,7 +1621,7 @@ struct tm * const tmp;
else {
#ifdef ALL_STATE
if (gmtptr == NULL)
else tmp->TM_ZONE = gmtptr->chars;
#endif /* defined ALL_STATE */
#ifndef ALL_STATE
-@@ -1176,6 +1536,9 @@ struct tm * const tmp;
+@@ -1221,6 +1629,9 @@ struct tm * const tmp;
#endif /* State Farm */
}
#endif /* defined TM_ZONE */
}
struct tm *
-@@ -1186,10 +1549,12 @@ const time_t * const timep;
- static pthread_key_t gmtime_key = -1;
+@@ -1232,10 +1643,11 @@ const time_t * const timep;
struct tm *p_tm;
-+
if (__isthreaded != 0) {
- _pthread_mutex_lock(&gmtime_mutex);
- if (gmtime_key < 0) {
-- if (_pthread_key_create(&gmtime_key, free) < 0) {
+ if (gmtime_key == (pthread_key_t)-1) {
-+ gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
-+ if (pthread_key_init_np(gmtime_key, free) < 0) {
- _pthread_mutex_unlock(&gmtime_mutex);
- return(NULL);
- }
-@@ -1206,12 +1571,20 @@ const time_t * const timep;
+ _pthread_mutex_lock(&gmtime_mutex);
+- if (gmtime_key < 0) {
+- if (_pthread_key_create(&gmtime_key, free) < 0) {
++ if (gmtime_key == (pthread_key_t)-1) {
++ gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
++ if (pthread_key_init_np(gmtime_key, free) < 0) {
+ _pthread_mutex_unlock(&gmtime_mutex);
+ return(NULL);
+ }
+@@ -1253,12 +1665,20 @@ const time_t * const timep;
}
_pthread_setspecific(gmtime_key, p_tm);
}
}
}
-@@ -1224,8 +1597,13 @@ gmtime_r(timep, tm)
+@@ -1271,8 +1691,13 @@ gmtime_r(timep, tm)
const time_t * const timep;
struct tm * tm;
{
}
#ifdef STD_INSPIRED
-@@ -1235,13 +1613,21 @@ offtime(timep, offset)
+@@ -1282,13 +1707,21 @@ offtime(timep, offset)
const time_t * const timep;
const long offset;
{
timesub(timep, offset, sp, tmp)
const time_t * const timep;
const long offset;
-@@ -1330,7 +1716,16 @@ struct tm * const tmp;
+@@ -1365,7 +1798,12 @@ struct tm * const tmp;
+ if (tmp->tm_wday < 0)
+ tmp->tm_wday += DAYSPERWEEK;
+ y = EPOCH_YEAR;
+-#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
++#define _LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
++#ifdef __LP64__
++#define LEAPS_THRU_END_OF(y) ((y) >= 0 ? _LEAPS_THRU_END_OF(y) : _LEAPS_THRU_END_OF((y) + 1) - 1)
++#else /* !__LP64__ */
++#define LEAPS_THRU_END_OF(y) _LEAPS_THRU_END_OF(y)
++#endif /* __LP64__ */
+ while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
+ long newy;
+
+@@ -1377,7 +1815,16 @@ struct tm * const tmp;
LEAPS_THRU_END_OF(y - 1);
y = newy;
}
tmp->tm_yday = (int) days;
ip = mon_lengths[yleap];
for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
-@@ -1340,6 +1735,9 @@ struct tm * const tmp;
+@@ -1387,6 +1834,9 @@ struct tm * const tmp;
#ifdef TM_GMTOFF
tmp->TM_GMTOFF = offset;
#endif /* defined TM_GMTOFF */
}
char *
-@@ -1352,7 +1750,20 @@ const time_t * const timep;
+@@ -1399,7 +1849,20 @@ const time_t * const timep;
** to local time in the form of a string. It is equivalent to
** asctime(localtime(timer))
*/
}
char *
-@@ -1362,7 +1773,18 @@ char * buf;
+@@ -1409,7 +1872,18 @@ char * buf;
{
struct tm tm;
}
/*
-@@ -1427,12 +1849,17 @@ const struct tm * const btmp;
+@@ -1464,8 +1938,14 @@ const struct tm * const btmp;
+ {
+ int result;
+
+- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
++ /*
++ * Assume that atmp and btmp point to normalized tm strutures.
++ * So only arithmetic with tm_year could overflow in 64-bit.
++ */
++ if (atmp->tm_year != btmp->tm_year) {
++ return (atmp->tm_year > btmp->tm_year ? 1 : -1);
++ }
++ if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+ (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
+ (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+ (result = (atmp->tm_min - btmp->tm_min)) == 0)
+@@ -1474,12 +1954,17 @@ const struct tm * const btmp;
}
static time_t
{
const struct state * sp;
int dir;
-@@ -1442,6 +1869,9 @@ const int do_norm_secs;
+@@ -1489,6 +1974,9 @@ const int do_norm_secs;
time_t newt;
time_t t;
struct tm yourtm, mytm;
*okayp = FALSE;
yourtm = *tmp;
-@@ -1460,33 +1890,64 @@ const int do_norm_secs;
+@@ -1507,33 +1995,64 @@ const int do_norm_secs;
** Turn yourtm.tm_year into an actual year number for now.
** It is converted back to an offset from TM_YEAR_BASE later.
*/
/* Don't go below 1900 for POLA */
if (yourtm.tm_year < 0)
return WRONG;
-@@ -1513,7 +1974,13 @@ const int do_norm_secs;
+@@ -1560,13 +2079,21 @@ const int do_norm_secs;
** Divide the search space in half
** (this works whether time_t is signed or unsigned).
*/
bits = TYPE_BIT(time_t) - 1;
+#endif /* __LP64__ */
/*
- ** If we have more than this, we will overflow tm_year for tmcomp().
- ** We should really return an error if we cannot represent it.
-@@ -1527,8 +1994,19 @@ const int do_norm_secs;
+- ** If we have more than this, we will overflow tm_year for tmcomp().
+- ** We should really return an error if we cannot represent it.
++ ** In 64-bit, we now return an error if we cannot represent the
++ ** struct tm value in a time_t. And tmcomp() is fixed to avoid
++ ** overflow in tm_year. So we only put a cap on bits because time_t
++ ** can't be larger that 56 bit (when tm_year == INT_MAX).
+ */
+- if (bits > 48)
+- bits = 48;
++ if (bits > 56)
++ bits = 56;
+ /*
+ ** If time_t is signed, then 0 is just above the median,
+ ** assuming two's complement arithmetic.
+@@ -1574,8 +2101,19 @@ const int do_norm_secs;
*/
t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
for ( ; ; ) {
if (dir != 0) {
if (bits-- < 0)
return WRONG;
-@@ -1539,6 +2017,9 @@ const int do_norm_secs;
+@@ -1586,6 +2124,9 @@ const int do_norm_secs;
else t += ((time_t) 1) << bits;
continue;
}
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
break;
/*
-@@ -1547,7 +2028,6 @@ const int do_norm_secs;
+@@ -1594,7 +2135,6 @@ const int do_norm_secs;
** It's okay to guess wrong since the guess
** gets checked.
*/
#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
-@@ -1560,7 +2040,12 @@ const int do_norm_secs;
+@@ -1607,7 +2147,12 @@ const int do_norm_secs;
continue;
newt = t + sp->ttis[j].tt_gmtoff -
sp->ttis[i].tt_gmtoff;
if (tmcomp(&mytm, &yourtm) != 0)
continue;
if (mytm.tm_isdst != yourtm.tm_isdst)
-@@ -1579,17 +2064,27 @@ label:
+@@ -1626,17 +2171,27 @@ label:
if ((newt < t) != (saved_seconds < 0))
return WRONG;
t = newt;
{
time_t t;
-@@ -1598,15 +2093,20 @@ int * const okayp;
+@@ -1645,15 +2200,20 @@ int * const okayp;
** (in case tm_sec contains a value associated with a leap second).
** If that fails, try with normalization of seconds.
*/
{
time_t t;
const struct state * sp;
-@@ -1620,7 +2120,7 @@ const long offset;
+@@ -1667,7 +2227,7 @@ const long offset;
if (tmp->tm_isdst > 1)
tmp->tm_isdst = 1;
#ifdef PCTS
/*
** PCTS code courtesy Grant Sullivan (grant@osf.org).
-@@ -1664,7 +2164,7 @@ const long offset;
+@@ -1711,7 +2271,7 @@ const long offset;
tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
sp->ttis[samei].tt_gmtoff;
tmp->tm_isdst = !tmp->tm_isdst;
if (okay)
return t;
tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
-@@ -1674,19 +2174,25 @@ const long offset;
+@@ -1721,19 +2281,25 @@ const long offset;
}
return WRONG;
}
+#else /* BUILDING_VARIANT */
-+__private_extern__ pthread_mutex_t lcl_mutex;
++__private_extern__ pthread_rwlock_t lcl_rwlock;
+#endif /* BUILDING_VARIANT */
time_t
{
time_t mktime_return_value;
+ int serrno = errno;
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
- mktime_return_value = time1(tmp, localsub, 0L);
+ mktime_return_value = time1(tmp, localsub, 0L, __DARWIN_UNIX03);
- _MUTEX_UNLOCK(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+ errno = serrno;
return(mktime_return_value);
}
#ifdef STD_INSPIRED
time_t
-@@ -1702,7 +2208,7 @@ timegm(tmp)
+@@ -1749,7 +2315,7 @@ timegm(tmp)
struct tm * const tmp;
{
tmp->tm_isdst = 0;
}
time_t
-@@ -1711,7 +2217,7 @@ struct tm * const tmp;
+@@ -1758,7 +2324,7 @@ struct tm * const tmp;
const long offset;
{
tmp->tm_isdst = 0;
}
#endif /* defined STD_INSPIRED */
-@@ -1811,3 +2317,4 @@ time_t t;
+@@ -1858,3 +2424,4 @@ time_t t;
}
#endif /* defined STD_INSPIRED */
/*
** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+** 1996-06-05 by Arthur David Olson.
**
-** $FreeBSD: src/lib/libc/stdtime/private.h,v 1.10 2004/06/14 10:31:52 stefanf Exp $
+** $FreeBSD: src/lib/libc/stdtime/private.h,v 1.11 2009/05/23 06:31:50 edwin Exp $
*/
/* Stuff moved from Makefile.inc to reduce clutter */
#ifndef lint
#ifndef NOID
/*
-static char privatehid[] = "@(#)private.h 7.53";
+static char privatehid[] = "@(#)private.h 8.6";
*/
#endif /* !defined NOID */
#endif /* !defined lint */
+#define GRANDPARENTED "Local time zone must be set--see zic manual page"
+
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
#define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */
-#ifndef HAVE_STRERROR
-#define HAVE_STRERROR 1
-#endif /* !defined HAVE_STRERROR */
-
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
#include "stdio.h"
#include "errno.h"
#include "string.h"
-#include "limits.h" /* for CHAR_BIT */
+#include "limits.h" /* for CHAR_BIT et al. */
#include "time.h"
#include "stdlib.h"
-#if HAVE_GETTEXT - 0
+#if HAVE_GETTEXT
#include "libintl.h"
-#endif /* HAVE_GETTEXT - 0 */
+#endif /* HAVE_GETTEXT */
-#if HAVE_SYS_WAIT_H - 0
+#if HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
-#endif /* HAVE_SYS_WAIT_H - 0 */
+#endif /* HAVE_SYS_WAIT_H */
#ifndef WIFEXITED
#define WIFEXITED(status) (((status) & 0xff) == 0)
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
#endif /* !defined WEXITSTATUS */
-#if HAVE_UNISTD_H - 0
-#include "unistd.h" /* for F_OK and R_OK */
-#endif /* HAVE_UNISTD_H - 0 */
+#if HAVE_UNISTD_H
+#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */
+#endif /* HAVE_UNISTD_H */
-#if !(HAVE_UNISTD_H - 0)
+#if !(HAVE_UNISTD_H)
#ifndef F_OK
#define F_OK 0
#endif /* !defined F_OK */
#ifndef R_OK
#define R_OK 4
#endif /* !defined R_OK */
-#endif /* !(HAVE_UNISTD_H - 0) */
+#endif /* !(HAVE_UNISTD_H) */
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
+/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
/*
-** SunOS 4.1.1 headers lack FILENAME_MAX.
+** Define HAVE_STDINT_H's default value here, rather than at the
+** start, since __GLIBC__'s value depends on previously-included
+** files.
+** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
*/
+#ifndef HAVE_STDINT_H
+#define HAVE_STDINT_H \
+ (199901 <= __STDC_VERSION__ || \
+ 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+#endif /* !defined HAVE_STDINT_H */
+
+#if HAVE_STDINT_H
+#include "stdint.h"
+#endif /* !HAVE_STDINT_H */
+
+#ifndef INT_FAST64_MAX
+/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
+#if defined LLONG_MAX || defined __LONG_LONG_MAX__
+typedef long long int_fast64_t;
+#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
+#if (LONG_MAX >> 31) < 0xffffffff
+Please use a compiler that supports a 64-bit integer type (or wider);
+you may need to compile with "-DHAVE_STDINT_H".
+#endif /* (LONG_MAX >> 31) < 0xffffffff */
+typedef long int_fast64_t;
+#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
+#endif /* !defined INT_FAST64_MAX */
+
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif /* !defined INT32_MAX */
+#ifndef INT32_MIN
+#define INT32_MIN (-1 - INT32_MAX)
+#endif /* !defined INT32_MIN */
-#ifndef FILENAME_MAX
-
-#ifndef MAXPATHLEN
-#ifdef unix
-#include "sys/param.h"
-#endif /* defined unix */
-#endif /* !defined MAXPATHLEN */
+/*
+** Workarounds for compilers/systems.
+*/
-#ifdef MAXPATHLEN
-#define FILENAME_MAX MAXPATHLEN
-#endif /* defined MAXPATHLEN */
-#ifndef MAXPATHLEN
-#define FILENAME_MAX 1024 /* Pure guesswork */
-#endif /* !defined MAXPATHLEN */
+/*
+** Some time.h implementations don't declare asctime_r.
+** Others might define it as a macro.
+** Fix the former without affecting the latter.
+*/
-#endif /* !defined FILENAME_MAX */
+#ifndef asctime_r
+extern char * asctime_r(struct tm const *, char *);
+#endif
/*
** Private function declarations.
*/
-char * icalloc(int nelem, int elsize);
-char * icatalloc(char * old, const char * new);
-char * icpyalloc(const char * string);
-char * imalloc(int n);
-void * irealloc(void * pointer, int size);
-void icfree(char * pointer);
-void ifree(char * pointer);
-char * scheck(const char *string, const char *format);
+char * icalloc(int nelem, int elsize);
+char * icatalloc(char * old, const char * new);
+char * icpyalloc(const char * string);
+char * imalloc(int n);
+void * irealloc(void * pointer, int size);
+void icfree(char * pointer);
+void ifree(char * pointer);
+const char * scheck(const char * string, const char * format);
/*
** Finally, some convenience items.
#define TYPE_SIGNED(type) (((type) -1) < 0)
#endif /* !defined TYPE_SIGNED */
+/*
+** Since the definition of TYPE_INTEGRAL contains floating point numbers,
+** it cannot be used in preprocessor directives.
+*/
+
+#ifndef TYPE_INTEGRAL
+#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
+#endif /* !defined TYPE_INTEGRAL */
+
+/*
+** Since the definition of TYPE_INTEGRAL contains floating point numbers,
+** it cannot be used in preprocessor directives.
+*/
+
+#ifndef TYPE_INTEGRAL
+#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
+#endif /* !defined TYPE_INTEGRAL */
+
#ifndef INT_STRLEN_MAXIMUM
/*
** 302 / 1000 is log10(2.0) rounded up.
** add one more for a minus sign if the type is signed.
*/
#define INT_STRLEN_MAXIMUM(type) \
- ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
+ ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
+ 1 + TYPE_SIGNED(type))
#endif /* !defined INT_STRLEN_MAXIMUM */
/*
*/
#ifndef _
-#if HAVE_GETTEXT - 0
+#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
-#else /* !(HAVE_GETTEXT - 0) */
+#else /* !HAVE_GETTEXT */
#define _(msgid) msgid
-#endif /* !(HAVE_GETTEXT - 0) */
+#endif /* !HAVE_GETTEXT */
#endif /* !defined _ */
#ifndef TZ_DOMAIN
char *asctime_r(struct tm const *, char *);
char *ctime_r(time_t const *, char *);
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+#ifndef YEARSPERREPEAT
+#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
+#endif /* !defined YEARSPERREPEAT */
+
+/*
+** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
+*/
+
+#ifndef AVGSECSPERYEAR
+#define AVGSECSPERYEAR 31556952L
+#endif /* !defined AVGSECSPERYEAR */
+
+#ifndef SECSPERREPEAT
+#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
+#endif /* !defined SECSPERREPEAT */
+
+#ifndef SECSPERREPEAT_BITS
+#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
+#endif /* !defined SECSPERREPEAT_BITS */
/*
** UNIX was a registered trademark of The Open Group in 2003.
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strftime.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdtime/strftime.3,v 1.34 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdtime/strftime.3,v 1.40 2008/05/16 04:33:04 grog Exp $
.\"
-.Dd January 4, 2003
+.Dd November 4, 2004
.Dt STRFTIME 3
.Os
.Sh NAME
.Dq Li %m/%d/%y .
.It Cm %d
is replaced by the day of the month as a decimal number (01-31).
-.It Cm \&%E* Cm \&%O*
+.It Cm %E* %O*
POSIX locale extensions.
The sequences
%Ec %EC %Ex %EX %Ey %EY
are supposed to provide alternate
representations.
.Pp
-Additionly %OB implemented
+Additionally %OB implemented
to represent alternative months names
(used standalone, without day mentioned).
.It Cm %e
-is replaced by the day of month as a decimal number (1-31); single
+is replaced by the day of the month as a decimal number (1-31); single
digits are preceded by a blank.
.It Cm \&%F
is equivalent to
.It Cm \&%H
is replaced by the hour (24-hour clock) as a decimal number (00-23).
.It Cm %h
-the same as %b.
+the same as
+.Cm %b .
.It Cm \&%I
is replaced by the hour (12-hour clock) as a decimal number (01-12).
.It Cm %j
is replaced by the month as a decimal number (01-12).
.It Cm %n
is replaced by a newline.
-.It Cm \&%O*
-the same as %E*.
+.It Cm %O*
+the same as
+.Cm %E* .
.It Cm %p
is replaced by national representation of either
-"ante meridiem"
+"ante meridiem" (a.m.)
or
-"post meridiem"
+"post meridiem" (p.m.)
as appropriate.
.It Cm \&%R
is equivalent to
is replaced by the year without century as a decimal number (00-99).
.It Cm \&%Z
is replaced by the time zone name.
-.It Cm \&%z
+.It Cm %z
is replaced by the time zone offset from UTC; a leading plus sign stands for
east of UTC, a minus sign for west of UTC, hours and minutes follow
with two digits each and no delimiter between them (common form for
is replaced by national representation of the date and time
(the format is similar to that produced by
.Xr date 1 ) .
+.It Cm %-*
+GNU libc extension.
+Do not do any padding when performing numerical outputs.
+.It Cm %_*
+GNU libc extension.
+Explicitly specify space for padding.
+.It Cm %0*
+GNU libc extension.
+Explicitly specify zero for padding.
.It Cm %%
is replaced by
.Ql % .
---- _SB/Libc/stdtime/FreeBSD/strftime.3 2004-11-25 11:38:45.000000000 -0800
-+++ _SB/Libc/stdtime/FreeBSD/strftime.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -40,7 +40,8 @@
+--- strftime.3.bsdnew 2009-11-14 13:55:44.000000000 -0800
++++ strftime.3 2009-11-14 13:55:44.000000000 -0800
+@@ -36,7 +36,8 @@
.Dt STRFTIME 3
.Os
.Sh NAME
.Nd format date and time
.Sh LIBRARY
.Lb libc
-@@ -48,10 +49,20 @@
+@@ -44,10 +45,20 @@
.In time.h
.Ft size_t
.Fo strftime
.Fc
.Sh DESCRIPTION
The
-@@ -59,7 +70,7 @@
+@@ -55,7 +66,7 @@ The
function formats the information from
.Fa timeptr
into the buffer
according to the string pointed to by
.Fa format .
.Pp
-@@ -83,6 +94,14 @@
+@@ -79,6 +90,14 @@ returns the number of characters in the
terminating NUL.
Otherwise, zero is returned and the buffer contents are indeterminate.
.Pp
The conversion specifications are copied to the buffer after expansion
as follows:-
.Bl -tag -width "xxxx"
-@@ -226,7 +245,8 @@
+@@ -233,7 +252,8 @@ is replaced by
.Xr ctime 3 ,
.Xr printf 3 ,
.Xr strptime 3 ,
.Sh STANDARDS
The
.Fn strftime
-@@ -253,11 +273,12 @@
+@@ -260,11 +280,12 @@ with a lot of extensions including
.Ql %u ,
.Ql \&%V ,
.Ql %z ,
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
+ * by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
#ifndef lint
#ifndef NOID
-static const char elsieid[] = "@(#)strftime.c 7.64";
+static const char elsieid[] = "@(#)strftime.3 8.3";
/*
** Based on the UCB version with the ID appearing below.
** This is ANSIish only when "multibyte character == plain character".
static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.40 2004/06/14 10:31:52 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.44 2009/06/09 09:02:58 delphij Exp $");
#include "tzfile.h"
#include <fcntl.h>
static char * _add(const char *, char *, const char *);
static char * _conv(int, const char *, char *, const char *);
-static char * _fmt(const char *, const struct tm *, char *, const char *, int *);
-
-size_t strftime(char * __restrict, size_t, const char * __restrict,
- const struct tm * __restrict);
+static char * _fmt(const char *, const struct tm *, char *, const char *,
+ int *);
+static char * _yconv(int, int, int, int, char *, const char *);
extern char * tzname[];
#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
#endif /* !defined YEAR_2000_NAME */
-
#define IN_NONE 0
#define IN_SOME 1
#define IN_THIS 2
#define IN_ALL 3
+#define PAD_DEFAULT 0
+#define PAD_LESS 1
+#define PAD_SPACE 2
+#define PAD_ZERO 3
+
+static const char* fmt_padding[][4] = {
+ /* DEFAULT, LESS, SPACE, ZERO */
+#define PAD_FMT_MONTHDAY 0
+#define PAD_FMT_HMS 0
+#define PAD_FMT_CENTURY 0
+#define PAD_FMT_SHORTYEAR 0
+#define PAD_FMT_MONTH 0
+#define PAD_FMT_WEEKOFYEAR 0
+#define PAD_FMT_DAYOFMONTH 0
+ { "%02d", "%d", "%2d", "%02d" },
+#define PAD_FMT_SDAYOFMONTH 1
+#define PAD_FMT_SHMS 1
+ { "%2d", "%d", "%2d", "%02d" },
+#define PAD_FMT_DAYOFYEAR 2
+ { "%03d", "%d", "%3d", "%03d" },
+#define PAD_FMT_YEAR 3
+ { "%04d", "%d", "%4d", "%04d" }
+};
+
size_t
strftime(char * __restrict s, size_t maxsize, const char * __restrict format,
const struct tm * __restrict t)
const char * const ptlim;
int * warnp;
{
- int Ealternative, Oalternative;
+ int Ealternative, Oalternative, PadIndex;
struct lc_time_T *tptr = __get_current_time_locale();
for ( ; *format; ++format) {
if (*format == '%') {
Ealternative = 0;
Oalternative = 0;
+ PadIndex = PAD_DEFAULT;
label:
switch (*++format) {
case '\0':
** something completely different.
** (ado, 1993-05-24)
*/
- pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
- "%02d", pt, ptlim);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+ pt, ptlim);
continue;
case 'c':
{
int warn2 = IN_SOME;
- pt = _fmt(tptr->c_fmt, t, pt, ptlim, warnp);
+ pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
continue;
case 'd':
- pt = _conv(t->tm_mday, "%02d", pt, ptlim);
+ pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex],
+ pt, ptlim);
continue;
case 'E':
if (Ealternative || Oalternative)
Oalternative++;
goto label;
case 'e':
- pt = _conv(t->tm_mday, "%2d", pt, ptlim);
+ pt = _conv(t->tm_mday,
+ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim);
continue;
case 'F':
pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
continue;
case 'H':
- pt = _conv(t->tm_hour, "%02d", pt, ptlim);
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim);
continue;
case 'I':
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
- "%02d", pt, ptlim);
+ fmt_padding[PAD_FMT_HMS][PadIndex], pt, ptlim);
continue;
case 'j':
- pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
+ pt = _conv(t->tm_yday + 1,
+ fmt_padding[PAD_FMT_DAYOFYEAR][PadIndex], pt, ptlim);
continue;
case 'k':
/*
** t->tm_hour % 12 : 12, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbins'
- ** strftime version 3.0. That is, "%k" and
+ ** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
- pt = _conv(t->tm_hour, "%2d", pt, ptlim);
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_SHMS][PadIndex],
+ pt, ptlim);
continue;
#ifdef KITCHEN_SINK
case 'K':
** _conv(t->tm_hour, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbin's
- ** strftime version 3.0. That is, "%k" and
+ ** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
- "%2d", pt, ptlim);
+ fmt_padding[PAD_FMT_SHMS][PadIndex], pt, ptlim);
continue;
case 'M':
- pt = _conv(t->tm_min, "%02d", pt, ptlim);
+ pt = _conv(t->tm_min, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim);
continue;
case 'm':
- pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
+ pt = _conv(t->tm_mon + 1,
+ fmt_padding[PAD_FMT_MONTH][PadIndex], pt, ptlim);
continue;
case 'n':
pt = _add("\n", pt, ptlim);
warnp);
continue;
case 'S':
- pt = _conv(t->tm_sec, "%02d", pt, ptlim);
+ pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim);
continue;
case 's':
{
case 'U':
pt = _conv((t->tm_yday + DAYSPERWEEK -
t->tm_wday) / DAYSPERWEEK,
- "%02d", pt, ptlim);
+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim);
continue;
case 'u':
/*
case 'G': /* ISO 8601 year (four digits) */
case 'g': /* ISO 8601 year (two digits) */
/*
-** From Arnold Robbins' strftime version 3.0: "the week number of the
+** From Arnold Robbins' strftime version 3.0: "the week number of the
** year (the first Monday as the first day of week 1) as a decimal number
** (01-53)."
** (ado, 1993-05-24)
** might also contain days from the previous year and the week before week
** 01 of a year is the last week (52 or 53) of the previous year even if
** it contains days from the new year. A week starts with Monday (day 1)
-** and ends with Sunday (day 7). For example, the first week of the year
+** and ends with Sunday (day 7). For example, the first week of the year
** 1997 lasts from 1996-12-30 to 1997-01-05..."
** (ado, 1996-01-02)
*/
{
int year;
+ int base;
int yday;
int wday;
int w;
- year = t->tm_year + TM_YEAR_BASE;
+ year = t->tm_year;
+ base = TM_YEAR_BASE;
yday = t->tm_yday;
wday = t->tm_wday;
for ( ; ; ) {
int bot;
int top;
- len = isleap(year) ?
+ len = isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
/*
top += DAYSPERWEEK;
top += len;
if (yday >= top) {
- ++year;
+ ++base;
w = 1;
break;
}
DAYSPERWEEK);
break;
}
- --year;
- yday += isleap(year) ?
+ --base;
+ yday += isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
}
#ifdef XPG4_1994_04_09
- if ((w == 52
- && t->tm_mon == TM_JANUARY)
- || (w == 1
- && t->tm_mon == TM_DECEMBER))
- w = 53;
+ if ((w == 52 &&
+ t->tm_mon == TM_JANUARY) ||
+ (w == 1 &&
+ t->tm_mon == TM_DECEMBER))
+ w = 53;
#endif /* defined XPG4_1994_04_09 */
if (*format == 'V')
- pt = _conv(w, "%02d",
+ pt = _conv(w, fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],
pt, ptlim);
else if (*format == 'g') {
*warnp = IN_ALL;
- pt = _conv(year % 100, "%02d",
+ pt = _yconv(year, base, 0, 1,
pt, ptlim);
- } else pt = _conv(year, "%04d",
+ } else pt = _yconv(year, base, 1, 1,
pt, ptlim);
}
continue;
(t->tm_wday ?
(t->tm_wday - 1) :
(DAYSPERWEEK - 1))) / DAYSPERWEEK,
- "%02d", pt, ptlim);
+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim);
continue;
case 'w':
pt = _conv(t->tm_wday, "%d", pt, ptlim);
continue;
case 'y':
*warnp = IN_ALL;
- pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
- "%02d", pt, ptlim);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+ pt, ptlim);
continue;
case 'Y':
- pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
pt, ptlim);
continue;
case 'Z':
/*
** C99 says that the UTC offset must
** be computed by looking only at
- ** tm_isdst. This requirement is
+ ** tm_isdst. This requirement is
** incorrect, since it means the code
** must rely on magic (in this case
** altzone and timezone), and the
** magic might not have the correct
- ** offset. Doing things correctly is
+ ** offset. Doing things correctly is
** tricky and requires disobeying C99;
** see GNU C strftime for details.
** For now, punt and conform to the
diff = -diff;
} else sign = "+";
pt = _add(sign, pt, ptlim);
- diff /= 60;
- pt = _conv((diff/60)*100 + diff%60,
- "%04d", pt, ptlim);
+ diff /= SECSPERMIN;
+ diff = (diff / MINSPERHOUR) * 100 +
+ (diff % MINSPERHOUR);
+ pt = _conv(diff,
+ fmt_padding[PAD_FMT_YEAR][PadIndex], pt, ptlim);
}
continue;
case '+':
pt = _fmt(tptr->date_fmt, t, pt, ptlim,
warnp);
continue;
+ case '-':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_LESS;
+ goto label;
+ case '_':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_SPACE;
+ goto label;
+ case '0':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_ZERO;
+ goto label;
case '%':
/*
** X311J/88-090 (4.12.3.5): if conversion char is
- ** undefined, behavior is undefined. Print out the
+ ** undefined, behavior is undefined. Print out the
** character itself as printf(3) also does.
*/
default:
++pt;
return pt;
}
+
+/*
+** POSIX and the C Standard are unclear or inconsistent about
+** what %C and %y do if the year is negative or exceeds 9999.
+** Use the convention that %C concatenated with %y yields the
+** same output as %Y, and that %Y contains at least 4 bytes,
+** with more only if necessary.
+*/
+
+static char *
+_yconv(a, b, convert_top, convert_yy, pt, ptlim)
+const int a;
+const int b;
+const int convert_top;
+const int convert_yy;
+char * pt;
+const char * const ptlim;
+{
+ register int lead;
+ register int trail;
+
+#define DIVISOR 100
+ trail = a % DIVISOR + b % DIVISOR;
+ lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
+ trail %= DIVISOR;
+ if (trail < 0 && lead > 0) {
+ trail += DIVISOR;
+ --lead;
+ } else if (lead < 0 && trail > 0) {
+ trail -= DIVISOR;
+ ++lead;
+ }
+ if (convert_top) {
+ if (lead == 0 && trail < 0)
+ pt = _add("-0", pt, ptlim);
+ else pt = _conv(lead, "%02d", pt, ptlim);
+ }
+ if (convert_yy)
+ pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
+ return pt;
+}
---- strftime.c.orig 2004-11-25 11:38:45.000000000 -0800
-+++ strftime.c 2005-02-27 16:07:41.000000000 -0800
-@@ -25,6 +25,8 @@
+--- strftime.c.orig 2010-06-24 01:11:42.000000000 -0700
++++ strftime.c 2010-06-24 11:29:51.000000000 -0700
+@@ -25,6 +25,8 @@ static const char elsieid[] = "@(#)strft
#endif /* !defined NOID */
#endif /* !defined lint */
#include "namespace.h"
#include "private.h"
-@@ -35,19 +37,26 @@
- __FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.40 2004/06/14 10:31:52 stefanf Exp $");
+@@ -35,18 +37,25 @@ static const char sccsid[] = "@(#)strfti
+ __FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.44 2009/06/09 09:02:58 delphij Exp $");
#include "tzfile.h"
+#include <time.h>
+#if !BUILDING_VARIANT
static char * _add(const char *, char *, const char *);
-static char * _conv(int, const char *, char *, const char *);
--static char * _fmt(const char *, const struct tm *, char *, const char *, int *);
+-static char * _fmt(const char *, const struct tm *, char *, const char *,
+- int *);
+-static char * _yconv(int, int, int, int, char *, const char *);
+static char * _conv(int, const char *, char *, const char *, locale_t);
-+#endif /* !BUILDING_VARIANT */
++static char * _yconv(int, int, int, int, char *, const char *, locale_t);
++#endif
+#define _fmt _st_fmt
-+__private_extern__ char *_fmt(const char *, const struct tm *, char *, const char *, int *, struct lc_time_T *, locale_t);
-
- size_t strftime(char * __restrict, size_t, const char * __restrict,
- const struct tm * __restrict);
++__private_extern__ char * _fmt(const char *, const struct tm *, char *, const char *,
++ int *, struct lc_time_T *, locale_t);
extern char * tzname[];
+__private_extern__ long __darwin_altzone; /* DST timezone offset */
#ifndef YEAR_2000_NAME
#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
-@@ -60,29 +69,40 @@
- #define IN_ALL 3
+@@ -62,6 +71,7 @@ extern char * tzname[];
+ #define PAD_SPACE 2
+ #define PAD_ZERO 3
+
++#ifndef BUILDING_VARIANT
+ static const char* fmt_padding[][4] = {
+ /* DEFAULT, LESS, SPACE, ZERO */
+ #define PAD_FMT_MONTHDAY 0
+@@ -80,31 +90,36 @@ static const char* fmt_padding[][4] = {
+ #define PAD_FMT_YEAR 3
+ { "%04d", "%d", "%4d", "%04d" }
+ };
++#endif
++
++#define USG_COMPAT
++#define ALTZONE
size_t
-strftime(char * __restrict s, size_t maxsize, const char * __restrict format,
{
char * p;
int warn;
-+#if __DARWIN_UNIX03
-+ struct tm t2;
-+#endif /* __DARWIN_UNIX03 */
+ NORMALIZE_LOCALE(loc);
tzset();
warn = IN_NONE;
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
-+#if __DARWIN_UNIX03
-+ if (t->tm_isdst >= 0) {
-+ t2 = *t;
-+ t2.tm_gmtoff = t->tm_isdst ? -__darwin_altzone : -_st_get_timezone();
-+ t = &t2;
-+ }
-+#endif /* __DARWIN_UNIX03 */
+ p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, __get_current_time_locale(loc), loc);
#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
}
#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
if (p == s + maxsize)
-@@ -91,16 +111,25 @@
+@@ -113,16 +128,25 @@ strftime(char * __restrict s, size_t max
return p - s;
}
+struct lc_time_T * tptr;
+locale_t loc;
{
- int Ealternative, Oalternative;
+ int Ealternative, Oalternative, PadIndex;
- struct lc_time_T *tptr = __get_current_time_locale();
for ( ; *format; ++format) {
if (*format == '%') {
-@@ -146,13 +175,13 @@
+@@ -163,19 +187,19 @@ label:
+ case 'C':
+ /*
+ ** %C used to do a...
+- ** _fmt("%a %b %e %X %Y", t);
++ ** _fmt("%a %b %e %X %Y", t, tptr, loc);
+ ** ...whereas now POSIX 1003.2 calls for
+ ** something completely different.
** (ado, 1993-05-24)
*/
- pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
-- "%02d", pt, ptlim);
-+ "%02d", pt, ptlim, loc);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+- pt, ptlim);
++ pt, ptlim, loc);
continue;
case 'c':
{
int warn2 = IN_SOME;
-- pt = _fmt(tptr->c_fmt, t, pt, ptlim, warnp);
-+ pt = _fmt(tptr->c_fmt, t, pt, ptlim, warnp, tptr, loc);
+- pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2);
++ pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, tptr, loc);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
-@@ -160,10 +189,10 @@
+@@ -183,11 +207,11 @@ label:
}
continue;
case 'D':
+ pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, tptr, loc);
continue;
case 'd':
-- pt = _conv(t->tm_mday, "%02d", pt, ptlim);
-+ pt = _conv(t->tm_mday, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex],
+- pt, ptlim);
++ pt, ptlim, loc);
continue;
case 'E':
if (Ealternative || Oalternative)
-@@ -188,21 +217,21 @@
- Oalternative++;
+@@ -213,29 +237,29 @@ label:
goto label;
case 'e':
-- pt = _conv(t->tm_mday, "%2d", pt, ptlim);
-+ pt = _conv(t->tm_mday, "%2d", pt, ptlim, loc);
+ pt = _conv(t->tm_mday,
+- fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim, loc);
continue;
case 'F':
- pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
+ pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, tptr, loc);
continue;
case 'H':
-- pt = _conv(t->tm_hour, "%02d", pt, ptlim);
-+ pt = _conv(t->tm_hour, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex],
+- pt, ptlim);
++ pt, ptlim, loc);
continue;
case 'I':
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
-- "%02d", pt, ptlim);
-+ "%02d", pt, ptlim, loc);
+- fmt_padding[PAD_FMT_HMS][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_HMS][PadIndex], pt, ptlim, loc);
continue;
case 'j':
-- pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
-+ pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim, loc);
+ pt = _conv(t->tm_yday + 1,
+- fmt_padding[PAD_FMT_DAYOFYEAR][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_DAYOFYEAR][PadIndex], pt, ptlim, loc);
continue;
case 'k':
/*
-@@ -215,7 +244,7 @@
- ** "%l" have been swapped.
+ ** This used to be...
+ ** _conv(t->tm_hour % 12 ?
+- ** t->tm_hour % 12 : 12, 2, ' ');
++ ** t->tm_hour % 12 : 12, 2, ' ', loc);
+ ** ...and has been changed to the below to
+ ** match SunOS 4.1.1 and Arnold Robbins'
+ ** strftime version 3.0. That is, "%k" and
+@@ -243,7 +267,7 @@ label:
** (ado, 1993-05-24)
*/
-- pt = _conv(t->tm_hour, "%2d", pt, ptlim);
-+ pt = _conv(t->tm_hour, "%2d", pt, ptlim, loc);
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_SHMS][PadIndex],
+- pt, ptlim);
++ pt, ptlim, loc);
continue;
#ifdef KITCHEN_SINK
case 'K':
-@@ -237,13 +266,13 @@
+@@ -265,15 +289,15 @@ label:
*/
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
-- "%2d", pt, ptlim);
-+ "%2d", pt, ptlim, loc);
+- fmt_padding[PAD_FMT_SHMS][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_SHMS][PadIndex], pt, ptlim, loc);
continue;
case 'M':
-- pt = _conv(t->tm_min, "%02d", pt, ptlim);
-+ pt = _conv(t->tm_min, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_min, fmt_padding[PAD_FMT_HMS][PadIndex],
+- pt, ptlim);
++ pt, ptlim, loc);
continue;
case 'm':
-- pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
-+ pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_mon + 1,
+- fmt_padding[PAD_FMT_MONTH][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_MONTH][PadIndex], pt, ptlim, loc);
continue;
case 'n':
pt = _add("\n", pt, ptlim);
-@@ -255,14 +284,14 @@
+@@ -285,15 +309,15 @@ label:
pt, ptlim);
continue;
case 'R':
+ warnp, tptr, loc);
continue;
case 'S':
-- pt = _conv(t->tm_sec, "%02d", pt, ptlim);
-+ pt = _conv(t->tm_sec, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex],
+- pt, ptlim);
++ pt, ptlim, loc);
continue;
case 's':
{
-@@ -274,15 +303,15 @@
+@@ -305,15 +329,15 @@ label:
tm = *t;
mkt = mktime(&tm);
if (TYPE_SIGNED(time_t))
continue;
case 't':
pt = _add("\t", pt, ptlim);
-@@ -290,7 +319,7 @@
+@@ -321,7 +345,7 @@ label:
case 'U':
pt = _conv((t->tm_yday + DAYSPERWEEK -
t->tm_wday) / DAYSPERWEEK,
-- "%02d", pt, ptlim);
-+ "%02d", pt, ptlim, loc);
+- fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim, loc);
continue;
case 'u':
/*
-@@ -301,7 +330,7 @@
+@@ -332,7 +356,7 @@ label:
*/
pt = _conv((t->tm_wday == 0) ?
DAYSPERWEEK : t->tm_wday,
continue;
case 'V': /* ISO 8601 week number */
case 'G': /* ISO 8601 year (four digits) */
-@@ -380,13 +409,13 @@
+@@ -413,13 +437,13 @@ label:
#endif /* defined XPG4_1994_04_09 */
if (*format == 'V')
- pt = _conv(w, "%02d",
+ pt = _conv(w, fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],
- pt, ptlim);
+ pt, ptlim, loc);
else if (*format == 'g') {
*warnp = IN_ALL;
- pt = _conv(year % 100, "%02d",
+ pt = _yconv(year, base, 0, 1,
- pt, ptlim);
+ pt, ptlim, loc);
- } else pt = _conv(year, "%04d",
+ } else pt = _yconv(year, base, 1, 1,
- pt, ptlim);
+ pt, ptlim, loc);
}
continue;
case 'v':
-@@ -395,26 +424,26 @@
+@@ -428,26 +452,26 @@ label:
** "date as dd-bbb-YYYY"
** (ado, 1993-05-24)
*/
(t->tm_wday ?
(t->tm_wday - 1) :
(DAYSPERWEEK - 1))) / DAYSPERWEEK,
-- "%02d", pt, ptlim);
-+ "%02d", pt, ptlim, loc);
+- fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim, loc);
continue;
case 'w':
- pt = _conv(t->tm_wday, "%d", pt, ptlim);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
-@@ -424,11 +453,11 @@
+@@ -457,11 +481,11 @@ label:
case 'y':
*warnp = IN_ALL;
- pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
-- "%02d", pt, ptlim);
-+ "%02d", pt, ptlim, loc);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+- pt, ptlim);
++ pt, ptlim, loc);
continue;
case 'Y':
- pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
- pt, ptlim);
+ pt, ptlim, loc);
continue;
case 'Z':
#ifdef TM_ZONE
-@@ -476,7 +505,7 @@
+@@ -485,9 +509,9 @@ label:
+
+ if (t->tm_isdst < 0)
+ continue;
+-#ifdef TM_GMTOFF
++#if defined(TM_GMTOFF) && !__DARWIN_UNIX03
+ diff = t->TM_GMTOFF;
+-#else /* !defined TM_GMTOFF */
++#else /* !defined TM_GMTOFF || __DARWIN_UNIX03 */
+ /*
+ ** C99 says that the UTC offset must
+ ** be computed by looking only at
+@@ -509,7 +533,7 @@ label:
*/
if (t->tm_isdst == 0)
#ifdef USG_COMPAT
#else /* !defined USG_COMPAT */
continue;
#endif /* !defined USG_COMPAT */
-@@ -494,12 +523,12 @@
- pt = _add(sign, pt, ptlim);
- diff /= 60;
- pt = _conv((diff/60)*100 + diff%60,
-- "%04d", pt, ptlim);
-+ "%04d", pt, ptlim, loc);
+@@ -519,7 +543,7 @@ label:
+ #else /* !defined ALTZONE */
+ continue;
+ #endif /* !defined ALTZONE */
+-#endif /* !defined TM_GMTOFF */
++#endif /* !defined TM_GMTOFF || __DARWIN_UNIX03 */
+ if (diff < 0) {
+ sign = "-";
+ diff = -diff;
+@@ -529,12 +553,12 @@ label:
+ diff = (diff / MINSPERHOUR) * 100 +
+ (diff % MINSPERHOUR);
+ pt = _conv(diff,
+- fmt_padding[PAD_FMT_YEAR][PadIndex], pt, ptlim);
++ fmt_padding[PAD_FMT_YEAR][PadIndex], pt, ptlim, loc);
}
continue;
case '+':
- warnp);
+ warnp, tptr, loc);
continue;
- case '%':
- /*
-@@ -519,15 +548,16 @@
+ case '-':
+ if (PadIndex != PAD_DEFAULT)
+@@ -569,15 +593,16 @@ label:
}
static char *
return _add(buf, pt, ptlim);
}
-@@ -541,3 +571,4 @@
- ++pt;
+@@ -601,13 +626,14 @@ const char * const ptlim;
+ */
+
+ static char *
+-_yconv(a, b, convert_top, convert_yy, pt, ptlim)
++_yconv(a, b, convert_top, convert_yy, pt, ptlim, loc)
+ const int a;
+ const int b;
+ const int convert_top;
+ const int convert_yy;
+ char * pt;
+ const char * const ptlim;
++locale_t loc;
+ {
+ register int lead;
+ register int trail;
+@@ -626,9 +652,10 @@ const char * const ptlim;
+ if (convert_top) {
+ if (lead == 0 && trail < 0)
+ pt = _add("-0", pt, ptlim);
+- else pt = _conv(lead, "%02d", pt, ptlim);
++ else pt = _conv(lead, "%02d", pt, ptlim, loc);
+ }
+ if (convert_yy)
+- pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
++ pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim, loc);
return pt;
}
+#endif /* !BUILDING_VARIANT */
.\" (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/libc/stdtime/strptime.3,v 1.23 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdtime/strptime.3,v 1.24 2005/01/20 09:17:04 ru Exp $
.\" "
.Dd January 4, 2003
.Dt STRPTIME 3
.Xr date 1 ,
.Xr scanf 3 ,
.Xr strftime 3
+.Sh HISTORY
+The
+.Fn strptime
+function appeared in
+.Fx 3.0 .
.Sh AUTHORS
The
.Fn strptime
.Pp
This man page was written by
.An J\(:org Wunsch .
-.Sh HISTORY
-The
-.Fn strptime
-function appeared in
-.Fx 3.0 .
.Sh BUGS
Both the
.Fa %e
---- strptime.3.orig 2007-04-03 12:19:24.000000000 -0700
-+++ strptime.3 2007-04-03 12:54:12.000000000 -0700
+--- strptime.3.bsdnew 2009-11-14 13:55:44.000000000 -0800
++++ strptime.3 2009-11-14 14:00:22.000000000 -0800
@@ -29,7 +29,8 @@
.Dt STRPTIME 3
.Os
The resulting values will be relative to the local time zone.
Thus, it can be considered the reverse operation of
.Xr strftime 3 .
-@@ -78,7 +88,7 @@
+@@ -78,7 +88,7 @@ string does not contain enough conversio
specify the resulting
.Vt struct tm ,
the unspecified members of
are left untouched.
For example, if
.Fa format
-@@ -91,9 +101,17 @@
+@@ -91,9 +101,17 @@ and
.Va tm_min
will be modified.
If time relative to today is desired, initialize the
.Sh RETURN VALUES
Upon successful completion,
.Fn strptime
-@@ -104,10 +122,16 @@
+@@ -104,10 +122,16 @@ that has not been required to satisfy th
It returns
.Dv NULL
if one of the conversions failed.
-.Xr strftime 3
+.Xr strftime 3 ,
+.Xr xlocale 3
- .Sh AUTHORS
+ .Sh HISTORY
The
.Fn strptime
static char sccsid[] __unused = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
#endif /* !defined NOID */
#endif /* not lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.37 2009/09/02 04:56:30 ache Exp $");
#include "namespace.h"
#include <time.h>
}
}
break;
+
+ case 'z':
+ {
+ int sign = 1;
+
+ if (*buf != '+') {
+ if (*buf == '-')
+ sign = -1;
+ else
+ return 0;
+ }
+
+ buf++;
+ i = 0;
+ for (len = 4; len > 0; len--) {
+ if (isdigit((unsigned char)*buf)) {
+ i *= 10;
+ i += *buf - '0';
+ buf++;
+ } else
+ return 0;
+ }
+
+ tm->tm_hour -= sign * (i / 100);
+ tm->tm_min -= sign * (i % 100);
+ *GMTp = 1;
+ }
+ break;
}
}
return (char *)buf;
---- strptime.c.orig 2009-03-04 16:49:20.000000000 -0800
-+++ strptime.c 2009-05-13 16:39:36.000000000 -0700
-@@ -61,41 +61,56 @@ static char sccsid[] __unused = "@(#)str
+--- strptime.c.orig 2009-11-14 13:55:44.000000000 -0800
++++ strptime.c 2009-11-18 16:56:27.000000000 -0800
+@@ -61,41 +61,55 @@ static char sccsid[] __unused = "@(#)str
#endif /* not lint */
- __FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.37 2009/09/02 04:56:30 ache Exp $");
+#include "xlocale_private.h"
+
#include "timelocal.h"
-static char * _strptime(const char *, const char *, struct tm *, int *);
-+static char * _strptime(const char *, const char *, struct tm *, int *, locale_t) __DARWIN_ALIAS(_strptime);
+time_t _mktime(struct tm *, const char *);
#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
+ while (isspace_l((unsigned char)*ptr, loc)) {
+ ptr++;
+ }
-+ return ((*ptr)==0) ? fmt : 0; /* trailing whitespace is ok */
++ return ((*ptr)==0) ? (char *)fmt : 0; /* trailing whitespace is ok */
+ }
c = *ptr++;
buf++;
else if (c != *buf++)
return 0;
-@@ -114,18 +129,18 @@ label:
+@@ -114,18 +128,18 @@ label:
break;
case '+':
i *= 10;
i += *buf - '0';
len--;
-@@ -133,17 +148,21 @@ label:
+@@ -133,17 +147,21 @@ label:
if (i < 19)
return 0;
if (buf == 0)
return 0;
break;
-@@ -161,47 +180,55 @@ label:
+@@ -161,47 +179,55 @@ label:
goto label;
case 'F':
i *= 10;
i += *buf - '0';
len--;
-@@ -209,19 +236,19 @@ label:
+@@ -209,19 +235,19 @@ label:
if (i < 1 || i > 366)
return 0;
i *= 10;
i += *buf - '0';
len--;
-@@ -237,8 +264,8 @@ label:
+@@ -237,8 +263,8 @@ label:
tm->tm_sec = i;
}
ptr++;
break;
-@@ -254,11 +281,11 @@ label:
+@@ -254,11 +280,11 @@ label:
* XXX The %l specifier may gobble one too many
* digits if used incorrectly.
*/
i *= 10;
i += *buf - '0';
len--;
-@@ -271,8 +298,8 @@ label:
+@@ -271,8 +297,8 @@ label:
tm->tm_hour = i;
ptr++;
break;
-@@ -282,7 +309,7 @@ label:
+@@ -282,7 +308,7 @@ label:
* specifiers.
*/
len = strlen(tptr->am);
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour == 12)
-@@ -292,7 +319,7 @@ label:
+@@ -292,7 +318,7 @@ label:
}
len = strlen(tptr->pm);
if (tm->tm_hour > 12)
return 0;
if (tm->tm_hour != 12)
-@@ -307,34 +334,28 @@ label:
+@@ -307,34 +333,28 @@ label:
case 'a':
for (i = 0; i < asizeof(tptr->weekday); i++) {
len = strlen(tptr->weekday[i]);
i *= 10;
i += *buf - '0';
len--;
-@@ -342,23 +363,46 @@ label:
+@@ -342,23 +362,46 @@ label:
if (i > 53)
return 0;
ptr++;
break;
-@@ -372,11 +416,18 @@ label:
+@@ -372,11 +415,18 @@ label:
* XXX The %e specifier may gobble one too many
* digits if used incorrectly.
*/
i *= 10;
i += *buf - '0';
len--;
-@@ -386,8 +437,8 @@ label:
+@@ -386,8 +436,8 @@ label:
tm->tm_mday = i;
ptr++;
break;
-@@ -398,19 +449,19 @@ label:
+@@ -398,19 +448,19 @@ label:
if (Oalternative) {
if (c == 'B') {
len = strlen(tptr->alt_month[i]);
break;
}
}
-@@ -422,11 +473,11 @@ label:
+@@ -422,11 +472,11 @@ label:
break;
case 'm':
i *= 10;
i += *buf - '0';
len--;
-@@ -436,8 +487,8 @@ label:
+@@ -436,8 +486,8 @@ label:
tm->tm_mon = i - 1;
ptr++;
break;
-@@ -450,7 +501,7 @@ label:
+@@ -450,7 +500,7 @@ label:
sverrno = errno;
errno = 0;
if (errno == ERANGE || (long)(t = n) != n) {
errno = sverrno;
return 0;
-@@ -458,24 +509,82 @@ label:
+@@ -458,24 +508,82 @@ label:
errno = sverrno;
buf = cp;
gmtime_r(&t, tm);
if (c == 'Y')
i -= 1900;
if (c == 'y' && i < 69)
-@@ -483,35 +592,58 @@ label:
+@@ -483,37 +591,40 @@ label:
if (i < 0)
return 0;
+ *convp = CONVERT_GMT;
+ buf += len;
+ break;
-+ }
+ }
+ tzset();
+ tzlen = strlen(tzname[0]);
+ if (len == tzlen && strncmp(buf, tzname[0], tzlen) == 0) {
+ tm->tm_isdst = 1;
+ buf += len;
+ break;
- }
-+ return 0;
+ }
-+
-+ case 'z':
-+ {
-+ char sign;
-+ int hr, min;
-+
-+ if ((buf[0] != '+' && buf[0] != '-')
-+ || !isdigit_l((unsigned char)buf[1], loc)
-+ || !isdigit_l((unsigned char)buf[2], loc)
-+ || !isdigit_l((unsigned char)buf[3], loc)
-+ || !isdigit_l((unsigned char)buf[4], loc))
-+ return 0;
-+ sscanf(buf, "%c%2d%2d", &sign, &hr, &min);
-+ *convp = CONVERT_ZONE;
-+ tm->tm_gmtoff = 60 * (60 * hr + min);
-+ if (sign == '-')
-+ tm->tm_gmtoff = -tm->tm_gmtoff;
-+ buf += 5;
++ return 0;
+ }
+- break;
+
+ case 'z':
+ {
+@@ -529,7 +640,7 @@ label:
+ buf++;
+ i = 0;
+ for (len = 4; len > 0; len--) {
+- if (isdigit((unsigned char)*buf)) {
++ if (isdigit_l((unsigned char)*buf, loc)) {
+ i *= 10;
+ i += *buf - '0';
+ buf++;
+@@ -539,7 +650,7 @@ label:
+
+ tm->tm_hour -= sign * (i / 100);
+ tm->tm_min -= sign * (i % 100);
+- *GMTp = 1;
++ *convp = CONVERT_GMT;
}
break;
}
-@@ -524,14 +656,39 @@ char *
+@@ -552,14 +663,39 @@ char *
strptime(const char * __restrict buf, const char * __restrict fmt,
struct tm * __restrict tm)
{
-.\" $FreeBSD: src/lib/libc/stdtime/time2posix.3,v 1.13 2001/10/01 16:08:59 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdtime/time2posix.3,v 1.17 2009/05/27 12:18:39 edwin Exp $
.\"
-.Dd May 1, 1996
+.Dd September 11, 2005
.Dt TIME2POSIX 3
.Os
.Sh NAME
.Sh SYNOPSIS
.In time.h
.Ft time_t
-.Fn time2posix "const time_t *t"
+.Fn time2posix "time_t t"
.Ft time_t
-.Fn posix2time "const time_t *t"
+.Fn posix2time "time_t t"
.Sh DESCRIPTION
.St -p1003.1-88
legislates that a time_t value of
function is less well-behaved:
for a positive leap second hit the result is not unique,
and for a negative leap second hit the corresponding
-POSIX time_t doesn't exist so an adjacent value is returned.
+POSIX time_t does not exist so an adjacent value is returned.
Both of these are good indicators of the inferiority of the
POSIX representation.
.Pp
.Xr localtime 3 ,
.Xr mktime 3 ,
.Xr time 3
+.\" @(#)time2posix.3 8.2
+.\" This file is in the public domain, so clarified as of
+.\" 1996-06-05 by Arthur David Olson.
+++ /dev/null
---- time2posix.3.orig Tue May 20 15:23:48 2003
-+++ time2posix.3 Tue May 27 12:02:20 2003
-@@ -12,9 +12,9 @@
- .Sh SYNOPSIS
- .In time.h
- .Ft time_t
--.Fn time2posix "const time_t *t"
-+.Fn time2posix "time_t t"
- .Ft time_t
--.Fn posix2time "const time_t *t"
-+.Fn posix2time "time_t t"
- .Sh DESCRIPTION
- .St -p1003.1-88
- legislates that a time_t value of
---- tzfile.h.orig 2008-03-15 10:50:45.000000000 -0700
-+++ tzfile.h 2008-03-29 11:45:13.000000000 -0700
-@@ -38,7 +38,11 @@
+--- tzfile.h.orig 2010-01-15 00:06:58.000000000 -0800
++++ tzfile.h 2010-01-15 00:07:28.000000000 -0800
+@@ -38,7 +38,11 @@ static char tzfilehid[] = "@(#)tzfile.h
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES
+@@ -167,6 +171,20 @@ struct tzhead {
+
+ #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
++/*
++** Since everything in isleap is modulo 400 (or a factor of 400), we know that
++** isleap(y) == isleap(y % 400)
++** and so
++** isleap(a + b) == isleap((a + b) % 400)
++** or
++** isleap(a + b) == isleap(a % 400 + b % 400)
++** This is true even if % means modulo rather than Fortran remainder
++** (which is allowed by C89 but not C99).
++** We use this to avoid addition overflow problems.
++*/
++
++#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
++
+ #ifndef USG
+
+ /*
/*
** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+** 1996-06-05 by Arthur David Olson.
+*/
+
+/*
+** Avoid the temptation to punt entirely to strftime;
+** the output of strftime is supposed to be locale specific
+** whereas the output of asctime is supposed to be constant.
*/
#include <sys/cdefs.h>
#ifndef lint
#ifndef NOID
-static char elsieid[] __unused = "@(#)asctime.c 7.9";
+static char elsieid[] __unused = "@(#)asctime.c 8.2";
#endif /* !defined NOID */
#endif /* !defined lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/asctime.c,v 1.12 2004/06/14 10:31:52 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/asctime.c,v 1.13 2009/05/23 06:31:50 edwin Exp $");
/*LINTLIBRARY*/
#include "tzfile.h"
/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12.
+** Some systems only handle "%.2d"; others only handle "%02d";
+** "%02.2d" makes (most) everybody happy.
+** At least some versions of gcc warn about the %02.2d;
+** we conditionalize below to avoid the warning.
+*/
+/*
+** All years associated with 32-bit time_t values are exactly four digits long;
+** some years associated with 64-bit time_t values are not.
+** Vintage programs are coded for years that are always four digits long
+** and may assume that the newline always lands in the same place.
+** For years that are less than four digits, we pad the output with
+** leading zeroes to get the newline in the traditional place.
+** The -4 ensures that we get four characters of output even if
+** we call a strftime variant that produces fewer characters for some years.
+** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
+** but many implementations pad anyway; most likely the standards are buggy.
*/
+#ifdef __GNUC__
+#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
+#else /* !defined __GNUC__ */
+#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
+#endif /* !defined __GNUC__ */
+/*
+** For years that are more than four digits we put extra spaces before the year
+** so that code trying to overwrite the newline won't end up overwriting
+** a digit within a year and truncating the year (operating on the assumption
+** that no output is better than wrong output).
+*/
+#ifdef __GNUC__
+#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n"
+#else /* !defined __GNUC__ */
+#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n"
+#endif /* !defined __GNUC__ */
-#define EXPECTEDLEN 26
+#define STD_ASCTIME_BUF_SIZE 26
+/*
+** Big enough for something such as
+** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
+** (two three-character abbreviations, five strings denoting integers,
+** seven explicit spaces, two explicit colons, a newline,
+** and a trailing ASCII nul).
+** The values above are for systems where an int is 32 bits and are provided
+** as an example; the define below calculates the maximum for the system at
+** hand.
+*/
+#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1)
+
+static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
+
+/*
+** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
+*/
char *
asctime_r(const struct tm * __restrict timeptr, char * __restrict buf)
};
const char * wn;
const char * mn;
- int len;
- char tmp[EXPECTEDLEN];
+ char year[INT_STRLEN_MAXIMUM(int) + 2];
+ char result[MAX_ASCTIME_BUF_SIZE];
if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
wn = "???";
mn = "???";
else mn = mon_name[timeptr->tm_mon];
/*
- ** The X3J11-suggested format is
- ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
- ** Since the .2 in 02.2d is ignored, we drop it.
+ ** Use strftime's %Y to generate the year, to avoid overflow problems
+ ** when computing timeptr->tm_year + TM_YEAR_BASE.
+ ** Assume that strftime is unaffected by other out-of-range members
+ ** (e.g., timeptr->tm_mday) when processing "%Y".
*/
+ (void) strftime(year, sizeof year, "%Y", timeptr);
/*
- ** Because various values in the tm structure may cause the
- ** resulting string to be longer than the 26-bytes that is
- ** specified in the spec, we should return NULL rather than
- ** possibly overwrite beyond the string.
+ ** We avoid using snprintf since it's not available on all systems.
*/
- len = snprintf(tmp, EXPECTEDLEN, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
+ (void) sprintf(result,
+ ((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
wn, mn,
timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec,
- TM_YEAR_BASE + timeptr->tm_year);
- if (len >= EXPECTEDLEN)
+ year);
+ if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime) {
+ (void) strcpy(buf, result);
+ return buf;
+ } else {
+#ifdef EOVERFLOW
+ errno = EOVERFLOW;
+#else /* !defined EOVERFLOW */
+ errno = EINVAL;
+#endif /* !defined EOVERFLOW */
return NULL;
- strcpy(buf, tmp);
- return buf;
+ }
}
+/*
+** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
+*/
+
char *
asctime(timeptr)
const struct tm * timeptr;
{
- static char result[EXPECTEDLEN];
-
- return asctime_r(timeptr, result);
+ return asctime_r(timeptr, buf_asctime);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" From: @(#)ctime.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdtime/ctime.3,v 1.22 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdtime/ctime.3,v 1.24 2007/01/09 00:28:11 imp Exp $
.\"
.Dd January 2, 1999
.Dt CTIME 3
static char elsieid[] __unused = "@(#)localtime.c 7.78";
#endif /* !defined NOID */
#endif /* !defined lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.40 2004/08/24 00:15:37 peter Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.43 2008/04/01 06:56:11 davidxu Exp $");
/*
** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
+#define _RWLOCK_RDLOCK(x) \
+ do { \
+ if (__isthreaded) _pthread_rwlock_rdlock(x); \
+ } while (0)
+
+#define _RWLOCK_WRLOCK(x) \
+ do { \
+ if (__isthreaded) _pthread_rwlock_wrlock(x); \
+ } while (0)
+
+#define _RWLOCK_UNLOCK(x) \
+ do { \
+ if (__isthreaded) _pthread_rwlock_unlock(x); \
+ } while (0)
+
/*
** SunOS 4.1.1 headers lack O_BINARY.
*/
long offset,
int unix03);
__private_extern__
-void tzset_basic(void);
-
-#define lcl_mutex _st_lcl_mutex
+void tzset_basic(int);
#if !BUILDING_VARIANT
static long detzcode(const char * codep);
static char lcl_TZname[TZ_STRLEN_MAX + 1];
#ifdef NOTIFY_TZ
-#define lcl_is_set (lcl_notify.is_set)
-#define gmt_is_set (gmt_notify.is_set)
+#define lcl_is_set (lcl_notify.is_set)
+#define gmt_is_set (gmt_notify.is_set)
#else /* ! NOTIFY_TZ */
static int lcl_is_set;
static int gmt_is_set;
#endif /* NOTIFY_TZ */
-__private_extern__ pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
+__private_extern__ pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
char * tzname[2] = {
wildabbr,
settzname(void)
{
struct state * sp = lclptr;
- int i;
+ int i, need;
+ unsigned char * types;
+#define NEED_STD 1
+#define NEED_DST 2
+#define NEED_DAYLIGHT 4
+#define NEED_ALL (NEED_STD | NEED_DST | NEED_DAYLIGHT)
tzname[0] = wildabbr;
tzname[1] = wildabbr;
return;
}
#endif /* defined ALL_STATE */
- for (i = 0; i < sp->typecnt; ++i) {
- const struct ttinfo * const ttisp = &sp->ttis[i];
+ /*
+ * PR-3765457: The original settzname went sequentially through the ttis
+ * array, rather than correctly indexing via the types array, to get
+ * the real order of the timezone changes. In addition, as a speed up,
+ * we start at the end of the changes, and work back, so that most of
+ * the time, we don't have to look through the entire array.
+ */
+ if (sp->timecnt == 0 && sp->typecnt == 1) {
+ /*
+ * Unfortunately, there is an edge case when typecnt == 1 and
+ * timecnt == 0, which would cause the loop to never run. So
+ * in that case, we fudge things up so that it is as if
+ * timecnt == 1.
+ */
+ i = 0;
+ types = (unsigned char *)""; /* we use the null as index */
+ } else {
+ /* the usual case */
+ i = sp->timecnt - 1;
+ types = sp->types;
+ }
+ need = NEED_ALL;
+ for (; i >= 0 && need; --i) {
+ const struct ttinfo * const ttisp = &sp->ttis[types[i]];
- tzname[ttisp->tt_isdst] =
- &sp->chars[ttisp->tt_abbrind];
#ifdef USG_COMPAT
- if (ttisp->tt_isdst)
+ if ((need & NEED_DAYLIGHT) && ttisp->tt_isdst) {
+ need &= ~NEED_DAYLIGHT;
daylight = 1;
- if (i == 0 || !ttisp->tt_isdst)
+ }
+#endif /* defined USG_COMPAT */
+ if (ttisp->tt_isdst) {
+ if (need & NEED_DST) {
+ need &= ~NEED_DST;
+ tzname[1] = &sp->chars[ttisp->tt_abbrind];
+#ifdef ALTZONE
+ altzone = -(ttisp->tt_gmtoff);
+#endif /* defined ALTZONE */
+ }
+ } else if (need & NEED_STD) {
+ need &= ~NEED_STD;
+ tzname[0] = &sp->chars[ttisp->tt_abbrind];
+#ifdef USG_COMPAT
_st_set_timezone(-(ttisp->tt_gmtoff));
#endif /* defined USG_COMPAT */
+ }
+#if defined(ALTZONE) || defined(USG_COMPAT)
+ if (i == 0) {
+#endif /* defined(ALTZONE) || defined(USG_COMPAT) */
#ifdef ALTZONE
- if (i == 0 || ttisp->tt_isdst)
- altzone = -(ttisp->tt_gmtoff);
+ if (need & NEED_DST)
+ altzone = -(ttisp->tt_gmtoff);
#endif /* defined ALTZONE */
- }
- /*
- ** And to get the latest zone names into tzname. . .
- */
- for (i = 0; i < sp->timecnt; ++i) {
- const struct ttinfo * const ttisp =
- &sp->ttis[
- sp->types[i]];
-
- tzname[ttisp->tt_isdst] =
- &sp->chars[ttisp->tt_abbrind];
+#ifdef USG_COMPAT
+ if (need & NEED_STD)
+ _st_set_timezone(-(ttisp->tt_gmtoff));
+#endif /* defined USG_COMPAT */
+#if defined(ALTZONE) || defined(USG_COMPAT)
+ }
+#endif /* defined(ALTZONE) || defined(USG_COMPAT) */
}
}
}
static void
-tzsetwall_basic(void)
+tzsetwall_basic(int rdlocked)
{
#ifdef NOTIFY_TZ
notify_check_tz(&lcl_notify);
+#else
+ if (TZDEFAULT) {
+ static struct timespec last_mtimespec = {0, 0};
+ struct stat statbuf;
+
+ if (lstat(TZDEFAULT, &statbuf) == 0) {
+ if (statbuf.st_mtimespec.tv_sec > last_mtimespec.tv_sec ||
+ (statbuf.st_mtimespec.tv_sec == last_mtimespec.tv_sec &&
+ statbuf.st_mtimespec.tv_nsec > last_mtimespec.tv_nsec)) {
+ /* Trigger resetting the local TZ */
+ lcl_is_set = 0;
+ }
+ last_mtimespec = statbuf.st_mtimespec;
+ }
+ }
#endif /* NOTIFY_TZ */
-#ifdef NOTIFY_TZ_DEBUG
+ if (!rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
if (lcl_is_set < 0) {
+#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("tzsetwall_basic lcl_is_set < 0\n");
+#endif
+ if (!rdlocked)
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return;
}
+#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("tzsetwall_basic not set\n");
-#else /* ! NOTIFY_TZ_DEBUG */
- if (lcl_is_set < 0)
- return;
-#endif /* NOTIFY_TZ_DEBUG */
+#endif
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ _RWLOCK_WRLOCK(&lcl_rwlock);
lcl_is_set = -1;
#ifdef ALL_STATE
lclptr = (struct state *) malloc(sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
return;
}
}
notify_register_tz(fullname, &lcl_notify);
#endif /* NOTIFY_TZ */
settzname();
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
}
void
#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("tzsetwall called\n");
#endif /* NOTIFY_TZ_DEBUG */
- _MUTEX_LOCK(&lcl_mutex);
- tzsetwall_basic();
- _MUTEX_UNLOCK(&lcl_mutex);
+ tzsetwall_basic(0);
}
__private_extern__ void
-tzset_basic(void)
+tzset_basic(int rdlocked)
{
const char * name;
name = getenv("TZ");
if (name == NULL) {
- tzsetwall_basic();
+ tzsetwall_basic(rdlocked);
return;
}
#ifdef NOTIFY_TZ
notify_check_tz(&lcl_notify);
#endif /* NOTIFY_TZ */
-#ifdef NOTIFY_TZ_DEBUG
+ if (!rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
+ if (!rdlocked)
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("tzset_basic matched %s\n", lcl_TZname);
+#endif
return;
}
-#else /* ! NOTIFY_TZ_DEBUG */
- if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
- return;
-#endif /* NOTIFY_TZ_DEBUG */
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ _RWLOCK_WRLOCK(&lcl_rwlock);
lcl_is_set = strlen(name) < sizeof lcl_TZname;
if (lcl_is_set)
(void) strcpy(lcl_TZname, name);
lclptr = (struct state *) malloc(sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
return;
}
}
notify_register_tz(fullname, &lcl_notify);
#endif /* NOTIFY_TZ */
settzname();
+ _RWLOCK_UNLOCK(&lcl_rwlock);
+
+ if (rdlocked)
+ _RWLOCK_RDLOCK(&lcl_rwlock);
}
void
#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("tzset called TZ=%s\n", getenv("TZ"));
#endif /* NOTIFY_TZ_DEBUG */
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
- _MUTEX_UNLOCK(&lcl_mutex);
+ tzset_basic(0);
}
/*
struct tm *p_tm;
if (__isthreaded != 0) {
- _pthread_mutex_lock(&localtime_mutex);
if (localtime_key == (pthread_key_t)-1) {
- localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
- if (pthread_key_init_np(localtime_key, free) < 0) {
- _pthread_mutex_unlock(&localtime_mutex);
- return(NULL);
+ _pthread_mutex_lock(&localtime_mutex);
+ if (localtime_key == (pthread_key_t)-1) {
+ localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
+ if (pthread_key_init_np(localtime_key, free) < 0) {
+ _pthread_mutex_unlock(&localtime_mutex);
+ return(NULL);
+ }
}
+ _pthread_mutex_unlock(&localtime_mutex);
}
- _pthread_mutex_unlock(&localtime_mutex);
p_tm = _pthread_getspecific(localtime_key);
if (p_tm == NULL) {
if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
return(NULL);
_pthread_setspecific(localtime_key, p_tm);
}
- _pthread_mutex_lock(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
#ifdef __LP64__
p_tm = localsub(timep, 0L, p_tm);
#else /* !__LP64__ */
localsub(timep, 0L, p_tm);
#endif /* __LP64__ */
- _pthread_mutex_unlock(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return(p_tm);
} else {
- tzset_basic();
+ tzset_basic(0);
#ifdef __LP64__
return localsub(timep, 0L, &tm);
#else /* !__LP64__ */
struct tm *
localtime_r(const time_t * const __restrict timep, struct tm * __restrict tm)
{
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
#ifdef __LP64__
tm = localsub(timep, 0L, tm);
#else /* !__LP64__ */
localsub(timep, 0L, tm);
#endif /* __LP64__ */
- _MUTEX_UNLOCK(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
return tm;
}
#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("gmtsub called\n");
#endif /* NOTIFY_TZ_DEBUG */
- _MUTEX_LOCK(&gmt_mutex);
#ifdef NOTIFY_TZ
notify_check_tz(&gmt_notify);
#endif /* NOTIFY_TZ */
if (!gmt_is_set) {
- gmt_is_set = TRUE;
+ _MUTEX_LOCK(&gmt_mutex);
+ if (!gmt_is_set) {
#ifdef ALL_STATE
#ifdef NOTIFY_TZ
- if (gmtptr == NULL)
+ if (gmtptr == NULL)
#endif /* NOTIFY_TZ */
- gmtptr = (struct state *) malloc(sizeof *gmtptr);
- if (gmtptr != NULL)
+ gmtptr = (struct state *) malloc(sizeof *gmtptr);
+ if (gmtptr != NULL)
#ifdef NOTIFY_TZ
- {
+ {
#endif /* NOTIFY_TZ */
#endif /* defined ALL_STATE */
- gmtload(gmtptr);
+ gmtload(gmtptr);
#ifdef NOTIFY_TZ
- notify_register_tz(fullname, &gmt_notify);
- }
+ notify_register_tz(fullname, &gmt_notify);
+#ifdef ALL_STATE
+ }
+#endif
#endif /* NOTIFY_TZ */
+ gmt_is_set = TRUE;
+ }
+ _MUTEX_UNLOCK(&gmt_mutex);
}
- _MUTEX_UNLOCK(&gmt_mutex);
#ifdef __LP64__
if(timesub(timep, offset, gmtptr, tmp) == NULL)
return NULL;
static pthread_key_t gmtime_key = -1;
struct tm *p_tm;
-
if (__isthreaded != 0) {
- _pthread_mutex_lock(&gmtime_mutex);
if (gmtime_key == (pthread_key_t)-1) {
- gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
- if (pthread_key_init_np(gmtime_key, free) < 0) {
- _pthread_mutex_unlock(&gmtime_mutex);
- return(NULL);
+ _pthread_mutex_lock(&gmtime_mutex);
+ if (gmtime_key == (pthread_key_t)-1) {
+ gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
+ if (pthread_key_init_np(gmtime_key, free) < 0) {
+ _pthread_mutex_unlock(&gmtime_mutex);
+ return(NULL);
+ }
}
+ _pthread_mutex_unlock(&gmtime_mutex);
}
- _pthread_mutex_unlock(&gmtime_mutex);
/*
* Changed to follow POSIX.1 threads standard, which
* is what BSD currently has.
if (tmp->tm_wday < 0)
tmp->tm_wday += DAYSPERWEEK;
y = EPOCH_YEAR;
-#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
+#define _LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
+#ifdef __LP64__
+#define LEAPS_THRU_END_OF(y) ((y) >= 0 ? _LEAPS_THRU_END_OF(y) : _LEAPS_THRU_END_OF((y) + 1) - 1)
+#else /* !__LP64__ */
+#define LEAPS_THRU_END_OF(y) _LEAPS_THRU_END_OF(y)
+#endif /* __LP64__ */
while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
long newy;
{
int result;
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+ /*
+ * Assume that atmp and btmp point to normalized tm strutures.
+ * So only arithmetic with tm_year could overflow in 64-bit.
+ */
+ if (atmp->tm_year != btmp->tm_year) {
+ return (atmp->tm_year > btmp->tm_year ? 1 : -1);
+ }
+ if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
bits = TYPE_BIT(time_t) - 1;
#endif /* __LP64__ */
/*
- ** If we have more than this, we will overflow tm_year for tmcomp().
- ** We should really return an error if we cannot represent it.
+ ** In 64-bit, we now return an error if we cannot represent the
+ ** struct tm value in a time_t. And tmcomp() is fixed to avoid
+ ** overflow in tm_year. So we only put a cap on bits because time_t
+ ** can't be larger that 56 bit (when tm_year == INT_MAX).
*/
if (bits > 56)
bits = 56;
return WRONG;
}
#else /* BUILDING_VARIANT */
-__private_extern__ pthread_mutex_t lcl_mutex;
+__private_extern__ pthread_rwlock_t lcl_rwlock;
#endif /* BUILDING_VARIANT */
time_t
{
time_t mktime_return_value;
int serrno = errno;
- _MUTEX_LOCK(&lcl_mutex);
- tzset_basic();
+ _RWLOCK_RDLOCK(&lcl_rwlock);
+ tzset_basic(1);
mktime_return_value = time1(tmp, localsub, 0L, __DARWIN_UNIX03);
- _MUTEX_UNLOCK(&lcl_mutex);
+ _RWLOCK_UNLOCK(&lcl_rwlock);
errno = serrno;
return(mktime_return_value);
}
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
+ * by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
#ifndef lint
#ifndef NOID
-static const char elsieid[] = "@(#)strftime.c 7.64";
+static const char elsieid[] = "@(#)strftime.3 8.3";
/*
** Based on the UCB version with the ID appearing below.
** This is ANSIish only when "multibyte character == plain character".
static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.40 2004/06/14 10:31:52 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/strftime.c,v 1.44 2009/06/09 09:02:58 delphij Exp $");
#include "tzfile.h"
#include <time.h>
#if !BUILDING_VARIANT
static char * _add(const char *, char *, const char *);
static char * _conv(int, const char *, char *, const char *, locale_t);
-#endif /* !BUILDING_VARIANT */
+static char * _yconv(int, int, int, int, char *, const char *, locale_t);
+#endif
#define _fmt _st_fmt
-__private_extern__ char *_fmt(const char *, const struct tm *, char *, const char *, int *, struct lc_time_T *, locale_t);
-
-size_t strftime(char * __restrict, size_t, const char * __restrict,
- const struct tm * __restrict);
+__private_extern__ char * _fmt(const char *, const struct tm *, char *, const char *,
+ int *, struct lc_time_T *, locale_t);
extern char * tzname[];
__private_extern__ long __darwin_altzone; /* DST timezone offset */
#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
#endif /* !defined YEAR_2000_NAME */
-
#define IN_NONE 0
#define IN_SOME 1
#define IN_THIS 2
#define IN_ALL 3
+#define PAD_DEFAULT 0
+#define PAD_LESS 1
+#define PAD_SPACE 2
+#define PAD_ZERO 3
+
+#ifndef BUILDING_VARIANT
+static const char* fmt_padding[][4] = {
+ /* DEFAULT, LESS, SPACE, ZERO */
+#define PAD_FMT_MONTHDAY 0
+#define PAD_FMT_HMS 0
+#define PAD_FMT_CENTURY 0
+#define PAD_FMT_SHORTYEAR 0
+#define PAD_FMT_MONTH 0
+#define PAD_FMT_WEEKOFYEAR 0
+#define PAD_FMT_DAYOFMONTH 0
+ { "%02d", "%d", "%2d", "%02d" },
+#define PAD_FMT_SDAYOFMONTH 1
+#define PAD_FMT_SHMS 1
+ { "%2d", "%d", "%2d", "%02d" },
+#define PAD_FMT_DAYOFYEAR 2
+ { "%03d", "%d", "%3d", "%03d" },
+#define PAD_FMT_YEAR 3
+ { "%04d", "%d", "%4d", "%04d" }
+};
+#endif
+
+#define USG_COMPAT
+#define ALTZONE
+
size_t
strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format,
const struct tm * __restrict t, locale_t loc)
{
char * p;
int warn;
-#if __DARWIN_UNIX03
- struct tm t2;
-#endif /* __DARWIN_UNIX03 */
NORMALIZE_LOCALE(loc);
tzset();
warn = IN_NONE;
-#if __DARWIN_UNIX03
- if (t->tm_isdst >= 0) {
- t2 = *t;
- t2.tm_gmtoff = t->tm_isdst ? -__darwin_altzone : -_st_get_timezone();
- t = &t2;
- }
-#endif /* __DARWIN_UNIX03 */
p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, __get_current_time_locale(loc), loc);
#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
struct lc_time_T * tptr;
locale_t loc;
{
- int Ealternative, Oalternative;
+ int Ealternative, Oalternative, PadIndex;
for ( ; *format; ++format) {
if (*format == '%') {
Ealternative = 0;
Oalternative = 0;
+ PadIndex = PAD_DEFAULT;
label:
switch (*++format) {
case '\0':
case 'C':
/*
** %C used to do a...
- ** _fmt("%a %b %e %X %Y", t);
+ ** _fmt("%a %b %e %X %Y", t, tptr, loc);
** ...whereas now POSIX 1003.2 calls for
** something completely different.
** (ado, 1993-05-24)
*/
- pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
- "%02d", pt, ptlim, loc);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+ pt, ptlim, loc);
continue;
case 'c':
{
int warn2 = IN_SOME;
- pt = _fmt(tptr->c_fmt, t, pt, ptlim, warnp, tptr, loc);
+ pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, tptr, loc);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, tptr, loc);
continue;
case 'd':
- pt = _conv(t->tm_mday, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex],
+ pt, ptlim, loc);
continue;
case 'E':
if (Ealternative || Oalternative)
Oalternative++;
goto label;
case 'e':
- pt = _conv(t->tm_mday, "%2d", pt, ptlim, loc);
+ pt = _conv(t->tm_mday,
+ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim, loc);
continue;
case 'F':
pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, tptr, loc);
continue;
case 'H':
- pt = _conv(t->tm_hour, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim, loc);
continue;
case 'I':
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
- "%02d", pt, ptlim, loc);
+ fmt_padding[PAD_FMT_HMS][PadIndex], pt, ptlim, loc);
continue;
case 'j':
- pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim, loc);
+ pt = _conv(t->tm_yday + 1,
+ fmt_padding[PAD_FMT_DAYOFYEAR][PadIndex], pt, ptlim, loc);
continue;
case 'k':
/*
** This used to be...
** _conv(t->tm_hour % 12 ?
- ** t->tm_hour % 12 : 12, 2, ' ');
+ ** t->tm_hour % 12 : 12, 2, ' ', loc);
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbins'
- ** strftime version 3.0. That is, "%k" and
+ ** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
- pt = _conv(t->tm_hour, "%2d", pt, ptlim, loc);
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_SHMS][PadIndex],
+ pt, ptlim, loc);
continue;
#ifdef KITCHEN_SINK
case 'K':
** _conv(t->tm_hour, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbin's
- ** strftime version 3.0. That is, "%k" and
+ ** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
- "%2d", pt, ptlim, loc);
+ fmt_padding[PAD_FMT_SHMS][PadIndex], pt, ptlim, loc);
continue;
case 'M':
- pt = _conv(t->tm_min, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_min, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim, loc);
continue;
case 'm':
- pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_mon + 1,
+ fmt_padding[PAD_FMT_MONTH][PadIndex], pt, ptlim, loc);
continue;
case 'n':
pt = _add("\n", pt, ptlim);
warnp, tptr, loc);
continue;
case 'S':
- pt = _conv(t->tm_sec, "%02d", pt, ptlim, loc);
+ pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim, loc);
continue;
case 's':
{
case 'U':
pt = _conv((t->tm_yday + DAYSPERWEEK -
t->tm_wday) / DAYSPERWEEK,
- "%02d", pt, ptlim, loc);
+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim, loc);
continue;
case 'u':
/*
case 'G': /* ISO 8601 year (four digits) */
case 'g': /* ISO 8601 year (two digits) */
/*
-** From Arnold Robbins' strftime version 3.0: "the week number of the
+** From Arnold Robbins' strftime version 3.0: "the week number of the
** year (the first Monday as the first day of week 1) as a decimal number
** (01-53)."
** (ado, 1993-05-24)
** might also contain days from the previous year and the week before week
** 01 of a year is the last week (52 or 53) of the previous year even if
** it contains days from the new year. A week starts with Monday (day 1)
-** and ends with Sunday (day 7). For example, the first week of the year
+** and ends with Sunday (day 7). For example, the first week of the year
** 1997 lasts from 1996-12-30 to 1997-01-05..."
** (ado, 1996-01-02)
*/
{
int year;
+ int base;
int yday;
int wday;
int w;
- year = t->tm_year + TM_YEAR_BASE;
+ year = t->tm_year;
+ base = TM_YEAR_BASE;
yday = t->tm_yday;
wday = t->tm_wday;
for ( ; ; ) {
int bot;
int top;
- len = isleap(year) ?
+ len = isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
/*
top += DAYSPERWEEK;
top += len;
if (yday >= top) {
- ++year;
+ ++base;
w = 1;
break;
}
DAYSPERWEEK);
break;
}
- --year;
- yday += isleap(year) ?
+ --base;
+ yday += isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
}
#ifdef XPG4_1994_04_09
- if ((w == 52
- && t->tm_mon == TM_JANUARY)
- || (w == 1
- && t->tm_mon == TM_DECEMBER))
- w = 53;
+ if ((w == 52 &&
+ t->tm_mon == TM_JANUARY) ||
+ (w == 1 &&
+ t->tm_mon == TM_DECEMBER))
+ w = 53;
#endif /* defined XPG4_1994_04_09 */
if (*format == 'V')
- pt = _conv(w, "%02d",
+ pt = _conv(w, fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],
pt, ptlim, loc);
else if (*format == 'g') {
*warnp = IN_ALL;
- pt = _conv(year % 100, "%02d",
+ pt = _yconv(year, base, 0, 1,
pt, ptlim, loc);
- } else pt = _conv(year, "%04d",
+ } else pt = _yconv(year, base, 1, 1,
pt, ptlim, loc);
}
continue;
(t->tm_wday ?
(t->tm_wday - 1) :
(DAYSPERWEEK - 1))) / DAYSPERWEEK,
- "%02d", pt, ptlim, loc);
+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim, loc);
continue;
case 'w':
pt = _conv(t->tm_wday, "%d", pt, ptlim, loc);
continue;
case 'y':
*warnp = IN_ALL;
- pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
- "%02d", pt, ptlim, loc);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+ pt, ptlim, loc);
continue;
case 'Y':
- pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
pt, ptlim, loc);
continue;
case 'Z':
if (t->tm_isdst < 0)
continue;
-#ifdef TM_GMTOFF
+#if defined(TM_GMTOFF) && !__DARWIN_UNIX03
diff = t->TM_GMTOFF;
-#else /* !defined TM_GMTOFF */
+#else /* !defined TM_GMTOFF || __DARWIN_UNIX03 */
/*
** C99 says that the UTC offset must
** be computed by looking only at
- ** tm_isdst. This requirement is
+ ** tm_isdst. This requirement is
** incorrect, since it means the code
** must rely on magic (in this case
** altzone and timezone), and the
** magic might not have the correct
- ** offset. Doing things correctly is
+ ** offset. Doing things correctly is
** tricky and requires disobeying C99;
** see GNU C strftime for details.
** For now, punt and conform to the
#else /* !defined ALTZONE */
continue;
#endif /* !defined ALTZONE */
-#endif /* !defined TM_GMTOFF */
+#endif /* !defined TM_GMTOFF || __DARWIN_UNIX03 */
if (diff < 0) {
sign = "-";
diff = -diff;
} else sign = "+";
pt = _add(sign, pt, ptlim);
- diff /= 60;
- pt = _conv((diff/60)*100 + diff%60,
- "%04d", pt, ptlim, loc);
+ diff /= SECSPERMIN;
+ diff = (diff / MINSPERHOUR) * 100 +
+ (diff % MINSPERHOUR);
+ pt = _conv(diff,
+ fmt_padding[PAD_FMT_YEAR][PadIndex], pt, ptlim, loc);
}
continue;
case '+':
pt = _fmt(tptr->date_fmt, t, pt, ptlim,
warnp, tptr, loc);
continue;
+ case '-':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_LESS;
+ goto label;
+ case '_':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_SPACE;
+ goto label;
+ case '0':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_ZERO;
+ goto label;
case '%':
/*
** X311J/88-090 (4.12.3.5): if conversion char is
- ** undefined, behavior is undefined. Print out the
+ ** undefined, behavior is undefined. Print out the
** character itself as printf(3) also does.
*/
default:
++pt;
return pt;
}
+
+/*
+** POSIX and the C Standard are unclear or inconsistent about
+** what %C and %y do if the year is negative or exceeds 9999.
+** Use the convention that %C concatenated with %y yields the
+** same output as %Y, and that %Y contains at least 4 bytes,
+** with more only if necessary.
+*/
+
+static char *
+_yconv(a, b, convert_top, convert_yy, pt, ptlim, loc)
+const int a;
+const int b;
+const int convert_top;
+const int convert_yy;
+char * pt;
+const char * const ptlim;
+locale_t loc;
+{
+ register int lead;
+ register int trail;
+
+#define DIVISOR 100
+ trail = a % DIVISOR + b % DIVISOR;
+ lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
+ trail %= DIVISOR;
+ if (trail < 0 && lead > 0) {
+ trail += DIVISOR;
+ --lead;
+ } else if (lead < 0 && trail > 0) {
+ trail -= DIVISOR;
+ ++lead;
+ }
+ if (convert_top) {
+ if (lead == 0 && trail < 0)
+ pt = _add("-0", pt, ptlim);
+ else pt = _conv(lead, "%02d", pt, ptlim, loc);
+ }
+ if (convert_yy)
+ pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim, loc);
+ return pt;
+}
#endif /* !BUILDING_VARIANT */
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strftime.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdtime/strftime.3,v 1.34 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdtime/strftime.3,v 1.40 2008/05/16 04:33:04 grog Exp $
.\"
-.Dd January 4, 2003
+.Dd November 4, 2004
.Dt STRFTIME 3
.Os
.Sh NAME
.Dq Li %m/%d/%y .
.It Cm %d
is replaced by the day of the month as a decimal number (01-31).
-.It Cm \&%E* Cm \&%O*
+.It Cm %E* %O*
POSIX locale extensions.
The sequences
%Ec %EC %Ex %EX %Ey %EY
are supposed to provide alternate
representations.
.Pp
-Additionly %OB implemented
+Additionally %OB implemented
to represent alternative months names
(used standalone, without day mentioned).
.It Cm %e
-is replaced by the day of month as a decimal number (1-31); single
+is replaced by the day of the month as a decimal number (1-31); single
digits are preceded by a blank.
.It Cm \&%F
is equivalent to
.It Cm \&%H
is replaced by the hour (24-hour clock) as a decimal number (00-23).
.It Cm %h
-the same as %b.
+the same as
+.Cm %b .
.It Cm \&%I
is replaced by the hour (12-hour clock) as a decimal number (01-12).
.It Cm %j
is replaced by the month as a decimal number (01-12).
.It Cm %n
is replaced by a newline.
-.It Cm \&%O*
-the same as %E*.
+.It Cm %O*
+the same as
+.Cm %E* .
.It Cm %p
is replaced by national representation of either
-"ante meridiem"
+"ante meridiem" (a.m.)
or
-"post meridiem"
+"post meridiem" (p.m.)
as appropriate.
.It Cm \&%R
is equivalent to
is replaced by the year without century as a decimal number (00-99).
.It Cm \&%Z
is replaced by the time zone name.
-.It Cm \&%z
+.It Cm %z
is replaced by the time zone offset from UTC; a leading plus sign stands for
east of UTC, a minus sign for west of UTC, hours and minutes follow
with two digits each and no delimiter between them (common form for
is replaced by national representation of the date and time
(the format is similar to that produced by
.Xr date 1 ) .
+.It Cm %-*
+GNU libc extension.
+Do not do any padding when performing numerical outputs.
+.It Cm %_*
+GNU libc extension.
+Explicitly specify space for padding.
+.It Cm %0*
+GNU libc extension.
+Explicitly specify zero for padding.
.It Cm %%
is replaced by
.Ql % .
static char sccsid[] __unused = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
#endif /* !defined NOID */
#endif /* not lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.37 2009/09/02 04:56:30 ache Exp $");
#include "xlocale_private.h"
#include "libc_private.h"
#include "timelocal.h"
-static char * _strptime(const char *, const char *, struct tm *, int *, locale_t) __DARWIN_ALIAS(_strptime);
time_t _mktime(struct tm *, const char *);
#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
while (isspace_l((unsigned char)*ptr, loc)) {
ptr++;
}
- return ((*ptr)==0) ? fmt : 0; /* trailing whitespace is ok */
+ return ((*ptr)==0) ? (char *)fmt : 0; /* trailing whitespace is ok */
}
c = *ptr++;
case 'z':
{
- char sign;
- int hr, min;
-
- if ((buf[0] != '+' && buf[0] != '-')
- || !isdigit_l((unsigned char)buf[1], loc)
- || !isdigit_l((unsigned char)buf[2], loc)
- || !isdigit_l((unsigned char)buf[3], loc)
- || !isdigit_l((unsigned char)buf[4], loc))
- return 0;
- sscanf(buf, "%c%2d%2d", &sign, &hr, &min);
- *convp = CONVERT_ZONE;
- tm->tm_gmtoff = 60 * (60 * hr + min);
- if (sign == '-')
- tm->tm_gmtoff = -tm->tm_gmtoff;
- buf += 5;
+ int sign = 1;
+
+ if (*buf != '+') {
+ if (*buf == '-')
+ sign = -1;
+ else
+ return 0;
+ }
+
+ buf++;
+ i = 0;
+ for (len = 4; len > 0; len--) {
+ if (isdigit_l((unsigned char)*buf, loc)) {
+ i *= 10;
+ i += *buf - '0';
+ buf++;
+ } else
+ return 0;
+ }
+
+ tm->tm_hour -= sign * (i / 100);
+ tm->tm_min -= sign * (i % 100);
+ *convp = CONVERT_GMT;
}
break;
}
.\" (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/libc/stdtime/strptime.3,v 1.23 2004/07/02 23:52:12 ru Exp $
+.\" $FreeBSD: src/lib/libc/stdtime/strptime.3,v 1.24 2005/01/20 09:17:04 ru Exp $
.\" "
.Dd January 4, 2003
.Dt STRPTIME 3
.Xr scanf 3 ,
.Xr strftime 3 ,
.Xr xlocale 3
+.Sh HISTORY
+The
+.Fn strptime
+function appeared in
+.Fx 3.0 .
.Sh AUTHORS
The
.Fn strptime
.Pp
This man page was written by
.An J\(:org Wunsch .
-.Sh HISTORY
-The
-.Fn strptime
-function appeared in
-.Fx 3.0 .
.Sh BUGS
Both the
.Fa %e
+++ /dev/null
-.\" $FreeBSD: src/lib/libc/stdtime/time2posix.3,v 1.13 2001/10/01 16:08:59 ru Exp $
-.\"
-.Dd May 1, 1996
-.Dt TIME2POSIX 3
-.Os
-.Sh NAME
-.Nm time2posix ,
-.Nm posix2time
-.Nd convert seconds since the Epoch
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In time.h
-.Ft time_t
-.Fn time2posix "time_t t"
-.Ft time_t
-.Fn posix2time "time_t t"
-.Sh DESCRIPTION
-.St -p1003.1-88
-legislates that a time_t value of
-536457599 shall correspond to "Wed Dec 31 23:59:59 GMT 1986."
-This effectively implies that POSIX time_t's cannot include leap
-seconds and,
-therefore,
-that the system time must be adjusted as each leap occurs.
-.Pp
-If the time package is configured with leap-second support
-enabled,
-however,
-no such adjustment is needed and
-time_t values continue to increase over leap events
-(as a true `seconds since...' value).
-This means that these values will differ from those required by POSIX
-by the net number of leap seconds inserted since the Epoch.
-.Pp
-Typically this is not a problem as the type time_t is intended
-to be
-(mostly)
-opaque\(emtime_t values should only be obtained-from and
-passed-to functions such as
-.Xr time 3 ,
-.Xr localtime 3 ,
-.Xr mktime 3
-and
-.Xr difftime 3 .
-However,
-.St -p1003.1-88
-gives an arithmetic
-expression for directly computing a time_t value from a given date/time,
-and the same relationship is assumed by some
-(usually older)
-applications.
-Any programs creating/dissecting time_t's
-using such a relationship will typically not handle intervals
-over leap seconds correctly.
-.Pp
-The
-.Fn time2posix
-and
-.Fn posix2time
-functions are provided to address this time_t mismatch by converting
-between local time_t values and their POSIX equivalents.
-This is done by accounting for the number of time-base changes that
-would have taken place on a POSIX system as leap seconds were inserted
-or deleted.
-These converted values can then be used in lieu of correcting the older
-applications,
-or when communicating with POSIX-compliant systems.
-.Pp
-The
-.Fn time2posix
-function is single-valued.
-That is,
-every local time_t
-corresponds to a single POSIX time_t.
-The
-.Fn posix2time
-function is less well-behaved:
-for a positive leap second hit the result is not unique,
-and for a negative leap second hit the corresponding
-POSIX time_t doesn't exist so an adjacent value is returned.
-Both of these are good indicators of the inferiority of the
-POSIX representation.
-.Pp
-The following table summarizes the relationship between time_t
-and its conversion to,
-and back from,
-the POSIX representation over the leap second inserted at the end of June,
-1993.
-.Bl -column "93/06/30" "23:59:59" "A+0" "X=time2posix(T)"
-.It Sy "DATE TIME T X=time2posix(T) posix2time(X)"
-.It "93/06/30 23:59:59 A+0 B+0 A+0"
-.It "93/06/30 23:59:60 A+1 B+1 A+1 or A+2"
-.It "93/07/01 00:00:00 A+2 B+1 A+1 or A+2"
-.It "93/07/01 00:00:01 A+3 B+2 A+3"
-.El
-.Pp
-A leap second deletion would look like...
-.Bl -column "??/06/30" "23:59:58" "A+0" "X=time2posix(T)"
-.It Sy "DATE TIME T X=time2posix(T) posix2time(X)"
-.It "??/06/30 23:59:58 A+0 B+0 A+0"
-.It "??/07/01 00:00:00 A+1 B+2 A+1"
-.It "??/07/01 00:00:01 A+2 B+3 A+2"
-.El
-.Pp
-.D1 No "[Note: posix2time(B+1) => A+0 or A+1]"
-.Pp
-If leap-second support is not enabled,
-local time_t's and
-POSIX time_t's are equivalent,
-and both
-.Fn time2posix
-and
-.Fn posix2time
-degenerate to the identity function.
-.Sh "SEE ALSO"
-.Xr difftime 3 ,
-.Xr localtime 3 ,
-.Xr mktime 3 ,
-.Xr time 3
--- /dev/null
+./time2posix.3
\ No newline at end of file
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+/*
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+** isleap(y) == isleap(y % 400)
+** and so
+** isleap(a + b) == isleap((a + b) % 400)
+** or
+** isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not C99).
+** We use this to avoid addition overflow problems.
+*/
+
+#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
+
#ifndef USG
/*
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bcmp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bcmp.3,v 1.10 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bcmp.3,v 1.11 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BCMP 3
---- _SB/Libc/string/FreeBSD/bcmp.3 2004-11-25 11:38:46.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/bcmp.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -45,18 +45,18 @@
+--- bcmp.3.bsdnew 2009-11-18 18:24:31.000000000 -0800
++++ bcmp.3 2009-11-18 18:24:31.000000000 -0800
+@@ -41,18 +41,18 @@
.Sh SYNOPSIS
.In strings.h
.Ft int
* 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.
static char sccsid[] = "@(#)bcmp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/bcmp.c,v 1.5 2002/08/30 21:07:40 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/bcmp.c,v 1.6 2007/01/09 00:28:11 imp Exp $");
#include <strings.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bcopy.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bcopy.3,v 1.9 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bcopy.3,v 1.10 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BCOPY 3
---- _SB/Libc/string/FreeBSD/bcopy.3 2004-11-25 11:38:46.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/bcopy.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -46,20 +46,20 @@
+--- bcopy.3.bsdnew 2009-11-18 18:24:32.000000000 -0800
++++ bcopy.3 2009-11-18 18:24:32.000000000 -0800
+@@ -42,20 +42,20 @@
.Sh SYNOPSIS
.In strings.h
.Ft void
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bstring.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bstring.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bstring.3,v 1.8 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BSTRING 3
---- bstring.3 2003-05-20 15:23:54.000000000 -0700
-+++ bstring.3.edit 2006-07-12 10:55:13.000000000 -0700
-@@ -51,33 +51,76 @@
+--- bstring.3.bsdnew 2009-11-18 18:24:32.000000000 -0800
++++ bstring.3 2009-11-18 18:24:32.000000000 -0800
+@@ -47,33 +47,76 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.Sh SEE ALSO
.Xr bcmp 3 ,
.Xr bcopy 3 ,
-@@ -87,7 +130,8 @@
+@@ -83,7 +126,8 @@ See the specific manual pages for more i
.Xr memcmp 3 ,
.Xr memcpy 3 ,
.Xr memmove 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bzero.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bzero.3,v 1.9 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bzero.3,v 1.10 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BZERO 3
---- _SB/Libc/string/FreeBSD/bzero.3 2004-11-25 11:38:46.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/bzero.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -46,17 +46,17 @@
+--- bzero.3.bsdnew 2009-11-18 18:24:32.000000000 -0800
++++ bzero.3 2009-11-18 18:24:32.000000000 -0800
+@@ -42,17 +42,17 @@
.Sh SYNOPSIS
.In strings.h
.Ft void
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ffs.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/string/ffs.3,v 1.9 2004/06/30 20:09:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/ffs.3,v 1.13 2009/01/13 13:19:42 kib Exp $
.\"
-.Dd January 13, 2004
+.Dd October 26, 2008
.Dt FFS 3
.Os
.Sh NAME
.Nm ffs ,
.Nm ffsl ,
+.Nm ffsll ,
.Nm fls ,
-.Nm flsl
+.Nm flsl ,
+.Nm flsll
.Nd find first or last bit set in a bit string
.Sh LIBRARY
.Lb libc
.Ft int
.Fn ffsl "long value"
.Ft int
+.Ft int
+.Fn ffsll "long long value"
.Fn fls "int value"
.Ft int
.Fn flsl "long value"
+.Ft int
+.Fn flsll "long long value"
.Sh DESCRIPTION
The
-.Fn ffs
-and
+.Fn ffs ,
.Fn ffsl
-functions find the first bit set in
+and
+.Fn ffsll
+functions find the first bit set
+(beginning with the least significant bit)
+in
.Fa value
and return the index of that bit.
.Pp
The
-.Fn fls
-and
+.Fn fls ,
.Fn flsl
+and
+.Fn flsll
functions find the last bit set in
.Fa value
and return the index of that bit.
.Pp
-Bits are numbered starting from 1, starting at the right-most
-(least significant) bit.
+Bits are numbered starting at 1 (the least significant bit).
A return value of zero from any of these functions means that the
argument was zero.
.Sh SEE ALSO
.Fn flsl
functions appeared in
.Fx 5.3 .
+The
+.Fn ffsll
+and
+.Fn flsll
+functions appeared in
+.Fx 7.1 .
---- _SB/Libc/string/FreeBSD/ffs.3 2004-11-25 11:38:46.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/ffs.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -48,20 +48,20 @@
+--- ffs.3.bsdnew 2009-11-30 13:52:21.000000000 -0800
++++ ffs.3 2009-11-30 13:56:29.000000000 -0800
+@@ -36,46 +36,38 @@
+ .Sh NAME
+ .Nm ffs ,
+ .Nm ffsl ,
+-.Nm ffsll ,
+ .Nm fls ,
+-.Nm flsl ,
+-.Nm flsll
++.Nm flsl
+ .Nd find first or last bit set in a bit string
+ .Sh LIBRARY
+ .Lb libc
.Sh SYNOPSIS
.In strings.h
.Ft int
-.Fn ffsl "long value"
+.Fn ffsl "long i"
.Ft int
--.Fn fls "int value"
+.Fn fls "int i"
.Ft int
+-.Fn ffsll "long long value"
+-.Fn fls "int value"
+-.Ft int
-.Fn flsl "long value"
+-.Ft int
+-.Fn flsll "long long value"
+.Fn flsl "long i"
.Sh DESCRIPTION
The
- .Fn ffs
+-.Fn ffs ,
+-.Fn ffsl
++.Fn ffs
and
- .Fn ffsl
- functions find the first bit set in
+-.Fn ffsll
++.Fn ffsl
+ functions find the first bit set
+ (beginning with the least significant bit)
+ in
-.Fa value
+.Fa i
and return the index of that bit.
.Pp
The
-@@ -69,7 +69,7 @@
+-.Fn fls ,
+-.Fn flsl
++.Fn fls
and
- .Fn flsl
+-.Fn flsll
++.Fn flsl
functions find the last bit set in
-.Fa value
+.Fa i
and return the index of that bit.
.Pp
- Bits are numbered starting from 1, starting at the right-most
-@@ -93,7 +93,7 @@
+ Bits are numbered starting at 1 (the least significant bit).
+@@ -98,14 +90,8 @@ compliance.
.Pp
The
.Fn ffsl ,
and
.Fn flsl
functions appeared in
+ .Fx 5.3 .
+-The
+-.Fn ffsll
+-and
+-.Fn flsll
+-functions appeared in
+-.Fx 7.1 .
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)index.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/index.3,v 1.11 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/index.3,v 1.12 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt INDEX 3
---- _SB/Libc/string/FreeBSD/index.3 2004-11-25 11:38:46.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/index.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -58,8 +58,8 @@
+--- index.3.bsdnew 2009-11-18 18:24:32.000000000 -0800
++++ index.3 2009-11-18 18:24:32.000000000 -0800
+@@ -54,8 +54,8 @@ locates the first occurrence of
.Vt char )
in the string pointed to by
.Fa s .
.Fa c
is
.Ql \e0 ,
-@@ -70,7 +70,7 @@
+@@ -66,7 +66,7 @@ The
.Fn rindex
function is identical to
.Fn index ,
* 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.
static char sccsid[] = "@(#)index.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/index.c,v 1.7 2003/12/18 07:44:53 jkh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/index.c,v 1.8 2007/01/09 00:28:12 imp Exp $");
#include <stddef.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memccpy.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/memccpy.3,v 1.6 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memccpy.3,v 1.7 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 9, 1993
.Dt MEMCCPY 3
---- memccpy.3.orig 2008-02-29 10:45:52.000000000 -0800
-+++ memccpy.3 2008-02-29 12:03:32.000000000 -0800
-@@ -43,27 +43,35 @@
+--- memccpy.3.bsdnew 2009-11-18 18:24:32.000000000 -0800
++++ memccpy.3 2009-11-18 18:24:32.000000000 -0800
+@@ -39,27 +39,35 @@
.Sh SYNOPSIS
.In string.h
.Ft void *
* 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.
static char sccsid[] = "@(#)memccpy.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/memccpy.c,v 1.5 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/memccpy.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
void *
-memccpy(t, f, c, n)
- void *t;
- const void *f;
- int c;
- size_t n;
+memccpy(void *t, const void *f, int c, size_t n)
{
if (n) {
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memchr.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memchr.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memchr.3,v 1.12 2009/04/23 08:37:56 brueffer Exp $
.\"
-.Dd June 4, 1993
+.Dd April 9, 2008
.Dt MEMCHR 3
.Os
.Sh NAME
.In string.h
.Ft void *
.Fn memchr "const void *b" "int c" "size_t len"
+.Ft void *
+.Fn memrchr "const void *b" "int c" "size_t len"
.Sh DESCRIPTION
The
.Fn memchr
(converted to an unsigned char)
in string
.Fa b .
+.Pp
+The
+.Fn memrchr
+function behaves like
+.Fn memchr ,
+except that it locates the last occurrence of
+.Fa c
+in string
+.Fa b .
.Sh RETURN VALUES
The
.Fn memchr
-function
-returns a pointer to the byte located,
+and
+.Fn memrchr
+functions
+return a pointer to the byte located,
or NULL if no such byte exists within
.Fa len
bytes.
.Sh SEE ALSO
+.Xr memmem 3 ,
.Xr strchr 3 ,
.Xr strcspn 3 ,
.Xr strpbrk 3 ,
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wmemchr 3
.Sh STANDARDS
The
.Fn memchr
function
conforms to
.St -isoC .
+.Pp
+The
+.Fn memrchr
+function is a GNU extension and conforms to no standard.
+.Sh HISTORY
+The
+.Fn memrchr
+function first appeared in GNU libc 2.1.91, this implementation
+first appeared in
+.Fx 6.4 ,
+coming from
+.Ox 4.3 .
---- _SB/Libc/string/FreeBSD/memchr.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/memchr.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,7 +47,11 @@
+--- memchr.3.bsdnew 2009-11-30 13:52:21.000000000 -0800
++++ memchr.3 2009-11-30 14:18:10.000000000 -0800
+@@ -43,9 +43,11 @@
.Sh SYNOPSIS
.In string.h
.Ft void *
-.Fn memchr "const void *b" "int c" "size_t len"
+-.Ft void *
+-.Fn memrchr "const void *b" "int c" "size_t len"
+.Fo memchr
+.Fa "const void *s"
+.Fa "int c"
.Sh DESCRIPTION
The
.Fn memchr
-@@ -56,14 +60,14 @@
+@@ -54,28 +56,16 @@ locates the first occurrence of
.Fa c
(converted to an unsigned char)
in string
-.Fa b .
+-.Pp
+-The
+-.Fn memrchr
+-function behaves like
+-.Fn memchr ,
+-except that it locates the last occurrence of
+-.Fa c
+-in string
+-.Fa b .
+.Fa s .
.Sh RETURN VALUES
The
.Fn memchr
- function
- returns a pointer to the byte located,
+-and
+-.Fn memrchr
+-functions
+-return a pointer to the byte located,
++function
++returns a pointer to the byte located,
or NULL if no such byte exists within
-.Fa len
+.Fa n
bytes.
.Sh SEE ALSO
+-.Xr memmem 3 ,
.Xr strchr 3 ,
+ .Xr strcspn 3 ,
+ .Xr strpbrk 3 ,
+@@ -91,15 +81,3 @@ The
+ function
+ conforms to
+ .St -isoC .
+-.Pp
+-The
+-.Fn memrchr
+-function is a GNU extension and conforms to no standard.
+-.Sh HISTORY
+-The
+-.Fn memrchr
+-function first appeared in GNU libc 2.1.91, this implementation
+-first appeared in
+-.Fx 6.4 ,
+-coming from
+-.Ox 4.3 .
* 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.
static char sccsid[] = "@(#)memchr.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/memchr.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/memchr.c,v 1.8 2009/02/07 19:34:44 imp Exp $");
#include <string.h>
void *
-memchr(s, c, n)
- const void *s;
- unsigned char c;
- size_t n;
+memchr(const void *s, int c, size_t n)
{
if (n != 0) {
const unsigned char *p = s;
do {
- if (*p++ == c)
+ if (*p++ == (unsigned char)c)
return ((void *)(p - 1));
} while (--n != 0);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memcmp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memcmp.3,v 1.8 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memcmp.3,v 1.10 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMCMP 3
.Xr strcasecmp 3 ,
.Xr strcmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wmemcmp 3
.Sh STANDARDS
The
.Fn memcmp
---- _SB/Libc/string/FreeBSD/memcmp.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/memcmp.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,17 +47,21 @@
+--- memcmp.3.bsdnew 2009-11-18 18:24:32.000000000 -0800
++++ memcmp.3 2009-11-18 18:24:32.000000000 -0800
+@@ -43,17 +43,21 @@
.Sh SYNOPSIS
.In string.h
.Ft int
* 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.
static char sccsid[] = "@(#)memcmp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/memcmp.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/memcmp.c,v 1.6 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
* Compare memory regions.
*/
int
-memcmp(s1, s2, n)
- const void *s1, *s2;
- size_t n;
+memcmp(const void *s1, const void *s2, size_t n)
{
if (n != 0) {
const unsigned char *p1 = s1, *p2 = s2;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memcpy.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memcpy.3,v 1.7 2002/01/07 06:03:37 dd Exp $
+.\" $FreeBSD: src/lib/libc/string/memcpy.3,v 1.9 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMCPY 3
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memmove 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemcpy 3
.Sh STANDARDS
The
.Fn memcpy
---- _SB/Libc/string/FreeBSD/memcpy.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/memcpy.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -41,29 +41,45 @@
+--- memcpy.3.bsdnew 2009-11-18 18:24:32.000000000 -0800
++++ memcpy.3 2009-11-18 18:24:32.000000000 -0800
+@@ -37,29 +37,45 @@
.Os
.Sh NAME
.Nm memcpy
.Sh SEE ALSO
.Xr bcopy 3 ,
.Xr memccpy 3 ,
-@@ -75,17 +91,3 @@
+@@ -72,17 +88,3 @@ The
function
conforms to
.St -isoC .
--- /dev/null
+.\" Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
+.\"
+.\" 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. 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/libc/string/memmem.3,v 1.3 2005/11/24 06:56:21 ru Exp $
+.\"
+.Dd August 24, 2005
+.Dt MEMMEM 3
+.Os
+.Sh NAME
+.Nm memmem
+.Nd "locate a byte substring in a byte string"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft "void *"
+.Fo memmem
+.Fa "const void *big" "size_t big_len"
+.Fa "const void *little" "size_t little_len"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn memmem
+function
+locates the first occurrence of the byte string
+.Fa little
+in the byte string
+.Fa big .
+.Sh RETURN VALUES
+If
+.Fa big_len
+is smaller than
+.Fa little_len ,
+if
+.Fa little_len
+is 0, if
+.Fa big_len
+is 0 or if
+.Fa little
+occurs nowhere in
+.Fa big ,
+.Dv NULL
+is returned;
+otherwise a pointer to the first character of the first occurrence of
+.Fa little
+is returned.
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strstr 3
+.Sh CONFORMING TO
+.Fn memmem
+is a GNU extension.
+.Sh HISTORY
+The
+.Fn memmem
+function first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+.An Pascal Gloor Aq pascal.gloor@spale.com
+.Sh BUGS
+This function was broken in Linux libc up to and including version 5.0.9
+and in GNU libc prior to version 2.1.
--- /dev/null
+/*-
+ * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
+ *
+ * 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. 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/memmem.c,v 1.2 2009/02/03 17:58:20 danger Exp $");
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of the byte string s in byte string l.
+ */
+
+void *
+memmem(const void *l, size_t l_len, const void *s, size_t s_len)
+{
+ register char *cur, *last;
+ const char *cl = (const char *)l;
+ const char *cs = (const char *)s;
+
+ /* we need something to compare */
+ if (l_len == 0 || s_len == 0)
+ return NULL;
+
+ /* "s" must be smaller or equal to "l" */
+ if (l_len < s_len)
+ return NULL;
+
+ /* special case where s_len == 1 */
+ if (s_len == 1)
+ return memchr(l, (int)*cs, l_len);
+
+ /* the last position where its possible to find "s" in "l" */
+ last = (char *)cl + l_len - s_len;
+
+ for (cur = (char *)cl; cur <= last; cur++)
+ if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
+ return cur;
+
+ return NULL;
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memmove.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memmove.3,v 1.6 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memmove.3,v 1.8 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMMOVE 3
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memcpy 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemmove 3
.Sh STANDARDS
The
.Fn memmove
---- memmove.3 2003-05-20 15:23:54.000000000 -0700
-+++ memmove.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,24 +47,28 @@
+--- memmove.3.bsdnew 2009-11-18 18:24:33.000000000 -0800
++++ memmove.3 2009-11-18 18:24:33.000000000 -0800
+@@ -43,24 +43,28 @@
.Sh SYNOPSIS
.In string.h
.Ft void *
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memset.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memset.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memset.3,v 1.9 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMSET 3
function returns its first argument.
.Sh SEE ALSO
.Xr bzero 3 ,
-.Xr swab 3
+.Xr swab 3 ,
+.Xr wmemset 3
.Sh STANDARDS
The
.Fn memset
---- memset.3.orig 2008-02-29 10:45:51.000000000 -0800
-+++ memset.3 2008-02-29 10:59:18.000000000 -0800
-@@ -41,7 +41,7 @@
+--- memset.3.bsdnew 2009-11-30 13:52:22.000000000 -0800
++++ memset.3 2009-11-30 14:19:30.000000000 -0800
+@@ -37,7 +37,7 @@
.Os
.Sh NAME
.Nm memset
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-@@ -56,7 +56,7 @@
+@@ -52,7 +52,7 @@ writes
.Fa len
bytes of value
.Fa c
.Fa b .
.Sh RETURN VALUES
The
-@@ -64,6 +64,7 @@
+@@ -60,6 +60,7 @@ The
function returns its first argument.
.Sh SEE ALSO
.Xr bzero 3 ,
+.Xr memset_pattern 3 ,
- .Xr swab 3
+ .Xr swab 3 ,
+ .Xr wmemset 3
.Sh STANDARDS
- The
* 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.
static char sccsid[] = "@(#)memset.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/memset.c,v 1.8 2002/09/01 21:53:46 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/memset.c,v 1.9 2007/01/09 00:28:12 imp Exp $");
#include <sys/types.h>
* 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.
static char sccsid[] = "@(#)rindex.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/rindex.c,v 1.7 2003/12/18 07:44:53 jkh Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/rindex.c,v 1.8 2007/01/09 00:28:12 imp Exp $");
#include <stddef.h>
static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/stpcpy.c,v 1.1 2002/10/03 19:39:20 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/stpcpy.c,v 1.2 2009/02/28 06:05:37 das Exp $");
#include <string.h>
char *
-stpcpy(char * to, const char * from)
+stpcpy(char * __restrict to, const char * __restrict from)
{
for (; (*to = *from); ++from, ++to);
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/stpncpy.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#include <string.h>
+
+char *
+stpncpy(char * __restrict dst, const char * __restrict src, size_t n)
+{
+
+ for (; n--; dst++, src++) {
+ if (!(*dst = *src)) {
+ char *ret = dst;
+ while (n--)
+ *++dst = '\0';
+ return (ret);
+ }
+ }
+ return (dst);
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcasecmp.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/strcasecmp.3,v 1.11 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcasecmp.3,v 1.13 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 9, 1993
.Dt STRCASECMP 3
.Xr strcmp 3 ,
.Xr strcoll 3 ,
.Xr strxfrm 3 ,
-.Xr tolower 3
+.Xr tolower 3 ,
+.Xr wcscasecmp 3
.Sh HISTORY
The
.Fn strcasecmp
---- _SB/Libc/string/FreeBSD/strcasecmp.3 2004-11-25 11:38:46.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/strcasecmp.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -39,16 +39,40 @@
+--- strcasecmp.3.orig 2009-11-30 13:52:22.000000000 -0800
++++ strcasecmp.3 2009-11-30 15:12:56.000000000 -0800
+@@ -35,16 +35,40 @@
.Os
.Sh NAME
.Nm strcasecmp ,
.Sh DESCRIPTION
The
.Fn strcasecmp
-@@ -63,8 +87,20 @@
+@@ -59,8 +83,20 @@ and
The
.Fn strncasecmp
compares at most
.Sh RETURN VALUES
The
.Fn strcasecmp
-@@ -87,7 +123,8 @@
- .Xr strcmp 3 ,
+@@ -84,7 +120,7 @@ is greater than
.Xr strcoll 3 ,
.Xr strxfrm 3 ,
--.Xr tolower 3
-+.Xr tolower 3 ,
+ .Xr tolower 3 ,
+-.Xr wcscasecmp 3
+.Xr xlocale 3
.Sh HISTORY
The
* 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.
static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcasecmp.c,v 1.6 2002/08/30 15:40:01 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcasecmp.c,v 1.8 2009/02/03 17:58:20 danger Exp $");
#include <strings.h>
#include <ctype.h>
typedef unsigned char u_char;
int
-strcasecmp(s1, s2)
- const char *s1, *s2;
+strcasecmp(const char *s1, const char *s2)
{
const u_char
*us1 = (const u_char *)s1,
}
int
-strncasecmp(s1, s2, n)
- const char *s1, *s2;
- size_t n;
+strncasecmp(const char *s1, const char *s2, size_t n)
{
if (n != 0) {
const u_char
---- strcasecmp.c.orig 2003-05-20 15:23:54.000000000 -0700
-+++ strcasecmp.c 2005-02-18 18:46:40.000000000 -0800
-@@ -37,41 +37,62 @@
+--- strcasecmp.c.bsdnew 2009-11-18 18:24:33.000000000 -0800
++++ strcasecmp.c 2009-11-18 18:24:33.000000000 -0800
+@@ -33,38 +33,59 @@ static char sccsid[] = "@(#)strcasecmp.c
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/string/strcasecmp.c,v 1.6 2002/08/30 15:40:01 robert Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/string/strcasecmp.c,v 1.8 2009/02/03 17:58:20 danger Exp $");
+#include "xlocale_private.h"
+
typedef unsigned char u_char;
int
--strcasecmp(s1, s2)
+-strcasecmp(const char *s1, const char *s2)
+strcasecmp_l(s1, s2, loc)
- const char *s1, *s2;
++ const char *s1, *s2;
+ locale_t loc;
{
const u_char
}
int
--strncasecmp(s1, s2, n)
-+strcasecmp(s1, s2)
-+ const char *s1, *s2;
-+{
+-strncasecmp(const char *s1, const char *s2, size_t n)
++strcasecmp(const char *s1, const char *s2)
+ {
+ return strcasecmp_l(s1, s2, __current_locale());
+}
+
+int
+strncasecmp_l(s1, s2, n, loc)
- const char *s1, *s2;
- size_t n;
++ const char *s1, *s2;
++ size_t n;
+ locale_t loc;
- {
++{
+ NORMALIZE_LOCALE(loc);
if (n != 0) {
const u_char
}
+
+int
-+strncasecmp(s1, s2, n)
-+ const char *s1, *s2;
-+ size_t n;
++strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ return strncasecmp_l(s1, s2, n, __current_locale());
+}
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcasestr.c,v 1.3 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcasestr.c,v 1.5 2009/02/03 17:58:20 danger Exp $");
#include <ctype.h>
#include <string.h>
* Find the first occurrence of find in s, ignore case.
*/
char *
-strcasestr(s, find)
- const char *s, *find;
+strcasestr(const char *s, const char *find)
{
char c, sc;
size_t len;
---- strcasestr.c.orig 2003-05-20 15:23:54.000000000 -0700
-+++ strcasestr.c 2005-02-18 18:48:55.000000000 -0800
-@@ -37,6 +37,8 @@
+--- strcasestr.c.bsdnew 2009-11-18 18:24:33.000000000 -0800
++++ strcasestr.c 2009-11-18 18:24:33.000000000 -0800
+@@ -33,6 +33,8 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/string/strcasestr.c,v 1.3 2002/03/21 18:44:54 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/string/strcasestr.c,v 1.5 2009/02/03 17:58:20 danger Exp $");
+#include "xlocale_private.h"
+
#include <ctype.h>
#include <string.h>
-@@ -44,22 +46,31 @@
+@@ -40,21 +42,30 @@ __FBSDID("$FreeBSD: src/lib/libc/string/
* Find the first occurrence of find in s, ignore case.
*/
char *
--strcasestr(s, find)
+-strcasestr(const char *s, const char *find)
+strcasestr_l(s, find, loc)
- const char *s, *find;
++ const char *s, *find;
+ locale_t loc;
{
char c, sc;
}
+
+char *
-+strcasestr(s, find)
-+ const char *s, *find;
++strcasestr(const char *s, const char *find)
+{
+ return strcasestr_l(s, find, __current_locale());
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcat.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcat.3,v 1.13 2002/09/06 11:24:06 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/strcat.3,v 1.17 2009/12/01 07:28:56 brueffer Exp $
.\"
-.Dd June 4, 1993
+.Dd December 1, 2009
.Dt STRCAT 3
.Os
.Sh NAME
-.Nm strcat
+.Nm strcat ,
+.Nm strncat
.Nd concatenate strings
.Sh LIBRARY
.Lb libc
.Xr memmove 3 ,
.Xr strcpy 3 ,
.Xr strlcat 3 ,
-.Xr strlcpy 3
-.Rs
-.%T "The FreeBSD Security Architecture"
-.Re
-(See
-.Pa "/usr/share/doc/{to be decided}" . )
+.Xr strlcpy 3 ,
+.Xr wcscat 3
.Sh STANDARDS
The
.Fn strcat
---- strcat.3.orig 2008-02-29 10:45:51.000000000 -0800
-+++ strcat.3 2008-02-29 12:07:09.000000000 -0800
-@@ -40,16 +40,24 @@
- .Dt STRCAT 3
- .Os
- .Sh NAME
--.Nm strcat
-+.Nm strcat ,
-+.Nm strncat
- .Nd concatenate strings
- .Sh LIBRARY
- .Lb libc
+--- strcat.3.orig 2010-06-17 08:44:44.000000000 -0700
++++ strcat.3 2010-06-17 08:46:22.000000000 -0700
+@@ -44,9 +44,16 @@
.Sh SYNOPSIS
.In string.h
.Ft char *
.Sh DESCRIPTION
The
.Fn strcat
-@@ -57,24 +65,27 @@
+@@ -54,24 +61,27 @@ and
.Fn strncat
functions
append a copy of the null-terminated string
.Sh RETURN VALUES
The
.Fn strcat
-@@ -82,7 +93,7 @@
+@@ -79,7 +89,7 @@ and
.Fn strncat
functions
return the pointer
.Sh SECURITY CONSIDERATIONS
The
.Fn strcat
-@@ -114,7 +125,7 @@
+@@ -111,7 +121,7 @@ Example:
void
foo(const char *arbitrary_string)
{
#if defined(BAD)
/*
-@@ -149,11 +160,6 @@
- .Xr strcpy 3 ,
- .Xr strlcat 3 ,
- .Xr strlcpy 3
--.Rs
--.%T "The FreeBSD Security Architecture"
--.Re
--(See
--.Pa "/usr/share/doc/{to be decided}" . )
- .Sh STANDARDS
- The
- .Fn strcat
* 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.
static char sccsid[] = "@(#)strcat.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcat.c,v 1.7 2002/09/06 11:24:06 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcat.c,v 1.8 2007/01/09 00:28:12 imp Exp $");
#include <string.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strchr.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/string/strchr.3,v 1.11 2003/09/04 20:36:54 simon Exp $
+.\" $FreeBSD: src/lib/libc/string/strchr.3,v 1.14 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd April 19, 1994
.Dt STRCHR 3
if the character does not appear in the string.
.Sh SEE ALSO
.Xr memchr 3 ,
+.Xr memmem 3 ,
.Xr strcspn 3 ,
.Xr strpbrk 3 ,
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcschr 3
.Sh STANDARDS
The functions
.Fn strchr
---- _SB/Libc/string/FreeBSD/strchr.3 2004-11-25 11:38:47.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/strchr.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,9 +47,15 @@
+--- strchr.3.bsdnew 2009-11-18 18:24:33.000000000 -0800
++++ strchr.3 2009-11-18 18:24:33.000000000 -0800
+@@ -43,9 +43,15 @@
.Sh SYNOPSIS
.In string.h
.Ft "char *"
.Sh DESCRIPTION
The
.Fn strchr
-@@ -59,7 +65,7 @@
+@@ -55,7 +61,7 @@ function locates the first occurrence of
.Vt char )
in the string pointed to by
.Fa s .
therefore if
.Fa c
is
-@@ -70,7 +76,7 @@
+@@ -66,7 +72,7 @@ the functions locate the terminating
The
.Fn strrchr
function is identical to
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcmp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcmp.3,v 1.10 2001/10/11 17:02:44 mike Exp $
+.\" $FreeBSD: src/lib/libc/string/strcmp.3,v 1.13 2009/12/04 09:20:20 trhodes Exp $
.\"
.Dd October 11, 2001
.Dt STRCMP 3
.Fn strcmp
and
.Fn strncmp
-return an integer greater than, equal to, or less than 0, according
+functions return an integer greater than, equal to, or less than 0, according
as the string
.Fa s1
is greater than, equal to, or less than the string
.Xr memcmp 3 ,
.Xr strcasecmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wcscmp 3
.Sh STANDARDS
The
.Fn strcmp
---- _SB/Libc/string/FreeBSD/strcmp.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strcmp.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -48,9 +48,16 @@
+--- strcmp.3.bsdnew 2009-11-18 18:24:33.000000000 -0800
++++ strcmp.3 2009-11-18 18:24:34.000000000 -0800
+@@ -44,9 +44,16 @@
.Sh SYNOPSIS
.In string.h
.Ft int
.Sh DESCRIPTION
The
.Fn strcmp
-@@ -66,7 +73,7 @@
+@@ -62,7 +69,7 @@ The
.Fn strncmp
function
compares not more than
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcoll.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcoll.3,v 1.12 2002/10/15 10:11:53 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/strcoll.3,v 1.14 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt STRCOLL 3
.Fa s1
and
.Fa s2
-according to the current locale collation if any, otherwise call
-.Fa strcmp ,
+according to the current locale collation
and returns an integer greater than, equal to, or less than 0,
according as
.Fa s1
is greater than, equal to, or less than
.Fa s2 .
+If information about the current locale collation is not available,
+the value of
+.Fn strcmp s1 s2
+is returned.
.Sh SEE ALSO
.Xr setlocale 3 ,
.Xr strcmp 3 ,
---- _SB/Libc/string/FreeBSD/strcoll.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strcoll.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -40,14 +40,26 @@
+--- strcoll.3.bsdnew 2009-11-30 13:52:22.000000000 -0800
++++ strcoll.3 2009-11-30 14:29:06.000000000 -0800
+@@ -36,14 +36,26 @@
.Dt STRCOLL 3
.Os
.Sh NAME
.Sh DESCRIPTION
The
.Fn strcoll
-@@ -55,19 +67,29 @@
- lexicographically compares the null-terminated strings
- .Fa s1
- and
--.Fa s2
--according to the current locale collation if any, otherwise call
--.Fa strcmp ,
-+.Fa s2 ,
-+according to the current locale collation, if any.
-+Otherwise, it calls
-+.Fa strcmp
- and returns an integer greater than, equal to, or less than 0,
- according as
- .Fa s1
- is greater than, equal to, or less than
- .Fa s2 .
+@@ -62,11 +74,20 @@ If information about the current locale
+ the value of
+ .Fn strcmp s1 s2
+ is returned.
+.Pp
+Although the
+.Fn strcoll
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcoll.c,v 1.13 2001/11/07 19:55:16 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcoll.c,v 1.14 2009/02/03 17:58:20 danger Exp $");
#include <stdlib.h>
#include <string.h>
#include "collate.h"
int
-strcoll(s, s2)
- const char *s, *s2;
+strcoll(const char *s, const char *s2)
{
int len, len2, prim, prim2, sec, sec2, ret, ret2;
const char *t, *t2;
---- strcoll.c.orig 2003-05-20 15:23:54.000000000 -0700
-+++ strcoll.c 2005-03-30 15:16:28.000000000 -0800
-@@ -28,59 +28,44 @@
+--- strcoll.c.bsdnew 2009-11-18 18:24:34.000000000 -0800
++++ strcoll.c 2009-11-18 18:26:43.000000000 -0800
+@@ -28,58 +28,41 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/string/strcoll.c,v 1.13 2001/11/07 19:55:16 obrien Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/string/strcoll.c,v 1.14 2009/02/03 17:58:20 danger Exp $");
+#include "xlocale_private.h"
+
#include "collate.h"
int
--strcoll(s, s2)
-+strcoll_l(s, s2, loc)
- const char *s, *s2;
-+ locale_t loc;
+-strcoll(const char *s, const char *s2)
++strcoll_l(const char *s, const char *s2, locale_t loc)
{
- int len, len2, prim, prim2, sec, sec2, ret, ret2;
- const char *t, *t2;
}
+
+int
-+strcoll(s, s2)
-+ const char *s, *s2;
++strcoll(const char *s, const char *s2)
+{
+ return strcoll_l(s, s2, __current_locale());
+}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcpy.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcpy.3,v 1.24 2002/12/19 09:40:24 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcpy.3,v 1.28 2009/04/07 13:42:53 trasz Exp $
.\"
-.Dd August 9, 2001
+.Dd February 28, 2009
.Dt STRCPY 3
.Os
.Sh NAME
-.Nm strcpy , strncpy
+.Nm stpcpy, stpncpy, strcpy , strncpy
.Nd copy strings
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In string.h
.Ft char *
-.Fn stpcpy "char *dst" "const char *src"
+.Fn stpcpy "char * restrict dst" "const char * restrict src"
+.Ft char *
+.Fn stpncpy "char * restrict dst" "const char * restrict src" "size_t len"
.Ft char *
.Fn strcpy "char * restrict dst" "const char * restrict src"
.Ft char *
character.)
.Pp
The
+.Fn stpncpy
+and
.Fn strncpy
-function copies at most
+functions copy at most
.Fa len
characters from
.Fa src
.Fa dst .
The
.Fn stpcpy
-function returns a pointer to the terminating
+and
+.Fn stpncpy
+functions return a pointer to the terminating
.Ql \e0
character of
.Fa dst .
+If
+.Fn stpncpy
+does not terminate
+.Fa dst
+with a
+.Dv NUL
+character, it instead returns a pointer to
+.Li dst[n]
+(which does not necessarily refer to a valid memory location.)
.Sh EXAMPLES
The following sets
.Va chararray
.Xr memccpy 3 ,
.Xr memcpy 3 ,
.Xr memmove 3 ,
-.Xr strlcpy 3
-.Rs
-.%T "The FreeBSD Security Architecture"
-.Re
-(See
-.Pa "/usr/share/doc/{to be decided}" . )
+.Xr strlcpy 3 ,
+.Xr wcscpy 3
.Sh STANDARDS
The
.Fn strcpy
.St -isoC .
The
.Fn stpcpy
-function is an MS-DOS and GNUism.
-The
-.Fn stpcpy
-function
-conforms to no standard.
+and
+.Fn stpncpy
+functions conform to
+.St -p1003.1-2008 .
.Sh HISTORY
The
.Fn stpcpy
function first appeared in
.Fx 4.4 ,
-coming from 1998-vintage Linux.
+and
+.Fn stpncpy
+was added in
+.Fx 8.0 .
---- strcpy.3.orig 2008-02-29 10:45:51.000000000 -0800
-+++ strcpy.3 2008-02-29 12:08:34.000000000 -0800
-@@ -40,18 +40,30 @@
- .Dt STRCPY 3
- .Os
- .Sh NAME
--.Nm strcpy , strncpy
-+.Nm stpcpy ,
-+.Nm strcpy ,
-+.Nm strncpy
- .Nd copy strings
- .Sh LIBRARY
- .Lb libc
+--- strcpy.3.orig 2010-04-28 23:38:50.000000000 -0700
++++ strcpy.3 2010-04-29 09:37:17.000000000 -0700
+@@ -43,13 +43,27 @@
.Sh SYNOPSIS
.In string.h
.Ft char *
--.Fn stpcpy "char *dst" "const char *src"
+-.Fn stpcpy "char * restrict dst" "const char * restrict src"
+.Fo stpcpy
+.Fa "char *s1"
+.Fa "const char *s2"
++.Fc
+ .Ft char *
+-.Fn stpncpy "char * restrict dst" "const char * restrict src" "size_t len"
++.Fo stpncpy
++.Fa "char *restrict s1"
++.Fa "const char *restrict s2"
++.Fa "size_t n"
+.Fc
.Ft char *
-.Fn strcpy "char * restrict dst" "const char * restrict src"
.Sh DESCRIPTION
The
.Fn stpcpy
-@@ -59,36 +71,39 @@
+@@ -57,38 +71,41 @@ and
.Fn strcpy
functions
copy the string
+character).
.Pp
The
+ .Fn stpncpy
+ and
.Fn strncpy
- function copies at most
+ functions copy at most
-.Fa len
+.Fa n
characters from
.Sh RETURN VALUES
The
.Fn strcpy
-@@ -96,13 +111,13 @@
+@@ -96,7 +113,7 @@ and
.Fn strncpy
functions
return
+.Fa s1 .
The
.Fn stpcpy
- function returns a pointer to the terminating
+ and
+@@ -104,15 +121,15 @@ and
+ functions return a pointer to the terminating
.Ql \e0
character of
-.Fa dst .
+.Fa s1 .
+ If
+ .Fn stpncpy
+ does not terminate
+-.Fa dst
++.Fa s1
+ with a
+ .Dv NUL
+ character, it instead returns a pointer to
+-.Li dst[n]
++.Li s1[n]
+ (which does not necessarily refer to a valid memory location.)
.Sh EXAMPLES
The following sets
- .Va chararray
-@@ -128,7 +143,7 @@
+@@ -139,7 +156,7 @@ Note that it does
.Em not
.Tn NUL
terminate
because the length of the source string is greater than or equal
to the length argument.
.Pp
-@@ -159,7 +174,7 @@
+@@ -169,21 +186,26 @@ This could be better achieved using
+ as shown in the following example:
.Pp
.Dl "(void)strlcpy(buf, input, sizeof(buf));"
- .Pp
+-.Pp
-Note that because
-+Note that, because
- .Xr strlcpy 3
- is not defined in any standards, it should
- only be used when portability is not a concern.
-@@ -179,11 +194,6 @@
- .Xr memcpy 3 ,
- .Xr memmove 3 ,
- .Xr strlcpy 3
--.Rs
--.%T "The FreeBSD Security Architecture"
--.Re
--(See
--.Pa "/usr/share/doc/{to be decided}" . )
- .Sh STANDARDS
+-.Xr strlcpy 3
+-is not defined in any standards, it should
+-only be used when portability is not a concern.
+ .Sh SECURITY CONSIDERATIONS
The
- .Fn strcpy
+-.Fn strcpy
+-function is easily misused in a manner which enables malicious users
++.Fn strcpy ,
++.Fn strncpy ,
++.Fn stpcpy ,
++and
++.Fn stpncpy
++functions are easily misused in a manner which enables malicious users
+ to arbitrarily change a running program's functionality through a
+ buffer overflow attack.
+ (See
+ the FSA
+ and
+ .Sx EXAMPLES . )
++.Pp
++It is recommended that
++.Xr strlcpy 3
++be used instead as a way to avoid such problems.
++.Xr strlcpy 3
++is not defined in any standards, but it has been adopted by most major libc implementations.
+ .Sh SEE ALSO
+ .Xr bcopy 3 ,
+ .Xr memccpy 3 ,
* 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.
static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcpy.c,v 1.7 2002/09/06 11:24:06 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcpy.c,v 1.8 2007/01/09 00:28:12 imp Exp $");
#include <string.h>
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcspn.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.9 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt STRCSPN 3
.Em complement
of
.Fa charset ) .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is also in
+.Fa charset ,
+else the index of the first null character.
.Sh RETURN VALUES
The
.Fn strcspn
---- _SB/Libc/string/FreeBSD/strcspn.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strcspn.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,27 +47,29 @@
+--- strcspn.3.orig 2009-11-30 13:52:23.000000000 -0800
++++ strcspn.3 2009-11-30 14:57:01.000000000 -0800
+@@ -43,28 +43,31 @@
.Sh SYNOPSIS
.In string.h
.Ft size_t
of
-.Fa charset ) .
+.Fa s2 ) .
+ In other words, it computes the string array index in
+-.Fa s
++.Fa s1
+ of the first character of
+-.Fa s
++.Fa s1
+ which is also in
+-.Fa charset ,
++.Fa s2 ,
+ else the index of the first null character.
.Sh RETURN VALUES
The
- .Fn strcspn
--function
--returns the number of characters spanned.
-+function returns the number of characters spanned.
- .Sh SEE ALSO
- .Xr memchr 3 ,
- .Xr strchr 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strdup.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/strdup.3,v 1.10 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strdup.3,v 1.15 2009/04/07 13:42:53 trasz Exp $
.\"
-.Dd June 9, 1993
+.Dd December 5, 2008
.Dt STRDUP 3
.Os
.Sh NAME
-.Nm strdup
+.Nm strdup ,
+.Nm strndup
.Nd save a copy of a string
.Sh LIBRARY
.Lb libc
.In string.h
.Ft char *
.Fn strdup "const char *str"
+.Ft char *
+.Fn strndup "const char *str" "size_t len"
.Sh DESCRIPTION
The
.Fn strdup
.Va errno
is set to
.Er ENOMEM .
+.Pp
+The
+.Fn strndup
+function copies at most
+.Fa len
+characters from the string
+.Fa str
+always
+.Dv NUL
+terminating the copied string.
.Sh SEE ALSO
.Xr free 3 ,
-.Xr malloc 3
+.Xr malloc 3 ,
+.Xr wcsdup 3
.Sh HISTORY
The
.Fn strdup
function first appeared in
.Bx 4.4 .
+The
+.Fn strndup
+function was added in
+.Fx 7.2 .
---- _SB/Libc/string/FreeBSD/strdup.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strdup.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -43,14 +43,16 @@
+--- strdup.3.orig 2009-11-30 13:52:20.000000000 -0800
++++ strdup.3 2009-11-30 15:13:21.000000000 -0800
+@@ -40,16 +40,21 @@
.Sh SYNOPSIS
.In string.h
.Ft char *
-.Fn strdup "const char *str"
+.Fo strdup
+.Fa "const char *s1"
++.Fc
+ .Ft char *
+-.Fn strndup "const char *str" "size_t len"
++.Fo strndup
++.Fa "const char *s1"
++.Fa "size_t n"
+.Fc
.Sh DESCRIPTION
The
does the copy, and returns a pointer to it.
The pointer may subsequently be used as an
argument to the function
+@@ -63,16 +68,15 @@ is set to
+ The
+ .Fn strndup
+ function copies at most
+-.Fa len
++.Fa n
+ characters from the string
+-.Fa str
++.Fa s1
+ always
+ .Dv NUL
+ terminating the copied string.
+ .Sh SEE ALSO
+ .Xr free 3 ,
+-.Xr malloc 3 ,
+-.Xr wcsdup 3
++.Xr malloc 3
+ .Sh HISTORY
+ The
+ .Fn strdup
* 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.
static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strdup.c,v 1.4 2001/11/07 19:55:16 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strdup.c,v 1.6 2009/02/03 17:58:20 danger Exp $");
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
char *
-strdup(str)
- const char *str;
+strdup(const char *str)
{
size_t len;
char *copy;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strerror.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/strerror.3,v 1.23 2004/10/12 14:52:52 keramida Exp $
+.\" $FreeBSD: src/lib/libc/string/strerror.3,v 1.24 2007/01/09 00:28:12 imp Exp $
.\"
.Dd October 12, 2004
.Dt STRERROR 3
---- _SB/Libc/string/FreeBSD/strerror.3 2004-11-25 11:38:47.000000000 -0800
-+++ _SB/Libc/string/FreeBSD/strerror.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -51,18 +51,26 @@
+--- strerror.3.orig 2010-10-07 16:06:39.000000000 -0700
++++ strerror.3 2010-10-07 16:32:34.000000000 -0700
+@@ -47,18 +47,26 @@
.Sh SYNOPSIS
.In stdio.h
.Ft void
and
.Fn perror
functions look up the error message string corresponding to an
-@@ -92,7 +100,7 @@
+@@ -88,7 +96,7 @@
and writes it, followed by a newline, to the
standard error file descriptor.
If the argument
is
.Pf non- Dv NULL
and does not point to the null character,
+@@ -110,7 +118,7 @@
+ .Er EINVAL
+ as a warning.
+ Error numbers recognized by this implementation fall in
+-the range 0 <
++the range 0 <=
+ .Fa errnum
+ <
+ .Fa sys_nerr .
* 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.
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strerror.c,v 1.13 2003/05/01 19:03:14 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strerror.c,v 1.16 2007/01/09 00:28:12 imp Exp $");
+#if defined(NLS)
+#include <nl_types.h>
+#endif
+
+#include <limits.h>
#include <errno.h>
-#include <stdio.h>
#include <string.h>
+#include <stdio.h>
-#define UPREFIX "Unknown error: "
+#define UPREFIX "Unknown error"
/*
* Define a buffer size big enough to describe a 64-bit signed integer
* converted to ASCII decimal (19 bytes), with an optional leading sign
- * (1 byte); finally, we get the prefix and a trailing NUL from UPREFIX.
+ * (1 byte); finally, we get the prefix, delimiter (": ") and a trailing
+ * NUL from UPREFIX.
*/
-#define EBUFSIZE (20 + sizeof(UPREFIX))
+#define EBUFSIZE (20 + 2 + sizeof(UPREFIX))
/*
* Doing this by hand instead of linking with stdio(3) avoids bloat for
* statically linked binaries.
*/
static void
-errstr(int num, char *buf, size_t len)
+errstr(int num, char *uprefix, char *buf, size_t len)
{
char *t;
unsigned int uerr;
} while (uerr /= 10);
if (num < 0)
*--t = '-';
- strlcpy(buf, UPREFIX, len);
+ *--t = ' ';
+ *--t = ':';
+ strlcpy(buf, uprefix, len);
strlcat(buf, t, len);
}
int
strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
+ int retval = 0;
+#if defined(NLS)
+ int saved_errno = errno;
+ nl_catd catd;
+ catd = catopen("libc", NL_CAT_LOCALE);
+#endif
if (errnum < 1 || errnum >= sys_nerr) {
- errstr(errnum, strerrbuf, buflen);
- return (EINVAL);
+ errstr(errnum,
+#if defined(NLS)
+ catgets(catd, 1, 0xffff, UPREFIX),
+#else
+ UPREFIX,
+#endif
+ strerrbuf, buflen);
+ retval = EINVAL;
+ } else {
+ if (strlcpy(strerrbuf,
+#if defined(NLS)
+ catgets(catd, 1, errnum, sys_errlist[errnum]),
+#else
+ sys_errlist[errnum],
+#endif
+ buflen) >= buflen)
+ retval = ERANGE;
}
- if (strlcpy(strerrbuf, sys_errlist[errnum], buflen) >= buflen)
- return (ERANGE);
- return (0);
+
+#if defined(NLS)
+ catclose(catd);
+ errno = saved_errno;
+#endif
+
+ return (retval);
}
char *
strerror(int num)
{
- static char ebuf[EBUFSIZE];
+ static char ebuf[NL_TEXTMAX];
- if (num > 0 && num < sys_nerr)
- return ((char *)sys_errlist[num]);
+ if (strerror_r(num, ebuf, sizeof(ebuf)) != 0)
errno = EINVAL;
- errstr(num, ebuf, sizeof(ebuf));
return (ebuf);
}
---- strerror.c.orig 2004-11-25 11:38:47.000000000 -0800
-+++ strerror.c 2005-04-30 01:26:56.000000000 -0700
-@@ -50,12 +50,13 @@
+--- strerror.c.orig 2010-10-07 16:06:39.000000000 -0700
++++ strerror.c 2010-10-07 16:17:59.000000000 -0700
+@@ -52,12 +52,13 @@ __FBSDID("$FreeBSD: src/lib/libc/string/
*/
- #define EBUFSIZE (20 + sizeof(UPREFIX))
+ #define EBUFSIZE (20 + 2 + sizeof(UPREFIX))
+#ifndef BUILDING_VARIANT
/*
* statically linked binaries.
*/
-static void
--errstr(int num, char *buf, size_t len)
+-errstr(int num, char *uprefix, char *buf, size_t len)
+__private_extern__ void
-+__errstr(int num, char *buf, size_t len)
++__errstr(int num, char *uprefix, char *buf, size_t len)
{
char *t;
unsigned int uerr;
-@@ -77,14 +78,17 @@
- strerror_r(int errnum, char *strerrbuf, size_t buflen)
- {
+@@ -87,8 +88,8 @@ strerror_r(int errnum, char *strerrbuf,
+ catd = catopen("libc", NL_CAT_LOCALE);
+ #endif
- if (errnum < 1 || errnum >= sys_nerr) {
-- errstr(errnum, strerrbuf, buflen);
+- errstr(errnum,
+ if (errnum < 0 || errnum >= sys_nerr) {
-+ __errstr(errnum, strerrbuf, buflen);
- return (EINVAL);
- }
- if (strlcpy(strerrbuf, sys_errlist[errnum], buflen) >= buflen)
- return (ERANGE);
- return (0);
++ __errstr(errnum,
+ #if defined(NLS)
+ catgets(catd, 1, 0xffff, UPREFIX),
+ #else
+@@ -114,13 +115,20 @@ strerror_r(int errnum, char *strerrbuf,
+
+ return (retval);
}
+#else /* BUILDING_VARIANT */
+__private_extern__ void __errstr(int, char *, size_t);
char *
strerror(int num)
-@@ -93,7 +97,9 @@
+ {
+ static char ebuf[NL_TEXTMAX];
- if (num > 0 && num < sys_nerr)
- return ((char *)sys_errlist[num]);
+#if !__DARWIN_UNIX03
+ if (strerror_r(num, ebuf, sizeof(ebuf)) != 0)
errno = EINVAL;
-- errstr(num, ebuf, sizeof(ebuf));
-+#endif /* !__DARWIN_UNIX03 */
-+ __errstr(num, ebuf, sizeof(ebuf));
++#else
++ (void)strerror_r(num, ebuf, sizeof(ebuf));
++#endif
return (ebuf);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)string.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/string/string.3,v 1.13 2002/10/19 13:41:22 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/string.3,v 1.14 2007/01/09 00:28:12 imp Exp $
.\"
.Dd December 11, 1993
.Dt STRING 3
---- _SB/Libc/string/FreeBSD/string.3 2003-05-20 15:23:54.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/string.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -38,77 +38,143 @@
+--- string.3.bsdnew 2009-11-18 18:24:34.000000000 -0800
++++ string.3 2009-11-18 18:24:34.000000000 -0800
+@@ -34,77 +34,143 @@
.Dt STRING 3
.Os
.Sh NAME
-/* $OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $ */
+/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED ``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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char *rcsid = "$OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strlcat.c,v 1.10 2004/10/16 06:32:43 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strlcat.c,v 1.12 2009/02/28 05:15:02 das Exp $");
#include <sys/types.h>
#include <string.h>
* If retval >= siz, truncation occurred.
*/
size_t
-strlcat(dst, src, siz)
- char *dst;
- const char *src;
- size_t siz;
+strlcat(char * __restrict dst, const char * __restrict src, size_t siz)
{
char *d = dst;
const char *s = src;
-.\" $OpenBSD: strlcpy.3,v 1.5 1999/06/06 15:17:32 aaron Exp $
+.\" $OpenBSD: strlcpy.3,v 1.19 2007/05/31 19:19:32 jmc Exp $
.\"
-.\" Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
-.\" All rights reserved.
+.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
.\"
-.\" 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. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/string/strlcpy.3,v 1.13 2004/07/02 23:52:13 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strlcpy.3,v 1.16 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 22, 1998
.Dt STRLCPY 3
.Sh SYNOPSIS
.In string.h
.Ft size_t
-.Fn strlcpy "char *dst" "const char *src" "size_t size"
+.Fn strlcpy "char * restrict dst" "const char * restrict src" "size_t size"
.Ft size_t
-.Fn strlcat "char *dst" "const char *src" "size_t size"
+.Fn strlcat "char * restrict dst" "const char * restrict src" "size_t size"
.Sh DESCRIPTION
The
.Fn strlcpy
.Fn strlcat ,
as long as there is at least one byte free in
.Fa dst ) .
-Note that you should include a byte for the NUL in
+Note that a byte for the NUL should be included in
.Fa size .
Also note that
.Fn strlcpy
plus
the length of
.Fa src .
-While this may seem somewhat confusing it was done to make
+While this may seem somewhat confusing, it was done to make
truncation detection simple.
.Pp
Note however, that if
goto toolong;
.Ed
.Pp
-Since we know how many characters we copied the first time, we can
-speed things up a bit by using a copy instead of an append:
+Since it is known how many characters were copied the first time, things
+can be sped up a bit by using a copy instead of an append
.Bd -literal -offset indent
char *dir, *file, pname[MAXPATHLEN];
size_t n;
.Sh SEE ALSO
.Xr snprintf 3 ,
.Xr strncat 3 ,
-.Xr strncpy 3
+.Xr strncpy 3 ,
+.Xr wcslcpy 3
.Sh HISTORY
The
.Fn strlcpy
---- strlcpy.3.orig 2008-02-29 10:45:51.000000000 -0800
-+++ strlcpy.3 2008-02-29 12:11:21.000000000 -0800
-@@ -103,6 +103,9 @@
+--- strlcpy.3.bsdnew 2009-11-18 18:24:34.000000000 -0800
++++ strlcpy.3 2009-11-18 18:24:34.000000000 -0800
+@@ -103,6 +103,9 @@ to the end of
It will append at most
.Fa size
- strlen(dst) - 1 bytes, NUL-terminating the result.
-/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */
+/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED ``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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.8 2004/10/14 21:31:42 stefanf Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.11 2009/02/28 05:15:02 das Exp $");
#include <sys/types.h>
#include <string.h>
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
-size_t strlcpy(dst, src, siz)
- char *dst;
- const char *src;
- size_t siz;
+size_t
+strlcpy(char * __restrict dst, const char * __restrict src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
- if (n != 0 && --n != 0) {
- do {
- if ((*d++ = *s++) == 0)
+ if (n != 0) {
+ while (--n != 0) {
+ if ((*d++ = *s++) == '\0')
break;
- } while (--n != 0);
+ }
}
/* Not enough room in dst, add NUL and traverse rest of src */
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strlen.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strlen.3,v 1.6 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strlen.3,v 1.9 2009/04/07 13:42:53 trasz Exp $
.\"
-.Dd June 4, 1993
+.Dd February 28, 2009
.Dt STRLEN 3
.Os
.Sh NAME
-.Nm strlen
+.Nm strlen, strnlen
.Nd find length of string
.Sh LIBRARY
.Lb libc
.In string.h
.Ft size_t
.Fn strlen "const char *s"
+.Ft size_t
+.Fn strnlen "const char *s" "size_t maxlen"
.Sh DESCRIPTION
The
.Fn strlen
function
computes the length of the string
.Fa s .
+The
+.Fn strnlen
+function attempts to compute the length of
+.Fa s ,
+but never scans beyond the first
+.Fa maxlen
+bytes of
+.Fa s .
.Sh RETURN VALUES
The
.Fn strlen
terminating
.Dv NUL
character.
+The
+.Fn strnlen
+function returns either the same result as
+.Fn strlen
+or
+.Fa maxlen ,
+whichever is smaller.
.Sh SEE ALSO
-.Xr string 3
+.Xr string 3 ,
+.Xr wcslen 3 ,
+.Xr wcswidth 3
.Sh STANDARDS
The
.Fn strlen
function
conforms to
.St -isoC .
+The
+.Fn strnlen
+function conforms to
+.St -p1003.1-2008 .
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2009 Xin LI <delphij@FreeBSD.org>
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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
+ *
+ * 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 REGENTS OR CONTRIBUTORS BE LIABLE
+ * 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)
* SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strlen.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strlen.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strlen.c,v 1.7 2009/01/26 07:31:28 delphij Exp $");
+#include <sys/limits.h>
+#include <sys/types.h>
#include <string.h>
+/*
+ * Portable strlen() for 32-bit and 64-bit systems.
+ *
+ * Rationale: it is generally much more efficient to do word length
+ * operations and avoid branches on modern computer systems, as
+ * compared to byte-length operations with a lot of branches.
+ *
+ * The expression:
+ *
+ * ((x - 0x01....01) & ~x & 0x80....80)
+ *
+ * would evaluate to a non-zero value iff any of the bytes in the
+ * original word is zero. However, we can further reduce ~1/3 of
+ * time if we consider that strlen() usually operate on 7-bit ASCII
+ * by employing the following expression, which allows false positive
+ * when high bit of 1 and use the tail case to catch these case:
+ *
+ * ((x - 0x01....01) & 0x80....80)
+ *
+ * This is more than 5.2 times as fast as the raw implementation on
+ * Intel T7300 under long mode for strings longer than word length.
+ */
+
+/* Magic numbers for the algorithm */
+#if LONG_BIT == 32
+static const unsigned long mask01 = 0x01010101;
+static const unsigned long mask80 = 0x80808080;
+#elif LONG_BIT == 64
+static const unsigned long mask01 = 0x0101010101010101;
+static const unsigned long mask80 = 0x8080808080808080;
+#else
+#error Unsupported word size
+#endif
+
+#define LONGPTR_MASK (sizeof(long) - 1)
+
+/*
+ * Helper macro to return string length if we caught the zero
+ * byte.
+ */
+#define testbyte(x) \
+ do { \
+ if (p[x] == '\0') \
+ return (p - str + x); \
+ } while (0)
+
size_t
-strlen(str)
- const char *str;
+strlen(const char *str)
{
- const char *s;
+ const char *p;
+ const unsigned long *lp;
+
+ /* Skip the first few bytes until we have an aligned p */
+ for (p = str; (uintptr_t)p & LONGPTR_MASK; p++)
+ if (*p == '\0')
+ return (p - str);
+
+ /* Scan the rest of the string using word sized operation */
+ for (lp = (const unsigned long *)p; ; lp++)
+ if ((*lp - mask01) & mask80) {
+ p = (const char *)(lp);
+ testbyte(0);
+ testbyte(1);
+ testbyte(2);
+ testbyte(3);
+#if (LONG_BIT >= 64)
+ testbyte(4);
+ testbyte(5);
+ testbyte(6);
+ testbyte(7);
+#endif
+ }
- for (s = str; *s; ++s);
- return(s - str);
+ /* NOTREACHED */
+ return (0);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strmode.3 8.3 (Berkeley) 7/28/94
-.\" $FreeBSD: src/lib/libc/string/strmode.3,v 1.9 2003/07/01 15:28:05 maxim Exp $
+.\" $FreeBSD: src/lib/libc/string/strmode.3,v 1.11 2009/04/14 11:39:56 trasz Exp $
.\"
.Dd July 28, 1994
.Dt STRMODE 3
None of the above apply.
.El
.Pp
-The last character is a plus sign ``+'' if any there are any alternate
-or additional access control methods associated with the inode, otherwise
-it will be a space.
+The last character will always be a space.
.Sh SEE ALSO
.Xr chmod 1 ,
.Xr find 1 ,
---- strmode.3 2004-11-25 11:38:47.000000000 -0800
-+++ strmode.3.edit 2006-08-12 10:29:49.000000000 -0700
-@@ -43,7 +43,10 @@
+--- strmode.3.bsdnew 2009-11-18 18:24:34.000000000 -0800
++++ strmode.3 2009-11-18 18:24:35.000000000 -0800
+@@ -39,7 +39,10 @@
.Sh SYNOPSIS
.In string.h
.Ft void
* 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.
static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strmode.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strmode.c,v 1.8 2009/04/14 11:39:56 trasz Exp $");
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void
-strmode(mode, p)
- mode_t mode;
- char *p;
+strmode(/* mode_t */ int mode, char *p)
{
/* print type */
switch (mode & S_IFMT) {
*p++ = 't';
break;
}
- *p++ = ' '; /* will be a '+' if ACL's implemented */
+ *p++ = ' ';
*p = '\0';
}
* 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.
static char sccsid[] = "@(#)strncat.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strncat.c,v 1.6 2002/09/06 11:24:06 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strncat.c,v 1.7 2007/01/09 00:28:12 imp Exp $");
#include <string.h>
* 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.
static char sccsid[] = "@(#)strncmp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strncmp.c,v 1.5 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strncmp.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
int
-strncmp(s1, s2, n)
- const char *s1, *s2;
- size_t n;
+strncmp(const char *s1, const char *s2, size_t n)
{
if (n == 0)
if (*s1 != *s2++)
return (*(const unsigned char *)s1 -
*(const unsigned char *)(s2 - 1));
- if (*s1++ == 0)
+ if (*s1++ == '\0')
break;
} while (--n != 0);
return (0);
* 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.
static char sccsid[] = "@(#)strncpy.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strncpy.c,v 1.6 2002/09/06 11:24:06 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strncpy.c,v 1.8 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
const char *s = src;
do {
- if ((*d++ = *s++) == 0) {
+ if ((*d++ = *s++) == '\0') {
/* NUL pad the remaining n-1 bytes */
while (--n != 0)
- *d++ = 0;
+ *d++ = '\0';
break;
}
} while (--n != 0);
--- /dev/null
+/* $NetBSD: strndup.c,v 1.3 2007/01/14 23:41:24 cbiere Exp $ */
+
+/*
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strndup.c,v 1.1 2008/12/06 09:37:54 kib Exp $");
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+strndup(const char *str, size_t n)
+{
+ size_t len;
+ char *copy;
+
+ for (len = 0; len < n && str[len]; len++)
+ continue;
+
+ if ((copy = malloc(len + 1)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ copy[len] = '\0';
+ return (copy);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/strnlen.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#include <string.h>
+
+size_t
+strnlen(const char *s, size_t maxlen)
+{
+ size_t len;
+
+ for (len = 0; len < maxlen; len++, s++) {
+ if (!*s)
+ break;
+ }
+ return (len);
+}
* 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.
static char sccsid[] = "@(#)strstr.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strnstr.c,v 1.3 2005/02/11 21:07:51 pjd Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strnstr.c,v 1.5 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
* first slen characters of s.
*/
char *
-strnstr(s, find, slen)
- const char *s;
- const char *find;
- size_t slen;
+strnstr(const char *s, const char *find, size_t slen)
{
char c, sc;
size_t len;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strpbrk.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strpbrk.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strpbrk.3,v 1.9 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt STRPBRK 3
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcspbrk 3
.Sh STANDARDS
The
.Fn strpbrk
---- _SB/Libc/string/FreeBSD/strpbrk.3 2003-05-20 15:23:55.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strpbrk.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,20 +47,23 @@
+--- strpbrk.3.bsdnew 2009-11-18 18:24:36.000000000 -0800
++++ strpbrk.3 2009-11-18 18:24:36.000000000 -0800
+@@ -43,20 +43,23 @@
.Sh SYNOPSIS
.In string.h
.Ft char *
* 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.
static char sccsid[] = "@(#)strpbrk.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strpbrk.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strpbrk.c,v 1.6 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
* Find the first occurrence in s1 of a character in s2 (excluding NUL).
*/
char *
-strpbrk(s1, s2)
- const char *s1, *s2;
+strpbrk(const char *s1, const char *s2)
{
const char *scanp;
int c, sc;
while ((c = *s1++) != 0) {
- for (scanp = s2; (sc = *scanp++) != 0;)
+ for (scanp = s2; (sc = *scanp++) != '\0';)
if (sc == c)
return ((char *)(s1 - 1));
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strsep.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/strsep.3,v 1.14 2004/07/02 23:52:13 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strsep.3,v 1.16 2008/12/05 15:50:59 pjd Exp $
.\"
-.Dd June 9, 1993
+.Dd December 5, 2008
.Dt STRSEP 3
.Os
.Sh NAME
.Sh EXAMPLES
The following uses
.Fn strsep
+to parse a string, and prints each token in separate line:
+.Bd -literal -offset indent
+char *token, *string, *tofree;
+
+tofree = string = strdup("abc,def,ghi");
+assert(string != NULL);
+
+while ((token = strsep(&string, ",")) != NULL)
+ printf("%s\en", token);
+
+free(tofree);
+.Ed
+.Pp
+The following uses
+.Fn strsep
to parse a string, containing tokens delimited by white space, into an
argument vector:
.Bd -literal -offset indent
* 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.
static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strsep.c,v 1.5 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strsep.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
#include <stdio.h>
* If *stringp is NULL, strsep returns NULL.
*/
char *
-strsep(stringp, delim)
- char **stringp;
- const char *delim;
+strsep(char **stringp, const char *delim)
{
char *s;
const char *spanp;
* 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.
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strsignal.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strsignal.c,v 1.9 2010/01/24 10:35:26 ume Exp $");
-#include <stdio.h>
+#include "namespace.h"
+#if defined(NLS)
+#include <nl_types.h>
+#endif
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include "reentrant.h"
+#include "un-namespace.h"
+#define UPREFIX "Unknown signal"
+
+static char sig_ebuf[NL_TEXTMAX];
+static char sig_ebuf_err[NL_TEXTMAX];
+static once_t sig_init_once = ONCE_INITIALIZER;
+static thread_key_t sig_key;
+static int sig_keycreated = 0;
+
+static void
+sig_keycreate(void)
+{
+ sig_keycreated = (thr_keycreate(&sig_key, free) == 0);
+}
+
+static char *
+sig_tlsalloc(void)
+{
+ char *ebuf = NULL;
+
+ if (thr_main() != 0)
+ ebuf = sig_ebuf;
+ else {
+ if (thr_once(&sig_init_once, sig_keycreate) != 0 ||
+ !sig_keycreated)
+ goto thr_err;
+ if ((ebuf = thr_getspecific(sig_key)) == NULL) {
+ if ((ebuf = malloc(sizeof(sig_ebuf))) == NULL)
+ goto thr_err;
+ if (thr_setspecific(sig_key, ebuf) != 0) {
+ free(ebuf);
+ ebuf = NULL;
+ goto thr_err;
+ }
+ }
+ }
+thr_err:
+ if (ebuf == NULL)
+ ebuf = sig_ebuf_err;
+ return (ebuf);
+}
+
+/* XXX: negative 'num' ? (REGR) */
char *
-strsignal(num)
- int num;
+strsignal(int num)
{
-#define UPREFIX "Unknown signal: "
- static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
- unsigned int signum;
- char *p, *t;
- char tmp[40];
+ char *ebuf;
+ char tmp[20];
+ size_t n;
+ int signum;
+ char *t, *p;
- signum = num; /* convert to unsigned */
- if (signum < sys_nsig)
- return ((char *)sys_siglist[signum]);
+#if defined(NLS)
+ int saved_errno = errno;
+ nl_catd catd;
+ catd = catopen("libc", NL_CAT_LOCALE);
+#endif
- /* Do this by hand, so we don't link to stdio(3). */
- t = tmp;
+ ebuf = sig_tlsalloc();
+
+ if (num > 0 && num < sys_nsig) {
+ n = strlcpy(ebuf,
+#if defined(NLS)
+ catgets(catd, 2, num, sys_siglist[num]),
+#else
+ sys_siglist[num],
+#endif
+ sizeof(sig_ebuf));
+ } else {
+ n = strlcpy(ebuf,
+#if defined(NLS)
+ catgets(catd, 2, 0xffff, UPREFIX),
+#else
+ UPREFIX,
+#endif
+ sizeof(sig_ebuf));
+ }
+
+ signum = num;
if (num < 0)
signum = -signum;
+
+ t = tmp;
do {
*t++ = "0123456789"[signum % 10];
} while (signum /= 10);
if (num < 0)
*t++ = '-';
- for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+
+ p = (ebuf + n);
+ *p++ = ':';
+ *p++ = ' ';
+
+ for (;;) {
*p++ = *--t;
if (t <= tmp)
break;
}
*p = '\0';
+
+#if defined(NLS)
+ catclose(catd);
+ errno = saved_errno;
+#endif
return (ebuf);
}
---- strsignal.c.orig Thu Mar 21 10:44:54 2002
-+++ strsignal.c Thu May 8 00:44:31 2003
-@@ -52,7 +52,7 @@
- char tmp[40];
+--- strsignal.c.orig 2010-01-24 02:35:26.000000000 -0800
++++ strsignal.c 2010-05-06 12:29:53.000000000 -0700
+@@ -47,8 +47,6 @@ __FBSDID("$FreeBSD: src/lib/libc/string/
- signum = num; /* convert to unsigned */
-- if (signum < sys_nsig)
-+ if (signum < NSIG)
- return ((char *)sys_siglist[signum]);
+ #define UPREFIX "Unknown signal"
- /* Do this by hand, so we don't link to stdio(3). */
+-static char sig_ebuf[NL_TEXTMAX];
+-static char sig_ebuf_err[NL_TEXTMAX];
+ static once_t sig_init_once = ONCE_INITIALIZER;
+ static thread_key_t sig_key;
+ static int sig_keycreated = 0;
+@@ -64,25 +62,19 @@ sig_tlsalloc(void)
+ {
+ char *ebuf = NULL;
+
+- if (thr_main() != 0)
+- ebuf = sig_ebuf;
+- else {
+- if (thr_once(&sig_init_once, sig_keycreate) != 0 ||
+- !sig_keycreated)
++ if (thr_once(&sig_init_once, sig_keycreate) != 0 ||
++ !sig_keycreated)
++ goto thr_err;
++ if ((ebuf = thr_getspecific(sig_key)) == NULL) {
++ if ((ebuf = malloc(NL_TEXTMAX * sizeof(char))) == NULL)
++ goto thr_err;
++ if (thr_setspecific(sig_key, ebuf) != 0) {
++ free(ebuf);
++ ebuf = NULL;
+ goto thr_err;
+- if ((ebuf = thr_getspecific(sig_key)) == NULL) {
+- if ((ebuf = malloc(sizeof(sig_ebuf))) == NULL)
+- goto thr_err;
+- if (thr_setspecific(sig_key, ebuf) != 0) {
+- free(ebuf);
+- ebuf = NULL;
+- goto thr_err;
+- }
+ }
+ }
+ thr_err:
+- if (ebuf == NULL)
+- ebuf = sig_ebuf_err;
+ return (ebuf);
+ }
+
+@@ -103,15 +95,19 @@ strsignal(int num)
+ #endif
+
+ ebuf = sig_tlsalloc();
++ if(ebuf == NULL) {
++ errno = ENOMEM;
++ return NULL;
++ }
+
+- if (num > 0 && num < sys_nsig) {
++ if (num > 0 && num < NSIG) {
+ n = strlcpy(ebuf,
+ #if defined(NLS)
+ catgets(catd, 2, num, sys_siglist[num]),
+ #else
+ sys_siglist[num],
+ #endif
+- sizeof(sig_ebuf));
++ NL_TEXTMAX * sizeof(char));
+ } else {
+ n = strlcpy(ebuf,
+ #if defined(NLS)
+@@ -119,7 +115,7 @@ strsignal(int num)
+ #else
+ UPREFIX,
+ #endif
+- sizeof(sig_ebuf));
++ NL_TEXTMAX * sizeof(char));
+ }
+
+ signum = num;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strspn.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.8 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.11 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt STRSPN 3
.Fa s
as long as the characters from
.Fa s
-occur in string
+occur in the null-terminated string
.Fa charset .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is not in
+.Fa charset ,
+else the index of the first null character.
.Sh RETURN VALUES
The
.Fn strspn
.Xr strrchr 3 ,
.Xr strsep 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcsspn 3
.Sh STANDARDS
The
.Fn strspn
---- _SB/Libc/string/FreeBSD/strspn.3 2003-05-20 15:23:55.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strspn.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -47,17 +47,20 @@
+--- strspn.3.bsdnew 2009-11-30 13:52:24.000000000 -0800
++++ strspn.3 2009-11-30 14:55:45.000000000 -0800
+@@ -43,23 +43,26 @@
.Sh SYNOPSIS
.In string.h
.Ft size_t
as long as the characters from
-.Fa s
+.Fa s1
- occur in string
+ occur in the null-terminated string
-.Fa charset .
+.Fa s2 .
+ In other words, it computes the string array index in
+-.Fa s
++.Fa s1
+ of the first character of
+-.Fa s
++.Fa s1
+ which is not in
+-.Fa charset ,
++.Fa s2 ,
+ else the index of the first null character.
.Sh RETURN VALUES
The
- .Fn strspn
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strstr.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strstr.3,v 1.12 2001/11/20 14:11:07 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strstr.3,v 1.15 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd October 11, 2001
.Dt STRSTR 3
.Ed
.Sh SEE ALSO
.Xr memchr 3 ,
+.Xr memmem 3 ,
.Xr strchr 3 ,
.Xr strcspn 3 ,
.Xr strpbrk 3 ,
.Xr strrchr 3 ,
.Xr strsep 3 ,
.Xr strspn 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcsstr 3
.Sh STANDARDS
The
.Fn strstr
---- _SB/Libc/string/FreeBSD/strstr.3 2003-05-20 15:23:55.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strstr.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -41,26 +41,47 @@
+--- strstr.3.bsdnew 2009-11-30 13:52:24.000000000 -0800
++++ strstr.3 2009-11-30 14:58:48.000000000 -0800
+@@ -37,26 +37,47 @@
.Dt STRSTR 3
.Os
.Sh NAME
.Pp
The
.Fn strcasestr
-@@ -72,11 +93,11 @@
+@@ -68,11 +89,11 @@ The
.Fn strnstr
function
locates the first occurrence of the null-terminated string
characters are searched.
Characters that appear after a
.Ql \e0
-@@ -86,20 +107,28 @@
+@@ -82,20 +103,28 @@ Since the
function is a
.Fx
specific API, it should only be used when portability is not a concern.
is returned.
.Sh EXAMPLES
The following sets the pointer
-@@ -138,7 +167,8 @@
- .Xr strrchr 3 ,
+@@ -128,7 +157,6 @@ ptr = strnstr(largestring, smallstring,
+ .Ed
+ .Sh SEE ALSO
+ .Xr memchr 3 ,
+-.Xr memmem 3 ,
+ .Xr strchr 3 ,
+ .Xr strcspn 3 ,
+ .Xr strpbrk 3 ,
+@@ -136,7 +164,8 @@ ptr = strnstr(largestring, smallstring,
.Xr strsep 3 ,
.Xr strspn 3 ,
--.Xr strtok 3
-+.Xr strtok 3 ,
+ .Xr strtok 3 ,
+-.Xr wcsstr 3
++.Xr wcsstr 3 ,
+.Xr xlocale 3
.Sh STANDARDS
The
* 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.
static char sccsid[] = "@(#)strstr.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strstr.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strstr.c,v 1.6 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
* Find the first occurrence of find in s.
*/
char *
-strstr(s, find)
- const char *s, *find;
+strstr(const char *s, const char *find)
{
char c, sc;
size_t len;
- if ((c = *find++) != 0) {
+ if ((c = *find++) != '\0') {
len = strlen(find);
do {
do {
- if ((sc = *s++) == 0)
+ if ((sc = *s++) == '\0')
return (NULL);
} while (sc != c);
} while (strncmp(s, find, len) != 0);
.\" 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 Softweyr LLC, the
-.\" University of California, Berkeley, and its contributors.
-.\"
.\" 4. Neither the name of Softweyr LLC, the University nor the names
.\" of its contributors may be used to endorse or promote products
.\" derived from this software without specific prior written
.\" SUCH DAMAGE.
.\"
.\" @(#)strtok.3 8.2 (Berkeley) 2/3/94
-.\" $FreeBSD: src/lib/libc/string/strtok.3,v 1.24 2002/12/18 12:45:11 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strtok.3,v 1.26 2007/12/12 18:33:06 wes Exp $
.\"
.Dd November 27, 1998
.Dt STRTOK 3
function
conforms to
.St -isoC .
+.Sh AUTHORS
+.An Wes Peters ,
+Softweyr LLC:
+.Aq wes@softweyr.com
+.Pp
+Based on the
+.Fx 3.0
+implementation.
.Sh BUGS
The System V
.Fn strtok ,
Since this implementation always alters the next starting point,
such a sequence of calls would always return
.Dv NULL .
-.Sh AUTHORS
-.An Wes Peters ,
-Softweyr LLC:
-.Aq wes@softweyr.com
-.Pp
-Based on the
-.Fx 3.0
-implementation.
---- _SB/Libc/string/FreeBSD/strtok.3 2003-05-20 15:23:55.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strtok.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -61,9 +61,16 @@
+--- strtok.3.bsdnew 2009-11-18 18:24:37.000000000 -0800
++++ strtok.3 2009-11-18 18:24:37.000000000 -0800
+@@ -55,9 +55,16 @@
.Sh SYNOPSIS
.In string.h
.Ft char *
* 2. Redistributions in binary form must reproduce the above copyright
* notices, 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 Softweyr LLC, 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.
static char sccsid[] = "@(#)strtok.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strtok.c,v 1.9 2002/09/07 02:53:19 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strtok.c,v 1.10 2007/12/12 18:33:06 wes Exp $");
#include <stddef.h>
#ifdef DEBUG_STRTOK
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strxfrm.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strxfrm.3,v 1.17 2002/10/15 10:11:53 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/strxfrm.3,v 1.18 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt STRXFRM 3
---- _SB/Libc/string/FreeBSD/strxfrm.3 2003-05-20 15:23:55.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/strxfrm.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -40,34 +40,48 @@
+--- strxfrm.3.bsdnew 2009-11-18 18:24:38.000000000 -0800
++++ strxfrm.3 2009-11-18 18:24:38.000000000 -0800
+@@ -36,34 +36,48 @@
.Dt STRXFRM 3
.Os
.Sh NAME
is permitted to be a NULL pointer.
.Pp
Comparing two strings using
-@@ -77,6 +91,14 @@
+@@ -73,6 +87,14 @@ after
is equal to comparing
two original strings with
.Fn strcoll .
.Sh RETURN VALUES
Upon successful completion,
.Fn strxfrm
-@@ -85,13 +107,14 @@
+@@ -81,13 +103,14 @@ the terminating null character.
If this value is
.Fa n
or more, the contents of
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strxfrm.c,v 1.17 2008/10/19 09:10:44 delphij Exp $");
#include <stdlib.h>
#include <string.h>
return 0;
}
- if (__collate_load_error) {
- slen = strlen(src);
- if (len > 0) {
- if (slen < len)
- strcpy(dest, src);
- else {
- strncpy(dest, src, len - 1);
- dest[len - 1] = '\0';
- }
- }
- return slen;
- }
+ if (__collate_load_error)
+ return strlcpy(dest, src, len);
slen = 0;
prim = sec = 0;
---- strxfrm.c.orig 2003-05-20 15:23:55.000000000 -0700
-+++ strxfrm.c 2005-04-02 17:59:53.000000000 -0800
-@@ -28,24 +28,59 @@
+--- strxfrm.c.bsdnew 2009-11-18 18:24:38.000000000 -0800
++++ strxfrm.c 2009-11-18 18:38:07.000000000 -0800
+@@ -28,46 +28,118 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/string/strxfrm.c,v 1.17 2008/10/19 09:10:44 delphij Exp $");
+#include "xlocale_private.h"
+
return 0;
}
-- if (__collate_load_error) {
+- if (__collate_load_error)
+ NORMALIZE_LOCALE(loc);
-+ if (loc->__collate_load_error || (wcs = __collate_mbstowcs(src, loc)) == NULL) {
- slen = strlen(src);
- if (len > 0) {
- if (slen < len)
-@@ -58,26 +93,63 @@
- return slen;
- }
++ if (loc->__collate_load_error || (wcs = __collate_mbstowcs(src, loc)) == NULL)
+ return strlcpy(dest, src, len);
- slen = 0;
- prim = sec = 0;
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)swab.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/swab.3,v 1.7 2002/08/30 21:18:39 robert Exp $
+.\" $FreeBSD: src/lib/libc/string/swab.3,v 1.10 2007/01/09 00:28:12 imp Exp $
.\"
-.Dd June 4, 1993
+.Dd December 10, 2004
.Dt SWAB 3
.Os
.Sh NAME
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In string.h
+.In unistd.h
.Ft void
-.Fn swab "const void * restrict src" "void * restrict dst" "size_t len"
+.Fn swab "const void * restrict src" "void * restrict dst" "ssize_t len"
.Sh DESCRIPTION
The function
.Fn swab
---- swab.3 2003-05-20 15:23:55.000000000 -0700
-+++ swab.3.edit 2006-07-12 11:27:22.000000000 -0700
-@@ -41,26 +41,48 @@
- .Sh LIBRARY
- .Lb libc
+--- swab.3.orig 2010-02-24 20:50:11.000000000 -0800
++++ swab.3 2010-02-24 21:17:49.000000000 -0800
+@@ -28,7 +28,7 @@
+ .\" @(#)swab.3 8.1 (Berkeley) 6/4/93
+ .\" $FreeBSD: src/lib/libc/string/swab.3,v 1.10 2007/01/09 00:28:12 imp Exp $
+ .\"
+-.Dd December 10, 2004
++.Dd February 24, 2010
+ .Dt SWAB 3
+ .Os
+ .Sh NAME
+@@ -39,24 +39,41 @@
.Sh SYNOPSIS
--.In string.h
-+.In unistd.h
+ .In unistd.h
.Ft void
--.Fn swab "const void * restrict src" "void * restrict dst" "size_t len"
+-.Fn swab "const void * restrict src" "void * restrict dst" "ssize_t len"
+.Fo swab
+.Fa "const void *restrict src"
+.Fa "void *restrict dest"
.Pp
The argument
-.Fa len
+-must be an even number.
+.Fa nbytes
- must be an even number.
-+.Sh LEGACY SYNOPSIS
-+.Fd #include <string.h>
-+.Pp
-+.Ft void
-+.br
-+.Fo swab
-+.Fa "const void *restrict src"
-+.Fa "void *restrict dest"
-+.Fa "size_t nbytes"
-+.Fc ;
-+.Pp
-+The include file
-+.In string.h
-+is necessary for this function.
-+The type of
++should be an even number. If
++.Fa nbytes
++is odd,
++.Fn swab
++copies and exchanges
++.Fa nbytes
++-1 bytes and the disposition of the last byte is unspecified.
++If copying takes place between objects that overlap,
++the behavior is undefined. If
+.Fa nbytes
-+has changed.
++is negative,
++.Fn swab
++does nothing.
.Sh SEE ALSO
.Xr bzero 3 ,
-.Xr memset 3
* 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.
static char sccsid[] = "@(#)swab.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/swab.c,v 1.5 2002/08/30 20:33:05 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/swab.c,v 1.7 2007/01/09 00:28:12 imp Exp $");
-#include <string.h>
+#include <unistd.h>
void
-swab(const void * __restrict from, void * __restrict to, size_t len)
+swab(const void * __restrict from, void * __restrict to, ssize_t len)
{
unsigned long temp;
int n;
---- swab.c.orig 2004-08-03 14:33:13.000000000 -0700
-+++ swab.c 2004-08-03 15:05:03.000000000 -0700
-@@ -43,12 +43,14 @@
- #include <string.h>
-
- void
--swab(const void * __restrict from, void * __restrict to, size_t len)
-+swab(const void * __restrict from, void * __restrict to, ssize_t len)
- {
- unsigned long temp;
+--- swab.c.bsdnew 2009-11-18 18:24:38.000000000 -0800
++++ swab.c 2009-11-18 18:40:17.000000000 -0800
+@@ -45,6 +45,8 @@ swab(const void * __restrict from, void
int n;
char *fp, *tp;
--- /dev/null
+/*
+ * Copyright (c) 1999
+ * David E. O'Brien
+ * 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. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcpcpy.c,v 1.1 2009/03/04 06:01:27 das Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+wcpcpy(wchar_t * __restrict to, const wchar_t * __restrict from)
+{
+
+ for (; (*to = *from); ++from, ++to);
+ return(to);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcpncpy.c,v 1.1 2009/03/04 06:01:27 das Exp $");
+
+#include <wchar.h>
+
+wchar_t *
+wcpncpy(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n)
+{
+
+ for (; n--; dst++, src++) {
+ if (!(*dst = *src)) {
+ wchar_t *ret = dst;
+ while (n--)
+ *++dst = L'\0';
+ return (ret);
+ }
+ }
+ return (dst);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscasecmp.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcscasecmp(const wchar_t *s1, const wchar_t *s2)
+{
+ wchar_t c1, c2;
+
+ for (; *s1; s1++, s2++) {
+ c1 = towlower(*s1);
+ c2 = towlower(*s2);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ }
+ return (-*s2);
+}
--- /dev/null
+--- wcscasecmp.c.orig 2009-12-16 12:51:30.000000000 -0800
++++ wcscasecmp.c 2009-12-16 12:59:33.000000000 -0800
+@@ -27,19 +27,27 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/string/wcscasecmp.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
++#include "xlocale_private.h"
++
+ #include <wchar.h>
+ #include <wctype.h>
+
+ int
+-wcscasecmp(const wchar_t *s1, const wchar_t *s2)
++wcscasecmp_l(const wchar_t *s1, const wchar_t *s2, locale_t loc)
+ {
+ wchar_t c1, c2;
+
+ for (; *s1; s1++, s2++) {
+- c1 = towlower(*s1);
+- c2 = towlower(*s2);
++ c1 = towlower_l(*s1, loc);
++ c2 = towlower_l(*s2, loc);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ }
+ return (-*s2);
+ }
++
++int
++wcscasecmp(const wchar_t *s1, const wchar_t *s2) {
++ return wcscasecmp_l(s1, s2, __current_locale());
++}
++
__RCSID("$NetBSD: wcscat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcscat.c,v 1.8 2002/09/26 09:28:55 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscat.c,v 1.9 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
wchar_t *
-wcscat(s1, s2)
- wchar_t * __restrict s1;
- const wchar_t * __restrict s2;
+wcscat(wchar_t * __restrict s1, const wchar_t * __restrict s2)
{
wchar_t *cp;
* 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.
__RCSID("$NetBSD: wcscmp.c,v 1.3 2001/01/05 12:13:12 itojun Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
-__FBSDID("$FreeBSD: src/lib/libc/string/wcscmp.c,v 1.7 2002/10/23 11:08:40 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscmp.c,v 1.9 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
* Compare strings.
*/
int
-wcscmp(s1, s2)
- const wchar_t *s1, *s2;
+wcscmp(const wchar_t *s1, const wchar_t *s2)
{
while (*s1 == *s2++)
- if (*s1++ == 0)
+ if (*s1++ == '\0')
return (0);
/* XXX assumes wchar_t = int */
return (*(const unsigned int *)s1 - *(const unsigned int *)--s2);
.\" 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.
.\"
.\" @(#)strcoll.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/string/strcoll.3,v 1.11 2001/10/01 16:09:00 ru Exp
-.\" $FreeBSD: src/lib/libc/string/wcscoll.3,v 1.2 2002/12/09 14:04:05 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/wcscoll.3,v 1.3 2007/01/09 00:28:12 imp Exp $
.\"
.Dd October 4, 2002
.Dt WCSCOLL 3
---- _SB/Libc/string/FreeBSD/wcscoll.3 2003-05-20 15:23:55.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/wcscoll.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -41,37 +41,57 @@
+--- wcscoll.3.bsdnew 2009-11-18 18:24:39.000000000 -0800
++++ wcscoll.3 2009-11-18 18:24:39.000000000 -0800
+@@ -37,37 +37,57 @@
.Dt WCSCOLL 3
.Os
.Sh NAME
.Pp
No return value is reserved to indicate errors;
callers should set
-@@ -95,7 +115,8 @@
+@@ -91,7 +111,8 @@ Cannot allocate enough memory for tempor
.Xr setlocale 3 ,
.Xr strcoll 3 ,
.Xr wcscmp 3 ,
__RCSID("$NetBSD: wcscpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcscpy.c,v 1.8 2002/09/26 09:23:07 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscpy.c,v 1.9 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
wchar_t *
-wcscpy(s1, s2)
- wchar_t * __restrict s1;
- const wchar_t * __restrict s2;
+wcscpy(wchar_t * __restrict s1, const wchar_t * __restrict s2)
{
wchar_t *cp;
__RCSID("$NetBSD: wcscspn.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcscspn.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscspn.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
size_t
-wcscspn(s, set)
- const wchar_t *s;
- const wchar_t *set;
+wcscspn(const wchar_t *s, const wchar_t *set)
{
const wchar_t *p;
const wchar_t *q;
--- /dev/null
+/*-
+ * Copyright (c) 2005 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsdup.c,v 1.1 2005/08/13 05:54:33 tjr Exp $");
+
+#include <stdlib.h>
+#include <wchar.h>
+
+wchar_t *
+wcsdup(const wchar_t *s)
+{
+ wchar_t *copy;
+ size_t len;
+
+ len = wcslen(s) + 1;
+ if ((copy = malloc(len * sizeof(wchar_t))) == NULL)
+ return (NULL);
+ return (wmemcpy(copy, s, len));
+}
__RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcslcat.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcslcat.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <sys/types.h>
#include <wchar.h>
* truncation occurred.
*/
size_t
-wcslcat(dst, src, siz)
- wchar_t *dst;
- const wchar_t *src;
- size_t siz;
+wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
{
wchar_t *d = dst;
const wchar_t *s = src;
__RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcslcpy.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcslcpy.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <sys/types.h>
#include <wchar.h>
* Returns wcslen(src); if retval >= siz, truncation occurred.
*/
size_t
-wcslcpy(dst, src, siz)
- wchar_t *dst;
- const wchar_t *src;
- size_t siz;
+wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
{
wchar_t *d = dst;
const wchar_t *s = src;
__RCSID("$NetBSD: wcslen.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcslen.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcslen.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
size_t
-wcslen(s)
- const wchar_t *s;
+wcslen(const wchar_t *s)
{
const wchar_t *p;
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncasecmp.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+ wchar_t c1, c2;
+
+ if (n == 0)
+ return (0);
+ for (; *s1; s1++, s2++) {
+ c1 = towlower(*s1);
+ c2 = towlower(*s2);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ if (--n == 0)
+ return (0);
+ }
+ return (-*s2);
+}
--- /dev/null
+--- wcsncasecmp.c.orig 2009-12-16 12:51:30.000000000 -0800
++++ wcsncasecmp.c 2009-12-16 13:02:55.000000000 -0800
+@@ -27,19 +27,21 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD: src/lib/libc/string/wcsncasecmp.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
++#include "xlocale_private.h"
++
+ #include <wchar.h>
+ #include <wctype.h>
+
+ int
+-wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
++wcsncasecmp_l(const wchar_t *s1, const wchar_t *s2, size_t n, locale_t loc)
+ {
+ wchar_t c1, c2;
+
+ if (n == 0)
+ return (0);
+ for (; *s1; s1++, s2++) {
+- c1 = towlower(*s1);
+- c2 = towlower(*s2);
++ c1 = towlower_l(*s1, loc);
++ c2 = towlower_l(*s2, loc);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ if (--n == 0)
+@@ -47,3 +49,9 @@ wcsncasecmp(const wchar_t *s1, const wch
+ }
+ return (-*s2);
+ }
++
++int
++wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
++ return wcsncasecmp_l(s1, s2, n, __current_locale());
++}
++
__RCSID("$NetBSD: wcsncat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcsncat.c,v 1.7 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncat.c,v 1.8 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
wchar_t *
-wcsncat(s1, s2, n)
- wchar_t * __restrict s1;
- const wchar_t * __restrict s2;
- size_t n;
+wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n)
{
wchar_t *p;
wchar_t *q;
* 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.
__RCSID("$NetBSD: wcsncmp.c,v 1.3 2001/01/05 12:13:13 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcsncmp.c,v 1.7 2002/10/23 11:08:40 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncmp.c,v 1.9 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
int
-wcsncmp(s1, s2, n)
- const wchar_t *s1, *s2;
- size_t n;
+wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
{
if (n == 0)
* 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.
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/wcsncpy.c,v 1.9 2002/10/24 02:48:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncpy.c,v 1.10 2007/01/09 00:28:12 imp Exp $");
#include <wchar.h>
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsnlen.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#include <wchar.h>
+
+size_t
+wcsnlen(const wchar_t *s, size_t maxlen)
+{
+ size_t len;
+
+ for (len = 0; len < maxlen; len++, s++) {
+ if (!*s)
+ break;
+ }
+ return (len);
+}
__RCSID("$NetBSD: wcspbrk.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcspbrk.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcspbrk.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
wchar_t *
-wcspbrk(s, set)
- const wchar_t *s;
- const wchar_t *set;
+wcspbrk(const wchar_t *s, const wchar_t *set)
{
const wchar_t *p;
const wchar_t *q;
__RCSID("$NetBSD: wcsspn.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wcsspn.c,v 1.7 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsspn.c,v 1.8 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
size_t
-wcsspn(s, set)
- const wchar_t *s;
- const wchar_t *set;
+wcsspn(const wchar_t *s, const wchar_t *set)
{
const wchar_t *p;
const wchar_t *q;
* 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.
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/wcsstr.c,v 1.8 2002/10/24 02:53:45 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsstr.c,v 1.10 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
wchar_t c, sc;
size_t len;
- if ((c = *find++) != 0) {
+ if ((c = *find++) != L'\0') {
len = wcslen(find);
do {
do {
* 2. Redistributions in binary form must reproduce the above copyright
* notices, 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 Softweyr LLC, 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/wcstok.c,v 1.2 2003/03/12 06:41:49 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcstok.c,v 1.3 2007/12/12 18:33:06 wes Exp $");
#include <wchar.h>
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/wcswidth.c,v 1.6 2002/08/20 02:06:28 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcswidth.c,v 1.7 2007/01/09 00:28:12 imp Exp $");
#include <wchar.h>
---- wcswidth.c.orig 2003-05-20 15:23:56.000000000 -0700
-+++ wcswidth.c 2005-02-25 00:12:43.000000000 -0800
-@@ -42,20 +42,30 @@
+--- wcswidth.c.bsdnew 2009-11-18 18:24:40.000000000 -0800
++++ wcswidth.c 2009-11-18 18:24:41.000000000 -0800
+@@ -38,20 +38,30 @@
#include <sys/cdefs.h>
- __FBSDID("$FreeBSD: src/lib/libc/string/wcswidth.c,v 1.6 2002/08/20 02:06:28 ache Exp $");
+ __FBSDID("$FreeBSD: src/lib/libc/string/wcswidth.c,v 1.7 2007/01/09 00:28:12 imp Exp $");
+#include "xlocale_private.h"
+
.\" 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.
.\"
.\" @(#)strxfrm.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/string/strxfrm.3,v 1.16 2002/09/06 11:24:06 tjr Exp
-.\" $FreeBSD: src/lib/libc/string/wcsxfrm.3,v 1.2 2002/12/09 14:04:05 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/wcsxfrm.3,v 1.3 2007/01/09 00:28:12 imp Exp $
.\"
.Dd October 4, 2002
.Dt WCSXFRM 3
---- _SB/Libc/string/FreeBSD/wcsxfrm.3 2003-05-20 15:23:56.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/wcsxfrm.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -41,34 +41,47 @@
+--- wcsxfrm.3.bsdnew 2009-11-18 18:24:41.000000000 -0800
++++ wcsxfrm.3 2009-11-18 18:24:41.000000000 -0800
+@@ -37,34 +37,47 @@
.Dt WCSXFRM 3
.Os
.Sh NAME
is permitted to be a
.Dv NULL
pointer.
-@@ -80,6 +93,14 @@
+@@ -76,6 +89,14 @@ after
is equivalent to comparing
two original strings with
.Fn wcscoll .
.Sh RETURN VALUES
Upon successful completion,
.Fn wcsxfrm
-@@ -88,13 +109,14 @@
+@@ -84,13 +105,14 @@ the terminating null character.
If this value is
.Fa n
or more, the contents of
.Sh STANDARDS
The
.Fn wcsxfrm
-@@ -120,7 +142,7 @@
+@@ -116,7 +138,7 @@ always equivalent to comparison with
.Fn wcscoll ;
.Fn wcsxfrm
only stores information about primary collation weights into
.\" 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.
.\"
.\" from: @(#)strcpy.3 8.1 (Berkeley) 6/4/93
.\"
-.\" $FreeBSD: src/lib/libc/string/wmemchr.3,v 1.6 2002/09/07 04:07:00 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/wmemchr.3,v 1.10 2009/03/04 06:01:27 das Exp $
.\"
-.Dd December 22, 2000
+.Dd March 4, 2009
.Dt WMEMCHR 3
.Os
.Sh NAME
.Nm wmemcpy ,
.Nm wmemmove ,
.Nm wmemset ,
+.Nm wcpcpy ,
+.Nm wcpncpy ,
+.Nm wcscasecmp ,
.Nm wcscat ,
.Nm wcschr ,
.Nm wcscmp ,
.Nm wcscpy ,
.Nm wcscspn ,
+.Nm wcsdup ,
.Nm wcslcat ,
.Nm wcslcpy ,
.Nm wcslen ,
+.Nm wcsncasecmp ,
.Nm wcsncat ,
.Nm wcsncmp ,
.Nm wcsncpy ,
+.Nm wcsnlen ,
.Nm wcspbrk ,
.Nm wcsrchr ,
.Nm wcsspn ,
.Ft wchar_t *
.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n"
.Ft wchar_t *
+.Fn wcpcpy "wchar_t *s1" "wchar_t *s2"
+.Ft wchar_t *
+.Fn wcpncpy "wchar_t *s1" "wchar_t *s2" "size_t n"
+.Ft int
+.Fn wcscasecmp "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
.Fn wcscat "wchar_t * restrict s1" "const wchar_t * restrict s2"
.Ft wchar_t *
.Fn wcschr "const wchar_t *s" "wchar_t c"
.Fn wcscpy "wchar_t * restrict s1" "const wchar_t * restrict s2"
.Ft size_t
.Fn wcscspn "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcsdup "const wchar_t *s"
.Ft size_t
.Fn wcslcat "wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft size_t
.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft size_t
.Fn wcslen "const wchar_t *s"
+.Ft int
+.Fn wcsncasecmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft wchar_t *
.Fn wcsncat "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
.Ft int
.Fn wcsncmp "const wchar_t *s1" "const wchar_t * s2" "size_t n"
.Ft wchar_t *
.Fn wcsncpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
+.Ft size_t
+.Fn wcsnlen "const wchar_t *s" "size_t maxlen"
.Ft wchar_t *
.Fn wcspbrk "const wchar_t *s1" "const wchar_t *s2"
.Ft wchar_t *
.Xr memcpy 3 ,
.Xr memmove 3 ,
.Xr memset 3 ,
+.Xr stpcpy 3 ,
+.Xr stpncpy 3 ,
+.Xr strcasecmp 3 ,
.Xr strcat 3 ,
.Xr strchr 3 ,
.Xr strcmp 3 ,
.Xr strcpy 3 ,
.Xr strcspn 3 ,
+.Xr strdup 3 ,
.Xr strlcat 3 ,
.Xr strlcpy 3 ,
.Xr strlen 3 ,
.Xr strncat 3 ,
.Xr strncmp 3 ,
.Xr strncpy 3 ,
+.Xr strnlen 3 ,
.Xr strpbrk 3 ,
.Xr strrchr 3 ,
.Xr strspn 3 ,
These functions conform to
.St -isoC-99 ,
with the exception of
+.Fn wcpcpy ,
+.Fn wcpncpy ,
+.Fn wcscasecmp ,
+.Fn wcsdup ,
+.Fn wcsncasecmp ,
+and
+.Fn wcsnlen ,
+which conform to
+.St -p1003.1-2008 ;
+and
.Fn wcslcat
and
.Fn wcslcpy ,
---- _SB/Libc/string/FreeBSD/wmemchr.3 2003-05-20 15:23:56.000000000 -0700
-+++ _SB/Libc/string/FreeBSD/wmemchr.3.edit 2006-06-28 16:55:53.000000000 -0700
-@@ -43,11 +43,6 @@
+--- wmemchr.3.orig 2009-12-16 13:19:24.000000000 -0800
++++ wmemchr.3 2009-12-16 13:30:23.000000000 -0800
+@@ -39,11 +39,6 @@
.Dt WMEMCHR 3
.Os
.Sh NAME
-.Nm wmemcpy ,
-.Nm wmemmove ,
-.Nm wmemset ,
- .Nm wcscat ,
- .Nm wcschr ,
- .Nm wcscmp ,
-@@ -62,57 +57,131 @@
+ .Nm wcpcpy ,
+ .Nm wcpncpy ,
+ .Nm wcscasecmp ,
+@@ -64,23 +59,18 @@
.Nm wcspbrk ,
.Nm wcsrchr ,
.Nm wcsspn ,
.In wchar.h
.Ft wchar_t *
-.Fn wmemchr "const wchar_t *s" "wchar_t c" "size_t n"
-+.Fo wcscat
-+.Fa "wchar_t *restrict ws1"
-+.Fa "const wchar_t *restrict ws2"
-+.Fc
-+.Ft wchar_t *
-+.Fo wcschr
-+.Fa "const wchar_t *ws"
-+.Fa "wchar_t wc"
-+.Fc
- .Ft int
+-.Ft int
-.Fn wmemcmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
-.Ft wchar_t *
-.Fn wmemcpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
-.Ft wchar_t *
-.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n"
-.Ft wchar_t *
--.Fn wcscat "wchar_t * restrict s1" "const wchar_t * restrict s2"
--.Ft wchar_t *
--.Fn wcschr "const wchar_t *s" "wchar_t c"
--.Ft int
--.Fn wcscmp "const wchar_t *s1" "const wchar_t *s2"
--.Ft wchar_t *
--.Fn wcscpy "wchar_t * restrict s1" "const wchar_t * restrict s2"
-+.Fo wcscmp
-+.Fa "const wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fc
-+.Ft wchar_t *
-+.Fo wcscpy
-+.Fa "wchar_t *restrict ws1"
-+.Fa "const wchar_t *restrict ws2"
-+.Fc
- .Ft size_t
--.Fn wcscspn "const wchar_t *s1" "const wchar_t *s2"
-+.Fo wcscspn
-+.Fa "const wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fc
- .Ft size_t
--.Fn wcslcat "wchar_t *s1" "const wchar_t *s2" "size_t n"
-+.Fo wcslcat
-+.Fa "wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fa "size_t n"
-+.Fc
- .Ft size_t
--.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n"
-+.Fo wcslcpy
-+.Fa "wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fa "size_t n"
-+.Fc
- .Ft size_t
--.Fn wcslen "const wchar_t *s"
--.Ft wchar_t *
--.Fn wcsncat "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
-+.Fo wcslen
-+.Fa "const wchar_t *ws"
-+.Fc
-+.Ft wchar_t *
-+.Fo wcsncat
-+.Fa "wchar_t *restrict ws1"
-+.Fa "const wchar_t *restrict ws2"
-+.Fa "size_t n"
-+.Fc
- .Ft int
--.Fn wcsncmp "const wchar_t *s1" "const wchar_t * s2" "size_t n"
--.Ft wchar_t *
--.Fn wcsncpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
--.Ft wchar_t *
--.Fn wcspbrk "const wchar_t *s1" "const wchar_t *s2"
--.Ft wchar_t *
--.Fn wcsrchr "const wchar_t *s" "wchar_t c"
-+.Fo wcsncmp
-+.Fa "const wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fa "size_t n"
-+.Fc
-+.Ft wchar_t *
-+.Fo wcsncpy
-+.Fa "wchar_t *restrict ws1"
-+.Fa "const wchar_t *restrict ws2"
-+.Fa "size_t n"
-+.Fc
-+.Ft wchar_t *
-+.Fo wcspbrk
-+.Fa "const wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fc
-+.Ft wchar_t *
-+.Fo wcsrchr
-+.Fa "const wchar_t *ws"
-+.Fa "wchar_t wc"
-+.Fc
- .Ft size_t
--.Fn wcsspn "const wchar_t *s1" "const wchar_t *s2"
--.Ft wchar_t *
--.Fn wcsstr "const wchar_t * restrict s1" "const wchar_t * restrict s2"
-+.Fo wcsspn
-+.Fa "const wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fc
-+.Ft wchar_t *
-+.Fo wcsstr
-+.Fa "const wchar_t *restrict ws1"
-+.Fa "const wchar_t *restrict ws2"
-+.Fc
+ .Fn wcpcpy "wchar_t *s1" "wchar_t *s2"
+ .Ft wchar_t *
+ .Fn wcpncpy "wchar_t *s1" "wchar_t *s2" "size_t n"
+@@ -122,6 +112,22 @@
+ .Fn wcsspn "const wchar_t *s1" "const wchar_t *s2"
+ .Ft wchar_t *
+ .Fn wcsstr "const wchar_t * restrict s1" "const wchar_t * restrict s2"
+.Ft wchar_t *
-+.Fo wmemchr
-+.Fa "const wchar_t *ws"
-+.Fa "wchar_t wc"
-+.Fa "size_t n"
-+.Fc
++.Fn wmemchr "const wchar_t *s" "wchar_t c" "size_t n"
+.Ft int
-+.Fo wmemcmp
-+.Fa "const wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fa "size_t n"
-+.Fc
++.Fn wmemcmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft wchar_t *
-+.Fo wmemcpy
-+.Fa "wchar_t *restrict ws1"
-+.Fa "const wchar_t *restrict ws2"
-+.Fa "size_t n"
-+.Fc
++.Fn wmemcpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
+.Ft wchar_t *
-+.Fo wmemmove
-+.Fa "wchar_t *ws1"
-+.Fa "const wchar_t *ws2"
-+.Fa "size_t n"
-+.Fc
++.Fn wmemmove "wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft wchar_t *
-+.Fo wmemset
-+.Fa "wchar_t *ws"
-+.Fa "wchar_t wc"
-+.Fa "size_t n"
-+.Fc
++.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n"
++.In wchar.h
++.In xlocale.h
++.Ft int
++.Fn wcscasecmp_l "const wchar_t *s1" "const wchar_t *s2" "locale_t loc"
++.Ft int
++.Fn wcsncasecmp_l "const wchar_t *s1" "const wchar_t *s2" "size_t n" "locale_t loc"
.Sh DESCRIPTION
--The functions implement string manipulation operations over wide character
--strings.
--For a detailed description, refer to documents for the respective single-byte
--counterpart, such as
-+The functions implement string manipulation operations
-+over wide character strings.
-+For a detailed description,
-+refer to documents for the respective single-byte counterpart, such as
- .Xr memchr 3 .
- .Sh SEE ALSO
- .Xr memchr 3 ,
+ The functions implement string manipulation operations over wide character
+ strings.
+@@ -137,6 +143,7 @@ counterpart, such as
+ .Xr stpcpy 3 ,
+ .Xr stpncpy 3 ,
+ .Xr strcasecmp 3 ,
++.Xr strcasecmp_l 3 ,
+ .Xr strcat 3 ,
+ .Xr strchr 3 ,
+ .Xr strcmp 3 ,
+@@ -146,6 +153,8 @@ counterpart, such as
+ .Xr strlcat 3 ,
+ .Xr strlcpy 3 ,
+ .Xr strlen 3 ,
++.Xr strncasecmp 3 ,
++.Xr strncasecmp_l 3 ,
+ .Xr strncat 3 ,
+ .Xr strncmp 3 ,
+ .Xr strncpy 3 ,
+@@ -153,7 +162,8 @@ counterpart, such as
+ .Xr strpbrk 3 ,
+ .Xr strrchr 3 ,
+ .Xr strspn 3 ,
+-.Xr strstr 3
++.Xr strstr 3 ,
++.Xr xlocale 3
+ .Sh STANDARDS
+ These functions conform to
+ .St -isoC-99 ,
+@@ -161,8 +171,10 @@ with the exception of
+ .Fn wcpcpy ,
+ .Fn wcpncpy ,
+ .Fn wcscasecmp ,
++.Fn wcscasecmp_l ,
+ .Fn wcsdup ,
+ .Fn wcsncasecmp ,
++.Fn wcsncasecmp_l ,
+ and
+ .Fn wcsnlen ,
+ which conform to
__RCSID("$NetBSD: wmemchr.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wmemchr.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wmemchr.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
wchar_t *
-wmemchr(s, c, n)
- const wchar_t *s;
- wchar_t c;
- size_t n;
+wmemchr(const wchar_t *s, wchar_t c, size_t n)
{
size_t i;
__RCSID("$NetBSD: wmemcmp.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wmemcmp.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wmemcmp.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <wchar.h>
int
-wmemcmp(s1, s2, n)
- const wchar_t *s1;
- const wchar_t *s2;
- size_t n;
+wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n)
{
size_t i;
__RCSID("$NetBSD: wmemcpy.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wmemcpy.c,v 1.7 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wmemcpy.c,v 1.8 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
#include <wchar.h>
wchar_t *
-wmemcpy(d, s, n)
- wchar_t * __restrict d;
- const wchar_t * __restrict s;
- size_t n;
+wmemcpy(wchar_t * __restrict d, const wchar_t * __restrict s, size_t n)
{
-
return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t));
}
__RCSID("$NetBSD: wmemmove.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wmemmove.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wmemmove.c,v 1.7 2009/02/03 17:58:20 danger Exp $");
#include <string.h>
#include <wchar.h>
wchar_t *
-wmemmove(d, s, n)
- wchar_t *d;
- const wchar_t *s;
- size_t n;
+wmemmove(wchar_t *d, const wchar_t *s, size_t n)
{
-
return (wchar_t *)memmove(d, s, n * sizeof(wchar_t));
}
__RCSID("$NetBSD: wmemset.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
-__FBSDID("$FreeBSD: src/lib/libc/string/wmemset.c,v 1.6 2002/09/21 00:29:23 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wmemset.c,v 1.8 2009/02/03 20:25:36 imp Exp $");
#include <wchar.h>
wchar_t *
-wmemset(s, c, n)
- wchar_t *s;
- wchar_t c;
- size_t n;
+wmemset(wchar_t *s, wchar_t c, size_t n)
{
size_t i;
wchar_t *p;
.include "Makefile.fbsd_begin"
# machine-independent string sources
-FBSDMISRCS+=bcmp.c index.c memccpy.c memchr.c memcmp.c \
- memset.c rindex.c stpcpy.c strcasecmp.c strcat.c \
- strchr.c strcoll.c strcpy.c strcspn.c strdup.c strerror.c \
- strlcat.c strlcpy.c strlen.c strmode.c strncat.c strncmp.c strncpy.c \
+FBSDMISRCS+=bcmp.c index.c memccpy.c memchr.c memcmp.c memmem.c \
+ memset.c rindex.c stpcpy.c stpncpy.c strcasecmp.c strcat.c \
+ strchr.c strcoll.c strcpy.c strcspn.c strdup.c strndup.c strerror.c \
+ strlcat.c strlcpy.c strlen.c strmode.c strncat.c strncmp.c strncpy.c strnlen.c \
strcasestr.c strnstr.c \
strpbrk.c strrchr.c strsep.c strsignal.c strspn.c strstr.c strtok.c \
- strxfrm.c swab.c wcscat.c wcschr.c wcscmp.c wcscoll.c wcscpy.c \
- wcscspn.c \
- wcslcat.c wcslcpy.c wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcspbrk.c \
+ strxfrm.c swab.c \
+ wcpcpy.c wcpncpy.c wcscasecmp.c wcsncasecmp.c \
+ wcscat.c wcschr.c wcscmp.c wcscoll.c wcscpy.c \
+ wcscspn.c wcsdup.c wcslcat.c wcslcpy.c \
+ wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcsnlen.c wcspbrk.c \
wcsrchr.c wcsspn.c wcsstr.c wcstok.c wcswidth.c wcsxfrm.c wmemchr.c \
wmemcmp.c \
wmemcpy.c wmemmove.c wmemset.c
.include "Makefile.fbsd_end"
+DYLDSRCS += \
+ strcat.c \
+ strchr.c \
+ strcpy.c \
+ strdup.c \
+ strlcat.c \
+ strlcpy.c \
+ strncmp.c \
+ strncpy.c \
+ strrchr.c \
+ strstr.c
+
LEGACYSRCS+= strerror.c
# set the LIBC_ALIAS_* macros so we can decorate the symbol independent
.if ${LIB} == "c"
.include "Makefile.fbsd_begin"
FBSDMAN3= bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \
- memcmp.3 memcpy.3 memmove.3 memset.3 rindex.3 strcasecmp.3 strcat.3 \
+ memcmp.3 memcpy.3 memmem.3 memmove.3 memset.3 rindex.3 strcasecmp.3 strcat.3 \
strchr.3 strcmp.3 strcoll.3 strcpy.3 strcspn.3 strdup.3 strerror.3 \
string.3 strlcpy.3 strlen.3 strmode.3 strpbrk.3 strrchr.3 strsep.3 \
strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 wcscoll.3 wcstok.3 \
MLINKS+= strcoll.3 strcoll_l.3
MLINKS+= strcpy.3 stpcpy.3 \
+ strcpy.3 stpncpy.3 \
strcpy.3 strncpy.3
+MLINKS+= strdup.3 strndup.3
+
+MLINKS+= strlen.3 strnlen.3
+
MLINKS+= strerror.3 perror.3 \
strerror.3 strerror_r.3 \
strerror.3 sys_errlist.3 \
wmemchr.3 wmemcpy.3 \
wmemchr.3 wmemmove.3 \
wmemchr.3 wmemset.3 \
+ wmemchr.3 wcpcpy.3 \
+ wmemchr.3 wcpncpy.3 \
+ wmemchr.3 wcsdup.3 \
+ wmemchr.3 wcscasecmp.3 \
+ wmemchr.3 wcscasecmp_l.3 \
wmemchr.3 wcscat.3 \
wmemchr.3 wcschr.3 \
wmemchr.3 wcscmp.3 \
wmemchr.3 wcslcat.3 \
wmemchr.3 wcslcpy.3 \
wmemchr.3 wcslen.3 \
+ wmemchr.3 wcsncasecmp.3 \
+ wmemchr.3 wcsncasecmp_l.3 \
wmemchr.3 wcsncat.3 \
wmemchr.3 wcsncmp.3 \
wmemchr.3 wcsncpy.3 \
+ wmemchr.3 wcsnlen.3 \
wmemchr.3 wcspbrk.3 \
wmemchr.3 wcsrchr.3 \
wmemchr.3 wcsspn.3 \
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bcmp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bcmp.3,v 1.10 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bcmp.3,v 1.11 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BCMP 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bcopy.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bcopy.3,v 1.9 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bcopy.3,v 1.10 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BCOPY 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bstring.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bstring.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bstring.3,v 1.8 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BSTRING 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)bzero.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/bzero.3,v 1.9 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/bzero.3,v 1.10 2007/01/09 00:28:11 imp Exp $
.\"
.Dd June 4, 1993
.Dt BZERO 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)ffs.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/string/ffs.3,v 1.9 2004/06/30 20:09:09 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/ffs.3,v 1.13 2009/01/13 13:19:42 kib Exp $
.\"
-.Dd January 13, 2004
+.Dd October 26, 2008
.Dt FFS 3
.Os
.Sh NAME
.Fn ffs
and
.Fn ffsl
-functions find the first bit set in
+functions find the first bit set
+(beginning with the least significant bit)
+in
.Fa i
and return the index of that bit.
.Pp
.Fa i
and return the index of that bit.
.Pp
-Bits are numbered starting from 1, starting at the right-most
-(least significant) bit.
+Bits are numbered starting at 1 (the least significant bit).
A return value of zero from any of these functions means that the
argument was zero.
.Sh SEE ALSO
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)index.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/index.3,v 1.11 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/index.3,v 1.12 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt INDEX 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memccpy.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/memccpy.3,v 1.6 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memccpy.3,v 1.7 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 9, 1993
.Dt MEMCCPY 3
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memchr.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memchr.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memchr.3,v 1.12 2009/04/23 08:37:56 brueffer Exp $
.\"
-.Dd June 4, 1993
+.Dd April 9, 2008
.Dt MEMCHR 3
.Os
.Sh NAME
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wmemchr 3
.Sh STANDARDS
The
.Fn memchr
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memcmp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memcmp.3,v 1.8 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memcmp.3,v 1.10 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMCMP 3
.Xr strcasecmp 3 ,
.Xr strcmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wmemcmp 3
.Sh STANDARDS
The
.Fn memcmp
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memcpy.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memcpy.3,v 1.7 2002/01/07 06:03:37 dd Exp $
+.\" $FreeBSD: src/lib/libc/string/memcpy.3,v 1.9 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMCPY 3
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memmove 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemcpy 3
.Sh STANDARDS
The
.Fn memcpy
--- /dev/null
+./memmem.c
\ No newline at end of file
--- /dev/null
+./memmem.3
\ No newline at end of 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.
-.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memmove.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memmove.3,v 1.6 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memmove.3,v 1.8 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMMOVE 3
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memcpy 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemmove 3
.Sh STANDARDS
The
.Fn memmove
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)memset.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/memset.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/memset.3,v 1.9 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt MEMSET 3
.Sh SEE ALSO
.Xr bzero 3 ,
.Xr memset_pattern 3 ,
-.Xr swab 3
+.Xr swab 3 ,
+.Xr wmemset 3
.Sh STANDARDS
The
.Fn memset
--- /dev/null
+./stpncpy.c
\ No newline at end of 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.
- * 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.
static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcasecmp.c,v 1.6 2002/08/30 15:40:01 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcasecmp.c,v 1.8 2009/02/03 17:58:20 danger Exp $");
#include "xlocale_private.h"
}
int
-strcasecmp(s1, s2)
- const char *s1, *s2;
+strcasecmp(const char *s1, const char *s2)
{
return strcasecmp_l(s1, s2, __current_locale());
}
}
int
-strncasecmp(s1, s2, n)
- const char *s1, *s2;
- size_t n;
+strncasecmp(const char *s1, const char *s2, size_t n)
{
return strncasecmp_l(s1, s2, n, __current_locale());
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcasecmp.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/strcasecmp.3,v 1.11 2003/09/08 19:57:15 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcasecmp.3,v 1.13 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 9, 1993
.Dt STRCASECMP 3
* 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcasestr.c,v 1.3 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcasestr.c,v 1.5 2009/02/03 17:58:20 danger Exp $");
#include "xlocale_private.h"
}
char *
-strcasestr(s, find)
- const char *s, *find;
+strcasestr(const char *s, const char *find)
{
return strcasestr_l(s, find, __current_locale());
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcat.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcat.3,v 1.13 2002/09/06 11:24:06 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/strcat.3,v 1.17 2009/12/01 07:28:56 brueffer Exp $
.\"
-.Dd June 4, 1993
+.Dd December 1, 2009
.Dt STRCAT 3
.Os
.Sh NAME
.Xr memmove 3 ,
.Xr strcpy 3 ,
.Xr strlcat 3 ,
-.Xr strlcpy 3
+.Xr strlcpy 3 ,
+.Xr wcscat 3
.Sh STANDARDS
The
.Fn strcat
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strchr.3 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD: src/lib/libc/string/strchr.3,v 1.11 2003/09/04 20:36:54 simon Exp $
+.\" $FreeBSD: src/lib/libc/string/strchr.3,v 1.14 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd April 19, 1994
.Dt STRCHR 3
if the character does not appear in the string.
.Sh SEE ALSO
.Xr memchr 3 ,
+.Xr memmem 3 ,
.Xr strcspn 3 ,
.Xr strpbrk 3 ,
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcschr 3
.Sh STANDARDS
The functions
.Fn strchr
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcmp.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcmp.3,v 1.10 2001/10/11 17:02:44 mike Exp $
+.\" $FreeBSD: src/lib/libc/string/strcmp.3,v 1.13 2009/12/04 09:20:20 trhodes Exp $
.\"
.Dd October 11, 2001
.Dt STRCMP 3
.Fn strcmp
and
.Fn strncmp
-return an integer greater than, equal to, or less than 0, according
+functions return an integer greater than, equal to, or less than 0, according
as the string
.Fa s1
is greater than, equal to, or less than the string
.Xr memcmp 3 ,
.Xr strcasecmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wcscmp 3
.Sh STANDARDS
The
.Fn strcmp
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strcoll.c,v 1.13 2001/11/07 19:55:16 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strcoll.c,v 1.14 2009/02/03 17:58:20 danger Exp $");
#include "xlocale_private.h"
#include "collate.h"
int
-strcoll_l(s, s2, loc)
- const char *s, *s2;
- locale_t loc;
+strcoll_l(const char *s, const char *s2, locale_t loc)
{
int ret;
const wchar_t *t = NULL, *t2 = NULL;
}
int
-strcoll(s, s2)
- const char *s, *s2;
+strcoll(const char *s, const char *s2)
{
return strcoll_l(s, s2, __current_locale());
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcoll.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcoll.3,v 1.12 2002/10/15 10:11:53 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/strcoll.3,v 1.14 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt STRCOLL 3
lexicographically compares the null-terminated strings
.Fa s1
and
-.Fa s2 ,
-according to the current locale collation, if any.
-Otherwise, it calls
-.Fa strcmp
+.Fa s2
+according to the current locale collation
and returns an integer greater than, equal to, or less than 0,
according as
.Fa s1
is greater than, equal to, or less than
.Fa s2 .
+If information about the current locale collation is not available,
+the value of
+.Fn strcmp s1 s2
+is returned.
.Pp
Although the
.Fn strcoll
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcpy.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcpy.3,v 1.24 2002/12/19 09:40:24 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcpy.3,v 1.28 2009/04/07 13:42:53 trasz Exp $
.\"
-.Dd August 9, 2001
+.Dd February 28, 2009
.Dt STRCPY 3
.Os
.Sh NAME
-.Nm stpcpy ,
-.Nm strcpy ,
-.Nm strncpy
+.Nm stpcpy, stpncpy, strcpy , strncpy
.Nd copy strings
.Sh LIBRARY
.Lb libc
.Fa "const char *s2"
.Fc
.Ft char *
+.Fo stpncpy
+.Fa "char *restrict s1"
+.Fa "const char *restrict s2"
+.Fa "size_t n"
+.Fc
+.Ft char *
.Fo strcpy
.Fa "char *restrict s1"
.Fa "const char *restrict s2"
character).
.Pp
The
+.Fn stpncpy
+and
.Fn strncpy
-function copies at most
+functions copy at most
.Fa n
characters from
.Fa s2
.Fa s1 .
The
.Fn stpcpy
-function returns a pointer to the terminating
+and
+.Fn stpncpy
+functions return a pointer to the terminating
.Ql \e0
character of
.Fa s1 .
+If
+.Fn stpncpy
+does not terminate
+.Fa s1
+with a
+.Dv NUL
+character, it instead returns a pointer to
+.Li s1[n]
+(which does not necessarily refer to a valid memory location.)
.Sh EXAMPLES
The following sets
.Va chararray
as shown in the following example:
.Pp
.Dl "(void)strlcpy(buf, input, sizeof(buf));"
-.Pp
-Note that, because
-.Xr strlcpy 3
-is not defined in any standards, it should
-only be used when portability is not a concern.
.Sh SECURITY CONSIDERATIONS
The
-.Fn strcpy
-function is easily misused in a manner which enables malicious users
+.Fn strcpy ,
+.Fn strncpy ,
+.Fn stpcpy ,
+and
+.Fn stpncpy
+functions are easily misused in a manner which enables malicious users
to arbitrarily change a running program's functionality through a
buffer overflow attack.
(See
the FSA
and
.Sx EXAMPLES . )
+.Pp
+It is recommended that
+.Xr strlcpy 3
+be used instead as a way to avoid such problems.
+.Xr strlcpy 3
+is not defined in any standards, but it has been adopted by most major libc implementations.
.Sh SEE ALSO
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memcpy 3 ,
.Xr memmove 3 ,
-.Xr strlcpy 3
+.Xr strlcpy 3 ,
+.Xr wcscpy 3
.Sh STANDARDS
The
.Fn strcpy
.St -isoC .
The
.Fn stpcpy
-function is an MS-DOS and GNUism.
-The
-.Fn stpcpy
-function
-conforms to no standard.
+and
+.Fn stpncpy
+functions conform to
+.St -p1003.1-2008 .
.Sh HISTORY
The
.Fn stpcpy
function first appeared in
.Fx 4.4 ,
-coming from 1998-vintage Linux.
+and
+.Fn stpncpy
+was added in
+.Fx 8.0 .
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strcspn.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.9 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt STRCSPN 3
.Em complement
of
.Fa s2 ) .
+In other words, it computes the string array index in
+.Fa s1
+of the first character of
+.Fa s1
+which is also in
+.Fa s2 ,
+else the index of the first null character.
.Sh RETURN VALUES
The
.Fn strcspn
-function returns the number of characters spanned.
+function
+returns the number of characters spanned.
.Sh SEE ALSO
.Xr memchr 3 ,
.Xr strchr 3 ,
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strdup.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/strdup.3,v 1.10 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strdup.3,v 1.15 2009/04/07 13:42:53 trasz Exp $
.\"
-.Dd June 9, 1993
+.Dd December 5, 2008
.Dt STRDUP 3
.Os
.Sh NAME
-.Nm strdup
+.Nm strdup ,
+.Nm strndup
.Nd save a copy of a string
.Sh LIBRARY
.Lb libc
.Fo strdup
.Fa "const char *s1"
.Fc
+.Ft char *
+.Fo strndup
+.Fa "const char *s1"
+.Fa "size_t n"
+.Fc
.Sh DESCRIPTION
The
.Fn strdup
.Va errno
is set to
.Er ENOMEM .
+.Pp
+The
+.Fn strndup
+function copies at most
+.Fa n
+characters from the string
+.Fa s1
+always
+.Dv NUL
+terminating the copied string.
.Sh SEE ALSO
.Xr free 3 ,
.Xr malloc 3
.Fn strdup
function first appeared in
.Bx 4.4 .
+The
+.Fn strndup
+function was added in
+.Fx 7.2 .
* 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.
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strerror.c,v 1.13 2003/05/01 19:03:14 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strerror.c,v 1.16 2007/01/09 00:28:12 imp Exp $");
+#if defined(NLS)
+#include <nl_types.h>
+#endif
+
+#include <limits.h>
#include <errno.h>
-#include <stdio.h>
#include <string.h>
+#include <stdio.h>
-#define UPREFIX "Unknown error: "
+#define UPREFIX "Unknown error"
/*
* Define a buffer size big enough to describe a 64-bit signed integer
* converted to ASCII decimal (19 bytes), with an optional leading sign
- * (1 byte); finally, we get the prefix and a trailing NUL from UPREFIX.
+ * (1 byte); finally, we get the prefix, delimiter (": ") and a trailing
+ * NUL from UPREFIX.
*/
-#define EBUFSIZE (20 + sizeof(UPREFIX))
+#define EBUFSIZE (20 + 2 + sizeof(UPREFIX))
#ifndef BUILDING_VARIANT
/*
* statically linked binaries.
*/
__private_extern__ void
-__errstr(int num, char *buf, size_t len)
+__errstr(int num, char *uprefix, char *buf, size_t len)
{
char *t;
unsigned int uerr;
} while (uerr /= 10);
if (num < 0)
*--t = '-';
- strlcpy(buf, UPREFIX, len);
+ *--t = ' ';
+ *--t = ':';
+ strlcpy(buf, uprefix, len);
strlcat(buf, t, len);
}
int
strerror_r(int errnum, char *strerrbuf, size_t buflen)
{
+ int retval = 0;
+#if defined(NLS)
+ int saved_errno = errno;
+ nl_catd catd;
+ catd = catopen("libc", NL_CAT_LOCALE);
+#endif
if (errnum < 0 || errnum >= sys_nerr) {
- __errstr(errnum, strerrbuf, buflen);
- return (EINVAL);
+ __errstr(errnum,
+#if defined(NLS)
+ catgets(catd, 1, 0xffff, UPREFIX),
+#else
+ UPREFIX,
+#endif
+ strerrbuf, buflen);
+ retval = EINVAL;
+ } else {
+ if (strlcpy(strerrbuf,
+#if defined(NLS)
+ catgets(catd, 1, errnum, sys_errlist[errnum]),
+#else
+ sys_errlist[errnum],
+#endif
+ buflen) >= buflen)
+ retval = ERANGE;
}
- if (strlcpy(strerrbuf, sys_errlist[errnum], buflen) >= buflen)
- return (ERANGE);
- return (0);
+
+#if defined(NLS)
+ catclose(catd);
+ errno = saved_errno;
+#endif
+
+ return (retval);
}
#else /* BUILDING_VARIANT */
__private_extern__ void __errstr(int, char *, size_t);
char *
strerror(int num)
{
- static char ebuf[EBUFSIZE];
+ static char ebuf[NL_TEXTMAX];
- if (num > 0 && num < sys_nerr)
- return ((char *)sys_errlist[num]);
#if !__DARWIN_UNIX03
+ if (strerror_r(num, ebuf, sizeof(ebuf)) != 0)
errno = EINVAL;
-#endif /* !__DARWIN_UNIX03 */
- __errstr(num, ebuf, sizeof(ebuf));
+#else
+ (void)strerror_r(num, ebuf, sizeof(ebuf));
+#endif
return (ebuf);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strerror.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/lib/libc/string/strerror.3,v 1.23 2004/10/12 14:52:52 keramida Exp $
+.\" $FreeBSD: src/lib/libc/string/strerror.3,v 1.24 2007/01/09 00:28:12 imp Exp $
.\"
.Dd October 12, 2004
.Dt STRERROR 3
.Er EINVAL
as a warning.
Error numbers recognized by this implementation fall in
-the range 0 <
+the range 0 <=
.Fa errnum
<
.Fa sys_nerr .
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)string.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/string/string.3,v 1.13 2002/10/19 13:41:22 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/string.3,v 1.14 2007/01/09 00:28:12 imp Exp $
.\"
.Dd December 11, 1993
.Dt STRING 3
-.\" $OpenBSD: strlcpy.3,v 1.5 1999/06/06 15:17:32 aaron Exp $
+.\" $OpenBSD: strlcpy.3,v 1.19 2007/05/31 19:19:32 jmc Exp $
.\"
-.\" Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
-.\" All rights reserved.
+.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
.\"
-.\" 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. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/string/strlcpy.3,v 1.13 2004/07/02 23:52:13 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strlcpy.3,v 1.16 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 22, 1998
.Dt STRLCPY 3
.Sh SYNOPSIS
.In string.h
.Ft size_t
-.Fn strlcpy "char *dst" "const char *src" "size_t size"
+.Fn strlcpy "char * restrict dst" "const char * restrict src" "size_t size"
.Ft size_t
-.Fn strlcat "char *dst" "const char *src" "size_t size"
+.Fn strlcat "char * restrict dst" "const char * restrict src" "size_t size"
.Sh DESCRIPTION
The
.Fn strlcpy
.Fn strlcat ,
as long as there is at least one byte free in
.Fa dst ) .
-Note that you should include a byte for the NUL in
+Note that a byte for the NUL should be included in
.Fa size .
Also note that
.Fn strlcpy
plus
the length of
.Fa src .
-While this may seem somewhat confusing it was done to make
+While this may seem somewhat confusing, it was done to make
truncation detection simple.
.Pp
Note however, that if
goto toolong;
.Ed
.Pp
-Since we know how many characters we copied the first time, we can
-speed things up a bit by using a copy instead of an append:
+Since it is known how many characters were copied the first time, things
+can be sped up a bit by using a copy instead of an append
.Bd -literal -offset indent
char *dir, *file, pname[MAXPATHLEN];
size_t n;
.Sh SEE ALSO
.Xr snprintf 3 ,
.Xr strncat 3 ,
-.Xr strncpy 3
+.Xr strncpy 3 ,
+.Xr wcslcpy 3
.Sh HISTORY
The
.Fn strlcpy
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strmode.3 8.3 (Berkeley) 7/28/94
-.\" $FreeBSD: src/lib/libc/string/strmode.3,v 1.9 2003/07/01 15:28:05 maxim Exp $
+.\" $FreeBSD: src/lib/libc/string/strmode.3,v 1.11 2009/04/14 11:39:56 trasz Exp $
.\"
.Dd July 28, 1994
.Dt STRMODE 3
None of the above apply.
.El
.Pp
-The last character is a plus sign ``+'' if any there are any alternate
-or additional access control methods associated with the inode, otherwise
-it will be a space.
+The last character will always be a space.
.Sh SEE ALSO
.Xr chmod 1 ,
.Xr find 1 ,
--- /dev/null
+./strndup.c
\ No newline at end of file
--- /dev/null
+./strnlen.c
\ No newline at end of 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.
-.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strpbrk.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strpbrk.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strpbrk.3,v 1.9 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt STRPBRK 3
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcspbrk 3
.Sh STANDARDS
The
.Fn strpbrk
* 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.
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strsignal.c,v 1.4 2002/03/21 18:44:54 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strsignal.c,v 1.9 2010/01/24 10:35:26 ume Exp $");
-#include <stdio.h>
+#include "namespace.h"
+#if defined(NLS)
+#include <nl_types.h>
+#endif
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include "reentrant.h"
+#include "un-namespace.h"
+#define UPREFIX "Unknown signal"
+
+static once_t sig_init_once = ONCE_INITIALIZER;
+static thread_key_t sig_key;
+static int sig_keycreated = 0;
+
+static void
+sig_keycreate(void)
+{
+ sig_keycreated = (thr_keycreate(&sig_key, free) == 0);
+}
+
+static char *
+sig_tlsalloc(void)
+{
+ char *ebuf = NULL;
+
+ if (thr_once(&sig_init_once, sig_keycreate) != 0 ||
+ !sig_keycreated)
+ goto thr_err;
+ if ((ebuf = thr_getspecific(sig_key)) == NULL) {
+ if ((ebuf = malloc(NL_TEXTMAX * sizeof(char))) == NULL)
+ goto thr_err;
+ if (thr_setspecific(sig_key, ebuf) != 0) {
+ free(ebuf);
+ ebuf = NULL;
+ goto thr_err;
+ }
+ }
+thr_err:
+ return (ebuf);
+}
+
+/* XXX: negative 'num' ? (REGR) */
char *
-strsignal(num)
- int num;
+strsignal(int num)
{
-#define UPREFIX "Unknown signal: "
- static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
- unsigned int signum;
- char *p, *t;
- char tmp[40];
+ char *ebuf;
+ char tmp[20];
+ size_t n;
+ int signum;
+ char *t, *p;
- signum = num; /* convert to unsigned */
- if (signum < NSIG)
- return ((char *)sys_siglist[signum]);
+#if defined(NLS)
+ int saved_errno = errno;
+ nl_catd catd;
+ catd = catopen("libc", NL_CAT_LOCALE);
+#endif
- /* Do this by hand, so we don't link to stdio(3). */
- t = tmp;
+ ebuf = sig_tlsalloc();
+ if(ebuf == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ if (num > 0 && num < NSIG) {
+ n = strlcpy(ebuf,
+#if defined(NLS)
+ catgets(catd, 2, num, sys_siglist[num]),
+#else
+ sys_siglist[num],
+#endif
+ NL_TEXTMAX * sizeof(char));
+ } else {
+ n = strlcpy(ebuf,
+#if defined(NLS)
+ catgets(catd, 2, 0xffff, UPREFIX),
+#else
+ UPREFIX,
+#endif
+ NL_TEXTMAX * sizeof(char));
+ }
+
+ signum = num;
if (num < 0)
signum = -signum;
+
+ t = tmp;
do {
*t++ = "0123456789"[signum % 10];
} while (signum /= 10);
if (num < 0)
*t++ = '-';
- for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+
+ p = (ebuf + n);
+ *p++ = ':';
+ *p++ = ' ';
+
+ for (;;) {
*p++ = *--t;
if (t <= tmp)
break;
}
*p = '\0';
+
+#if defined(NLS)
+ catclose(catd);
+ errno = saved_errno;
+#endif
return (ebuf);
}
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strspn.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.8 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.11 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd June 4, 1993
.Dt STRSPN 3
.Fa s1 ,
as long as the characters from
.Fa s1
-occur in string
+occur in the null-terminated string
.Fa s2 .
+In other words, it computes the string array index in
+.Fa s1
+of the first character of
+.Fa s1
+which is not in
+.Fa s2 ,
+else the index of the first null character.
.Sh RETURN VALUES
The
.Fn strspn
.Xr strrchr 3 ,
.Xr strsep 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcsspn 3
.Sh STANDARDS
The
.Fn strspn
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strstr.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strstr.3,v 1.12 2001/11/20 14:11:07 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strstr.3,v 1.15 2009/04/07 13:42:53 trasz Exp $
.\"
.Dd October 11, 2001
.Dt STRSTR 3
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strtok 3 ,
+.Xr wcsstr 3 ,
.Xr xlocale 3
.Sh STANDARDS
The
.\" 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 Softweyr LLC, the
-.\" University of California, Berkeley, and its contributors.
-.\"
.\" 4. Neither the name of Softweyr LLC, the University nor the names
.\" of its contributors may be used to endorse or promote products
.\" derived from this software without specific prior written
.\" SUCH DAMAGE.
.\"
.\" @(#)strtok.3 8.2 (Berkeley) 2/3/94
-.\" $FreeBSD: src/lib/libc/string/strtok.3,v 1.24 2002/12/18 12:45:11 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strtok.3,v 1.26 2007/12/12 18:33:06 wes Exp $
.\"
.Dd November 27, 1998
.Dt STRTOK 3
function
conforms to
.St -isoC .
+.Sh AUTHORS
+.An Wes Peters ,
+Softweyr LLC:
+.Aq wes@softweyr.com
+.Pp
+Based on the
+.Fx 3.0
+implementation.
.Sh BUGS
The System V
.Fn strtok ,
Since this implementation always alters the next starting point,
such a sequence of calls would always return
.Dv NULL .
-.Sh AUTHORS
-.An Wes Peters ,
-Softweyr LLC:
-.Aq wes@softweyr.com
-.Pp
-Based on the
-.Fx 3.0
-implementation.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strxfrm.c,v 1.17 2008/10/19 09:10:44 delphij Exp $");
#include "xlocale_private.h"
}
NORMALIZE_LOCALE(loc);
- if (loc->__collate_load_error || (wcs = __collate_mbstowcs(src, loc)) == NULL) {
- slen = strlen(src);
- if (len > 0) {
- if (slen < len)
- strcpy(dest, src);
- else {
- strncpy(dest, src, len - 1);
- dest[len - 1] = '\0';
- }
- }
- return slen;
- }
+ if (loc->__collate_load_error || (wcs = __collate_mbstowcs(src, loc)) == NULL)
+ return strlcpy(dest, src, len);
__collate_xfrm(wcs, xf, loc);
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)strxfrm.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strxfrm.3,v 1.17 2002/10/15 10:11:53 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/strxfrm.3,v 1.18 2007/01/09 00:28:12 imp Exp $
.\"
.Dd June 4, 1993
.Dt STRXFRM 3
* 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.
static char sccsid[] = "@(#)swab.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/swab.c,v 1.5 2002/08/30 20:33:05 robert Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/swab.c,v 1.7 2007/01/09 00:28:12 imp Exp $");
-#include <string.h>
+#include <unistd.h>
void
swab(const void * __restrict from, void * __restrict to, ssize_t len)
.\" 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.
.\" SUCH DAMAGE.
.\"
.\" @(#)swab.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/swab.3,v 1.7 2002/08/30 21:18:39 robert Exp $
+.\" $FreeBSD: src/lib/libc/string/swab.3,v 1.10 2007/01/09 00:28:12 imp Exp $
.\"
-.Dd June 4, 1993
+.Dd February 24, 2010
.Dt SWAB 3
.Os
.Sh NAME
.Pp
The argument
.Fa nbytes
-must be an even number.
-.Sh LEGACY SYNOPSIS
-.Fd #include <string.h>
-.Pp
-.Ft void
-.br
-.Fo swab
-.Fa "const void *restrict src"
-.Fa "void *restrict dest"
-.Fa "size_t nbytes"
-.Fc ;
-.Pp
-The include file
-.In string.h
-is necessary for this function.
-The type of
+should be an even number. If
+.Fa nbytes
+is odd,
+.Fn swab
+copies and exchanges
.Fa nbytes
-has changed.
+-1 bytes and the disposition of the last byte is unspecified.
+If copying takes place between objects that overlap,
+the behavior is undefined. If
+.Fa nbytes
+is negative,
+.Fn swab
+does nothing.
.Sh SEE ALSO
.Xr bzero 3 ,
.Xr memset 3 ,
--- /dev/null
+./wcpcpy.c
\ No newline at end of file
--- /dev/null
+./wcpncpy.c
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcscasecmp.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#include "xlocale_private.h"
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcscasecmp_l(const wchar_t *s1, const wchar_t *s2, locale_t loc)
+{
+ wchar_t c1, c2;
+
+ for (; *s1; s1++, s2++) {
+ c1 = towlower_l(*s1, loc);
+ c2 = towlower_l(*s2, loc);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ }
+ return (-*s2);
+}
+
+int
+wcscasecmp(const wchar_t *s1, const wchar_t *s2) {
+ return wcscasecmp_l(s1, s2, __current_locale());
+}
+
.\" 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.
.\"
.\" @(#)strcoll.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/string/strcoll.3,v 1.11 2001/10/01 16:09:00 ru Exp
-.\" $FreeBSD: src/lib/libc/string/wcscoll.3,v 1.2 2002/12/09 14:04:05 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/wcscoll.3,v 1.3 2007/01/09 00:28:12 imp Exp $
.\"
.Dd October 4, 2002
.Dt WCSCOLL 3
--- /dev/null
+./wcsdup.c
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/lib/libc/string/wcsncasecmp.c,v 1.1 2009/02/28 06:00:58 das Exp $");
+
+#include "xlocale_private.h"
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcsncasecmp_l(const wchar_t *s1, const wchar_t *s2, size_t n, locale_t loc)
+{
+ wchar_t c1, c2;
+
+ if (n == 0)
+ return (0);
+ for (; *s1; s1++, s2++) {
+ c1 = towlower_l(*s1, loc);
+ c2 = towlower_l(*s2, loc);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ if (--n == 0)
+ return (0);
+ }
+ return (-*s2);
+}
+
+int
+wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
+ return wcsncasecmp_l(s1, s2, n, __current_locale());
+}
+
--- /dev/null
+./wcsnlen.c
\ No newline at end of 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.
- * 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.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/wcswidth.c,v 1.6 2002/08/20 02:06:28 ache Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/wcswidth.c,v 1.7 2007/01/09 00:28:12 imp Exp $");
#include "xlocale_private.h"
.\" 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.
.\"
.\" @(#)strxfrm.3 8.1 (Berkeley) 6/4/93
.\" FreeBSD: src/lib/libc/string/strxfrm.3,v 1.16 2002/09/06 11:24:06 tjr Exp
-.\" $FreeBSD: src/lib/libc/string/wcsxfrm.3,v 1.2 2002/12/09 14:04:05 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/wcsxfrm.3,v 1.3 2007/01/09 00:28:12 imp Exp $
.\"
.Dd October 4, 2002
.Dt WCSXFRM 3
.\" 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.
.\"
.\" from: @(#)strcpy.3 8.1 (Berkeley) 6/4/93
.\"
-.\" $FreeBSD: src/lib/libc/string/wmemchr.3,v 1.6 2002/09/07 04:07:00 tjr Exp $
+.\" $FreeBSD: src/lib/libc/string/wmemchr.3,v 1.10 2009/03/04 06:01:27 das Exp $
.\"
-.Dd December 22, 2000
+.Dd March 4, 2009
.Dt WMEMCHR 3
.Os
.Sh NAME
+.Nm wcpcpy ,
+.Nm wcpncpy ,
+.Nm wcscasecmp ,
.Nm wcscat ,
.Nm wcschr ,
.Nm wcscmp ,
.Nm wcscpy ,
.Nm wcscspn ,
+.Nm wcsdup ,
.Nm wcslcat ,
.Nm wcslcpy ,
.Nm wcslen ,
+.Nm wcsncasecmp ,
.Nm wcsncat ,
.Nm wcsncmp ,
.Nm wcsncpy ,
+.Nm wcsnlen ,
.Nm wcspbrk ,
.Nm wcsrchr ,
.Nm wcsspn ,
.Sh SYNOPSIS
.In wchar.h
.Ft wchar_t *
-.Fo wcscat
-.Fa "wchar_t *restrict ws1"
-.Fa "const wchar_t *restrict ws2"
-.Fc
+.Fn wcpcpy "wchar_t *s1" "wchar_t *s2"
.Ft wchar_t *
-.Fo wcschr
-.Fa "const wchar_t *ws"
-.Fa "wchar_t wc"
-.Fc
+.Fn wcpncpy "wchar_t *s1" "wchar_t *s2" "size_t n"
.Ft int
-.Fo wcscmp
-.Fa "const wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fc
+.Fn wcscasecmp "const wchar_t *s1" "const wchar_t *s2"
.Ft wchar_t *
-.Fo wcscpy
-.Fa "wchar_t *restrict ws1"
-.Fa "const wchar_t *restrict ws2"
-.Fc
+.Fn wcscat "wchar_t * restrict s1" "const wchar_t * restrict s2"
+.Ft wchar_t *
+.Fn wcschr "const wchar_t *s" "wchar_t c"
+.Ft int
+.Fn wcscmp "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcscpy "wchar_t * restrict s1" "const wchar_t * restrict s2"
.Ft size_t
-.Fo wcscspn
-.Fa "const wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fc
+.Fn wcscspn "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcsdup "const wchar_t *s"
.Ft size_t
-.Fo wcslcat
-.Fa "wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fa "size_t n"
-.Fc
+.Fn wcslcat "wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft size_t
-.Fo wcslcpy
-.Fa "wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fa "size_t n"
-.Fc
+.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft size_t
-.Fo wcslen
-.Fa "const wchar_t *ws"
-.Fc
+.Fn wcslen "const wchar_t *s"
+.Ft int
+.Fn wcsncasecmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft wchar_t *
-.Fo wcsncat
-.Fa "wchar_t *restrict ws1"
-.Fa "const wchar_t *restrict ws2"
-.Fa "size_t n"
-.Fc
+.Fn wcsncat "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
.Ft int
-.Fo wcsncmp
-.Fa "const wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fa "size_t n"
-.Fc
+.Fn wcsncmp "const wchar_t *s1" "const wchar_t * s2" "size_t n"
.Ft wchar_t *
-.Fo wcsncpy
-.Fa "wchar_t *restrict ws1"
-.Fa "const wchar_t *restrict ws2"
-.Fa "size_t n"
-.Fc
+.Fn wcsncpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
+.Ft size_t
+.Fn wcsnlen "const wchar_t *s" "size_t maxlen"
.Ft wchar_t *
-.Fo wcspbrk
-.Fa "const wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fc
+.Fn wcspbrk "const wchar_t *s1" "const wchar_t *s2"
.Ft wchar_t *
-.Fo wcsrchr
-.Fa "const wchar_t *ws"
-.Fa "wchar_t wc"
-.Fc
+.Fn wcsrchr "const wchar_t *s" "wchar_t c"
.Ft size_t
-.Fo wcsspn
-.Fa "const wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fc
+.Fn wcsspn "const wchar_t *s1" "const wchar_t *s2"
.Ft wchar_t *
-.Fo wcsstr
-.Fa "const wchar_t *restrict ws1"
-.Fa "const wchar_t *restrict ws2"
-.Fc
+.Fn wcsstr "const wchar_t * restrict s1" "const wchar_t * restrict s2"
.Ft wchar_t *
-.Fo wmemchr
-.Fa "const wchar_t *ws"
-.Fa "wchar_t wc"
-.Fa "size_t n"
-.Fc
+.Fn wmemchr "const wchar_t *s" "wchar_t c" "size_t n"
.Ft int
-.Fo wmemcmp
-.Fa "const wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fa "size_t n"
-.Fc
+.Fn wmemcmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft wchar_t *
-.Fo wmemcpy
-.Fa "wchar_t *restrict ws1"
-.Fa "const wchar_t *restrict ws2"
-.Fa "size_t n"
-.Fc
+.Fn wmemcpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
.Ft wchar_t *
-.Fo wmemmove
-.Fa "wchar_t *ws1"
-.Fa "const wchar_t *ws2"
-.Fa "size_t n"
-.Fc
+.Fn wmemmove "wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft wchar_t *
-.Fo wmemset
-.Fa "wchar_t *ws"
-.Fa "wchar_t wc"
-.Fa "size_t n"
-.Fc
+.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n"
+.In wchar.h
+.In xlocale.h
+.Ft int
+.Fn wcscasecmp_l "const wchar_t *s1" "const wchar_t *s2" "locale_t loc"
+.Ft int
+.Fn wcsncasecmp_l "const wchar_t *s1" "const wchar_t *s2" "size_t n" "locale_t loc"
.Sh DESCRIPTION
-The functions implement string manipulation operations
-over wide character strings.
-For a detailed description,
-refer to documents for the respective single-byte counterpart, such as
+The functions implement string manipulation operations over wide character
+strings.
+For a detailed description, refer to documents for the respective single-byte
+counterpart, such as
.Xr memchr 3 .
.Sh SEE ALSO
.Xr memchr 3 ,
.Xr memcpy 3 ,
.Xr memmove 3 ,
.Xr memset 3 ,
+.Xr stpcpy 3 ,
+.Xr stpncpy 3 ,
+.Xr strcasecmp 3 ,
+.Xr strcasecmp_l 3 ,
.Xr strcat 3 ,
.Xr strchr 3 ,
.Xr strcmp 3 ,
.Xr strcpy 3 ,
.Xr strcspn 3 ,
+.Xr strdup 3 ,
.Xr strlcat 3 ,
.Xr strlcpy 3 ,
.Xr strlen 3 ,
+.Xr strncasecmp 3 ,
+.Xr strncasecmp_l 3 ,
.Xr strncat 3 ,
.Xr strncmp 3 ,
.Xr strncpy 3 ,
+.Xr strnlen 3 ,
.Xr strpbrk 3 ,
.Xr strrchr 3 ,
.Xr strspn 3 ,
-.Xr strstr 3
+.Xr strstr 3 ,
+.Xr xlocale 3
.Sh STANDARDS
These functions conform to
.St -isoC-99 ,
with the exception of
+.Fn wcpcpy ,
+.Fn wcpncpy ,
+.Fn wcscasecmp ,
+.Fn wcscasecmp_l ,
+.Fn wcsdup ,
+.Fn wcsncasecmp ,
+.Fn wcsncasecmp_l ,
+and
+.Fn wcsnlen ,
+which conform to
+.St -p1003.1-2008 ;
+and
.Fn wcslcat
and
.Fn wcslcpy ,
# Sources common to both syscall interfaces:
-MISRCS += chmod.c chmodx_np.c crt_externs.c \
- errno.c fchmod.c \
- getiopolicy_np.c getrlimit.c gettimeofday.c \
- kill.c __libc_init.c \
- mmap.c \
+MISRCS += chmodx_np.c crt_externs.c \
+ errno.c fork.c \
+ getiopolicy_np.c gettimeofday.c \
+ __libc_init.c _libc_fork_child.c \
openx_np.c \
posix_spawn.c \
- remove_counter.c rename.c rmdir.c \
- select.c setrlimit.c settimeofday.c \
- sigaction.c sigcatch.c sigsuspend.c \
- sigtramp.c statx_np.c \
- umaskx_np.c unlink.c
+ settimeofday.c \
+ sigaction.c sigcatch.c \
+ sigtramp.c slot_name.c statx_np.c \
+ umaskx_np.c
.ifdef FEATURE_MEM_THERM_NOTIFICATION_APIS
MISRCS += OSMemoryNotification.c OSThermalNotification.c
OBSDMISRCS= stack_protector.c
.include "Makefile.obsd_end"
-.ifdef FEATURE_PATCH_3375657
-# patches for sem_open() sem_unlink() shm_open() shm_unlink()
-MISRCS+= fix-3375657.c sem_open.c sem_unlink.c shm_open.c shm_unlink.c
-.endif # FEATURE_PATCH_3375657
-
DARWINEXTSNSRCS += getgroups.c
INODE32SRCS += statx_np.c
-CANCELABLESRCS += select.c sigsuspend.c
+DYLDSRCS += errno.c
-.if defined(LP64) || (${MACHINE_ARCH} == arm)
-CANCELABLESRCS+= fcntl.c
-MISRCS+= fcntl.c ioctl.c
-.endif
-.if defined(LP64)
-PRE1050SRCS+= select.c
-.endif
-
-LEGACYSRCS += accept.c bind.c connect.c \
- getattrlist.c getpeername.c getsockname.c \
- kill.c lchown.c listen.c \
- mprotect.c msgctl.c msync.c munmap.c \
- open.c \
- recvfrom.c recvmsg.c \
- select.c semctl.c sendmsg.c sendto.c setattrlist.c \
- shmctl.c sigsuspend.c socketpair.c
+LEGACYSRCS += msgctl.c \
+ semctl.c \
+ shmctl.c
.for _src in msgctl.c semctl.c shmctl.c
CFLAGS-${_src} += -DKERNEL
#CFLAGS-close.c += -DLIBC_ALIAS_CLOSE
CFLAGS-connect.c += -DLIBC_ALIAS_CONNECT
CFLAGS-fchmod.c += -DLIBC_ALIAS_FCHMOD
-CFLAGS-fcntl.c += -DLIBC_ALIAS_FCNTL
#CFLAGS-fsync.c += -DLIBC_ALIAS_FSYNC
CFLAGS-getattrlist.c += -DLIBC_ALIAS_GETATTRLIST
CFLAGS-getpeername.c += -DLIBC_ALIAS_GETPEERNAME
-CFLAGS-getrlimit.c += -DLIBC_ALIAS_GETRLIMIT
CFLAGS-getsockname.c += -DLIBC_ALIAS_GETSOCKNAME
-CFLAGS-kill.c += -DLIBC_ALIAS_KILL
CFLAGS-lchmod.c += -DLIBC_ALIAS_LCHMOD
CFLAGS-lchown.c += -DLIBC_ALIAS_LCHOWN
CFLAGS-listen.c += -DLIBC_ALIAS_LISTEN
-CFLAGS-mmap.c += -DLIBC_ALIAS_MMAP
-CFLAGS-mprotect.c += -DLIBC_ALIAS_MPROTECT
CFLAGS-msgctl.c += -DLIBC_ALIAS_MSGCTL
#CFLAGS-msgrcv.c += -DLIBC_ALIAS_MSGRCV
#CFLAGS-msgsnd.c += -DLIBC_ALIAS_MSGSND
-CFLAGS-msync.c += -DLIBC_ALIAS_MSYNC
-CFLAGS-munmap.c += -DLIBC_ALIAS_MUNMAP
-#CFLAGS-open.c += -DLIBC_ALIAS_OPEN
#CFLAGS-poll.c += -DLIBC_ALIAS_POLL
#CFLAGS-pread.c += -DLIBC_ALIAS_PREAD
#CFLAGS-pwrite.c += -DLIBC_ALIAS_PWRITE
#CFLAGS-readv.c += -DLIBC_ALIAS_READV
CFLAGS-recvfrom.c += -DLIBC_ALIAS_RECVFROM
CFLAGS-recvmsg.c += -DLIBC_ALIAS_RECVMSG
-CFLAGS-select.c += -DLIBC_ALIAS_SELECT
#CFLAGS-sem_wait.c += -DLIBC_ALIAS_SEM_WAIT
CFLAGS-semctl.c += -DLIBC_ALIAS_SEMCTL
CFLAGS-sendmsg.c += -DLIBC_ALIAS_SENDMSG
CFLAGS-sendto.c += -DLIBC_ALIAS_SENDTO
CFLAGS-setattrlist.c += -DLIBC_ALIAS_SETATTRLIST
-CFLAGS-setrlimit.c += -DLIBC_ALIAS_SETRLIMIT
CFLAGS-shmctl.c += -DLIBC_ALIAS_SHMCTL
-CFLAGS-sigsuspend.c += -DLIBC_ALIAS_SIGSUSPEND
CFLAGS-socketpair.c += -DLIBC_ALIAS_SOCKETPAIR
+CFLAGS-stack_protector-obsd.c += -fno-stack-protector
#CFLAGS-waitid.c += -DLIBC_ALIAS_WAITID
#CFLAGS-write.c += -DLIBC_ALIAS_WRITE
#CFLAGS-writev.c += -DLIBC_ALIAS_WRITEV
-COPYFILES+= ${.CURDIR}/sys/libc.syscall
-
.if ${LIB} == "c"
MAN2+= pthread_kill.2 pthread_sigmask.2 \
- sem_close.2 sem_open.2 sem_post.2 \
- sem_unlink.2 sem_wait.2 shm_open.2 shm_unlink.2 \
- sigwait.2 getdtablesize.2 setreuid.2 setregid.2 \
- nanosleep.2 undelete.2
+ sigwait.2 nanosleep.2
MAN3+= atomic.3 barrier.3 getiopolicy_np.3 spinlock.3 cache.3
MLINKS+= atomic.3 OSAtomicAdd32.3
MLINKS+= atomic.3 OSAtomicAdd32Barrier.3
MLINKS+= getiopolicy_np.3 setiopolicy_np.3
-MLINKS+= sem_wait.2 sem_trywait.2
MLINKS+= cache.3 sys_cache_control.3
MLINKS+= cache.3 sys_icache_invalidate.3
MLINKS+= cache.3 sys_dcache_flush.3
# fcntl.2 fhopen.2 flock.2 fork.2 fsync.2 \
# getdirentries.2 getdtablesize.2 \
# getfh.2 getfsstat.2 getgid.2 getgroups.2 getitimer.2 getlogin.2 \
-# getpeername.2 getpgrp.2 getpid.2 getpriority.2 getrlimit.2 \
+# getpeername.2 getpgrp.2 getpid.2 getpriority.2 \
# getrusage.2 getsid.2 getsockname.2 \
# getsockopt.2 gettimeofday.2 getuid.2 \
-# intro.2 ioctl.2 issetugid.2 jail.2 kill.2 \
+# intro.2 ioctl.2 issetugid.2 jail.2 \
# kldfind.2 kldfirstmod.2 kldload.2 kldnext.2 kldstat.2 kldsym.2 \
# kldunload.2 kqueue.2 link.2 listen.2 lseek.2 \
-# madvise.2 mincore.2 minherit.2 mkdir.2 mkfifo.2 mknod.2 mlock.2 mmap.2 \
+# madvise.2 mincore.2 minherit.2 mkdir.2 mkfifo.2 mknod.2 mlock.2 \
# modfind.2 modnext.2 modstat.2 \
-# mount.2 mprotect.2 msync.2 munmap.2 nanosleep.2 \
-# nfssvc.2 open.2 pathconf.2 pipe.2 poll.2 profil.2 ptrace.2 quotactl.2 \
-# read.2 readlink.2 reboot.2 recv.2 rename.2 revoke.2 rfork.2 rmdir.2 \
-# rtprio.2 select.2 semctl.2 semget.2 semop.2 send.2 sendfile.2 \
+# mount.2 nanosleep.2 \
+# nfssvc.2 pathconf.2 pipe.2 poll.2 profil.2 ptrace.2 quotactl.2 \
+# read.2 readlink.2 reboot.2 recv.2 revoke.2 rfork.2 \
+# rtprio.2 semctl.2 semget.2 semop.2 send.2 sendfile.2 \
# setgroups.2 setpgid.2 setregid.2 setresuid.2 setreuid.2 setsid.2 \
# setuid.2 shmat.2 shmctl.2 shmget.2 shutdown.2 \
# sigaction.2 sigaltstack.2 sigpending.2 sigprocmask.2 sigreturn.2 \
-# sigstack.2 sigsuspend.2 socket.2 socketpair.2 stat.2 statfs.2 \
+# sigstack.2 socket.2 socketpair.2 stat.2 statfs.2 \
# swapon.2 symlink.2 sync.2 sysarch.2 syscall.2 \
# truncate.2 umask.2 undelete.2 \
-# unlink.2 utimes.2 vfork.2 wait.2 write.2
+# utimes.2 vfork.2 wait.2 write.2
#.if !defined(NO_P1003_1B)
#MAN+= sched_get_priority_max.2 sched_setparam.2 \
# sched_setscheduler.2 sched_yield.2
#MLINKS+=getpgrp.2 getpgid.2
#MLINKS+=getpid.2 getppid.2
#MLINKS+=getpriority.2 setpriority.2
-#MLINKS+=getrlimit.2 setrlimit.2
#MLINKS+=getsockopt.2 setsockopt.2
#MLINKS+=gettimeofday.2 settimeofday.2
#MLINKS+=getuid.2 geteuid.2
* @APPLE_LICENSE_HEADER_END@
*/
+#include <dispatch/dispatch.h>
#include <libkern/OSThermalNotification.h>
#include <notify.h>
-const char *kOSThermalNotificationName = "com.apple.system.thermalstatus";
+#define OSThermalStatusName "com.apple.system.thermalstatus"
-OSThermalNotificationLevel OSThermalNotificationCurrentLevel(void)
-{
- uint64_t val;
- int token;
-
- if (NOTIFY_STATUS_OK != notify_register_check(kOSThermalNotificationName, &token))
- return OSThermalNotificationLevelAny;
+const char * const kOSThermalNotificationName = OSThermalStatusName;
- if (NOTIFY_STATUS_OK != notify_get_state(token, &val))
- return OSThermalNotificationLevelAny;
+static const char * const kOSThermalMitigationNames[kOSThermalMitigationCount] = {
+ OSThermalStatusName,
+ "com.apple.system.thermalmitigation.70percenttorch",
+ "com.apple.system.thermalmitigation.70percentbacklight",
+ "com.apple.system.thermalmitigation.50percenttorch",
+ "com.apple.system.thermalmitigation.50percentbacklight",
+ "com.apple.system.thermalmitigation.disabletorch",
+ "com.apple.system.thermalmitigation.25percentbacklight",
+ "com.apple.system.thermalmitigation.disablemapshalo",
+ "com.apple.system.thermalmitigation.appterminate",
+ "com.apple.system.thermalmitigation.devicerestart"
+};
- if (NOTIFY_STATUS_OK != notify_cancel(token))
- return OSThermalNotificationLevelAny;
+static int tokens[kOSThermalMitigationCount];
+static dispatch_once_t predicates[kOSThermalMitigationCount];
+OSThermalNotificationLevel _OSThermalNotificationLevelForBehavior(int behavior)
+{
+ uint64_t val = OSThermalNotificationLevelAny;
+ if (behavior >= 0 && behavior < kOSThermalMitigationCount) {
+ dispatch_once(&predicates[behavior], ^{
+ (void)notify_register_check(kOSThermalMitigationNames[behavior], &tokens[behavior]);
+ });
+ (void)notify_get_state(tokens[behavior], &val);
+ }
return (OSThermalNotificationLevel)val;
}
+
+void _OSThermalNotificationSetLevelForBehavior(int level, int behavior)
+{
+ uint64_t val = (uint64_t)level;
+ if (behavior >= 0 && behavior < kOSThermalMitigationCount) {
+ dispatch_once(&predicates[behavior], ^{
+ (void)notify_register_check(kOSThermalMitigationNames[behavior], &tokens[behavior]);
+ });
+ (void)notify_set_state(tokens[behavior], val);
+ }
+}
+
+
+OSThermalNotificationLevel OSThermalNotificationCurrentLevel(void)
+{
+ return _OSThermalNotificationLevelForBehavior(kOSThermalMitigationNone);
+}
+/* $OpenBSD: stack_protector.c,v 1.10 2006/03/31 05:34:44 deraadt Exp $ */
+
/*
* Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.
* All rights reserved.
*
*/
-#if defined(LIBC_SCCS) && !defined(list)
-static char rcsid[] = "$OpenBSD: stack_protector.c,v 1.3 2002/12/10 08:53:42 etoh Exp $";
-#endif
-
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <signal.h>
+#include <string.h>
#include <syslog.h>
+#include <unistd.h>
+
+extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t);
long __guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
static void __guard_setup(void) __attribute__ ((constructor));
static void
__guard_setup(void)
{
- int fd;
- if (__guard[0]!=0) return;
- fd = open ("/dev/urandom", 0);
- if (fd != -1) {
- ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
- close (fd) ;
- if (size == sizeof(__guard)) return;
- }
- /* If a random generator can't be used, the protector switches the guard
- to the "terminator canary" */
- ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
- ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
+ int mib[2];
+ size_t len;
+
+ if (__guard[0] != 0)
+ return;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARND;
+
+ len = sizeof(__guard);
+ if (__sysctl(mib, 2, __guard, &len, NULL, 0) == -1 ||
+ len != sizeof(__guard)) {
+ /* If sysctl was unsuccessful, use the "terminator canary". */
+ ((unsigned char *)__guard)[0] = 0;
+ ((unsigned char *)__guard)[1] = 0;
+ ((unsigned char *)__guard)[2] = '\n';
+ ((unsigned char *)__guard)[3] = 255;
+ }
}
+/*ARGSUSED*/
void
__stack_smash_handler(char func[], int damaged)
{
- const char message[] = "stack overflow in function %s";
- struct sigaction sa;
+ struct syslog_data sdata = SYSLOG_DATA_INIT;
+ const char message[] = "stack overflow in function %s";
+ struct sigaction sa;
+ sigset_t mask;
+
+ /* Immediately block all signal handlers from running code */
+ sigfillset(&mask);
+ sigdelset(&mask, SIGABRT);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
- /* this may fail on a chroot jail, though luck */
- syslog(LOG_CRIT, message, func);
+ /* This may fail on a chroot jail... */
+ syslog_r(LOG_CRIT, &sdata, message, func);
- bzero(&sa, sizeof(struct sigaction));
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_DFL;
- sigaction(SIGABRT, &sa, NULL);
+ bzero(&sa, sizeof(struct sigaction));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGABRT, &sa, NULL);
- kill(getpid(), SIGABRT);
+ kill(getpid(), SIGABRT);
- _exit(127);
+ _exit(127);
}
-Index: stack_protector.c
-===================================================================
---- stack_protector.c (revision 31377)
-+++ stack_protector.c (working copy)
-@@ -32,44 +32,41 @@ static char rcsid[] = "$OpenBSD: stack_p
+--- stack_protector.c.orig 2010-10-07 09:55:01.000000000 -0700
++++ stack_protector.c 2010-10-07 09:55:30.000000000 -0700
+@@ -28,65 +28,112 @@
+ */
+
#include <sys/param.h>
- #include <sys/sysctl.h>
- #include <syslog.h>
+-#include <sys/sysctl.h>
+ #include <signal.h>
+ #include <string.h>
+-#include <syslog.h>
++#include <stdlib.h>
++#include <asl.h>
+ #include <unistd.h>
+#include <sys/types.h>
-+#include <unistd.h>
+#include <fcntl.h>
++#include "CrashReporterClient.h"
++#include "libproc.h"
++#include "_simple.h"
+
-+extern void __abort(void) __dead2;
-+long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-+void __guard_setup(void) __attribute__ ((visibility ("hidden")));
++#define GUARD_MAX 8
++long __stack_chk_guard[GUARD_MAX] = {0, 0, 0, 0, 0, 0, 0, 0};
++void __abort(void) __dead2;
++void __guard_setup(const char *apple[]) __attribute__ ((visibility ("hidden")));
+void __stack_chk_fail(void);
+-extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t);
++static void
++__guard_from_kernel(const char *str)
++{
++ unsigned long long val;
++ char tmp[20], *p;
++ int idx = 0;
++
++ /* Skip over the 'stack_guard=' key to the list of values */
++ str = strchr(str, '=');
++ if (str == NULL)
++ return;
++ str++;
+
-long __guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-static void __guard_setup(void) __attribute__ ((constructor));
-void __stack_smash_handler(char func[], int damaged __attribute__((unused)));
--
++ while (str && idx < GUARD_MAX) {
++ /*
++ * Pull the next numeric string out of the list and convert it to
++ * a real number.
++ */
++ strlcpy(tmp, str, 20);
++ p = strchr(tmp, ',');
++ if (p)
++ *p = '\0';
++ val = strtoull(tmp, NULL, 0);
++ __stack_chk_guard[idx] = (long)(val & ((unsigned long) -1));
++ idx++;
++ if ((str = strchr(str, ',')) != NULL)
++ str++;
++ }
++}
+
-static void
+-__guard_setup(void)
+void
- __guard_setup(void)
++__guard_setup(const char *apple[])
{
- int fd;
-- if (__guard[0]!=0) return;
-+ if (__stack_chk_guard[0]!=0) return;
- fd = open ("/dev/urandom", 0);
- if (fd != -1) {
-- ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
-+ ssize_t size = read (fd, (char*)&__stack_chk_guard,
-+ sizeof(__stack_chk_guard));
- close (fd) ;
-- if (size == sizeof(__guard)) return;
-+ if (size == sizeof(__stack_chk_guard)
-+ && *__stack_chk_guard != 0) return;
- }
- /* If a random generator can't be used, the protector switches the guard
- to the "terminator canary" */
-- ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
-- ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
-+ ((char*)__stack_chk_guard)[0] = 0; ((char*)__stack_chk_guard)[1] = 0;
-+ ((char*)__stack_chk_guard)[2] = '\n'; ((char*)__stack_chk_guard)[3] = 255;
+- int mib[2];
++ int fd;
+ size_t len;
++ const char **p;
+
+- if (__guard[0] != 0)
++ if (__stack_chk_guard[0] != 0)
+ return;
+
+- mib[0] = CTL_KERN;
+- mib[1] = KERN_ARND;
++ for (p = apple; p && *p; p++) {
++ if (strstr(*p, "stack_guard") == *p) {
++ __guard_from_kernel(*p);
++ if (__stack_chk_guard[0] != 0)
++ return;
++ }
++ }
+
+- len = sizeof(__guard);
+- if (__sysctl(mib, 2, __guard, &len, NULL, 0) == -1 ||
+- len != sizeof(__guard)) {
+- /* If sysctl was unsuccessful, use the "terminator canary". */
+- ((unsigned char *)__guard)[0] = 0;
+- ((unsigned char *)__guard)[1] = 0;
+- ((unsigned char *)__guard)[2] = '\n';
+- ((unsigned char *)__guard)[3] = 255;
++ fd = open ("/dev/urandom", 0);
++ if (fd != -1) {
++ len = read (fd, (char*)&__stack_chk_guard, sizeof(__stack_chk_guard));
++ close(fd);
++ if (len == sizeof(__stack_chk_guard) &&
++ *__stack_chk_guard != 0)
++ return;
+ }
++
++ /* If If a random generator can't be used, the protector switches the guard
++ to the "terminator canary" */
++ ((unsigned char *)__stack_chk_guard)[0] = 0;
++ ((unsigned char *)__stack_chk_guard)[1] = 0;
++ ((unsigned char *)__stack_chk_guard)[2] = '\n';
++ ((unsigned char *)__stack_chk_guard)[3] = 255;
}
+-/*ARGSUSED*/
++#define STACKOVERFLOW "] stack overflow"
++
void
-__stack_smash_handler(char func[], int damaged)
+__stack_chk_fail()
{
-- const char message[] = "stack overflow in function %s";
-- struct sigaction sa;
-+ const char message[] = "[%d] stack overflow";
-
- /* this may fail on a chroot jail, though luck */
-- syslog(LOG_CRIT, message, func);
+- struct syslog_data sdata = SYSLOG_DATA_INIT;
+- const char message[] = "stack overflow in function %s";
+- struct sigaction sa;
+- sigset_t mask;
+-
+- /* Immediately block all signal handlers from running code */
+- sigfillset(&mask);
+- sigdelset(&mask, SIGABRT);
+- sigprocmask(SIG_BLOCK, &mask, NULL);
+-
++ char n[16]; // bigger than will hold the digits in a pid_t
++ char *np;
++ int pid = getpid();
++ char message[sizeof(n) + sizeof(STACKOVERFLOW)] = "[";
++ char prog[2*MAXCOMLEN+1] = {0};
++
++ proc_name(pid, prog, 2*MAXCOMLEN);
++ prog[2*MAXCOMLEN] = 0;
++ np = n + sizeof(n);
++ *--np = 0;
++ while(pid > 0) {
++ *--np = (pid % 10) + '0';
++ pid /= 10;
++ }
++ strlcat(message, np, sizeof(message));
++ strlcat(message, STACKOVERFLOW, sizeof(message));
+ /* This may fail on a chroot jail... */
+- syslog_r(LOG_CRIT, &sdata, message, func);
-
-- bzero(&sa, sizeof(struct sigaction));
-- sigemptyset(&sa.sa_mask);
-- sa.sa_flags = 0;
-- sa.sa_handler = SIG_DFL;
-- sigaction(SIGABRT, &sa, NULL);
+- bzero(&sa, sizeof(struct sigaction));
+- sigemptyset(&sa.sa_mask);
+- sa.sa_flags = 0;
+- sa.sa_handler = SIG_DFL;
+- sigaction(SIGABRT, &sa, NULL);
-
-- kill(getpid(), SIGABRT);
-+ syslog(LOG_CRIT, message, getpid());
+- kill(getpid(), SIGABRT);
++ _simple_asl_log_prog(ASL_LEVEL_CRIT, "user", message, prog);
-- _exit(127);
-+ __abort();
+- _exit(127);
++ CRSetCrashLogMessage(message);
++ __abort();
}
struct ProgramVars; /* forward reference */
extern void _program_vars_init(const struct ProgramVars *vars);
+extern void _libc_fork_init(void (*prepare)(void), void (*parent)(void), void (*child)(void));
+extern void _init_clock_port();
extern pthread_lock_t _malloc_lock;
extern void __xlocale_init(void);
-extern void __guard_setup(void);
+extern void __guard_setup(const char *apple[]);
+extern void __malloc_entropy_setup(const char *apple[]);
+extern int usenew_impl;
#ifdef PR_5243343
/* 5243343 - temporary hack to detect if we are running the conformance test */
#include <stdlib.h>
__private_extern__ int PR_5243343_flag = 0;
#endif /* PR_5243343 */
+__private_extern__ int __pthread_lock_debug = 0;
+__private_extern__ int __pthread_lock_old = 0;
-__private_extern__ void
-__libc_init(const struct ProgramVars *vars)
+void
+__libc_init(const struct ProgramVars *vars, void (*atfork_prepare)(void), void (*atfork_parent)(void), void (*atfork_child)(void), const char *apple[])
{
_program_vars_init(vars);
+ _libc_fork_init(atfork_prepare, atfork_parent, atfork_child);
LOCK_INIT(_malloc_lock);
+ _init_clock_port();
__xlocale_init();
- __guard_setup();
+ __guard_setup(apple);
+ __malloc_entropy_setup(apple);
+
#ifdef PR_5243343
/* 5243343 - temporary hack to detect if we are running the conformance test */
if(getenv("TET_EXECUTE"))
PR_5243343_flag = 1;
#endif /* PR_5243343 */
+#if defined(__i386__) || defined(__x86_64__)
+ if(getenv("__PTHREAD_LOCK_DEBUG__"))
+ __pthread_lock_debug = 1;
+ if(getenv("__PTHREAD_LOCK_OLD__")) {
+ __pthread_lock_old = 1;
+ usenew_impl = 0;
+ }
+#endif
+
}
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * _libc_fork_child() is called from Libsystem's libSystem_atfork_child()
+ */
+
+extern void _asl_fork_child();
+extern void _arc4_fork_child();
+extern void _init_clock_port();
+extern void _dirhelper_fork_child();
+
+void
+_libc_fork_child(void)
+{
+ _asl_fork_child();
+ _arc4_fork_child();
+ _init_clock_port();
+ _dirhelper_fork_child();
+}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-
-int __accept_nocancel(int, struct sockaddr *, socklen_t *);
-
-/*
- * accept stub, legacy version
- */
-int
-accept(int s, struct sockaddr *addr, socklen_t *addrlen)
-{
- int ret = __accept_nocancel(s, addr, addrlen);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-
-extern int __bind(int, const struct sockaddr *, socklen_t);
-
-/*
- * bind stub, legacy version
- */
-int
-bind(int s, const struct sockaddr *name, socklen_t namelen)
-{
- int ret = __bind(s, name, namelen);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-extern int __chmod(const char *path, mode_t mode);
-
-/*
- * chmod stub, ignore S_ISUID and/or S_ISGID on EPERM,
- * mandated for conformance.
- *
- * This is for UNIX03 only.
- */
-int
-chmod(const char *path, mode_t mode)
-{
- int res = __chmod(path, mode);
-
- if (res >= 0 || errno != EPERM || (mode & (S_ISUID | S_ISGID)) == 0)
- return res;
- if (mode & S_ISGID) {
- res = __chmod(path, mode ^ S_ISGID);
- if (res >= 0 || errno != EPERM)
- return res;
- }
- if (mode & S_ISUID) {
- res = __chmod(path, mode ^ S_ISUID);
- if (res >= 0 || errno != EPERM)
- return res;
- }
- if (mode & (S_ISUID | S_ISGID) == (S_ISUID | S_ISGID))
- res = __chmod(path, mode ^ (S_ISUID | S_ISGID));
- return res;
-}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-
-int __connect_nocancel(int, const struct sockaddr *, socklen_t);
-
-/*
- * connect stub, legacy version
- */
-int
-connect(int s, const struct sockaddr *name, socklen_t namelen)
-{
- int ret = __connect_nocancel(s, name, namelen);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-extern int __fchmod(int fd, mode_t mode);
-
-/*
- * fchmod stub, ignore S_ISUID and/or S_ISGID on EPERM,
- * mandated for conformance.
- *
- * This is for UNIX03 only.
- */
-int
-fchmod(int fd, mode_t mode)
-{
- int res = __fchmod(fd, mode);
-
- if (res >= 0 || errno != EPERM || (mode & (S_ISUID | S_ISGID)) == 0)
- return res;
- if (mode & S_ISGID) {
- res = __fchmod(fd, mode ^ S_ISGID);
- if (res >= 0 || errno != EPERM)
- return res;
- }
- if (mode & S_ISUID) {
- res = __fchmod(fd, mode ^ S_ISUID);
- if (res >= 0 || errno != EPERM)
- return res;
- }
- if (mode & (S_ISUID | S_ISGID) == (S_ISUID | S_ISGID))
- res = __fchmod(fd, mode ^ (S_ISUID | S_ISGID));
- return res;
-}
+++ /dev/null
-/*
- * Copyright (c) 2004, 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <fcntl.h>
-#include <stdarg.h>
-
-#ifdef VARIANT_CANCELABLE
-int __fcntl(int, int, void *);
-#else /* !VARIANT_CANCELABLE */
-int __fcntl_nocancel(int, int, void *);
-#endif /* VARIANT_CANCELABLE */
-
-/*
- * Stub function to account for the differences in the size of the third
- * argument when int and void * are different sizes. Also add pthread
- * cancelability.
- *
- * This is for LP64 only.
- */
-int
-fcntl(int fd, int cmd, ...)
-{
- va_list ap;
- void *arg;
-
- va_start(ap, cmd);
- switch(cmd) {
- case F_GETLK:
- case F_SETLK:
- case F_SETLKW:
- case F_PREALLOCATE:
- case F_SETSIZE:
- case F_RDADVISE:
- case F_READBOOTSTRAP:
- case F_WRITEBOOTSTRAP:
- case F_LOG2PHYS:
- case F_GETPATH:
- case F_PATHPKG_CHECK:
- case F_OPENFROM:
- case F_UNLINKFROM:
- case F_ADDSIGS:
- arg = va_arg(ap, void *);
- break;
- default:
- arg = (void *)((unsigned long)va_arg(ap, int));
- break;
- }
- va_end(ap);
-#ifdef VARIANT_CANCELABLE
- return (__fcntl(fd, cmd, arg));
-#else /* !VARIANT_CANCELABLE */
- return (__fcntl_nocancel(fd, cmd, arg));
-#endif /* VARIANT_CANCELABLE */
-}
+++ /dev/null
-/*
- * 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@
- */
-
-/*
- * When mutexes or spinlocks were added for thread safety, the system would
- * hang during the boot process, just after changing to the blue background.
- * So for the common case of not calling _s[eh]m_hack_{add,init}(), we just
- * use static name lists. This should be reinvestigated when there is time.
- */
-
-#define PRIVATE __private_extern__
-//#define SEM_DEBUG_FILE "/tmp/sem_names"
-//#define SHM_DEBUG_FILE "/tmp/shm_names"
-
-#if defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE)
-#include <stdio.h>
-#include <unistd.h>
-#endif /* defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE) */
-#include <stdlib.h>
-#include <string.h>
-#include <stdlib.h>
-
-#ifdef SEM_DEBUG_FILE
-#define SEM_PRINTF(fmt, args...) \
-{ \
- FILE *_sem_fp_; \
- if (access(SEM_DEBUG_FILE, F_OK) == 0 && \
- (_sem_fp_ = fopen(SEM_DEBUG_FILE, "a")) != NULL) { \
- fprintf(_sem_fp_, fmt, ## args); \
- fclose(_sem_fp_); \
- } \
-}
-#endif /* SEM_DEBUG_FILE */
-#ifdef SHM_DEBUG_FILE
-#define SHM_PRINTF(fmt, args...) \
-{ \
- FILE *_shm_fp_; \
- if (access(SHM_DEBUG_FILE, F_OK) == 0 && \
- (_shm_fp_ = fopen(SHM_DEBUG_FILE, "a")) != NULL) { \
- fprintf(_shm_fp_, fmt, ## args); \
- fclose(_shm_fp_); \
- } \
-}
-#endif /* SHM_DEBUG_FILE */
-
-/*-----------------------------------------------------------------------
- * For the Hack structure:
- *
- * first >= 0 starting serial number
- * first < 0 no serial number
- * last ending serial number (only if first >= 0)
- * debug whether an option 'D' can be appended
- *-----------------------------------------------------------------------*/
-typedef struct {
- const char *name;
- int first;
- int last;
- int debug;
-} Hack;
-
-/*-----------------------------------------------------------------------
- * For the HackList structure:
- *
- * list the list of Hack structures
- * cur the number of valid Hack structures in list
- * max the actual number of Hack structures allocated
- *-----------------------------------------------------------------------*/
-#define HACKLISTDELTA 16
-#define HACKLISTSTART 16
-typedef struct {
- const Hack *list;
- int cur;
- int max;
-} HackList;
-
-static const Hack sem_hack_default_names[] = {
- {"EDBPool", 1, 255, 0},
- {"EDDPoolLock", -1, 0, 0},
- {"Mso97SharedDg", 1920, 2047, 1},
- {"Office", 1920, 2047, 1},
- {"PT_EDBPool", 1, 255, 0},
- {"PT_EDDPoolLock", -1, 0, 0},
- {"PT_Mso97SharedDg", 1920, 2047, 0},
- {"PT_Office", 1920, 2047, 0},
- {"ShMemExtCritSection", -1, 0, 0},
- {"ShMemIntCritSection", -1, 0, 0},
- {NULL, 0, 0, 0},
-};
-static HackList sem_hack_defaults = {
- sem_hack_default_names,
- (sizeof(sem_hack_default_names) / sizeof(const Hack)) - 1,
- 0
-};
-static HackList *sem_hack_names = &sem_hack_defaults;
-
-static const Hack shm_hack_default_names[] = {
- {"EDBPool", 1, 255, 0},
- {"EDDPoolLock", -1, 0, 0},
- {"Mso97SharedDg", 1920, 2047, 1},
- {"Office", 1920, 2047, 1},
- {"PT_EDBPool", 1, 255, 0},
- {"PT_EDDPoolLock", -1, 0, 0},
- {"PT_Mso97SharedDg", 1920, 2047, 0},
- {"PT_Office", 1920, 2047, 0},
- {"PT_ShMemRefCount", -1, 0, 0}, /* not specified by MS, but seen */
- {"ShMemRefCount", -1, 0, 0},
- {NULL, 0, 0, 0},
-};
-static HackList shm_hack_defaults = {
- shm_hack_default_names,
- (sizeof(shm_hack_default_names) / sizeof(const Hack)) - 1,
- 0
-};
-static HackList *shm_hack_names = &shm_hack_defaults;
-
-static int comparkey(const void *key, const void *hname);
-static int comparstr(const void *a, const void *b);
-static int dosearch(const char *name, const HackList *hl);
-static int hl_add(HackList *hl, const Hack *h);
-static void hl_free(HackList *hl);
-static HackList *hl_init(void);
-static HackList *initList(const Hack *list);
-int _sem_hack_add(const Hack *list);
-void _sem_hack_init(void);
-PRIVATE int _sem_match(const char *name);
-int _shm_hack_add(const Hack *list);
-void _shm_hack_init(void);
-PRIVATE int _shm_match(const char *name);
-
-/*-----------------------------------------------------------------------
- * comparkey - used by bsearch to find the Hack structure with the given key
- *-----------------------------------------------------------------------*/
-static int
-comparkey(const void *key, const void *h)
-{
- return strcmp(key, ((const Hack *)h)->name);
-}
-
-/*-----------------------------------------------------------------------
- * comparstr - used by qsort to sort the Hack list
- *-----------------------------------------------------------------------*/
-static int
-comparstr(const void *a, const void *b)
-{
- return strcmp(((const Hack *)a)->name, ((const Hack *)b)->name);
-}
-
-/*-----------------------------------------------------------------------
- * dosearch - search of the given name in the given HackList. First see
- * if there is a trailing D, and a serial number. If the serial number
- * exists, try to match without the serial number, checking the series
- * range and whether the trailing D is allowed. Otherwise, try to match
- * the whole string, but check if the matched Hack structure requires a
- * serial number.
- *-----------------------------------------------------------------------*/
-static int
-dosearch(const char *name, const HackList *hl)
-{
- int series;
- int len = strlen(name);
- const char *end, *p;
- char *key;
- const Hack *h;
-
- end = name + len - 1;
- if (*end != 'D')
- end++;
- p = end - 1;
- while (p >= name && *p >= '0' && *p <= '9')
- p--;
- p++;
- if (p < end && (len = p - name) > 0) {
- key = alloca(len + 1);
- if (key) {
- series = atoi(p);
- strncpy(key, name, len);
- key[len] = 0;
- h = (const Hack *)bsearch(key, hl->list, hl->cur,
- sizeof(const Hack), comparkey);
- if (h && h->first >= 0
- && series >= h->first && series <= h->last
- && (*end == 0 || h->debug))
- return 1;
- }
- }
- h = (const Hack *)bsearch(name, hl->list, hl->cur, sizeof(const Hack),
- comparkey);
- return (h && h->first < 0);
-}
-
-/*-----------------------------------------------------------------------
- * hl_add - append to the given HackList a copy of the given Hack structure
- *-----------------------------------------------------------------------*/
-static int
-hl_add(HackList *hl, const Hack *c)
-{
- int i = hl->cur;
- Hack *h;
-
- if (!c->name)
- return -1;
- if (i >= hl->max) {
- int s = hl->max + HACKLISTDELTA;
- const Hack *new = (const Hack *)realloc((void *)hl->list,
- s * sizeof(const Hack));
-
- if (!new)
- return -1;
- hl->list = new;
- hl->max = s;
- }
- h = (Hack *)(hl->list + i);
- if ((h->name = strdup(c->name)) == NULL)
- return -1;
- h->first = c->first;
- h->last = c->last;
- h->debug = c->debug;
- hl->cur++;
- return 0;
-}
-
-/*-----------------------------------------------------------------------
- * hl_free - deallocate all memory from the given HackList
- *-----------------------------------------------------------------------*/
-static void
-hl_free(HackList *hl)
-{
- const Hack *h;
- int i;
-
- for (h = hl->list, i = hl->cur; i > 0; h++, i--)
- free((void *)h->name);
- free((void *)hl->list);
- free(hl);
-}
-
-/*-----------------------------------------------------------------------
- * hl_init - create a new HackList, with preallocated Hack structures
- *-----------------------------------------------------------------------*/
-static HackList *
-hl_init(void)
-{
- HackList *hl = (HackList *)malloc(sizeof(HackList));
-
- if (!hl)
- return NULL;
- hl->list = (Hack *)malloc(HACKLISTSTART * sizeof(Hack));
- if (!hl->list) {
- free(hl);
- return NULL;
- }
- hl->cur = 0;
- hl->max = HACKLISTSTART;
- return hl;
-}
-
-/*-----------------------------------------------------------------------
- * initList - initialize a new HackList with the given list of Hack structures
- *-----------------------------------------------------------------------*/
-static HackList *
-initList(const Hack *list)
-{
- HackList *hl = hl_init();
-
- if (hl == NULL)
- return NULL;
- for (; list->name; list++)
- if (hl_add(hl, list) < 0) {
- hl_free(hl);
- return NULL;
- }
- return hl;
-}
-
-/*-----------------------------------------------------------------------
- * PUBLIC _sem_hack_add - add the given Hack list to sem_hack_names.
- *-----------------------------------------------------------------------*/
-int
-_sem_hack_add(const Hack *list)
-{
- if (list == NULL)
- return -1;
- if (sem_hack_names == &sem_hack_defaults) {
- HackList *hl = initList(sem_hack_default_names);
- if (!hl)
- return -1;
- sem_hack_names = hl;
- }
- for (; list->name; list++)
- if (hl_add(sem_hack_names, list) < 0)
- return -1;
- qsort((void *)sem_hack_names->list, sem_hack_names->cur,
- sizeof(const Hack), comparstr);
- return 0;
-}
-
-/*-----------------------------------------------------------------------
- * PUBLIC _sem_hack_init - reinitialize sem_hack_names to the default
- *-----------------------------------------------------------------------*/
-void
-_sem_hack_init(void)
-{
- if (sem_hack_names == &sem_hack_defaults)
- return;
- hl_free(sem_hack_names);
- sem_hack_names = &sem_hack_defaults;
-}
-
-/*-----------------------------------------------------------------------
- * _sem_match - try to match the given named to sem_hack_names. Called
- * by sem_open() and sem_unlink().
- *-----------------------------------------------------------------------*/
-PRIVATE int
-_sem_match(const char *name)
-{
-#ifdef SEM_DEBUG_FILE
- int match;
-#endif /* SEM_DEBUG_FILE */
-
- if (!name || !*name)
- return 0;
-#ifdef SEM_DEBUG_FILE
- match = dosearch(name, sem_hack_names);
- if (!match)
- SEM_PRINTF("%s\n", name);
- return match;
-#else /* SEM_DEBUG_FILE */
- return dosearch(name, sem_hack_names);
-#endif /* SEM_DEBUG_FILE */
-}
-
-/*-----------------------------------------------------------------------
- * PUBLIC _shm_hack_add - add the given Hack list to shm_hack_names.
- *-----------------------------------------------------------------------*/
-int
-_shm_hack_add(const Hack *list)
-{
- if (list == NULL)
- return -1;
- if (shm_hack_names == &shm_hack_defaults) {
- HackList *hl = initList(shm_hack_default_names);
- if (!hl)
- return -1;
- shm_hack_names = hl;
- }
- for (; list->name; list++)
- if (hl_add(shm_hack_names, list) < 0)
- return -1;
- qsort((void *)shm_hack_names->list, shm_hack_names->cur,
- sizeof(const Hack), comparstr);
- return 0;
-}
-
-/*-----------------------------------------------------------------------
- * PUBLIC _shm_hack_init - reinitialize shm_hack_names to the default
- *-----------------------------------------------------------------------*/
-void
-_shm_hack_init(void)
-{
- if (shm_hack_names == &shm_hack_defaults)
- return;
- hl_free(shm_hack_names);
- shm_hack_names = &shm_hack_defaults;
-}
-
-/*-----------------------------------------------------------------------
- * _shm_match - try to match the given named to shm_hack_names. Called
- * by shm_open() and shm_unlink().
- *-----------------------------------------------------------------------*/
-PRIVATE int
-_shm_match(const char *name)
-{
-#ifdef SHM_DEBUG_FILE
- int match;
-#endif /* SHM_DEBUG_FILE */
-
- if (!name || !*name)
- return 0;
-#ifdef SHM_DEBUG_FILE
- match = dosearch(name, shm_hack_names);
- if (!match)
- SHM_PRINTF("%s\n", name);
- return match;
-#else /* SHM_DEBUG_FILE */
- return dosearch(name, shm_hack_names);
-#endif /* SHM_DEBUG_FILE */
-}
--- /dev/null
+/*
+ * Copyright (c) 2010 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+extern pid_t __fork(void);
+extern void _cthread_fork_prepare();
+extern void _cthread_fork_parent();
+extern void _cthread_fork_child();
+
+static void (*_libSystem_atfork_prepare)(void) = 0;
+static void (*_libSystem_atfork_parent)(void) = 0;
+static void (*_libSystem_atfork_child)(void) = 0;
+
+__private_extern__ void _libc_fork_init(void (*prepare)(void), void (*parent)(void), void (*child)(void))
+{
+ _libSystem_atfork_prepare = prepare;
+ _libSystem_atfork_parent = parent;
+ _libSystem_atfork_child = child;
+}
+
+/*
+ * fork stub
+ */
+pid_t
+fork(void)
+{
+ int ret;
+
+ _libSystem_atfork_prepare();
+ // Reader beware: this __fork() call is yet another wrapper around the actual syscall
+ // and lives inside libsyscall. The fork syscall needs some cuddling by asm before it's
+ // allowed to see the big wide C world.
+ ret = __fork();
+ if (-1 == ret)
+ {
+ // __fork already set errno for us
+ _libSystem_atfork_parent();
+ return ret;
+ }
+
+ if (0 == ret)
+ {
+ // We're the child in this part.
+ _libSystem_atfork_child();
+ return 0;
+ }
+
+ _libSystem_atfork_parent();
+ return ret;
+}
+
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/attr.h>
-#include <unistd.h>
-
-#include <errno.h>
-
-#ifdef __LP64__
-extern int __getattrlist(const char *, void *, void *, size_t, unsigned int);
-#else /* !__LP64__ */
-extern int __getattrlist(const char *, void *, void *, size_t, unsigned long);
-#endif /* __LP64__ */
-
-/*
- * getattrlist stub, legacy version
- */
-int
-#ifdef __LP64__
-getattrlist(const char *path, void *attrList, void *attrBuf,
- size_t attrBufSize, unsigned int options)
-#else /* !__LP64__ */
-getattrlist(const char *path, void *attrList, void *attrBuf,
- size_t attrBufSize, unsigned long options)
-#endif /* __LP64__ */
-{
- int ret = __getattrlist(path, attrList, attrBuf, attrBufSize, options);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-.\" Copyright (c) 1983, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)getdtablesize.2 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/sys/getdtablesize.2,v 1.4.2.3 2001/12/14 18:34:00 ru Exp $
-.\"
-.Dd June 4, 1993
-.Dt GETDTABLESIZE 2
-.Os
-.Sh NAME
-.Nm getdtablesize
-.Nd get descriptor table size
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In unistd.h
-.Ft int
-.Fn getdtablesize void
-.Sh DESCRIPTION
-Each process has a fixed size descriptor table,
-which is guaranteed to have at least 20 slots. The entries in
-the descriptor table are numbered with small integers starting at 0.
-The call
-.Fn getdtablesize
-returns the size of this table.
-.Sh SEE ALSO
-.Xr close 2 ,
-.Xr dup 2 ,
-.Xr open 2 ,
-.Xr select 2
-.Sh HISTORY
-The
-.Fn getdtablesize
-function call appeared in
-.Bx 4.2 .
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/socket.h>
-#include <errno.h>
-
-extern int __getpeername(int, struct sockaddr * __restrict, socklen_t * __restrict);
-
-/*
- * getpeername stub, legacy version
- */
-int
-getpeername(int socket, struct sockaddr * __restrict address,
- socklen_t * __restrict address_len)
-{
- int ret = __getpeername(socket, address, address_len);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-extern int __getrlimit(int resource, struct rlimit *rlp);
-
-/*
- * getrlimit stub, for conformance, OR in _RLIMIT_POSIX_FLAG
- *
- * This is for UNIX03 only.
- */
-int
-getrlimit(int resource, struct rlimit *rlp)
-{
- resource |= _RLIMIT_POSIX_FLAG;
- return(__getrlimit(resource, rlp));
-}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/socket.h>
-#include <errno.h>
-
-extern int __getsockname(int, struct sockaddr * __restrict, socklen_t * __restrict);
-
-/*
- * getsockname stub, legacy version
- */
-int
-getsockname(int socket, struct sockaddr * __restrict address,
- socklen_t * __restrict address_len)
-{
- int ret = __getsockname(socket, address, address_len);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <sys/ioctl.h>
-#include <stdarg.h>
-
-int __ioctl(int, unsigned long, void *);
-/*
- * Stub function to account for the third argument being void *
- *
- * This is for LP64 only.
- */
-int
-ioctl(int d, unsigned long request, ...)
-{
- va_list ap;
- void *arg;
-
- va_start(ap, request);
- arg = va_arg(ap, void *);
- va_end(ap);
- return (__ioctl(d, request, arg));
-}
+++ /dev/null
-/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <signal.h>
-
-extern int __kill(pid_t pid, int sig, int posix);
-
-/*
- * kill stub, which wraps a modified kill system call that takes a posix
- * behaviour indicator as the third parameter to indicate whether or not
- * conformance to standards is needed. We use a trailing parameter in
- * case the call is called directly via syscall(), since for most uses,
- * it won't matter to the caller.
- */
-int
-kill(pid_t pid, int sig)
-{
-#if __DARWIN_UNIX03
- return(__kill(pid, sig, 1));
-#else /* !__DARWIN_UNIX03 */
- return(__kill(pid, sig, 0));
-#endif /* !__DARWIN_UNIX03 */
-}
+++ /dev/null
-/*
- * Copyright (c) 2006, 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@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <unistd.h>
-#include <errno.h>
-
-int __lchown(const char *, uid_t, gid_t);
-
-/*
- * lchown stub, legacy version
- */
-int
-lchown(const char *path, uid_t owner, gid_t group)
-{
- int ret = __lchown(path, owner, group);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-___sandbox_me ___mac_execve
-___sandbox_mm ___mac_mount
-___sandbox_ms ___mac_syscall
-___sandbox_msp ___mac_set_proc
-__exit ___exit
-_accessx_np ___access_extended
-_getsgroups_np ___getsgroups
-_getwgroups_np ___getwgroups
-# initgroups wrapper is defined in Libinfo
-_initgroups
-_posix_madvise ___madvise
-_pthread_getugid_np ___gettid
-_pthread_setugid_np ___settid
-_setsgroups_np ___setsgroups
-_setwgroups_np ___setwgroups
-_wait4 ___wait4_nocancel
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/socket.h>
-#include <errno.h>
-
-extern int __listen(int, int);
-
-/*
- * listen stub, legacy version
- */
-int
-listen(int socket, int backlog)
-{
- int ret = __listen(socket, backlog);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <sys/mman.h>
-#include <mach/vm_param.h>
-#include <errno.h>
-
-void *__mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
-
-/*
- * mmap stub, with preemptory failures due to extra parameter checking
- * mandated for conformance.
- *
- * This is for UNIX03 only.
- */
-void *
-mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
-{
- /*
- * Preemptory failures:
- *
- * o off is not a multiple of the page size
- * o flags does not contain either MAP_PRIVATE or MAP_SHARED
- * o len is zero
- */
- extern void cthread_set_errno_self(int);
- if ((off & PAGE_MASK) ||
- (((flags & MAP_PRIVATE) != MAP_PRIVATE) &&
- ((flags & MAP_SHARED) != MAP_SHARED)) ||
- (len == 0)) {
- cthread_set_errno_self(EINVAL);
- return(MAP_FAILED);
- }
-
- return(__mmap(addr, len, prot, flags, fildes, off));
-}
+++ /dev/null
-/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-/*
- * Stub function to account for the differences in standard compliance
- * while maintaining binary backward compatibility.
- *
- * This is only the legacy behavior.
- */
-extern int __mprotect(void *, size_t, int);
-
-int
-mprotect(void *addr, size_t len, int prot)
-{
- void *aligned_addr;
- int page_mask;
- size_t offset;
- int rv;
-
- /*
- * Page-align "addr" since the system now requires it
- * for standards compliance.
- * Update "len" to reflect the alignment.
- */
- page_mask = getpagesize() - 1;
- offset = ((uintptr_t) addr) & page_mask;
- aligned_addr = (void *) (((uintptr_t) addr) & ~page_mask);
- len += offset;
- rv = __mprotect(aligned_addr, len, prot);
- if (rv == -1 && errno == ENOMEM) {
- /*
- * Standards now require that we return ENOMEM if there was
- * a hole in the address range. Panther and earlier used
- * to return an EINVAL error, so honor backwards compatibility.
- */
- errno = EINVAL;
- }
- return rv;
-}
+++ /dev/null
-.\" Copyright (c) 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)msync.2 8.2 (Berkeley) 6/21/94
-.\" $FreeBSD: src/lib/libc/sys/msync.2,v 1.17 2000/04/21 09:41:53 phantom Exp $
-.\"
-.Dd June 21, 1994
-.Dt MSYNC 2
-.Os
-.Sh NAME
-.Nm msync
-.Nd synchronize a mapped region
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.Fd #include <sys/types.h>
-.Fd #include <sys/mman.h>
-.Ft int
-.Fn msync "void *addr" "size_t len" "int flags"
-.Sh DESCRIPTION
-The
-.Fn msync
-system call
-writes any modified pages back to the filesystem and updates
-the file modification time.
-If
-.Fa len
-is 0, all modified pages within the region containing
-.Fa addr
-will be flushed;
-if
-.Fa len
-is non-zero, only those pages containing
-.Fa addr
-and
-.Fa len-1
-succeeding locations will be examined.
-The
-.Fa flags
-argument may be specified as follows:
-.Bd -literal
-MS_ASYNC Return immediately
-MS_SYNC Perform synchronous writes
-MS_INVALIDATE Invalidate all cached data
-.Ed
-.Sh RETURN VALUES
-If any errors occur, -1 is returned and errno is set to indicate the
-error.
-Otherwise, a 0 value is returned.
-.Sh ERRORS
-.Fn msync
-will fail if:
-.Bl -tag -width Er
-.It Bq Er EINVAL
-.Fa addr
-is not a multiple of the hardware page size.
-.It Bq Er EINVAL
-.Fa len
-is too large or negative.
-.It Bq Er EINVAL
-.Fa flags
-was both MS_ASYNC and MS_INVALIDATE.
-Only one of these flags is allowed.
-.It Bq Er EIO
-An I/O error occurred while writing to the file system.
-.Sh SEE ALSO
-.Xr madvise 2 ,
-.Xr mincore 2 ,
-.Xr mprotect 2 ,
-.Xr munmap 2
-.Sh HISTORY
-The
-.Fn msync
-function first appeared in
-.Bx 4.4 .
+++ /dev/null
-/*
- * Copyright (c) 2004, 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-int __msync_nocancel(void *, size_t, int);
-
-/*
- * Stub function for legacy version
- */
-int
-msync(void *addr, size_t len, int flags)
-{
- int page_mask;
- size_t offset;
-
- /*
- * Page-align "addr" since the system now requires it
- * for standards compliance.
- * Update "len" to reflect the alignment.
- */
- page_mask = getpagesize() - 1;
- offset = ((uintptr_t) addr) & page_mask;
- addr = (void *) (((uintptr_t) addr) & ~page_mask);
- len += offset;
- return __msync_nocancel(addr, len, flags);
-}
+++ /dev/null
-/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-/*
- * Stub function to account for the differences in standard compliance
- * while maintaining binary backward compatibility.
- *
- * This is only the legacy behavior.
- */
-extern int __munmap(void *, size_t);
-
-int
-munmap(void *addr, size_t len)
-{
- int page_mask;
- size_t offset;
-
- if (len == 0) {
- /*
- * Standard compliance now requires the system to return EINVAL
- * for munmap(addr, 0). Return success now to maintain
- * backwards compatibility.
- */
- return 0;
- }
- /*
- * Page-align "addr" since the system now requires it
- * for standards compliance.
- * Update "len" to reflect the adjustment and still cover the same area.
- */
- page_mask = getpagesize() - 1;
- offset = ((uintptr_t) addr) & page_mask;
- addr = (void *) (((uintptr_t) addr) & ~page_mask);
- len += offset;
- return __munmap(addr, len);
-}
.Fn nanosleep
call fails if:
.Bl -tag -width Er
-.It Bq Er EFAULT
-Either
-.Fa rqtp
-or
-.Fa rmtp
-points to memory that is not a valid part of the process
-address space.
.It Bq Er EINTR
.Fn nanosleep
was interrupted by the delivery of a signal.
.Fa rqtp
specified a nanosecond value less than zero
or greater than or equal to 1000 million.
-.It Bq Er ENOSYS
-.Fn nanosleep
-is not supported by this implementation.
.El
.Sh SEE ALSO
.Xr sigsuspend 2 ,
+++ /dev/null
-/*
- * Copyright (c) 2005, 2009 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdarg.h>
-
-int __open_nocancel(const char *path, int flags, mode_t mode);
-
-/*
- * open stub: The legacy interface never automatically associated a controlling
- * tty, so we always pass O_NOCTTY.
- */
-int
-open(const char *path, int flags, ...)
-{
- mode_t mode = 0;
-
- if(flags & O_CREAT) {
- va_list ap;
- va_start(ap, flags);
- // compiler warns to pass int (not mode_t) to va_arg
- mode = va_arg(ap, int);
- va_end(ap);
- }
- return(__open_nocancel(path, flags | O_NOCTTY, mode));
-}
* NOTIMP: Allowed failures (checking NOT required):
* EINVAL The value specified by attr is invalid.
*/
-int posix_spawn_destroyportactions_np(posix_spawnattr_t *);
+static int posix_spawn_destroyportactions_np(posix_spawnattr_t *);
int
posix_spawnattr_destroy(posix_spawnattr_t *attr)
* Description: create a new posix_spawn_port_actions struct and link
* it into the posix_spawnattr.
*/
-int
+static int
posix_spawn_createportactions_np(posix_spawnattr_t *attr)
{
_posix_spawnattr_t psattr;
* posix_spawn_growportactions_np
* Description: Enlarge the size of portactions if necessary
*/
-int
+static int
posix_spawn_growportactions_np(posix_spawnattr_t *attr)
{
_posix_spawnattr_t psattr;
* posix_spawn_destroyportactions_np
* Description: clean up portactions struct in posix_spawnattr_t attr
*/
-int
+static int
posix_spawn_destroyportactions_np(posix_spawnattr_t *attr)
{
_posix_spawnattr_t psattr;
* opened with flags 'oflag' and mode 'mode', and, if successful,
* return as descriptor 'filedes' to the spawned process.
*
- * Parameters: file_actions File action object to add open to
+ * Parameters: file_actions File action object to augment
* filedes fd that open is to use
* path path to file to open
* oflag open file flags
* that will cause the file referenced by 'filedes' to be
* attempted to be closed in the spawned process.
*
- * Parameters: file_actions File action object to add open to
+ * Parameters: file_actions File action object to augment
* filedes fd to close
*
* Returns: 0 Success
/*
* posix_spawn_file_actions_adddup2
*
- * Description: Add a dpu2 action to the object referenced by 'file_actions'
+ * Description: Add a dup2 action to the object referenced by 'file_actions'
* that will cause the file referenced by 'filedes' to be
* attempted to be dup2'ed to the descriptor 'newfiledes' in the
* spawned process.
*
- * Parameters: file_actions File action object to add open to
+ * Parameters: file_actions File action object to augment
* filedes fd to dup2
* newfiledes fd to dup2 it to
*
return (0);
}
+/*
+ * posix_spawn_file_actions_addinherit_np
+ *
+ * Description: Add the "inherit" action to the object referenced by
+ * 'file_actions' that will cause the file referenced by
+ * 'filedes' to continue to be available in the spawned
+ * process via the same descriptor.
+ *
+ * Inheritance is the normal default behaviour for
+ * file descriptors across exec and spawn; but if the
+ * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
+ * default is reversed for the purposes of the spawn
+ * invocation. Any pre-existing descriptors that
+ * need to be made available to the spawned process can
+ * be marked explicitly as 'inherit' via this interface.
+ * Otherwise they will be automatically closed.
+ *
+ * Note that any descriptors created via the other file
+ * actions interfaces are automatically marked as 'inherit'.
+ *
+ * Parameters: file_actions File action object to augment
+ * filedes fd to inherit.
+ *
+ * Returns: 0 Success
+ * EBADF The value specified by fildes is
+ * negative or greater than or equal to
+ * {OPEN_MAX}.
+ * ENOMEM Insufficient memory exists to add to
+ * the spawn file actions object.
+ *
+ * NOTIMP: Allowed failures (checking NOT required):
+ * EINVAL The value specified by file_actions is invalid.
+ */
+int
+posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t *file_actions,
+ int filedes)
+{
+ _posix_spawn_file_actions_t *psactsp;
+ _psfa_action_t *psfileact;
+
+ if (file_actions == NULL || *file_actions == NULL)
+ return (EINVAL);
+
+ psactsp = (_posix_spawn_file_actions_t *)file_actions;
+ /* Range check; required by POSIX */
+ if (filedes < 0 || filedes >= OPEN_MAX)
+ return (EBADF);
+
+#if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
+ /* If we do not have enough slots, grow the structure */
+ if ((*psactsp)->psfa_act_count == (*psactsp)->psfa_act_alloc) {
+ /* need to grow file actions structure */
+ if (_posix_spawn_file_actions_grow(psactsp))
+ return (ENOMEM);
+ }
+
+ /*
+ * Allocate next available slot and fill it out
+ */
+ psfileact = &(*psactsp)->psfa_act_acts[(*psactsp)->psfa_act_count++];
+
+ psfileact->psfaa_type = PSFA_INHERIT;
+ psfileact->psfaa_filedes = filedes;
+#endif
+ return (0);
+}
+
/*
* posix_spawnp
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/socket.h>
-#include <errno.h>
-
-ssize_t __recvfrom_nocancel(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict);
-
-/*
- * recvfrom stub, legacy version
- */
-ssize_t
-recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr * __restrict from, socklen_t * __restrict fromlen)
-{
- int ret = __recvfrom_nocancel(s, buf, len, flags, from, fromlen);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/socket.h>
-#include <errno.h>
-
-ssize_t __recvmsg_nocancel(int, struct msghdr *, int);
-
-/*
- * recvmsg stub, legacy version
- */
-ssize_t
-recvmsg(int s, struct msghdr *msg, int flags)
-{
- int ret = __recvmsg_nocancel(s, msg, flags);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2009 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 <libkern/OSAtomic.h>
-
-#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)
-static int64_t __remove_counter = 0;
-#else
-static int32_t __remove_counter = 0;
-#endif
-
-uint64_t
-__get_remove_counter(void) {
-#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)
- return (uint64_t)OSAtomicAdd64Barrier(0, &__remove_counter);
-#else
- return (uint64_t)OSAtomicAdd32Barrier(0, &__remove_counter);
-#endif
-}
-
-__private_extern__ void
-__inc_remove_counter(void)
-{
-#if defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)
- (void)OSAtomicAdd64(1, &__remove_counter);
-#else
- (void)OSAtomicAdd32(1, &__remove_counter);
-#endif
-}
+++ /dev/null
-/*
- * Copyright (c) 2009 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 <stdio.h>
-
-void __inc_remove_counter(void);
-int __rename(const char *old, const char *new);
-
-int
-rename(const char *old, const char *new)
-{
- int res = __rename(old, new);
- if (res == 0) __inc_remove_counter();
- return res;
-}
+++ /dev/null
-/*
- * Copyright (c) 2009 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 <unistd.h>
-
-void __inc_remove_counter(void);
-int __rmdir(const char *path);
-
-int
-rmdir(const char *path)
-{
- int res = __rmdir(path);
- if (res == 0) __inc_remove_counter();
- return res;
-}
+++ /dev/null
-/*
- * Copyright (c) 2005, 2007 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#if defined(__LP64__) && (defined(VARIANT_CANCELABLE) || defined(VARIANT_PRE1050))
-#undef __DARWIN_NON_CANCELABLE
-#define __DARWIN_NON_CANCELABLE 0
-#endif /* __LP64__ && (VARIANT_CANCELABLE || VARIANT_PRE1050) */
-#include <sys/select.h>
-#include <errno.h>
-
-#if defined(VARIANT_CANCELABLE) || defined(VARIANT_PRE1050)
-extern int __select(int, fd_set * __restrict, fd_set * __restrict,
- fd_set * __restrict, struct timeval * __restrict);
-#else /* !VARIANT_CANCELABLE && !VARIANT_PRE1050 */
-int __select_nocancel(int, fd_set * __restrict, fd_set * __restrict,
- fd_set * __restrict, struct timeval * __restrict);
-#endif /* VARIANT_CANCELABLE || VARIANT_PRE1050 */
-
-/*
- * select stub, return error if nfds > FD_SETSIZE
- * add pthread cancelability
- * mandated for conformance.
- *
- * This is only for (non DARWINEXTSN) UNIX03 (both cancelable and
- * non-cancelable) and for legacy
- */
-int
-select(int nfds, fd_set * __restrict readfds, fd_set * __restrict writefds,
- fd_set * __restrict exceptfds, struct timeval * __restrict
-#if defined(VARIANT_LEGACY) || defined(VARIANT_PRE1050)
- intimeout
-#else /* !VARIANT_LEGACY && !VARIANT_PRE1050 */
- timeout
-#endif /* VARIANT_LEGACY || VARIANT_PRE1050 */
- )
-{
-
-#if defined(VARIANT_LEGACY) || defined(VARIANT_PRE1050)
- struct timeval tb, *timeout;
-
- /*
- * Legacy select behavior is minimum 10 msec when tv_usec is non-zero
- */
- if (intimeout && intimeout->tv_sec == 0 && intimeout->tv_usec > 0 && intimeout->tv_usec < 10000) {
- tb.tv_sec = 0;
- tb.tv_usec = 10000;
- timeout = &tb;
- } else
- timeout = intimeout;
-#else /* !VARIANT_LEGACY && !VARIANT_PRE1050 */
- if (nfds > FD_SETSIZE) {
- errno = EINVAL;
- return -1;
- }
-#endif /* VARIANT_LEGACY || VARIANT_PRE1050 */
-#if defined(VARIANT_CANCELABLE) || defined(VARIANT_PRE1050)
- return __select(nfds, readfds, writefds, exceptfds, timeout);
-#else /* !VARIANT_CANCELABLE && !VARIANT_PRE1050 */
- return __select_nocancel(nfds, readfds, writefds, exceptfds, timeout);
-#endif /* VARIANT_CANCELABLE || VARIANT_PRE1050 */
-}
+++ /dev/null
-.\" $Darwin$
-.\"
-.\" Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
-.\"
-.\" @APPLE_LICENSE_HEADER_START@
-.\"
-.\" The contents of this file constitute Original Code as defined in and
-.\" are subject to the Apple Public Source License Version 1.1 (the
-.\" "License"). You may not use this file except in compliance with the
-.\" License. Please obtain a copy of the License at
-.\" http://www.apple.com/publicsource and read it before using this file.
-.\"
-.\" This Original Code and all software distributed under the License are
-.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-.\" License for the specific language governing rights and limitations
-.\" under the License.
-.\"
-.\" @APPLE_LICENSE_HEADER_END@
-.\"
-.Dd June 8, 2000
-.Dt SEM_CLOSE 2
-.Os Darwin
-.Sh NAME
-.Nm sem_close
-.Nd close a named semaphore
-.Sh SYNOPSIS
-.Fd #include <semaphore.h>
-.Ft int
-.Fn sem_close "sem_t *sem"
-.Sh DESCRIPTION
-The system resources associated with the named semaphore referenced by
-.Fa sem
-are deallocated and the descriptor is invalidated.
-.Pp
-If successful,
-.Fn sem_close
-will return 0. Otherwise, -1 is returned and
-.Va errno
-is set.
-.Sh ERRORS
-.Fn sem_close
-succeeds unless:
-.Bl -tag -width Er
-.It Bq Er EINVAL
-.Fa sem
-is not a valid semaphore descriptor.
-.El
-.Sh SEE ALSO
-.Xr sem_init 2 ,
-.Xr sem_open 2 ,
-.Xr sem_unlink 2 ,
-.Xr semctl 2 ,
-.Xr semget 2 ,
-.Xr semop 2
-.Sh HISTORY
-.Fn sem_close
-is specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995).
+++ /dev/null
-.\" $Darwin$
-.\"
-.\" Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
-.\"
-.\" @APPLE_LICENSE_HEADER_START@
-.\"
-.\" The contents of this file constitute Original Code as defined in and
-.\" are subject to the Apple Public Source License Version 1.1 (the
-.\" "License"). You may not use this file except in compliance with the
-.\" License. Please obtain a copy of the License at
-.\" http://www.apple.com/publicsource and read it before using this file.
-.\"
-.\" This Original Code and all software distributed under the License are
-.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-.\" License for the specific language governing rights and limitations
-.\" under the License.
-.\"
-.\" @APPLE_LICENSE_HEADER_END@
-.\"
-.Dd June 8, 2000
-.Dt SEM_OPEN 2
-.Os Darwin
-.Sh NAME
-.Nm sem_open
-.Nd initialize and open a named semaphore
-.Sh SYNOPSIS
-.Fd #include <semaphore.h>
-.Ft sem_t *
-.Fo sem_open
-.Fa "const char *name"
-.Fa "int oflag"
-.Fa "..."
-.Fc
-.Pp
-The parameters "mode_t mode" and "unsigned int value"
-are optional.
-.Sh DESCRIPTION
-The named semaphore named
-.Fa name
-is initialized and opened as specified by the argument
-.Fa oflag
-and a semaphore descriptor is returned to the calling process.
-.Pp
-The value of
-.Fa oflag
-is formed by
-.Em or Ns 'ing
-the following values:
-.Pp
-.Bd -literal -offset indent -compact
-O_CREAT create the semaphore if it does not exist
-O_EXCL error if create and semaphore exists
-.Ed
-.Pp
-If
-.Dv O_CREAT
-is specified,
-.Fn sem_open
-requires an additional two arguments.
-.Fa mode
-specifies the permissions for the semaphore as described in
-.Xr chmod 2
-and modified by the process' umask value (see
-.Xr umask 2 ) .
-The semaphore is created with an initial
-.Fa value ,
-which must be less than or equal to
-.Dv SEM_VALUE_MAX .
-.Pp
-If
-.Dv O_EXCL
-is specified and the semaphore exists,
-.Fn sem_open
-fails. The check for the existence of the semaphore and the creation
-of the semaphore are atomic with respect to all processes calling
-.Fn sem_open
-with
-.Dv O_CREAT
-and
-.Dv O_EXCL
-set.
-.Pp
-When a new semaphore is created, it is given the user ID and group ID
-which correspond to the effective user and group IDs of the calling
-process. There is no visible entry in the file system for the created
-object in this implementation.
-.Pp
-The returned semaphore descriptor is available to the calling process
-until it is closed with
-.Fn sem_close ,
-or until the caller exits or execs.
-.Pp
-If a process makes repeated calls to
-.Fn sem_open ,
-with the same
-.Fa name
-argument, the same descriptor is returned for each successful call,
-unless
-.Fn sem_unlink
-has been called on the semaphore in the interim.
-.Pp
-If
-.Fn sem_open
-fails for any reason, it will return a value of
-.Dv SEM_FAILED
-and sets
-.Va errno .
-On success, it returns a semaphore descriptor.
-.Sh ERRORS
-The named semaphore is opened unless:
-.Bl -tag -width Er
-.It Bq Er EACCES
-The required permissions (for reading and/or writing)
-are denied for the given flags; or
-.Dv O_CREAT
-is specified, the object does not exist, and permission to
-create the semaphore is denied.
-.It Bq Er EEXIST
-.Dv O_CREAT
-and
-.Dv O_EXCL
-were specified and the semaphore exists.
-.It Bq Er EINTR
-The
-.Fn sem_open
-operation was interrupted by a signal.
-.It Bq Er EINVAL
-The
-.Fn shm_open
-operation is not supported; or
-.Dv O_CREAT
-is specified and
-.Fa value
-exceeds
-.Dv SEM_VALUE_MAX .
-.It Bq Er EMFILE
-The process has already reached its limit for semaphores or file
-descriptors in use.
-.It Bq Er ENAMETOOLONG
-.Fa name
-exceeded
-.Dv SEM_NAME_LEN
-characters.
-.It Bq Er ENFILE
-Too many semaphores or file descriptors are open on the system.
-.It Bq Er ENOENT
-.Dv O_CREAT
-is not set and the named semaphore does not exist.
-.It Bq Er ENOSPC
-.Dv O_CREAT
-is specified, the file does not exist, and there is insufficient
-space available to create the semaphore.
-.El
-.Sh SEE ALSO
-.Xr sem_close 2 ,
-.Xr sem_post 2 ,
-.Xr sem_trywait 2 ,
-.Xr sem_unlink 2 ,
-.Xr sem_wait 2 ,
-.Xr semctl 2 ,
-.Xr semget 2 ,
-.Xr semop 2 ,
-.Xr umask 2
-.Sh HISTORY
-.Fn sem_open
-is specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995).
+++ /dev/null
-/*
- * Copyright (c) 1999, 2009 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <sys/cdefs.h>
-
-#ifdef __APPLE_PR3375657_HACK__
-
-#include <stdio.h>
-#include <semaphore.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <alloca.h>
-#include <stdarg.h>
-#include <string.h>
-
-__private_extern__ int _sem_match(const char *name);
-extern sem_t *__sem_open(const char *, int, int, unsigned int);
-
-sem_t *
-sem_open (const char *name, int flags, ...)
-{
- char *buffer;
- va_list ap;
- int mode;
- unsigned int value;
-
- /*
- * To work-around applications that don't play
- * well in multiple GUI sessions, we append
- * shared memory names with the effective user ID.
- * It would be better to append the region name
- * with a session ID, but nothing like that
- * exists at this level of the system yet.
- */
-
- if (_sem_match(name) && (buffer = alloca(strlen(name) + 32)) != NULL) {
- sprintf(buffer, "%s\t%d", name, geteuid());
- name = buffer;
- }
-
-// sem_open (const char *name, int flags, mode_t mode, unsigned int value)
- va_start(ap, flags);
- mode = va_arg(ap, int); /* promoted from mode_t to int */
- value = va_arg(ap, unsigned int);
- va_end(ap);
-
- return __sem_open(name, flags, mode, value);
-}
-
-#endif /* __APPLE_PR3375657_HACK__ */
+++ /dev/null
-.\" $Darwin$
-.\"
-.\" Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
-.\"
-.\" @APPLE_LICENSE_HEADER_START@
-.\"
-.\" The contents of this file constitute Original Code as defined in and
-.\" are subject to the Apple Public Source License Version 1.1 (the
-.\" "License"). You may not use this file except in compliance with the
-.\" License. Please obtain a copy of the License at
-.\" http://www.apple.com/publicsource and read it before using this file.
-.\"
-.\" This Original Code and all software distributed under the License are
-.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-.\" License for the specific language governing rights and limitations
-.\" under the License.
-.\"
-.\" @APPLE_LICENSE_HEADER_END@
-.\"
-.Dd June 8, 2000
-.Dt SEM_POST 2
-.Os Darwin
-.Sh NAME
-.Nm sem_post
-.Nd unlock a semaphore
-.Sh SYNOPSIS
-.Fd #include <semaphore.h>
-.Ft int
-.Fn sem_post "sem_t *sem"
-.Sh DESCRIPTION
-The semaphore referenced by
-.Fa sem
-is unlocked, the value of the semaphore is incremented, and all
-threads which are waiting on the semaphore are awakened.
-.Pp
-.Fn sem_post
-is reentrant with respect to signals and may be called from within a
-signal hanlder.
-.Pp
-If successful,
-.Fn sem_post
-will return 0. Otherwise, -1 is returned and
-.Va errno
-is set.
-.Sh ERRORS
-.Fn sem_post
-succeeds unless:
-.Bl -tag -width Er
-.It Bq Er EINVAL
-.Fa sem
-is not a valid semaphore descriptor.
-.El
-.Sh SEE ALSO
-.Xr sem_open 2 ,
-.Xr sem_trywait 2 ,
-.Xr sem_wait 2 ,
-.Xr semctl 2 ,
-.Xr semget 2 ,
-.Xr semop 2
-.Sh HISTORY
-.Fn sem_post
-is specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995).
+++ /dev/null
-.\" $Darwin$
-.\"
-.\" Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
-.\"
-.\" @APPLE_LICENSE_HEADER_START@
-.\"
-.\" The contents of this file constitute Original Code as defined in and
-.\" are subject to the Apple Public Source License Version 1.1 (the
-.\" "License"). You may not use this file except in compliance with the
-.\" License. Please obtain a copy of the License at
-.\" http://www.apple.com/publicsource and read it before using this file.
-.\"
-.\" This Original Code and all software distributed under the License are
-.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-.\" License for the specific language governing rights and limitations
-.\" under the License.
-.\"
-.\" @APPLE_LICENSE_HEADER_END@
-.\"
-.Dd June 8, 2000
-.Dt SEM_UNLINK 2
-.Os Darwin
-.Sh NAME
-.Nm sem_unlink
-.Nd remove a named semaphore
-.Sh SYNOPSIS
-.Fd #include <semaphore.h>
-.Ft int
-.Fn sem_unlink "const char *name"
-.Sh DESCRIPTION
-The named semaphore named
-.Fa name
-is removed. If the semaphore is in use by other processes, then
-.Fa name
-is immediately disassociated with the semaphore, but the semaphore
-itself will not be removed until all references to it have been
-closed. Subsequent calls to
-.Fn sem_open
-using
-.Fa name
-will refer to or create a new semaphore named
-.Fa name .
-.Pp
-If successful,
-.Fn sem_unlink
-will return 0. Otherwise, -1 is returned and
-.Va errno
-is set, and the state of the semaphore is unchanged.
-.Sh ERRORS
-.Fn sem_unlink
-succeeds unless:
-.Bl -tag -width Er
-.It Bq Er EACCES
-Permission is denied to be remove the semaphore.
-.It Bq Er ENAMETOOLONG
-.Fa name
-exceeded
-.Dv SEM_NAME_LEN
-characters.
-.It Bq Er ENOENT
-The named semaphore does not exist.
-.El
-.Sh SEE ALSO
-.Xr sem_close 2 ,
-.Xr sem_open 2 ,
-.Xr semctl 2 ,
-.Xr semget 2 ,
-.Xr semop 2
-.Sh HISTORY
-.Fn sem_unlink
-is specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995).
+++ /dev/null
-/*
- * Copyright (c) 1999, 2009 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <sys/cdefs.h>
-
-#ifdef __APPLE_PR3375657_HACK__
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <alloca.h>
-#include <string.h>
-
-__private_extern__ int _sem_match(const char *name);
-extern int __sem_unlink(const char *);
-
-int
-sem_unlink (const char *name)
-{
- char *buffer;
-
- /*
- * To work-around applications that don't play
- * well in multiple GUI sessions, we append
- * shared memory names with the effective user ID.
- * It would be better to append the region name
- * with a session ID, but nothing like that
- * exists at this level of the system yet.
- */
-
- if (_sem_match(name) && (buffer = alloca(strlen(name) + 32)) != NULL) {
- sprintf(buffer, "%s\t%d", name, geteuid());
- name = buffer;
- }
-
- return __sem_unlink(name);
-}
-
-#endif /* __APPLE_PR3375657_HACK__ */
+++ /dev/null
-.\" $Darwin$
-.\"
-.\" Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
-.\"
-.\" @APPLE_LICENSE_HEADER_START@
-.\"
-.\" The contents of this file constitute Original Code as defined in and
-.\" are subject to the Apple Public Source License Version 1.1 (the
-.\" "License"). You may not use this file except in compliance with the
-.\" License. Please obtain a copy of the License at
-.\" http://www.apple.com/publicsource and read it before using this file.
-.\"
-.\" This Original Code and all software distributed under the License are
-.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-.\" License for the specific language governing rights and limitations
-.\" under the License.
-.\"
-.\" @APPLE_LICENSE_HEADER_END@
-.\"
-.Dd June 8, 2000
-.Dt SEM_WAIT 2
-.Os Darwin
-.Sh NAME
-.Nm sem_trywait, sem_wait
-.Nd lock a semaphore
-.Sh SYNOPSIS
-.Fd #include <semaphore.h>
-.Ft int
-.Fn sem_trywait "sem_t *sem"
-.Ft int
-.Fn sem_wait "sem_t *sem"
-.Sh DESCRIPTION
-The semaphore referenced by
-.Fa sem
-is locked. When calling
-.Fn sem_wait ,
-if the semaphore's value is zero, the calling thread will block until
-the lock is acquired or until the call is interrupted by a
-signal. Alternatively, the
-.Fn sem_trywait
-function will fail if the semaphore is already locked, rather than
-blocking on the semaphore.
-.Pp
-If successful (the lock was acquired),
-.Fn sem_wait
-and
-.Fn sem_trywait
-will return 0. Otherwise, -1 is returned and
-.Va errno
-is set, and the state of the semaphore is unchanged.
-.Sh ERRORS
-.Fn sem_wait
-and
-.Fn sem_trywait
-succeed unless:
-.Bl -tag -width Er
-.It Bq Er EAGAIN
-The semaphore is already locked.
-.It Bq Er EDEADLK
-A deadlock was detected.
-.It Bq Er EINTR
-The call was interrupted by a signal.
-.It Bq Er EINVAL
-.Fa sem
-is not a valid semaphore descriptor.
-.El
-.Sh NOTES
-Applications may encounter a priority inversion while using
-semaphores. When a thread is waiting on a semaphore which is about to
-be posted by a lower-priority thread and the lower-priority thread is
-preempted by another thread (of medium priority), a priority inversion
-has occured, and the higher-priority thread will be blocked for an
-unlimited time period. Programmers using the realtime functionality
-of the system should take care to avoid priority inversions.
-.Sh SEE ALSO
-.Xr sem_open 2 ,
-.Xr sem_post 2 ,
-.Xr semctl 2 ,
-.Xr semget 2 ,
-.Xr semop 2
-.Sh HISTORY
-.Fn sem_wait
-and
-.Fn sem_trywait
-are specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995).
+++ /dev/null
-/*
- * Copyright (c) 2006, 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@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-
-ssize_t __sendmsg_nocancel(int, const struct msghdr *, int);
-
-/*
- * sendmsg stub, legacy version
- */
-ssize_t
-sendmsg(int s, const struct msghdr *msg, int flags)
-{
- int ret = __sendmsg_nocancel(s, msg, flags);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-
-ssize_t __sendto_nocancel(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
-
-/*
- * sendto stub, legacy version
- */
-ssize_t
-sendto(int s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
-{
- int ret = __sendto_nocancel(s, msg, len, flags, to, tolen);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/attr.h>
-#include <unistd.h>
-
-#include <errno.h>
-
-#ifdef __LP64__
-extern int __setattrlist(const char *, void *, void *, size_t, unsigned int);
-#else /* !__LP64__ */
-extern int __setattrlist(const char *, void *, void *, size_t, unsigned long);
-#endif /* __LP64__ */
-
-/*
- * setattrlist stub, legacy version
- */
-int
-#ifdef __LP64__
-setattrlist(const char *path, void *attrList, void *attrBuf,
- size_t attrBufSize, unsigned int options)
-#else /* !__LP64__ */
-setattrlist(const char *path, void *attrList, void *attrBuf,
- size_t attrBufSize, unsigned long options)
-#endif /* __LP64__ */
-{
- int ret = __setattrlist(path, attrList, attrBuf, attrBufSize, options);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
+++ /dev/null
-.\" Copyright (c) 1980, 1991, 1993, 1994
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)setregid.2 8.2 (Berkeley) 4/16/94
-.\" $FreeBSD: src/lib/libc/sys/setregid.2,v 1.6.2.4 2001/12/14 18:34:01 ru Exp $
-.\"
-.Dd April 16, 1994
-.Dt SETREGID 2
-.Os
-.Sh NAME
-.Nm setregid
-.Nd set real and effective group ID
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In unistd.h
-.Ft int
-.Fn setregid "gid_t rgid" "gid_t egid"
-.Sh DESCRIPTION
-The real and effective group ID's of the current process
-are set to the arguments.
-Unprivileged users may change the real group
-ID to the effective group ID and vice-versa; only the super-user may
-make other changes.
-.Pp
-Supplying a value of -1 for either the real or effective
-group ID forces the system to substitute the current
-ID in place of the -1 parameter.
-.Pp
-The
-.Fn setregid
-function was intended to allow swapping
-the real and effective group IDs
-in set-group-ID programs to temporarily relinquish the set-group-ID value.
-This function did not work correctly;
-its purpose is now better served by the use of the
-.Fn setegid
-function (see
-.Xr setuid 2 ) .
-.Pp
-When setting the real and effective group IDs to the same value,
-the standard
-.Fn setgid
-function is preferred.
-.Sh RETURN VALUES
-.Rv -std setregid
-.Sh ERRORS
-.Bl -tag -width Er
-.It Bq Er EPERM
-The current process is not the super-user and a change
-other than changing the effective group-id to the real group-id
-was specified.
-.El
-.Sh SEE ALSO
-.Xr getgid 2 ,
-.Xr issetugid 2 ,
-.Xr setegid 2 ,
-.Xr setgid 2 ,
-.Xr setuid 2
-.Sh HISTORY
-The
-.Fn setregid
-system call appeared in
-.Bx 4.2 .
+++ /dev/null
-.\" Copyright (c) 1980, 1991, 1993, 1994
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)setreuid.2 8.2 (Berkeley) 4/16/94
-.\" $FreeBSD: src/lib/libc/sys/setreuid.2,v 1.6.2.6 2001/12/14 18:34:01 ru Exp $
-.\"
-.Dd February 8, 2001
-.Dt SETREUID 2
-.Os
-.Sh NAME
-.Nm setreuid
-.Nd set real and effective user IDs
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In unistd.h
-.Ft int
-.Fn setreuid "uid_t ruid" "uid_t euid"
-.Sh DESCRIPTION
-The real and effective user IDs of the
-current process are set according to the arguments.
-If
-.Fa ruid
-or
-.Fa euid
-is -1, the current uid is filled in by the system.
-Unprivileged users may change the real user
-ID to the effective user ID and vice-versa; only the super-user may
-make other changes.
-.Pp
-The
-.Fn setreuid
-function has been used to swap the real and effective user IDs
-in set-user-ID programs to temporarily relinquish the set-user-ID value.
-This purpose is now better served by the use of the
-.Fn seteuid
-function (see
-.Xr setuid 2 ) .
-.Pp
-When setting the real and effective user IDs to the same value,
-the standard
-.Fn setuid
-function is preferred.
-.Sh RETURN VALUES
-.Rv -std setreuid
-.Sh ERRORS
-.Bl -tag -width Er
-.It Bq Er EPERM
-The current process is not the super-user and a change
-other than changing the effective user-id to the real user-id
-was specified.
-.El
-.Sh SEE ALSO
-.Xr getuid 2 ,
-.Xr issetugid 2 ,
-.Xr seteuid 2 ,
-.Xr setuid 2
-.Sh HISTORY
-The
-.Fn setreuid
-system call appeared in
-.Bx 4.2 .
+++ /dev/null
-/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-extern int __setrlimit(int resource, const struct rlimit *rlp);
-
-/*
- * setrlimit stub, for conformance, OR in _RLIMIT_POSIX_FLAG
- *
- * This is for UNIX03 only.
- */
-int
-setrlimit(int resource, const struct rlimit *rlp)
-{
- resource |= _RLIMIT_POSIX_FLAG;
- return(__setrlimit(resource, rlp));
-}
+++ /dev/null
-.\" $Darwin$
-.\"
-.\" Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
-.\"
-.\" @APPLE_LICENSE_HEADER_START@
-.\"
-.\" The contents of this file constitute Original Code as defined in and
-.\" are subject to the Apple Public Source License Version 1.1 (the
-.\" "License"). You may not use this file except in compliance with the
-.\" License. Please obtain a copy of the License at
-.\" http://www.apple.com/publicsource and read it before using this file.
-.\"
-.\" This Original Code and all software distributed under the License are
-.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-.\" License for the specific language governing rights and limitations
-.\" under the License.
-.\"
-.\" @APPLE_LICENSE_HEADER_END@
-.\"
-.Dd August 29, 2008
-.Dt SHM_OPEN 2
-.Os Darwin
-.Sh NAME
-.Nm shm_open
-.Nd open a shared memory object
-.Sh SYNOPSIS
-.Fd #include <sys/mman.h>
-.Ft int
-.Fo shm_open
-.Fa "const char *name"
-.Fa "int oflag"
-.Fa "..."
-.Fc
-.Pp
-The parameter "mode_t mode" is optional.
-.Sh DESCRIPTION
-The shared memory object referenced by
-.Fa name
-is opened for reading and/or writing as specified by the argument
-.Fa oflag
-and the file descriptor returned to the calling process.
-The returned file descriptor will be the lowest non-open file
-descriptor for the calling process, and is not shared with any
-other processes, as it is a new file descriptor. The new file
-descriptor will have the
-.Dv FD_CLOEXEC
-flag set.
-Repeated calls
-to
-.Nm shm_open
-with the same string value for
-.Fn name
-will return a file descriptor referring to the same shared memory
-object, provided that the object has not been unlinked by a call to
-.Fn shm_unlink .
-The
-.Fa oflag
-argument may indicate the file is to be
-created if it does not exist (by specifying the
-.Dv O_CREAT
-flag), in which case the file is created with mode
-.Fa mode
-as described in
-.Xr chmod 2
-and modified by the process' umask value (see
-.Xr umask 2 ) .
-.Pp
-The value of
-.Fa oflag
-is formed by
-.Em or Ns 'ing
-the following values:
-.Pp
-.Bd -literal -offset indent -compact
-O_RDONLY open for reading only
-O_RDWR open for reading and writing
-O_CREAT create object if it does not exist
-O_EXCL error if create and object exists
-O_TRUNC truncate size to 0
-.Ed
-.Pp
-Exactly one of
-.Dv O_RDONLY
-or
-.Dv O_RDWR
-must be specified.
-.Pp
-If
-.Dv O_TRUNC
-is specified and the
-file exists, the file is truncated to zero length.
-If
-.Dv O_EXCL
-is set with
-.Dv O_CREAT
-and the file already
-exists,
-.Fn shm_open
-returns an error. This may be used to
-implement a simple exclusive access locking mechanism.
-.Pp
-If successful,
-.Fn shm_open
-returns a non-negative integer, termed a file descriptor.
-It returns -1 and sets
-.Va errno
-on failure.
-The file pointer used to mark the current position within the
-memory object is set to the beginning of the object.
-.Pp
-When a new shared memory object is created it is given the
-owner and group corresponding to the effective user and
-group of the calling process. There is no visible entry in the
-file system for the created object in this implementation.
-.Pp
-When a shared memory object is created, it persists until it
-it unlinked and all other references are gone. Objects do
-not persist across a system reboot.
-.Pp
-The system imposes a limit on the number of file descriptors
-open simultaneously by one process.
-.Xr Getdtablesize 2
-returns the current system limit.
-.Sh ERRORS
-The named object is opened unless:
-.Bl -tag -width Er
-.It Bq Er EACCES
-The required permissions (for reading and/or writing)
-are denied for the given flags.
-.It Bq Er EACCES
-.Dv O_CREAT
-is specified, the object does not exist, and permission to
-create the object is denied.
-.It Bq Er EEXIST
-.Dv O_CREAT
-and
-.Dv O_EXCL
-were specified and the object exists.
-.It Bq Er EINTR
-The
-.Fn shm_open
-operation was interrupted by a signal.
-.It Bq Er EINVAL
-The
-.Fn shm_open
-operation is not supported.
-.It Bq Er EMFILE
-The process has already reached its limit for open file descriptors.
-.It Bq Er ENAMETOOLONG
-.Fa name
-exceeded the name size limit.
-This is currently
-.Dv PSHMNAMLEN
-characters (defined in
-.In sys/posix_shm.h ) ,
-but this may change in the future.
-.It Bq Er ENFILE
-The system file table is full.
-.It Bq Er ENOENT
-.Dv O_CREAT
-is not set and the named object does not exist.
-.It Bq Er ENOSPC
-.Dv O_CREAT
-is specified, the file does not exist, and there is insufficient
-space available to create the object.
-.El
-.Sh SEE ALSO
-.Xr chmod 2 ,
-.Xr close 2 ,
-.Xr getdtablesize 2 ,
-.Xr mmap 2 ,
-.Xr shm_unlink 2 ,
-.Xr umask 2
-.Sh HISTORY
-.Fn shm_open
-is specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995).
+++ /dev/null
-/*
- * Copyright (c) 1999, 2009 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <sys/cdefs.h>
-
-#ifdef __APPLE_PR3375657_HACK__
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <alloca.h>
-#include <string.h>
-
-__private_extern__ int _shm_match(const char *name);
-extern int __shm_open (const char *, int, int);
-
-int
-shm_open (const char *name, int flags, mode_t mode)
-{
- char *buffer;
-
- /*
- * To work-around applications that don't play
- * well in multiple GUI sessions, we append
- * shared memory names with the effective user ID.
- * It would be better to append the region name
- * with a session ID, but nothing like that
- * exists at this level of the system yet.
- */
-
- if (_shm_match(name) && (buffer = alloca(strlen(name) + 32)) != NULL) {
- sprintf(buffer, "%s\t%d", name, geteuid());
- name = buffer;
- }
-
- return __shm_open(name, flags, mode);
-}
-
-#endif /* __APPLE_PR3375657_HACK__ */
+++ /dev/null
-.\" $Darwin$
-.\"
-.\" Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
-.\"
-.\" @APPLE_LICENSE_HEADER_START@
-.\"
-.\" The contents of this file constitute Original Code as defined in and
-.\" are subject to the Apple Public Source License Version 1.1 (the
-.\" "License"). You may not use this file except in compliance with the
-.\" License. Please obtain a copy of the License at
-.\" http://www.apple.com/publicsource and read it before using this file.
-.\"
-.\" This Original Code and all software distributed under the License are
-.\" distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-.\" FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
-.\" License for the specific language governing rights and limitations
-.\" under the License.
-.\"
-.\" @APPLE_LICENSE_HEADER_END@
-.\"
-.Dd August 31, 2006
-.Dt SHM_UNLINK 2
-.Os Darwin
-.Sh NAME
-.Nm shm_unlink
-.Nd remove shared memory object
-.Sh SYNOPSIS
-.Fd #include <sys/mman.h>
-.Ft int
-.Fn shm_unlink "const char *name"
-.Sh DESCRIPTION
-The
-.Fn shm_unlink
-function disassociates the shared memory object specified by
-.Fa name
-from that name.
-The resources associated with the shared memory object remain intact
-until the last file descriptor reference is removed, e.g., by
-.Xr close 2
-or
-.Xr munmap 2 ,
-at which point the resources are reclaimed
-(if no references exist at the time of the call to
-.Fn shm_unlink ,
-the resources are reclaimed immediately).
-The name can only be reused
-when it is bound to a new shared memory object with a call to
-.Xr shm_open 2
-with the
-.Dv O_CREAT
-flag.
-.Sh RETURN VALUES
-Upon successful completion, a value of 0 is returned.
-Otherwise, a value of -1 is returned and
-.Va errno
-is set to indicate the error,
-and the named shared memory object will remain unchanged.
-.Sh ERRORS
-The
-.Fn shm_unlink
-succeeds unless:
-.Bl -tag -width Er
-.It Bq Er EACCES
-Permission is denied to be remove the object.
-.It Bq Er ENAMETOOLONG
-.Fa name
-exceeded the name size limit.
-This is currently
-.Dv PSHMNAMLEN
-characters (defined in
-.In sys/posix_shm.h ) ,
-but this may change in the future.
-.It Bq Er ENOENT
-The named object does not exist.
-.El
-.Sh SEE ALSO
-.Xr close 2 ,
-.Xr mmap 2 ,
-.Xr munmap 2 ,
-.Xr shm_open 2 ,
-.Xr shmat 2 ,
-.Xr shmctl 2
-.Sh HISTORY
-.Fn shm_open
-is specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995).
+++ /dev/null
-/*
- * Copyright (c) 1999, 2009 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <sys/cdefs.h>
-
-#ifdef __APPLE_PR3375657_HACK__
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <alloca.h>
-#include <string.h>
-
-__private_extern__ int _shm_match(const char *name);
-extern int __shm_unlink (const char *);
-
-int
-shm_unlink (const char *name)
-{
- char *buffer;
-
- /*
- * To work-around applications that don't play
- * well in multiple GUI sessions, we append
- * shared memory names with the effective user ID.
- * It would be better to append the region name
- * with a session ID, but nothing like that
- * exists at this level of the system yet.
- */
-
- if (_shm_match(name) && (buffer = alloca(strlen(name) + 32)) != NULL) {
- sprintf(buffer, "%s\t%d", name, geteuid());
- name = buffer;
- }
-
- return __shm_unlink(name);
-}
-
-#endif /* __APPLE_PR3375657_HACK__ */
+++ /dev/null
-/*
- * 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@
- */
-/* @(#)sigsuspend.c 1.0 9/22/95 (c) 1995 NeXT */
-
-#include <signal.h>
-#include <unistd.h>
-
-#ifdef VARIANT_CANCELABLE
-int __sigsuspend (const sigset_t);
-#else /* !VARIANT_CANCELABLE */
-int __sigsuspend_nocancel(const sigset_t);
-#endif /* VARIANT_CANCELABLE */
-
-int
-sigsuspend (const sigset_t *sigmask_p)
-{
- sigset_t mask;
-
- if (sigmask_p)
- mask = *sigmask_p;
- else
- sigemptyset(&mask);
-#ifdef VARIANT_CANCELABLE
- return __sigsuspend(mask);
-#else /* !VARIANT_CANCELABLE */
- return __sigsuspend_nocancel(mask);
-#endif /* VARIANT_CANCELABLE */
-}
-
--- /dev/null
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * File: slot_name.c
+ * Author: Avadis Tevanian, Jr.
+ *
+ * Copyright (C) 1987, Avadis Tevanian, Jr.
+ *
+ * Convert machine slot values to human readable strings.
+ *
+ * HISTORY
+ * 26-Jan-88 Mary Thompson (mrt) at Carnegie Mellon
+ * added case for CUP_SUBTYPE_RT_APC
+ *
+ * 28-Feb-87 Avadis Tevanian (avie) at Carnegie-Mellon University
+ * Created.
+ *
+ */
+
+#include <mach-o/arch.h>
+#include <stddef.h>
+
+/*
+ * Convert the specified cpu_type/cpu_subtype pair to their
+ * human readable form.
+ */
+void slot_name(cpu_type, cpu_subtype, cpu_name, cpu_subname)
+ cpu_type_t cpu_type;
+ cpu_subtype_t cpu_subtype;
+ char **cpu_name, **cpu_subname;
+{
+ register char *name = "Unknown CPU";
+ register char *subname = "";
+ const NXArchInfo *ai = NXGetArchInfoFromCpuType(cpu_type, cpu_subtype);
+ if (ai != NULL) {
+ name = (char *)ai->name;
+ subname = (char *)ai->description;
+ }
+ *cpu_name = name;
+ *cpu_subname = subname;
+}
+++ /dev/null
-/*
- * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * We need conformance on so that EOPNOTSUPP=102. But the routine symbol
- * will still be the legacy (undecorated) one.
- */
-#undef __DARWIN_UNIX03
-#define __DARWIN_UNIX03 1
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <errno.h>
-
-extern int __socketpair(int, int, int, int [2]);
-
-/*
- * socketpair stub, legacy version
- */
-int
-socketpair(int domain, int type, int protocol, int socket_vector[2])
-{
- int ret = __socketpair(domain, type, protocol, socket_vector);
-
- /* use ENOTSUP for legacy behavior */
- if (ret < 0 && errno == EOPNOTSUPP)
- errno = ENOTSUP;
- return ret;
-}
returns true if it took the lock, false if the lock was already held.
.Sh SEE ALSO
.Xr atomic 3 ,
-.Xr atomicqueue 3 ,
-.Xr barrier 3
\ No newline at end of file
+.Xr barrier 3
+/* $OpenBSD: stack_protector.c,v 1.10 2006/03/31 05:34:44 deraadt Exp $ */
+
/*
* Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.
* All rights reserved.
*
*/
-#if defined(LIBC_SCCS) && !defined(list)
-static char rcsid[] = "$OpenBSD: stack_protector.c,v 1.3 2002/12/10 08:53:42 etoh Exp $";
-#endif
-
#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <syslog.h>
-#include <sys/types.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <asl.h>
#include <unistd.h>
+#include <sys/types.h>
#include <fcntl.h>
+#include "CrashReporterClient.h"
+#include "libproc.h"
+#include "_simple.h"
-extern void __abort(void) __dead2;
-long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-void __guard_setup(void) __attribute__ ((visibility ("hidden")));
+#define GUARD_MAX 8
+long __stack_chk_guard[GUARD_MAX] = {0, 0, 0, 0, 0, 0, 0, 0};
+void __abort(void) __dead2;
+void __guard_setup(const char *apple[]) __attribute__ ((visibility ("hidden")));
void __stack_chk_fail(void);
+static void
+__guard_from_kernel(const char *str)
+{
+ unsigned long long val;
+ char tmp[20], *p;
+ int idx = 0;
+
+ /* Skip over the 'stack_guard=' key to the list of values */
+ str = strchr(str, '=');
+ if (str == NULL)
+ return;
+ str++;
+
+ while (str && idx < GUARD_MAX) {
+ /*
+ * Pull the next numeric string out of the list and convert it to
+ * a real number.
+ */
+ strlcpy(tmp, str, 20);
+ p = strchr(tmp, ',');
+ if (p)
+ *p = '\0';
+ val = strtoull(tmp, NULL, 0);
+ __stack_chk_guard[idx] = (long)(val & ((unsigned long) -1));
+ idx++;
+ if ((str = strchr(str, ',')) != NULL)
+ str++;
+ }
+}
+
void
-__guard_setup(void)
+__guard_setup(const char *apple[])
{
- int fd;
- if (__stack_chk_guard[0]!=0) return;
- fd = open ("/dev/urandom", 0);
- if (fd != -1) {
- ssize_t size = read (fd, (char*)&__stack_chk_guard,
- sizeof(__stack_chk_guard));
- close (fd) ;
- if (size == sizeof(__stack_chk_guard)
- && *__stack_chk_guard != 0) return;
- }
- /* If a random generator can't be used, the protector switches the guard
- to the "terminator canary" */
- ((char*)__stack_chk_guard)[0] = 0; ((char*)__stack_chk_guard)[1] = 0;
- ((char*)__stack_chk_guard)[2] = '\n'; ((char*)__stack_chk_guard)[3] = 255;
+ int fd;
+ size_t len;
+ const char **p;
+
+ if (__stack_chk_guard[0] != 0)
+ return;
+
+ for (p = apple; p && *p; p++) {
+ if (strstr(*p, "stack_guard") == *p) {
+ __guard_from_kernel(*p);
+ if (__stack_chk_guard[0] != 0)
+ return;
+ }
+ }
+
+ fd = open ("/dev/urandom", 0);
+ if (fd != -1) {
+ len = read (fd, (char*)&__stack_chk_guard, sizeof(__stack_chk_guard));
+ close(fd);
+ if (len == sizeof(__stack_chk_guard) &&
+ *__stack_chk_guard != 0)
+ return;
+ }
+
+ /* If If a random generator can't be used, the protector switches the guard
+ to the "terminator canary" */
+ ((unsigned char *)__stack_chk_guard)[0] = 0;
+ ((unsigned char *)__stack_chk_guard)[1] = 0;
+ ((unsigned char *)__stack_chk_guard)[2] = '\n';
+ ((unsigned char *)__stack_chk_guard)[3] = 255;
}
+#define STACKOVERFLOW "] stack overflow"
+
void
__stack_chk_fail()
{
- const char message[] = "[%d] stack overflow";
+ char n[16]; // bigger than will hold the digits in a pid_t
+ char *np;
+ int pid = getpid();
+ char message[sizeof(n) + sizeof(STACKOVERFLOW)] = "[";
+ char prog[2*MAXCOMLEN+1] = {0};
- /* this may fail on a chroot jail, though luck */
- syslog(LOG_CRIT, message, getpid());
+ proc_name(pid, prog, 2*MAXCOMLEN);
+ prog[2*MAXCOMLEN] = 0;
+ np = n + sizeof(n);
+ *--np = 0;
+ while(pid > 0) {
+ *--np = (pid % 10) + '0';
+ pid /= 10;
+ }
+ strlcat(message, np, sizeof(message));
+ strlcat(message, STACKOVERFLOW, sizeof(message));
+ /* This may fail on a chroot jail... */
+ _simple_asl_log_prog(ASL_LEVEL_CRIT, "user", message, prog);
- __abort();
+ CRSetCrashLogMessage(message);
+ __abort();
}
+++ /dev/null
-.\" Copyright (c) 1994
-.\" Jan-Simon Pendry
-.\" 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.
-.\"
-.\" @(#)undelete.2 8.4 (Berkeley) 10/18/94
-.\" $FreeBSD: src/lib/libc/sys/undelete.2,v 1.17 2006/01/22 19:49:37 truckman Exp $
-.\"
-.Dd January 22, 2006
-.Dt UNDELETE 2
-.Os
-.Sh NAME
-.Nm undelete
-.Nd attempt to recover a deleted file
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In unistd.h
-.Ft int
-.Fn undelete "const char *path"
-.Sh DESCRIPTION
-The
-.Fn undelete
-system call attempts to recover the deleted file named by
-.Fa path .
-Currently, this works only when the named object
-is a whiteout in a union file system.
-The system call removes the whiteout causing
-any objects in a lower layer of the
-union stack to become visible once more.
-.Pp
-Eventually, the
-.Fn undelete
-functionality may be expanded to other file systems able to recover
-deleted files such as the log-structured file system.
-.Sh RETURN VALUES
-.Rv -std undelete
-.Sh ERRORS
-The
-.Fn undelete
-succeeds unless:
-.Bl -tag -width Er
-.It Bq Er ENOTDIR
-A component of the path prefix is not a directory.
-.It Bq Er ENAMETOOLONG
-A component of a pathname exceeded 255 characters,
-or an entire path name exceeded 1023 characters.
-.It Bq Er EEXIST
-The path does not reference a whiteout.
-.It Bq Er ENOENT
-The named whiteout does not exist.
-.It Bq Er EACCES
-Search permission is denied for a component of the path prefix.
-.It Bq Er EACCES
-Write permission is denied on the directory containing the name
-to be undeleted.
-.It Bq Er ELOOP
-Too many symbolic links were encountered in translating the pathname.
-.It Bq Er EPERM
-The directory containing the name is marked sticky,
-and the containing directory is not owned by the effective user ID.
-.It Bq Er EINVAL
-The last component of the path is
-.Ql .. .
-.It Bq Er EIO
-An I/O error occurred while updating the directory entry.
-.It Bq Er EROFS
-The name resides on a read-only file system.
-.It Bq Er EFAULT
-The
-.Fa path
-argument
-points outside the process's allocated address space.
-.El
-.Sh SEE ALSO
-.Xr unlink 2 ,
-.Xr mount_unionfs 8
-.Sh HISTORY
-The
-.Fn undelete
-system call first appeared in
-.Bx 4.4 Lite .
+++ /dev/null
-/*
- * Copyright (c) 2009 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 <unistd.h>
-
-void __inc_remove_counter(void);
-int __unlink(const char *path);
-
-int
-unlink(const char *path)
-{
- int res = __unlink(path);
- if (res == 0) __inc_remove_counter();
- return res;
-}
.sinclude "${.CURDIR}/${MACHINE_ARCH}/threads/Makefile.inc"
-MISRCS += cprocs.c cthreads.c lu_utils.c mig_support.c
+MISRCS += cprocs.c cthreads.c mig_support.c
+
+DYLDSRCS += mig_support.c
{
int *ep = __error();
extern int __unix_conforming;
+ pthread_t self = NULL;
- if ((__unix_conforming) && (error == EINTR) && (__pthread_canceled(0) == 0))
+ if ((__unix_conforming) && ((error & 0xff) == EINTR) && (__pthread_canceled(0) == 0)) {
+ self = pthread_self();
+ if (self != NULL)
+ self->cancel_error = error;
pthread_exit(PTHREAD_CANCELED);
+ }
if (ep != &errno)
*ep = error;
extern void _malloc_fork_child();
extern void fork_mach_init();
extern void _cproc_fork_child(), _stack_fork_child();
-extern void _lu_fork_child(void);
extern void _asl_fork_child(void);
extern void _pthread_fork_child(pthread_t);
+extern void _pthread_fork_child_postinit();
extern void _notify_fork_child(void);
static pthread_t psaved_self = 0;
*/
{
pthread_t p = psaved_self;
- struct pthread_atfork_entry *e;
_pthread_set_self(p);
_spin_unlock(&psaved_self_global_lock);
_malloc_fork_child();
p->kernel_thread = mach_thread_self();
p->reply_port = mach_reply_port();
- p->mutexes = NULL;
p->__cleanup_stack = NULL;
p->death = MACH_PORT_NULL;
p->joiner = NULL;
p->detached |= _PTHREAD_CREATE_PARENT;
_spin_unlock(&p->lock);
- fork_mach_init();
_pthread_fork_child(p);
+}
- _cproc_fork_child();
-
- _lu_fork_child();
- _asl_fork_child();
- _notify_fork_child();
+void _cthread_fork_child_postinit()
+{
+ struct pthread_atfork_entry *e;
__is_threaded = 0;
+ _pthread_fork_child_postinit();
mig_init(1); /* enable multi-threaded mig interfaces */
pthread_workqueue_atfork_child();
if (e->child != NULL)
e->child();
}
- LOCK_INIT(pthread_atfork_lock);
-
+ LOCK_INIT(pthread_atfork_lock);
}
-
+++ /dev/null
-/*
- * Copyright (c) 2003 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@
- */
-/*
- * Port and memory management for doing lookups to the lookup server
- * Copyright (C) 1989 by NeXT, Inc.
- */
-/*
- * HISTORY
- * 27-Mar-90 Gregg Kellogg (gk) at NeXT
- * Changed to use bootstrap port instead of service port.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <mach/mach.h>
-#include <mach/error.h>
-#include <servers/bootstrap.h>
-
-mach_port_t _lu_port = MACH_PORT_NULL;
-mach_port_t _ds_port = MACH_PORT_NULL;
-mach_port_t _mbr_port = MACH_PORT_NULL;
-
-static name_t LOOKUP_NAME = "lookup daemon v2";
-
-#ifndef kDSStdMachDSLookupPortName
-#define kDSStdMachDSLookupPortName "com.apple.system.DirectoryService.libinfo_v1"
-#define kDSStdMachDSMembershipPortName "com.apple.system.DirectoryService.membership_v1"
-#endif
-
-mach_port_t
-_lookupd_port(mach_port_t port)
-{
- kern_return_t status;
-
- if (port != MACH_PORT_NULL)
- {
- status = bootstrap_register(bootstrap_port, LOOKUP_NAME, port);
- if (status != BOOTSTRAP_SUCCESS) abort();
-
- return port;
- }
- else if ((_lu_port == MACH_PORT_NULL) && (getpid() > 1))
- {
- status = bootstrap_look_up(bootstrap_port, LOOKUP_NAME, &_lu_port);
- if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _lu_port = MACH_PORT_NULL;
- }
-
- return _lu_port;
-}
-
-/* called as child starts up. mach ports aren't inherited: trash cache */
-void
-_lu_fork_child()
-{
- _lu_port = MACH_PORT_NULL;
- _ds_port = MACH_PORT_NULL;
- _mbr_port = MACH_PORT_NULL;
-}
-
-void
-_lu_setport(mach_port_t desired)
-{
- if (_lu_port != MACH_PORT_NULL) mach_port_deallocate(mach_task_self(), _lu_port);
- _lu_port = desired;
-}
-
-int
-_lu_running(void)
-{
- return ((_lu_port != MACH_PORT_NULL) || (_lookupd_port(MACH_PORT_NULL) != MACH_PORT_NULL));
-}
-
-int
-_ds_running(void)
-{
- kern_return_t status;
-
- if (_ds_port != MACH_PORT_NULL) return 1;
-
- status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port);
- if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL;
-
- status = bootstrap_look_up(bootstrap_port, kDSStdMachDSMembershipPortName, &_mbr_port);
- if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _mbr_port = MACH_PORT_NULL;
-
- return (_ds_port != MACH_PORT_NULL);
-}
* can result in a call to malloc() which eventually reenters
* mig_get_reply_port() and deadlocks.
*/
-mach_port_t
-mig_get_reply_port()
+mach_port_t _mig_get_reply_port()
{
- register cproc_t self;
- pthread_t pself;
-#ifdef CTHREADS_DEBUG
- int d = cthread_debug;
-#endif /* CTHREADS_DEBUG */
+ pthread_t pself;
-#ifdef CTHREADS_DEBUG
- cthread_debug = FALSE;
-#endif /* CTHREADS_DEBUG */
- pself = pthread_self();
- if ((pself != (pthread_t)NULL) && (pself->sig == _PTHREAD_SIG)) {
- if (pself->reply_port == MACH_PORT_NULL) {
- pself->reply_port = mach_reply_port();
- }
- return pself->reply_port;
- }
- self = cproc_self();
- if (self == NO_CPROC) {
-#ifdef CTHREADS_DEBUG
- cthread_debug = d;
-#endif /* CTHREADS_DEBUG */
- return(_task_reply_port);
- }
- if (self->reply_port == MACH_PORT_NULL) {
- self->reply_port = mach_reply_port();
- }
-#ifdef CTHREADS_DEBUG
- cthread_debug = d;
-#endif /* CTHREADS_DEBUG */
- return self->reply_port;
-}
-
-/*
- * Called by mig interface code after a timeout on the reply port.
- * May also be called by user. The new mig calls with port passed in
- * We are ignoring this , so is osfmk cthreads code
- */
-void
-mig_dealloc_reply_port(mach_port_t migport)
-{
- register cproc_t self;
- pthread_t pself;
- register mach_port_t port;
-#ifdef CTHREADS_DEBUG
- int d = cthread_debug;
-#endif /* CTHREADS_DEBUG */
-
-#ifdef CTHREADS_DEBUG
- cthread_debug = FALSE;
-#endif /* CTHREADS_DEBUG */
- pself = pthread_self();
- if ((pself != (pthread_t)NULL) && (pself->sig == _PTHREAD_SIG)) {
- port = pself->reply_port;
- if (port != MACH_PORT_NULL && port != _task_reply_port) {
- LOCK(reply_port_lock);
- pself->reply_port = _task_reply_port;
- (void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
- pself->reply_port = MACH_PORT_NULL;
- UNLOCK(reply_port_lock);
- }
- return;
- }
- self = cproc_self();
- if (self == NO_CPROC) {
-#ifdef CTHREADS_DEBUG
- cthread_debug = d;
-#endif /* CTHREADS_DEBUG */
- return;
- }
- ASSERT(self != NO_CPROC);
- port = self->reply_port;
- if (port != MACH_PORT_NULL && port != _task_reply_port) {
- LOCK(reply_port_lock);
- self->reply_port = _task_reply_port;
- (void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
- self->reply_port = MACH_PORT_NULL;
- UNLOCK(reply_port_lock);
- }
-#ifdef CTHREADS_DEBUG
- cthread_debug = d;
-#endif /* CTHREADS_DEBUG */
+ pself = pthread_self();
+ if ((pself != (pthread_t)NULL) && (pself->sig == _PTHREAD_SIG)) {
+ return pself->reply_port;
+ }
+ return MACH_PORT_NULL;
}
-/*************************************************************
- * Called by mig interfaces after each RPC.
- * Could be called by user.
- ***********************************************************/
-
-void
-mig_put_reply_port(
- mach_port_t reply_port)
+void _mig_set_reply_port(mach_port_t port)
{
+ pthread_t pself;
+ pself = pthread_self();
+
+ if ((pself != (pthread_t)NULL) && (pself->sig == _PTHREAD_SIG)) {
+ pself->reply_port = port;
+ }
}
* SUCH DAMAGE.
*/
-
#include <sys/types.h>
#include <utmp.h>
#include <utmpx.h>
/*
- * Copyright (c) 1999, 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999, 2005, 2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
strncpy(utx.ut_line, line, sizeof(utx.ut_line));
utx.ut_type = UTMPX_AUTOFILL_MASK | UTMPX_DEAD_IF_CORRESPONDING_MASK | DEAD_PROCESS;
(void)gettimeofday(&utx.ut_tv, NULL);
- UTMPX_LOCK;
- _setutxent();
- ux = _pututxline(&utx);
- _endutxent();
+ UTMPX_LOCK(&__utx__);
+ __setutxent(&__utx__);
+ ux = __pututxline(&__utx__, &utx);
+ __endutxent(&__utx__);
if (!ux) {
- UTMPX_UNLOCK;
+ UTMPX_UNLOCK(&__utx__);
return 0;
}
#ifdef UTMP_COMPAT
- if (utfile_system) { /* only if we are using _PATH_UTMPX */
+ if (__utx__.utfile_system) { /* only if we are using _PATH_UTMPX */
which = _utmp_compat(ux, &u);
if (which & UTMP_COMPAT_UTMP0)
_write_utmp(&u, 0);
_write_utmp(&u, 1);
}
#endif /* UTMP_COMPAT */
- UTMPX_UNLOCK;
+ UTMPX_UNLOCK(&__utx__);
return 1;
}
#include <paths.h>
#include <stdio.h>
#include <string.h>
+#include <pthread.h>
#include "util.h"
+/*
+ * opendev(3) is an inherently non-thread-safe API, since
+ * it returns a buffer to global storage. However we can
+ * at least make sure the storage allocation is thread safe
+ * and does not leak memory in case of simultaneous
+ * initialization
+ */
+static pthread_once_t opendev_namebuf_once = PTHREAD_ONCE_INIT;
+static char *namebuf = NULL;
+
+static void opendev_namebuf_init(void);
+
int
opendev(path, oflags, dflags, realpath)
char *path;
{
int fd;
char *slash, *prefix;
- static char namebuf[PATH_MAX];
/* Initial state */
if (realpath)
fd = -1;
errno = ENOENT;
+ if (pthread_once(&opendev_namebuf_once,
+ opendev_namebuf_init)
+ || !namebuf) {
+ errno = ENOMEM;
+ return -1;
+ }
+
if (dflags & OPENDEV_BLCK)
prefix = ""; /* block device */
else
if ((slash = strchr(path, '/')))
fd = open(path, oflags);
else if (dflags & OPENDEV_PART) {
- if (snprintf(namebuf, sizeof(namebuf), "%s%s%s",
- _PATH_DEV, prefix, path) < sizeof(namebuf)) {
+ if (snprintf(namebuf, PATH_MAX, "%s%s%s",
+ _PATH_DEV, prefix, path) < PATH_MAX) {
char *slice;
while ((slice = strrchr(namebuf, 's')) &&
isdigit(*(slice-1))) *slice = '\0';
errno = ENAMETOOLONG;
}
if (!slash && fd == -1 && errno == ENOENT) {
- if (snprintf(namebuf, sizeof(namebuf), "%s%s%s",
- _PATH_DEV, prefix, path) < sizeof(namebuf)) {
+ if (snprintf(namebuf, PATH_MAX, "%s%s%s",
+ _PATH_DEV, prefix, path) < PATH_MAX) {
fd = open(namebuf, oflags);
if (realpath)
*realpath = namebuf;
}
return (fd);
}
+
+static void opendev_namebuf_init(void)
+{
+ namebuf = malloc(PATH_MAX);
+}
#include <util.h>
#include <syslog.h>
-static char ptytemplate[] = "/dev/ptyXX";
-
int openpty(amaster, aslave, name, termp, winp)
int *amaster, *aslave;
char *name;
+++ /dev/null
-./unparse.c
\ No newline at end of file
--- /dev/null
+/*
+ * unparse.c -- convert a UUID to string
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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 ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+
+#include "uuidP.h"
+
+static const char *fmt_lower =
+ "0123456789abcdef";
+
+static const char *fmt_upper =
+ "0123456789ABCDEF";
+
+#ifdef UUID_UNPARSE_DEFAULT_UPPER
+#define FMT_DEFAULT fmt_upper
+#else
+#define FMT_DEFAULT fmt_lower
+#endif
+
+static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
+{
+ const uint8_t *uuid_array = (const uint8_t *)uu;
+ int uuid_index;
+
+ for ( uuid_index = 0; uuid_index < sizeof(uuid_t); ++uuid_index ) {
+ // insert '-' after the 4th, 6th, 8th, and 10th uuid byte
+ switch (uuid_index) {
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ *out++ = '-';
+ break;
+ }
+ // insert uuid byte as two hex characters
+ *out++ = fmt[*uuid_array >> 4];
+ *out++ = fmt[*uuid_array++ & 0xF];
+ }
+ *out = 0;
+}
+
+void uuid_unparse_lower(const uuid_t uu, char *out)
+{
+ uuid_unparse_x(uu, out, fmt_lower);
+}
+
+void uuid_unparse_upper(const uuid_t uu, char *out)
+{
+ uuid_unparse_x(uu, out, fmt_upper);
+}
+
+void uuid_unparse(const uuid_t uu, char *out)
+{
+ uuid_unparse_x(uu, out, FMT_DEFAULT);
+}
.sp
\fIvoid\fP
.br
-\fBuuid_unparse\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
+\fBuuid_unparse\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
.sp
\fIvoid\fP
.br
-\fBuuid_unparse_lower\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
+\fBuuid_unparse_lower\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
.sp
\fIvoid\fP
.br
-\fBuuid_unparse_upper\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
+\fBuuid_unparse_upper\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
.sp
.fi
.SH DESCRIPTION
.B uuid_unparse
function converts the supplied UUID
.I uu
-from the binary representation into a 36\-byte string (plus tailing '\\0')
+from the binary representation into a uuid_string_t (37\-byte string including tailing '\\0')
of the form 1b4e28ba\-2fa1\-11d2\-883f\-b9a761bde3fb and stores this value in the
character string pointed to by
.IR out .
.sp
\fIvoid\fP
.br
-\fBuuid_unparse\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
+\fBuuid_unparse\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
.sp
\fIvoid\fP
.br
-\fBuuid_unparse_lower\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
+\fBuuid_unparse_lower\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
.sp
\fIvoid\fP
.br
-\fBuuid_unparse_upper\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
+\fBuuid_unparse_upper\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
.sp
.fi
.SH DESCRIPTION
.B uuid_unparse
function converts the supplied UUID
.I uu
-from the binary representation into a 36\-byte string (plus tailing '\\0')
+from the binary representation into a uuid_string_t (37\-byte string including tailing '\\0')
of the form 1b4e28ba\-2fa1\-11d2\-883f\-b9a761bde3fb and stores this value in the
character string pointed to by
.IR out .
--- /dev/null
+--- unparse.c.orig 2010-06-27 12:49:24.000000000 -0700
++++ unparse.c 2010-06-27 13:06:53.000000000 -0700
+@@ -37,10 +37,10 @@
+ #include "uuidP.h"
+
+ static const char *fmt_lower =
+- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
++ "0123456789abcdef";
+
+ static const char *fmt_upper =
+- "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X";
++ "0123456789ABCDEF";
+
+ #ifdef UUID_UNPARSE_DEFAULT_UPPER
+ #define FMT_DEFAULT fmt_upper
+@@ -50,14 +50,24 @@ static const char *fmt_upper =
+
+ static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt)
+ {
+- struct uuid uuid;
+-
+- uuid_unpack(uu, &uuid);
+- sprintf(out, fmt,
+- uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+- uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
+- uuid.node[0], uuid.node[1], uuid.node[2],
+- uuid.node[3], uuid.node[4], uuid.node[5]);
++ const uint8_t *uuid_array = (const uint8_t *)uu;
++ int uuid_index;
++
++ for ( uuid_index = 0; uuid_index < sizeof(uuid_t); ++uuid_index ) {
++ // insert '-' after the 4th, 6th, 8th, and 10th uuid byte
++ switch (uuid_index) {
++ case 4:
++ case 6:
++ case 8:
++ case 10:
++ *out++ = '-';
++ break;
++ }
++ // insert uuid byte as two hex characters
++ *out++ = fmt[*uuid_array >> 4];
++ *out++ = fmt[*uuid_array++ & 0xF];
++ }
++ *out = 0;
+ }
+
+ void uuid_unparse_lower(const uuid_t uu, char *out)
---- uuid_unparse.3.in.orig 2008-09-25 10:43:40.000000000 -0700
-+++ uuid_unparse.3.in 2008-09-25 10:51:45.000000000 -0700
-@@ -36,9 +36,18 @@
+--- uuid_unparse.3.in.orig 2010-04-28 23:38:50.000000000 -0700
++++ uuid_unparse.3.in 2010-04-28 23:53:36.000000000 -0700
+@@ -36,17 +36,26 @@ uuid_unparse \- convert an UUID from bin
.nf
.B #include <uuid/uuid.h>
.sp
-.BI "void uuid_unparse_lower(uuid_t " uu ", char *" out );
+\fIvoid\fP
+.br
-+\fBuuid_unparse\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
++\fBuuid_unparse\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
+.sp
+\fIvoid\fP
+.br
-+\fBuuid_unparse_lower\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
++\fBuuid_unparse_lower\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
+.sp
+\fIvoid\fP
+.br
-+\fBuuid_unparse_upper\fP(\fIuuid_t uu\fP, \fIchar * out\fP);
++\fBuuid_unparse_upper\fP(\fIuuid_t uu\fP, \fIuuid_string_t out\fP);
+.sp
.fi
.SH DESCRIPTION
The
-@@ -46,7 +55,7 @@
+ .B uuid_unparse
function converts the supplied UUID
.I uu
- from the binary representation into a 36\-byte string (plus tailing '\\0')
+-from the binary representation into a 36\-byte string (plus tailing '\\0')
-of the form 1b4e28ba\-2fa1\-11d2\-883f\-b9a76 and stores this value in the
++from the binary representation into a uuid_string_t (37\-byte string including tailing '\\0')
+of the form 1b4e28ba\-2fa1\-11d2\-883f\-b9a761bde3fb and stores this value in the
character string pointed to by
.IR out .
mcount.s \
setcontext.c \
setjmperr.c \
- swapcontext.c
+ swapcontext.c \
+ cpu_number.s
.for _src in makecontext.c setcontext.c swapcontext.c
CFLAGS-${_src} += -fomit-frame-pointer
--- /dev/null
+/*
+ * Copyright (c) 2008 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+/*
+ * This routine provides fast access to the logical cpu number
+ * of the calling processor assuming no pre-emption occurs. This number
+ * is encoded in the bottom 12-bits of the limit field of the IDTR (the
+ * Interrupt Descriptor Table Register). The SIDT instruction is used in
+ * userspace to read this register and thus to gain access to the cpu number.
+ * The IDTR is loaded by the kernel for each processor at startup - see
+ * osfmk/i386/mp_desc.c.
+ */
+
+/* return logical cpu number in %rax */
+
+ .private_extern _cpu_number
+_cpu_number:
+ push %rbp
+ mov %rsp,%rbp
+ sub $16,%rsp // space to read IDTR
+
+ sidt (%rsp) // store limit:base on stack
+ movw (%rsp), %ax // get limit
+ and $0xfff, %rax // mask off lower 12 bits to return
+
+ mov %rbp,%rsp
+ pop %rbp
+ ret
uctx->uc_mcontext = mctx;
#ifdef __DYNAMIC__
- uctx->uc_link = (ucontext_t*)__in_sigtramp; /* non-zero if in signal handler */
+ uctx->uc_link = (ucontext_t*)(uintptr_t)__in_sigtramp; /* non-zero if in signal handler */
#else /* !__DYNAMIC__ */
uctx->uc_link = 0;
#endif /* __DYNAMIC__ */
/* void sys_icache_invalidate(addr_t start, int length) */
-.globl _sys_icache_invalidate
+ .globl _sys_icache_invalidate
_sys_icache_invalidate:
- movq $(_COMM_PAGE_FLUSH_ICACHE), %rax
- jmp *%rax
+ // This is a NOP on intel processors, since the intent of the API
+ // is to make data executable, and Intel L1Is are coherent with L1D.
+ ret
/* void sys_dcache_flush(addr_t start, int length) */
-.globl _sys_dcache_flush
+ .globl _sys_dcache_flush
_sys_dcache_flush:
- movq $(_COMM_PAGE_FLUSH_DCACHE), %rax
- jmp *%rax
+ testq %rsi,%rsi // length 0?
+ jz 2f // yes
+ mfence // ensure previous stores make it to memory
+ clflush -1(%rdi,%rsi) // make sure last line is flushed
+1:
+ clflush (%rdi) // flush a line
+ addq $64,%rdi
+ subq $64,%rsi
+ ja 1b
+ mfence // make sure memory is updated before we return
+2:
+ ret
#define _XOPEN_SOURCE 600L
#include <ucontext.h>
-#undef _ANSI_SOURCE
+#undef _XOPEN_SOURCE
+#undef _POSIX_C_SOURCE /* sigsetmask() */
#include <signal.h>
extern int _setcontext(const mcontext_t);
pthread_self.s \
pthread_getspecific.s \
start_wqthread.s \
- thread_start.s
+ thread_start.s \
+ preempt.s
+DYLDSRCS += \
+ pthread_set_self.s \
+ pthread_self.s \
+ pthread_getspecific.s \
+ preempt.s
--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <mach/i386/syscall_sw.h>
+
+/* Subroutine to make a preempt syscall. Called when we notice %ebx is
+ * nonzero after returning from a PFZ subroutine. Not in PFZ.
+ *
+ * All registers preserved (but does clear the %ebx preemption flag).
+ */
+ .align 2
+ .private_extern _preempt
+_preempt:
+ pushq %rax
+ pushq %rcx
+ pushq %r11
+ movl $(SYSCALL_CONSTRUCT_MACH(58)),%eax /* 58 = pfz_exit */
+ xorl %ebx,%ebx
+ syscall
+ popq %r11
+ popq %rcx
+ popq %rax
+ ret
+
+/* Subroutine to back off if we cannot get the spinlock. Called
+ * after a few attempts inline in the PFZ subroutines. This code is
+ * not in the PFZ.
+ * %rdi = ptr to queue head structure
+ * %ebx = preemption flag (nonzero if preemption pending)
+ * Uses: %rax.
+ */
+ .align 2
+ .private_extern _backoff
+_backoff:
+ testl %ebx,%ebx // does kernel want to preempt us?
+ jz 1f // no
+ call _preempt
+1:
+ pause // SMT-friendly backoff
+ cmpl $0,16(%rdi) // sniff the lockword
+ jnz 1b // loop if still taken
+ ret // lockword is free, so reenter PFZ
.align 2, 0x90
.globl _pthread_getspecific
_pthread_getspecific:
- movq %gs:_PTHREAD_TSD_OFFSET(,%rdi,8),%rax
+ movq %gs:(,%rdi,8),%rax
ret
#include <machine/cpu_capabilities.h>
+#define PTHRW_LVAL 0
+#define PTHRW_UVAL 4
.text
.align 2
.globl __commpage_pthread_mutex_lock
__commpage_pthread_mutex_lock:
- movq $(_COMM_PAGE_MUTEX_LOCK), %rax
- jmp *%rax
-
+ pushq %rbp // set up frame for backtrace
+ movq %rsp,%rbp
+ pushq %rbx
+ xorl %ebx,%ebx // clear "preemption pending" flag
+ movl $(_COMM_PAGE_SPIN_COUNT), %eax
+1:
+ testl PTHRW_LVAL(%rdi),%ecx // is mutex available?
+ jz 2f // yes, it is available
+ pause
+ decl %eax // decrement max spin count
+ jnz 1b // keep spinning
+2:
+ movq $(_COMM_PAGE_PFZ_MUTEX_LOCK), %rcx
+ call *%rcx
+ testl %ebx,%ebx // pending preemption?
+ jz 1f // no
+ call _preempt
+1:
+ popq %rbx
+ popq %rbp
+ ret
.align 2, 0x90
.globl _pthread_self
_pthread_self:
- movq %gs:_PTHREAD_TSD_OFFSET,%rax
+ movq %gs:0,%rax
ret
#
.PATH: ${.CURDIR}/x86_64/string
-MDSRCS += bcopy.s \
- bzero.s \
- memcpy.s \
- memmove.s \
+MDSRCS += \
+ bcopy.c \
+ bcopy_sse3x.s \
+ bcopy_sse42.s \
+ bzero.c \
+ bzero_sse2.s \
+ bzero_sse42.s \
+ __bzero.s \
+ longcopy_sse3x.s \
+ memcpy.c \
+ memmove.c \
strlcat.s \
strlcpy.s \
strlen.s \
ffs.s
SUPPRESSSRCS += bcmp.c
+
+DYLDSRCS += \
+ __bzero.s \
+ bcopy_sse3x.s \
+ bzero_sse2.s \
+ ffs.s \
+ longcopy_sse3x.s \
+ strcmp.s \
+ strlen.s
--- /dev/null
+ .globl ___bzero
+___bzero:
+ jmp _bzero
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bcopy, sse42)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bcopy, sse3x)
+
+static const platfunc_descriptor *bcopy_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(bcopy, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(bcopy, sse3x),
+ 0
+};
+
+void *bcopy_chooser() __asm__("_bcopy");
+void *bcopy_chooser() {
+ __asm__(".desc _bcopy, 0x100");
+ return find_platform_function((const platfunc_descriptor **) bcopy_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 1999-2003 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@
- */
-
-/*
- * Call the comm page routines
- */
-
-#define __APPLE_API_PRIVATE
-#include <machine/cpu_capabilities.h>
-
-#include <architecture/i386/asm_help.h>
-
- TEXT
- ALIGN
-
-#if defined(MEMCOPY)
-LEAF(_memcpy,0)
- movq $(_COMM_PAGE_MEMCPY), %rax
- jmp *%rax
-#elif defined(MEMMOVE)
-LEAF(_memmove,0)
- movq $(_COMM_PAGE_MEMMOVE), %rax
- jmp *%rax
-#else
-LEAF(_bcopy,0)
- movq $(_COMM_PAGE_BCOPY), %rax
- jmp *%rax
-#endif
--- /dev/null
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * The bcopy/memcpy loops, tuned for 64-bit Pentium-M class processors with
+ * Supplemental SSE3 and 64-byte cache lines. This is the 64-bit version.
+ *
+ * The following #defines are tightly coupled to the u-architecture:
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+#define kVeryLong (500*1024) // large enough for non-temporal stores (>=8192 and <2GB)
+#define kFastUCode ((16*1024)-15) // cutoff for microcode fastpath for "rep/movsl"
+
+// void bcopy(const void *src, void *dst, size_t len);
+
+PLATFUNC_FUNCTION_START_GENERIC(bcopy, sse3x, 64, 5)
+LZero:
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ movq %rsi,%rax // copy dest ptr
+ movq %rdi,%rsi // xchange source and dest ptrs
+ movq %rax,%rdi
+ subq %rsi,%rax // (dest - source)
+ cmpq %rdx,%rax // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpq $(kShort),%rdx // long enough to bother with SSE?
+ jbe LShort // no
+ jmp LNotShort
+
+//
+// void *memcpy(void *dst, const void *src, size_t len);
+// void *memmove(void *dst, const void *src, size_t len);
+//
+
+PLATFUNC_FUNCTION_START_GENERIC(memcpy, sse3x, 64, 0) // void *memcpy(void *dst, const void *src, size_t len)
+PLATFUNC_FUNCTION_START_GENERIC(memmove, sse3x, 64, 0) // void *memmove(void *dst, const void *src, size_t len)
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ movq %rdi,%r11 // save return value here
+ movq %rdi,%rax
+ subq %rsi,%rax // (dest - source)
+ cmpq %rdx,%rax // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpq $(kShort),%rdx // long enough to bother with SSE?
+ ja LNotShort // yes
+
+// Handle short forward copies. As the most common case, this is the fall-through path.
+// rdx = length (<= kShort)
+// rsi = source ptr
+// rdi = dest ptr
+
+LShort:
+ movl %edx,%ecx // copy length using 32-bit operation
+ shrl $2,%ecx // get #doublewords
+ jz LLeftovers
+2: // loop copying doublewords
+ movl (%rsi),%eax
+ addq $4,%rsi
+ movl %eax,(%rdi)
+ addq $4,%rdi
+ decl %ecx
+ jnz 2b
+LLeftovers: // handle leftover bytes (0..3) in last word
+ andl $3,%edx // any leftover bytes?
+ jz 5f
+4: // loop copying bytes
+ movb (%rsi),%al
+ incq %rsi
+ movb %al,(%rdi)
+ incq %rdi
+ decl %edx
+ jnz 4b
+5:
+ movq %r11,%rax // get return value (dst ptr) for memcpy/memmove
+ popq %rbp
+ ret
+
+
+LReverseIsland: // keep the "jb" above a short branch...
+ jmp LReverse // ...because reverse moves are uncommon
+
+
+// Handle forward moves that are long enough to justify use of SSE.
+// First, 16-byte align the destination.
+// rdx = length (> kShort)
+// rsi = source ptr
+// rdi = dest ptr
+
+LNotShort:
+ cmpq $(kVeryLong),%rdx // long enough to justify heavyweight loops?
+ jae LVeryLong // use very-long-operand path
+ movl %edi,%ecx // copy low half of destination ptr
+ negl %ecx
+ andl $15,%ecx // get #bytes to align destination
+ jz LDestAligned // already aligned
+ subl %ecx,%edx // decrement length
+ rep // align destination
+ movsb
+
+
+// Destination is now aligned. Dispatch to one of sixteen loops over 64-byte chunks,
+// based on the alignment of the source. All vector loads and stores are aligned.
+// Even though this means we have to shift and repack vectors, doing so is much faster
+// than unaligned loads. Since kShort>=80 and we've moved at most 15 bytes already,
+// there is at least one chunk. When we enter the copy loops, the following registers
+// are set up:
+// rdx = residual length (0..63)
+// rcx = -(length to move), a multiple of 64 less than 2GB
+// rsi = ptr to 1st source byte not to move (unaligned)
+// rdi = ptr to 1st dest byte not to move (aligned)
+
+LDestAligned:
+ movq %rdx,%rcx // copy length
+ movl %esi,%eax // copy low half of source address
+ andl $63,%edx // get remaining bytes for LShort
+ andl $15,%eax // mask to low 4 bits of source address
+ andq $-64,%rcx // get number of bytes we will copy in inner loop
+ leaq LTable(%rip), %r8
+ addq %rcx,%rsi // point to 1st byte not copied
+ addq %rcx,%rdi
+ movl (%r8,%rax,4),%eax // get offset of routine
+ negq %rcx // now generate offset to 1st byte to be copied
+ addq %r8,%rax // generate address of copy loop
+ jmp *%rax // enter copy loop, selected by source alignment
+
+ .align 2
+LTable: // table of copy loop addresses
+// force generation of assembly-time constants. Otherwise assembler
+// creates subtractor relocations relative to first external symbol,
+// and this file has none
+ .set LMod0Offset, LMod0 - LTable
+ .set LMod1Offset, LMod1 - LTable
+ .set LMod2Offset, LMod2 - LTable
+ .set LMod3Offset, LMod3 - LTable
+ .set LMod4Offset, LMod4 - LTable
+ .set LMod5Offset, LMod5 - LTable
+ .set LMod6Offset, LMod6 - LTable
+ .set LMod7Offset, LMod7 - LTable
+ .set LMod8Offset, LMod8 - LTable
+ .set LMod9Offset, LMod9 - LTable
+ .set LMod10Offset, LMod10 - LTable
+ .set LMod11Offset, LMod11 - LTable
+ .set LMod12Offset, LMod12 - LTable
+ .set LMod13Offset, LMod13 - LTable
+ .set LMod14Offset, LMod14 - LTable
+ .set LMod15Offset, LMod15 - LTable
+ .long LMod0Offset
+ .long LMod1Offset
+ .long LMod2Offset
+ .long LMod3Offset
+ .long LMod4Offset
+ .long LMod5Offset
+ .long LMod6Offset
+ .long LMod7Offset
+ .long LMod8Offset
+ .long LMod9Offset
+ .long LMod10Offset
+ .long LMod11Offset
+ .long LMod12Offset
+ .long LMod13Offset
+ .long LMod14Offset
+ .long LMod15Offset
+
+
+// Very long forward moves. These are at least several pages. They are special cased
+// and aggressively optimized, not so much because they are common or useful, but
+// because they are subject to benchmark. There isn't enough room for them in the
+// area reserved on the platfunc for bcopy, so we put them elsewhere. We call
+// the longcopy routine using the normal ABI:
+// rdi = dest
+// rsi = source
+// rdx = length (>= kVeryLong bytes)
+
+LVeryLong:
+ pushq %r11 // save return value
+ call _longcopy // call very long operand routine
+ popq %rax // pop return value
+ popq %rbp
+ ret
+
+
+// On Pentium-M, the microcode for "rep/movsl" is faster than SSE for 16-byte
+// aligned operands from about 32KB up to kVeryLong for the hot cache case, and from
+// about 256 bytes up to kVeryLong for cold caches. This is because the microcode
+// avoids having to read destination cache lines that will be completely overwritten.
+// The cutoff we use (ie, kFastUCode) must somehow balance the two cases, since
+// we do not know if the destination is in cache or not.
+
+Lfastpath:
+ addq %rcx,%rsi // restore ptrs to 1st byte of source and dest
+ addq %rcx,%rdi
+ negl %ecx // make length positive (known to be < 2GB)
+ orl %edx,%ecx // restore total #bytes remaining to move
+ cld // we'll move forward
+ shrl $2,%ecx // compute #words to move
+ rep // the u-code will optimize this
+ movsl
+ jmp LLeftovers // handle 0..3 leftover bytes
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0000
+
+LMod0:
+ cmpl $(-kFastUCode),%ecx // %rcx == -length, where (length < kVeryLong)
+ jle Lfastpath // long enough for fastpath in microcode
+ jmp 1f
+ .align 4,0x90 // 16-byte align inner loops
+1: // loop over 64-byte chunks
+ movdqa (%rsi,%rcx),%xmm0
+ movdqa 16(%rsi,%rcx),%xmm1
+ movdqa 32(%rsi,%rcx),%xmm2
+ movdqa 48(%rsi,%rcx),%xmm3
+
+ movdqa %xmm0,(%rdi,%rcx)
+ movdqa %xmm1,16(%rdi,%rcx)
+ movdqa %xmm2,32(%rdi,%rcx)
+ movdqa %xmm3,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0001
+
+LMod1:
+ movdqa -1(%rsi,%rcx),%xmm0 // prime the loop by loading 1st quadword
+1: // loop over 64-byte chunks
+ movdqa 15(%rsi,%rcx),%xmm1
+ movdqa 31(%rsi,%rcx),%xmm2
+ movdqa 47(%rsi,%rcx),%xmm3
+ movdqa 63(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $1,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $1,%xmm2,%xmm3
+ palignr $1,%xmm1,%xmm2
+ palignr $1,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0010
+
+LMod2:
+ movdqa -2(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 14(%rsi,%rcx),%xmm1
+ movdqa 30(%rsi,%rcx),%xmm2
+ movdqa 46(%rsi,%rcx),%xmm3
+ movdqa 62(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $2,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $2,%xmm2,%xmm3
+ palignr $2,%xmm1,%xmm2
+ palignr $2,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0011
+
+LMod3:
+ movdqa -3(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 13(%rsi,%rcx),%xmm1
+ movdqa 29(%rsi,%rcx),%xmm2
+ movdqa 45(%rsi,%rcx),%xmm3
+ movdqa 61(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $3,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $3,%xmm2,%xmm3
+ palignr $3,%xmm1,%xmm2
+ palignr $3,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0100
+// We use the float single data type in order to use "movss" to merge vectors.
+
+LMod4:
+ movaps -4(%rsi,%rcx),%xmm0 // 4-byte aligned: prime the loop
+ jmp 1f
+ .align 4,0x90
+1: // loop over 64-byte chunks
+ movaps 12(%rsi,%rcx),%xmm1
+ movaps 28(%rsi,%rcx),%xmm2
+ movss %xmm1,%xmm0 // copy low 4 bytes of source into destination
+ pshufd $(0x39),%xmm0,%xmm0 // rotate right 4 bytes (mask -- 00 11 10 01)
+ movaps 44(%rsi,%rcx),%xmm3
+ movss %xmm2,%xmm1
+ pshufd $(0x39),%xmm1,%xmm1
+ movaps 60(%rsi,%rcx),%xmm4
+ movss %xmm3,%xmm2
+ pshufd $(0x39),%xmm2,%xmm2
+
+ movaps %xmm0,(%rdi,%rcx)
+ movss %xmm4,%xmm3
+ pshufd $(0x39),%xmm3,%xmm3
+ movaps %xmm1,16(%rdi,%rcx)
+ movaps %xmm2,32(%rdi,%rcx)
+ movaps %xmm4,%xmm0
+ movaps %xmm3,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0101
+
+LMod5:
+ movdqa -5(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 11(%rsi,%rcx),%xmm1
+ movdqa 27(%rsi,%rcx),%xmm2
+ movdqa 43(%rsi,%rcx),%xmm3
+ movdqa 59(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $5,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $5,%xmm2,%xmm3
+ palignr $5,%xmm1,%xmm2
+ palignr $5,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0110
+
+LMod6:
+ movdqa -6(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 10(%rsi,%rcx),%xmm1
+ movdqa 26(%rsi,%rcx),%xmm2
+ movdqa 42(%rsi,%rcx),%xmm3
+ movdqa 58(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $6,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $6,%xmm2,%xmm3
+ palignr $6,%xmm1,%xmm2
+ palignr $6,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 0111
+
+LMod7:
+ movdqa -7(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 9(%rsi,%rcx),%xmm1
+ movdqa 25(%rsi,%rcx),%xmm2
+ movdqa 41(%rsi,%rcx),%xmm3
+ movdqa 57(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $7,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $7,%xmm2,%xmm3
+ palignr $7,%xmm1,%xmm2
+ palignr $7,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1000
+// We use the float double data type in order to use "shufpd" to shift by 8 bytes.
+
+LMod8:
+ cmpl $(-kFastUCode),%ecx // %rcx == -length, where (length < kVeryLong)
+ jle Lfastpath // long enough for fastpath in microcode
+ movapd -8(%rsi,%rcx),%xmm0 // 8-byte aligned: prime the loop
+ jmp 1f
+ .align 4,0x90
+1: // loop over 64-byte chunks
+ movapd 8(%rsi,%rcx),%xmm1
+ movapd 24(%rsi,%rcx),%xmm2
+ shufpd $01,%xmm1,%xmm0 // %xmm0 <- shr( %xmm0 || %xmm1, 8 bytes)
+ movapd 40(%rsi,%rcx),%xmm3
+ shufpd $01,%xmm2,%xmm1
+ movapd 56(%rsi,%rcx),%xmm4
+ shufpd $01,%xmm3,%xmm2
+
+ movapd %xmm0,(%rdi,%rcx)
+ shufpd $01,%xmm4,%xmm3
+ movapd %xmm1,16(%rdi,%rcx)
+ movapd %xmm2,32(%rdi,%rcx)
+ movapd %xmm4,%xmm0
+ movapd %xmm3,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1001
+
+LMod9:
+ movdqa -9(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 7(%rsi,%rcx),%xmm1
+ movdqa 23(%rsi,%rcx),%xmm2
+ movdqa 39(%rsi,%rcx),%xmm3
+ movdqa 55(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $9,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $9,%xmm2,%xmm3
+ palignr $9,%xmm1,%xmm2
+ palignr $9,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1010
+
+LMod10:
+ movdqa -10(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 6(%rsi,%rcx),%xmm1
+ movdqa 22(%rsi,%rcx),%xmm2
+ movdqa 38(%rsi,%rcx),%xmm3
+ movdqa 54(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $10,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $10,%xmm2,%xmm3
+ palignr $10,%xmm1,%xmm2
+ palignr $10,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1011
+
+LMod11:
+ movdqa -11(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 5(%rsi,%rcx),%xmm1
+ movdqa 21(%rsi,%rcx),%xmm2
+ movdqa 37(%rsi,%rcx),%xmm3
+ movdqa 53(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $11,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $11,%xmm2,%xmm3
+ palignr $11,%xmm1,%xmm2
+ palignr $11,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1100
+// We use the float single data type in order to use "movss" to merge vectors.
+
+LMod12:
+ movss (%rsi,%rcx),%xmm0 // prefetch 1st four bytes of source, right justified
+ jmp 1f
+ .align 4,0x90
+1: // loop over 64-byte chunks
+ pshufd $(0x93),4(%rsi,%rcx),%xmm1 // load and rotate right 12 bytes (mask -- 10 01 00 11)
+ pshufd $(0x93),20(%rsi,%rcx),%xmm2
+ pshufd $(0x93),36(%rsi,%rcx),%xmm3
+ pshufd $(0x93),52(%rsi,%rcx),%xmm4
+
+ movaps %xmm4,%xmm5
+ movss %xmm3,%xmm4 // copy low 4 bytes of source into destination
+ movss %xmm2,%xmm3
+ movss %xmm1,%xmm2
+ movss %xmm0,%xmm1
+
+ movaps %xmm1,(%rdi,%rcx)
+ movaps %xmm2,16(%rdi,%rcx)
+ movaps %xmm5,%xmm0
+ movaps %xmm3,32(%rdi,%rcx)
+ movaps %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1101
+
+LMod13:
+ movdqa -13(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 3(%rsi,%rcx),%xmm1
+ movdqa 19(%rsi,%rcx),%xmm2
+ movdqa 35(%rsi,%rcx),%xmm3
+ movdqa 51(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $13,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $13,%xmm2,%xmm3
+ palignr $13,%xmm1,%xmm2
+ palignr $13,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1110
+
+LMod14:
+ movdqa -14(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 2(%rsi,%rcx),%xmm1
+ movdqa 18(%rsi,%rcx),%xmm2
+ movdqa 34(%rsi,%rcx),%xmm3
+ movdqa 50(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $14,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $14,%xmm2,%xmm3
+ palignr $14,%xmm1,%xmm2
+ palignr $14,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for medium length operands in which low four bits of %rsi == 1111
+
+LMod15:
+ movdqa -15(%rsi,%rcx),%xmm0 // prime the loop by loading 1st source dq
+1: // loop over 64-byte chunks
+ movdqa 1(%rsi,%rcx),%xmm1
+ movdqa 17(%rsi,%rcx),%xmm2
+ movdqa 33(%rsi,%rcx),%xmm3
+ movdqa 49(%rsi,%rcx),%xmm4
+
+ movdqa %xmm0,%xmm5
+ movdqa %xmm4,%xmm0
+
+ palignr $15,%xmm3,%xmm4 // dest <- shr( dest || source, imm*8 )
+ palignr $15,%xmm2,%xmm3
+ palignr $15,%xmm1,%xmm2
+ palignr $15,%xmm5,%xmm1
+
+ movdqa %xmm1,(%rdi,%rcx)
+ movdqa %xmm2,16(%rdi,%rcx)
+ movdqa %xmm3,32(%rdi,%rcx)
+ movdqa %xmm4,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz 1b
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Reverse moves. These are not optimized as aggressively as their forward
+// counterparts, as they are only used with destructive overlap.
+// rdx = length
+// rsi = source ptr
+// rdi = dest ptr
+
+LReverse:
+ addq %rdx,%rsi // point to end of strings
+ addq %rdx,%rdi
+ cmpq $(kShort),%rdx // long enough to bother with SSE?
+ ja LReverseNotShort // yes
+
+// Handle reverse short copies.
+// edx = length (<= kShort)
+// rsi = one byte past end of source
+// rdi = one byte past end of dest
+
+LReverseShort:
+ movl %edx,%ecx // copy length
+ shrl $3,%ecx // #quadwords
+ jz 3f
+1:
+ subq $8,%rsi
+ movq (%rsi),%rax
+ subq $8,%rdi
+ movq %rax,(%rdi)
+ decl %ecx
+ jnz 1b
+3:
+ andl $7,%edx // bytes?
+ jz 5f
+4:
+ decq %rsi
+ movb (%rsi),%al
+ decq %rdi
+ movb %al,(%rdi)
+ decl %edx
+ jnz 4b
+5:
+ movq %r11,%rax // get return value (dst ptr) for memcpy/memmove
+ popq %rbp
+ ret
+
+// Handle a reverse move long enough to justify using SSE.
+// rdx = length (> kShort)
+// rsi = one byte past end of source
+// rdi = one byte past end of dest
+
+LReverseNotShort:
+ movl %edi,%ecx // copy destination
+ andl $15,%ecx // get #bytes to align destination
+ je LReverseDestAligned // already aligned
+ subq %rcx,%rdx // adjust length
+1: // loop copying 1..15 bytes
+ decq %rsi
+ movb (%rsi),%al
+ decq %rdi
+ movb %al,(%rdi)
+ decl %ecx
+ jnz 1b
+
+// Destination is now aligned. Prepare for reverse loops.
+
+LReverseDestAligned:
+ movq %rdx,%rcx // copy length
+ andl $63,%edx // get remaining bytes for LReverseShort
+ andq $-64,%rcx // get number of bytes we will copy in inner loop
+ subq %rcx,%rsi // point to endpoint of copy
+ subq %rcx,%rdi
+ testl $15,%esi // is source aligned too?
+ jnz LReverseUnalignedLoop // no
+
+LReverseAlignedLoop: // loop over 64-byte chunks
+ movdqa -16(%rsi,%rcx),%xmm0
+ movdqa -32(%rsi,%rcx),%xmm1
+ movdqa -48(%rsi,%rcx),%xmm2
+ movdqa -64(%rsi,%rcx),%xmm3
+
+ movdqa %xmm0,-16(%rdi,%rcx)
+ movdqa %xmm1,-32(%rdi,%rcx)
+ movdqa %xmm2,-48(%rdi,%rcx)
+ movdqa %xmm3,-64(%rdi,%rcx)
+
+ subq $64,%rcx
+ jne LReverseAlignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+
+// Reverse, unaligned loop. LDDQU==MOVDQU on these machines.
+
+LReverseUnalignedLoop: // loop over 64-byte chunks
+ movdqu -16(%rsi,%rcx),%xmm0
+ movdqu -32(%rsi,%rcx),%xmm1
+ movdqu -48(%rsi,%rcx),%xmm2
+ movdqu -64(%rsi,%rcx),%xmm3
+
+ movdqa %xmm0,-16(%rdi,%rcx)
+ movdqa %xmm1,-32(%rdi,%rcx)
+ movdqa %xmm2,-48(%rdi,%rcx)
+ movdqa %xmm3,-64(%rdi,%rcx)
+
+ subq $64,%rcx
+ jne LReverseUnalignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+PLATFUNC_DESCRIPTOR(bcopy,sse3x,kHasSSE2|kHasSupplementalSSE3|kCache64,kHasSSE4_2)
+PLATFUNC_DESCRIPTOR(memcpy,sse3x,kHasSSE2|kHasSupplementalSSE3|kCache64,kHasSSE4_2)
+PLATFUNC_DESCRIPTOR(memmove,sse3x,kHasSSE2|kHasSupplementalSSE3|kCache64,kHasSSE4_2)
--- /dev/null
+/*
+ * Copyright (c) 2008 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * The bcopy/memcpy loops, tuned for Nehalem. This is the 64-bit version.
+ *
+ * The following #defines are tightly coupled to the u-architecture:
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+
+
+// void bcopy(const void *src, void *dst, size_t len);
+
+PLATFUNC_FUNCTION_START(bcopy, sse42, 64, 5)
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ movq %rsi,%rax // copy dest ptr
+ movq %rdi,%rsi // xchange source and dest ptrs
+ movq %rax,%rdi
+ subq %rsi,%rax // (dest - source)
+ cmpq %rdx,%rax // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpq $(kShort),%rdx // long enough to bother with SSE?
+ jbe LShort // no
+ jmp LNotShort
+
+//
+// void *memcpy(void *dst, const void *src, size_t len);
+// void *memmove(void *dst, const void *src, size_t len);
+//
+
+PLATFUNC_FUNCTION_START(memcpy, sse42, 64, 0) // void *memcpy(void *dst, const void *src, size_t len)
+PLATFUNC_FUNCTION_START(memmove, sse42, 64, 0) // void *memmove(void *dst, const void *src, size_t len)
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ movq %rdi,%r11 // save return value here
+ movq %rdi,%rax
+ subq %rsi,%rax // (dest - source)
+ cmpq %rdx,%rax // must move in reverse if (dest - source) < length
+ jb LReverseIsland
+ cmpq $(kShort),%rdx // long enough to bother with SSE?
+ ja LNotShort // yes
+
+// Handle short forward copies. As the most common case, this is the fall-through path.
+// rdx = length (<= kShort)
+// rsi = source ptr
+// rdi = dest ptr
+
+LShort:
+ movl %edx,%ecx // copy length using 32-bit operation
+ shrl $2,%ecx // get #doublewords
+ jz 3f
+2: // loop copying doublewords
+ movl (%rsi),%eax
+ addq $4,%rsi
+ movl %eax,(%rdi)
+ addq $4,%rdi
+ decl %ecx
+ jnz 2b
+3: // handle leftover bytes (0..3) in last word
+ andl $3,%edx // any leftover bytes?
+ jz 5f
+4: // loop copying bytes
+ movb (%rsi),%al
+ incq %rsi
+ movb %al,(%rdi)
+ incq %rdi
+ decl %edx
+ jnz 4b
+5:
+ movq %r11,%rax // get return value (dst ptr) for memcpy/memmove
+ popq %rbp
+ ret
+
+
+LReverseIsland: // keep the "jb" above a short branch...
+ jmp LReverse // ...because reverse moves are uncommon
+
+
+// Handle forward moves that are long enough to justify use of SSE.
+// First, 16-byte align the destination.
+// rdx = length (> kShort)
+// rsi = source ptr
+// rdi = dest ptr
+
+LNotShort:
+ movl %edi,%ecx // copy low half of destination ptr
+ negl %ecx
+ andl $15,%ecx // get #bytes to align destination
+ jz LDestAligned // already aligned
+ subl %ecx,%edx // decrement length
+1: // loop copying 1..15 bytes
+ movb (%rsi),%al
+ inc %rsi
+ movb %al,(%rdi)
+ inc %rdi
+ dec %ecx
+ jnz 1b
+
+
+// Destination is now aligned. Nehalem does a great job with unaligned SSE loads,
+// so we use MOVDQU rather than aligned loads and shifts. Since kShort>=80, we
+// know there is at least one 64-byte chunk to move.
+// When we enter the copy loops, the following registers are set up:
+// rdx = residual length (0..63)
+// rcx = -(length to move), a multiple of 64 less than 2GB
+// rsi = ptr to 1st source byte not to move (unaligned)
+// rdi = ptr to 1st dest byte not to move (aligned)
+
+LDestAligned:
+ movq %rdx,%rcx // copy length
+ andl $63,%edx // get remaining bytes for LShort
+ andq $-64,%rcx // get number of bytes we will copy in inner loop
+ addq %rcx,%rsi // point to 1st byte not copied
+ addq %rcx,%rdi
+ negq %rcx // now generate offset to 1st byte to be copied
+ testl $15,%esi // source also aligned?
+ jnz LUnalignedLoop
+ jmp LAlignedLoop
+
+
+// Forward loop for aligned operands.
+
+ .align 4,0x90 // 16-byte align inner loops
+LAlignedLoop: // loop over 64-byte chunks
+ movdqa (%rsi,%rcx),%xmm0
+ movdqa 16(%rsi,%rcx),%xmm1
+ movdqa 32(%rsi,%rcx),%xmm2
+ movdqa 48(%rsi,%rcx),%xmm3
+
+ movdqa %xmm0,(%rdi,%rcx)
+ movdqa %xmm1,16(%rdi,%rcx)
+ movdqa %xmm2,32(%rdi,%rcx)
+ movdqa %xmm3,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz LAlignedLoop
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Forward loop for unaligned operands.
+
+ .align 4,0x90 // 16-byte align inner loops
+LUnalignedLoop: // loop over 64-byte chunks
+ movdqu (%rsi,%rcx),%xmm0
+ movdqu 16(%rsi,%rcx),%xmm1
+ movdqu 32(%rsi,%rcx),%xmm2
+ movdqu 48(%rsi,%rcx),%xmm3
+
+ movdqa %xmm0,(%rdi,%rcx)
+ movdqa %xmm1,16(%rdi,%rcx)
+ movdqa %xmm2,32(%rdi,%rcx)
+ movdqa %xmm3,48(%rdi,%rcx)
+
+ addq $64,%rcx
+ jnz LUnalignedLoop
+
+ jmp LShort // copy remaining 0..63 bytes and done
+
+
+// Reverse moves. These are only used with destructive overlap.
+// rdx = length
+// rsi = source ptr
+// rdi = dest ptr
+
+LReverse:
+ addq %rdx,%rsi // point to end of strings
+ addq %rdx,%rdi
+ cmpq $(kShort),%rdx // long enough to bother with SSE?
+ ja LReverseNotShort // yes
+
+// Handle reverse short copies.
+// edx = length (<= kShort)
+// rsi = one byte past end of source
+// rdi = one byte past end of dest
+
+LReverseShort:
+ movl %edx,%ecx // copy length
+ shrl $3,%ecx // #quadwords
+ jz 3f
+1:
+ subq $8,%rsi
+ movq (%rsi),%rax
+ subq $8,%rdi
+ movq %rax,(%rdi)
+ decl %ecx
+ jnz 1b
+3:
+ andl $7,%edx // bytes?
+ jz 5f
+4:
+ decq %rsi
+ movb (%rsi),%al
+ decq %rdi
+ movb %al,(%rdi)
+ decl %edx
+ jnz 4b
+5:
+ movq %r11,%rax // get return value (dst ptr) for memcpy/memmove
+ popq %rbp
+ ret
+
+// Handle a reverse move long enough to justify using SSE.
+// rdx = length (> kShort)
+// rsi = one byte past end of source
+// rdi = one byte past end of dest
+
+LReverseNotShort:
+ movl %edi,%ecx // copy destination
+ andl $15,%ecx // get #bytes to align destination
+ jz LReverseDestAligned // already aligned
+ subq %rcx,%rdx // adjust length
+1: // loop copying 1..15 bytes
+ decq %rsi
+ movb (%rsi),%al
+ decq %rdi
+ movb %al,(%rdi)
+ decl %ecx
+ jnz 1b
+
+// Destination is now aligned. Prepare for reverse loops.
+
+LReverseDestAligned:
+ movq %rdx,%rcx // copy length
+ andl $63,%edx // get remaining bytes for LReverseShort
+ andq $-64,%rcx // get number of bytes we will copy in inner loop
+ subq %rcx,%rsi // point to endpoint of copy
+ subq %rcx,%rdi
+ testl $15,%esi // is source aligned too?
+ jnz LReverseUnalignedLoop // no
+
+LReverseAlignedLoop: // loop over 64-byte chunks
+ movdqa -16(%rsi,%rcx),%xmm0
+ movdqa -32(%rsi,%rcx),%xmm1
+ movdqa -48(%rsi,%rcx),%xmm2
+ movdqa -64(%rsi,%rcx),%xmm3
+
+ movdqa %xmm0,-16(%rdi,%rcx)
+ movdqa %xmm1,-32(%rdi,%rcx)
+ movdqa %xmm2,-48(%rdi,%rcx)
+ movdqa %xmm3,-64(%rdi,%rcx)
+
+ subq $64,%rcx
+ jne LReverseAlignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+
+// Reverse, unaligned loop. LDDQU==MOVDQU on these machines.
+
+LReverseUnalignedLoop: // loop over 64-byte chunks
+ movdqu -16(%rsi,%rcx),%xmm0
+ movdqu -32(%rsi,%rcx),%xmm1
+ movdqu -48(%rsi,%rcx),%xmm2
+ movdqu -64(%rsi,%rcx),%xmm3
+
+ movdqa %xmm0,-16(%rdi,%rcx)
+ movdqa %xmm1,-32(%rdi,%rcx)
+ movdqa %xmm2,-48(%rdi,%rcx)
+ movdqa %xmm3,-64(%rdi,%rcx)
+
+ subq $64,%rcx
+ jne LReverseUnalignedLoop
+
+ jmp LReverseShort // copy remaining 0..63 bytes and done
+
+
+PLATFUNC_DESCRIPTOR(bcopy,sse42,kHasSSE4_2,0)
+PLATFUNC_DESCRIPTOR(memcpy,sse42,kHasSSE4_2,0)
+PLATFUNC_DESCRIPTOR(memmove,sse42,kHasSSE4_2,0)
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bzero, sse42)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(bzero, sse2)
+
+static const platfunc_descriptor *bzero_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(bzero, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(bzero, sse2),
+ 0
+};
+
+void *bzero_chooser() __asm__("_bzero");
+void *bzero_chooser() {
+ __asm__(".desc _bzero, 0x100");
+ return find_platform_function((const platfunc_descriptor **) bzero_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 2002-2003 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@
- */
-
-/*
- * Call the comm page routine
- */
-
-#define __APPLE_API_PRIVATE
-#include <machine/cpu_capabilities.h>
-
-#include <architecture/i386/asm_help.h>
-
- TEXT
- ALIGN
-
-LEAF(_bzero,0)
- movq $(_COMM_PAGE_BZERO), %rax
- jmp *%rax
-
-X_LEAF(___bzero, _bzero)
--- /dev/null
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * Bzero, tuned for Pentium-M class processors with SSE2
+ * and 64-byte cache lines. This is the 64-bit version.
+ *
+ * This routine is also used for memset(p,0,n), which is a common case
+ * since gcc sometimes silently maps bzero() into memset(). As a result,
+ * we always load the original ptr into %eax before returning.
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+#define kVeryLong (1024*1024)
+
+// void bzero(void *b, size_t len);
+
+PLATFUNC_FUNCTION_START_GENERIC(bzero, sse2, 64, 5)
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ xorl %eax,%eax // set fill data to 0
+ movq %rdi,%r11 // save original ptr as return value
+ cmpq $(kShort),%rsi // long enough for SSE?
+ jg LNotShort // yes
+
+// Here for short operands or the end of long ones.
+// %esi = length (<= kShort)
+// %rdi = ptr
+// %eax = zero
+
+Lshort:
+ cmpl $16,%esi // long enough to word align?
+ jge 3f // yes
+ test %esi,%esi // length==0?
+ jz 6f
+1:
+ movb %al,(%rdi) // zero a byte
+ incq %rdi
+ decl %esi
+ jnz 1b
+ jmp 6f
+2:
+ movb %al,(%rdi) // zero a byte
+ incq %rdi
+ decl %esi
+3:
+ testl $3,%edi // is ptr doubleword aligned?
+ jnz 2b // no
+ movl %esi,%ecx // copy length
+ shrl $2,%esi // #doublewords to store
+4:
+ movl %eax,(%rdi) // zero an aligned doubleword
+ addq $4,%rdi
+ decl %esi
+ jnz 4b
+ andl $3,%ecx // mask down to #bytes at end (0..3)
+ jz 6f // none
+5:
+ movb %al,(%rdi) // zero a byte
+ incq %rdi
+ decl %ecx
+ jnz 5b
+6:
+ movq %r11,%rax // set return value in case this was a call of memset()
+ popq %rbp
+ ret
+
+
+// We will be using SSE, so align ptr.
+// %rsi = length (> kShort)
+// %rdi = ptr
+// %eax = zero
+
+LNotShort:
+ movl %edi,%ecx // get #bytes to 16-byte align ptr
+ negl %ecx
+ andl $15,%ecx
+ jz LDestAligned // already aligned
+ subq %rcx,%rsi // decrement length
+0: // loop storing bytes to align the ptr
+ movb %al,(%rdi) // pack in a byte
+ incq %rdi
+ decl %ecx
+ jnz 0b
+
+// Destination is now 16-byte aligned. Prepare to loop over 64-byte chunks.
+// %rsi = length (> (kShort-15))
+// %rdi = ptr (aligned)
+// %eax = zero
+
+LDestAligned:
+ movq %rsi,%rcx
+ andl $63,%esi // mask down to residual length (0..63)
+ andq $-64,%rcx // get #bytes we will zero in this loop
+ pxor %xmm0,%xmm0 // zero an SSE register
+ addq %rcx,%rdi // increment ptr by length to move
+ cmpq $(kVeryLong),%rcx // long enough to justify non-temporal stores?
+ jae LVeryLong // yes
+ negq %rcx // negate length to move
+ jmp 1f
+
+// Loop over 64-byte chunks, storing into cache.
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movdqa %xmm0,(%rdi,%rcx)
+ movdqa %xmm0,16(%rdi,%rcx)
+ movdqa %xmm0,32(%rdi,%rcx)
+ movdqa %xmm0,48(%rdi,%rcx)
+ addq $64,%rcx
+ jne 1b
+
+ jmp Lshort
+
+// Very long operands: use non-temporal stores to bypass cache.
+
+LVeryLong:
+ negq %rcx // negate length to move
+ jmp 1f
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movntdq %xmm0,(%rdi,%rcx)
+ movntdq %xmm0,16(%rdi,%rcx)
+ movntdq %xmm0,32(%rdi,%rcx)
+ movntdq %xmm0,48(%rdi,%rcx)
+ addq $64,%rcx
+ jne 1b
+
+ sfence // required by non-temporal stores
+ jmp Lshort
+
+PLATFUNC_DESCRIPTOR(bzero,sse2,kHasSSE2,kHasSSE4_2)
--- /dev/null
+/*
+ * Copyright (c) 2008 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+/*
+ * Bzero, tuned for processors with SSE4.2 and 64-byte cache lines, ie Nehalem.
+ * We don't actually use SSE4.2, but rather use it to identify Nehalem.
+ * This is the 64-bit version.
+ *
+ * We do not use nontemporal operations, but use MOVDQA in preference to REP/STOS.
+ *
+ * This routine is also used for memset(p,0,n), which is a common case
+ * since gcc sometimes silently maps bzero() into memset(). As a result,
+ * we always load the original ptr into %eax before returning.
+ */
+
+#define kShort 80 // too short to bother with SSE (must be >=80)
+
+
+// void bzero(void *b, size_t len);
+
+PLATFUNC_FUNCTION_START(bzero, sse42, 64, 5)
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ xorl %eax,%eax // set fill data to 0
+ movq %rdi,%r11 // save original ptr as return value
+ cmpq $(kShort),%rsi // long enough for SSE?
+ jg LNotShort // yes
+
+// Here for short operands or the end of long ones.
+// %esi = length (<= kShort)
+// %rdi = ptr
+// %eax = zero
+
+Lshort:
+ cmpl $12,%esi // long enough to word align?
+ jge 3f // yes
+ test %esi,%esi // length==0?
+ jz 6f
+1:
+ movb %al,(%rdi) // zero a byte
+ incq %rdi
+ decl %esi
+ jnz 1b
+ jmp 6f
+2:
+ movb %al,(%rdi) // zero a byte
+ incq %rdi
+ decl %esi
+3:
+ testl $3,%edi // is ptr doubleword aligned?
+ jnz 2b // no
+ movl %esi,%ecx // copy length
+ shrl $2,%esi // #doublewords to store
+4:
+ movl %eax,(%rdi) // zero an aligned doubleword
+ addq $4,%rdi
+ decl %esi
+ jnz 4b
+ andl $3,%ecx // mask down to #bytes at end (0..3)
+ jz 6f // none
+5:
+ movb %al,(%rdi) // zero a byte
+ incq %rdi
+ decl %ecx
+ jnz 5b
+6:
+ movq %r11,%rax // set return value in case this was a call of memset()
+ popq %rbp
+ ret
+
+
+// We will be using SSE, so align ptr.
+// %rsi = length (> kShort)
+// %rdi = ptr
+// %eax = zero
+
+LNotShort:
+ testl $3,%edi // 4-byte aligned?
+ jz 2f // yes
+ movb %al,(%rdi) // zero another byte
+ incq %rdi
+ decq %rsi
+ jmp LNotShort
+1: // zero doublewords until 16-byte aligned
+ movl %eax,(%rdi)
+ addq $4,%rdi
+ subq $4,%rsi
+2:
+ testl $15,%edi // 16-byte aligned?
+ jnz 1b // no
+
+// Destination is now 16-byte aligned. Prepare to loop over 64-byte chunks.
+// %rsi = length (> (kShort-15))
+// %rdi = ptr (aligned)
+// %eax = zero
+
+LDestAligned:
+ movq %rsi,%rcx
+ andl $63,%esi // mask down to residual length (0..63)
+ andq $-64,%rcx // get #bytes we will zero in this loop
+ pxor %xmm0,%xmm0 // zero an SSE register
+ addq %rcx,%rdi // increment ptr by length to move
+ negq %rcx // negate length to move
+ jmp 1f
+
+// Loop over 64-byte chunks, storing into cache.
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movdqa %xmm0,(%rdi,%rcx)
+ movdqa %xmm0,16(%rdi,%rcx)
+ movdqa %xmm0,32(%rdi,%rcx)
+ movdqa %xmm0,48(%rdi,%rcx)
+ addq $64,%rcx
+ jne 1b
+
+ jmp Lshort
+
+
+PLATFUNC_DESCRIPTOR(bzero,sse42,kHasSSE4_2,0)
--- /dev/null
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <machine/cpu_capabilities.h>
+
+/*
+ * The bcopy/memcpy loops for very long operands, tuned for 64-bit
+ * Pentium-M class processors with Supplemental SSE3 and 64-byte cache lines.
+ * This is the 64-bit version.
+ *
+ * The following #defines are tightly coupled to the u-architecture:
+ */
+
+#define kBigChunk (256*1024) // outer loop chunk size for kVeryLong sized operands
+
+
+// Very long forward moves. These are at least several pages, so we loop over big
+// chunks of memory (kBigChunk in size.) We first prefetch the chunk, and then copy
+// it using non-temporal stores. Hopefully all the reads occur in the prefetch loop,
+// so the copy loop reads from L2 and writes directly to memory (with write combining.)
+// This minimizes bus turnaround and maintains good DRAM page locality.
+// Note that for this scheme to work, kVeryLong must be a large fraction of L2 cache
+// size. Otherwise, it is counter-productive to bypass L2 on the stores.
+//
+// We are called from the platfunc bcopy loops when they encounter very long
+// operands, with the standard ABI:
+// rdi = dest ptr
+// rsi = source ptr
+// rdx = length (>= 8kb, probably much bigger)
+
+// void longcopy(const void *dest, void *sou, size_t len)
+
+ .private_extern _longcopy
+_longcopy:
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ movl %edi,%eax // copy dest ptr
+ negl %eax
+ andl $63,%eax // get #bytes to cache line align destination
+ jz LBigChunkLoop // already aligned
+
+ // Cache line align destination, so temporal stores in copy loops work right.
+ // The recursive call returns with the source and dest ptrs properly updated.
+
+ subq %rax,%rdx // get length remaining after dest is aligned
+ pushq %rdx // save length remaining
+ movl %eax,%edx // #bytes to copy to align destination
+ call _memcpy
+ popq %rdx // recover adjusted length
+
+// Loop over big chunks.
+// rdx = length remaining (>= 4096)
+// rdi = dest (64-byte aligned)
+// rsi = source (may be unaligned)
+
+LBigChunkLoop:
+ movl $(kBigChunk),%r8d // assume we can do a full chunk
+ cmpq %r8,%rdx // do we have a full chunk left to do?
+ cmovbl %edx,%r8d // if not, only move what we have left
+ andl $-4096,%r8d // we work in page multiples
+ xorl %eax,%eax // initialize chunk offset
+ jmp LTouchLoop
+
+// Touch in the next chunk. We try to keep the prefetch unit in "kick-start" mode,
+// by touching two adjacent cache lines every 8 lines of each page, in four slices.
+// Because the source may be unaligned, we use byte loads to touch.
+// rdx = length remaining (including this chunk)
+// rdi = ptr to start of dest chunk
+// rsi = ptr to start of source chunk
+// r8d = chunk length (multiples of pages, less than 2**32)
+// ecx = scratch reg used to read a byte of each cache line
+// eax = chunk offset
+
+ .align 4,0x90 // 16-byte align inner loops
+LTouchLoop:
+ movzb (%rsi,%rax),%ecx // touch line 0, 2, 4, or 6 of page
+ movzb 1*64(%rsi,%rax),%ecx // touch line 1, 3, 5, or 7
+ movzb 8*64(%rsi,%rax),%ecx // touch line 8, 10, 12, or 14
+ movzb 9*64(%rsi,%rax),%ecx // etc
+
+ movzb 16*64(%rsi,%rax),%ecx
+ movzb 17*64(%rsi,%rax),%ecx
+ movzb 24*64(%rsi,%rax),%ecx
+ movzb 25*64(%rsi,%rax),%ecx
+
+ movzb 32*64(%rsi,%rax),%ecx
+ movzb 33*64(%rsi,%rax),%ecx
+ movzb 40*64(%rsi,%rax),%ecx
+ movzb 41*64(%rsi,%rax),%ecx
+
+ movzb 48*64(%rsi,%rax),%ecx
+ movzb 49*64(%rsi,%rax),%ecx
+ movzb 56*64(%rsi,%rax),%ecx
+ movzb 57*64(%rsi,%rax),%ecx
+
+ subl $-128,%eax // next slice of page (adding 128 w 8-bit immediate)
+ testl $512,%eax // done with this page?
+ jz LTouchLoop // no, next of four slices
+ addl $(4096-512),%eax // move on to next page
+ cmpl %eax,%r8d // done with this chunk?
+ jnz LTouchLoop // no, do next page
+
+ // The chunk has been pre-fetched, now copy it using non-temporal stores.
+ // There are two copy loops, depending on whether the source is 16-byte aligned
+ // or not.
+
+ movl %r8d,%ecx // copy chunk size to a reg that doesn't use REX prefix
+ addq %rcx,%rsi // increment ptrs by chunk length
+ addq %rcx,%rdi
+ subq %rcx,%rdx // adjust remaining length
+ negq %rcx // prepare loop index (counts up to 0)
+ testl $15,%esi // is source 16-byte aligned?
+ jnz LVeryLongUnaligned // no
+ jmp LVeryLongAligned
+
+ .align 4,0x90 // 16-byte align inner loops
+LVeryLongAligned: // aligned loop over 128-bytes
+ movdqa (%rsi,%rcx),%xmm0
+ movdqa 16(%rsi,%rcx),%xmm1
+ movdqa 32(%rsi,%rcx),%xmm2
+ movdqa 48(%rsi,%rcx),%xmm3
+ movdqa 64(%rsi,%rcx),%xmm4
+ movdqa 80(%rsi,%rcx),%xmm5
+ movdqa 96(%rsi,%rcx),%xmm6
+ movdqa 112(%rsi,%rcx),%xmm7
+
+ movntdq %xmm0,(%rdi,%rcx)
+ movntdq %xmm1,16(%rdi,%rcx)
+ movntdq %xmm2,32(%rdi,%rcx)
+ movntdq %xmm3,48(%rdi,%rcx)
+ movntdq %xmm4,64(%rdi,%rcx)
+ movntdq %xmm5,80(%rdi,%rcx)
+ movntdq %xmm6,96(%rdi,%rcx)
+ movntdq %xmm7,112(%rdi,%rcx)
+
+ subq $-128,%rcx // add 128 with an 8-bit immediate
+ jnz LVeryLongAligned
+ jmp LVeryLongChunkEnd
+
+ .align 4,0x90 // 16-byte align inner loops
+LVeryLongUnaligned: // unaligned loop over 128-bytes
+ movdqu (%rsi,%rcx),%xmm0
+ movdqu 16(%rsi,%rcx),%xmm1
+ movdqu 32(%rsi,%rcx),%xmm2
+ movdqu 48(%rsi,%rcx),%xmm3
+ movdqu 64(%rsi,%rcx),%xmm4
+ movdqu 80(%rsi,%rcx),%xmm5
+ movdqu 96(%rsi,%rcx),%xmm6
+ movdqu 112(%rsi,%rcx),%xmm7
+
+ movntdq %xmm0,(%rdi,%rcx)
+ movntdq %xmm1,16(%rdi,%rcx)
+ movntdq %xmm2,32(%rdi,%rcx)
+ movntdq %xmm3,48(%rdi,%rcx)
+ movntdq %xmm4,64(%rdi,%rcx)
+ movntdq %xmm5,80(%rdi,%rcx)
+ movntdq %xmm6,96(%rdi,%rcx)
+ movntdq %xmm7,112(%rdi,%rcx)
+
+ subq $-128,%rcx // add 128 with an 8-bit immediate
+ jnz LVeryLongUnaligned
+
+LVeryLongChunkEnd:
+ cmpq $4096,%rdx // at least another page to go?
+ jae LBigChunkLoop // yes
+
+ // Done. Call memcpy() again to handle the 0-4095 bytes at the end.
+ // We still have the args in the right registers:
+ // rdi = destination ptr
+ // rsi = source ptr
+ // rdx = length remaining (0..4095)
+
+ sfence // required by non-temporal stores
+ testl %edx,%edx // anything left to copy?
+ jz 1f
+ call _memcpy
+1:
+ popq %rbp // restore frame ptr
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memcpy, sse42)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memcpy, sse3x)
+
+static const platfunc_descriptor *memcpy_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(memcpy, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memcpy, sse3x),
+ 0
+};
+
+void *memcpy_chooser() __asm__("_memcpy");
+void *memcpy_chooser() {
+ __asm__(".desc _memcpy, 0x100");
+ return find_platform_function((const platfunc_descriptor **) memcpy_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
- *
- * File: libc/i386/ansi/memcpy.c
- * Author: Bruce Martin, NeXT Computer, Inc.
- *
- * HISTORY
- * 24-Nov-92 Derek B Clegg (dclegg@next.com)
- * Created for m98k.
- */
-#define MEMCOPY
-#include "bcopy.s"
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memmove, sse42)
+PLATFUNC_DESCRIPTOR_PROTOTYPE(memmove, sse3x)
+
+static const platfunc_descriptor *memmove_platfunc_descriptors[] = {
+ PLATFUNC_DESCRIPTOR_REFERENCE(memmove, sse42),
+ PLATFUNC_DESCRIPTOR_REFERENCE(memmove, sse3x),
+ 0
+};
+
+void *memmove_chooser() __asm__("_memmove");
+void *memmove_chooser() {
+ __asm__(".desc _memmove, 0x100");
+ return find_platform_function((const platfunc_descriptor **) memmove_platfunc_descriptors);
+}
+++ /dev/null
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
- *
- * File: libc/i386/ansi/memmove.c
- * Author: Bruce Martin, NeXT Computer, Inc.
- *
- * HISTORY
- * 24-Nov-92 Derek B Clegg (dclegg@next.com)
- * Created for m98k.
- */
-#define MEMMOVE
-#include "bcopy.s"
*/
#include <machine/cpu_capabilities.h>
-
+
/* This file contains the following functions:
*
* void memset_pattern16(void *b, const void *c16, size_t len);
*
* Calls of memset() with c==0 are routed to the bzero() routine. Most of the
- * others go to _COMM_PAGE_MEMSET_PATTERN, which is entered as follows:
+ * others go to _memset_pattern, which is entered as follows:
* %rdi = ptr to memory to set (aligned)
* %edx = length (which can be short, though we bias in favor of long operands)
* %xmm0 = the pattern to store
* NB: we avoid "stos" family of instructions (stosl, stosb), as they are very slow
* on P4s and probably other processors.
*/
-
- #define kShort 255 // for nonzero memset(), too short for commpage
-
-
+
+#define kShort 255 // for nonzero memset(), too short for commpage
+
+
.text
.globl _memset
.align 2
_memset: // void *memset(void *b, int c, size_t len);
andl $0xFF,%esi // (c==0) ?
jnz LNonzero // not a bzero
-
- movq $(_COMM_PAGE_BZERO),%rax// map memset(p,0,n) into bzero(p,n)
+
movq %rdx,%rsi // put count where bzero() expects it
- jmp *%rax // enter commpage
+ jmp _bzero // enter _bzero
+
+// Handle memset of a nonzero value.
- // Handle memset of a nonzero value.
-
LNonzero:
movq %rdi,%r8 // preserve the original pointer so we can return it
movl %esi,%eax // replicate byte in %esi into all four bytes
orl %esi,%eax // now %eax has "c" in all 4 bytes
cmpq $(kShort),%rdx // is operand too short for SSE?
ja LCallCommpage // no
-
-// Nonzero memset() too short to call commpage.
-// %eax = replicated 4-byte pattern
-// %rdi = ptr
-// %edx = length (<= kShort)
-
+
+ // Nonzero memset() too short to call commpage.
+ // %eax = replicated 4-byte pattern
+ // %rdi = ptr
+ // %edx = length (<= kShort)
+
cmpl $16,%edx // long enough to word align?
jge 3f // yes
test %edx,%edx // length==0?
6:
movq %r8,%rax // get return value (ie, original ptr)
ret
-
-// Nonzero memset() is long enough to call commpage.
-// %eax = replicated 4-byte pattern
-// %rdi = ptr
-// %rdx = length (> kShort)
-
+
+ // Nonzero memset() is long enough to call commpage.
+ // %eax = replicated 4-byte pattern
+ // %rdi = ptr
+ // %rdx = length (> kShort)
+
LCallCommpage:
movd %eax,%xmm0 // move %eax to low 4 bytes of %xmm0
pshufd $(0x00),%xmm0,%xmm0 // replicate across the vector
subl $1,%ecx
jnz 1b
2: // ptr aligned, length long enough to justify
- movq $(_COMM_PAGE_MEMSET_PATTERN),%rax
- call *%rax // call commpage to do the heavy lifting
+ call Lmemset_pattern // call commpage to do the heavy lifting
movq %r8,%rax // get return value (ie, original ptr)
ret
-// Handle memset of a 16-byte pattern.
-
+ // Handle memset of a 16-byte pattern.
+
.globl _memset_pattern16
.align 2, 0x90
_memset_pattern16: // void memset_pattern16(void *b, const void *c16, size_t len);
jmp LAlignPtr
-// Handle memset of an 8-byte pattern.
-
+ // Handle memset of an 8-byte pattern.
+
.globl _memset_pattern8
.align 2, 0x90
_memset_pattern8: // void memset_pattern8(void *b, const void *c8, size_t len);
punpcklqdq %xmm0,%xmm0 // replicate into all 16
jmp LAlignPtr
-// Handle memset of a 4-byte pattern.
-
+ // Handle memset of a 4-byte pattern.
+
.globl _memset_pattern4
.align 2, 0x90
_memset_pattern4: // void memset_pattern4(void *b, const void *c4, size_t len);
pshufd $(0x00),%xmm0,%xmm0 // replicate the 4 bytes across the vector
-// Align ptr if necessary. We must rotate the pattern right for each byte we
-// store while aligning the ptr. Since there is no rotate instruction in SSE3,
-// we have to synthesize the rotates.
-// %rdi = ptr
-// %rdx = length
-// %xmm0 = pattern
-
+ // Align ptr if necessary. We must rotate the pattern right for each byte we
+ // store while aligning the ptr. Since there is no rotate instruction in SSE3,
+ // we have to synthesize the rotates.
+ // %rdi = ptr
+ // %rdx = length
+ // %xmm0 = pattern
+
LAlignPtr: // NB: can drop down to here!
cmpq $100,%rdx // long enough to bother aligning ptr?
movq %rdi,%rcx // copy ptr
andl $15,%ecx // get #bytes to align ptr
jz LReady // already aligned
subq %rcx,%rdx // adjust length
-
+
test $1,%cl // 1-byte store required?
movd %xmm0,%eax // get 4 low bytes in %eax
jz 2f // no
movq %xmm0,(%rdi) // store low 8 bytes of %xmm0
pshufd $(0x4e),%xmm0,%xmm0 // rotate %xmm0 right 8 bytes (mask == 01 00 11 10)
addq $8,%rdi // adjust ptr
-
-// Ptr is aligned if practical, we're ready to call commpage to do the heavy lifting.
+
+ // Ptr is aligned if practical, we're ready to call commpage to do the heavy lifting.
LReady:
- movq $(_COMM_PAGE_MEMSET_PATTERN),%rax
- call *%rax // call commpage to do the heavy lifting
+ call Lmemset_pattern // call commpage to do the heavy lifting
ret
+
+
+#define kLShort 63
+#define kVeryLong (1024*1024)
+
+Lmemset_pattern:
+ cmpq $(kLShort),%rdx // long enough to bother aligning?
+ ja LNotShort // yes
+ jmp LShort // no
+
+ // Here for short operands or the end of long ones.
+ // %rdx = length (<= kLShort)
+ // %rdi = ptr (may not be not aligned)
+ // %xmm0 = pattern
+
+LUnalignedStore16:
+ movdqu %xmm0,(%rdi) // stuff in another 16 bytes
+ subl $16,%edx
+ addq $16,%rdi
+LShort:
+ cmpl $16,%edx // room for another vector?
+ jge LUnalignedStore16 // yes
+LLessThan16: // here at end of copy with < 16 bytes remaining
+ test $8,%dl // 8-byte store required?
+ jz 2f // no
+ movq %xmm0,(%rdi) // pack in 8 low bytes
+ psrldq $8,%xmm0 // then shift vector down 8 bytes
+ addq $8,%rdi
+2:
+ test $4,%dl // 4-byte store required?
+ jz 3f // no
+ movd %xmm0,(%rdi) // pack in 4 low bytes
+ psrldq $4,%xmm0 // then shift vector down 4 bytes
+ addq $4,%rdi
+3:
+ andl $3,%edx // more to go?
+ jz 5f // no
+ movd %xmm0,%eax // move remainders out into %eax
+4: // loop on up to three bytes
+ movb %al,(%rdi) // pack in next byte
+ shrl $8,%eax // shift next byte into position
+ incq %rdi
+ dec %edx
+ jnz 4b
+5: ret
+
+// Long enough to justify aligning ptr. Note that we have to rotate the
+// pattern to account for any alignment. We do this by doing two unaligned
+// stores, and then an aligned load from the middle of the two stores.
+// This will stall on store forwarding alignment mismatch, and the unaligned
+// stores can be pretty slow too, but the alternatives aren't any better.
+// Fortunately, in most cases our caller has already aligned the ptr.
+// %rdx = length (> kLShort)
+// %rdi = ptr (may not be aligned)
+// %xmm0 = pattern
+
+LNotShort:
+ movl %edi,%ecx // copy low bits of dest ptr
+ negl %ecx
+ andl $15,%ecx // mask down to #bytes to 16-byte align
+ jz LAligned // skip if already aligned
+ movdqu %xmm0,(%rdi) // store 16 unaligned bytes
+ movdqu %xmm0,16(%rdi) // and 16 more, to be sure we have an aligned chunk
+ addq %rcx,%rdi // now point to the aligned chunk
+ subq %rcx,%rdx // adjust remaining count
+ movdqa (%rdi),%xmm0 // get the rotated pattern (probably stalling)
+ addq $16,%rdi // skip past the aligned chunk
+ subq $16,%rdx
+
+// Set up for 64-byte loops.
+// %rdx = length remaining
+// %rdi = ptr (aligned)
+// %xmm0 = rotated pattern
+
+LAligned:
+ movq %rdx,%rcx // copy length remaining
+ andl $63,%edx // mask down to residual length (0..63)
+ andq $-64,%rcx // %ecx <- #bytes we will zero in by-64 loop
+ jz LNoMoreChunks // no 64-byte chunks
+ addq %rcx,%rdi // increment ptr by length to move
+ cmpq $(kVeryLong),%rcx // long enough to justify non-temporal stores?
+ jge LVeryLong // yes
+ negq %rcx // negate length to move
+ jmp 1f
+
+// Loop over 64-byte chunks, storing into cache.
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movdqa %xmm0,(%rdi,%rcx)
+ movdqa %xmm0,16(%rdi,%rcx)
+ movdqa %xmm0,32(%rdi,%rcx)
+ movdqa %xmm0,48(%rdi,%rcx)
+ addq $64,%rcx
+ jne 1b
+
+ jmp LNoMoreChunks
+
+// Very long operands: use non-temporal stores to bypass cache.
+
+LVeryLong:
+ negq %rcx // negate length to move
+ jmp 1f
+
+ .align 4,0x90 // keep inner loops 16-byte aligned
+1:
+ movntdq %xmm0,(%rdi,%rcx)
+ movntdq %xmm0,16(%rdi,%rcx)
+ movntdq %xmm0,32(%rdi,%rcx)
+ movntdq %xmm0,48(%rdi,%rcx)
+ addq $64,%rcx
+ jne 1b
+
+ sfence // required by non-temporal stores
+ jmp LNoMoreChunks
+
+// Handle leftovers: loop by 16.
+// %edx = length remaining (<64)
+// %edi = ptr (aligned)
+// %xmm0 = rotated pattern
+
+LLoopBy16:
+ movdqa %xmm0,(%rdi) // pack in 16 more bytes
+ subl $16,%edx // decrement count
+ addq $16,%rdi // increment ptr
+LNoMoreChunks:
+ cmpl $16,%edx // more to go?
+ jge LLoopBy16 // yes
+ jmp LLessThan16 // handle up to 15 remaining bytes
LZeroBuffer:
movq %rdx,%rsi // remaining buffer size (2nd argument)
- movq $(_COMM_PAGE_BZERO),%rax
- call *%rax
+ call _bzero
LDone:
movq %r8,%rax // original dest ptr is return value
AINC+= -I${.CURDIR}/x86_64/sys
MDSRCS+= OSAtomic.s \
- i386_gettimeofday.s \
+ atomic.c \
+ spinlocks.c \
+ spinlocks_asm.s \
+ i386_gettimeofday_asm.s \
_setjmp.s \
setjmp.s \
- _sigtramp.s
+ _sigtramp.s \
+ nanotime.s
-MDCOPYFILES+= ${.CURDIR}/Platforms/${RC_TARGET_CONFIG}/x86_64/libc.syscall.x86_64
+DYLDSRCS += \
+ OSAtomic.s \
+ i386_gettimeofday_asm.s \
+ spinlocks_asm.s \
+ nanotime.s
*/
#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
#define DECLARE(x) \
-.align 2, 0x90 ; \
-.globl x ; \
-.globl x ## Barrier ; \
+ .align 2, 0x90 ; \
+ .globl x ; \
+ .globl x ## Barrier ; \
x: ; \
x ## Barrier:
.text
+#define ATOMIC_UP 0
+#define ATOMIC_MP 1
+#define ATOMIC_RET_ORIG 0
+#define ATOMIC_RET_NEW 1
+
+// compare and exchange 32-bit
+// xchg32 <new> <dst> <mp>
+.macro xchg32
+ .if $2 == ATOMIC_MP
+ lock
+ .endif
+ cmpxchgl $0, ($1)
+.endm
+
+// xchg64 <new> <dst> <mp>
+.macro xchg64
+ .if $2 == ATOMIC_MP
+ lock
+ .endif
+ cmpxchg $0, ($1)
+.endm
+
+#define ATOMIC_ARITHMETIC(instr, orig, mp) \
+ movl (%rsi), %eax /* get 2nd arg -> eax */ ;\
+1: movl %eax, %edx /* copy value to new reg */ ;\
+ instr %edi, %edx /* apply instr to %edx with arg2 */ ;\
+ xchg32 %edx, %rsi, mp /* do the compare swap (see macro above) */ ;\
+ jnz 1b /* jump if failed */ ;\
+ .if orig == 1 /* to return the new value, overwrite eax */ ;\
+ movl %edx, %eax /* return the new value */ ;\
+ .endif
+
+// Used in OSAtomicTestAndSet( uint32_t n, void *value ), assumes ABI parameter loctions
+// Manpage says bit to test/set is (0x80 >> (n & 7)) of byte (addr + (n >> 3))
+#define ATOMIC_BIT_OP(instr, mp) \
+ xorl $7, %edi /* bit position is numbered big endian so convert to little endian */ ;\
+ shlq $3, %rsi ;\
+ addq %rdi, %rsi /* generate bit address */ ;\
+ movq %rsi, %rdi ;\
+ andq $31, %rdi /* keep bit offset in range 0..31 */ ;\
+ xorq %rdi, %rsi /* 4-byte align address */ ;\
+ shrq $3, %rsi /* get 4-byte aligned address */ ;\
+ .if mp == ATOMIC_MP /* don't plant the lock in UP code */ ;\
+ lock /* lock the bit test */ ;\
+ .endif ;\
+ instr %edi, (%rsi) /* do the bit test, supplied into the macro */ ;\
+ setc %al ;\
+ movzbl %al,%eax /* widen in case caller assumes we return an int */
// uint32_t OSAtomicAnd32( uint32_t mask, uint32_t *value);
-DECLARE(_OSAtomicAnd32)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP32), %rcx
- movl %edi, %r11d // save mask
- movl (%rsi), %eax // get value
- movq %rsi, %rdx // put ptr where compare-and-swap expects it
-1:
- movl %r11d, %esi // original mask
- movl %eax, %edi // old value
- andl %eax, %esi // new value
- call *%rcx // %edi=old value, %esi=new value. %rdx=ptr
- jnz 1b
- movl %esi, %eax
+PLATFUNC_FUNCTION_START(OSAtomicAnd32, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAnd32Barrier, up, 64, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_NEW, ATOMIC_UP)
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32Barrier, mp, 64, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_NEW, ATOMIC_MP)
ret
-
// uint32_t OSAtomicOr32( uint32_t mask, uint32_t *value);
-DECLARE(_OSAtomicOr32)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP32), %rcx
- movl %edi, %r11d // save mask
- movl (%rsi), %eax // get value
- movq %rsi, %rdx // put ptr where compare-and-swap expects it
-1:
- movl %r11d, %esi // original mask
- movl %eax, %edi // old value
- orl %eax, %esi // new value
- call *%rcx // %edi=old value, %esi=new value. %rdx=ptr
- jnz 1b
- movl %esi, %eax
+PLATFUNC_FUNCTION_START(OSAtomicOr32, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicOr32Barrier, up, 64, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_NEW, ATOMIC_UP)
ret
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32Barrier, mp, 64, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_NEW, ATOMIC_MP)
+ ret
// uint32_t OSAtomicXor32( uint32_t mask, uint32_t *value);
-DECLARE(_OSAtomicXor32)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP32), %rcx
- movl %edi, %r11d // save mask
- movl (%rsi), %eax // get value
- movq %rsi, %rdx // put ptr where compare-and-swap expects it
-1:
- movl %r11d, %esi // original mask
- movl %eax, %edi // old value
- xorl %eax, %esi // new value
- call *%rcx // %edi=old value, %esi=new value. %rdx=ptr
- jnz 1b
- movl %esi, %eax
+PLATFUNC_FUNCTION_START(OSAtomicXor32, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicXor32Barrier, up, 64, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_NEW, ATOMIC_UP)
ret
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32Barrier, mp, 64, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_NEW, ATOMIC_MP)
+ ret
// uint32_t OSAtomicAnd32Orig( uint32_t mask, uint32_t *value);
-DECLARE(_OSAtomicAnd32Orig)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP32), %rcx
- movl %edi, %r11d // save mask
- movl (%rsi), %eax // get value
- movq %rsi, %rdx // put ptr where compare-and-swap expects it
-1:
- movl %r11d, %esi // original mask
- movl %eax, %edi // old value
- andl %eax, %esi // new value
- call *%rcx // %edi=old value, %esi=new value. %rdx=ptr
- jnz 1b
- movl %edi, %eax
+PLATFUNC_FUNCTION_START(OSAtomicAnd32Orig, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAnd32OrigBarrier, up, 64, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_ORIG, ATOMIC_UP)
ret
-
-// uint32_t OSAtomicOr32Orig( uint32_t mask, uint32_t *value);
-DECLARE(_OSAtomicOr32Orig)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP32), %rcx
- movl %edi, %r11d // save mask
- movl (%rsi), %eax // get value
- movq %rsi, %rdx // put ptr where compare-and-swap expects it
-1:
- movl %r11d, %esi // original mask
- movl %eax, %edi // old value
- orl %eax, %esi // new value
- call *%rcx // %edi=old value, %esi=new value. %rdx=ptr
- jnz 1b
- movl %edi, %eax
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32Orig, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAnd32OrigBarrier, mp, 64, 2)
+ ATOMIC_ARITHMETIC(andl, ATOMIC_RET_ORIG, ATOMIC_MP)
ret
+// uint32_t OSAtomicOr32Orig( uint32_t mask, uint32_t *value);
+PLATFUNC_FUNCTION_START(OSAtomicOr32Orig, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicOr32OrigBarrier, up, 64, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_ORIG, ATOMIC_UP)
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32Orig, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicOr32OrigBarrier, mp, 64, 2)
+ ATOMIC_ARITHMETIC(orl, ATOMIC_RET_ORIG, ATOMIC_MP)
+ ret
// uint32_t OSAtomicXor32Orig( uint32_t mask, uint32_t *value);
-DECLARE(_OSAtomicXor32Orig)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP32), %rcx
- movl %edi, %r11d // save mask
- movl (%rsi), %eax // get value
- movq %rsi, %rdx // put ptr where compare-and-swap expects it
-1:
- movl %r11d, %esi // original mask
- movl %eax, %edi // old value
- xorl %eax, %esi // new value
- call *%rcx // %edi=old value, %esi=new value. %rdx=ptr
- jnz 1b
- movl %edi, %eax
+PLATFUNC_FUNCTION_START(OSAtomicXor32Orig, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicXor32OrigBarrier, up, 64, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_ORIG, ATOMIC_UP)
ret
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32Orig, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicXor32OrigBarrier, mp, 64, 2)
+ ATOMIC_ARITHMETIC(xorl, ATOMIC_RET_ORIG, ATOMIC_MP)
+ ret
// bool OSAtomicCompareAndSwap32( int32_t old, int32_t new, int32_t *value);
-DECLARE(_OSAtomicCompareAndSwapInt)
-DECLARE(_OSAtomicCompareAndSwap32)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP32), %rcx
- call *%rcx // %edi=old value, %esi=new value. %rdx=ptr
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapInt, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapIntBarrier, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap32, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap32Barrier, up, 64, 2)
+ movl %edi, %eax
+ xchg32 %esi, %rdx, ATOMIC_UP
sete %al
movzbl %al,%eax // widen in case caller assumes we return an int
ret
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapInt, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapIntBarrier, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap32, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap32Barrier, mp, 64, 2)
+ movl %edi, %eax
+ xchg32 %esi, %rdx, ATOMIC_MP
+ sete %al
+ movzbl %al,%eax // widen in case caller assumes we return an int
+ ret
// bool OSAtomicCompareAndSwap64( int64_t old, int64_t new, int64_t *value);
-DECLARE(_OSAtomicCompareAndSwapPtr)
-DECLARE(_OSAtomicCompareAndSwapLong)
-DECLARE(_OSAtomicCompareAndSwap64)
- movq $(_COMM_PAGE_COMPARE_AND_SWAP64), %rcx
- call *%rcx // %rdi=old value, %rsi=new value. %rdx=ptr
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapPtr, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapPtrBarrier, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapLong, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwapLongBarrier, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap64, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicCompareAndSwap64Barrier, up, 64, 2)
+ mov %rdi, %rax
+ xchg64 %rsi, %rdx, ATOMIC_UP
+ sete %al
+ movzbl %al,%eax // widen in case caller assumes we return an int
+ ret
+
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapPtr, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapPtrBarrier, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapLong, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwapLongBarrier, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap64, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicCompareAndSwap64Barrier, mp, 64, 2)
+ mov %rdi, %rax
+ xchg64 %rsi, %rdx, ATOMIC_MP
sete %al
movzbl %al,%eax // widen in case caller assumes we return an int
ret
-
// int32_t OSAtomicAdd32( int32_t amt, int32_t *value );
-DECLARE(_OSAtomicAdd32)
- movq $(_COMM_PAGE_ATOMIC_ADD32), %rcx
+PLATFUNC_FUNCTION_START(OSAtomicAdd32, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAdd32Barrier, up, 64, 2)
movl %edi, %eax // save amt to add
- call *%rcx
- addl %edi,%eax // new value
+ xaddl %edi, (%rsi) // swap and add value, returns old value in %edi
+ addl %edi, %eax // add old value to amt as return value
ret
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd32, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd32Barrier, mp, 64, 2)
+ movl %edi, %eax // save amt to add
+ lock // lock prefix breaks tabs ;)
+ xaddl %edi, (%rsi) // swap and add value, returns old value in %edi
+ addl %edi, %eax // add old value to amt as return value
+ ret
// int64_t OSAtomicAdd64( int64_t amt, int64_t *value );
-DECLARE(_OSAtomicAdd64)
- movq $(_COMM_PAGE_ATOMIC_ADD64), %rcx
+PLATFUNC_FUNCTION_START(OSAtomicAdd64, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicAdd64Barrier, up, 64, 2)
movq %rdi, %rax // save amt to add
- call *%rcx
- addq %rdi, %rax // new value
+ xadd %rdi, (%rsi) // swap and add value, returns old value in %rsi
+ addq %rdi, %rax // add old value to amt as return value
ret
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd64, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicAdd64Barrier, mp, 64, 2)
+ movq %rdi, %rax // save amt to add
+ lock
+ xadd %rdi, (%rsi) // swap and add value, returns old value in %rsi
+ addq %rdi, %rax // add old value to amt as return value
+ ret
// bool OSAtomicTestAndSet( uint32_t n, void *value );
-DECLARE(_OSAtomicTestAndSet)
- movq $(_COMM_PAGE_BTS), %rax
- xorl $7, %edi // bit position is numbered big endian
- call *%rax
- setc %al
- movzbl %al,%eax // widen in case caller assumes we return an int
+PLATFUNC_FUNCTION_START(OSAtomicTestAndSet, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicTestAndSetBarrier, up, 64, 2)
+ ATOMIC_BIT_OP(btsl, ATOMIC_UP)
ret
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndSet, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndSetBarrier, mp, 64, 2)
+ ATOMIC_BIT_OP(btsl, ATOMIC_MP)
+ ret
// bool OSAtomicTestAndClear( uint32_t n, void *value );
-DECLARE(_OSAtomicTestAndClear)
- movq $(_COMM_PAGE_BTC), %rax
- xorl $7, %edi // bit position is numbered big endian
- call *%rax
- setc %al
- movzbl %al,%eax // widen in case caller assumes we return an int
+PLATFUNC_FUNCTION_START(OSAtomicTestAndClear, up, 64, 2)
+PLATFUNC_FUNCTION_START(OSAtomicTestAndClearBarrier, up, 64, 2)
+ ATOMIC_BIT_OP(btrl, ATOMIC_UP)
ret
-// bool OSSpinLockTry( OSSpinLock *lock );
- .align 2, 0x90
- .globl _OSSpinLockTry
- .globl __spin_lock_try
-_OSSpinLockTry:
-__spin_lock_try:
- movq $(_COMM_PAGE_SPINLOCK_TRY), %rax
- jmp *%rax
-
-
-// void OSSpinLockLock( OSSpinLock *lock );
- .align 2, 0x90
- .globl _OSSpinLockLock
- .globl _spin_lock
- .globl __spin_lock
-_OSSpinLockLock:
-_spin_lock:
-__spin_lock:
- movq $(_COMM_PAGE_SPINLOCK_LOCK), %rax
- jmp *%rax
-
-
-// void OSSpinLockUnlock( OSSpinLock *lock );
- .align 2, 0x90
- .globl _OSSpinLockUnlock
- .globl _spin_unlock
- .globl __spin_unlock
-_OSSpinLockUnlock:
-_spin_unlock:
-__spin_unlock:
- movl $0, (%rdi)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndClear, mp, 64, 2)
+PLATFUNC_FUNCTION_START_GENERIC(OSAtomicTestAndClearBarrier, mp, 64, 2)
+ ATOMIC_BIT_OP(btrl, ATOMIC_MP)
ret
-
// void OSMemoryBarrier( void );
.align 2, 0x90
.globl _OSMemoryBarrier
_OSMemoryBarrier:
- movq $(_COMM_PAGE_MEMORY_BARRIER), %rax
- jmp *%rax
-
+ mfence
+ ret
/*
* typedef volatile struct {
jnz 1b
popq %rbx
ret
-
-
-/* void* OSAtomicDequeue( OSQueueHead *list, size_t offset); */
+
+
+ /* void* OSAtomicDequeue( OSQueueHead *list, size_t offset); */
.align 2
.globl _OSAtomicDequeue
_OSAtomicDequeue: // %rdi == list head, %rsi == offset
2:
popq %rbx
ret // ptr to 1st element in Q still in %rax
+
+/*
+ * typedef volatile struct {
+ * void *opaque1; <-- ptr to first queue element or null
+ * void *opaque2; <-- ptr to last queue element or null
+ * int opaque3; <-- spinlock
+ * } OSFifoQueueHead;
+ *
+ * void OSAtomicFifoEnqueue( OSFifoQueueHead *list, void *new, size_t offset);
+ */
+ .align 2
+ .globl _OSAtomicFifoEnqueue
+_OSAtomicFifoEnqueue:
+ pushq %rbx
+ xorl %ebx,%ebx // clear "preemption pending" flag
+ movq $(_COMM_PAGE_PFZ_ENQUEUE), %rcx
+ call *%rcx
+ testl %ebx,%ebx // pending preemption?
+ jz 1f
+ call _preempt // call into the kernel to pfz_exit
+1:
+ popq %rbx
+ ret
+
+
+/* void* OSAtomicFifoDequeue( OSFifoQueueHead *list, size_t offset); */
+ .align 2
+ .globl _OSAtomicFifoDequeue
+_OSAtomicFifoDequeue:
+ pushq %rbx
+ xorl %ebx,%ebx // clear "preemption pending" flag
+ movq %rsi,%rdx // move offset to %rdx to be like the Enqueue case
+ movq $(_COMM_PAGE_PFZ_DEQUEUE), %rcx
+ call *%rcx
+ testl %ebx,%ebx // pending preemption?
+ jz 1f
+ call _preempt // call into the kernel to pfz_exit
+1:
+ popq %rbx
+ ret // ptr to 1st element in Q in %rax
+
+// Local Variables:
+// tab-width: 8
+// End:
movq (%rsp), %rax
movq %rax, JB_RIP(%rdi)
// RSP is set to the frame return address plus 8
- movq %rsp, %rax
- addq $8, %rax
+ leaq 8(%rsp), %rax
movq %rax, JB_RSP(%rdi)
- // save rflags - you can't use movq
- pushfq
- popq %rax
- movq %rax, JB_RFLAGS(%rdi)
-
// save fp control word
fnstcw JB_FPCONTROL(%rdi)
stmxcsr JB_MXCSR(%rdi)
// return 0
- xorq %rax, %rax
+ xorl %eax, %eax
ret
LEAF(__longjmp, 0)
- fninit // reset FP coprocessor
-
+ fninit // Clear all FP exceptions
// %rdi is a jmp_buf (struct sigcontext *)
- // %rsi is the return value
- movq %rsi, %rax
- testq %rax, %rax
+ // %esi is the return value
+ movl %esi, %eax
+ testl %esi, %esi
jnz 1f
- addq $1, %rax
+ incl %eax
// general registers
1:
// restore MXCSR
ldmxcsr JB_MXCSR(%rdi)
- // rflags
- pushq JB_RFLAGS(%rdi)
- popfq
+
+ // Make sure DF is reset
+ cld
jmp *JB_RIP(%rdi)
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
.text
.align 4,0x90
__sigtramp:
+Lstart:
/* Although this routine does not need any stack frame, various parts
of the OS can't analyse the stack without them. */
pushq %rbp
#endif
movq %rbx, %rdi
movl $ UC_FLAVOR, %esi
- jmp ___sigreturn
+ callq ___sigreturn
+ ret
+Lend:
/* DWARF unwind table #defines. */
#define DW_CFA_advance_loc_4 0x44
.long L$set$0 # Length of Common Information Entry
LSCIE1:
.long 0 # CIE Identifier Tag
- .byte 0x3 # CIE Version
- .ascii "zR\0" # CIE Augmentation
+ .byte 0x1 # CIE Version
+ .ascii "zRS\0" # CIE Augmentation
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
.byte 0x10 # CIE RA Column
.byte 0x8 # uleb128 0x4
.byte DW_CFA_offset(16)
.byte 0x1 # uleb128 0x1
+ .byte DW_CFA_offset(16) // duplicate DW_CFA_offset (rip, -8) tells linker to not make compact unwind
+ .byte 0x1 # uleb128 0x1
.align 3
LECIE1:
.globl _sigtramp.eh
.long L$set$1 # FDE Length
LASFDE1:
.long LASFDE1-EH_frame1 # FDE CIE offset
- .quad Lcall_start-. # FDE initial location
- .set L$set$2,Lcall_end-Lcall_start
+ .quad Lstart-. # FDE initial location
+ .set L$set$2,Lend-Lstart
.quad L$set$2 # FDE address range
.byte 0x0 # uleb128 0x0; Augmentation size
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+#define RESOLVER_UP_MP(symbol) \
+ PLATFUNC_DESCRIPTOR(symbol, up, kUP, 0); \
+ PLATFUNC_DESCRIPTOR(symbol, mp, 0, kUP); \
+ static const platfunc_descriptor* symbol ## _platfunc_descriptors[] = { \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, mp), \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, up), \
+ 0 \
+ }; \
+ void* symbol ## _chooser() __asm__("_" #symbol); \
+ void* symbol ## _chooser() { \
+ __asm__(".symbol_resolver _" #symbol); \
+ return find_platform_function((const platfunc_descriptor**) symbol ## _platfunc_descriptors); \
+ }
+
+RESOLVER_UP_MP(OSAtomicAnd32)
+RESOLVER_UP_MP(OSAtomicAnd32Barrier)
+RESOLVER_UP_MP(OSAtomicOr32)
+RESOLVER_UP_MP(OSAtomicOr32Barrier)
+RESOLVER_UP_MP(OSAtomicXor32)
+RESOLVER_UP_MP(OSAtomicXor32Barrier)
+RESOLVER_UP_MP(OSAtomicAnd32Orig)
+RESOLVER_UP_MP(OSAtomicAnd32OrigBarrier)
+RESOLVER_UP_MP(OSAtomicOr32Orig)
+RESOLVER_UP_MP(OSAtomicOr32OrigBarrier)
+RESOLVER_UP_MP(OSAtomicXor32Orig)
+RESOLVER_UP_MP(OSAtomicXor32OrigBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapInt)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapIntBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap32)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap32Barrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapPtr)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapPtrBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapLong)
+RESOLVER_UP_MP(OSAtomicCompareAndSwapLongBarrier)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap64)
+RESOLVER_UP_MP(OSAtomicCompareAndSwap64Barrier)
+RESOLVER_UP_MP(OSAtomicAdd32)
+RESOLVER_UP_MP(OSAtomicAdd32Barrier)
+RESOLVER_UP_MP(OSAtomicAdd64)
+RESOLVER_UP_MP(OSAtomicAdd64Barrier)
+RESOLVER_UP_MP(OSAtomicTestAndSet)
+RESOLVER_UP_MP(OSAtomicTestAndSetBarrier)
+RESOLVER_UP_MP(OSAtomicTestAndClear)
+RESOLVER_UP_MP(OSAtomicTestAndClearBarrier)
+++ /dev/null
-/*
- * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-/* Copyright 1998 Apple Computer, Inc. */
-
-#include <architecture/i386/asm_help.h>
-
-#define __APPLE_API_PRIVATE
-#include <machine/cpu_capabilities.h>
-#undef __APPLE_API_PRIVATE
-
-LABEL(___commpage_gettimeofday)
- movq $(_COMM_PAGE_GETTIMEOFDAY),%rax
- jmp *%rax
--- /dev/null
+/*
+ * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+#define NSEC_PER_SEC 1000*1000*1000
+#define NSEC_PER_USEC 1000
+
+ .private_extern ___commpage_gettimeofday
+ .align 4, 0x90
+___commpage_gettimeofday:
+// %rdi = ptr to timeval
+ pushq %rbp // set up a frame for backtraces
+ pushq %r12 // push callee-saved registers we want to use
+ pushq %r13
+ pushq %r14
+ movq %rsp,%rbp
+ movq %rdi,%r12 // save ptr to timeval
+ movq $(_COMM_PAGE_TIME_DATA_START),%r13
+0:
+ movl _GTOD_GENERATION(%r13),%r14d // get generation (0 if disabled)
+ testl %r14d,%r14d // disabled?
+ jz 4f
+
+ call _mach_absolute_time // get %rax <- nanotime()
+
+ movl _GTOD_SEC_BASE(%r13),%r8d // get _COMM_PAGE_TIMESTAMP
+ subq _GTOD_NS_BASE(%r13),%rax // generate nanoseconds since timestamp
+ cmpl _GTOD_GENERATION(%r13),%r14d // has data changed out from under us?
+ jne 0b
+
+ movl $ NSEC_PER_SEC,%ecx
+ movq %rax,%rdx
+ shrq $32,%rdx // get high half of delta in %edx
+ divl %ecx // %eax <- seconds since timestamp, %edx <- nanoseconds
+ addl %eax,%r8d // add seconds elapsed to timestamp seconds
+
+ movl $ NSEC_PER_USEC,%ecx
+ movl %edx,%eax
+ xorl %edx,%edx
+ divl %ecx // divide residual ns by 1000 to get residual us in %eax
+
+ movq %r8,(%r12) // store 64-bit seconds into timeval
+ movl %eax,8(%r12) // store 32-bit useconds into timeval
+ xorl %eax,%eax // return 0 for success
+3:
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbp
+ ret
+4: // fail
+ movl $1,%eax
+ jmp 3b
--- /dev/null
+/*
+ * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+
+/*
+ * 64-bit version _mach_absolute_time. We return the 64-bit nanotime in %rax,
+ */
+ .globl _mach_absolute_time
+_mach_absolute_time:
+ pushq %rbp // set up a frame for backtraces
+ movq %rsp,%rbp
+ movq $(_COMM_PAGE_TIME_DATA_START),%rsi
+1:
+ movl _NT_GENERATION(%rsi),%r8d // get generation
+ testl %r8d,%r8d // if 0, data is being changed...
+ jz 1b // ...so loop until stable
+ lfence
+ rdtsc // edx:eax := tsc
+ lfence
+ shlq $32,%rdx // rax := ((edx << 32) | eax), ie 64-bit tsc
+ orq %rdx,%rax
+ subq _NT_TSC_BASE(%rsi), %rax // rax := (tsc - base_tsc)
+ movl _NT_SCALE(%rsi),%ecx
+ mulq %rcx // rdx:rax := (tsc - base_tsc) * scale
+ shrdq $32,%rdx,%rax // _COMM_PAGE_NT_SHIFT is always 32
+ addq _NT_NS_BASE(%rsi),%rax // (((tsc - base_tsc) * scale) >> 32) + ns_base
+
+ cmpl _NT_GENERATION(%rsi),%r8d // did the data change during computation?
+ jne 1b
+ popq %rbp
+ ret
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 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 <machine/cpu_capabilities.h>
+#include <platfunc.h>
+
+#define RESOLVER_UP_MP(symbol) \
+ PLATFUNC_DESCRIPTOR_PROTOTYPE(symbol, up); \
+ PLATFUNC_DESCRIPTOR_PROTOTYPE(symbol, mp); \
+ static const platfunc_descriptor* symbol ## _platfunc_descriptors[] = { \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, mp), \
+ PLATFUNC_DESCRIPTOR_REFERENCE(symbol, up), \
+ 0 \
+ }; \
+ void* symbol ## _chooser() __asm__("_" #symbol); \
+ void* symbol ## _chooser() { \
+ __asm__(".symbol_resolver _" #symbol); \
+ return find_platform_function((const platfunc_descriptor**) symbol ## _platfunc_descriptors); \
+ }
+
+RESOLVER_UP_MP(OSSpinLockTry)
+RESOLVER_UP_MP(_spin_lock_try)
+RESOLVER_UP_MP(OSSpinLockLock)
+RESOLVER_UP_MP(_spin_lock)
+RESOLVER_UP_MP(spin_lock)
--- /dev/null
+/*
+ * Copyright (c) 2003-2009 Apple, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * 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_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <sys/appleapiopts.h>
+#include <machine/cpu_capabilities.h>
+#include <platfunc.h>
+#include <mach/i386/syscall_sw.h>
+
+PLATFUNC_FUNCTION_START(OSSpinLockTry, up, 64, 4)
+PLATFUNC_FUNCTION_START(_spin_lock_try, up, 64, 4)
+ xorl %eax, %eax
+ orl $-1, %edx
+ cmpxchgl %edx, (%rdi)
+ setz %dl
+ movzbl %dl, %eax
+ ret
+PLATFUNC_DESCRIPTOR(OSSpinLockTry,up,kUP,0)
+PLATFUNC_DESCRIPTOR(_spin_lock_try,up,kUP,0)
+
+
+PLATFUNC_FUNCTION_START_GENERIC(OSSpinLockTry, mp, 64, 4)
+PLATFUNC_FUNCTION_START_GENERIC(_spin_lock_try, mp, 64, 4)
+ xorl %eax, %eax
+ orl $-1, %edx
+ lock
+ cmpxchgl %edx, (%rdi)
+ setz %dl
+ movzbl %dl, %eax
+ ret
+PLATFUNC_DESCRIPTOR(OSSpinLockTry,mp,0,kUP)
+PLATFUNC_DESCRIPTOR(_spin_lock_try,mp,0,kUP)
+
+
+PLATFUNC_FUNCTION_START(OSSpinLockLock, up, 64, 4)
+PLATFUNC_FUNCTION_START(_spin_lock, up, 64, 4)
+PLATFUNC_FUNCTION_START(spin_lock, up, 64, 4)
+ movq %rdi,%r8
+0:
+ xorl %eax, %eax
+ orl $-1, %edx
+ cmpxchgl %edx, (%r8)
+ jnz 1f
+ ret
+1:
+ /* failed to get lock so relinquish the processor immediately on UP */
+ xorl %edi,%edi /* THREAD_NULL */
+ movl $1,%esi /* SWITCH_OPTION_DEPRESS */
+ movl $1,%edx /* 1 ms */
+ movl $(SYSCALL_CONSTRUCT_MACH(61)),%eax /* 61 = thread_switch */
+ syscall
+ jmp 0b
+PLATFUNC_DESCRIPTOR(OSSpinLockLock,up,kUP,0)
+PLATFUNC_DESCRIPTOR(_spin_lock,up,kUP,0)
+PLATFUNC_DESCRIPTOR(spin_lock,up,kUP,0)
+
+
+PLATFUNC_FUNCTION_START_GENERIC(OSSpinLockLock, mp, 64, 4)
+PLATFUNC_FUNCTION_START_GENERIC(_spin_lock, mp, 64, 4)
+PLATFUNC_FUNCTION_START_GENERIC(spin_lock, mp, 64, 4)
+ movq %rdi,%r8
+0:
+ xorl %eax, %eax
+ orl $-1, %edx
+ lock
+ cmpxchgl %edx, (%r8)
+ jnz 1f
+ ret
+1:
+ xorl %eax, %eax
+ movl $(MP_SPIN_TRIES), %edx
+2: /* spin for awhile before relinquish */
+ pause
+ cmpl %eax, (%r8)
+ jz 0b
+ decl %edx
+ jnz 2b
+ /* failed to get lock after spinning so relinquish */
+ xorl %edi,%edi /* THREAD_NULL */
+ movl $1,%esi /* SWITCH_OPTION_DEPRESS */
+ movl $1,%edx /* 1 ms */
+ movl $(SYSCALL_CONSTRUCT_MACH(61)),%eax /* 61 = thread_switch */
+ syscall
+ jmp 0b
+PLATFUNC_DESCRIPTOR(OSSpinLockLock,mp,0,kUP)
+PLATFUNC_DESCRIPTOR(_spin_lock,mp,0,kUP)
+PLATFUNC_DESCRIPTOR(spin_lock,mp,0,kUP)
+
+// void OSSpinLockUnlock( OSSpinLock *lock );
+ .align 2, 0x90
+ .globl _OSSpinLockUnlock
+ .globl _spin_unlock
+ .globl __spin_unlock
+_OSSpinLockUnlock:
+_spin_unlock:
+__spin_unlock:
+ movl $0, (%rdi)
+ ret
+