summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2009-09-17 16:16:44 +0000
committerdes <des@FreeBSD.org>2009-09-17 16:16:44 +0000
commit9ed1a4b5ebe734049aa444f14884ed8ad4c23aee (patch)
treedea5b87c905a5175efdc56037f61b7ecb2031d98 /lib/libc
parent5f4ee8bdfb4e4ffae101ac65837e519f1f957e43 (diff)
parent74dba11aaa299f71f2bf2b583d74575fec440e7b (diff)
downloadFreeBSD-src-9ed1a4b5ebe734049aa444f14884ed8ad4c23aee.zip
FreeBSD-src-9ed1a4b5ebe734049aa444f14884ed8ad4c23aee.tar.gz
Merge from head
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/Makefile3
-rw-r--r--lib/libc/Versions.def12
-rw-r--r--lib/libc/arm/Makefile.inc2
-rw-r--r--lib/libc/arm/gen/_setjmp.S8
-rw-r--r--lib/libc/arm/gen/setjmp.S8
-rw-r--r--lib/libc/arm/stdlib/Makefile.inc4
-rw-r--r--lib/libc/arm/string/strncmp.S13
-rw-r--r--lib/libc/db/README8
-rw-r--r--lib/libc/db/Symbol.map6
-rw-r--r--lib/libc/db/btree/bt_close.c10
-rw-r--r--lib/libc/db/btree/bt_conv.c13
-rw-r--r--lib/libc/db/btree/bt_debug.c52
-rw-r--r--lib/libc/db/btree/bt_delete.c110
-rw-r--r--lib/libc/db/btree/bt_get.c6
-rw-r--r--lib/libc/db/btree/bt_open.c54
-rw-r--r--lib/libc/db/btree/bt_overflow.c18
-rw-r--r--lib/libc/db/btree/bt_page.c10
-rw-r--r--lib/libc/db/btree/bt_put.c45
-rw-r--r--lib/libc/db/btree/bt_search.c29
-rw-r--r--lib/libc/db/btree/bt_seq.c53
-rw-r--r--lib/libc/db/btree/bt_split.c63
-rw-r--r--lib/libc/db/btree/bt_utils.c28
-rw-r--r--lib/libc/db/btree/btree.h4
-rw-r--r--lib/libc/db/db/db.c29
-rw-r--r--lib/libc/db/hash/README5
-rw-r--r--lib/libc/db/hash/hash.c161
-rw-r--r--lib/libc/db/hash/hash.h34
-rw-r--r--lib/libc/db/hash/hash_bigkey.c118
-rw-r--r--lib/libc/db/hash/hash_buf.c72
-rw-r--r--lib/libc/db/hash/hash_func.c106
-rw-r--r--lib/libc/db/hash/hash_log2.c8
-rw-r--r--lib/libc/db/hash/hash_page.c182
-rw-r--r--lib/libc/db/hash/page.h2
-rw-r--r--lib/libc/db/man/mpool.332
-rw-r--r--lib/libc/db/mpool/Makefile.inc2
-rw-r--r--lib/libc/db/mpool/mpool-compat.c (renamed from lib/libc/i386/stdlib/labs.S)38
-rw-r--r--lib/libc/db/mpool/mpool.c157
-rw-r--r--lib/libc/db/recno/rec_close.c16
-rw-r--r--lib/libc/db/recno/rec_delete.c22
-rw-r--r--lib/libc/db/recno/rec_get.c34
-rw-r--r--lib/libc/db/recno/rec_open.c11
-rw-r--r--lib/libc/db/recno/rec_put.c34
-rw-r--r--lib/libc/db/recno/rec_search.c27
-rw-r--r--lib/libc/db/recno/rec_seq.c7
-rw-r--r--lib/libc/db/recno/rec_utils.c16
-rw-r--r--lib/libc/gen/Makefile.inc8
-rw-r--r--lib/libc/gen/Symbol.map55
-rw-r--r--lib/libc/gen/dlfcn.c8
-rw-r--r--lib/libc/gen/dlfunc.c30
-rw-r--r--lib/libc/gen/dlopen.318
-rw-r--r--lib/libc/gen/fmtcheck.c12
-rw-r--r--lib/libc/gen/ftok.36
-rw-r--r--lib/libc/gen/fts.c4
-rw-r--r--lib/libc/gen/getcap.c12
-rw-r--r--lib/libc/gen/initgroups.37
-rw-r--r--lib/libc/gen/initgroups.c21
-rw-r--r--lib/libc/gen/lockf.39
-rw-r--r--lib/libc/gen/lockf.c14
-rw-r--r--lib/libc/gen/popen.c2
-rw-r--r--lib/libc/gen/pw_scan.c25
-rw-r--r--lib/libc/gen/semctl.c30
-rw-r--r--lib/libc/gen/tcgetsid.33
-rw-r--r--lib/libc/gen/tcsetsid.392
-rw-r--r--lib/libc/gen/termios.c12
-rw-r--r--lib/libc/gen/ttyname.35
-rw-r--r--lib/libc/i386/stdlib/Makefile.inc2
-rw-r--r--lib/libc/i386/stdlib/div.S2
-rw-r--r--lib/libc/i386/stdlib/ldiv.S2
-rw-r--r--lib/libc/i386/sys/Makefile.inc7
-rw-r--r--lib/libc/ia64/stdlib/Makefile.inc3
-rw-r--r--lib/libc/include/compat.h48
-rw-r--r--lib/libc/mips/stdlib/Makefile.inc4
-rw-r--r--lib/libc/net/getaddrinfo.c287
-rw-r--r--lib/libc/net/nsdispatch.c27
-rw-r--r--lib/libc/net/rcmd.31
-rw-r--r--lib/libc/net/resolver.315
-rw-r--r--lib/libc/net/sourcefilter.397
-rw-r--r--lib/libc/net/sourcefilter.c34
-rw-r--r--lib/libc/nls/Makefile.inc25
-rw-r--r--lib/libc/nls/be_BY.UTF-8.msg249
-rw-r--r--lib/libc/nls/ca_ES.ISO8859-1.msg267
-rw-r--r--lib/libc/nls/de_DE.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/el_GR.ISO8859-7.msg249
-rw-r--r--lib/libc/nls/es_ES.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/fi_FI.ISO8859-1.msg233
-rw-r--r--lib/libc/nls/fr_FR.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/hu_HU.ISO8859-2.msg249
-rw-r--r--lib/libc/nls/it_IT.ISO8859-15.msg231
-rw-r--r--lib/libc/nls/mn_MN.UTF-8.msg249
-rw-r--r--lib/libc/nls/nl_NL.ISO8859-1.msg267
-rw-r--r--lib/libc/nls/no_NO.ISO8859-1.msg231
-rw-r--r--lib/libc/nls/pt_BR.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/sk_SK.ISO8859-2.msg267
-rw-r--r--lib/libc/nls/sv_SE.ISO8859-1.msg233
-rw-r--r--lib/libc/nls/uk_UA.UTF-8.msg249
-rw-r--r--lib/libc/posix1e/Makefile.inc40
-rw-r--r--lib/libc/posix1e/Symbol.map23
-rw-r--r--lib/libc/posix1e/acl.374
-rw-r--r--lib/libc/posix1e/acl_add_flag_np.398
-rw-r--r--lib/libc/posix1e/acl_add_perm.344
-rw-r--r--lib/libc/posix1e/acl_branding.c166
-rw-r--r--lib/libc/posix1e/acl_calc_mask.c9
-rw-r--r--lib/libc/posix1e/acl_clear_flags_np.379
-rw-r--r--lib/libc/posix1e/acl_compat.c59
-rw-r--r--lib/libc/posix1e/acl_copy.c18
-rw-r--r--lib/libc/posix1e/acl_create_entry.318
-rw-r--r--lib/libc/posix1e/acl_delete.c6
-rw-r--r--lib/libc/posix1e/acl_delete_entry.322
-rw-r--r--lib/libc/posix1e/acl_delete_entry.c100
-rw-r--r--lib/libc/posix1e/acl_delete_flag_np.384
-rw-r--r--lib/libc/posix1e/acl_entry.c51
-rw-r--r--lib/libc/posix1e/acl_flag.c155
-rw-r--r--lib/libc/posix1e/acl_from_text.c224
-rw-r--r--lib/libc/posix1e/acl_from_text_nfs4.c312
-rw-r--r--lib/libc/posix1e/acl_get.315
-rw-r--r--lib/libc/posix1e/acl_get.c51
-rw-r--r--lib/libc/posix1e/acl_get_brand_np.386
-rw-r--r--lib/libc/posix1e/acl_get_entry_type_np.380
-rw-r--r--lib/libc/posix1e/acl_get_flag_np.394
-rw-r--r--lib/libc/posix1e/acl_get_flagset_np.383
-rw-r--r--lib/libc/posix1e/acl_init.c23
-rw-r--r--lib/libc/posix1e/acl_is_trivial_np.384
-rw-r--r--lib/libc/posix1e/acl_set.320
-rw-r--r--lib/libc/posix1e/acl_set.c92
-rw-r--r--lib/libc/posix1e/acl_set_entry_type_np.395
-rw-r--r--lib/libc/posix1e/acl_set_flagset_np.385
-rw-r--r--lib/libc/posix1e/acl_set_qualifier.32
-rw-r--r--lib/libc/posix1e/acl_set_tag_type.324
-rw-r--r--lib/libc/posix1e/acl_strip.c200
-rw-r--r--lib/libc/posix1e/acl_strip_np.3109
-rw-r--r--lib/libc/posix1e/acl_support.c125
-rw-r--r--lib/libc/posix1e/acl_support.h19
-rw-r--r--lib/libc/posix1e/acl_support_nfs4.c256
-rw-r--r--lib/libc/posix1e/acl_to_text.328
-rw-r--r--lib/libc/posix1e/acl_to_text.c43
-rw-r--r--lib/libc/posix1e/acl_to_text_nfs4.c266
-rw-r--r--lib/libc/posix1e/acl_valid.c8
-rw-r--r--lib/libc/posix1e/mac.3153
-rw-r--r--lib/libc/posix1e/mac_free.39
-rw-r--r--lib/libc/posix1e/mac_get.31
-rw-r--r--lib/libc/posix1e/mac_set.31
-rw-r--r--lib/libc/posix1e/mac_text.31
-rw-r--r--lib/libc/posix1e/posix1e.3118
-rw-r--r--lib/libc/regex/engine.c5
-rw-r--r--lib/libc/regex/grot/tests3
-rw-r--r--lib/libc/resolv/res_comp.c4
-rw-r--r--lib/libc/rpc/auth_unix.c18
-rw-r--r--lib/libc/rpc/clnt_bcast.c2
-rw-r--r--lib/libc/rpc/getnetconfig.c64
-rw-r--r--lib/libc/rpc/netname.c3
-rw-r--r--lib/libc/rpc/netnamer.c10
-rw-r--r--lib/libc/rpc/svc_dg.c130
-rw-r--r--lib/libc/softfloat/fpgetmask.c9
-rw-r--r--lib/libc/softfloat/fpgetround.c9
-rw-r--r--lib/libc/softfloat/fpgetsticky.c9
-rw-r--r--lib/libc/softfloat/fpsetmask.c9
-rw-r--r--lib/libc/softfloat/fpsetround.c9
-rw-r--r--lib/libc/softfloat/fpsetsticky.c9
-rw-r--r--lib/libc/sparc64/stdlib/Makefile.inc1
-rw-r--r--lib/libc/stdio/Makefile.inc17
-rw-r--r--lib/libc/stdio/Symbol.map7
-rw-r--r--lib/libc/stdio/asprintf.c65
-rw-r--r--lib/libc/stdio/dprintf.c46
-rw-r--r--lib/libc/stdio/fgetln.31
-rw-r--r--lib/libc/stdio/fgets.33
-rw-r--r--lib/libc/stdio/findfp.c13
-rw-r--r--lib/libc/stdio/fopen.32
-rw-r--r--lib/libc/stdio/fread.c4
-rw-r--r--lib/libc/stdio/fwrite.c9
-rw-r--r--lib/libc/stdio/getdelim.c160
-rw-r--r--lib/libc/stdio/getline.3164
-rw-r--r--lib/libc/stdio/getline.c39
-rw-r--r--lib/libc/stdio/printf-pos.c17
-rw-r--r--lib/libc/stdio/printf.3103
-rw-r--r--lib/libc/stdio/printflocal.h2
-rw-r--r--lib/libc/stdio/stdio.36
-rw-r--r--lib/libc/stdio/vdprintf.c66
-rw-r--r--lib/libc/stdio/vfprintf.c19
-rw-r--r--lib/libc/stdio/vfwprintf.c20
-rw-r--r--lib/libc/stdlib/Makefile.inc4
-rw-r--r--lib/libc/stdlib/atol.32
-rw-r--r--lib/libc/stdlib/malloc.c9
-rw-r--r--lib/libc/stdlib/ptsname.330
-rw-r--r--lib/libc/stdtime/asctime.c106
-rw-r--r--lib/libc/stdtime/difftime.c98
-rw-r--r--lib/libc/stdtime/localtime.c768
-rw-r--r--lib/libc/stdtime/private.h154
-rw-r--r--lib/libc/stdtime/strftime.c114
-rw-r--r--lib/libc/stdtime/strptime.c28
-rw-r--r--lib/libc/stdtime/time2posix.33
-rw-r--r--lib/libc/stdtime/tzfile.522
-rw-r--r--lib/libc/stdtime/tzfile.h62
-rw-r--r--lib/libc/string/Makefile.inc21
-rw-r--r--lib/libc/string/Symbol.map7
-rw-r--r--lib/libc/string/memchr.35
-rw-r--r--lib/libc/string/memcmp.33
-rw-r--r--lib/libc/string/memcpy.33
-rw-r--r--lib/libc/string/memmove.33
-rw-r--r--lib/libc/string/memset.33
-rw-r--r--lib/libc/string/stpcpy.c2
-rw-r--r--lib/libc/string/stpncpy.c45
-rw-r--r--lib/libc/string/strcasecmp.33
-rw-r--r--lib/libc/string/strcat.33
-rw-r--r--lib/libc/string/strchr.33
-rw-r--r--lib/libc/string/strcmp.33
-rw-r--r--lib/libc/string/strcpy.342
-rw-r--r--lib/libc/string/strdup.35
-rw-r--r--lib/libc/string/strlcat.c2
-rw-r--r--lib/libc/string/strlcpy.37
-rw-r--r--lib/libc/string/strlcpy.c2
-rw-r--r--lib/libc/string/strlen.329
-rw-r--r--lib/libc/string/strmode.34
-rw-r--r--lib/libc/string/strmode.c2
-rw-r--r--lib/libc/string/strnlen.c42
-rw-r--r--lib/libc/string/strpbrk.33
-rw-r--r--lib/libc/string/strspn.33
-rw-r--r--lib/libc/string/strstr.33
-rw-r--r--lib/libc/string/wcpcpy.c (renamed from lib/libc/i386/stdlib/abs.S)33
-rw-r--r--lib/libc/string/wcpncpy.c45
-rw-r--r--lib/libc/string/wcscasecmp.c45
-rw-r--r--lib/libc/string/wcsncasecmp.c49
-rw-r--r--lib/libc/string/wcsnlen.c42
-rw-r--r--lib/libc/string/wmemchr.332
-rw-r--r--lib/libc/sys/Makefile.inc15
-rw-r--r--lib/libc/sys/Symbol.map23
-rw-r--r--lib/libc/sys/bind.23
-rw-r--r--lib/libc/sys/close.21
-rw-r--r--lib/libc/sys/closefrom.253
-rw-r--r--lib/libc/sys/execve.211
-rw-r--r--lib/libc/sys/getgroups.210
-rw-r--r--lib/libc/sys/getrlimit.29
-rw-r--r--lib/libc/sys/getsockopt.29
-rw-r--r--lib/libc/sys/intro.24
-rw-r--r--lib/libc/sys/jail.2311
-rw-r--r--lib/libc/sys/kqueue.254
-rw-r--r--lib/libc/sys/link.22
-rw-r--r--lib/libc/sys/mmap.211
-rw-r--r--lib/libc/sys/msgctl.2 (renamed from lib/libc/gen/msgctl.3)28
-rw-r--r--lib/libc/sys/msgget.2 (renamed from lib/libc/gen/msgget.3)12
-rw-r--r--lib/libc/sys/msgrcv.2 (renamed from lib/libc/gen/msgrcv.3)10
-rw-r--r--lib/libc/sys/msgsnd.2 (renamed from lib/libc/gen/msgsnd.3)8
-rw-r--r--lib/libc/sys/open.216
-rw-r--r--lib/libc/sys/pathconf.231
-rw-r--r--lib/libc/sys/ptrace.220
-rw-r--r--lib/libc/sys/revoke.23
-rw-r--r--lib/libc/sys/sctp_generic_recvmsg.22
-rw-r--r--lib/libc/sys/sctp_generic_sendmsg.24
-rw-r--r--lib/libc/sys/sctp_peeloff.22
-rw-r--r--lib/libc/sys/semctl.23
-rw-r--r--lib/libc/sys/setfib.22
-rw-r--r--lib/libc/sys/setgroups.26
-rw-r--r--lib/libc/sys/shmctl.25
-rw-r--r--lib/libc/sys/stack_protector.c11
253 files changed, 11587 insertions, 2365 deletions
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 2d97fbe..4f13f8e 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -16,6 +16,7 @@ SHLIB_MAJOR= 7
WARNS?= 2
CFLAGS+=-I${.CURDIR}/include -I${.CURDIR}/../../include
CFLAGS+=-I${.CURDIR}/${MACHINE_ARCH}
+CFLAGS+=-DNLS
CLEANFILES+=tags
INSTALL_PIC_ARCHIVE=
PRECIOUSLIB=
@@ -25,7 +26,7 @@ PRECIOUSLIB=
#
DPADD+= ${LIBGCC}
LDFLAGS+= -nodefaultlibs
-LDADD+= -lgcc
+LDADD+= -lgcc -lssp_nonshared
# Define (empty) variables so that make doesn't give substitution
# errors if the included makefiles don't change these:
diff --git a/lib/libc/Versions.def b/lib/libc/Versions.def
index a17e0a5..da0ca6f 100644
--- a/lib/libc/Versions.def
+++ b/lib/libc/Versions.def
@@ -1,5 +1,11 @@
# $FreeBSD$
+#
+# Note: Whenever bumping the FBSD version, always make
+# FBSDprivate_1.0 depend on the new FBSD version.
+# This will keep it at the end of the dependency chain.
+#
+
# This is our first version; it depends on no other.
# This version was first added to 7.0-current.
FBSD_1.0 {
@@ -9,6 +15,10 @@ FBSD_1.0 {
FBSD_1.1 {
} FBSD_1.0;
+# This version was first added to 9.0-current.
+FBSD_1.2 {
+} FBSD_1.1;
+
# This is our private namespace. Any global interfaces that are
# strictly for use only by other FreeBSD applications and libraries
# are listed here. We use a separate namespace so we can write
@@ -16,4 +26,4 @@ FBSD_1.1 {
#
# Please do NOT increment the version of this namespace.
FBSDprivate_1.0 {
-} FBSD_1.1;
+} FBSD_1.2;
diff --git a/lib/libc/arm/Makefile.inc b/lib/libc/arm/Makefile.inc
index 666cadc..4c72e56 100644
--- a/lib/libc/arm/Makefile.inc
+++ b/lib/libc/arm/Makefile.inc
@@ -5,8 +5,6 @@
SOFTFLOAT_BITS=32
-CFLAGS+=-DSOFTFLOAT
-
# Long double is just double precision.
MDSRCS+=machdep_ldisd.c
SYM_MAPS+=${.CURDIR}/arm/Symbol.map
diff --git a/lib/libc/arm/gen/_setjmp.S b/lib/libc/arm/gen/_setjmp.S
index 1cd370c..6594afb 100644
--- a/lib/libc/arm/gen/_setjmp.S
+++ b/lib/libc/arm/gen/_setjmp.S
@@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
ENTRY(_setjmp)
ldr r1, .L_setjmp_magic
str r1, [r0], #4
-#ifdef SOFTFLOAT
+#ifdef __SOFTFP__
add r0, r0, #52
#else
/* Store fp registers */
@@ -59,7 +59,7 @@ ENTRY(_setjmp)
/* Store fpsr */
rfs r1
str r1, [r0], #0x0004
-#endif /* SOFTFLOAT */
+#endif /* __SOFTFP__ */
/* Store integer registers */
stmia r0, {r4-r14}
@@ -76,7 +76,7 @@ ENTRY(_longjmp)
teq r2, r3
bne botch
-#ifdef SOFTFLOAT
+#ifdef __SOFTFP__
add r0, r0, #52
#else
/* Restore fp registers */
@@ -84,7 +84,7 @@ ENTRY(_longjmp)
/* Restore fpsr */
ldr r4, [r0], #0x0004
wfs r4
-#endif /* SOFTFLOAT */
+#endif /* __SOFTFP__ */
/* Restore integer registers */
ldmia r0, {r4-r14}
diff --git a/lib/libc/arm/gen/setjmp.S b/lib/libc/arm/gen/setjmp.S
index f0e9cfa..e5f581f 100644
--- a/lib/libc/arm/gen/setjmp.S
+++ b/lib/libc/arm/gen/setjmp.S
@@ -58,7 +58,7 @@ ENTRY(setjmp)
ldr r1, .Lsetjmp_magic
str r1, [r0], #4
-#ifdef SOFTFLOAT
+#ifdef __SOFTFP__
add r0, r0, #52
#else
/* Store fp registers */
@@ -66,7 +66,7 @@ ENTRY(setjmp)
/* Store fpsr */
rfs r1
str r1, [r0], #0x0004
-#endif /*SOFTFLOAT*/
+#endif /* __SOFTFP__ */
/* Store integer registers */
stmia r0, {r4-r14}
mov r0, #0x00000000
@@ -98,7 +98,7 @@ ENTRY(__longjmp)
ldmfd sp!, {r0, r1, r14}
add r0, r0, #4
-#ifdef SOFTFLOAT
+#ifdef __SOFTFP__
add r0, r0, #52
#else
/* Restore fp registers */
@@ -106,7 +106,7 @@ ENTRY(__longjmp)
/* Restore FPSR */
ldr r4, [r0], #0x0004
wfs r4
-#endif /* SOFTFLOAT */
+#endif /* __SOFTFP__ */
/* Restore integer registers */
ldmia r0, {r4-r14}
diff --git a/lib/libc/arm/stdlib/Makefile.inc b/lib/libc/arm/stdlib/Makefile.inc
deleted file mode 100644
index 1814a0a..0000000
--- a/lib/libc/arm/stdlib/Makefile.inc
+++ /dev/null
@@ -1,4 +0,0 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
-# $FreeBSD$
-
-MDSRCS+=abs.c div.c labs.c ldiv.c
diff --git a/lib/libc/arm/string/strncmp.S b/lib/libc/arm/string/strncmp.S
index d172264..fce0159 100644
--- a/lib/libc/arm/string/strncmp.S
+++ b/lib/libc/arm/string/strncmp.S
@@ -33,13 +33,16 @@
__FBSDID("$FreeBSD$");
ENTRY(strncmp)
-/* if ((len - 1) < 0) return 0 */
- subs r2, r2, #1
- movmi r0, #0
- movmi pc, lr
+/* if (len == 0) return 0 */
+ cmp r2, #0
+ moveq r0, #0
+ moveq pc, lr
/* ip == last src address to compare */
- add ip, r0, r2
+ adds ip, r0, r2
+/* Use last possible address on overflow. */
+ movcs ip, #0
+ sub ip, ip, #1
1:
ldrb r2, [r0], #1
ldrb r3, [r1], #1
diff --git a/lib/libc/db/README b/lib/libc/db/README
index bed2c92..1f9ae72 100644
--- a/lib/libc/db/README
+++ b/lib/libc/db/README
@@ -1,4 +1,5 @@
# @(#)README 8.27 (Berkeley) 9/1/94
+# $FreeBSD$
This is version 1.85 of the Berkeley DB code.
@@ -31,10 +32,3 @@ mpool The memory pool routines.
recno The fixed/variable length record routines.
test Test package.
-============================================
-Debugging:
-
-If you're running a memory checker (e.g. Purify) on DB, make sure that
-you recompile it with "-DPURIFY" in the CFLAGS, first. By default,
-allocated pages are not initialized by the DB code, and they will show
-up as reads of uninitialized memory in the buffer write routines.
diff --git a/lib/libc/db/Symbol.map b/lib/libc/db/Symbol.map
index 14df29f..225fd40 100644
--- a/lib/libc/db/Symbol.map
+++ b/lib/libc/db/Symbol.map
@@ -16,7 +16,6 @@ FBSD_1.0 {
dbm_dirfno;
mpool_open;
mpool_filter;
- mpool_new;
mpool_get;
mpool_put;
mpool_close;
@@ -24,6 +23,11 @@ FBSD_1.0 {
mpool_stat;
};
+FBSD_1.1 {
+ mpool_new;
+ mpool_delete;
+};
+
FBSDprivate_1.0 {
__bt_open;
__dbpanic;
diff --git a/lib/libc/db/btree/bt_close.c b/lib/libc/db/btree/bt_close.c
index 46abf07..1f85992 100644
--- a/lib/libc/db/btree/bt_close.c
+++ b/lib/libc/db/btree/bt_close.c
@@ -61,8 +61,7 @@ static int bt_meta(BTREE *);
* RET_ERROR, RET_SUCCESS
*/
int
-__bt_close(dbp)
- DB *dbp;
+__bt_close(DB *dbp)
{
BTREE *t;
int fd;
@@ -116,9 +115,7 @@ __bt_close(dbp)
* 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;
@@ -159,8 +156,7 @@ __bt_sync(dbp, flags)
* RET_ERROR, RET_SUCCESS
*/
static int
-bt_meta(t)
- BTREE *t;
+bt_meta(BTREE *t)
{
BTMETA m;
void *p;
diff --git a/lib/libc/db/btree/bt_conv.c b/lib/libc/db/btree/bt_conv.c
index 1f13faa..ba4a38b 100644
--- a/lib/libc/db/btree/bt_conv.c
+++ b/lib/libc/db/btree/bt_conv.c
@@ -56,10 +56,7 @@ static void mswap(PAGE *);
* 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;
@@ -124,10 +121,7 @@ __bt_pgin(t, pg, pp)
}
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;
@@ -198,8 +192,7 @@ __bt_pgout(t, pg, pp)
* p: page to convert
*/
static void
-mswap(pg)
- PAGE *pg;
+mswap(PAGE *pg)
{
char *p;
diff --git a/lib/libc/db/btree/bt_debug.c b/lib/libc/db/btree/bt_debug.c
index 19ccaca..dc8b83d 100644
--- a/lib/libc/db/btree/bt_debug.c
+++ b/lib/libc/db/btree/bt_debug.c
@@ -53,8 +53,7 @@ __FBSDID("$FreeBSD$");
* dbp: pointer to the DB
*/
void
-__bt_dump(dbp)
- DB *dbp;
+__bt_dump(DB *dbp)
{
BTREE *t;
PAGE *h;
@@ -62,7 +61,7 @@ __bt_dump(dbp)
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);
@@ -84,10 +83,9 @@ __bt_dump(dbp)
}
#undef X
- for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+ for (i = P_ROOT;
+ (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
__bt_dpage(h);
- (void)mpool_put(t->bt_mp, h, 0);
- }
}
/*
@@ -97,8 +95,7 @@ __bt_dump(dbp)
* h: pointer to the PAGE
*/
void
-__bt_dmpage(h)
- PAGE *h;
+__bt_dmpage(PAGE *h)
{
BTMETA *m;
char *sep;
@@ -131,18 +128,14 @@ __bt_dmpage(h)
* 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;
t = dbp->internal;
- if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) {
+ if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL)
__bt_dpage(h);
- (void)mpool_put(t->bt_mp, h, 0);
- }
}
/*
@@ -152,8 +145,7 @@ __bt_dnpage(dbp, pgno)
* h: pointer to the PAGE
*/
void
-__bt_dpage(h)
- PAGE *h;
+__bt_dpage(PAGE *h)
{
BINTERNAL *bi;
BLEAF *bl;
@@ -162,7 +154,7 @@ __bt_dpage(h)
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) { \
@@ -179,7 +171,7 @@ __bt_dpage(h)
(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;
@@ -249,8 +241,7 @@ __bt_dpage(h)
* 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;
@@ -263,7 +254,8 @@ __bt_stat(dbp)
t = dbp->internal;
pcont = pinternal = pleaf = 0;
nkeys = ifree = lfree = 0;
- for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+ for (i = P_ROOT;
+ (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
switch (h->flags & P_TYPE) {
case P_BINTERNAL:
case P_RINTERNAL:
@@ -280,45 +272,41 @@ __bt_stat(dbp)
++pcont;
break;
}
- (void)mpool_put(t->bt_mp, h, 0);
- }
/* Count the levels of the tree. */
for (i = P_ROOT, levels = 0 ;; ++levels) {
- h = mpool_get(t->bt_mp, i, 0);
+ h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN);
if (h->flags & (P_BLEAF|P_RLEAF)) {
if (levels == 0)
levels = 1;
- (void)mpool_put(t->bt_mp, h, 0);
break;
}
i = F_ISSET(t, R_RECNO) ?
GETRINTERNAL(h, 0)->pgno :
GETBINTERNAL(h, 0)->pgno;
- (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)
diff --git a/lib/libc/db/btree/bt_delete.c b/lib/libc/db/btree/bt_delete.c
index f520f78..aa191b6 100644
--- a/lib/libc/db/btree/bt_delete.c
+++ b/lib/libc/db/btree/bt_delete.c
@@ -58,10 +58,7 @@ static int __bt_stkacq(BTREE *, PAGE **, CURSOR *);
* 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;
@@ -139,20 +136,17 @@ __bt_delete(dbp, key, flags)
* 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.
@@ -186,8 +180,8 @@ __bt_stkacq(t, hp, c)
/* 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);
@@ -196,7 +190,7 @@ __bt_stkacq(t, hp, c)
/* 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);
@@ -206,7 +200,7 @@ __bt_stkacq(t, hp, c)
/* 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)
@@ -241,8 +235,8 @@ __bt_stkacq(t, hp, c)
/* 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);
@@ -251,7 +245,7 @@ __bt_stkacq(t, hp, c)
/* 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. */
@@ -261,14 +255,14 @@ __bt_stkacq(t, hp, c)
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);
@@ -286,9 +280,7 @@ ret: mpool_put(t->bt_mp, h, 0);
* 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;
@@ -373,14 +365,12 @@ loop: if ((e = __bt_search(t, key, &exact)) == NULL)
* 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;
@@ -400,9 +390,9 @@ __bt_pdelete(t, h)
/* 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 &&
@@ -416,7 +406,7 @@ __bt_pdelete(t, h)
* 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;
@@ -426,7 +416,7 @@ __bt_pdelete(t, h)
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;
@@ -434,11 +424,11 @@ __bt_pdelete(t, h)
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);
}
@@ -463,17 +453,13 @@ __bt_pdelete(t, h)
* 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;
@@ -484,12 +470,12 @@ __bt_dleaf(t, key, h, index)
/* 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 &&
@@ -503,18 +489,18 @@ __bt_dleaf(t, key, h, index)
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);
@@ -528,17 +514,13 @@ __bt_dleaf(t, key, h, index)
* 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;
@@ -561,7 +543,7 @@ __bt_curdel(t, key, h, index)
*/
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);
@@ -569,25 +551,25 @@ __bt_curdel(t, key, h, index)
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;
@@ -599,7 +581,7 @@ __bt_curdel(t, key, h, index)
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;
@@ -615,7 +597,7 @@ dup2: c->pg.pgno = e.page->pgno;
}
}
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);
@@ -633,9 +615,7 @@ dup2: c->pg.pgno = e.page->pgno;
* h: page to be deleted
*/
static int
-__bt_relink(t, h)
- BTREE *t;
- PAGE *h;
+__bt_relink(BTREE *t, PAGE *h)
{
PAGE *pg;
diff --git a/lib/libc/db/btree/bt_get.c b/lib/libc/db/btree/bt_get.c
index 95d8e00..77fae30 100644
--- a/lib/libc/db/btree/bt_get.c
+++ b/lib/libc/db/btree/bt_get.c
@@ -58,11 +58,7 @@ __FBSDID("$FreeBSD$");
* 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;
diff --git a/lib/libc/db/btree/bt_open.c b/lib/libc/db/btree/bt_open.c
index 92ac140..47f3646 100644
--- a/lib/libc/db/btree/bt_open.c
+++ b/lib/libc/db/btree/bt_open.c
@@ -87,10 +87,7 @@ static int tmp(void);
*
*/
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;
@@ -99,7 +96,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
DB *dbp;
pgno_t ncache;
ssize_t nr;
- int machine_lorder;
+ int machine_lorder, saved_errno;
t = NULL;
@@ -159,9 +156,8 @@ __bt_open(fname, flags, mode, openinfo, dflags)
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;
@@ -169,9 +165,8 @@ __bt_open(fname, flags, mode, openinfo, dflags)
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);
@@ -200,7 +195,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
default:
goto einval;
}
-
+
if ((t->bt_fd = _open(fname, flags, mode)) < 0)
goto err;
@@ -330,13 +325,15 @@ einval: errno = EINVAL;
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);
}
@@ -350,24 +347,30 @@ err: if (t) {
* RET_ERROR, RET_SUCCESS
*/
static int
-nroot(t)
- BTREE *t;
+nroot(BTREE *t)
{
PAGE *meta, *root;
pgno_t npg;
- if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) {
- mpool_put(t->bt_mp, meta, 0);
- return (RET_SUCCESS);
+ if ((root = mpool_get(t->bt_mp, 1, 0)) != NULL) {
+ if (root->lower == 0 &&
+ root->pgno == 0 &&
+ root->linp[0] == 0) {
+ mpool_delete(t->bt_mp, root);
+ errno = EINVAL;
+ } else {
+ mpool_put(t->bt_mp, root, 0);
+ return (RET_SUCCESS);
+ }
}
if (errno != EINVAL) /* It's OK to not exist. */
return (RET_ERROR);
errno = 0;
- if ((meta = mpool_new(t->bt_mp, &npg)) == NULL)
+ if ((meta = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
return (RET_ERROR);
- if ((root = mpool_new(t->bt_mp, &npg)) == NULL)
+ if ((root = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
return (RET_ERROR);
if (npg != P_ROOT)
@@ -384,17 +387,21 @@ nroot(t)
}
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);
@@ -405,7 +412,7 @@ tmp()
}
static int
-byteorder()
+byteorder(void)
{
u_int32_t x;
u_char *p;
@@ -423,8 +430,7 @@ byteorder()
}
int
-__bt_fd(dbp)
- const DB *dbp;
+__bt_fd(const DB *dbp)
{
BTREE *t;
diff --git a/lib/libc/db/btree/bt_overflow.c b/lib/libc/db/btree/bt_overflow.c
index 4058ca9..266d599 100644
--- a/lib/libc/db/btree/bt_overflow.c
+++ b/lib/libc/db/btree/bt_overflow.c
@@ -75,12 +75,7 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -97,7 +92,7 @@ __ovfl_get(t, p, ssz, buf, bufsz)
#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;
@@ -134,10 +129,7 @@ __ovfl_get(t, p, ssz, buf, bufsz)
* 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;
@@ -188,9 +180,7 @@ __ovfl_put(t, dbt, pg)
* RET_ERROR, RET_SUCCESS
*/
int
-__ovfl_delete(t, p)
- BTREE *t;
- void *p;
+__ovfl_delete(BTREE *t, void *p)
{
PAGE *h;
pgno_t pg;
diff --git a/lib/libc/db/btree/bt_page.c b/lib/libc/db/btree/bt_page.c
index 67aedf6..ab5e359 100644
--- a/lib/libc/db/btree/bt_page.c
+++ b/lib/libc/db/btree/bt_page.c
@@ -55,9 +55,7 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -81,9 +79,7 @@ __bt_free(t, h)
* 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;
@@ -94,5 +90,5 @@ __bt_new(t, npg)
F_SET(t, B_METADIRTY);
return (h);
}
- return (mpool_new(t->bt_mp, npg));
+ return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT));
}
diff --git a/lib/libc/db/btree/bt_put.c b/lib/libc/db/btree/bt_put.c
index f1416e7..e4016c0 100644
--- a/lib/libc/db/btree/bt_put.c
+++ b/lib/libc/db/btree/bt_put.c
@@ -62,17 +62,13 @@ static EPG *bt_fast(BTREE *, const DBT *, const DBT *, int *);
* 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;
@@ -103,7 +99,7 @@ __bt_put(dbp, key, data, flags)
*/
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:
@@ -153,7 +149,7 @@ storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
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;
}
@@ -165,7 +161,7 @@ storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
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
@@ -187,7 +183,7 @@ storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
* 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);
}
@@ -201,37 +197,37 @@ delete: if (__bt_dleaf(t, key, h, index) == 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;
@@ -261,13 +257,10 @@ u_long bt_cache_hit, bt_cache_miss;
* 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;
@@ -285,7 +278,7 @@ bt_fast(t, key, data, exactp)
* 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) {
diff --git a/lib/libc/db/btree/bt_search.c b/lib/libc/db/btree/bt_search.c
index 9413e6e..15ef1fa 100644
--- a/lib/libc/db/btree/bt_search.c
+++ b/lib/libc/db/btree/bt_search.c
@@ -61,13 +61,10 @@ static int __bt_sprev(BTREE *, PAGE *, const DBT *, int *);
* 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;
@@ -79,7 +76,7 @@ __bt_search(t, key, exactp)
/* 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;
@@ -88,7 +85,7 @@ __bt_search(t, key, exactp)
goto next;
}
if (cmp > 0) {
- base = index + 1;
+ base = idx + 1;
--lim;
}
}
@@ -124,10 +121,10 @@ __bt_search(t, key, exactp)
* 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);
}
}
@@ -146,11 +143,7 @@ next: BT_PUSH(t, h->pgno, index);
* 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;
@@ -185,11 +178,7 @@ __bt_snext(t, h, key, exactp)
* 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;
diff --git a/lib/libc/db/btree/bt_seq.c b/lib/libc/db/btree/bt_seq.c
index 51cd6e9..1928951 100644
--- a/lib/libc/db/btree/bt_seq.c
+++ b/lib/libc/db/btree/bt_seq.c
@@ -72,10 +72,7 @@ static int __bt_seqset(BTREE *, EPG *, DBT *, int);
* 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;
@@ -147,11 +144,7 @@ __bt_seq(dbp, key, data, flags)
* 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;
@@ -235,14 +228,11 @@ __bt_seqset(t, ep, key, flags)
* 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;
@@ -268,7 +258,7 @@ __bt_seqadv(t, ep, flags)
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) {
@@ -280,15 +270,15 @@ __bt_seqadv(t, ep, 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. */
@@ -303,22 +293,22 @@ usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE);
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);
}
@@ -337,11 +327,7 @@ usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE);
* 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;
@@ -362,7 +348,7 @@ __bt_first(t, key, erval, exactp)
*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
@@ -435,13 +421,10 @@ __bt_first(t, key, erval, exactp)
* 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) {
@@ -453,6 +436,6 @@ __bt_setcur(t, pgno, index)
/* 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);
}
diff --git a/lib/libc/db/btree/bt_split.c b/lib/libc/db/btree/bt_split.c
index dc27917..ca8b16a 100644
--- a/lib/libc/db/btree/bt_split.c
+++ b/lib/libc/db/btree/bt_split.c
@@ -31,7 +31,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94";
+static char sccsid[] = "@(#)bt_split.c 8.10 (Berkeley) 1/9/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -47,10 +47,10 @@ __FBSDID("$FreeBSD$");
#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 *);
@@ -74,13 +74,8 @@ u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
* 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;
@@ -154,7 +149,7 @@ __bt_split(t, sp, key, data, flags, ilen, argskip)
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.
*/
@@ -210,7 +205,7 @@ __bt_split(t, sp, key, data, flags, ilen, argskip)
}
/* 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) :
@@ -336,11 +331,7 @@ err2: mpool_put(t->bt_mp, l, 0);
* 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;
@@ -381,13 +372,10 @@ bt_page(t, h, lp, rp, skip, ilen)
}
/* 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;
@@ -441,11 +429,7 @@ bt_page(t, h, lp, rp, skip, ilen)
* 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;
@@ -488,9 +472,7 @@ bt_root(t, h, lp, rp, skip, ilen)
* 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;
@@ -528,9 +510,7 @@ bt_rroot(t, h, l, r)
* 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;
@@ -605,11 +585,7 @@ bt_broot(t, h, l, r)
* 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;
@@ -668,8 +644,8 @@ bt_psplit(t, h, l, r, pskip, ilen)
* where we decide to try and copy too much onto the left page.
* Make sure that doesn't happen.
*/
- if ((skip <= off && used + nbytes + sizeof(indx_t) >= full)
- || nxt == top - 1) {
+ if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) ||
+ nxt == top - 1) {
--off;
break;
}
@@ -783,9 +759,7 @@ bt_psplit(t, h, l, r, pskip, ilen)
* RET_SUCCESS, RET_ERROR.
*/
static int
-bt_preserve(t, pg)
- BTREE *t;
- pgno_t pg;
+bt_preserve(BTREE *t, pgno_t pg)
{
PAGE *h;
@@ -811,8 +785,7 @@ bt_preserve(t, pg)
* 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;
diff --git a/lib/libc/db/btree/bt_utils.c b/lib/libc/db/btree/bt_utils.c
index e32854f..92b76ba 100644
--- a/lib/libc/db/btree/bt_utils.c
+++ b/lib/libc/db/btree/bt_utils.c
@@ -62,11 +62,7 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -88,8 +84,7 @@ __bt_ret(t, e, key, rkey, data, rdata, copy)
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;
@@ -115,9 +110,7 @@ dataonly:
} 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;
@@ -148,10 +141,7 @@ dataonly:
* > 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;
@@ -203,7 +193,7 @@ __bt_cmp(t, k1, e)
*
* Parameters:
* a: DBT #1
- * b: DBT #2
+ * b: DBT #2
*
* Returns:
* < 0 if a is < b
@@ -211,8 +201,7 @@ __bt_cmp(t, k1, e)
* > 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;
@@ -235,14 +224,13 @@ __bt_defcmp(a, b)
*
* 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;
diff --git a/lib/libc/db/btree/btree.h b/lib/libc/db/btree/btree.h
index 7d16462..a1766dc 100644
--- a/lib/libc/db/btree/btree.h
+++ b/lib/libc/db/btree/btree.h
@@ -309,8 +309,8 @@ typedef struct _btree {
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)
diff --git a/lib/libc/db/db/db.c b/lib/libc/db/db/db.c
index 287def0..3cfd0a9 100644
--- a/lib/libc/db/db/db.c
+++ b/lib/libc/db/db/db.c
@@ -42,18 +42,16 @@ __FBSDID("$FreeBSD$");
#include <db.h>
+static int __dberr(void);
+
DB *
-dbopen(fname, flags, mode, type, openinfo)
- const char *fname;
- int flags, mode;
- DBTYPE type;
- const void *openinfo;
+dbopen(const char *fname, int flags, int mode, DBTYPE type, const void *openinfo)
{
#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN)
#define USE_OPEN_FLAGS \
- (O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \
- O_RDWR | O_SHLOCK | O_TRUNC)
+ (O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW | O_NONBLOCK | \
+ O_RDONLY | O_RDWR | O_SHLOCK | O_SYNC | O_TRUNC)
if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
switch (type) {
@@ -72,7 +70,7 @@ dbopen(fname, flags, mode, type, openinfo)
}
static int
-__dberr()
+__dberr(void)
{
return (RET_ERROR);
}
@@ -84,14 +82,13 @@ __dberr()
* dbp: pointer to the DB structure.
*/
void
-__dbpanic(dbp)
- DB *dbp;
+__dbpanic(DB *dbp)
{
/* The only thing that can succeed is a close. */
- dbp->del = (int (*)())__dberr;
- dbp->fd = (int (*)())__dberr;
- dbp->get = (int (*)())__dberr;
- dbp->put = (int (*)())__dberr;
- dbp->seq = (int (*)())__dberr;
- dbp->sync = (int (*)())__dberr;
+ dbp->del = (int (*)(const struct __db *, const DBT*, u_int))__dberr;
+ dbp->fd = (int (*)(const struct __db *))__dberr;
+ dbp->get = (int (*)(const struct __db *, const DBT*, DBT *, u_int))__dberr;
+ dbp->put = (int (*)(const struct __db *, DBT *, const DBT *, u_int))__dberr;
+ dbp->seq = (int (*)(const struct __db *, DBT *, DBT *, u_int))__dberr;
+ dbp->sync = (int (*)(const struct __db *, u_int))__dberr;
}
diff --git a/lib/libc/db/hash/README b/lib/libc/db/hash/README
index f29ccf7..80d6743 100644
--- a/lib/libc/db/hash/README
+++ b/lib/libc/db/hash/README
@@ -1,4 +1,5 @@
# @(#)README 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
This package implements a superset of the hsearch and dbm/ndbm libraries.
@@ -44,10 +45,6 @@ Test Programs:
NOTES:
-The file search.h is provided for using the hsearch compatible interface
-on BSD systems. On System V derived systems, search.h should appear in
-/usr/include.
-
The man page ../man/db.3 explains the interface to the hashing system.
The file hash.ps is a postscript copy of a paper explaining
the history, implementation, and performance of the hash package.
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
index 6b71d4a..83d2657 100644
--- a/lib/libc/db/hash/hash.c
+++ b/lib/libc/db/hash/hash.c
@@ -92,11 +92,11 @@ int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
/************************** 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;
@@ -120,25 +120,15 @@ __hash_open(file, flags, mode, info, dflags)
*/
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, info)))
RETURN_ERROR(errno, error1);
@@ -164,7 +154,7 @@ __hash_open(file, flags, mode, info, dflags)
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
@@ -173,7 +163,6 @@ __hash_open(file, flags, mode, info, dflags)
*/
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
@@ -249,8 +238,7 @@ error0:
}
static int
-hash_close(dbp)
- DB *dbp;
+hash_close(DB *dbp)
{
HTAB *hashp;
int retval;
@@ -265,8 +253,7 @@ hash_close(dbp)
}
static int
-hash_fd(dbp)
- const DB *dbp;
+hash_fd(const DB *dbp)
{
HTAB *hashp;
@@ -283,10 +270,7 @@ hash_fd(dbp)
/************************** LOCAL CREATION ROUTINES **********************/
static HTAB *
-init_hash(hashp, file, info)
- HTAB *hashp;
- const char *file;
- const HASHINFO *info;
+init_hash(HTAB *hashp, const char *file, const HASHINFO *info)
{
struct stat statbuf;
int nelem;
@@ -350,12 +334,9 @@ init_hash(hashp, file, info)
* 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
@@ -396,8 +377,7 @@ init_htab(hashp, nelem)
* structure, freeing all allocated space.
*/
static int
-hdestroy(hashp)
- HTAB *hashp;
+hdestroy(HTAB *hashp)
{
int i, save_errno;
@@ -436,6 +416,10 @@ hdestroy(hashp)
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);
@@ -456,9 +440,7 @@ hdestroy(hashp)
* -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;
@@ -485,8 +467,7 @@ hash_sync(dbp, flags)
* -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
@@ -506,8 +487,7 @@ flush_meta(hashp)
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)) {
@@ -533,11 +513,7 @@ flush_meta(hashp)
* -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;
@@ -550,18 +526,13 @@ hash_get(dbp, key, data, flag)
}
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) {
@@ -573,10 +544,8 @@ hash_put(dbp, key, data, flag)
}
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;
@@ -596,10 +565,7 @@ hash_delete(dbp, key, flag)
* 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;
@@ -725,10 +691,7 @@ found:
}
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;
@@ -748,7 +711,7 @@ hash_seq(dbp, key, data, flag)
hashp->cndx = 1;
hashp->cpage = NULL;
}
-
+next_bucket:
for (bp = NULL; !bp || !bp[0]; ) {
if (!(bufp = hashp->cpage)) {
for (bucket = hashp->cbucket;
@@ -763,12 +726,22 @@ hash_seq(dbp, key, data, flag)
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 || flag == 0) {
+ hashp->cndx += 2;
+ if (hashp->cndx > bp[0]) {
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ hashp->cndx = 1;
+ goto next_bucket;
+ }
+ }
+ }
#ifdef DEBUG
assert(bp);
@@ -792,17 +765,12 @@ hash_seq(dbp, key, data, flag)
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);
}
@@ -814,9 +782,8 @@ hash_seq(dbp, key, data, flag)
* 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;
@@ -870,9 +837,7 @@ __expand_table(hashp)
* 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;
@@ -885,13 +850,10 @@ hash_realloc(p_ptr, oldsize, newsize)
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;
@@ -906,9 +868,7 @@ __call_hash(hashp, k, len)
* Returns 0 on success
*/
static int
-alloc_segs(hashp, nsegs)
- HTAB *hashp;
- int nsegs;
+alloc_segs(HTAB *hashp, int nsegs)
{
int i;
SEGMENT store;
@@ -922,15 +882,18 @@ alloc_segs(hashp, nsegs)
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);
}
@@ -940,8 +903,7 @@ alloc_segs(hashp, nsegs)
* 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;
@@ -969,8 +931,7 @@ swap_header_copy(srcp, destp)
}
static void
-swap_header(hashp)
- HTAB *hashp;
+swap_header(HTAB *hashp)
{
HASHHDR *hdrp;
int i;
diff --git a/lib/libc/db/hash/hash.h b/lib/libc/db/hash/hash.h
index 66f86aa..8329413 100644
--- a/lib/libc/db/hash/hash.h
+++ b/lib/libc/db/hash/hash.h
@@ -60,28 +60,28 @@ typedef BUFHEAD **SEGMENT;
/* 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;
diff --git a/lib/libc/db/hash/hash_bigkey.c b/lib/libc/db/hash/hash_bigkey.c
index 3a28ae5..c1914a5 100644
--- a/lib/libc/db/hash/hash_bigkey.c
+++ b/lib/libc/db/hash/hash_bigkey.c
@@ -82,14 +82,12 @@ static int collect_data(HTAB *, BUFHEAD *, int, int);
* 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;
@@ -120,18 +118,30 @@ __big_insert(hashp, bufp, key, val)
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;
@@ -182,10 +192,8 @@ __big_insert(hashp, bufp, key, val)
* 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;
@@ -243,12 +251,12 @@ __big_delete(hashp, bufp)
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--;
@@ -261,13 +269,8 @@ __big_delete(hashp, bufp)
* -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;
@@ -313,10 +316,8 @@ __find_bigpair(hashp, bufp, ndx, key, size)
* 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;
@@ -354,13 +355,8 @@ __find_last_page(hashp, bpp)
* 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;
@@ -429,8 +425,8 @@ __big_return(hashp, bufp, ndx, val, set_current)
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. */
@@ -446,10 +442,7 @@ __big_return(hashp, bufp, ndx, val, set_current)
* 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;
@@ -501,15 +494,11 @@ collect_data(hashp, bufp, len, set)
/*
* 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);
@@ -520,12 +509,7 @@ __big_keydata(hashp, bufp, key, val, set)
* 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;
@@ -564,23 +548,19 @@ collect_key(hashp, bufp, len, val, set)
* 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;
@@ -592,7 +572,7 @@ __big_split(hashp, op, np, big_keyp, addr, obucket, ret)
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;
diff --git a/lib/libc/db/hash/hash_buf.c b/lib/libc/db/hash/hash_buf.c
index db8ad1a..4445fc5 100644
--- a/lib/libc/db/hash/hash_buf.c
+++ b/lib/libc/db/hash/hash_buf.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#ifdef DEBUG
#include <assert.h>
@@ -98,12 +99,10 @@ static BUFHEAD *newbuf(HTAB *, u_int32_t, BUFHEAD *);
* 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;
@@ -154,10 +153,7 @@ __get_buf(hashp, addr, prev_bp, newpage)
* 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 */
@@ -168,24 +164,38 @@ newbuf(hashp, addr, prev_bp)
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 {
@@ -272,7 +282,7 @@ newbuf(hashp, addr, prev_bp)
*/
#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;
@@ -283,10 +293,8 @@ newbuf(hashp, addr, prev_bp)
return (bp);
}
-extern void
-__buf_init(hashp, nbytes)
- HTAB *hashp;
- int nbytes;
+void
+__buf_init(HTAB *hashp, int nbytes)
{
BUFHEAD *bfp;
int npages;
@@ -308,10 +316,8 @@ __buf_init(hashp, nbytes)
*/
}
-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;
@@ -328,8 +334,10 @@ __buf_free(hashp, do_free, to_disk)
}
/* 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;
@@ -339,10 +347,8 @@ __buf_free(hashp, do_free, to_disk)
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;
diff --git a/lib/libc/db/hash/hash_func.c b/lib/libc/db/hash/hash_func.c
index 2ca0a48..db32a75 100644
--- a/lib/libc/db/hash/hash_func.c
+++ b/lib/libc/db/hash/hash_func.c
@@ -43,60 +43,57 @@ __FBSDID("$FreeBSD$");
#include "page.h"
#include "extern.h"
+#ifdef notdef
static u_int32_t hash1(const void *, size_t) __unused;
static u_int32_t hash2(const void *, size_t) __unused;
static u_int32_t hash3(const void *, size_t) __unused;
+#endif
static u_int32_t hash4(const void *, size_t);
-/* Global default hash function */
+/* Default hash function. */
u_int32_t (*__default_hash)(const void *, size_t) = hash4;
+#ifdef notdef
/*
- * HASH FUNCTIONS
- *
* Assume that we've already split the bucket to which this key hashes,
* calculate that bucket, and check that in fact we did already split it.
*
- * This came from ejb's hsearch.
+ * EJB's original hsearch hash.
*/
-
#define PRIME1 37
#define PRIME2 1048583
-static u_int32_t
-hash1(keyarg, len)
- const void *keyarg;
- size_t len;
+u_int32_t
+hash1(const void *key, size_t len)
{
- const u_char *key;
u_int32_t h;
+ u_int8_t *k;
+ h = 0;
+ k = (u_int8_t *)key;
/* Convert string to integer */
- for (key = keyarg, h = 0; len--;)
- h = h * PRIME1 ^ (*key++ - ' ');
+ while (len--)
+ h = h * PRIME1 ^ (*k++ - ' ');
h %= PRIME2;
return (h);
}
/*
- * Phong's linear congruential hash
+ * Phong Vo's linear congruential hash
*/
#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
-static u_int32_t
-hash2(keyarg, len)
- const void *keyarg;
- size_t len;
+u_int32_t
+hash2(const void *key, size_t len)
{
- const u_char *e, *key;
u_int32_t h;
- u_char c;
+ u_int8_t *e, c, *k;
- key = keyarg;
- e = key + len;
- for (h = 0; key != e;) {
- c = *key++;
- if (!c && key > e)
+ k = (u_int8_t *)key;
+ e = k + len;
+ for (h = 0; k != e;) {
+ c = *k++;
+ if (!c && k > e)
break;
dcharhash(h, c);
}
@@ -110,101 +107,84 @@ hash2(keyarg, len)
* all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
* this routine is heavily used enough, it's worth the ugly coding.
*
- * OZ's original sdbm hash
+ * Ozan Yigit's original sdbm hash.
*/
-static u_int32_t
-hash3(keyarg, len)
- const void *keyarg;
- size_t len;
+u_int32_t
+hash3(const void *key, size_t len)
{
- const u_char *key;
- size_t loop;
- u_int32_t h;
+ u_int32_t n, loop;
+ u_int8_t *k;
-#define HASHC h = *key++ + 65599 * h
+#define HASHC n = *k++ + 65599 * n
- h = 0;
- key = keyarg;
+ n = 0;
+ k = (u_int8_t *)key;
if (len > 0) {
loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
- do {
+ do { /* All fall throughs */
HASHC;
- /* FALLTHROUGH */
case 7:
HASHC;
- /* FALLTHROUGH */
case 6:
HASHC;
- /* FALLTHROUGH */
case 5:
HASHC;
- /* FALLTHROUGH */
case 4:
HASHC;
- /* FALLTHROUGH */
case 3:
HASHC;
- /* FALLTHROUGH */
case 2:
HASHC;
- /* FALLTHROUGH */
case 1:
HASHC;
} while (--loop);
}
+
}
- return (h);
+ return (n);
}
+#endif /* notdef */
-/* Hash function from Chris Torek. */
-static u_int32_t
-hash4(keyarg, len)
- const void *keyarg;
- size_t len;
+/* Chris Torek's hash function. */
+u_int32_t
+hash4(const void *key, size_t len)
{
- const u_char *key;
- size_t loop;
- u_int32_t h;
+ u_int32_t h, loop;
+ const u_int8_t *k;
-#define HASH4a h = (h << 5) - h + *key++;
-#define HASH4b h = (h << 5) + h + *key++;
+#define HASH4a h = (h << 5) - h + *k++;
+#define HASH4b h = (h << 5) + h + *k++;
#define HASH4 HASH4b
h = 0;
- key = keyarg;
+ k = key;
if (len > 0) {
loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
- do {
+ do { /* All fall throughs */
HASH4;
- /* FALLTHROUGH */
case 7:
HASH4;
- /* FALLTHROUGH */
case 6:
HASH4;
- /* FALLTHROUGH */
case 5:
HASH4;
- /* FALLTHROUGH */
case 4:
HASH4;
- /* FALLTHROUGH */
case 3:
HASH4;
- /* FALLTHROUGH */
case 2:
HASH4;
- /* FALLTHROUGH */
case 1:
HASH4;
} while (--loop);
}
+
}
return (h);
}
diff --git a/lib/libc/db/hash/hash_log2.c b/lib/libc/db/hash/hash_log2.c
index cbbfdc8..0586aa7 100644
--- a/lib/libc/db/hash/hash_log2.c
+++ b/lib/libc/db/hash/hash_log2.c
@@ -36,13 +36,13 @@ static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
-
#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;
diff --git a/lib/libc/db/hash/hash_page.c b/lib/libc/db/hash/hash_page.c
index daeb18e..fa01775 100644
--- a/lib/libc/db/hash/hash_page.c
+++ b/lib/libc/db/hash/hash_page.c
@@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$");
*/
#include "namespace.h"
-#include <sys/types.h>
+#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
@@ -72,14 +72,13 @@ __FBSDID("$FreeBSD$");
#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; \
@@ -93,9 +92,7 @@ static int ugly_split
* 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;
@@ -124,15 +121,11 @@ putpair(p, key, val)
* 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];
@@ -162,6 +155,14 @@ __delpair(hashp, bufp, ndx)
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;
@@ -177,10 +178,8 @@ __delpair(hashp, bufp, ndx)
* 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;
@@ -274,17 +273,17 @@ __split_page(hashp, obucket, nbucket)
* -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;
@@ -394,11 +393,8 @@ ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
* 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;
@@ -416,17 +412,22 @@ __addel(hashp, bufp, key, val)
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);
@@ -443,6 +444,7 @@ __addel(hashp, bufp, 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,
@@ -461,13 +463,10 @@ __addel(hashp, bufp, key, val)
* 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
@@ -514,15 +513,11 @@ __add_ovflpage(hashp, bufp)
* 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;
@@ -536,8 +531,7 @@ __get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
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)
@@ -574,15 +568,10 @@ __get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
* 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))
@@ -590,8 +579,7 @@ __put_page(hashp, p, bucket, is_bucket, is_bitmap)
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 */
@@ -607,8 +595,7 @@ __put_page(hashp, p, bucket, is_bucket, is_bitmap)
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) {
@@ -623,10 +610,8 @@ __put_page(hashp, p, bucket, is_bucket, is_bitmap)
* 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;
@@ -647,8 +632,7 @@ __ibitmap(hashp, pnum, nbits, ndx)
}
static u_int32_t
-first_free(map)
- u_int32_t map;
+first_free(u_int32_t map)
{
u_int32_t i, mask;
@@ -662,8 +646,7 @@ first_free(map)
}
static u_int16_t
-overflow_page(hashp)
- HTAB *hashp;
+overflow_page(HTAB *hashp)
{
u_int32_t *freep;
int max_free, offset, splitnum;
@@ -713,6 +696,7 @@ overflow_page(hashp)
if (offset > SPLITMASK) {
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
@@ -726,6 +710,7 @@ overflow_page(hashp)
free_page++;
if (free_page >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
/*
@@ -751,6 +736,7 @@ overflow_page(hashp)
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG,
sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
@@ -794,8 +780,11 @@ found:
/* 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",
@@ -809,10 +798,8 @@ found:
/*
* 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;
@@ -856,17 +843,27 @@ __free_ovflpage(hashp, obufp)
* -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 >= (int)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);
@@ -878,9 +875,7 @@ open_temp(hashp)
* 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;
@@ -905,9 +900,7 @@ squeeze_key(sp, key, val)
}
static u_int32_t *
-fetch_bitmap(hashp, ndx)
- HTAB *hashp;
- int ndx;
+fetch_bitmap(HTAB *hashp, int ndx)
{
if (ndx >= hashp->nmaps)
return (NULL);
@@ -923,8 +916,7 @@ fetch_bitmap(hashp, ndx)
#ifdef DEBUG4
int
-print_chain(addr)
- int addr;
+print_chain(int addr)
{
BUFHEAD *bufp;
short *bp, oaddr;
diff --git a/lib/libc/db/hash/page.h b/lib/libc/db/hash/page.h
index 8155035..6959fe8 100644
--- a/lib/libc/db/hash/page.h
+++ b/lib/libc/db/hash/page.h
@@ -48,7 +48,7 @@
* +--------+---------------------+
* | F R E E A R E A |
* +--------------+---------------+
- * | <---- - - - | data |
+ * | <---- - - - | data |
* +--------+-----+----+----------+
* | key | data | key |
* +--------+----------+----------+
diff --git a/lib/libc/db/man/mpool.3 b/lib/libc/db/man/mpool.3
index e9918a9..3de51c3 100644
--- a/lib/libc/db/man/mpool.3
+++ b/lib/libc/db/man/mpool.3
@@ -28,7 +28,7 @@
.\" @(#)mpool.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd February 25, 1999
.Dt MPOOL 3
.Os
.Sh NAME
@@ -47,7 +47,9 @@
.Fa "void *pgcookie"
.Fc
.Ft void *
-.Fn mpool_new "MPOOL *mp" "pgno_t *pgnoaddr"
+.Fn mpool_new "MPOOL *mp" "pgno_t *pgnoaddr" "u_int flags"
+.Ft int
+.Fn mpool_delete "MPOOL *mp" "void *page"
.Ft void *
.Fn mpool_get "MPOOL *mp" "pgno_t pgno" "u_int flags"
.Ft int
@@ -99,11 +101,11 @@ Both functions are called with the
.Fa pgcookie
pointer, the page number and a pointer to the page to being read or written.
.Pp
-The
+The function
.Fn mpool_new
-function takes an
-.Ft MPOOL
-pointer and an address as arguments.
+takes an
+.Dv MPOOL
+pointer, an address, and a set of flags as arguments.
If a new page can be allocated, a pointer to the page is returned and
the page number is stored into the
.Fa pgnoaddr
@@ -113,6 +115,24 @@ Otherwise,
is returned and
.Va errno
is set.
+The flags value is formed by
+.Tn OR Ns 'ing
+the following values:
+.Bl -tag -width Ds
+.It Dv MPOOL_PAGE_REQUEST
+Allocate a new page with a specific page number.
+.It Dv MPOOL_PAGE_NEXT
+Allocate a new page with the next page number.
+.El
+.Pp
+The function
+.Fn mpool_delete
+deletes the specified page from a pool and frees the page.
+It takes an
+.Dv MPOOL
+pointer and a page as arguments.
+The page must have been generated by
+.Fn mpool_new .
.Pp
The
.Fn mpool_get
diff --git a/lib/libc/db/mpool/Makefile.inc b/lib/libc/db/mpool/Makefile.inc
index 9fef712..832e54d 100644
--- a/lib/libc/db/mpool/Makefile.inc
+++ b/lib/libc/db/mpool/Makefile.inc
@@ -3,4 +3,4 @@
.PATH: ${.CURDIR}/db/mpool
-SRCS+= mpool.c
+SRCS+= mpool.c mpool-compat.c
diff --git a/lib/libc/i386/stdlib/labs.S b/lib/libc/db/mpool/mpool-compat.c
index 5e00b7a..9df76ff 100644
--- a/lib/libc/i386/stdlib/labs.S
+++ b/lib/libc/db/mpool/mpool-compat.c
@@ -1,10 +1,7 @@
/*-
- * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2009 Xin LI <delphij@FreeBSD.org>
* All rights reserved.
*
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,14 +10,11 @@
* 2. Redistributions in binary form must 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
+ * 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)
@@ -28,20 +22,22 @@
* 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)
- .text
- .asciz "@(#)abs.s 5.2 (Berkeley) 12/17/90"
-#endif /* LIBC_SCCS and not lint */
-#include <machine/asm.h>
+#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <db.h>
+#include <mpool.h>
+
+void *__mpool_new__44bsd(MPOOL *, pgno_t *);
+
+void *
+__mpool_new__44bsd(MPOOL *mp, pgno_t *pgnoaddr)
+{
+
+ return (mpool_new(mp, pgnoaddr, MPOOL_PAGE_NEXT));
+}
-ENTRY(labs)
- movl 4(%esp),%eax
- testl %eax,%eax
- jns 1f
- negl %eax
-1: ret
-END(labs)
+__sym_compat(mpool_new, __mpool_new_44bsd, FBSD_1.0);
diff --git a/lib/libc/db/mpool/mpool.c b/lib/libc/db/mpool/mpool.c
index aedf1fd..c3a19e0 100644
--- a/lib/libc/db/mpool/mpool.c
+++ b/lib/libc/db/mpool/mpool.c
@@ -28,7 +28,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94";
+static char sccsid[] = "@(#)mpool.c 8.7 (Berkeley) 11/2/95";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -58,11 +58,9 @@ static int mpool_write(MPOOL *, BKT *);
* 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;
@@ -99,11 +97,8 @@ mpool_open(key, fd, pagesize, maxcache)
* 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;
@@ -115,9 +110,7 @@ mpool_filter(mp, pgin, pgout, pgcookie)
* Get a new page of memory.
*/
void *
-mpool_new(mp, pgnoaddr)
- MPOOL *mp;
- pgno_t *pgnoaddr;
+mpool_new(MPOOL *mp, pgno_t *pgnoaddr, u_int flags)
{
struct _hqh *head;
BKT *bp;
@@ -136,8 +129,13 @@ mpool_new(mp, pgnoaddr)
*/
if ((bp = mpool_bkt(mp)) == NULL)
return (NULL);
- *pgnoaddr = bp->pgno = mp->npages++;
- bp->flags = MPOOL_PINNED;
+ if (flags == MPOOL_PAGE_REQUEST) {
+ mp->npages++;
+ bp->pgno = *pgnoaddr;
+ } else
+ bp->pgno = *pgnoaddr = mp->npages++;
+
+ bp->flags = MPOOL_PINNED | MPOOL_INUSE;
head = &mp->hqh[HASHKEY(bp->pgno)];
TAILQ_INSERT_HEAD(head, bp, hq);
@@ -145,27 +143,46 @@ mpool_new(mp, pgnoaddr)
return (bp->page);
}
+int
+mpool_delete(MPOOL *mp, void *page)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ bp = (BKT *)((char *)page - sizeof(BKT));
+
+#ifdef DEBUG
+ if (!(bp->flags & MPOOL_PINNED)) {
+ (void)fprintf(stderr,
+ "mpool_delete: page %d not pinned\n", bp->pgno);
+ abort();
+ }
+#endif
+
+ /* Remove from the hash and lru queues. */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_REMOVE(head, bp, hq);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+
+ free(bp);
+ mp->curcache--;
+ return (RET_SUCCESS);
+}
+
/*
* 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;
off_t off;
int nr;
- /* Check for attempt to retrieve a non-existent page. */
- if (pgno >= mp->npages) {
- errno = EINVAL;
- return (NULL);
- }
-
#ifdef STATISTICS
++mp->pageget;
#endif
@@ -173,7 +190,7 @@ mpool_get(mp, pgno, flags)
/* Check for a page that is cached. */
if ((bp = mpool_look(mp, pgno)) != NULL) {
#ifdef DEBUG
- if (bp->flags & MPOOL_PINNED) {
+ if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) {
(void)fprintf(stderr,
"mpool_get: page %d already pinned\n", bp->pgno);
abort();
@@ -199,20 +216,38 @@ mpool_get(mp, pgno, flags)
return (NULL);
/* Read in the contents. */
+ off = mp->pagesize * pgno;
+ if ((nr = pread(mp->fd, bp->page, mp->pagesize, off)) != (ssize_t)mp->pagesize) {
+ switch (nr) {
+ case -1:
+ /* errno is set for us by pread(). */
+ free(bp);
+ mp->curcache--;
+ return (NULL);
+ case 0:
+ /*
+ * A zero-length read means you need to create a
+ * new page.
+ */
+ memset(bp->page, 0, mp->pagesize);
+ break;
+ default:
+ /* A partial read is definitely bad. */
+ free(bp);
+ mp->curcache--;
+ errno = EINVAL;
+ return (NULL);
+ }
+ }
#ifdef STATISTICS
++mp->pageread;
#endif
- off = mp->pagesize * pgno;
- nr = pread(mp->fd, bp->page, mp->pagesize, off);
- if (nr != mp->pagesize) {
- if (nr >= 0)
- errno = EFTYPE;
- return (NULL);
- }
/* Set the page number, pin the page. */
bp->pgno = pgno;
- bp->flags = MPOOL_PINNED;
+ if (!(flags & MPOOL_IGNOREPIN))
+ bp->flags = MPOOL_PINNED;
+ bp->flags |= MPOOL_INUSE;
/*
* Add the page to the head of the hash chain and the tail
@@ -233,11 +268,9 @@ mpool_get(mp, pgno, flags)
* 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;
@@ -253,7 +286,8 @@ mpool_put(mp, page, flags)
}
#endif
bp->flags &= ~MPOOL_PINNED;
- bp->flags |= flags & MPOOL_DIRTY;
+ if (flags & MPOOL_DIRTY)
+ bp->flags |= flags & MPOOL_DIRTY;
return (RET_SUCCESS);
}
@@ -262,8 +296,7 @@ mpool_put(mp, page, flags)
* Close the buffer pool.
*/
int
-mpool_close(mp)
- MPOOL *mp;
+mpool_close(MPOOL *mp)
{
BKT *bp;
@@ -284,8 +317,7 @@ mpool_close(mp)
* Sync the pool to disk.
*/
int
-mpool_sync(mp)
- MPOOL *mp;
+mpool_sync(MPOOL *mp)
{
BKT *bp;
@@ -304,8 +336,7 @@ mpool_sync(mp)
* 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;
@@ -340,18 +371,17 @@ mpool_bkt(mp)
bp->page = spage;
}
#endif
+ bp->flags = 0;
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);
+ bp->flags = 0;
++mp->curcache;
return (bp);
}
@@ -361,9 +391,7 @@ new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
* Write a page to disk.
*/
static int
-mpool_write(mp, bp)
- MPOOL *mp;
- BKT *bp;
+mpool_write(MPOOL *mp, BKT *bp)
{
off_t off;
@@ -376,9 +404,18 @@ mpool_write(mp, bp)
(mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
off = mp->pagesize * bp->pgno;
- if (pwrite(mp->fd, bp->page, mp->pagesize, off) != mp->pagesize)
+ if (pwrite(mp->fd, bp->page, mp->pagesize, off) != (ssize_t)mp->pagesize)
return (RET_ERROR);
+ /*
+ * Re-run through the input filter since this page may soon be
+ * accessed via the cache, and whatever the user's output filter
+ * did may screw things up if we don't let the input filter
+ * restore the in-core copy.
+ */
+ if (mp->pgin)
+ (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
bp->flags &= ~MPOOL_DIRTY;
return (RET_SUCCESS);
}
@@ -388,16 +425,15 @@ mpool_write(mp, bp)
* 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;
head = &mp->hqh[HASHKEY(pgno)];
TAILQ_FOREACH(bp, head, hq)
- if (bp->pgno == pgno) {
+ if ((bp->pgno == pgno) &&
+ ((bp->flags & MPOOL_INUSE) == MPOOL_INUSE)) {
#ifdef STATISTICS
++mp->cachehit;
#endif
@@ -415,16 +451,15 @@ mpool_look(mp, pgno)
* 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);
diff --git a/lib/libc/db/recno/rec_close.c b/lib/libc/db/recno/rec_close.c
index 7da0376..2d1ff84 100644
--- a/lib/libc/db/recno/rec_close.c
+++ b/lib/libc/db/recno/rec_close.c
@@ -57,8 +57,7 @@ __FBSDID("$FreeBSD$");
* RET_ERROR, RET_SUCCESS
*/
int
-__rec_close(dbp)
- DB *dbp;
+__rec_close(DB *dbp)
{
BTREE *t;
int status;
@@ -83,9 +82,10 @@ __rec_close(dbp)
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)
@@ -104,9 +104,7 @@ __rec_close(dbp)
* 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;
@@ -152,19 +150,19 @@ __rec_sync(dbp, flags)
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);
}
diff --git a/lib/libc/db/recno/rec_delete.c b/lib/libc/db/recno/rec_delete.c
index 8036013..d799da2 100644
--- a/lib/libc/db/recno/rec_delete.c
+++ b/lib/libc/db/recno/rec_delete.c
@@ -59,10 +59,7 @@ static int rec_rdelete(BTREE *, recno_t);
* 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;
@@ -115,9 +112,7 @@ einval: errno = EINVAL;
* 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;
@@ -143,16 +138,13 @@ rec_rdelete(t, nrec)
*
* 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;
@@ -170,7 +162,7 @@ __rec_dleaf(t, h, index)
* 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);
@@ -183,8 +175,8 @@ __rec_dleaf(t, h, index)
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)
diff --git a/lib/libc/db/recno/rec_get.c b/lib/libc/db/recno/rec_get.c
index e28c2a1..b543d47 100644
--- a/lib/libc/db/recno/rec_get.c
+++ b/lib/libc/db/recno/rec_get.c
@@ -58,11 +58,7 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -117,9 +113,7 @@ __rec_get(dbp, key, data, flags)
* 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;
@@ -128,9 +122,7 @@ __rec_fpipe(t, top)
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;
@@ -173,9 +165,7 @@ __rec_fpipe(t, top)
* 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;
@@ -201,9 +191,7 @@ __rec_vpipe(t, top)
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;
@@ -230,9 +218,7 @@ __rec_vpipe(t, top)
* 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;
@@ -240,9 +226,7 @@ __rec_fmap(t, top)
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;
@@ -280,9 +264,7 @@ __rec_fmap(t, top)
* 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;
diff --git a/lib/libc/db/recno/rec_open.c b/lib/libc/db/recno/rec_open.c
index f7119b2..dd286c0 100644
--- a/lib/libc/db/recno/rec_open.c
+++ b/lib/libc/db/recno/rec_open.c
@@ -53,10 +53,8 @@ __FBSDID("$FreeBSD$");
#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;
@@ -205,7 +203,7 @@ slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
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;
@@ -219,8 +217,7 @@ err: sverrno = errno;
}
int
-__rec_fd(dbp)
- const DB *dbp;
+__rec_fd(const DB *dbp)
{
BTREE *t;
diff --git a/lib/libc/db/recno/rec_put.c b/lib/libc/db/recno/rec_put.c
index 336f474..441cced 100644
--- a/lib/libc/db/recno/rec_put.c
+++ b/lib/libc/db/recno/rec_put.c
@@ -57,11 +57,7 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -173,7 +169,7 @@ einval: errno = EINVAL;
t->bt_cursor.rcursor = nrec;
break;
}
-
+
F_SET(t, R_MODIFIED);
return (__rec_ret(t, NULL, nrec, key, NULL));
}
@@ -190,16 +186,12 @@ einval: errno = EINVAL;
* 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;
@@ -230,7 +222,7 @@ __rec_iput(t, nrec, data, flags)
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
@@ -240,13 +232,13 @@ __rec_iput(t, nrec, data, flags)
*/
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);
}
@@ -259,19 +251,19 @@ __rec_iput(t, nrec, data, flags)
* 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);
diff --git a/lib/libc/db/recno/rec_search.c b/lib/libc/db/recno/rec_search.c
index 377a59b..8115e0f 100644
--- a/lib/libc/db/recno/rec_search.c
+++ b/lib/libc/db/recno/rec_search.c
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
* 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
@@ -59,12 +59,9 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -82,23 +79,23 @@ __rec_search(t, recno, op)
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:
@@ -117,8 +114,8 @@ err: sverrno = errno;
--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);
}
diff --git a/lib/libc/db/recno/rec_seq.c b/lib/libc/db/recno/rec_seq.c
index 85465fa..42d98d7 100644
--- a/lib/libc/db/recno/rec_seq.c
+++ b/lib/libc/db/recno/rec_seq.c
@@ -57,10 +57,7 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -106,7 +103,7 @@ __rec_seq(dbp, key, data, flags)
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)
diff --git a/lib/libc/db/recno/rec_utils.c b/lib/libc/db/recno/rec_utils.c
index 885ef71..39285a5 100644
--- a/lib/libc/db/recno/rec_utils.c
+++ b/lib/libc/db/recno/rec_utils.c
@@ -51,17 +51,13 @@ __FBSDID("$FreeBSD$");
* 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;
@@ -71,9 +67,7 @@ __rec_ret(t, e, nrec, key, data)
/* 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;
@@ -101,9 +95,7 @@ dataonly:
} 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;
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index a7997ab..8837038 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -9,7 +9,7 @@ SRCS+= __getosreldate.c __xuname.c \
alarm.c arc4random.c assert.c basename.c check_utility_compat.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
- dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c errno.c \
+ dlfcn.c drand48.c erand48.c err.c errlst.c errno.c \
exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \
fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \
getbootfile.c getbsize.c \
@@ -55,7 +55,7 @@ MAN+= alarm.3 arc4random.3 \
getpagesize.3 getpass.3 getpeereid.3 getprogname.3 getpwent.3 \
getttyent.3 getusershell.3 getvfsbyname.3 \
glob.3 initgroups.3 isgreater.3 ldexp.3 lockf.3 makecontext.3 \
- modf.3 msgctl.3 msgget.3 msgrcv.3 msgsnd.3 \
+ modf.3 \
nice.3 nlist.3 pause.3 popen.3 \
posix_spawn.3 posix_spawn_file_actions_addopen.3 \
posix_spawn_file_actions_init.3 posix_spawnattr_getflags.3 \
@@ -70,8 +70,8 @@ MAN+= alarm.3 arc4random.3 \
siginterrupt.3 signal.3 sigsetops.3 sleep.3 \
statvfs.3 stringlist.3 \
strtofflags.3 sysconf.3 sysctl.3 syslog.3 tcgetpgrp.3 tcgetsid.3 \
- tcsendbreak.3 tcsetattr.3 tcsetpgrp.3 time.3 times.3 timezone.3 \
- ttyname.3 tzset.3 ualarm.3 ucontext.3 ulimit.3 uname.3 \
+ tcsendbreak.3 tcsetattr.3 tcsetpgrp.3 tcsetsid.3 time.3 times.3 \
+ timezone.3 ttyname.3 tzset.3 ualarm.3 ucontext.3 ulimit.3 uname.3 \
unvis.3 usleep.3 utime.3 valloc.3 vis.3 wordexp.3
MLINKS+=arc4random.3 arc4random_addrandom.3 arc4random.3 arc4random_stir.3 \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index afdecb5..4f1efaf 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -223,8 +223,6 @@ FBSD_1.0 {
posix_madvise;
popen;
pclose;
- shm_open;
- shm_unlink;
pselect;
psignal;
raise;
@@ -249,7 +247,6 @@ FBSD_1.0 {
sem_timedwait;
sem_post;
sem_getvalue;
- semctl;
setdomainname;
sethostname;
longjmperror;
@@ -335,36 +332,38 @@ FBSD_1.1 {
fdevname_r;
fdopendir;
feature_present;
- fts_open;
- fts_close;
- fts_read;
- fts_set;
fts_children;
+ fts_close;
fts_get_clientptr;
fts_get_stream;
+ fts_open;
+ fts_read;
+ fts_set;
fts_set_clientptr;
+ posix_spawn;
+ posix_spawn_file_actions_addclose;
+ posix_spawn_file_actions_adddup2;
+ posix_spawn_file_actions_addopen;
+ posix_spawn_file_actions_destroy;
+ posix_spawn_file_actions_init;
+ posix_spawnattr_destroy;
+ posix_spawnattr_getflags;
+ posix_spawnattr_getpgroup;
+ posix_spawnattr_getschedparam;
+ posix_spawnattr_getschedpolicy;
+ posix_spawnattr_getsigdefault;
+ posix_spawnattr_getsigmask;
+ posix_spawnattr_init;
+ posix_spawnattr_setflags;
+ posix_spawnattr_setpgroup;
+ posix_spawnattr_setschedparam;
+ posix_spawnattr_setschedpolicy;
+ posix_spawnattr_setsigdefault;
+ posix_spawnattr_setsigmask;
+ posix_spawnp;
+ semctl;
tcgetsid;
- posix_spawn;
- posix_spawn_file_actions_addclose;
- posix_spawn_file_actions_adddup2;
- posix_spawn_file_actions_addopen;
- posix_spawn_file_actions_destroy;
- posix_spawn_file_actions_init;
- posix_spawnattr_destroy;
- posix_spawnattr_getflags;
- posix_spawnattr_getpgroup;
- posix_spawnattr_getschedparam;
- posix_spawnattr_getschedpolicy;
- posix_spawnattr_getsigdefault;
- posix_spawnattr_getsigmask;
- posix_spawnattr_init;
- posix_spawnattr_setflags;
- posix_spawnattr_setpgroup;
- posix_spawnattr_setschedparam;
- posix_spawnattr_setschedpolicy;
- posix_spawnattr_setsigdefault;
- posix_spawnattr_setsigmask;
- posix_spawnp;
+ tcsetsid;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
index eac3f1a..4be8847 100644
--- a/lib/libc/gen/dlfcn.c
+++ b/lib/libc/gen/dlfcn.c
@@ -105,6 +105,14 @@ dlsym(void * __restrict handle, const char * __restrict name)
return NULL;
}
+#pragma weak dlfunc
+dlfunc_t
+dlfunc(void * __restrict handle, const char * __restrict name)
+{
+ _rtld_error(sorry);
+ return NULL;
+}
+
#pragma weak dlvsym
void *
dlvsym(void * __restrict handle, const char * __restrict name,
diff --git a/lib/libc/gen/dlfunc.c b/lib/libc/gen/dlfunc.c
deleted file mode 100644
index 72a683a..0000000
--- a/lib/libc/gen/dlfunc.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This source file is in the public domain.
- * Garrett A. Wollman, 2002-05-28.
- *
- * $FreeBSD$
- */
-
-#include <dlfcn.h>
-
-/*
- * Implement the dlfunc() interface, which behaves exactly the same as
- * dlsym() except that it returns a function pointer instead of a data
- * pointer. This can be used by applications to avoid compiler warnings
- * about undefined behavior, and is intended as prior art for future
- * POSIX standardization. This function requires that all pointer types
- * have the same representation, which is true on all platforms FreeBSD
- * runs on, but is not guaranteed by the C standard.
- */
-dlfunc_t
-dlfunc(void * __restrict handle, const char * __restrict symbol)
-{
- union {
- void *d;
- dlfunc_t f;
- } rv;
-
- rv.d = dlsym(handle, symbol);
- return (rv.f);
-}
-
diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3
index 118e165..6488bef 100644
--- a/lib/libc/gen/dlopen.3
+++ b/lib/libc/gen/dlopen.3
@@ -32,7 +32,7 @@
.\" @(#) dlopen.3 1.6 90/01/31 SMI
.\" $FreeBSD$
.\"
-.Dd September 10, 2002
+.Dd July 7, 2009
.Os
.Dt DLOPEN 3
.Sh NAME
@@ -123,7 +123,7 @@ call to
One of the following flags may be ORed into the
.Fa mode
argument:
-.Bl -tag -width RTLD_GLOBALX
+.Bl -tag -width RTLD_NODELETE
.It Dv RTLD_GLOBAL
Symbols from this shared object and its directed acyclic graph (DAG)
of needed objects will be available for resolving undefined references
@@ -141,6 +141,20 @@ the absolute pathnames of all objects, to standard output.
With this flag
.Fn dlopen
will return to the caller only in the case of error.
+.It Dv RTLD_NODELETE
+Prevents unload of the loaded object on
+.Fn dlclose .
+The same behaviour may be requested by
+.Fl "z nodelete"
+option of the static linker
+.Xr ld 1 .
+.It Dv RTLD_NOLOAD
+Ony return valid handle for the object if it is already loaded in
+the process address space, otherwise
+.Dv NULL
+is returned.
+Other mode flags may be specified, which will be applied for promotion
+for the found object.
.El
.Pp
If
diff --git a/lib/libc/gen/fmtcheck.c b/lib/libc/gen/fmtcheck.c
index 6082913..5b3f2c4 100644
--- a/lib/libc/gen/fmtcheck.c
+++ b/lib/libc/gen/fmtcheck.c
@@ -1,3 +1,5 @@
+/* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */
+
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -12,13 +14,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
@@ -33,7 +28,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* $NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -308,7 +302,7 @@ get_next_format(const char **pf, EFT eft)
/*NOTREACHED*/
}
-__const char *
+const char *
__fmtcheck(const char *f1, const char *f2)
{
const char *f1p, *f2p;
diff --git a/lib/libc/gen/ftok.3 b/lib/libc/gen/ftok.3
index a1c7dde..78bfe45 100644
--- a/lib/libc/gen/ftok.3
+++ b/lib/libc/gen/ftok.3
@@ -24,7 +24,7 @@
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd June 24, 1994
+.Dd July 9, 2009
.Os
.Dt FTOK 3
.Sh NAME
@@ -41,7 +41,7 @@
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
@@ -66,7 +66,7 @@ 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 2
.Sh HISTORY
The
.Fn ftok
diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c
index ced205b..41443c5 100644
--- a/lib/libc/gen/fts.c
+++ b/lib/libc/gen/fts.c
@@ -570,8 +570,10 @@ fts_children(sp, instr)
if ((fd = _open(".", O_RDONLY, 0)) < 0)
return (NULL);
sp->fts_child = fts_build(sp, instr);
- if (fchdir(fd))
+ if (fchdir(fd)) {
+ (void)_close(fd);
return (NULL);
+ }
(void)_close(fd);
return (sp->fts_child);
}
diff --git a/lib/libc/gen/getcap.c b/lib/libc/gen/getcap.c
index 0f0bb20..32d66d48 100644
--- a/lib/libc/gen/getcap.c
+++ b/lib/libc/gen/getcap.c
@@ -189,7 +189,7 @@ getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
{
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];
@@ -251,14 +251,16 @@ getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
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 {
diff --git a/lib/libc/gen/initgroups.3 b/lib/libc/gen/initgroups.3
index 2fe2dd9..3ed3ca7 100644
--- a/lib/libc/gen/initgroups.3
+++ b/lib/libc/gen/initgroups.3
@@ -65,6 +65,13 @@ function may fail and set
.Va errno
for any of the errors specified for the library function
.Xr setgroups 2 .
+It may also return:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+The
+.Fn initgroups
+function was unable to allocate temporary storage.
+.El
.Sh SEE ALSO
.Xr setgroups 2 ,
.Xr getgrouplist 3
diff --git a/lib/libc/gen/initgroups.c b/lib/libc/gen/initgroups.c
index 299ae50..aacaf7e 100644
--- a/lib/libc/gen/initgroups.c
+++ b/lib/libc/gen/initgroups.c
@@ -35,10 +35,12 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <stdio.h>
#include "namespace.h"
#include <err.h>
#include "un-namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
int
@@ -46,14 +48,21 @@ initgroups(uname, agroup)
const char *uname;
gid_t agroup;
{
- int ngroups;
+ int ngroups, ret;
+ long ngroups_max;
+ gid_t *groups;
+
/*
- * Provide space for one group more than NGROUPS to allow
+ * Provide space for one group more than possible to allow
* setgroups to fail and set errno.
*/
- gid_t groups[NGROUPS + 1];
+ ngroups_max = sysconf(_SC_NGROUPS_MAX) + 2;
+ if ((groups = malloc(sizeof(*groups) * ngroups_max)) == NULL)
+ return (ENOMEM);
- ngroups = NGROUPS + 1;
+ ngroups = (int)ngroups_max;
getgrouplist(uname, agroup, groups, &ngroups);
- return (setgroups(ngroups, groups));
+ ret = setgroups(ngroups, groups);
+ free(groups);
+ return (ret);
}
diff --git a/lib/libc/gen/lockf.3 b/lib/libc/gen/lockf.3
index cb3b8ef..d9350d1 100644
--- a/lib/libc/gen/lockf.3
+++ b/lib/libc/gen/lockf.3
@@ -1,4 +1,4 @@
-.\" $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.
@@ -14,13 +14,6 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the 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
diff --git a/lib/libc/gen/lockf.c b/lib/libc/gen/lockf.c
index e79e162..2c567ba 100644
--- a/lib/libc/gen/lockf.c
+++ b/lib/libc/gen/lockf.c
@@ -1,3 +1,4 @@
+/* $NetBSD: lockf.c,v 1.3 2008/04/28 20:22:59 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -13,13 +14,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
@@ -34,7 +28,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/* $NetBSD: lockf.c,v 1.1 1997/12/20 20:23:18 kleink Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -45,10 +38,7 @@ __FBSDID("$FreeBSD$");
#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;
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c
index f3450b5..b123234 100644
--- a/lib/libc/gen/popen.c
+++ b/lib/libc/gen/popen.c
@@ -191,7 +191,7 @@ pclose(iop)
if (last == NULL)
SLIST_REMOVE_HEAD(&pidlist, next);
else
- SLIST_REMOVE_NEXT(&pidlist, last, next);
+ SLIST_REMOVE_AFTER(last, next);
THREAD_UNLOCK();
(void)fclose(iop);
diff --git a/lib/libc/gen/pw_scan.c b/lib/libc/gen/pw_scan.c
index 9242dd0..24e8225 100644
--- a/lib/libc/gen/pw_scan.c
+++ b/lib/libc/gen/pw_scan.c
@@ -58,8 +58,14 @@ __FBSDID("$FreeBSD$");
*
* If pw_big_ids_warning is -1 on entry to pw_scan(), it will be set based
* on the existence of PW_SCAN_BIG_IDS in the environment.
+ *
+ * It is believed all baseline system software that can not handle the
+ * normal ID sizes is now gone so pw_big_ids_warning is disabled for now.
+ * But the code has been left in place in case end-users want to re-enable
+ * it and/or for the next time the ID sizes get bigger but pieces of the
+ * system lag behind.
*/
-static int pw_big_ids_warning = -1;
+static int pw_big_ids_warning = 0;
int
__pw_scan(char *bp, struct passwd *pw, int flags)
@@ -67,6 +73,7 @@ __pw_scan(char *bp, struct passwd *pw, int flags)
uid_t id;
int root;
char *ep, *p, *sh;
+ unsigned long temp;
if (pw_big_ids_warning == -1)
pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0;
@@ -94,12 +101,14 @@ __pw_scan(char *bp, struct passwd *pw, int flags)
return (0);
}
}
- id = strtoul(p, &ep, 10);
- if (errno == ERANGE) {
+ errno = 0;
+ temp = strtoul(p, &ep, 10);
+ if ((temp == ULONG_MAX && errno == ERANGE) || temp > UID_MAX) {
if (flags & _PWSCAN_WARN)
- warnx("%s > max uid value (%lu)", p, ULONG_MAX);
+ warnx("%s > max uid value (%u)", p, UID_MAX);
return (0);
}
+ id = temp;
if (*ep != '\0') {
if (flags & _PWSCAN_WARN)
warnx("%s uid is incorrect", p);
@@ -127,12 +136,14 @@ __pw_scan(char *bp, struct passwd *pw, int flags)
return (0);
}
}
- id = strtoul(p, &ep, 10);
- if (errno == ERANGE) {
+ errno = 0;
+ temp = strtoul(p, &ep, 10);
+ if ((temp == ULONG_MAX && errno == ERANGE) || temp > GID_MAX) {
if (flags & _PWSCAN_WARN)
- warnx("%s > max gid value (%lu)", p, ULONG_MAX);
+ warnx("%s > max gid value (%u)", p, GID_MAX);
return (0);
}
+ id = temp;
if (*ep != '\0') {
if (flags & _PWSCAN_WARN)
warnx("%s gid is incorrect", p);
diff --git a/lib/libc/gen/semctl.c b/lib/libc/gen/semctl.c
index 4b5283f..156d18c 100644
--- a/lib/libc/gen/semctl.c
+++ b/lib/libc/gen/semctl.c
@@ -29,15 +29,19 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#define _WANT_SEMUN_OLD
+
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdarg.h>
#include <stdlib.h>
-extern int __semctl(int semid, int semnum, int cmd, union semun *arg);
+int __semctl(int semid, int semnum, int cmd, union semun *arg);
+int freebsd7___semctl(int semid, int semnum, int cmd, union semun_old *arg);
-int semctl(int semid, int semnum, int cmd, ...)
+int
+semctl(int semid, int semnum, int cmd, ...)
{
va_list ap;
union semun semun;
@@ -55,3 +59,25 @@ int semctl(int semid, int semnum, int cmd, ...)
return (__semctl(semid, semnum, cmd, semun_ptr));
}
+
+int
+freebsd7_semctl(int semid, int semnum, int cmd, ...)
+{
+ va_list ap;
+ union semun_old semun;
+ union semun_old *semun_ptr;
+
+ va_start(ap, cmd);
+ if (cmd == IPC_SET || cmd == IPC_STAT || cmd == GETALL
+ || cmd == SETVAL || cmd == SETALL) {
+ semun = va_arg(ap, union semun_old);
+ semun_ptr = &semun;
+ } else {
+ semun_ptr = NULL;
+ }
+ va_end(ap);
+
+ return (freebsd7___semctl(semid, semnum, cmd, semun_ptr));
+}
+
+__sym_compat(semctl, freebsd7_semctl, FBSD_1.0);
diff --git a/lib/libc/gen/tcgetsid.3 b/lib/libc/gen/tcgetsid.3
index 11c8d0c..a270a0b 100644
--- a/lib/libc/gen/tcgetsid.3
+++ b/lib/libc/gen/tcgetsid.3
@@ -63,7 +63,8 @@ is not the controlling terminal.
.Sh SEE ALSO
.Xr getsid 2 ,
.Xr setsid 2 ,
-.Xr tcgetpgrp 3
+.Xr tcgetpgrp 3 ,
+.Xr tcsetsid 3
.Sh STANDARDS
The
.Fn tcgetsid
diff --git a/lib/libc/gen/tcsetsid.3 b/lib/libc/gen/tcsetsid.3
new file mode 100644
index 0000000..d0f1d98
--- /dev/null
+++ b/lib/libc/gen/tcsetsid.3
@@ -0,0 +1,92 @@
+.\" Copyright (c) 2009 Ed Schouten <ed@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 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$
+.\"
+.Dd May 4, 2009
+.Dt TCSETSID 3
+.Os
+.Sh NAME
+.Nm tcsetsid
+.Nd set session ID associated with a controlling terminal
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In termios.h
+.Ft int
+.Fn tcsetsid "int fd" "pid_t pid"
+.Sh DESCRIPTION
+The
+.Fn tcsetsid
+function sets associates a session identified by
+.Fa pid
+with a controlling terminal specified by
+.Fa fd .
+.Pp
+This implementation only allows the controlling terminal to be changed
+by the session leader itself.
+This implies that
+.Fa pid
+always has to be equal to the process ID.
+.Pp
+It is unsupported to associate with a terminal that already has an
+associated session.
+Conversely, it is also unsupported to associate to a terminal when
+the session is already associated with a different terminal.
+.Sh ERRORS
+If an error occurs,
+.Fn tcsetsid
+returns -1 and the global variable
+.Va errno
+is set to indicate the error, as follows:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er ENOTTY
+The file descriptor represented by
+.Fa fd
+is not a terminal.
+.It Bq Er EINVAL
+The
+.Fa pid
+argument is not equal to the session ID of the calling process.
+.It Bq Er EPERM
+The calling process is not a session leader.
+.It Bq Er EPERM
+The session already has an associated terminal or the terminal already
+has an associated session.
+.El
+.Sh SEE ALSO
+.Xr getsid 2 ,
+.Xr setsid 2 ,
+.Xr tcgetpgrp 3 ,
+.Xr tcgetsid 3
+.Sh HISTORY
+A
+.Fn tcsetsid
+function first appeared in QNX.
+It does not comply to any standard.
diff --git a/lib/libc/gen/termios.c b/lib/libc/gen/termios.c
index 4c6dcff..85ca4e3 100644
--- a/lib/libc/gen/termios.c
+++ b/lib/libc/gen/termios.c
@@ -110,6 +110,18 @@ tcgetsid(int fd)
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;
diff --git a/lib/libc/gen/ttyname.3 b/lib/libc/gen/ttyname.3
index ada580f..c7b8cbc 100644
--- a/lib/libc/gen/ttyname.3
+++ b/lib/libc/gen/ttyname.3
@@ -57,11 +57,10 @@ These descriptors are not related to the standard
.Dv FILE
typedef, but refer to the special device files found in
.Pa /dev
-and named
-.Pa /dev/tty Ns Ar xx
and for which an entry exists
in the initialization file
-.Pa /etc/ttys .
+.Pa /etc/ttys
+or pseudo-terminals.
(See
.Xr ttys 5 . )
.Pp
diff --git a/lib/libc/i386/stdlib/Makefile.inc b/lib/libc/i386/stdlib/Makefile.inc
index 0a6a6a8..e4197d8 100644
--- a/lib/libc/i386/stdlib/Makefile.inc
+++ b/lib/libc/i386/stdlib/Makefile.inc
@@ -1,4 +1,4 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
# $FreeBSD$
-MDSRCS+=abs.S div.S labs.S ldiv.S
+MDSRCS+=div.S ldiv.S
diff --git a/lib/libc/i386/stdlib/div.S b/lib/libc/i386/stdlib/div.S
index dcc9eb0..42e7ef4 100644
--- a/lib/libc/i386/stdlib/div.S
+++ b/lib/libc/i386/stdlib/div.S
@@ -33,7 +33,5 @@ ENTRY(div)
movl 8(%esp),%ecx
cdq
idiv %ecx
- movl %eax,4(%esp)
- movl %edx,8(%esp)
ret
END(div)
diff --git a/lib/libc/i386/stdlib/ldiv.S b/lib/libc/i386/stdlib/ldiv.S
index a787714..b0455bf 100644
--- a/lib/libc/i386/stdlib/ldiv.S
+++ b/lib/libc/i386/stdlib/ldiv.S
@@ -36,7 +36,5 @@ ENTRY(ldiv)
movl 8(%esp),%ecx
cdq
idiv %ecx
- movl %eax,4(%esp)
- movl %edx,8(%esp)
ret
END(ldiv)
diff --git a/lib/libc/i386/sys/Makefile.inc b/lib/libc/i386/sys/Makefile.inc
index 593956b..98a9c9e 100644
--- a/lib/libc/i386/sys/Makefile.inc
+++ b/lib/libc/i386/sys/Makefile.inc
@@ -2,11 +2,10 @@
# $FreeBSD$
.if !defined(COMPAT_32BIT)
-SRCS+= i386_clr_watch.c i386_get_ioperm.c \
- i386_set_ioperm.c i386_set_watch.c i386_vm86.c
+SRCS+= i386_clr_watch.c i386_set_watch.c i386_vm86.c
.endif
-SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ldt.c \
- i386_set_fsbase.c i386_set_gsbase.c i386_set_ldt.c
+SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ioperm.c i386_get_ldt.c \
+ i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c
MDASM= Ovfork.S brk.S cerror.S exect.S getcontext.S pipe.S ptrace.S \
reboot.S sbrk.S setlogin.S sigreturn.S syscall.S
diff --git a/lib/libc/ia64/stdlib/Makefile.inc b/lib/libc/ia64/stdlib/Makefile.inc
deleted file mode 100644
index dda8c76..0000000
--- a/lib/libc/ia64/stdlib/Makefile.inc
+++ /dev/null
@@ -1,3 +0,0 @@
-# $FreeBSD$
-
-MDSRCS+= abs.c div.c labs.c ldiv.c
diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h
new file mode 100644
index 0000000..13c1d20
--- /dev/null
+++ b/lib/libc/include/compat.h
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2009 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb@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$
+ */
+
+/*
+ * This file defines compatiblity symbol versions for old system calls. It
+ * is included in all generated system call files.
+ */
+
+#ifndef __LIBC_COMPAT_H__
+#define __LIBC_COMPAT_H__
+
+#define __sym_compat(sym,impl,verid) \
+ .symver impl , sym @ verid
+
+__sym_compat(__semctl, freebsd7___semctl, FBSD_1.0);
+__sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0);
+__sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0);
+
+#undef __sym_compat
+
+#endif /* __LIBC_COMPAT_H__ */
+
diff --git a/lib/libc/mips/stdlib/Makefile.inc b/lib/libc/mips/stdlib/Makefile.inc
deleted file mode 100644
index b4ee750..0000000
--- a/lib/libc/mips/stdlib/Makefile.inc
+++ /dev/null
@@ -1,4 +0,0 @@
-# $NetBSD: Makefile.inc,v 1.3 2006/03/22 22:03:58 drochner Exp $
-# $FreeBSD$
-
-SRCS+= abs.c div.c labs.c ldiv.c llabs.c
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index 941c315..830e464 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -102,7 +102,6 @@ __FBSDID("$FreeBSD$");
# define FAITH
#endif
-#define SUCCESS 0
#define ANY 0
#define YES 1
#define NO 0
@@ -165,19 +164,20 @@ struct explore {
static const struct explore explore[] = {
#if 0
- { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
+ { PF_LOCAL, ANY, ANY, NULL, 0x01 },
#endif
#ifdef INET6
{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
+ { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
#endif
{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
+ { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
- { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
- { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
- { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
{ -1, 0, 0, NULL, 0 },
};
@@ -227,6 +227,8 @@ typedef union {
} querybuf;
static int str2number(const char *, int *);
+static int explore_copy(const struct addrinfo *, const struct addrinfo *,
+ struct addrinfo **);
static int explore_null(const struct addrinfo *,
const char *, struct addrinfo **);
static int explore_numeric(const struct addrinfo *, const char *,
@@ -237,6 +239,7 @@ static int get_canonname(const struct addrinfo *,
struct addrinfo *, const char *);
static struct addrinfo *get_ai(const struct addrinfo *,
const struct afd *, const char *);
+static struct addrinfo *copy_ai(const struct addrinfo *);
static int get_portmatch(const struct addrinfo *, const char *);
static int get_port(struct addrinfo *, const char *, int);
static const struct afd *find_afd(int);
@@ -365,12 +368,23 @@ getaddrinfo(const char *hostname, const char *servname,
struct addrinfo sentinel;
struct addrinfo *cur;
int error = 0;
- struct addrinfo ai;
- struct addrinfo ai0;
+ struct addrinfo ai, ai0, *afai;
struct addrinfo *pai;
+ const struct afd *afd;
const struct explore *ex;
+ struct addrinfo *afailist[sizeof(afdl)/sizeof(afdl[0])];
+ struct addrinfo *afai_unspec;
+ int found;
int numeric = 0;
+ /* ensure we return NULL on errors */
+ *res = NULL;
+
+ memset(&ai, 0, sizeof(ai));
+
+ memset(afailist, 0, sizeof(afailist));
+ afai_unspec = NULL;
+
memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel;
pai = &ai;
@@ -410,17 +424,22 @@ getaddrinfo(const char *hostname, const char *servname,
*/
if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
for (ex = explore; ex->e_af >= 0; ex++) {
- if (pai->ai_family != ex->e_af)
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
+ WILD_AF(ex)))
continue;
- if (ex->e_socktype == ANY)
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex)))
continue;
- if (ex->e_protocol == ANY)
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex)))
continue;
- if (pai->ai_socktype == ex->e_socktype &&
- pai->ai_protocol != ex->e_protocol) {
- ERR(EAI_BADHINTS);
- }
+
+ /* matched */
+ break;
}
+
+ if (ex->e_af < 0)
+ ERR(EAI_BADHINTS);
}
}
@@ -452,49 +471,48 @@ getaddrinfo(const char *hostname, const char *servname,
ai0 = *pai;
- /* NULL hostname, or numeric hostname */
- for (ex = explore; ex->e_af >= 0; ex++) {
+ /*
+ * NULL hostname, or numeric hostname.
+ * If numeric representation of AF1 can be interpreted as FQDN
+ * representation of AF2, we need to think again about the code below.
+ */
+ found = 0;
+ for (afd = afdl; afd->a_af; afd++) {
*pai = ai0;
- /* PF_UNSPEC entries are prepared for DNS queries only */
- if (ex->e_af == PF_UNSPEC)
- continue;
-
- if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
- continue;
- if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
- continue;
- if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+ if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
continue;
if (pai->ai_family == PF_UNSPEC)
- pai->ai_family = ex->e_af;
- if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
- pai->ai_socktype = ex->e_socktype;
- if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
- pai->ai_protocol = ex->e_protocol;
+ pai->ai_family = afd->a_af;
- if (hostname == NULL)
- error = explore_null(pai, servname, &cur->ai_next);
- else
+ if (hostname == NULL) {
+ error = explore_null(pai, servname,
+ &afailist[afd - afdl]);
+
+ /*
+ * Errors from explore_null should be unexpected and
+ * be caught to avoid returning an incomplete result.
+ */
+ if (error != 0)
+ goto bad;
+ } else {
error = explore_numeric_scope(pai, hostname, servname,
- &cur->ai_next);
+ &afailist[afd - afdl]);
- if (error)
- goto free;
+ /*
+ * explore_numeric_scope returns an error for address
+ * families that do not match that of hostname.
+ * Thus we should not catch the error at this moment.
+ */
+ }
- while (cur && cur->ai_next)
- cur = cur->ai_next;
+ if (!error && afailist[afd - afdl])
+ found++;
}
-
- /*
- * XXX
- * If numreic representation of AF1 can be interpreted as FQDN
- * representation of AF2, we need to think again about the code below.
- */
- if (sentinel.ai_next) {
+ if (found) {
numeric = 1;
- goto good;
+ goto globcopy;
}
if (hostname == NULL)
@@ -507,42 +525,55 @@ getaddrinfo(const char *hostname, const char *servname,
/*
* hostname as alphabetical name.
- * we would like to prefer AF_INET6 than AF_INET, so we'll make a
- * outer loop by AFs.
*/
+ *pai = ai0;
+ error = explore_fqdn(pai, hostname, servname, &afai_unspec);
+
+globcopy:
for (ex = explore; ex->e_af >= 0; ex++) {
*pai = ai0;
- /* require exact match for family field */
- if (pai->ai_family != ex->e_af)
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
continue;
-
if (!MATCH(pai->ai_socktype, ex->e_socktype,
- WILD_SOCKTYPE(ex))) {
+ WILD_SOCKTYPE(ex)))
continue;
- }
if (!MATCH(pai->ai_protocol, ex->e_protocol,
- WILD_PROTOCOL(ex))) {
+ WILD_PROTOCOL(ex)))
continue;
- }
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
pai->ai_socktype = ex->e_socktype;
if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
pai->ai_protocol = ex->e_protocol;
- error = explore_fqdn(pai, hostname, servname,
- &cur->ai_next);
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ continue;
+
+ if (afai_unspec)
+ afai = afai_unspec;
+ else {
+ if ((afd = find_afd(pai->ai_family)) == NULL)
+ continue;
+ /* XXX assumes that afd points inside afdl[] */
+ afai = afailist[afd - afdl];
+ }
+ if (!afai)
+ continue;
+
+ error = explore_copy(pai, afai, &cur->ai_next);
+ if (error != 0)
+ goto bad;
while (cur && cur->ai_next)
cur = cur->ai_next;
}
- /* XXX inhibit errors if we have the result */
- if (sentinel.ai_next)
- error = 0;
-
-good:
/*
* ensure we return either:
* - error == 0, non-NULL *res
@@ -578,16 +609,22 @@ good:
}
}
*res = sentinel.ai_next;
- return SUCCESS;
} else
error = EAI_FAIL;
}
-free:
+
bad:
- if (sentinel.ai_next)
- freeaddrinfo(sentinel.ai_next);
- *res = NULL;
- return error;
+ if (afai_unspec)
+ freeaddrinfo(afai_unspec);
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afailist[afd - afdl])
+ freeaddrinfo(afailist[afd - afdl]);
+ }
+ if (!*res)
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+
+ return (error);
}
static int
@@ -1039,6 +1076,41 @@ gai_addr2scopetype(struct sockaddr *sa)
}
}
+static int
+explore_copy(const struct addrinfo *pai, const struct addrinfo *src0,
+ struct addrinfo **res)
+{
+ int error;
+ struct addrinfo sentinel, *cur;
+ const struct addrinfo *src;
+
+ error = 0;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ for (src = src0; src != NULL; src = src->ai_next) {
+ if (src->ai_family != pai->ai_family)
+ continue;
+
+ cur->ai_next = copy_ai(src);
+ if (!cur->ai_next) {
+ error = EAI_MEMORY;
+ goto fail;
+ }
+
+ cur->ai_next->ai_socktype = pai->ai_socktype;
+ cur->ai_next->ai_protocol = pai->ai_protocol;
+ cur = cur->ai_next;
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+fail:
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
/*
* hostname == NULL.
* passive socket -> anyaddr (0.0.0.0 or ::)
@@ -1067,12 +1139,6 @@ explore_null(const struct addrinfo *pai, const char *servname,
} else
_close(s);
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
@@ -1109,12 +1175,6 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
*res = NULL;
ai = NULL;
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
@@ -1181,12 +1241,6 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
char *cp, *hostname2 = NULL, *scope, *addr;
struct sockaddr_in6 *sin6;
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
@@ -1219,6 +1273,8 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
free(hostname2);
+ freeaddrinfo(*res);
+ *res = NULL;
return(EAI_NONAME); /* XXX: is return OK? */
}
sin6->sin6_scope_id = scopeid;
@@ -1227,6 +1283,10 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
free(hostname2);
+ if (error && *res) {
+ freeaddrinfo(*res);
+ *res = NULL;
+ }
return error;
#endif
}
@@ -1310,6 +1370,38 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
return ai;
}
+/* XXX need to malloc() the same way we do from other functions! */
+static struct addrinfo *
+copy_ai(const struct addrinfo *pai)
+{
+ struct addrinfo *ai;
+ size_t l;
+
+ l = sizeof(*ai) + pai->ai_addrlen;
+ if ((ai = (struct addrinfo *)malloc(l)) == NULL)
+ return NULL;
+ memset(ai, 0, l);
+ memcpy(ai, pai, sizeof(*ai));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
+
+ if (pai->ai_canonname) {
+ l = strlen(pai->ai_canonname) + 1;
+ if ((ai->ai_canonname = malloc(l)) == NULL) {
+ free(ai);
+ return NULL;
+ }
+ strlcpy(ai->ai_canonname, pai->ai_canonname, l);
+ } else {
+ /* just to make sure */
+ ai->ai_canonname = NULL;
+ }
+
+ ai->ai_next = NULL;
+
+ return ai;
+}
+
static int
get_portmatch(const struct addrinfo *ai, const char *servname)
{
@@ -1344,10 +1436,21 @@ get_port(struct addrinfo *ai, const char *servname, int matchonly)
return EAI_SERVICE;
case SOCK_DGRAM:
case SOCK_STREAM:
+ case SOCK_SEQPACKET:
allownumeric = 1;
break;
case ANY:
- allownumeric = 0;
+ switch (ai->ai_family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ allownumeric = 1;
+ break;
+ default:
+ allownumeric = 0;
+ break;
+ }
break;
default:
return EAI_SOCKTYPE;
@@ -1363,13 +1466,17 @@ get_port(struct addrinfo *ai, const char *servname, int matchonly)
} else {
if (ai->ai_flags & AI_NUMERICSERV)
return EAI_NONAME;
- switch (ai->ai_socktype) {
- case SOCK_DGRAM:
+
+ switch (ai->ai_protocol) {
+ case IPPROTO_UDP:
proto = "udp";
break;
- case SOCK_STREAM:
+ case IPPROTO_TCP:
proto = "tcp";
break;
+ case IPPROTO_SCTP:
+ proto = "sctp";
+ break;
default:
proto = NULL;
break;
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c
index 9495443..162d592 100644
--- a/lib/libc/net/nsdispatch.c
+++ b/lib/libc/net/nsdispatch.c
@@ -80,12 +80,14 @@ __FBSDID("$FreeBSD$");
#define _NS_PRIVATE
#include <nsswitch.h>
#include <pthread.h>
+#include <pthread_np.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "un-namespace.h"
+#include "nss_tls.h"
#include "libc_private.h"
#ifdef NS_CACHING
#include "nscache.h"
@@ -143,7 +145,11 @@ static void *nss_cache_cycle_prevention_func = NULL;
* which in turn calls nsdispatch, which should call fallback
* function) are not supported
*/
-static int fallback_dispatch = 0;
+struct fb_state {
+ int fb_dispatch;
+};
+static void fb_endstate(void *);
+NSS_TLS_HANDLING(fb);
/*
* Attempt to spew relatively uniform messages to syslog.
@@ -598,6 +604,11 @@ nss_method_lookup(const char *source, const char *database,
return (NULL);
}
+static void
+fb_endstate(void *p)
+{
+ free(p);
+}
__weak_reference(_nsdispatch, nsdispatch);
@@ -611,6 +622,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
nss_method method, fb_method;
void *mdata;
int isthreaded, serrno, i, result, srclistsize;
+ struct fb_state *st;
#ifdef NS_CACHING
nss_cache_data cache_data;
@@ -630,12 +642,19 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
goto fin;
}
}
+
+ result = fb_getstate(&st);
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
+
result = nss_configure();
if (result != 0) {
result = NS_UNAVAIL;
goto fin;
}
- if (fallback_dispatch == 0) {
+ if (st->fb_dispatch == 0) {
dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
string_compare);
fb_method = nss_method_lookup(NSSRC_FALLBACK, database,
@@ -702,12 +721,12 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
break;
} else {
if (fb_method != NULL) {
- fallback_dispatch = 1;
+ st->fb_dispatch = 1;
va_start(ap, defaults);
result = fb_method(retval,
(void *)srclist[i].name, ap);
va_end(ap);
- fallback_dispatch = 0;
+ st->fb_dispatch = 0;
} else
nss_log(LOG_DEBUG, "%s, %s, %s, not found, "
"and no fallback provided",
diff --git a/lib/libc/net/rcmd.3 b/lib/libc/net/rcmd.3
index a7d2f8b..1cd4327 100644
--- a/lib/libc/net/rcmd.3
+++ b/lib/libc/net/rcmd.3
@@ -245,6 +245,7 @@ When using the
.Fn rcmd
function, this variable is used as the program to run instead of
.Xr rsh 1 .
+.El
.Sh DIAGNOSTICS
The
.Fn rcmd
diff --git a/lib/libc/net/resolver.3 b/lib/libc/net/resolver.3
index e35a545..c1a37b3 100644
--- a/lib/libc/net/resolver.3
+++ b/lib/libc/net/resolver.3
@@ -28,7 +28,7 @@
.\" @(#)resolver.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd November 4, 2006
+.Dd May 29, 2009
.Dt RESOLVER 3
.Os
.Sh NAME
@@ -401,6 +401,19 @@ function properly if the programmer attempts to declare his or her own
.Va _res
structure in an attempt to replace the per-thread version referred to
by that macro.
+.Pp
+The following compile-time option can be specified to change the default
+behavior of resolver routines when necessary.
+.Bl -tag -width RES_ENFORCE_RFC1034
+.It Dv RES_ENFORCE_RFC1034
+If this symbol is defined during compile-time,
+.Fn res_search
+will enforce RFC 1034 check, namely, disallow using of underscore character
+within host names.
+This is used by the standard host lookup routines like
+.Xr gethostbyname 3 .
+For compatibility reasons this option is not enabled by default.
+.El
.Sh RETURN VALUES
The
.Fn res_init
diff --git a/lib/libc/net/sourcefilter.3 b/lib/libc/net/sourcefilter.3
index c44101f..46f61a8 100644
--- a/lib/libc/net/sourcefilter.3
+++ b/lib/libc/net/sourcefilter.3
@@ -1,15 +1,19 @@
-.\" Copyright (c) 2007 Bruce M. Simpson. All rights reserved.
+.\" 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 Bruce M. Simpson ``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 Bruce M. Simpson 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)
@@ -20,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 12, 2007
+.Dd February 13, 2009
.Dt SOURCEFILTER 3
.Os
.Sh NAME
@@ -78,25 +82,34 @@ retrieve the multicast source address filters associated with a socket
and a multicast
.Fa group .
.Pp
-The protocol-independent functions
-.Fn getsourcefilter
+The functions
+.Fn getipv4sourcefilter
and
-.Fn setsourcefilter
-allow an application to join a multicast group on an interface by
-passing its index for the
-.Fa interface
-argument.
+.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
-argument.
-.Fa grouplen
-argument specifies the size of the structure pointed to by
-.Fa group .
+.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.
+functions,
the
.Fa fmode
argument may be used to place the socket into inclusive or exclusive
@@ -110,14 +123,57 @@ The
argument specifies the number of source entries in the
.Fa slist
array.
-A value of 0 will remove all source filters from the socket.
-The changes will be communicated to IGMPv3 and/or MLDv2 routers
+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 upwards compatibility with IPv6 networks.
+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
@@ -164,7 +220,8 @@ operation.
.Sh SEE ALSO
.Xr ip 4 ,
.Xr ip6 4 ,
-.Xr multicast 4
+.Xr multicast 4,
+.Xr ifmcstat 8
.Rs
.%A D. Thaler
.%A B. Fenner
diff --git a/lib/libc/net/sourcefilter.c b/lib/libc/net/sourcefilter.c
index 14812c5..cc0f1b9 100644
--- a/lib/libc/net/sourcefilter.c
+++ b/lib/libc/net/sourcefilter.c
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 2007 Bruce M. Simpson.
- * All rights reserved
+ * 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
@@ -10,21 +10,18 @@
* 2. Redistributions in binary form must 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 Bruce M. Simpson nor the names of other
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY BRUCE M. SIMPSON AND AFFILIATES
- * ``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 BRUCE M. SIMPSON 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.
+ * 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>
@@ -340,7 +337,7 @@ getsourcefilter(int s, uint32_t interface, struct sockaddr *group,
{
struct __msfilterreq msfr;
sockunion_t *psu;
- int err, level, optlen, optname;
+ int err, level, nsrcs, optlen, optname;
if (interface == 0 || group == NULL || numsrc == NULL ||
fmode == NULL) {
@@ -348,6 +345,7 @@ getsourcefilter(int s, uint32_t interface, struct sockaddr *group,
return (-1);
}
+ nsrcs = *numsrc;
*numsrc = 0;
*fmode = 0;
@@ -385,7 +383,7 @@ getsourcefilter(int s, uint32_t interface, struct sockaddr *group,
memset(&msfr, 0, optlen);
msfr.msfr_ifindex = interface;
msfr.msfr_fmode = 0;
- msfr.msfr_nsrcs = *numsrc;
+ msfr.msfr_nsrcs = nsrcs;
memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
/*
diff --git a/lib/libc/nls/Makefile.inc b/lib/libc/nls/Makefile.inc
index 90a6741..9e19e85 100644
--- a/lib/libc/nls/Makefile.inc
+++ b/lib/libc/nls/Makefile.inc
@@ -8,3 +8,28 @@ SRCS+= msgcat.c
SYM_MAPS+=${.CURDIR}/nls/Symbol.map
MAN+= catclose.3 catgets.3 catopen.3
+
+# NOTE: C.msg should not be processed here, it's used as a template
+# for translators.
+
+NLSNAME= libc
+NLS+= be_BY.UTF-8
+NLS+= ca_ES.ISO8859-1
+NLS+= de_DE.ISO8859-1
+NLS+= el_GR.ISO8859-7
+NLS+= es_ES.ISO8859-1
+NLS+= fi_FI.ISO8859-1
+NLS+= fr_FR.ISO8859-1
+NLS+= hu_HU.ISO8859-2
+NLS+= it_IT.ISO8859-15
+NLS+= ko_KR.UTF-8
+NLS+= ko_KR.eucKR
+NLS+= mn_MN.UTF-8
+NLS+= nl_NL.ISO8859-1
+NLS+= no_NO.ISO8859-1
+NLS+= pl_PL.ISO8859-2
+NLS+= pt_BR.ISO8859-1
+NLS+= ru_RU.KOI8-R
+NLS+= sk_SK.ISO8859-2
+NLS+= sv_SE.ISO8859-1
+NLS+= uk_UA.UTF-8
diff --git a/lib/libc/nls/be_BY.UTF-8.msg b/lib/libc/nls/be_BY.UTF-8.msg
new file mode 100644
index 0000000..56bd038
--- /dev/null
+++ b/lib/libc/nls/be_BY.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for be_BY.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ дазволена
+$ ENOENT
+2 ÐÑма такога файлу ці каталогу
+$ ESRCH
+3 ÐÑма такога працÑÑу
+$ EINTR
+4 Перарваны ÑÑ–ÑÑ‚Ñмны выклік
+$ EIO
+5 Памылка ўводу/вываду
+$ ENXIO
+6 ПрыÑтаÑаванне не Ñканфігуравана
+$ E2BIG
+7 Ðадта доўгі ÑÐ¿Ñ–Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñž
+$ ENOEXEC
+8 Памылка фармату файлу, Ñкі выконваецца
+$ EBADF
+9 ÐекарÑктны дÑÑкрыптар файлу
+$ ECHILD
+10 ÐÑма дачÑрніх працÑÑаў
+$ EDEADLK
+11 Прадухілена ÑžÐ·Ð°ÐµÐ¼Ð½Ð°Ñ Ð±Ð»Ð°ÐºÑ–Ñ€Ð¾ÑžÐºÐ° Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð´Ð¾Ñтупу да Ñ€ÑÑурÑу
+$ ENOMEM
+12 Ðе даÑтае памÑці
+$ EACCES
+13 Ðе даÑтае прывілеÑÑž
+$ EFAULT
+14 ÐекарÑктны адраÑ
+$ ENOTBLK
+15 Ðеабходна блочнае прыÑтаÑаванне
+$ EBUSY
+16 ПрыÑтаÑаванне занÑтае
+$ EEXIST
+17 Файл Ñ–Ñнуе
+$ EXDEV
+18 СпаÑылка на іншае прыÑтаÑаванне
+$ ENODEV
+19 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ падтрымліваецца прыÑтаÑаваннем
+$ ENOTDIR
+20 Пазначаны файл не з'ÑўлÑецца каталогам
+$ EISDIR
+21 Пазначаны файл з'ÑўлÑецца каталогам
+$ EINVAL
+22 Ðедапушчальны аргумент
+$ ENFILE
+23 Ðадта шмат адчыненых файлаў у ÑÑ–ÑÑ‚Ñме
+$ EMFILE
+24 Ðадта шмат адчыненых файлаў
+$ ENOTTY
+25 Выклік ioctl не падтрымліваецца прыÑтаÑаваннем
+$ ETXTBSY
+26 ТекÑтавы файл занÑÑ‚Ñ‹
+$ EFBIG
+27 Ðадта вÑлікі файл
+$ ENOSPC
+28 Ðа прыÑтаÑаванні не заÑталоÑÑ Ð¼ÐµÑца
+$ ESPIPE
+29 Ðедапушчальнае пазіцыÑнаванне
+$ EROFS
+30 Ð¤Ð°Ð¹Ð»Ð°Ð²Ð°Ñ ÑÑ–ÑÑ‚Ñма толькі Ð´Ð»Ñ Ñ‡Ñ‹Ñ‚Ð°Ð½Ð½Ñ
+$ EMLINK
+31 Ðадта шмат ÑпаÑылак
+$ EPIPE
+32 Канал пашкоджаны
+$ EDOM
+33 Ðедапушчальнае значÑнне лічбавага аргументу
+$ ERANGE
+34 Ðадта вÑлікі Ñ€Ñзультат
+$ EAGAIN, EWOULDBLOCK
+35 РÑÑÑƒÑ€Ñ Ñ‡Ð°Ñова недаÑтупны
+$ EINPROGRESS
+36 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ñž працÑÑе выкананнÑ
+$ EALREADY
+37 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ ÑžÐ¶Ð¾ выконваецца
+$ ENOTSOCK
+38 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð· Ñокетам прыменена не да Ñокету
+$ EDESTADDRREQ
+39 Патрабуецца Ð°Ð´Ñ€Ð°Ñ Ð¿Ñ€Ñ‹Ð·Ð½Ð°Ñ‡ÑннÑ
+$ EMSGSIZE
+40 Ðадта доўгае паведамленне
+$ EPROTOTYPE
+41 ÐÑправільны тып пратаколу Ð´Ð»Ñ Ñокету
+$ ENOPROTOOPT
+42 Пратакол недаÑтупны
+$ EPROTONOSUPPORT
+43 Пратакол не падтрымліваецца
+$ ESOCKTNOSUPPORT
+44 Тып Ñокету не падтрымліваецца
+$ EOPNOTSUPP
+45 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ падтрымліваецца
+$ EPFNOSUPPORT
+46 СÑмейÑтва пратаколаў не падтрымліваецца
+$ EAFNOSUPPORT
+47 СÑмейÑтва адраÑоў не падтрымліваецца ÑÑмейÑтвам пратаколаў
+$ EADDRINUSE
+48 ÐÐ´Ñ€Ð°Ñ ÑžÐ¶Ð¾ выкарыÑтоўваецца
+$ EADDRNOTAVAIL
+49 Ðе магчыма прызначыць дадзены адраÑ
+$ ENETDOWN
+50 Сетка не працуе
+$ ENETUNREACH
+51 Сетка недаÑÑжна
+$ ENETRESET
+52 ЗлучÑнне прыпынена Ñеткай
+$ ECONNABORTED
+53 Праграма выклікала аварыйнае завÑршÑнне злучÑннÑ
+$ ECONNRESET
+54 ЗлучÑнне завÑршана Ñупрацьлеглым бокам
+$ ENOBUFS
+55 Ðе заÑталоÑÑ Ð¼ÐµÑца пад буфер
+$ EISCONN
+56 Сокет ужо падлучаны
+$ ENOTCONN
+57 Сокет не падлучаны
+$ ESHUTDOWN
+58 Ðе магчыма даÑылаць паÑÐ»Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ†Ñ†Ñ Ñокету
+$ ETOOMANYREFS
+59 Ðадта шмат ÑпаÑылак: не магчыма злучыць
+$ ETIMEDOUT
+60 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð¿ÐµÑ€Ð°Ð²Ñ‹Ñіла чаÑавы ліміт
+$ ECONNREFUSED
+61 У злучÑнні адмоўлена
+$ ELOOP
+62 Ðадта шмат узроўнÑÑž Ñімвальных ÑпаÑылак
+$ ENAMETOOLONG
+63 Ðадта доўгае Ñ–Ð¼Ñ Ñ„Ð°Ð¹Ð»Ñƒ
+$ EHOSTDOWN
+64 ХоÑÑ‚ не працуе
+$ EHOSTUNREACH
+65 ÐÑма маршруту да хоÑту
+$ ENOTEMPTY
+66 Каталог не пуÑÑ‚Ñ‹
+$ EPROCLIM
+67 Ðадта шмат працÑÑаў
+$ EUSERS
+68 Ðадта шмат карыÑтальнікаў
+$ EDQUOT
+69 Перавышана дыÑÐºÐ°Ð²Ð°Ñ ÐºÐ²Ð¾Ñ‚Ð°
+$ ESTALE
+70 СаÑтарÑлы дÑÑкрыптар файлу NFS
+$ EREMOTE
+71 Ðадта шмат дыÑтанцыйных пераходаў на шлÑху
+$ EBADRPC
+72 ÐекарÑÐºÑ‚Ð½Ð°Ñ Ñтруктура RPC
+$ ERPCMISMATCH
+73 ÐÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ RPC
+$ EPROGUNAVAIL
+74 Праграма RPC недаÑÑжнаÑ
+$ EPROGMISMATCH
+75 ÐÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹
+$ EPROCUNAVAIL
+76 ÐекарÑÐºÑ‚Ð½Ð°Ñ Ð¿Ñ€Ð°Ñ†Ñдура Ð´Ð»Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹
+$ ENOLCK
+77 Блакіроўкі недаÑтупны
+$ ENOSYS
+78 Ð¤ÑƒÐ½ÐºÑ†Ñ‹Ñ Ð½Ðµ Ñ€Ñалізавана
+$ EFTYPE
+79 ÐепадыходзÑчы тып ці фармат файлу
+$ EAUTH
+80 Памылка аўтÑнтыфікацыі
+$ ENEEDAUTH
+81 Ðеабходна аўтÑнтыфікацыÑ
+$ EIDRM
+82 ІдÑнтыфікатар выдалены
+$ ENOMSG
+83 ÐÑма Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ‚Ñ€Ñбнага тыпу
+$ EOVERFLOW
+84 Ðадта вÑлікае значÑнне Ð´Ð»Ñ Ð·Ð°Ñ…Ð¾ÑžÐ²Ð°Ð½Ð½Ñ Ñž пазначаным тыпе дадзеных
+$ ECANCELED
+85 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð°Ð´Ð¼ÐµÐ½ÐµÐ½Ð°
+$ EILSEQ
+86 ÐÐµÐ´Ð°Ð·Ð²Ð¾Ð»ÐµÐ½Ð°Ñ Ð¿Ð°ÑлÑдоўнаÑць байтаў
+$ ENOATTR
+87 Ðтрыбут не знойдзены
+$ EDOOFUS
+88 Памылка праграмаваннÑ
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Разрыў ÑувÑзі
+$ SIGINT
+2 Перарванне па Ñігналу
+$ SIGQUIT
+3 Выхад
+$ SIGILL
+4 ÐÐµÐ´Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ–Ð½ÑтрукцыÑ
+$ SIGTRAP
+5 ПаÑтка траÑіроўкі/кропкі ÑпыненнÑ
+$ SIGABRT
+6 ПаÑтка аварыйнага завÑршÑннÑ
+$ SIGEMT
+7 ПаÑтка EMT
+$ SIGFPE
+8 Памылка Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð¿Ñ€Ð°Ñ†Ñ‹ з Ñ€Ñчыўным лікам
+$ SIGKILL
+9 ПрымуÑова Ñпынены
+$ SIGBUS
+10 Памылка шыны
+$ SIGSEGV
+11 Памылка Ñегментацыі
+$ SIGSYS
+12 Ðедапушчальны ÑÑ–ÑÑ‚Ñмны выклік
+$ SIGPIPE
+13 Канал пашкоджаны
+$ SIGALRM
+14 Спрацаваў таймер
+$ SIGTERM
+15 Завершаны
+$ SIGURG
+16 Ðеабходны Ñ‚Ñрміновы ўвод-вывад
+$ SIGSTOP
+17 Прыпыненне (Ñігнал)
+$ SIGTSTP
+18 Прыпыненне
+$ SIGCONT
+19 ПрацÑг працы
+$ SIGCHLD
+20 Завершана праца дачÑрнÑга працÑÑу
+$ SIGTTIN
+21 Спынены (увод з Ñ‚Ñрміналу)
+$ SIGTTOU
+22 Спынены (увод на Ñ‚Ñрмінал)
+$ SIGIO
+23 Увод-вывад магчымы
+$ SIGXCPU
+24 Перавышана абмежаванне працÑÑарнага чаÑу
+$ SIGXFSZ
+25 Перавышаны макÑімальны памер файлу
+$ SIGVTALRM
+26 Вычарпаны віртуальны таймер
+$ SIGPROF
+27 Вычарпаны таймер прафілÑваннÑ
+$ SIGWINCH
+28 Змена памеру вакна
+$ SIGINFO
+29 Запыт інфармацыі
+$ SIGUSR1
+30 Сігнал карыÑтальніка 1
+$ SIGUSR2
+31 Сігнал карыÑтальніка 2
diff --git a/lib/libc/nls/ca_ES.ISO8859-1.msg b/lib/libc/nls/ca_ES.ISO8859-1.msg
new file mode 100644
index 0000000..e786c29
--- /dev/null
+++ b/lib/libc/nls/ca_ES.ISO8859-1.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for ca_ES.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operació no permesa
+$ ENOENT
+2 Arxiu o directori inexistent
+$ ESRCH
+3 Procés inexistent
+$ EINTR
+4 Crida del sistema interrompuda
+$ EIO
+5 Error d'entrada/sortida
+$ ENXIO
+6 Dispositiu no configurat
+$ E2BIG
+7 Llista de paràmetres massa llarga
+$ ENOEXEC
+8 Error en el format de l'executable
+$ EBADF
+9 Descriptor d'arxiu incorrecte
+$ ECHILD
+10 No hi ha processos fills
+$ EDEADLK
+11 S'ha evitat el bloqueig del recurs
+$ ENOMEM
+12 No es pot assignar la memòria demanada
+$ EACCES
+13 Permís denegat
+$ EFAULT
+14 Adreça incorrecta
+$ ENOTBLK
+15 Es necessita un dispositiu de blocs
+$ EBUSY
+16 Dispositiu ocupat
+$ EEXIST
+17 L'arxiu ja existeix
+$ EXDEV
+18 Enllaç entre dispositius
+$ ENODEV
+19 Operació no suportada pel dispositiu
+$ ENOTDIR
+20 No és un directori
+$ EISDIR
+21 És un directori
+$ EINVAL
+22 Paràmetre incorrecte
+$ ENFILE
+23 Hi ha massa arxius oberts al sistema
+$ EMFILE
+24 Hi ha massa arxius oberts
+$ ENOTTY
+25 L'ioctl no és adecuat per al dispositiu
+$ ETXTBSY
+26 Arxiu de text ocupat
+$ EFBIG
+27 Arxiu massa gran
+$ ENOSPC
+28 No queda espai lliure en el dispositiu
+$ ESPIPE
+29 Cerca il·legal
+$ EROFS
+30 Sistema d'arxius de només lectura
+$ EMLINK
+31 Massa enllaços
+$ EPIPE
+32 Canal (pipe) trencat
+$ EDOM
+33 El resultat surt fora de rang
+$ ERANGE
+34 Resultat massa gran
+$ EAGAIN, EWOULDBLOCK
+35 El recurs no està disponible temporalment
+$ EINPROGRESS
+36 L'operació es troba en progrés actualment
+$ EALREADY
+37 L'operació ja es troba en progrés
+$ ENOTSOCK
+38 Operació de tipus socket en quelcom que no ho és
+$ EDESTADDRREQ
+39 Es requereix l'adreça de destí
+$ EMSGSIZE
+40 Missatge massa llarg
+$ EPROTOTYPE
+41 Tipus de protocol incorrecte per al socket
+$ ENOPROTOOPT
+42 Protocol no disponible
+$ EPROTONOSUPPORT
+43 Protocol no suportat
+$ ESOCKTNOSUPPORT
+44 Tipus de socket no suportat
+$ EOPNOTSUPP
+45 Operació no suportada
+$ EPFNOSUPPORT
+46 Família de protocols no suportada
+$ EAFNOSUPPORT
+47 Família d'adreces no suportada per la família de protocols
+$ EADDRINUSE
+48 L'adreça ja es troba en ús
+$ EADDRNOTAVAIL
+49 No es pot assignar l'adreça demanada
+$ ENETDOWN
+50 La xarxa no es troba disponible
+$ ENETUNREACH
+51 No es pot accedir a la xarxa
+$ ENETRESET
+52 La connexió a la xarxa s'ha perdut durant la reinicialització
+$ ECONNABORTED
+53 El programari ha causat l'avort de la connexió
+$ ECONNRESET
+54 L'interlocutor ha reinicialitzat la comunicació
+$ ENOBUFS
+55 No hi ha prou espai per a la memoria intermèdia (buffer)
+$ EISCONN
+56 El socket ja es troba connectat
+$ ENOTCONN
+57 El socket no es troba connectat
+$ ESHUTDOWN
+58 No es pot enviar desprès de la desconnexió del socket
+$ ETOOMANYREFS
+59 Hi ha massa referències: no es poden unir
+$ ETIMEDOUT
+60 El temps de connexió s'ha esgotat
+$ ECONNREFUSED
+61 Connexió rebutjada
+$ ELOOP
+62 Hi ha massa nivells d'enllaços simbòlics
+$ ENAMETOOLONG
+63 Nom d'arxiu massa llarg
+$ EHOSTDOWN
+64 La màquina no es troba disponible
+$ EHOSTUNREACH
+65 No hi ha cap camí fins a la màquina
+$ ENOTEMPTY
+66 El directori no està buit
+$ EPROCLIM
+67 Hi ha massa processos
+$ EUSERS
+68 Hi ha massa usuaris
+$ EDQUOT
+69 Quota de disc sobrepassada
+$ ESTALE
+70 Descriptor d'arxiu NFS incorrecte
+$ EREMOTE
+71 Massa nivells en el camí de destí
+$ EBADRPC
+72 L'estructura RPC es incorrecta
+$ ERPCMISMATCH
+73 La versió del RPC es incorrecta
+$ EPROGUNAVAIL
+74 El programa RPC no es troba disponible
+$ EPROGMISMATCH
+75 Versió incorrecta del programa
+$ EPROCUNAVAIL
+76 Procediment erroni per al programa
+$ ENOLCK
+77 No hi ha bloquejos disponibles
+$ ENOSYS
+78 Funció no implementada
+$ EFTYPE
+79 Tipus d'arxiu o de format inadequat
+$ EAUTH
+80 Error d'autenticació
+$ ENEEDAUTH
+81 Es necessita un autenticador
+$ EIDRM
+82 Identificador eliminat
+$ ENOMSG
+83 No hi ha missatges del tipus desitjat
+$ EOVERFLOW
+84 Valor massa gran per a ésser emmagatzemat en el tipus de dades
+$ EILSEQ
+85 Seqüència de bytes il·legal
+$ ENOTSUP
+86 No suportat
+$ ECANCELED
+87 Operació cancel·lada
+$ EBADMSG
+88 Missatje incorrecte o corrupte
+$ ENODATA
+89 No hi ha missatges disponibles
+$ ENOSR
+90 No hi ha recursos de tipus STREAM
+$ ENOSTR
+91 No és un STREAM
+$ ETIME
+92 Temps d'espera esgotat en el ioctl STREAM
+$ ENOATTR
+93 Atribut inexistent
+$ EMULTIHOP
+94 S'ha intentat un multisalt
+$ ENOLINK
+95 L'enllaç s'ha servit
+$ EPROTO
+96 Error de protocol
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fí de línia (hangup)
+$ SIGINT
+2 Interrupció
+$ SIGQUIT
+3 Finalització
+$ SIGILL
+4 Instrucció il·legal
+$ SIGTRAP
+5 Depuració (Trace/BPT)
+$ SIGABRT
+6 Crida d'avort
+$ SIGEMT
+7 Captura d'EMT
+$ SIGFPE
+8 Excepció de coma flotant
+$ SIGKILL
+9 Matat
+$ SIGBUS
+10 Error del bus
+$ SIGSEGV
+11 Error de segmentació
+$ SIGSYS
+12 Crida al sistema incorrecta
+$ SIGPIPE
+13 Canal (pipe) trencat
+$ SIGALRM
+14 Alarma de rellotge
+$ SIGTERM
+15 Finalitzat
+$ SIGURG
+16 Condició urgent d'E/S
+$ SIGSTOP
+17 Parat (per senyal)
+$ SIGTSTP
+18 Parat
+$ SIGCONT
+19 Continuant
+$ SIGCHLD
+20 El fill ha acabat
+$ SIGTTIN
+21 Parat (entrada de tty)
+$ SIGTTOU
+22 Parat (sortida de tty)
+$ SIGIO
+23 I/O permesa
+$ SIGXCPU
+24 S'ha sobrepassat el límit de temps de la CPU
+$ SIGXFSZ
+25 S'ha sobrepassat el límit de la longitud de l'arxiu
+$ SIGVTALRM
+26 El temporitzador virtual ha expirat
+$ SIGPROF
+27 El temporitzador del perfilador ha expirat
+$ SIGWINCH
+28 Canvis en la mida de la finestra
+$ SIGINFO
+29 Demanda d'informació
+$ SIGUSR1
+30 Senyal 1 definida per l'usuari
+$ SIGUSR2
+31 Senyal 2 definida per l'usuari
+$ SIGPWR
+32 Fallada/reinicialització de l'alimentació
diff --git a/lib/libc/nls/de_DE.ISO8859-1.msg b/lib/libc/nls/de_DE.ISO8859-1.msg
new file mode 100644
index 0000000..1bb4a3b
--- /dev/null
+++ b/lib/libc/nls/de_DE.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for de_DE.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operation nicht erlaubt
+$ ENOENT
+2 Datei oder Verzeichnis nicht gefunden
+$ ESRCH
+3 Prozess nicht gefunden
+$ EINTR
+4 Interrupt innerhalb eines Systemaufrufs
+$ EIO
+5 Ein-/Ausgabefehler
+$ ENXIO
+6 Gerät ist nicht konfiguriert
+$ E2BIG
+7 Argumentliste ist zu lang
+$ ENOEXEC
+8 Die Datei hat kein bekanntes ausführbares Format
+$ EBADF
+9 Ungültiger Dateideskriptor
+$ ECHILD
+10 Keine Kindprozesse
+$ EDEADLK
+11 Ein Deadlock wurde vermieden
+$ ENOMEM
+12 Kann nicht genug Speicher belegen
+$ EACCES
+13 Zugriff verweigert
+$ EFAULT
+14 Ungültige Adresse
+$ ENOTBLK
+15 Es wird ein Blockgerät benötigt
+$ EBUSY
+16 Das Gerät ist belegt
+$ EEXIST
+17 Datei existiert bereits
+$ EXDEV
+18 Link zwischen verschiedenen Geräten
+$ ENODEV
+19 Die Operation wird von diesem Gerät nicht unterstützt
+$ ENOTDIR
+20 Kein Verzeichnis
+$ EISDIR
+21 Ist ein Verzeichnis
+$ EINVAL
+22 Ungültiges Argument
+$ ENFILE
+23 Zu viele offene Dateien im System
+$ EMFILE
+24 Zu viele offene Dateien
+$ ENOTTY
+25 Ungültiger IOCTL für dieses Gerät
+$ ETXTBSY
+26 Datei wird benutzt
+$ EFBIG
+27 Datei zu groß
+$ ENOSPC
+28 Kein Platz mehr auf dem Gerät
+$ ESPIPE
+29 Ungültige Positionierung
+$ EROFS
+30 Dateisystem ist schreibgeschützt
+$ EMLINK
+31 Zu viele Links
+$ EPIPE
+32 Unterbrochene Pipe
+$ EDOM
+33 Numerisches Argument außerhalb des Wertebereichs
+$ ERANGE
+34 Ergebnis außerhalb des Wertebereichs
+$ EAGAIN, EWOULDBLOCK
+35 Ressource vorübergehend nicht verfügbar
+$ EINPROGRESS
+36 Operation wird gerade ausgeführt
+$ EALREADY
+37 Operation wird bereits ausgeführt
+$ ENOTSOCK
+38 Deskriptor ist kein Socket
+$ EDESTADDRREQ
+39 Zieladresse benötigt
+$ EMSGSIZE
+40 Nachricht zu lang
+$ EPROTOTYPE
+41 Ungültiger Protokolltyp für diesen Socket
+$ ENOPROTOOPT
+42 Protokoll nicht verfügbar
+$ EPROTONOSUPPORT
+43 Protokoll nicht unterstützt
+$ ESOCKTNOSUPPORT
+44 Sockettyp nicht unterstützt
+$ EOPNOTSUPP
+45 Operation nicht unterstützt
+$ EPFNOSUPPORT
+46 Protokollfamilie nicht unterstützt
+$ EAFNOSUPPORT
+47 Adressfamilie wird von der Protokollfamilie nicht unterstützt
+$ EADDRINUSE
+48 Adresse wird bereits benutzt
+$ EADDRNOTAVAIL
+49 Kann angeforderte Adresse nicht belegen
+$ ENETDOWN
+50 Netzwerk nicht verfügbar
+$ ENETUNREACH
+51 Netzwerk nicht erreichbar
+$ ENETRESET
+52 Netzwerk hat Verbindung mit Reset abgebrochen
+$ ECONNABORTED
+53 Software verursachte einen Verbindungsabbruch
+$ ECONNRESET
+54 Verbindung wurde von der Gegenstelle geschlossen
+$ ENOBUFS
+55 Keine Buffer verfügbar
+$ EISCONN
+56 Socket ist schon verbunden
+$ ENOTCONN
+57 Socket ist nicht verbunden
+$ ESHUTDOWN
+58 Kann nach einem Socket-Shutdown nicht mehr senden
+$ ETOOMANYREFS
+59 Zu viele Referenzen, kann nicht verbinden
+$ ETIMEDOUT
+60 Verbindungsabbruch durch Zeitüberschreitung
+$ ECONNREFUSED
+61 Verbindung wurde abgelehnt
+$ ELOOP
+62 Zu viele symbolische Links (zirkulär?)
+$ ENAMETOOLONG
+63 Dateiname zu lang
+$ EHOSTDOWN
+64 Host nicht verfügbar
+$ EHOSTUNREACH
+65 Keine Route zum Host
+$ ENOTEMPTY
+66 Verzeichnis ist nicht leer
+$ EPROCLIM
+67 Zu viele Prozesse
+$ EUSERS
+68 Zu viele Benutzer
+$ EDQUOT
+69 Platzlimit überschritten
+$ ESTALE
+70 Verwaister NFS-Dateideskriptor
+$ EREMOTE
+71 Zu viele Fernverweise in diesem Zugriff
+$ EBADRPC
+72 RPC-Struktur ist ungültig
+$ ERPCMISMATCH
+73 RPC-Version ist falsch
+$ EPROGUNAVAIL
+74 RPC-Programm nicht verfügbar
+$ EPROGMISMATCH
+75 Falsche Programmversion
+$ EPROCUNAVAIL
+76 Falsche Prozedur für dieses Programm
+$ ENOLCK
+77 Keine Dateisperren verfügbar
+$ ENOSYS
+78 Funktion nicht implementiert
+$ EFTYPE
+79 Ungültiger Dateityp oder Dateiformat
+$ EAUTH
+80 Authentifizierungsfehler
+$ ENEEDAUTH
+81 Authentikator benötigt
+$ EIDRM
+82 Identifizierung entfernt
+$ ENOMSG
+83 Keine Nachricht vom gewünschten Typ
+$ EOVERFLOW
+84 Wert zu groß, um in Datentyp zu speichern
+$ ECANCELED
+85 Operation abgebrochen
+$ EILSEQ
+86 Ungültige Byte-Sequenz
+$ ENOATTR
+87 Attribut nicht gefunden
+$ EDOOFUS
+88 Programmierfehler
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Verbindungsende
+$ SIGINT
+2 Unterbrechung
+$ SIGQUIT
+3 Programmende
+$ SIGILL
+4 Ungültiger Maschinenbefehl
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Fließkommafehler
+$ SIGKILL
+9 Unbedingter Programmabbruch
+$ SIGBUS
+10 Bus-Zugriffsfehler
+$ SIGSEGV
+11 Illegaler Speicherzugriff
+$ SIGSYS
+12 Ungültiger Systemaufruf
+$ SIGPIPE
+13 Unterbrochene Pipe
+$ SIGALRM
+14 Wecker
+$ SIGTERM
+15 Beendet
+$ SIGURG
+16 Dringende Ein/Ausgabeanforderung
+$ SIGSTOP
+17 Gestoppt (Signal)
+$ SIGTSTP
+18 Gestoppt
+$ SIGCONT
+19 Fortgesetzt
+$ SIGCHLD
+20 Kindprozess beendet
+$ SIGTTIN
+21 Gestoppt (Eingabe)
+$ SIGTTOU
+22 Gestoppt (Ausgabe)
+$ SIGIO
+23 Ein/Ausgabe möglich
+$ SIGXCPU
+24 CPU-Zeitlimit überschritten
+$ SIGXFSZ
+25 Dateigrößenlimit überschritten
+$ SIGVTALRM
+26 Virtueller Wecker abgelaufen
+$ SIGPROF
+27 Profil-Wecker abgelaufen
+$ SIGWINCH
+28 Fenstergröße hat sich verändert
+$ SIGINFO
+29 Informationsanforderung
+$ SIGUSR1
+30 Benutzerdefiniertes Signal 1
+$ SIGUSR2
+31 Benutzerdefiniertes Signal 2
diff --git a/lib/libc/nls/el_GR.ISO8859-7.msg b/lib/libc/nls/el_GR.ISO8859-7.msg
new file mode 100644
index 0000000..ca84929
--- /dev/null
+++ b/lib/libc/nls/el_GR.ISO8859-7.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for C locale (template)
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Ìç åðéôñåðôÞ åíÝñãåéá
+$ ENOENT
+2 Äåí õðÜñ÷åé ôÝôïéï áñ÷åßï Þ êáôÜëïãïò
+$ ESRCH
+3 Ç äéåñãáóßá áõôÞ äåí õðÜñ÷åé
+$ EINTR
+4 Ç êëÞóç óõóôÞìáôïò äéáêüðçêå
+$ EIO
+5 ÓöÜëìá åéóüäïõ/åîüäïõ
+$ ENXIO
+6 Ç óõóêåõÞ äåí Ý÷åé ñõèìéóôåß
+$ E2BIG
+7 Ç ëßóôá ôùí ðáñáìÝôñùí åßíáé ðïëý ìåãÜëç
+$ ENOEXEC
+8 ËáíèáóìÝíç ìïñöÞ åêôåëÝóéìïõ
+$ EBADF
+9 Ðñïâëçìáôéêüò ðåñéãñáöÝáò áñ÷åßïõ
+$ ECHILD
+10 Äåí õðÜñ÷ïõí åîáñôþìåíåò äéåñãáóßåò
+$ EDEADLK
+11 Áðïöåý÷èçêå áäéÝîïäï ðüñïõ
+$ ENOMEM
+12 Áäõíáìßá åê÷þñçóçò ìíÞìçò
+$ EACCES
+13 ¶ñíçóç ðñüóâáóçò
+$ EFAULT
+14 ËÜèïò äéåýèõíóç
+$ ENOTBLK
+15 Áðáéôåßôáé óõóêåõÞ ôýðïõ block
+$ EBUSY
+16 ÓõóêåõÞ êáôåéëçììÝíç
+$ EEXIST
+17 Ôï áñ÷åßï õðÜñ÷åé
+$ EXDEV
+18 Óýíäåóìïò ìåôáîý óõóêåõþí
+$ ENODEV
+19 Ç ëåéôïõñãßá äåí õðïóôçñßæåôáé áðü ôç óõóêåõÞ
+$ ENOTDIR
+20 Äåí åßíáé êáôÜëïãïò
+$ EISDIR
+21 Åßíáé êáôÜëïãïò
+$ EINVAL
+22 Ìç Ýãêõñç ðáñÜìåôñïò
+$ ENFILE
+23 ÕðåñâïëéêÜ ðïëëÜ áíïéêôÜ áñ÷åßá óôï óýóôçìá
+$ EMFILE
+24 ÕðåñâïëéêÜ ðïëëÜ áíïéêôÜ áñ÷åßá
+$ ENOTTY
+25 ÁêáôÜëëçëï ioctl ãéá ôç óõóêåõÞ
+$ ETXTBSY
+26 Ôï áñ÷åßï êåéìÝíïõ åßíáé êáôåéëçììÝíï
+$ EFBIG
+27 Ðïëý ìåãÜëï áñ÷åßï
+$ ENOSPC
+28 Äåí Ý÷åé ìåßíåé åëåýèåñïò ÷þñïò óôç óõóêåõÞ
+$ ESPIPE
+29 ÁêáôÜëëçëç áíß÷íåõóç
+$ EROFS
+30 Ôï óýóôçìá áñ÷åßùí åßíáé ìüíï ãéá áíÜãíùóç
+$ EMLINK
+31 ÐÜñá ðïëëïß óýíäåóìïé
+$ EPIPE
+32 Äéáêïðåßóá óùëÞíùóç
+$ EDOM
+33 Ôï áñéèìçôéêü üñéóìá åßíáé åêôüò ïñßùí
+$ ERANGE
+34 Ðïëý ìåãÜëï áðïôÝëåóìá
+$ EAGAIN, EWOULDBLOCK
+35 Ï ðüñïò äåí åßíáé äéáèÝóéìïò ðñïóùñéíÜ
+$ EINPROGRESS
+36 Ç ëåéôïõñãßá âñßóêåôáé óå åîÝëéîç ôþñá
+$ EALREADY
+37 Ç ëåéôïõñãßá åßíáé Þäç óå åîÝëéîç
+$ ENOTSOCK
+38 Ëåéôïõñãßá õðïäï÷Þò óå ìç-õðïäï÷Þ
+$ EDESTADDRREQ
+39 Áðáéôåßôáé äéåýèõíóç ðñïïñéóìïý
+$ EMSGSIZE
+40 Ðïëý ìåãÜëï ìÞíõìá
+$ EPROTOTYPE
+41 ËÜèïò ôýðïõ ðñùôüêïëëï ãéá õðïäï÷Þ
+$ ENOPROTOOPT
+42 Ôï ðñùôüêïëëï äåí åßíáé äéáèÝóéìï
+$ EPROTONOSUPPORT
+43 Ôï ðñùôüêïëëï äåí õðïóôçñßæåôáé
+$ ESOCKTNOSUPPORT
+44 Ï ôýðïò ôçò õðïäï÷Þò äåí õðóôçñßæåôáé
+$ EOPNOTSUPP
+45 Ç ëåéôïõñãßá äåí õðïóôçñßæåôáé
+$ EPFNOSUPPORT
+46 Äåí õðïóôçñßæåôáé ç ïéêïãÝíåéá ðñùôïêüëëùí
+$ EAFNOSUPPORT
+47 Ç ïéêïãÝíåéá äéåõèýíóåùí äåí õðïóôçñßæåôáé áðü ôçí ïéêïãÝíåéá ðñùôïêüëëùí
+$ EADDRINUSE
+48 Ç äéåýèõíóç ÷ñçóéìïðïéåßôáé Þäç
+$ EADDRNOTAVAIL
+49 Äåí ìðïñåß íá ãßíåé áíÜèåóç ôçò æçôïýìåíçò äéåýèõíóçò
+$ ENETDOWN
+50 Ôï äßêôõï äåí ëåéôïõñãåß
+$ ENETUNREACH
+51 Äåí õðÜñ÷åé äéáäñïìÞ ðñïò ôï äßêôõï
+$ ENETRESET
+52 Ôï äßêôõï äéÝêïøå ôç óýíäåóç êáôÜ ôçí åðáíáöïñÜ
+$ ECONNABORTED
+53 Ôï ëïãéóìéêü ðñïêÜëåóå ôåñìáôéóìü ôçò óýíäåóçò
+$ ECONNRESET
+54 Ç óýíäåóç ôåñìáôßóôçêå áðü ôçí Üëëç ìåñéÜ
+$ ENOBUFS
+55 Äåí õðÜñ÷åé äéáèÝóéìïò ðñïóùñéíüò ÷þñïò
+$ EISCONN
+56 Ç õðïäï÷Þ Ý÷åé Þäç óõíäåèåß
+$ ENOTCONN
+57 Ç õðïäï÷Þ äåí Ý÷åé óõíäåèåß
+$ ESHUTDOWN
+58 Äåí åßíáé äõíáôÞ ç áðïóôïëÞ ìåôÜ ôïí ôåñìáôéóìü ôçò õðïäï÷Þò
+$ ETOOMANYREFS
+59 ÐÜñá ðïëëÝò áíáöïñÝò: äåí ìðïñåß íá ãßíåé óõíÝíùóç
+$ ETIMEDOUT
+60 ÔÝëïò ÷ñüíïõ äéáäéêáóßáò
+$ ECONNREFUSED
+61 ¶ñíçóç óýíäåóçò
+$ ELOOP
+62 ÐÜñá ðïëëÜ åðßðåäá óõìâïëéêþí óõíäÝóåùí
+$ ENAMETOOLONG
+63 Ðïëý ìåãÜëï üíïìá áñ÷åßïõ
+$ EHOSTDOWN
+64 Ôï óýóôçìá äåí åßíáé óå ëåéôïõñãßá
+$ EHOSTUNREACH
+65 Äåí õðÜñ÷åé äéáäñïìÞ ðñïò ôï óýóôçìá
+$ ENOTEMPTY
+66 Ï êáôÜëïãïò äåí åßíáé Üäåéïò
+$ EPROCLIM
+67 ÕðåñâïëéêÜ ðïëëÝò äéåñãáóßåò
+$ EUSERS
+68 ÕðåñâïëéêÜ ðïëëïß ÷ñÞóôåò
+$ EDQUOT
+69 ÕðÝñâáóç ïñßùí ÷ñÞóçò äßóêïõ
+$ ESTALE
+70 ¶êõñï handle áñ÷åßïõ óôï NFS
+$ EREMOTE
+71 ÐÜñá ðïëëÜ áðïìáêñõóìÝíá åðßðåäá óôç äéáäñïìÞ
+$ EBADRPC
+72 Ç äïìÞ RPC åßíáé ðñïâëçìáôéêÞ
+$ ERPCMISMATCH
+73 ËáíèáóìÝíç Ýêäïóç RPC
+$ EPROGUNAVAIL
+74 Ôï ðñüãñáììá RPC äåí åßíáé äéáèÝóéìï
+$ EPROGMISMATCH
+75 ËáíèáóìÝíç Ýêäïóç ðñïãñÜììáôïò
+$ EPROCUNAVAIL
+76 ÐñïâëçìáôéêÞ äéáäéêáóßá ãéá ôï ðñüãñáììá
+$ ENOLCK
+77 Äåí õðÜñ÷ïõí äéáèÝóéìá êëåéäþìáôá
+$ ENOSYS
+78 Ç ëåéôïõñãßá äåí Ý÷åé õëïðïéçèåß
+$ EFTYPE
+79 ËáíèáóìÝíïò ôýðïò Þ ìïñöÞ áñ÷åßïõ
+$ EAUTH
+80 ÓöÜëìá êáôÜ ôçí ðéóôïðïßçóç áõèåíôéêüôçôáò
+$ ENEEDAUTH
+81 Áðáéôåßôáé ðéóôïðïéçôÞò áõèåíôéêüôçôáò
+$ EIDRM
+82 Ôï áíáãíùñéóôéêü Ý÷åé áöáéñåèåß
+$ ENOMSG
+83 Äåí õðÜñ÷åé ìÞíõìá ôïõ êáèïñéóìÝíïõ ôýðïõ
+$ EOVERFLOW
+84 Ç ôéìÞ åßíáé ðïëý ìåãÜëç ãéá íá áðïèçêåõèåß óôïí ôýðï äåäïìÝíùí
+$ ECANCELED
+85 Ç ëåéôïõñãßá áêõñþèçêå
+$ EILSEQ
+86 Ìç-Ýãêõñç áêïëïõèßá bytes
+$ ENOATTR
+87 Ôï ÷áñáêôçñéóôéêü äåí âñÝèçêå
+$ EDOOFUS
+88 ÓöÜëìá ðñïãñáììáôéóìïý
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Êëåßóéìï
+$ SIGINT
+2 ÄéáêïðÞ
+$ SIGQUIT
+3 Ôåñìáôéóìüò
+$ SIGILL
+4 Ìç-Ýãêõñç åíôïëÞ
+$ SIGTRAP
+5 Ðáãßäá Trace/BPT
+$ SIGABRT
+6 Ðáãßäá áêýñùóçò
+$ SIGEMT
+7 Ðáãßäá EMT
+$ SIGFPE
+8 Åîáßñåóç êéíçôÞò õðïäéáóôïëÞò
+$ SIGKILL
+9 Ôåñìáôßóôçêå
+$ SIGBUS
+10 ÓöÜëìá äéáýëïõ
+$ SIGSEGV
+11 ÓöÜëìá Segmentation
+$ SIGSYS
+12 ÊáêÞ êëÞóç óõóôÞìáôïò
+$ SIGPIPE
+13 ÄéáêïðÞ pipe
+$ SIGALRM
+14 Ñïëüé åéäïðïßçóçò
+$ SIGTERM
+15 Ôåñìáôßóôçêå
+$ SIGURG
+16 ¸êôáêôç êáôÜóôáóç É/Ï
+$ SIGSTOP
+17 Óå áíáìïíÞ (óÞìá)
+$ SIGTSTP
+18 Óå áíáìïíÞ
+$ SIGCONT
+19 Óõíå÷ßæåôáé
+$ SIGCHLD
+20 ÔÝëïò åîáñôþìåíçò äéåñãáóßáò
+$ SIGTTIN
+21 ÄéáêïðÞ (åßóïäïò tty)
+$ SIGTTOU
+22 ÄéáêïðÞ (Ýîïäïò tty)
+$ SIGIO
+23 Äõíáôüôçôá I/O
+$ SIGXCPU
+24 ÎåðåñÜóôçêå ôï üñéï ÷ñÞóçò ôçò CPU
+$ SIGXFSZ
+25 ÎåðåñÜóôçêå ôï ìÝãéóôï ìÝãåèïò áñ÷åßïõ
+$ SIGVTALRM
+26 ÅîáíôëÞèçêå ï åéêïíéêüò ÷ñïíïìåôñçôÞò
+$ SIGPROF
+27 ÅîáíôëÞèçêå ï ÷ñïíïìåôñçôÞò profiling
+$ SIGWINCH
+28 Ôï ìÝãåèïò ôïõ ðáñáèýñïõ áëëÜæåé
+$ SIGINFO
+29 Áßôçóç ãéá ðëçñïöïñßá
+$ SIGUSR1
+30 ÓÞìá 1 êáèïñéóìÝíï áðü ôï ÷ñÞóôç
+$ SIGUSR2
+31 ÓÞìá 2 êáèïñéóìÝíï áðü ôï ÷ñÞóôç
diff --git a/lib/libc/nls/es_ES.ISO8859-1.msg b/lib/libc/nls/es_ES.ISO8859-1.msg
new file mode 100644
index 0000000..8fc9c7d
--- /dev/null
+++ b/lib/libc/nls/es_ES.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for es_ES.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operación no permitida
+$ ENOENT
+2 Fichero o directorio inexistente
+$ ESRCH
+3 Proceso inexistente
+$ EINTR
+4 Llamada del sistema interrumpida
+$ EIO
+5 Error de Entrada/Salida
+$ ENXIO
+6 Dispositivo no configurado
+$ E2BIG
+7 La lista de argumentos es demasiado larga
+$ ENOEXEC
+8 Error en el formato del ejecutable
+$ EBADF
+9 Descriptor incorrecto de fichero
+$ ECHILD
+10 No hay procesos hijo
+$ EDEADLK
+11 Se ha evitado el bloqueo del recurso
+$ ENOMEM
+12 No se pudo asignar memoria
+$ EACCES
+13 Permiso denegado
+$ EFAULT
+14 Dirección incorrecta
+$ ENOTBLK
+15 Se necesita un dispositivo de bloques
+$ EBUSY
+16 Dispositivo ocupado
+$ EEXIST
+17 El fichero ya existe
+$ EXDEV
+18 Enlace entre dispositivos
+$ ENODEV
+19 Operación inadecuada para este dispositivo
+$ ENOTDIR
+20 No es un directorio
+$ EISDIR
+21 Es un directorio
+$ EINVAL
+22 Argumento inadecuado
+$ ENFILE
+23 Hay demasiados ficheros abiertos en el sistema
+$ EMFILE
+24 Hay demasiados ficheros abiertos
+$ ENOTTY
+25 ioctl inapropiado para el dispositivo
+$ ETXTBSY
+26 Fichero de texto ocupado
+$ EFBIG
+27 Fichero demasiado grande
+$ ENOSPC
+28 No queda espacio libre en el dispositivo
+$ ESPIPE
+29 Illegal seek
+$ EROFS
+30 Sistema de ficheros de solo lectura
+$ EMLINK
+31 Demasiados enlaces
+$ EPIPE
+32 Canal (pipe) roto
+$ EDOM
+33 Argumento numérico fuera de rango
+$ ERANGE
+34 El resultado es demasiado grande
+$ EAGAIN, EWOULDBLOCK
+35 el recurso no está disponible temporalmente
+$ EINPROGRESS
+36 Operación en proceso
+$ EALREADY
+37 La operación ya se está ejecutando
+$ ENOTSOCK
+38 Operación de socket inaceptable para el dispositivo
+$ EDESTADDRREQ
+39 Se necesita una dirección de destino
+$ EMSGSIZE
+40 Mensaje demasiado largo
+$ EPROTOTYPE
+41 Tipo erróneo de protocolo para el socket
+$ ENOPROTOOPT
+42 protocolo no disponible
+$ EPROTONOSUPPORT
+43 Protocolo no contemplado
+$ ESOCKTNOSUPPORT
+44 Tipo de socket no contemplado
+$ EOPNOTSUPP
+45 Operación no contemplada
+$ EPFNOSUPPORT
+46 Familia de protocolos no contemplada
+$ EAFNOSUPPORT
+47 Familia de direcciones no contemplada por la familia de protocolos
+$ EADDRINUSE
+48 La dirección ya está siendo usada
+$ EADDRNOTAVAIL
+49 No se pudo asignar la dirección requerida
+$ ENETDOWN
+50 La red no funciona
+$ ENETUNREACH
+51 No se ha podido acceder a la red
+$ ENETRESET
+52 La conexión de red se ha interrumpido al reinicializar
+$ ECONNABORTED
+53 Conexión perdida por problemas en el software
+$ ECONNRESET
+54 El interlocutor ha reinicializado la conexión
+$ ENOBUFS
+55 No queda espacio en el búfer
+$ EISCONN
+56 El socket ya estaba conectado
+$ ENOTCONN
+57 El socket no está conectado
+$ ESHUTDOWN
+58 No se puede enviar tras la desconexión del socket
+$ ETOOMANYREFS
+59 Demasiadas referencias: no se pueden unir
+$ ETIMEDOUT
+60 El tiempo de conexión ha expirado
+$ ECONNREFUSED
+61 Conexión rehusada
+$ ELOOP
+62 Demasiados niveles de enlaces simbólicos
+$ ENAMETOOLONG
+63 Nombre de fichero demasiado largo
+$ EHOSTDOWN
+64 La máquina está fuera de servicio
+$ EHOSTUNREACH
+65 No hay ruta hasta la máquina
+$ ENOTEMPTY
+66 Directorio no vacío
+$ EPROCLIM
+67 Demasiados procesos
+$ EUSERS
+68 Demasiados usuarios
+$ EDQUOT
+69 Cuota de disco sobrepasada
+$ ESTALE
+70 Descriptor de fichero NFS inválido
+$ EREMOTE
+71 Ruta con demasiados niveles
+$ EBADRPC
+72 La estructura de la RPC es errónea
+$ ERPCMISMATCH
+73 La versón de la RPC es errónea
+$ EPROGUNAVAIL
+74 La RPC no está accesible
+$ EPROGMISMATCH
+75 Versión errónea del programa
+$ EPROCUNAVAIL
+76 Procedimiento erróneo para el programa
+$ ENOLCK
+77 No hay bloqueos disponibles
+$ ENOSYS
+78 Función no realizada
+$ EFTYPE
+79 Tipo de fichero o formato inapropiado
+$ EAUTH
+80 Error de autentificación
+$ ENEEDAUTH
+81 Se necesita un autenticador
+$ EIDRM
+82 Identificador eliminado
+$ ENOMSG
+83 No hay mensajes del tipo deseado
+$ EOVERFLOW
+84 Valor demasiado grande para almacenarse en el tipo deseado
+$ ECANCELED
+85 Operación cancelada
+$ EILSEQ
+86 Illegal byte sequence
+$ ENOATTR
+87 Atributo no encontrado
+$ EDOOFUS
+88 Error de programación
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fín de línea (Hangup)
+$ SIGINT
+2 Interrumpido
+$ SIGQUIT
+3 Terminado
+$ SIGILL
+4 Illegal instruction
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Excepción de coma flotante
+$ SIGKILL
+9 Matado
+$ SIGBUS
+10 Error en el bus
+$ SIGSEGV
+11 Fallo de segmentación
+$ SIGSYS
+12 Llamada al sistema errónea
+$ SIGPIPE
+13 Canal (pipe) roto
+$ SIGALRM
+14 Alarma del reloj
+$ SIGTERM
+15 Terminado
+$ SIGURG
+16 Condición urgente de E/S
+$ SIGSTOP
+17 Detenido (señal)
+$ SIGTSTP
+18 Detenido
+$ SIGCONT
+19 Continuando
+$ SIGCHLD
+20 Proceso hijo terminado
+$ SIGTTIN
+21 Detenido (entrada tty)
+$ SIGTTOU
+22 Detenido (salida tty)
+$ SIGIO
+23 E/S posible
+$ SIGXCPU
+24 Se ha sobrepasado el tiempo límite de la CPU
+$ SIGXFSZ
+25 Se ha sobrepasado el límite de tamaño de fichero
+$ SIGVTALRM
+26 Temporizador virtual expirado
+$ SIGPROF
+27 Temporizador de perfilación expirado
+$ SIGWINCH
+28 Cambios en el tamaño de ventana
+$ SIGINFO
+29 Petición de información
+$ SIGUSR1
+30 Señal definida por el usuario n1
+$ SIGUSR2
+31 Señal definida por el usuario n2
diff --git a/lib/libc/nls/fi_FI.ISO8859-1.msg b/lib/libc/nls/fi_FI.ISO8859-1.msg
new file mode 100644
index 0000000..491f9a1
--- /dev/null
+++ b/lib/libc/nls/fi_FI.ISO8859-1.msg
@@ -0,0 +1,233 @@
+$ $FreeBSD$
+$
+$ Message catalog for fi_FI.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Toimintoa ei sallita
+$ ENOENT
+2 Tiedostoa tai hakemistoa ei löydy
+$ ESRCH
+3 Prosessia ei löydy
+$ EINTR
+4 Systeemikutsu keskeytyi
+$ EIO
+5 Syöttö/tulostusvirhe
+$ ENXIO
+6 Laitetta ei määritelty
+$ E2BIG
+7 Liikaa argumentteja
+$ ENOEXEC
+8 Tuntematon ohjelmatyyppi
+$ EBADF
+9 Virheellinen tiedosto-osoitin
+$ ECHILD
+10 Ei lapsiprosesseja
+$ EDEADLK
+11 Resurssin ristiinlukitus vältetty
+$ ENOMEM
+12 Muistinvaraus epäonnistui
+$ EACCES
+13 Lupa kielletty
+$ EFAULT
+14 Virheellinen osoite
+$ ENOTBLK
+15 Tarvitaan lohko-osoitettava laite
+$ EBUSY
+16 Laite käytössä
+$ EEXIST
+17 Tiedosto on jo olemassa
+$ EXDEV
+18 Laitteiden välinen linkki
+$ ENODEV
+19 Laite ei tue toimintoa
+$ ENOTDIR
+20 Kohde ei ole hakemisto
+$ EISDIR
+21 Kohde on hakemisto
+$ EINVAL
+22 Virheellinen argumentti
+$ ENFILE
+23 Järjestelmässä on liian monta avointa tiedostoa
+$ EMFILE
+24 Liian monta avointa tiedostoa
+$ ENOTTY
+25 Virheellinen ohjaustoiminto laitteelle
+$ ETXTBSY
+26 Tiedosto on käytössä
+$ EFBIG
+27 Tiedosto liian suuri
+$ ENOSPC
+28 Laitteella ei ole tilaa
+$ ESPIPE
+29 Virheellinen haku
+$ EROFS
+30 Vain luettava tiedostojärjestelmä
+$ EMLINK
+31 Liian monta linkkiä
+$ EPIPE
+32 Katkennut putki
+$ EDOM
+33 Numeerinen syöte virheellinen
+$ ERANGE
+34 Tulos liian suuri
+$ EAGAIN, EWOULDBLOCK
+35 Resurssi ei ole tilapäisesti saatavilla
+$ EINPROGRESS
+36 Toiminta on käynnissä
+$ EALREADY
+37 Toiminta oli jo käynnissä
+$ ENOTSOCK
+38 Socket-operaatio muulla kuin socketilla
+$ EDESTADDRREQ
+39 Tarvitaan kohdeosoite
+$ EMSGSIZE
+40 Sanoma liian pitkä
+$ EPROTOTYPE
+41 Väärä protokolla socketille
+$ ENOPROTOOPT
+42 Protokolla ei ole käytettävissä
+$ EPROTONOSUPPORT
+43 Protokollaa ei tueta
+$ ESOCKTNOSUPPORT
+44 Socket-tyyppiä ei tueta
+$ EOPNOTSUPP
+45 Toimintoa ei tueta
+$ EPFNOSUPPORT
+46 Protokollaperhettä ei tueta
+$ EAFNOSUPPORT
+47 Protokollaperhe ei tue osoiteperhettä
+$ EADDRINUSE
+48 Osoite on jo käytössä
+$ EADDRNOTAVAIL
+49 Ei pysty antamaan pyydettyä osoitetta
+$ ENETDOWN
+50 Verkko ei ole käytettävissä
+$ ENETUNREACH
+51 Verkkoon ei ole yhteyttä
+$ ENETRESET
+52 Verkko sulki yhteyden
+$ ECONNABORTED
+53 Ohjelmiston aiheuttama yhteyden keskeytyminen
+$ ECONNRESET
+54 Isäntä nollasi yhteyden
+$ ENOBUFS
+55 Puskuritila on lopussa
+$ EISCONN
+56 Yhteys on jo olemassa
+$ ENOTCONN
+57 Yhteyttä ei ole olemassa
+$ ESHUTDOWN
+58 Lähettäminen ei ole mahdollista yhteyden katkaisun jälkeen
+$ ETOOMANYREFS
+59 Liikaa viittauksia: ei voi yhdistää
+$ ETIMEDOUT
+60 Yhteyden aikavalvontakatkaisu
+$ ECONNREFUSED
+61 Yhteys hylätty
+$ ELOOP
+62 Liian monta peräkkäistä symbolista linkkiä
+$ ENAMETOOLONG
+63 Tiedoston nimi on liian pitkä
+$ EHOSTDOWN
+64 Isäntä ei vastaa
+$ EHOSTUNREACH
+65 Ei reittiä isäntään
+$ ENOTEMPTY
+66 Hakemisto ei ole tyhjä
+$ EPROCLIM
+67 Liian monta prosessia
+$ EUSERS
+68 Liian monta käyttäjää
+$ EDQUOT
+69 Levytilarajoitus ylittyi
+$ ESTALE
+70 Vanhentunut NFS-yhteys
+$ EREMOTE
+71 Liian monta verkkolevyä polussa
+$ EBADRPC
+72 Virheellinen RPC-pyyntö
+$ ERPCMISMATCH
+73 Väärä RPC-versio
+$ EPROGUNAVAIL
+74 RPC ei käytettävissä
+$ EPROGMISMATCH
+75 Väärä ohjelmaversio
+$ EPROCUNAVAIL
+76 Väärä RPC-pyyntö ohjelmalle
+$ ENOLCK
+77 Lukitus ei käytettävissä
+$ ENOSYS
+78 Toimintoa ei ole
+$ EFTYPE
+79 Väärä tiedostotyyppi tai -formaatti
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Katkaisu
+$ SIGINT
+2 Keskeytys
+$ SIGQUIT
+3 Lopetus
+$ SIGILL
+4 Laiton käsky
+$ SIGTRAP
+5 Jäljitys/BPT ansa
+$ SIGABRT
+6 Poistumisansa
+$ SIGEMT
+7 EMT-ansa
+$ SIGFPE
+8 Liukulukuvirhe
+$ SIGKILL
+9 Tapettu
+$ SIGBUS
+10 Väylävirhe
+$ SIGSEGV
+11 Suojausvirhe
+$ SIGSYS
+12 Virheellinen systeemikutsu
+$ SIGPIPE
+13 Katkennut putki
+$ SIGALRM
+14 Hälytyskello
+$ SIGTERM
+15 Lopetettu
+$ SIGURG
+16 Kiireellinen syöttö/tulostus
+$ SIGSTOP
+17 Pysäytetty (signaali)
+$ SIGTSTP
+18 Pysäytetty
+$ SIGCONT
+19 Jatkettu
+$ SIGCHLD
+20 Lapsiprosessi päättynyt
+$ SIGTTIN
+21 Pysäytetty (tty-syöte)
+$ SIGTTOU
+22 Pysäytetty (tty-tuloste)
+$ SIGIO
+23 Syöttö ja tulostus mahdollisia
+$ SIGXCPU
+24 Keskusyksikköaikarajoitus ylitetty
+$ SIGXFSZ
+25 Tiedoston kokorajoitus ylitetty
+$ SIGVTALRM
+26 Virtuaali-ajastin laukesi
+$ SIGPROF
+27 Profilointiajastin laukesi
+$ SIGWINCH
+28 Ikkunan koko muuttuu
+$ SIGINFO
+29 Informaatiopyyntö
+$ SIGUSR1
+30 Käyttäjän määriteltävä signaali 1
+$ SIGUSR2
+31 Käyttäjän määriteltävä signaali 2
+$ SIGPWR
+32 Virransaannin tilassa muutos
diff --git a/lib/libc/nls/fr_FR.ISO8859-1.msg b/lib/libc/nls/fr_FR.ISO8859-1.msg
new file mode 100644
index 0000000..35a8c4a
--- /dev/null
+++ b/lib/libc/nls/fr_FR.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for fr_FR.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Opération non autorisée
+$ ENOENT
+2 Fichier ou répertoire inexistant
+$ ESRCH
+3 Processus inconnu
+$ EINTR
+4 Appel système interrompu
+$ EIO
+5 Erreur d'entrée/sortie
+$ ENXIO
+6 Dispositif non configuré
+$ E2BIG
+7 Liste d'arguments trop longue
+$ ENOEXEC
+8 Format d'exécutable invalide
+$ EBADF
+9 Mauvais descripteur de fichier
+$ ECHILD
+10 Pas de processus fils
+$ EDEADLK
+11 Étreinte mortelle détectée
+$ ENOMEM
+12 Impossible d'allouer de la mémoire
+$ EACCES
+13 Permission refusée
+$ EFAULT
+14 Mauvaise adresse
+$ ENOTBLK
+15 Dispositif en mode bloc requis
+$ EBUSY
+16 Dispositif occupé
+$ EEXIST
+17 Le fichier existe
+$ EXDEV
+18 Lien inter-unités
+$ ENODEV
+19 Opération non supportée par le dispositif
+$ ENOTDIR
+20 Pas un répertoire
+$ EISDIR
+21 Est un répertoire
+$ EINVAL
+22 Argument invalide
+$ ENFILE
+23 Trop de fichiers ouverts sur le système
+$ EMFILE
+24 Trop de fichiers ouverts
+$ ENOTTY
+25 Fonction inadaptée au dispositif
+$ ETXTBSY
+26 Fichier en cours d'utilisation
+$ EFBIG
+27 Fichier trop grand
+$ ENOSPC
+28 Plus d'espace disponible
+$ ESPIPE
+29 Recherche illégale
+$ EROFS
+30 Système de fichier en lecture seulement
+$ EMLINK
+31 Trop de liens
+$ EPIPE
+32 Tube déconnecté
+$ EDOM
+33 Argument numérique hors définition
+$ ERANGE
+34 Résultat trop grand
+$ EAGAIN, EWOULDBLOCK
+35 Ressource indisponible temporairement
+$ EINPROGRESS
+36 Opération en cours
+$ EALREADY
+37 Opération déjà en cours
+$ ENOTSOCK
+38 Opération de type socket sur un descripteur de fichier
+$ EDESTADDRREQ
+39 Adresse de destination obligatoire
+$ EMSGSIZE
+40 Message trop long
+$ EPROTOTYPE
+41 Mauvais type de protocole pour la socket
+$ ENOPROTOOPT
+42 Protocole non disponible
+$ EPROTONOSUPPORT
+43 Protocole non supporté
+$ ESOCKTNOSUPPORT
+44 Type de socket non supporté
+$ EOPNOTSUPP
+45 Opération non supporté
+$ EPFNOSUPPORT
+46 Famille de protocole non supportée
+$ EAFNOSUPPORT
+47 Famille d'adresse non supportée par la famille de protocole
+$ EADDRINUSE
+48 Adresse en cours d'utilisation
+$ EADDRNOTAVAIL
+49 Impossible d'assigner l'adresse demandée
+$ ENETDOWN
+50 Plus de réseau
+$ ENETUNREACH
+51 Réseau inaccessible
+$ ENETRESET
+52 Connexion coupée par le réseau
+$ ECONNABORTED
+53 Connexion interrompue
+$ ECONNRESET
+54 Connexion interrompue par l'hôte distant
+$ ENOBUFS
+55 Tampon saturé
+$ EISCONN
+56 La socket est déjà connectée
+$ ENOTCONN
+57 La socket n'est pas connectée
+$ ESHUTDOWN
+58 Impossible d'envoyer après la coupure
+$ ETOOMANYREFS
+59 Trop de références : lien impossible
+$ ETIMEDOUT
+60 Dépassement du délai d'attente
+$ ECONNREFUSED
+61 Connexion refusée
+$ ELOOP
+62 Trop de niveaux de liens symboliques
+$ ENAMETOOLONG
+63 Nom de fichier trop long
+$ EHOSTDOWN
+64 Hôte distant arrêté
+$ EHOSTUNREACH
+65 Pas de route vers l'hôte distant
+$ ENOTEMPTY
+66 Répertoire non vide
+$ EPROCLIM
+67 Trop de processus
+$ EUSERS
+68 Trop d'utilisateurs
+$ EDQUOT
+69 Quota de disque dépassé
+$ ESTALE
+70 Identificateur de fichier NFS périmé
+$ EREMOTE
+71 Trop de niveaux extérieurs dans le path
+$ EBADRPC
+72 Mauvaise structure RPC
+$ ERPCMISMATCH
+73 Mauvaise version RPC
+$ EPROGUNAVAIL
+74 Prog. RPC indisponible
+$ EPROGMISMATCH
+75 Mauvaise version de programme
+$ EPROCUNAVAIL
+76 Mauvaise procédure pour le programme
+$ ENOLCK
+77 Plus de verrous disponibles
+$ ENOSYS
+78 Fonction non implémentée
+$ EFTYPE
+79 Type de fichier ou format inapproprié
+$ EAUTH
+80 Erreur d'authentification
+$ ENEEDAUTH
+81 Authentification requise
+$ EIDRM
+82 Identifiant retiré
+$ ENOMSG
+83 Aucun message du type souhaité
+$ EOVERFLOW
+84 Valeur trop grande pour le type de donnée
+$ ECANCELED
+85 Opération annulée
+$ EILSEQ
+86 Séquence d'octets illégale
+$ ENOATTR
+87 Attribut non trouvé
+$ EDOOFUS
+88 Erreur de programmation
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fin de connexion
+$ SIGINT
+2 Interruption
+$ SIGQUIT
+3 Quitter
+$ SIGILL
+4 Instruction illégale
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Exception sur virgule flottante
+$ SIGKILL
+9 Tué
+$ SIGBUS
+10 Bus error
+$ SIGSEGV
+11 Segmentation fault
+$ SIGSYS
+12 Bad system call
+$ SIGPIPE
+13 Broken pipe
+$ SIGALRM
+14 Alarm clock
+$ SIGTERM
+15 Terminé
+$ SIGURG
+16 Urgent I/O condition
+$ SIGSTOP
+17 Suspended (signal)
+$ SIGTSTP
+18 Suspended
+$ SIGCONT
+19 Continued
+$ SIGCHLD
+20 Child exited
+$ SIGTTIN
+21 Stopped (tty input)
+$ SIGTTOU
+22 Stopped (tty output)
+$ SIGIO
+23 I/O possible
+$ SIGXCPU
+24 Cputime limit exceeded
+$ SIGXFSZ
+25 Filesize limit exceeded
+$ SIGVTALRM
+26 Virtual timer expired
+$ SIGPROF
+27 Profiling timer expired
+$ SIGWINCH
+28 Window size changes
+$ SIGINFO
+29 Information request
+$ SIGUSR1
+30 User defined signal 1
+$ SIGUSR2
+31 User defined signal 2
diff --git a/lib/libc/nls/hu_HU.ISO8859-2.msg b/lib/libc/nls/hu_HU.ISO8859-2.msg
new file mode 100644
index 0000000..90b597b
--- /dev/null
+++ b/lib/libc/nls/hu_HU.ISO8859-2.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for hu_HU.ISO8859-2 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Nem engedélyezett mûvelet
+$ ENOENT
+2 Fájl vagy könyvtár nem található
+$ ESRCH
+3 Processz nem található
+$ EINTR
+4 Megszakított rendszerhívás
+$ EIO
+5 B/K hiba
+$ ENXIO
+6 Konfigurálatlan eszköz
+$ E2BIG
+7 Túl hosszú argumentumlista
+$ ENOEXEC
+8 Hibás végrehajtható formátum
+$ EBADF
+9 Rossz fájlleíró
+$ ECHILD
+10 Nem létezõ gyermek processz
+$ EDEADLK
+11 Resource deadlock avoided
+$ ENOMEM
+12 Memória nem foglalható le
+$ EACCES
+13 Hozzáférés megtagadva
+$ EFAULT
+14 Rossz cím
+$ ENOTBLK
+15 Blokkos eszköz szükséges
+$ EBUSY
+16 Eszköz foglalt
+$ EEXIST
+17 Fájl létezik
+$ EXDEV
+18 Kereszthivatkozás eszközökön
+$ ENODEV
+19 A mûvelet nem támogatott az eszköz által
+$ ENOTDIR
+20 Nem könyvtár
+$ EISDIR
+21 Könyvtár
+$ EINVAL
+22 Érvénytelen argumentum
+$ ENFILE
+23 Túl sok megnyitott fájl a rendszerben
+$ EMFILE
+24 Túl sok megnyitott fájl
+$ ENOTTY
+25 Nem megfelelõ ioctl az eszközhöz
+$ ETXTBSY
+26 Szöveges fájl foglalt
+$ EFBIG
+27 Fájl túl nagy
+$ ENOSPC
+28 Nincs hely az eszközön
+$ ESPIPE
+29 Érvénytelen seek
+$ EROFS
+30 Csak olvasható fájlrendszer
+$ EMLINK
+31 Túl sok link
+$ EPIPE
+32 Hibás csõvezeték
+$ EDOM
+33 Numerikus argumentum nem esik a tartományba
+$ ERANGE
+34 Az esermény túl nagy
+$ EAGAIN, EWOULDBLOCK
+35 Az erõforrás ideiglenesen nem érhetõ el
+$ EINPROGRESS
+36 A mûvelet folyamatban van
+$ EALREADY
+37 A mûvelet már folyamatban van
+$ ENOTSOCK
+38 Socket mûvelet nem socketen
+$ EDESTADDRREQ
+39 Cél cím szükséges
+$ EMSGSIZE
+40 Túl hosszú üzenet
+$ EPROTOTYPE
+41 Rossz protokolltípus a sockethez
+$ ENOPROTOOPT
+42 Protokoll nem érhetõ el
+$ EPROTONOSUPPORT
+43 Protokoll nem támogatott
+$ ESOCKTNOSUPPORT
+44 Sockettípus nem támogatott
+$ EOPNOTSUPP
+45 Mûvelet nem támogatott
+$ EPFNOSUPPORT
+46 Protokollcsalád nem támogatott
+$ EAFNOSUPPORT
+47 A címcsalád nem támogatott a protokollcsalád által
+$ EADDRINUSE
+48 A cím már használatban van
+$ EADDRNOTAVAIL
+49 A kért cím nem osztható ki
+$ ENETDOWN
+50 A hálózat nem mûködik
+$ ENETUNREACH
+51 A hálózat nem érhetõ el
+$ ENETRESET
+52 A hálózat megszakította a kapcsolatot
+$ ECONNABORTED
+53 A szoftver megszakította a kapcsolatot
+$ ECONNRESET
+54 A kapcsolatot megszakította a peer
+$ ENOBUFS
+55 Nincs rendelkezésre álló pufferterület
+$ EISCONN
+56 A socket már kapcsolódva van
+$ ENOTCONN
+57 A socket nincs kapcsolódva
+$ ESHUTDOWN
+58 Nem küldhetõ el a socket lebontása után
+$ ETOOMANYREFS
+59 Túl sok hivatkozás: nem illeszthetõ össze
+$ ETIMEDOUT
+60 A mûvelet túllépte a rendelkezésre álló idõt
+$ ECONNREFUSED
+61 Kapcsolat elutasítva
+$ ELOOP
+62 Túl sok szint a szimbolikus linkekben
+$ ENAMETOOLONG
+63 Túl hosszú fájlnév
+$ EHOSTDOWN
+64 A kiszolgáló nem érhetõ el
+$ EHOSTUNREACH
+65 Nincs útvonal a kiszolgálóhoz
+$ ENOTEMPTY
+66 Könyvtár nem üres
+$ EPROCLIM
+67 Túl sok processz
+$ EUSERS
+68 Túl sok felhasználó
+$ EDQUOT
+69 A lemezkvóta túllépve
+$ ESTALE
+70 Elavult NFS fájlkezelõ
+$ EREMOTE
+71 Túl sok szint a távoli útvonalban
+$ EBADRPC
+72 Rossz RPC struktúra
+$ ERPCMISMATCH
+73 Rossz RPC verzió
+$ EPROGUNAVAIL
+74 RPC program nem érhetõ el
+$ EPROGMISMATCH
+75 Rossz programverzió
+$ EPROCUNAVAIL
+76 Rossz eljárás a programhoz
+$ ENOLCK
+77 Nincs elérhetõ zárolás
+$ ENOSYS
+78 Nem implementált funkció
+$ EFTYPE
+79 Nem megfelelõ fájltípus vagy formátum
+$ EAUTH
+80 Azonosítási hiba
+$ ENEEDAUTH
+81 Azonosítás szükséges
+$ EIDRM
+82 Azonosító eltávolítva
+$ ENOMSG
+83 Nincs üzenet a kívánt típusból
+$ EOVERFLOW
+84 Az érték túl nagy az adott adattípusban való tároláshoz
+$ ECANCELED
+85 Mûvelet törölva
+$ EILSEQ
+86 Érvénytelen bájtsorrend
+$ ENOATTR
+87 Attribútum nem található
+$ EDOOFUS
+88 Programozási hiba
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Megszakítás
+$ SIGQUIT
+3 Kilépés
+$ SIGILL
+4 Érvénytelen mûvelet
+$ SIGTRAP
+5 Trace/BPT csapda
+$ SIGABRT
+6 Abort csapda
+$ SIGEMT
+7 EMT csapda
+$ SIGFPE
+8 Lebegõpontos kivétel
+$ SIGKILL
+9 Megölve
+$ SIGBUS
+10 Busz hiba
+$ SIGSEGV
+11 Szegmentációs hiba
+$ SIGSYS
+12 Rossz rendszerhívás
+$ SIGPIPE
+13 Hibás csõvezeték
+$ SIGALRM
+14 Idõzítési riasztás
+$ SIGTERM
+15 Befejezve
+$ SIGURG
+16 Sürgõs B/K feltétel
+$ SIGSTOP
+17 Elaltatva (szignál)
+$ SIGTSTP
+18 Elaltatva
+$ SIGCONT
+19 Folytatva
+$ SIGCHLD
+20 Gyermek befejezõdött
+$ SIGTTIN
+21 Leállítva (tty bevitel)
+$ SIGTTOU
+22 Leállítva (tty kivitel)
+$ SIGIO
+23 B/K lehetséges
+$ SIGXCPU
+24 Processzoridõ-korlátozás túllépve
+$ SIGXFSZ
+25 ájlméret-korlátozás túllépve
+$ SIGVTALRM
+26 Virtuális idõzítõ lejárt
+$ SIGPROF
+27 Profilidõzítõ lejárt
+$ SIGWINCH
+28 Ablakméret-változások
+$ SIGINFO
+29 Információkérés
+$ SIGUSR1
+30 Felhasználói szignál 1
+$ SIGUSR2
+31 Felhasználói szignál 2
diff --git a/lib/libc/nls/it_IT.ISO8859-15.msg b/lib/libc/nls/it_IT.ISO8859-15.msg
new file mode 100644
index 0000000..da3734d
--- /dev/null
+++ b/lib/libc/nls/it_IT.ISO8859-15.msg
@@ -0,0 +1,231 @@
+$ $FreeBSD$
+$
+$ Message catalog for it_IT.ISO8859-15 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operazione non permessa
+$ ENOENT
+2 File o directory inesistente
+$ ESRCH
+3 Processo inesistente
+$ EINTR
+4 Chiamata di sistema interrotta
+$ EIO
+5 Errore di input/output
+$ ENXIO
+6 Periferica non configurata
+$ E2BIG
+7 Lista degli argomenti troppo lunga
+$ ENOEXEC
+8 Errore nel formato eseguibile
+$ EBADF
+9 Descrittore di file non valido
+$ ECHILD
+10 Nessun processo figlio
+$ EDEADLK
+11 Situazione di deadlock evitata
+$ ENOMEM
+12 Impossibile allocare memoria
+$ EACCES
+13 Permesso negato
+$ EFAULT
+14 Indirizzo non valido
+$ ENOTBLK
+15 Periferica a blocchi necessaria
+$ EBUSY
+16 Periferica occupata
+$ EEXIST
+17 Il file esiste
+$ EXDEV
+18 Link improprio
+$ ENODEV
+19 Operazione non supportata dalla periferica
+$ ENOTDIR
+20 Non è una directory
+$ EISDIR
+21 E' una directory
+$ EINVAL
+22 Argomento non valido
+$ ENFILE
+23 Troppi file aperti nel sistema
+$ EMFILE
+24 Troppi file aperti
+$ ENOTTY
+25 Ioctl inappropriata per la periferica
+$ ETXTBSY
+26 File di testo occupato
+$ EFBIG
+27 File troppo grande
+$ ENOSPC
+28 Spazio sulla periferica esaurito
+$ ESPIPE
+29 Ricerca non valida
+$ EROFS
+30 Filesystem di sola lettura
+$ EMLINK
+31 Troppi link
+$ EPIPE
+32 Pipe rotta
+$ EDOM
+33 Argomento numerico fuori dal dominio
+$ ERANGE
+34 Risultato troppo grande
+$ EAGAIN, EWOULDBLOCK
+35 Risorsa temporaneamente non disponibile
+$ EINPROGRESS
+36 Operazione in esecuzione
+$ EALREADY
+37 Operazione già in esecuzione
+$ ENOTSOCK
+38 Operazione sui socket eseguita su un non-socket
+$ EDESTADDRREQ
+39 Indirizzo destinazione necessario
+$ EMSGSIZE
+40 Messaggio troppo lungo
+$ EPROTOTYPE
+41 Tipo di protocollo non valido per il socket
+$ ENOPROTOOPT
+42 Protocollo non disponibile
+$ EPROTONOSUPPORT
+43 Protocollo non supportato
+$ ESOCKTNOSUPPORT
+44 Tipo di socket non supportato
+$ EOPNOTSUPP
+45 Operazione non supportata
+$ EPFNOSUPPORT
+46 Famiglia di protocolli non supportata
+$ EAFNOSUPPORT
+47 Famiglia di indirizzi non supportata dalla famiglia di protocolli
+$ EADDRINUSE
+48 Indirizzo già in uso
+$ EADDRNOTAVAIL
+49 Impossibile assegnare l'indirizzo richiesto
+$ ENETDOWN
+50 Network fuori uso
+$ ENETUNREACH
+51 Network non raggiungibile
+$ ENETRESET
+52 Network dropped connection on reset
+$ ECONNABORTED
+53 Interruzione della connessione causata dal software
+$ ECONNRESET
+54 Connessione azzerata dal corrispondente
+$ ENOBUFS
+55 Spazio del buffer esaurito
+$ EISCONN
+56 Socket già connesso
+$ ENOTCONN
+57 Socket non connesso
+$ ESHUTDOWN
+58 Impossibile inviare dopo la chiusura del socket
+$ ETOOMANYREFS
+59 Troppe referenze: impossibile raccordare
+$ ETIMEDOUT
+60 Connessione scaduta
+$ ECONNREFUSED
+61 Connection rifiutata
+$ ELOOP
+62 Troppi livelli di link simbolici
+$ ENAMETOOLONG
+63 Nome di file troppo lungo
+$ EHOSTDOWN
+64 Host fuori uso
+$ EHOSTUNREACH
+65 Host irraggiungibile
+$ ENOTEMPTY
+66 Directory non vuota
+$ EPROCLIM
+67 Troppi processi
+$ EUSERS
+68 Troppi utenti
+$ EDQUOT
+69 Quota disco superata
+$ ESTALE
+70 Manipolatore di file NFS scaduto
+$ EREMOTE
+71 Troppi livelli remoti nel path
+$ EBADRPC
+72 Struttura RPC non valida
+$ ERPCMISMATCH
+73 Versione RPC non corrispondente
+$ EPROGUNAVAIL
+74 Programma RPC non disponibile
+$ EPROGMISMATCH
+75 Versione del programma non corrispodente
+$ EPROCUNAVAIL
+76 Procedura non disponibile
+$ ENOLCK
+77 Nessun lock disponibile
+$ ENOSYS
+78 Funzione non implementata
+$ EFTYPE
+79 Tipo di file o formato inappropriato
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Interruzione
+$ SIGQUIT
+3 Chiusura
+$ SIGILL
+4 Istruzione illegale
+$ SIGTRAP
+5 Trappola Trace/breakpoint
+$ SIGABRT
+6 Trappola abort()
+$ SIGEMT
+7 Trappola EMT
+$ SIGFPE
+8 Errore di virgola mobile
+$ SIGKILL
+9 Ucciso
+$ SIGBUS
+10 Errore di bus
+$ SIGSEGV
+11 Errore di segmentazione
+$ SIGSYS
+12 Chiamata di sistema non valida
+$ SIGPIPE
+13 Pipe rotta
+$ SIGALRM
+14 Sveglia
+$ SIGTERM
+15 Terminato
+$ SIGURG
+16 I/O urgente
+$ SIGSTOP
+17 Processo fermato
+$ SIGTSTP
+18 Stop da terminale
+$ SIGCONT
+19 Continuato
+$ SIGCHLD
+20 Processo figlio uscito
+$ SIGTTIN
+21 Input da terminale per processo in background
+$ SIGTTOU
+22 Output a terminale per processo in background
+$ SIGIO
+23 I/O possibile
+$ SIGXCPU
+24 Limite del tempo di CPU superato
+$ SIGXFSZ
+25 Limite della dimensione del file superato
+$ SIGVTALRM
+26 Timer virtuale scaduto
+$ SIGPROF
+27 Timer di profilo expired
+$ SIGWINCH
+28 Cambio di dimensione della finestra
+$ SIGINFO
+29 Richiesta di informazioni
+$ SIGUSR1
+30 Segnale definito dall'utente 1
+$ SIGUSR2
+31 Segnale definito dall'utente 2
diff --git a/lib/libc/nls/mn_MN.UTF-8.msg b/lib/libc/nls/mn_MN.UTF-8.msg
new file mode 100644
index 0000000..29ab4c1
--- /dev/null
+++ b/lib/libc/nls/mn_MN.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for mn_MN.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ҮйлдÑл зөвшөөрөгдөхгүй
+$ ENOENT
+2 Тийм файл ÑÑвÑл Ñан алга
+$ ESRCH
+3 Тийм процеÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ EINTR
+4 СиÑтемийн таÑалдÑан дуудлага
+$ EIO
+5 Оролт/гаралтын алдаа
+$ ENXIO
+6 Төхөөрөмж тохируулагдаагүй
+$ E2BIG
+7 Дагавар өгөгдлийн жагÑаалт Ñ…ÑÑ‚Ñрхий урт
+$ ENOEXEC
+8 Exec Ñ…ÑлбÑршилтийн алдаа
+$ EBADF
+9 Файлын буруу тодорхойлогч
+$ ECHILD
+10 ХүүхÑд процеÑÑ Ð°Ð»Ð³Ð°
+$ EDEADLK
+11 Эх Ò¯Ò¯ÑвÑрийн Ð³Ð°Ñ†Ð°Ð°Ð½Ð°Ð°Ñ Ð·Ð°Ð¹Ð»ÑхийÑÑн
+$ ENOMEM
+12 Санах ойд зай байрлуулж чадахгүй байна
+$ EACCES
+13 Ð—Ó©Ð²ÑˆÓ©Ó©Ñ€Ó©Ñ…Ó©Ó©Ñ Ñ‚Ð°Ñ‚Ð³Ð°Ð»Ð·Ñан
+$ EFAULT
+14 Буруу хаÑг
+$ ENOTBLK
+15 Блок төхөөрөмж шаардагдÑан
+$ EBUSY
+16 Төхөөрөмж завгүй
+$ EEXIST
+17 Файл байна
+$ EXDEV
+18 Төхөөрөмж хоорондын холбооÑ
+$ ENODEV
+19 Үйлдлийг төхөөрөмж дÑмжÑÑгүй
+$ ENOTDIR
+20 Сан биш
+$ EISDIR
+21 Сан мөн
+$ EINVAL
+22 Дагавар өгөгдөл буруу
+$ ENFILE
+23 СиÑтемд Ñ…ÑÑ‚Ñрхий олон нÑÑлттÑй файл байна
+$ EMFILE
+24 Ð¥ÑÑ‚Ñрхий олон нÑÑлттÑй файл байна
+$ ENOTTY
+25 ТөхөөрөмжтÑй тохирохгүй ioctl үйлдÑл
+$ ETXTBSY
+26 ТекÑÑ‚ файл завгүй
+$ EFBIG
+27 Файл Ñ…ÑÑ‚Ñрхий том
+$ ENOSPC
+28 Төхөөрөмж дÑÑÑ€ зай үлдÑÑнгүй
+$ ESPIPE
+29 Хайлт буруу
+$ EROFS
+30 Зөвхөн-уншигдах файлын ÑиÑтем
+$ EMLINK
+31 Ð¥ÑÑ‚Ñрхий олон Ñ…Ð¾Ð»Ð±Ð¾Ð¾Ñ Ð±Ð°Ð¹Ð½Ð°
+$ EPIPE
+32 ЭвдÑрхий хоолой
+$ EDOM
+33 Тоон дагавар өгөгдөл Ñ‚Ð°Ð»Ð±Ð°Ñ€Ð°Ð°Ñ Ð³Ð°Ð´Ð½Ð° байна
+$ ERANGE
+34 Үр дүн Ñ…ÑÑ‚Ñрхий том
+$ EAGAIN, EWOULDBLOCK
+35 Эх Ò¯Ò¯ÑвÑÑ€ түр зуур боломжгүй байна
+$ EINPROGRESS
+36 ҮйлдÑл одоо хийгдÑж байна
+$ EALREADY
+37 ҮйлдÑл аль Ñ…Ñдийн хийгдÑж байна
+$ ENOTSOCK
+38 Сокет Ð±ÑƒÑ Ð·Ò¯Ð¹Ð» дÑÑÑ€ Ñокет үйлдÑл
+$ EDESTADDRREQ
+39 Очих хаÑг шаардагдÑан
+$ EMSGSIZE
+40 Ð—ÑƒÑ€Ð²Ð°Ñ Ð¼ÑдÑÑ Ñ…ÑÑ‚Ñрхий урт
+$ EPROTOTYPE
+41 Сокетийн хувьд протокол буруу төрлийнх байна
+$ ENOPROTOOPT
+42 Протокол байхгүй
+$ EPROTONOSUPPORT
+43 Протокол дÑмжигдÑÑгүй
+$ ESOCKTNOSUPPORT
+44 Сокетийн төрөл дÑмжигдÑÑгүй
+$ EOPNOTSUPP
+45 ҮйлдÑл дÑмжигдÑÑгүй
+$ EPFNOSUPPORT
+46 Протоколын гÑÑ€ бүл дÑмжигдÑÑгүй
+$ EAFNOSUPPORT
+47 ХаÑгийн гÑÑ€ бүлийг протоколын гÑÑ€ бүл дÑмжÑÑгүй
+$ EADDRINUSE
+48 ХаÑг ашиглагдаж байна
+$ EADDRNOTAVAIL
+49 Ð¥Ò¯ÑÑÑн хаÑгийг өгч чадахгүй
+$ ENETDOWN
+50 СүлжÑÑ ÑƒÐ½Ð°Ñан байна
+$ ENETUNREACH
+51 СүлжÑÑнд хүрÑÑ… боломжгүй
+$ ENETRESET
+52 Салгалт хийгдÑÑ…Ñд ÑүлжÑÑ Ñ…Ð¾Ð»Ð±Ð¾Ð»Ñ‚Ñ‹Ð³ унагалаа
+$ ECONNABORTED
+53 Програм Ñ…Ð°Ð½Ð³Ð°Ð¼Ð¶Ð°Ð°Ñ Ð±Ð¾Ð»Ð¶ холболт зогÑлоо
+$ ECONNRESET
+54 Холболтыг харилцагч Ñалгалаа
+$ ENOBUFS
+55 Буфферийн зай байхгүй
+$ EISCONN
+56 Сокет аль Ñ…Ñдийн холбогдÑон
+$ ENOTCONN
+57 Сокет холбогдоогүй
+$ ESHUTDOWN
+58 Сокет унтарÑны дараа илгÑÑж чадахгүй
+$ ETOOMANYREFS
+59 Ð¥ÑÑ‚Ñрхий их хамаарлууд байна: залгаж чадахгүй
+$ ETIMEDOUT
+60 Үйлдлийн хугацаа дууÑÑан
+$ ECONNREFUSED
+61 Холболт Ñ‚Ð¾Ð³Ñ‚Ð¾Ð¾Ñ…Ð¾Ð¾Ñ Ñ‚Ð°Ñ‚Ð³Ð°Ð»Ð·Ð»Ð°Ð°
+$ ELOOP
+62 ТÑмдÑгт холбооÑуудын түвшин Ñ…ÑÑ‚Ñрхий олон байна
+$ ENAMETOOLONG
+63 Файлын нÑÑ€ Ñ…ÑÑ‚Ñрхий урт
+$ EHOSTDOWN
+64 Төв компьютер зогÑÑон байна
+$ EHOSTUNREACH
+65 Төв компьютер Ñ€Ò¯Ò¯ чиглүүлÑлт байхгүй
+$ ENOTEMPTY
+66 Сан хооÑон биш
+$ EPROCLIM
+67 Ð¥ÑÑ‚Ñрхий олон үйлдÑл байна
+$ EUSERS
+68 Ð¥ÑÑ‚Ñрхий олон Ñ…ÑÑ€ÑглÑгч байна
+$ EDQUOT
+69 ДиÑкийн Ñ…Ñзгаар Ñ…ÑмжÑÑ Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ ESTALE
+70 ХуучирÑан NFS файлын жолоо
+$ EREMOTE
+71 Зам Ñ…ÑÑ‚Ñрхий алÑлагдÑан түвшинтÑй байна
+$ EBADRPC
+2 RPC бүтÑц буруу
+$ ERPCMISMATCH
+73 RPC-ийн хувилбар буруу
+$ EPROGUNAVAIL
+74 RPC програм байхгүй
+$ EPROGMISMATCH
+75 Програмын хувилбар буруу
+$ EPROCUNAVAIL
+76 Програмын хувьд процедур буруу
+$ ENOLCK
+77 ТүгжÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ ENOSYS
+78 Функц гүйцÑтгÑгдÑÑгүй
+$ EFTYPE
+79 Файлын төрөл ÑÑвÑл Ñ…ÑлбÑршилт тохироогүй
+$ EAUTH
+80 ÐÑвтрүүлÑÑ… алдаа
+$ ENEEDAUTH
+81 ÐÑвтррүүлÑгч Ñ…ÑÑ€ÑгтÑй
+$ EIDRM
+82 Танигч уÑтгагдÑан
+$ ENOMSG
+83 Ð¥Ò¯ÑÑÑн төрлийн Ð·ÑƒÑ€Ð²Ð°Ñ Ð¼ÑдÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ EOVERFLOW
+84 Утга нь өгөгдлийн төрөлд хадгалагдаж болохооргүй Ñ…ÑÑ‚Ñрхий том байна
+$ ECANCELED
+85 ҮйлдÑл зогÑоогдÑон
+$ EILSEQ
+86 Байтын дараалал буруу
+$ ENOATTR
+87 Ðтрибут олдÑонгүй
+$ EDOOFUS
+88 Програмчлалын алдаа
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ЗогÑоох (Hangup)
+$ SIGINT
+2 ТаÑалдал
+$ SIGQUIT
+3 Гарах
+$ SIGILL
+4 Буруу заавар
+$ SIGTRAP
+5 Мөр/BPT занга
+$ SIGABRT
+6 ТаÑлан зогÑоох занга
+$ SIGEMT
+7 EMT занга
+$ SIGFPE
+8 Хөвөгч цÑгийн онцгой алдаа
+$ SIGKILL
+9 ХөнөөÑөн
+$ SIGBUS
+10 Шугамын алдаа
+$ SIGSEGV
+11 Сегментийн гÑмтÑл
+$ SIGSYS
+12 СиÑтемийн буруу дуудлага
+$ SIGPIPE
+13 ЭвдÑрхий хоолой
+$ SIGALRM
+14 СÑрүүлÑгт цаг
+$ SIGTERM
+15 ТөгÑÑөн
+$ SIGURG
+16 Яаралтай I/O нөхцөл
+$ SIGSTOP
+17 Түр зогÑÑон (дохио)
+$ SIGTSTP
+18 Түр зогÑÑон
+$ SIGCONT
+19 ҮргÑлжилÑÑн
+$ SIGCHLD
+20 ХүүхÑд процеÑÑ Ð³Ð°Ñ€Ñан
+$ SIGTTIN
+21 ЗогÑÑон (tty оролт)
+$ SIGTTOU
+22 ЗогÑÑон (tty гаралт)
+$ SIGIO
+23 I/O боломжтой
+$ SIGXCPU
+24 CPU-ийн хугацааны Ñ…Ñзгаар Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ SIGXFSZ
+25 Файлын Ñ…ÑмжÑÑний Ñ…Ñзгаар Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ SIGVTALRM
+26 Виртуал цаг Ñ…Ñмжигчийн хугацаа дууÑÑан
+$ SIGPROF
+27 Профил хийх цаг Ñ…Ñмжигчийн хугацаа дууÑÑан
+$ SIGWINCH
+28 Цонхны Ñ…ÑмжÑÑний өөрчлөлт
+$ SIGINFO
+29 ÐœÑдÑÑллийн Ñ…Ò¯ÑÑлт
+$ SIGUSR1
+30 Ð¥ÑÑ€ÑглÑгчийн тодорхойлÑон дохио 1
+$ SIGUSR2
+31 Ð¥ÑÑ€ÑглÑгчийн тодорхойлÑон дохио 2
diff --git a/lib/libc/nls/nl_NL.ISO8859-1.msg b/lib/libc/nls/nl_NL.ISO8859-1.msg
new file mode 100644
index 0000000..47103d4
--- /dev/null
+++ b/lib/libc/nls/nl_NL.ISO8859-1.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for nl_NL.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Bewerking niet toegestaan
+$ ENOENT
+2 Bestand of map niet gevonden
+$ ESRCH
+3 Taak bestaat niet
+$ EINTR
+4 Onderbroken systeemaanroep
+$ EIO
+5 Invoer/uitvoer fout
+$ ENXIO
+6 Apparaat niet geconfigureerd
+$ E2BIG
+7 Argumentenlijst is te lang
+$ ENOEXEC
+8 Programma kan niet worden uitgevoerd
+$ EBADF
+9 Ongeldige bestandsverwijzing
+$ ECHILD
+10 Geen kindprocessen
+$ EDEADLK
+11 Een deadlock is vermeden
+$ ENOMEM
+12 Kan geen geheugen meer verkrijgen
+$ EACCES
+13 Toegang geweigerd
+$ EFAULT
+14 Ongeldig adres
+$ ENOTBLK
+15 Een per blok adresseerbaar apparaat is vereist
+$ EBUSY
+16 Apparaat is bezig
+$ EEXIST
+17 Bestand bestaat reeds
+$ EXDEV
+18 Verwijzing tussen bestanden op verschillende bestandssystemen
+$ ENODEV
+19 Bewerking wordt niet ondersteund door dit apparaat
+$ ENOTDIR
+20 Dit is geen map
+$ EISDIR
+21 Dit is een map
+$ EINVAL
+22 Ongeldig argument
+$ ENFILE
+23 Te veel open bestanden in het systeem
+$ EMFILE
+24 Te veel open bestanden
+$ ENOTTY
+25 ioctl niet van toepassing op dit apparaat
+$ ETXTBSY
+26 Programmabestand is bezig
+$ EFBIG
+27 Bestand is te groot
+$ ENOSPC
+28 Geen ruimte meer op dit apparaat
+$ ESPIPE
+29 Onuitvoerbare zoekopdracht
+$ EROFS
+30 Van dit bestandssysteem kan alleen worden gelezen
+$ EMLINK
+31 Te veel bestandsverwijzingen
+$ EPIPE
+32 Gebroken pijp
+$ EDOM
+33 Numeriek argument valt buiten domein
+$ ERANGE
+34 Resultaat te groot of te klein
+$ EAGAIN, EWOULDBLOCK
+35 Middel tijdelijk onbeschikbaar
+$ EINPROGRESS
+36 Bewerking in gang gezet
+$ EALREADY
+37 Bewerking is al in gang gezet
+$ ENOTSOCK
+38 Voor deze bewerking is een contactpunt vereist
+$ EDESTADDRREQ
+39 Een bestemmingsadres is vereist
+$ EMSGSIZE
+40 Te grote bericht
+$ EPROTOTYPE
+41 Protocol past niet bij dit contactpunt
+$ ENOPROTOOPT
+42 Protocol is niet beschikbaar
+$ EPROTONOSUPPORT
+43 Protocol is niet ondersteund
+$ ESOCKTNOSUPPORT
+44 Dit soort contactpunt is niet ondersteund
+$ EOPNOTSUPP
+45 Bewerking niet ondersteund
+$ EPFNOSUPPORT
+46 Protocolfamilie niet ondersteund
+$ EAFNOSUPPORT
+47 Adressenfamilie niet ondersteund door protocolfamilie
+$ EADDRINUSE
+48 Adres is al in gebruik
+$ EADDRNOTAVAIL
+49 Het gevraagde adres kan niet worden toegekend
+$ ENETDOWN
+50 Netwerk is plat
+$ ENETUNREACH
+51 Netwerk is onbereikbaar
+$ ENETRESET
+52 Netwerk onderbrak verbinding tijdens herstart
+$ ECONNABORTED
+53 Verbroken verbinding veroorzaakt door software
+$ ECONNRESET
+54 Verbinding werd aan de andere kant verbroken
+$ ENOBUFS
+55 Geen bufferruimte meer beschikbaar
+$ EISCONN
+56 Dit contactpunt is al verbonden
+$ ENOTCONN
+57 Contactpunt is niet verbonden
+$ ESHUTDOWN
+58 Een afgesloten contactpunt kan geen gegevens meer verzenden
+$ ETOOMANYREFS
+59 Te veel verwijzingen: splitsen niet mogelijk
+$ ETIMEDOUT
+60 Verbinding te lang niet mogelijk
+$ ECONNREFUSED
+61 Verbinding geweigerd
+$ ELOOP
+62 Te veel niveaus van symbolische verwijzingen
+$ ENAMETOOLONG
+63 Bestandsnaam te lang
+$ EHOSTDOWN
+64 Bestemming niet actief
+$ EHOSTUNREACH
+65 Bestemming niet bereikbaar
+$ ENOTEMPTY
+66 Directory is niet leeg
+$ EPROCLIM
+67 Te veel taken
+$ EUSERS
+68 Te veel gebruikers
+$ EDQUOT
+69 Schijfquota overschreden
+$ ESTALE
+70 Verlopen NFS-bestandsverwijzing
+$ EREMOTE
+71 Te veel verwijzingen op afstand in dit pad
+$ EBADRPC
+72 RPC-argumentstructuur is incorrect
+$ ERPCMISMATCH
+73 RPC-versie is verkeerd
+$ EPROGUNAVAIL
+74 RPC-programma niet beschikbaar
+$ EPROGMISMATCH
+75 Programmaversie is verkeerd
+$ EPROCUNAVAIL
+76 Taak kan niet door dit programma worden uitgevoerd
+$ ENOLCK
+77 Geen sloten beschikbaar
+$ ENOSYS
+78 Deze systeemfunctie is niet geimplementeerd
+$ EFTYPE
+79 Bestandsformaat niet van toepassing
+$ EAUTH
+80 Aanmeldingsfout
+$ ENEEDAUTH
+81 Aanmeldingsprocedure benodigd
+$ EIDRM
+82 De aanwijzer is verwijderd
+$ ENOMSG
+83 Geen bericht van het gewenste type
+$ EOVERFLOW
+84 Waarde te groot om te bewaren in gegevenstype
+$ EILSEQ
+85 Ongeldige bytereeks
+$ ENOTSUP
+86 Niet ondersteund
+$ ECANCELED
+87 Bewerking geannuleerd
+$ EBADMSG
+88 Verkeerd of defect bericht
+$ ENODATA
+89 Geen bericht beschikbaar
+$ ENOSR
+90 Geen STREAM-voorraad
+$ ENOSTR
+91 Dit is geen STREAM
+$ ETIME
+92 STREAM-ioctl verlopen
+$ ENOATTR
+93 Attribuut niet gevonden
+$ EMULTIHOP
+94 Multihopverzoek
+$ ENOLINK
+95 Verbinding werd verstoord
+$ EPROTO
+96 Protocolfout
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Opgehangen
+$ SIGINT
+2 Onderbroken
+$ SIGQUIT
+3 Opgegeven
+$ SIGILL
+4 Verboden instructie
+$ SIGTRAP
+5 Spoor/BPT-val
+$ SIGABRT
+6 Abort-val
+$ SIGEMT
+7 EMT-val
+$ SIGFPE
+8 Drijvende kommafout
+$ SIGKILL
+9 Gedood
+$ SIGBUS
+10 Busfout
+$ SIGSEGV
+11 Segmentatiefout
+$ SIGSYS
+12 Verkeerde systeemaanroep
+$ SIGPIPE
+13 Gebroken pijp
+$ SIGALRM
+14 Wekker
+$ SIGTERM
+15 Beeindigd
+$ SIGURG
+16 Dringende I/O opgemerkt
+$ SIGSTOP
+17 Gestopt (signaal)
+$ SIGTSTP
+18 Gestopt
+$ SIGCONT
+19 Voortgezet
+$ SIGCHLD
+20 Kindproces beeindigd
+$ SIGTTIN
+21 Gestopt (TTY-invoer)
+$ SIGTTOU
+22 Gestopt (TTY-uitvoer)
+$ SIGIO
+23 I/O mogelijk
+$ SIGXCPU
+24 Te veel CPU-tijd verbruikt
+$ SIGXFSZ
+25 Maximale bestandsgrootte overschreden
+$ SIGVTALRM
+26 Virtuele wekker
+$ SIGPROF
+27 Profiling-wekker
+$ SIGWINCH
+28 Venstergrootte veranderd
+$ SIGINFO
+29 Informatieverzoek
+$ SIGUSR1
+30 Gebruikersignaal 1
+$ SIGUSR2
+31 Gebruikersignaal 2
+$ SIGPWR
+32 Stroomuitval/stroominschakeling
diff --git a/lib/libc/nls/no_NO.ISO8859-1.msg b/lib/libc/nls/no_NO.ISO8859-1.msg
new file mode 100644
index 0000000..2598f4d
--- /dev/null
+++ b/lib/libc/nls/no_NO.ISO8859-1.msg
@@ -0,0 +1,231 @@
+$ $FreeBSD$
+$
+$ Message catalog for no_NO.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operasjonen er ikke tillatt
+$ ENOENT
+2 Filen eller katalogen finnes ikke
+$ ESRCH
+3 Prosessen finnes ikke
+$ EINTR
+4 Avbrudt systemkall
+$ EIO
+5 I/O feil
+$ ENXIO
+6 Enheten er ikke konfigurert
+$ E2BIG
+7 Argumentlisten er for lang
+$ ENOEXEC
+8 Ukjent kjørbart format
+$ EBADF
+9 Ugyldig fildeskriptor
+$ ECHILD
+10 Ingen barneprosess
+$ EDEADLK
+11 Vranglås unngått
+$ ENOMEM
+12 Kan ikke allokere nok minne
+$ EACCES
+13 Ingen adgang
+$ EFAULT
+14 Ugyldig adresse
+$ ENOTBLK
+15 Blokk-enhet påkrevd
+$ EBUSY
+16 Enheten er opptatt
+$ EEXIST
+17 Filen finnes
+$ EXDEV
+18 Link mellom forskjellige enheter
+$ ENODEV
+19 Operasjonen er ikke støttet av enheten
+$ ENOTDIR
+20 Ikke en katalog
+$ EISDIR
+21 Er en katalog
+$ EINVAL
+22 Ugyldig argument
+$ ENFILE
+23 For mange åpne filer i systemet
+$ EMFILE
+24 For mange åpne filer
+$ ENOTTY
+25 Ugyldig ioctl for enheten
+$ ETXTBSY
+26 Kjørbar fil i bruk
+$ EFBIG
+27 Filen er for stor
+$ ENOSPC
+28 Ingen ledig plass på enheten
+$ ESPIPE
+29 Ugyldig seek operasjon
+$ EROFS
+30 Filsystemet er skrivebeskyttet
+$ EMLINK
+31 For mange linker
+$ EPIPE
+32 Brudt pipe
+$ EDOM
+33 Numerisk argument utenfor arbeidsområdet
+$ ERANGE
+34 Resultatet er for stort
+$ EAGAIN, EWOULDBLOCK
+35 Ressurs midlertidig utilgjengelig
+$ EINPROGRESS
+36 Operasjonen er nå i gang
+$ EALREADY
+37 Operasjonen er allerede i gang
+$ ENOTSOCK
+38 Deskriptoren er ikke en socket
+$ EDESTADDRREQ
+39 Mottakeradresse er påkrevd
+$ EMSGSIZE
+40 Meldingen er for lang
+$ EPROTOTYPE
+41 Ugyldig protokolltype for denne socketen
+$ ENOPROTOOPT
+42 Protokollen er ikke tilgjengelig
+$ EPROTONOSUPPORT
+43 Protokollen er ikke støttet
+$ ESOCKTNOSUPPORT
+44 Socket-typen er ikke støttet
+$ EOPNOTSUPP
+45 Operasjonen er ikke støttet
+$ EPFNOSUPPORT
+46 Protokollfamilien er ikke støttet
+$ EAFNOSUPPORT
+47 Adressetypen er ikke støttet av protokollfamilien
+$ EADDRINUSE
+48 Adressen er allerede i bruk
+$ EADDRNOTAVAIL
+49 Kan ikke bruke den ønskede adressen
+$ ENETDOWN
+50 Nettverket er nede
+$ ENETUNREACH
+51 Nettverket er utilgjengelig
+$ ENETRESET
+52 Nettverket kuttet forbindelsen ved reset
+$ ECONNABORTED
+53 Programvaren forårsaket brudd av forbindelsen
+$ ECONNRESET
+54 Forbindelsen avbrudt av korrespondenten
+$ ENOBUFS
+55 Buffer-plass ikke tilgjengelig
+$ EISCONN
+56 Socketen er allerede forbundet
+$ ENOTCONN
+57 Socketen er ikke forbundet
+$ ESHUTDOWN
+58 Kan ikke sende etter at socketen er tatt ned
+$ ETOOMANYREFS
+59 For mange referanser: kan ikke slå dem sammen
+$ ETIMEDOUT
+60 Tiden til forbindelsen utløp
+$ ECONNREFUSED
+61 Forbindelse nektet
+$ ELOOP
+62 For mange nivåer med symbolske linker
+$ ENAMETOOLONG
+63 Filnavnet er for langt
+$ EHOSTDOWN
+64 Maskinen er nede
+$ EHOSTUNREACH
+65 Ingen rute til maskinen
+$ ENOTEMPTY
+66 Katalogen er ikke tom
+$ EPROCLIM
+67 For mange prosesser
+$ EUSERS
+68 For mange brukere
+$ EDQUOT
+69 Diskkvote overskredet
+$ ESTALE
+70 Fastlåst NFS fildeskriptor
+$ EREMOTE
+71 For mange nivåer med remote i stien
+$ EBADRPC
+72 Ugyldig RPC struktur
+$ ERPCMISMATCH
+73 Feil RPC versjon
+$ EPROGUNAVAIL
+74 RPC program ikke tilgjengelig
+$ EPROGMISMATCH
+75 Feil programversjon
+$ EPROCUNAVAIL
+76 Prosedyren finnes ikke i programmet
+$ ENOLCK
+77 Ingen låsing tilgjengelig
+$ ENOSYS
+78 Funksjonen er ikke implementert
+$ EFTYPE
+79 Ugyldig filtype eller format
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Avbrudd
+$ SIGQUIT
+3 Avslutt
+$ SIGILL
+4 Ugyldig instruksjon
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Flyttallsfeil
+$ SIGKILL
+9 Drept
+$ SIGBUS
+10 Buss feil
+$ SIGSEGV
+11 Segmenteringsfeil
+$ SIGSYS
+12 Ugyldig systemkall
+$ SIGPIPE
+13 Brudt pipe
+$ SIGALRM
+14 Alarmklokke
+$ SIGTERM
+15 Terminert
+$ SIGURG
+16 Urgent I/O condition
+$ SIGSTOP
+17 Stoppet (signal)
+$ SIGTSTP
+18 Stoppet
+$ SIGCONT
+19 Fortsetter
+$ SIGCHLD
+20 Barn avsluttet
+$ SIGTTIN
+21 Stoppet (tty input)
+$ SIGTTOU
+22 Stoppet (tty output)
+$ SIGIO
+23 I/O mulig
+$ SIGXCPU
+24 CPU-tid overskredet
+$ SIGXFSZ
+25 Maksimal filstørrelse overskredet
+$ SIGVTALRM
+26 Virtuell timer utløpt
+$ SIGPROF
+27 Profileringstimer utløpt
+$ SIGWINCH
+28 Vindustørrelse endres
+$ SIGINFO
+29 Informasjonsforespørsel
+$ SIGUSR1
+30 Brukerdefinert signal 1
+$ SIGUSR2
+31 Brukerdefinert signal 2
diff --git a/lib/libc/nls/pt_BR.ISO8859-1.msg b/lib/libc/nls/pt_BR.ISO8859-1.msg
new file mode 100644
index 0000000..fb1c100
--- /dev/null
+++ b/lib/libc/nls/pt_BR.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for pt_BR.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operação não permitida
+$ ENOENT
+2 Nenhum arquivo ou diretório encontrado
+$ ESRCH
+3 Nenhum processo encontrado
+$ EINTR
+4 Chamada de sistema interrompida
+$ EIO
+5 Erro de entrada/saída
+$ ENXIO
+6 Dispositivo não configurado
+$ E2BIG
+7 Lista de argumentos muito grande
+$ ENOEXEC
+8 Erro no formato de execução
+$ EBADF
+9 Erro no descritor de arquivo
+$ ECHILD
+10 Nenhum processo filho
+$ EDEADLK
+11 Bloqueio de recurso evitado
+$ ENOMEM
+12 Impossível alocar memória
+$ EACCES
+13 Permissão negada
+$ EFAULT
+14 Endereço errado
+$ ENOTBLK
+15 Dispositivo de bloco requerido
+$ EBUSY
+16 Dispositivo ocupado
+$ EEXIST
+17 Arquivo existe
+$ EXDEV
+18 Ligação entre dispositivos
+$ ENODEV
+19 Operação não suportada pelo dispositivo
+$ ENOTDIR
+20 Não é um diretório
+$ EISDIR
+21 É um diretório
+$ EINVAL
+22 Argumento inválido
+$ ENFILE
+23 Muitos arquivos abertos no sistema
+$ EMFILE
+24 Muitos arquivos abertos no sistema
+$ ENOTTY
+25 ioctl inapropriado para o dispositivo
+$ ETXTBSY
+26 Arquivo texto sendo utilizado
+$ EFBIG
+27 Arquivo muito grande
+$ ENOSPC
+28 Sem espaço no dispositivo
+$ ESPIPE
+29 seek ilegal
+$ EROFS
+30 Sistema de arquivos apenas para leitura
+$ EMLINK
+31 Muitos links
+$ EPIPE
+32 pipe quebrado
+$ EDOM
+33 Argumento numérico fora do domínio
+$ ERANGE
+34 Resultado muito grande
+$ EAGAIN, EWOULDBLOCK
+35 Recurso temporariamente indisponível
+$ EINPROGRESS
+36 Operação em progresso agora
+$ EALREADY
+37 Operação em progresso pronta
+$ ENOTSOCK
+38 Operação de socket em um não-socket
+$ EDESTADDRREQ
+39 Endereço de destino requerido
+$ EMSGSIZE
+40 Mensagem muito grande
+$ EPROTOTYPE
+41 Tipo de protocolo errado para socket
+$ ENOPROTOOPT
+42 Protocolo não disponível
+$ EPROTONOSUPPORT
+43 Protocolo não suportado
+$ ESOCKTNOSUPPORT
+44 Tipo de socket não suportado
+$ EOPNOTSUPP
+45 Operação não permitida
+$ EPFNOSUPPORT
+46 Família de protocolo não suportada
+$ EAFNOSUPPORT
+47 Família de endereços não suportada pela família de protocolos
+$ EADDRINUSE
+48 Endereço já está em uso
+$ EADDRNOTAVAIL
+49 Impossível obter endereço solicitado
+$ ENETDOWN
+50 Rede está parada
+$ ENETUNREACH
+51 Rede está inalcançável
+$ ENETRESET
+52 Conexão de rede perdida durante reset
+$ ECONNABORTED
+53 Conexão abortada por software
+$ ECONNRESET
+54 Conexão reiniciada pelo outro ponto
+$ ENOBUFS
+55 Sem espaço de buffer disponível
+$ EISCONN
+56 Socket já está conectado
+$ ENOTCONN
+57 Socket não está conectado
+$ ESHUTDOWN
+58 Impossível enviar depois que o socket foi finalizado
+$ ETOOMANYREFS
+59 Muitas referências: impossível ligar
+$ ETIMEDOUT
+60 Tempo de operação expirou
+$ ECONNREFUSED
+61 Conexão recusada
+$ ELOOP
+62 Muitos níveis de links simbólicos
+$ ENAMETOOLONG
+63 Nome de arquivo muito grande
+$ EHOSTDOWN
+64 Host está desligado
+$ EHOSTUNREACH
+65 Sem rota para o host
+$ ENOTEMPTY
+66 Diretório não está vazio
+$ EPROCLIM
+67 Muitos processos
+$ EUSERS
+68 Muitos usuários
+$ EDQUOT
+69 Quota de disco excedida
+$ ESTALE
+70 Manipulador de arquivo NFS velho
+$ EREMOTE
+71 Muitos níveis no caminho remoto
+$ EBADRPC
+72 Estrutura RPC incorreta
+$ ERPCMISMATCH
+73 Versão RPC incorreta
+$ EPROGUNAVAIL
+74 Programa RPC indisponível
+$ EPROGMISMATCH
+75 Versão do programa incorreta
+$ EPROCUNAVAIL
+76 Procedimento incorreto para o programa
+$ ENOLCK
+77 Nenhum lock disponível
+$ ENOSYS
+78 Função não implementada
+$ EFTYPE
+79 Tipo de arquivo ou formato inapropriados
+$ EAUTH
+80 Erro de autenticação
+$ ENEEDAUTH
+81 Necessidade de autenticador
+$ EIDRM
+82 Identificador removido
+$ ENOMSG
+83 Nenhuma mensagem do tipo desejado
+$ EOVERFLOW
+84 Valor muito grande para ser armazenado neste tipo de dado
+$ ECANCELED
+85 Operação cancelada
+$ EILSEQ
+86 Sequência de bytes ilegal
+$ ENOATTR
+87 Atributo não encontrado
+$ EDOOFUS
+88 Erro de programação
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fim da linha (Hangup)
+$ SIGINT
+2 Interrupção
+$ SIGQUIT
+3 Saída
+$ SIGILL
+4 Instrução ilegal
+$ SIGTRAP
+5 Trap de Trace/BPT
+$ SIGABRT
+6 Abortar trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Exceção de ponto flutuante
+$ SIGKILL
+9 Morreu
+$ SIGBUS
+10 Erro de barramento
+$ SIGSEGV
+11 Falha de segmentação
+$ SIGSYS
+12 Chamada de sistema incorreta
+$ SIGPIPE
+13 Pipe incorreto
+$ SIGALRM
+14 Alarme do relógio
+$ SIGTERM
+15 Terminado
+$ SIGURG
+16 Condição urgente de E/S
+$ SIGSTOP
+17 Suspendido (sinal)
+$ SIGTSTP
+18 Suspendido
+$ SIGCONT
+19 Continuado
+$ SIGCHLD
+20 Filho saiu
+$ SIGTTIN
+21 Parado (entrada de tty)
+$ SIGTTOU
+22 Parado (saída de tty)
+$ SIGIO
+23 E/S possível
+$ SIGXCPU
+24 Limite de tempo de CPU excedido
+$ SIGXFSZ
+25 Tamanho de arquivo excedido
+$ SIGVTALRM
+26 Temporizador virtual expirou
+$ SIGPROF
+27 Temporizador de profiling expirou
+$ SIGWINCH
+28 Mudança no tamanho de janela
+$ SIGINFO
+29 Requisição de informação
+$ SIGUSR1
+30 Sinal 1 definido pelo usuário
+$ SIGUSR2
+31 Sinal 2 definido pelo usuário
diff --git a/lib/libc/nls/sk_SK.ISO8859-2.msg b/lib/libc/nls/sk_SK.ISO8859-2.msg
new file mode 100644
index 0000000..8efa17d
--- /dev/null
+++ b/lib/libc/nls/sk_SK.ISO8859-2.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for sk_SK.ISO8859-2 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operácia nie je povolená
+$ ENOENT
+2 Neexistujúci súbor alebo adresár
+$ ESRCH
+3 Proces neexistuje
+$ EINTR
+4 Systémové volanie preru¹ené
+$ EIO
+5 Chyba vstupu/výstupu
+$ ENXIO
+6 Zariadenie nie je nakonfigurované
+$ E2BIG
+7 Príli¹ dlhý zoznam argumentov
+$ ENOEXEC
+8 Chybný formát spusteného súboru
+$ EBADF
+9 Chybný deskriptor súboru
+$ ECHILD
+10 Neexistuje ¾iaden potomok procesu
+$ EDEADLK
+11 Bolo zabránené zablokovaniu prostriedku
+$ ENOMEM
+12 Nie je mo¾né prideli» pamä»
+$ EACCES
+13 Prístup odmietnutý
+$ EFAULT
+14 Chybná adresa
+$ ENOTBLK
+15 Vy¾adované blokové zariadenie
+$ EBUSY
+16 Zariadenie je pou¾ívané
+$ EEXIST
+17 Súbor existuje
+$ EXDEV
+18 Odkaz medzi zariadeniami
+$ ENODEV
+19 Operácia nie je zariadením podporovaná
+$ ENOTDIR
+20 Nie je adresár
+$ EISDIR
+21 Je adresár
+$ EINVAL
+22 Chybný argument
+$ ENFILE
+23 Priveµa otvorených súborov v systéme
+$ EMFILE
+24 Priveµa otvorených súborov
+$ ENOTTY
+25 Nevhodné ioctl pre dané zariadenie
+$ ETXTBSY
+26 Textový súbor je pou¾ívaný
+$ EFBIG
+27 Súbor je príli¹ veµký
+$ ENOSPC
+28 Na zariadení nie je voµné miesto
+$ ESPIPE
+29 Neprípustné nastavenie pozície
+$ EROFS
+30 Súborový systém je len na èítanie
+$ EMLINK
+31 Priveµa odkazov
+$ EPIPE
+32 Preru¹ená rúra
+$ EDOM
+33 Èíselný argument mimo definièný obor
+$ ERANGE
+34 Výsledok príli¹ veµký alebo príli¹ malý
+$ EAGAIN, EWOULDBLOCK
+35 Zdroj je doèasne nedostupný
+$ EINPROGRESS
+36 Operácia práve prebieha
+$ EALREADY
+37 Operácia u¾ prebieha
+$ ENOTSOCK
+38 Socketová operácia na objekte, ktorý nie je socket
+$ EDESTADDRREQ
+39 Vy¾adovaná cieµová adresa
+$ EMSGSIZE
+40 Príli¹ dlhá správa
+$ EPROTOTYPE
+41 Protokol nie je socketom podporovaný
+$ ENOPROTOOPT
+42 Protokol nie je k dispozícii
+$ EPROTONOSUPPORT
+43 Protokol nie je podporovaný
+$ ESOCKTNOSUPPORT
+44 Typ socketu nie je podporovaný
+$ EOPNOTSUPP
+45 Operácia nie je podporovaná
+$ EPFNOSUPPORT
+46 Rodina protokolov nie je podporovaná
+$ EAFNOSUPPORT
+47 Rodina adries nie je podporovaná rodinou protokolov
+$ EADDRINUSE
+48 Adresa je u¾ pou¾ívaná
+$ EADDRNOTAVAIL
+49 Nie je mo¾né prideli» po¾adovanú adresu
+$ ENETDOWN
+50 Sie» je nefunkèná
+$ ENETUNREACH
+51 Sie» je nedostupná
+$ ENETRESET
+52 Sie» zru¹ila spojenie po resete
+$ ECONNABORTED
+53 Program spôsobil ukonèenie spojenia
+$ ECONNRESET
+54 Spojenie zru¹ené druhou stranou
+$ ENOBUFS
+55 Vyrovnávacia pamä» nie je k dispozícii
+$ EISCONN
+56 Socket je u¾ pripojený
+$ ENOTCONN
+57 Socket nie je pripojený
+$ ESHUTDOWN
+58 Nie je mo¾né posiela» po uzavretí socketu
+$ ETOOMANYREFS
+59 Príli¹ mnoho odkazov: nie je mo¾né spoji»
+$ ETIMEDOUT
+60 Èasový limit pre spojenie vypr¹al
+$ ECONNREFUSED
+61 Spojenie odmietnuté
+$ ELOOP
+62 Priveµa úrovní symbolických odkazov
+$ ENAMETOOLONG
+63 Meno súboru príli¹ dlhé
+$ EHOSTDOWN
+64 Vzdialený uzol je odpojený
+$ EHOSTUNREACH
+65 Neexistuje cesta k vzdialenému uzlu
+$ ENOTEMPTY
+66 Adresár nie je prázdny
+$ EPROCLIM
+67 Priveµa procesov
+$ EUSERS
+68 Priveµa pou¾ívateµov
+$ EDQUOT
+69 Disková kvóta prekroèená
+$ ESTALE
+70 Zastaralý NFS súborový ukazateµ
+$ EREMOTE
+71 Priveµa úrovní vzdialeného v ceste
+$ EBADRPC
+72 RPC ¹truktúra je chybná
+$ ERPCMISMATCH
+73 Chybná verzia RPC
+$ EPROGUNAVAIL
+74 RPC program nie je k dispozícii
+$ EPROGMISMATCH
+75 Chybná verzia RPC programu
+$ EPROCUNAVAIL
+76 Chybná RPC procedúra pre program
+$ ENOLCK
+77 Zámky nie sú k dispozícii
+$ ENOSYS
+78 Funkcia nie je implementovaná
+$ EFTYPE
+79 Nevhodný typ alebo formát súboru
+$ EAUTH
+80 Overenie práv neúspe¹né
+$ ENEEDAUTH
+81 Vy¾adovaný overovací objekt
+$ EIDRM
+82 Identifikátor odstránený
+$ ENOMSG
+83 Neexistuje správa ¾elaného typu
+$ EOVERFLOW
+84 Hodnota je pre daný dátový typ priveµká
+$ EILSEQ
+85 Neprípustná postupnos» bajtov
+$ ENOTSUP
+86 Nie je podporované
+$ ECANCELED
+87 Operácia zru¹ená
+$ EBADMSG
+88 Chybná alebo poru¹ená správa
+$ ENODATA
+89 ®iadna správa nie je k dispozícii
+$ ENOSR
+90 ®iadne STREAM zdroje
+$ ENOSTR
+91 Nie je STREAM
+$ ETIME
+92 Èasový limit pre STREAM ioctl vypr¹al
+$ ENOATTR
+93 Atribút nenájdený
+$ EMULTIHOP
+94 Pokus o spojenie cez viacero uzlov
+$ ENOLINK
+95 Odkaz bol pretrhnutý
+$ EPROTO
+96 Chyba protokolu
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Terminál odpojený
+$ SIGINT
+2 Preru¹enie
+$ SIGQUIT
+3 Koniec
+$ SIGILL
+4 Chybná in¹trukcia
+$ SIGTRAP
+5 Trasovacia/ladiaca in¹trukcia
+$ SIGABRT
+6 Násilné ukonèenie
+$ SIGEMT
+7 Emulovaná in¹trukcia
+$ SIGFPE
+8 Výnimka pohyblivej rádovej èiarky
+$ SIGKILL
+9 Zabité
+$ SIGBUS
+10 Chyba na zbernici
+$ SIGSEGV
+11 Chyba segmentácie
+$ SIGSYS
+12 Chybné systémové volanie
+$ SIGPIPE
+13 Preru¹ená rúra
+$ SIGALRM
+14 Budík
+$ SIGTERM
+15 Ukonèené
+$ SIGURG
+16 Naliehavý vstupný/výstupný stav
+$ SIGSTOP
+17 Pozastavené (signál)
+$ SIGTSTP
+18 Pozastavené
+$ SIGCONT
+19 Pokraèovanie
+$ SIGCHLD
+20 Potomok procesu ukonèený
+$ SIGTTIN
+21 Pozastavené (terminálový vstup)
+$ SIGTTOU
+22 Pozastavené (terminálový výstup)
+$ SIGIO
+23 Vstup/výstup mo¾ný
+$ SIGXCPU
+24 Prekroèený èasový limit pre procesor
+$ SIGXFSZ
+25 Prekroèený limit veµkosti súboru
+$ SIGVTALRM
+26 Vypr¹al virtuálny èasovaè
+$ SIGPROF
+27 Vypr¹al profilovací èasovaè
+$ SIGWINCH
+28 Veµkos» okna zmenená
+$ SIGINFO
+29 ®iados» o informáciu
+$ SIGUSR1
+30 Pou¾ívateµom definovaný signál 1
+$ SIGUSR2
+31 Pou¾ívateµom definovaný signál 2
+$ SIGPWR
+32 Zlyhanie/opakované spustenie napájania
diff --git a/lib/libc/nls/sv_SE.ISO8859-1.msg b/lib/libc/nls/sv_SE.ISO8859-1.msg
new file mode 100644
index 0000000..13cdd23
--- /dev/null
+++ b/lib/libc/nls/sv_SE.ISO8859-1.msg
@@ -0,0 +1,233 @@
+$ $FreeBSD$
+$
+$ Message catalog for sv_SE.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Otillåten operation
+$ ENOENT
+2 Filen eller katalogen finns ej
+$ ESRCH
+3 Denna process finns ej
+$ EINTR
+4 Avbrutet systemanrop
+$ EIO
+5 In-/utmatningsfel
+$ ENXIO
+6 Enheten är ej konfigurerad
+$ E2BIG
+7 Argumentlistan är för lång
+$ ENOEXEC
+8 Ej körbar fil
+$ EBADF
+9 Felaktigt filhandtag
+$ ECHILD
+10 Inga barnprocesser
+$ EDEADLK
+11 Undvek resursdödläge
+$ ENOMEM
+12 Kan ej erhålla minne
+$ EACCES
+13 Tillstånd nekas
+$ EFAULT
+14 Felaktig adress
+$ ENOTBLK
+15 Blockenhet krävs
+$ EBUSY
+16 Enheten är upptagen
+$ EEXIST
+17 Filen finns redan
+$ EXDEV
+18 Länken korsar enheter
+$ ENODEV
+19 Enheten stöder ej operationen
+$ ENOTDIR
+20 Är ej en katalog
+$ EISDIR
+21 Är en katalog
+$ EINVAL
+22 Ogiltigt argument
+$ ENFILE
+23 För många öppna filer i systemet
+$ EMFILE
+24 För många öppna filer
+$ ENOTTY
+25 Olämplig ioctl för enheten
+$ ETXTBSY
+26 Programfilen är upptagen
+$ EFBIG
+27 Filen är för stor
+$ ENOSPC
+28 Inget utrymme kvar på enheten
+$ ESPIPE
+29 Otillåten sökning
+$ EROFS
+30 Skrivskyddat filsystem
+$ EMLINK
+31 För många länkar
+$ EPIPE
+32 Avbruten kommunikationskanal
+$ EDOM
+33 Numeriskt argument utanför domänen
+$ ERANGE
+34 Resultatet är för stort
+$ EAGAIN, EWOULDBLOCK
+35 Resursen är tillfälligt otillgänglig
+$ EINPROGRESS
+36 Operationen är igång
+$ EALREADY
+37 Operationen är redan igång
+$ ENOTSOCK
+38 Sockeloperation på icke-sockel
+$ EDESTADDRREQ
+39 Destinationsadress erfordras
+$ EMSGSIZE
+40 För långt meddelande
+$ EPROTOTYPE
+41 Fel protokolltyp för sockeln
+$ ENOPROTOOPT
+42 Protokollet otillgängligt
+$ EPROTONOSUPPORT
+43 Protokollet är ej understött
+$ ESOCKTNOSUPPORT
+44 Sockeltypen är ej understödd
+$ EOPNOTSUPP
+45 Operationen är ej understödd
+$ EPFNOSUPPORT
+46 Protokollfamiljen är ej understödd
+$ EAFNOSUPPORT
+47 Adressfamiljen är ej understödd av protokollfamiljen
+$ EADDRINUSE
+48 Adressen är upptagen
+$ EADDRNOTAVAIL
+49 Kan ej tilldela den begärda adressen
+$ ENETDOWN
+50 Nätverket fungerar inte
+$ ENETUNREACH
+51 Nätverket är ej kontaktbart
+$ ENETRESET
+52 Nätverket tappade kontakten vid återställningen
+$ ECONNABORTED
+53 Mjukvara orsakade nedkoppling
+$ ECONNRESET
+54 Motparten avbröt uppkopplingen
+$ ENOBUFS
+55 Inget buffertutrymme tillgängligt
+$ EISCONN
+56 Sockeln är redan uppkopplad
+$ ENOTCONN
+57 Sockeln är ej uppkopplad
+$ ESHUTDOWN
+58 Kan ej sända efter att sockeln nedkopplats
+$ ETOOMANYREFS
+59 För många referenser: kan inte delas
+$ ETIMEDOUT
+60 Uppkopplingstiden tog slut
+$ ECONNREFUSED
+61 Uppkopplingen nekad
+$ ELOOP
+62 För många nivåer av symboliska länkar
+$ ENAMETOOLONG
+63 Alldeles för långt filnamn
+$ EHOSTDOWN
+64 Värddatorn är nere
+$ EHOSTUNREACH
+65 Väg till värddatorn saknas
+$ ENOTEMPTY
+66 Katalogen ej tom
+$ EPROCLIM
+67 För många processer
+$ EUSERS
+68 För många användare
+$ EDQUOT
+69 Diskkvot överskriden
+$ ESTALE
+70 Inaktuellt NFS-filhandtag
+$ EREMOTE
+71 För många fjärrnivåer i sökvägen
+$ EBADRPC
+72 Felaktig RPC-struktur
+$ ERPCMISMATCH
+73 Felaktig RPC-version
+$ EPROGUNAVAIL
+74 RPC-programmet otillgängligt
+$ EPROGMISMATCH
+75 Fel programversion
+$ EPROCUNAVAIL
+76 Felaktig procedur för programmet
+$ ENOLCK
+77 Inga lås tillgängliga
+$ ENOSYS
+78 Funktionen är ej implementerad
+$ EFTYPE
+79 Olämplig filtyp eller format
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Lägg på
+$ SIGINT
+2 Avbryt
+$ SIGQUIT
+3 Avsluta
+$ SIGILL
+4 Olaglig instruktion
+$ SIGTRAP
+5 Spår- eller brytpunktsfälla
+$ SIGABRT
+6 Avslutsfälla
+$ SIGEMT
+7 Emuleringsfälla
+$ SIGFPE
+8 Flyttalsavbrott
+$ SIGKILL
+9 Dräpt
+$ SIGBUS
+10 Bussfel
+$ SIGSEGV
+11 Segmentfel
+$ SIGSYS
+12 Felaktigt systemanrop
+$ SIGPIPE
+13 Avbruten kommunikationskanal
+$ SIGALRM
+14 Äggklocka
+$ SIGTERM
+15 Terminerad
+$ SIGURG
+16 Brådskande In/Ut-tillstånd
+$ SIGSTOP
+17 Stoppad (signal)
+$ SIGTSTP
+18 Stoppad
+$ SIGCONT
+19 Fortsätter
+$ SIGCHLD
+20 Barn avslutat
+$ SIGTTIN
+21 Stoppad (terminalinmatning)
+$ SIGTTOU
+22 Stoppad (terminalutmatning)
+$ SIGIO
+23 In- och utmatning möjlig
+$ SIGXCPU
+24 Cputidsgränsen överskriden
+$ SIGXFSZ
+25 Filstorleksgränsen överskriden
+$ SIGVTALRM
+26 Virtuella äggklockan ringde
+$ SIGPROF
+27 Profileringsäggklockan ringde
+$ SIGWINCH
+28 Fönsterstorleken ändras
+$ SIGINFO
+29 Informationsförfrågan
+$ SIGUSR1
+30 Användardefinierad signal 1
+$ SIGUSR2
+31 Användardefinierad signal 2
+$ SIGPWR
+32 Kraftbortfall/omstart
diff --git a/lib/libc/nls/uk_UA.UTF-8.msg b/lib/libc/nls/uk_UA.UTF-8.msg
new file mode 100644
index 0000000..e6ea2f77
--- /dev/null
+++ b/lib/libc/nls/uk_UA.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for uk_UA.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ дозволена
+$ ENOENT
+2 Ðемає такого файлу або каталогу
+$ ESRCH
+3 Ðемає такого процеÑу
+$ EINTR
+4 Перервано виклик функції
+$ EIO
+5 Помилка вводу-виводу
+$ ENXIO
+6 Ðемає такого приÑтрою або адреÑи
+$ E2BIG
+7 Перелік аргументів надто довгий
+$ ENOEXEC
+8 Помилка формату виконуваного файлу
+$ EBADF
+9 Ðевірний деÑкриптор файлу
+$ ECHILD
+10 Ðемає дочірнього процеÑу
+$ EDEADLK
+11 Уникнуто взаємне Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑурÑів
+$ ENOMEM
+12 Ðе доÑтатньо пам'ÑÑ‚Ñ–
+$ EACCES
+13 Відмова у доÑтупі
+$ EFAULT
+14 Ðевірна адреÑа
+$ ENOTBLK
+15 Потрібен блочний приÑтрій
+$ EBUSY
+16 РеÑÑƒÑ€Ñ Ð·Ð°Ð¹Ð½Ñтий
+$ EEXIST
+17 Файл вже Ñ–Ñнує
+$ EXDEV
+18 ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð·Ð° межі приÑтрою
+$ ENODEV
+19 Ðемає такого приÑтрою
+$ ENOTDIR
+20 Це не каталог
+$ EISDIR
+21 Це каталог
+$ EINVAL
+22 Ðедозволений аргумент
+$ ENFILE
+23 Забагато відкритих файлів у ÑиÑтемі
+$ EMFILE
+24 Забагато відкритих файлів
+$ ENOTTY
+25 Це не термінал
+$ ETXTBSY
+26 ТекÑтовий файл зайнÑтий
+$ EFBIG
+27 Файл надто великий
+$ ENOSPC
+28 Ðе залишилоÑÑŒ міÑÑ†Ñ Ð½Ð° приÑтрої
+$ ESPIPE
+29 Ðедозволене позиціонуваннÑ
+$ EROFS
+30 Файлова ÑиÑтема лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ
+$ EMLINK
+31 Забагато поÑилань
+$ EPIPE
+32 Канал зруйновано
+$ EDOM
+33 Помилка облаÑÑ‚Ñ– визначеннÑ
+$ ERANGE
+34 Результат надто великий
+$ EAGAIN, EWOULDBLOCK
+35 РеÑÑƒÑ€Ñ Ñ‚Ð¸Ð¼Ñ‡Ð°Ñово не доÑтупний
+$ EINPROGRESS
+36 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ñƒ процеÑÑ– виконаннÑ
+$ EALREADY
+37 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð²Ð¶Ðµ виконуєтьÑÑ
+$ ENOTSOCK
+38 Це не Ñокет
+$ EDESTADDRREQ
+39 Ðеобхідна адреÑа призначеннÑ
+$ EMSGSIZE
+40 ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ð´Ñ‚Ð¾ довге
+$ EPROTOTYPE
+41 Помилковий тип протоколу Ð´Ð»Ñ Ñокету
+$ ENOPROTOOPT
+42 Ðемає такого протоколу
+$ EPROTONOSUPPORT
+43 Протокол не підтримуєтьÑÑ
+$ ESOCKTNOSUPPORT
+44 Цей тип Ñокету не підтримуєтьÑÑ
+$ EOPNOTSUPP
+45 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ підтримуєтьÑÑ
+$ EPFNOSUPPORT
+46 Родина протоколів не підтримуєтьÑÑ
+$ EAFNOSUPPORT
+47 Родина Ð°Ð´Ñ€ÐµÑ Ð½Ðµ підтримуєтьÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
+$ EADDRINUSE
+48 ÐдреÑа вже викориÑтовуєтьÑÑ
+$ EADDRNOTAVAIL
+49 ÐдреÑа недоÑÑжна
+$ ENETDOWN
+50 Мережа не працює
+$ ENETUNREACH
+51 Мережа недоÑÑжна
+$ ENETRESET
+52 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾ мережею
+$ ECONNABORTED
+53 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾
+$ ECONNRESET
+54 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾ протилежною Ñтороною
+$ ENOBUFS
+55 Ðемає вільних буферів
+$ EISCONN
+56 Сокет вже під'єднано
+$ ENOTCONN
+57 Сокет не під'єднано
+$ ESHUTDOWN
+58 Ðе можу відіÑлати піÑÐ»Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñокету протилежною Ñтороною
+$ ETOOMANYREFS
+59 Забагато поÑилань: не можу з'єднати
+$ ETIMEDOUT
+60 Вийшов ліміт чаÑу Ð´Ð»Ñ Ð·'єднаннÑ
+$ ECONNREFUSED
+61 Відмова у з'єднанні
+$ ELOOP
+62 Забагато рівнів Ñимволічних поÑилань
+$ ENAMETOOLONG
+63 Ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ надто довге
+$ EHOSTDOWN
+64 ХоÑÑ‚ не працює
+$ EHOSTUNREACH
+65 ХоÑÑ‚ недоÑÑжний
+$ ENOTEMPTY
+66 Каталог не порожній
+$ EPROCLIM
+67 Забагато процеÑів
+$ EUSERS
+68 Забагато кориÑтувачів
+$ EDQUOT
+69 Перевищена диÑкова квота
+$ ESTALE
+70 ЗаÑтарілий деÑкриптор файлу NFS
+$ EREMOTE
+71 Віддалений об'єкт
+$ EBADRPC
+72 Погана Ñтруктура RPC
+$ ERPCMISMATCH
+73 Ðевірна верÑÑ–Ñ RPC
+$ EPROGUNAVAIL
+74 Програма RPC недоÑÑжна
+$ EPROGMISMATCH
+75 Ðевірна верÑÑ–Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸
+$ EPROCUNAVAIL
+76 Погана процедура Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸
+$ ENOLCK
+77 Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ доÑтупне
+$ ENOSYS
+78 Функцію не реалізовано
+$ EFTYPE
+79 Ðепридатний тип чи формат файлу
+$ EAUTH
+80 Помилка аутентифікації
+$ ENEEDAUTH
+81 Потрібна аутентифікаціÑ
+$ EIDRM
+82 Ідентифікатор вилучено
+$ ENOMSG
+83 Ðемає Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±Ð°Ð¶Ð°Ð½Ð¾Ð³Ð¾ типу
+$ EOVERFLOW
+84 Завелике Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ типу даних
+$ ECANCELED
+85 Операцію ÑкаÑовано
+$ EILSEQ
+86 Ðедозволена поÑлідовніÑÑ‚ÑŒ байтів
+$ ENOATTR
+87 Ðтрибут не знайдено
+$ EDOOFUS
+88 Помилка програмуваннÑ
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ВідключеннÑ
+$ SIGINT
+2 ПерериваннÑ
+$ SIGQUIT
+3 Вихід
+$ SIGILL
+4 ÐеприпуÑтима інÑтрукціÑ
+$ SIGTRAP
+5 ПаÑтка траÑуваннÑ
+$ SIGABRT
+6 Ðварійне завершеннÑ
+$ SIGEMT
+7 ÐŸÐµÑ€ÐµÑ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»ÑŒÐ¾Ð²Ð°Ð½Ð¾Ñ— інÑтрукції
+$ SIGFPE
+8 Помилка роботи з плаваючою крапкою
+$ SIGKILL
+9 Вбито
+$ SIGBUS
+10 Помилка шини
+$ SIGSEGV
+11 ÐŸÐ¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ Ñегментації
+$ SIGSYS
+12 Поганий ÑиÑтемний виклик
+$ SIGPIPE
+13 Канал зруйновано
+$ SIGALRM
+14 Таймер вичерпано
+$ SIGTERM
+15 ЗавершеннÑ
+$ SIGURG
+16 Ðевідкладний Ñтан на Ñокеті
+$ SIGSTOP
+17 Призупинено (Ñигнал)
+$ SIGTSTP
+18 Призупинено
+$ SIGCONT
+19 ÐŸÑ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸
+$ SIGCHLD
+20 Зміна ÑтатуÑу дочірнього процеÑу
+$ SIGTTIN
+21 Зупинено (ввід з терміналу)
+$ SIGTTOU
+22 Зупинено (вивід на термінал)
+$ SIGIO
+23 Ввід-вивід можливий
+$ SIGXCPU
+24 Перевищено ліміт процеÑорного чаÑу
+$ SIGXFSZ
+25 Перевищено ліміт макÑимального розміру файла
+$ SIGVTALRM
+26 Віртуальний таймер вичерпано
+$ SIGPROF
+27 Таймер Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ñ‡ÐµÑ€Ð¿Ð°Ð½Ð¾
+$ SIGWINCH
+28 Розмір вікна змінено
+$ SIGINFO
+29 Запит інформації
+$ SIGUSR1
+30 Сигнал кориÑтувача 1
+$ SIGUSR2
+31 Сигнал кориÑтувача 2
diff --git a/lib/libc/posix1e/Makefile.inc b/lib/libc/posix1e/Makefile.inc
index 99f58e3..c9e78bd 100644
--- a/lib/libc/posix1e/Makefile.inc
+++ b/lib/libc/posix1e/Makefile.inc
@@ -2,51 +2,76 @@
.PATH: ${.CURDIR}/posix1e
-SRCS+= acl_calc_mask.c \
+CFLAGS+=-D_ACL_PRIVATE
+
+# Copy kern/subr_acl_nfs4.c to the libc object directory.
+subr_acl_nfs4.c: ${.CURDIR}/../../sys/kern/subr_acl_nfs4.c
+ cat ${.ALLSRC} > ${.TARGET}
+
+SRCS+= acl_branding.c \
+ acl_calc_mask.c \
acl_copy.c \
+ acl_compat.c \
acl_delete.c \
acl_delete_entry.c \
acl_entry.c \
+ acl_flag.c \
acl_free.c \
acl_from_text.c \
+ acl_from_text_nfs4.c \
acl_get.c \
acl_init.c \
acl_perm.c \
acl_set.c \
+ acl_strip.c \
acl_support.c \
+ acl_support_nfs4.c \
acl_to_text.c \
+ acl_to_text_nfs4.c \
acl_valid.c \
extattr.c \
mac.c \
mac_exec.c \
mac_get.c \
- mac_set.c
+ mac_set.c \
+ subr_acl_nfs4.c
SYM_MAPS+=${.CURDIR}/posix1e/Symbol.map
MAN+= acl.3 \
+ acl_add_flag_np.3 \
acl_add_perm.3 \
acl_calc_mask.3 \
+ acl_clear_flags_np.3 \
acl_clear_perms.3 \
acl_copy_entry.3 \
acl_create_entry.3 \
acl_delete.3 \
acl_delete_entry.3 \
+ acl_delete_flag_np.3 \
acl_delete_perm.3 \
acl_dup.3 \
acl_free.3 \
acl_from_text.3 \
acl_get.3 \
+ acl_get_brand_np.3 \
acl_get_entry.3 \
+ acl_get_entry_type_np.3 \
+ acl_get_flagset_np.3 \
+ acl_get_flag_np.3 \
acl_get_permset.3 \
acl_get_perm_np.3 \
acl_get_qualifier.3 \
acl_get_tag_type.3 \
acl_init.3 \
+ acl_is_trivial_np.3 \
acl_set.3 \
+ acl_set_entry_type_np.3 \
+ acl_set_flagset_np.3 \
acl_set_permset.3 \
acl_set_qualifier.3 \
acl_set_tag_type.3 \
+ acl_strip_np.3 \
acl_to_text.3 \
acl_valid.3 \
extattr.3 \
@@ -60,15 +85,20 @@ MAN+= acl.3 \
mac_text.3 \
posix1e.3
-MLINKS+=acl_delete.3 acl_delete_def_file.3 \
+MLINKS+=acl_create_entry.3 acl_create_entry_np.3\
+ acl_delete.3 acl_delete_def_file.3 \
acl_delete.3 acl_delete_file_np.3 \
acl_delete.3 acl_delete_fd_np.3 \
+ acl_delete_entry.3 acl_delete_entry_np.3\
acl_get.3 acl_get_file.3 \
acl_get.3 acl_get_fd.3 \
acl_get.3 acl_get_fd_np.3 \
+ acl_get.3 acl_get_link_np.3 \
acl_set.3 acl_set_file.3 \
acl_set.3 acl_set_fd.3 \
acl_set.3 acl_set_fd_np.3 \
+ acl_set.3 acl_set_link_np.3 \
+ acl_to_text.3 acl_to_text_np.3 \
acl_valid.3 acl_valid_file_np.3 \
acl_valid.3 acl_valid_fd_np.3 \
extattr.3 extattr_namespace_to_string.3 \
@@ -76,14 +106,16 @@ MLINKS+=acl_delete.3 acl_delete_def_file.3 \
mac_get.3 mac_get_fd.3 \
mac_get.3 mac_get_file.3 \
mac_get.3 mac_get_link.3 \
+ mac_get.3 mac_get_peer.3 \
mac_get.3 mac_get_pid.3 \
mac_get.3 mac_get_proc.3 \
mac_prepare.3 mac_prepare_file_label.3 \
mac_prepare.3 mac_prepare_ifnet_label.3 \
mac_prepare.3 mac_prepare_process_label.3 \
- mac_set.3 mac_set_link.3 \
+ mac_prepare.3 mac_prepare_type.3 \
mac_set.3 mac_set_fd.3 \
mac_set.3 mac_set_file.3 \
+ mac_set.3 mac_set_link.3 \
mac_set.3 mac_set_proc.3 \
mac_text.3 mac_from_text.3 \
mac_text.3 mac_to_text.3
diff --git a/lib/libc/posix1e/Symbol.map b/lib/libc/posix1e/Symbol.map
index dd3c08f..346c8ca 100644
--- a/lib/libc/posix1e/Symbol.map
+++ b/lib/libc/posix1e/Symbol.map
@@ -21,15 +21,12 @@ FBSD_1.0 {
acl_get_link_np;
acl_get_fd;
acl_get_fd_np;
- acl_get_perm_np;
acl_get_permset;
acl_get_qualifier;
acl_get_tag_type;
acl_init;
acl_dup;
- acl_add_perm;
acl_clear_perms;
- acl_delete_perm;
acl_set_file;
acl_set_link_np;
acl_set_fd;
@@ -67,3 +64,23 @@ FBSD_1.0 {
mac_set_link;
mac_set_proc;
};
+
+FBSD_1.1 {
+ acl_add_flag_np;
+ acl_add_perm;
+ acl_clear_flags_np;
+ acl_create_entry_np;
+ acl_delete_entry_np;
+ acl_delete_flag_np;
+ acl_delete_perm;
+ acl_get_brand_np;
+ acl_get_entry_type_np;
+ acl_get_flag_np;
+ acl_get_flagset_np;
+ acl_get_perm_np;
+ acl_is_trivial_np;
+ acl_set_entry_type_np;
+ acl_set_flagset_np;
+ acl_strip_np;
+ acl_to_text_np;
+};
diff --git a/lib/libc/posix1e/acl.3 b/lib/libc/posix1e/acl.3
index 1c824d0..717df67 100644
--- a/lib/libc/posix1e/acl.3
+++ b/lib/libc/posix1e/acl.3
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 18, 2002
+.Dd June 25, 2009
.Dt ACL 3
.Os
.Sh NAME
@@ -48,7 +48,7 @@ The library calls include routines to allocate, duplicate, retrieve, set,
and validate ACLs associated with file objects.
As well as the POSIX.1e routines, there are a number of non-portable
extensions defined that allow for alternative ACL semantics than the
-POSIX.1e semantics, such as AFS, NTFS, Coda, and NWFS semantics.
+POSIX.1e semantics, such as NFSv4, AFS, NTFS, Coda, and NWFS semantics.
Where routines are non-standard, they are suffixed with _np to indicate that
they are not portable.
.Pp
@@ -59,6 +59,10 @@ all of these support routines are implemented in
.Pp
Available functions, sorted by behavior, include:
.Bl -tag -width indent
+.It Fn acl_add_flag_np
+This function is described in
+.Xr acl_add_flag_np 3 ,
+and may be used to add flags to a flagset.
.It Fn acl_add_perm
This function is described in
.Xr acl_add_perm 3 ,
@@ -70,6 +74,10 @@ and may be used to calculate and set the permissions associated with
the
.Dv ACL_MASK
entry.
+.It Fn acl_clear_flags_np
+This function is described in
+.Xr acl_clear_flags_np 3 ,
+and may be used to clear all flags from a flagset.
.It Fn acl_clear_perms
This function is described in
.Xr acl_clear_perms 3 ,
@@ -78,8 +86,11 @@ and may be used to clear all permissions from a permission set.
This function is described in
.Xr acl_copy_entry 3 ,
and may be used to copy the contents of an ACL entry.
-.It Fn acl_create_entry
-This function is described in
+.It Xo
+.Fn acl_create_entry ,
+.Fn acl_create_entry_np
+.Xc
+These functions are described in
.Xr acl_create_entry 3 ,
and may be used to create an empty entry in an ACL.
.It Xo
@@ -92,10 +103,17 @@ and may be used to create an empty entry in an ACL.
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
+.It Xo
+.Fn acl_delete_entry ,
+.Fn acl_delete_entry_np ,
+.Xc
+This functions are described in
.Xr acl_delete_entry 3 ,
and may be used to delete an entry from an ACL.
+.It Fn acl_delete_flag_np
+This function is described in
+.Xr acl_delete_flag_np 3 ,
+and may be used to delete flags from a flagset.
.It Fn acl_delete_perm
This function is described in
.Xr acl_delete_perm 3 ,
@@ -112,7 +130,7 @@ and may be used to free userland working ACL storage.
This function is described in
.Xr acl_from_text 3 ,
and may be used to convert a text-form ACL into working ACL state, if
-the ACL has POSIX.1e semantics.
+the ACL has POSIX.1e or NFSv4 semantics.
.It Fn acl_get_entry
This function is described in
.Xr acl_get_entry 3 ,
@@ -126,6 +144,14 @@ and may be used to retrieve a designated ACL entry from an ACL.
These functions are described in
.Xr acl_get 3 ,
and may be used to retrieve ACLs from file system objects.
+.It Fn acl_get_entry_type_np
+This function is described in
+.Xr acl_get_entry_type_np 3 ,
+and may be used to retrieve an ACL type from an ACL entry.
+.It Fn acl_get_flagset_np
+This function is described in
+.Xr acl_get_flagset_np 3 ,
+and may be used to retrieve a flagset from an ACL entry.
.It Fn acl_get_permset
This function is described in
.Xr acl_get_permset 3 ,
@@ -142,6 +168,10 @@ and may be used to retrieve the tag type from an ACL entry.
This function is described in
.Xr acl_init 3 ,
and may be used to allocate a fresh (empty) ACL structure.
+.It Fn acl_is_trivial_np
+This function is described in
+.Xr acl_is_trivial_np 3 ,
+and may be used to find out whether ACL is trivial.
.It Xo
.Fn acl_set_fd ,
.Fn acl_set_fd_np ,
@@ -151,6 +181,14 @@ and may be used to allocate a fresh (empty) ACL structure.
These functions are described in
.Xr acl_set 3 ,
and may be used to assign an ACL to a file system object.
+.It Fn acl_set_entry_type_np
+This function is described in
+.Xr acl_set_entry_type_np 3 ,
+and may be used to set the ACL type of an ACL entry.
+.It Fn acl_set_flagset_np
+This function is described in
+.Xr acl_set_flagset_np 3 ,
+and may be used to set the flags of an ACL entry from a flagset.
.It Fn acl_set_permset
This function is described in
.Xr acl_set_permset 3 ,
@@ -163,10 +201,17 @@ and may be used to set the qualifier of an ACL.
This function is described in
.Xr acl_set_tag_type 3 ,
and may be used to set the tag type of an ACL.
-.It Fn acl_to_text
-This function is described in
+.It Fn acl_strip_np
+This function is describe din
+.Xr acl-strip_np 3 ,
+and may be used to remove extended entries from an ACL.
+.It Xo
+.Fn acl_to_text ,
+.Fn acl_to_text_np
+.Xc
+These functions are described in
.Xr acl_to_text 3 ,
-and may be used to generate a text-form of a POSIX.1e semantics ACL.
+and may be used to generate a text-form of a POSIX.1e or NFSv4 semantics ACL.
.It Xo
.Fn acl_valid ,
.Fn acl_valid_fd_np ,
@@ -189,25 +234,34 @@ library.
.Sh SEE ALSO
.Xr getfacl 1 ,
.Xr setfacl 1 ,
+.Xr acl_add_flag_np 3 ,
.Xr acl_add_perm 3 ,
.Xr acl_calc_mask 3 ,
+.Xr acl_clear_flags_np 3 ,
.Xr acl_clear_perms 3 ,
.Xr acl_copy_entry 3 ,
.Xr acl_create_entry 3 ,
.Xr acl_delete_entry 3 ,
+.Xr acl_delete_flag_np 3 ,
.Xr acl_delete_perm 3 ,
.Xr acl_dup 3 ,
.Xr acl_free 3 ,
.Xr acl_from_text 3 ,
.Xr acl_get 3 ,
+.Xr acl_get_entry_type_np 3 ,
+.Xr acl_get_flagset_np 3 ,
.Xr acl_get_permset 3 ,
.Xr acl_get_qualifier 3 ,
.Xr acl_get_tag_type 3 ,
.Xr acl_init 3 ,
+.Xr acl_is_trivial_np 3 ,
.Xr acl_set 3 ,
+.Xr acl_set_entry_type_np 3 ,
+.Xr acl_set_flagset_np 3 ,
.Xr acl_set_permset 3 ,
.Xr acl_set_qualifier 3 ,
.Xr acl_set_tag_type 3 ,
+.Xr acl_strip_np 3 ,
.Xr acl_to_text 3 ,
.Xr acl_valid 3 ,
.Xr posix1e 3 ,
diff --git a/lib/libc/posix1e/acl_add_flag_np.3 b/lib/libc/posix1e/acl_add_flag_np.3
new file mode 100644
index 0000000..18222b6
--- /dev/null
+++ b/lib/libc/posix1e/acl_add_flag_np.3
@@ -0,0 +1,98 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_ADD_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_add_flag_np
+.Nd add flags to a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_add_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_add_flag_np
+function
+is a non-portable call that adds the flags contained in
+.Fa flags
+to the flagset
+.Fa flagset_d .
+.Pp
+Note: it is not considered an error to attempt to add flags
+that already exist in the flagset.
+.Pp
+Valid values are:
+.Pp
+.Bl -column -offset 3n "ACL_ENTRY_NO_PROPAGATE_INHERIT"
+.It ACL_ENTRY_FILE_INHERIT Will be inherited by files.
+.It ACL_ENTRY_DIRECTORY_INHERIT Will be inherited by directories.
+.It ACL_ENTRY_NO_PROPAGATE_INHERIT Will not propagate.
+.It ACL_ENTRY_INHERIT_ONLY Inherit-only.
+.El
+.Sh RETURN VALUES
+.Rv -std acl_add_flag_np
+.Sh ERRORS
+The
+.Fn acl_add_flag_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset within an ACL entry.
+Argument
+.Fa flag
+does not contain a valid
+.Vt acl_flag_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_add_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_add_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_add_perm.3 b/lib/libc/posix1e/acl_add_perm.3
index 6a5893e..336e55e 100644
--- a/lib/libc/posix1e/acl_add_perm.3
+++ b/lib/libc/posix1e/acl_add_perm.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 10, 2001
+.Dd June 25, 2009
.Dt ACL_ADD_PERM 3
.Os
.Sh NAME
@@ -49,6 +49,46 @@ to the permission set
.Pp
Note: it is not considered an error to attempt to add permissions
that already exist in the permission set.
+.Pp
+For POSIX.1e ACLs, valid values are:
+.Pp
+.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS"
+.It ACL_EXECUTE Execute permission
+.It ACL_WRITE Write permission
+.It ACL_READ Read permission
+.El
+.Pp
+For NFSv4 ACLs, valid values are:
+.Pp
+.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS"
+.It ACL_READ_DATA Read permission
+.It ACL_LIST_DIRECTORY Same as ACL_READ_DATA
+.It ACL_WRITE_DATA Write permission, or permission to create files
+.It ACL_ADD_FILE Same as ACL_READ_DATA
+.It ACL_APPEND_DATA Permission to create directories. Ignored for files
+.It ACL_ADD_SUBDIRECTORY Same as ACL_APPEND_DATA
+.It ACL_READ_NAMED_ATTRS Ignored
+.It ACL_WRITE_NAMED_ATTRS Ignored
+.It ACL_EXECUTE Execute permission
+.It ACL_DELETE_CHILD Permission to delete files and subdirectories
+.It ACL_READ_ATTRIBUTES Permission to read basic attributes
+.It ACL_WRITE_ATTRIBUTES Permission to change basic attributes
+.It ACL_DELETE Permission to delete the object this ACL is placed on
+.It ACL_READ_ACL Permission to read ACL
+.It ACL_WRITE_ACL Permission to change the ACL and file mode
+.It ACL_SYNCHRONIZE Ignored
+.El
+.Pp
+Calling
+.Fn acl_add_perm
+with
+.Fa perm
+equal to ACL_WRITE or ACL_READ brands the ACL as POSIX.
+Calling it with ACL_READ_DATA, ACL_LIST_DIRECTORY, ACL_WRITE_DATA,
+ACL_ADD_FILE, ACL_APPEND_DATA, ACL_ADD_SUBDIRECTORY, ACL_READ_NAMED_ATTRS,
+ACL_WRITE_NAMED_ATTRS, ACL_DELETE_CHILD, ACL_READ_ATTRIBUTES,
+ACL_WRITE_ATTRIBUTES, ACL_DELETE, ACL_READ_ACL, ACL_WRITE_ACL
+or ACL_SYNCHRONIZE brands the ACL as NFSv4.
.Sh RETURN VALUES
.Rv -std acl_add_perm
.Sh ERRORS
@@ -65,11 +105,13 @@ Argument
does not contain a valid
.Vt acl_perm_t
value.
+ACL is already branded differently.
.El
.Sh SEE ALSO
.Xr acl 3 ,
.Xr acl_clear_perms 3 ,
.Xr acl_delete_perm 3 ,
+.Xr acl_get_brand_np 3 ,
.Xr acl_get_permset 3 ,
.Xr acl_set_permset 3 ,
.Xr posix1e 3
diff --git a/lib/libc/posix1e/acl_branding.c b/lib/libc/posix1e/acl_branding.c
new file mode 100644
index 0000000..9839477
--- /dev/null
+++ b/lib/libc/posix1e/acl_branding.c
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@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$");
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+/*
+ * An ugly detail of the implementation - fortunately not visible
+ * to the API users - is the "branding": libc needs to keep track
+ * of what "brand" ACL is: NFSv4, POSIX.1e or unknown. It happens
+ * automatically - for example, during acl_get_file(3) ACL gets
+ * branded according to the "type" argument; during acl_set_permset
+ * ACL, if its brand is unknown it gets branded as NFSv4 if any of the
+ * NFSv4 permissions that are not valid for POSIX.1e ACL are set etc.
+ * Branding information is used for printing out the ACL (acl_to_text(3)),
+ * veryfying acl_set_whatever arguments (checking against setting
+ * bits that are valid only for NFSv4 in ACL branded as POSIX.1e) etc.
+ */
+
+static acl_t
+entry2acl(acl_entry_t entry)
+{
+ acl_t aclp;
+
+ aclp = (acl_t)(((long)entry >> _ACL_T_ALIGNMENT_BITS) << _ACL_T_ALIGNMENT_BITS);
+
+ return (aclp);
+}
+
+/*
+ * Return brand of an ACL.
+ */
+int
+_acl_brand(const acl_t acl)
+{
+
+ return (acl->ats_brand);
+}
+
+int
+_entry_brand(const acl_entry_t entry)
+{
+
+ return (_acl_brand(entry2acl(entry)));
+}
+
+/*
+ * Return 1, iff branding ACL as "brand" is ok.
+ */
+int
+_acl_brand_may_be(const acl_t acl, int brand)
+{
+
+ if (_acl_brand(acl) == ACL_BRAND_UNKNOWN)
+ return (1);
+
+ if (_acl_brand(acl) == brand)
+ return (1);
+
+ return (0);
+}
+
+int
+_entry_brand_may_be(const acl_entry_t entry, int brand)
+{
+
+ return (_acl_brand_may_be(entry2acl(entry), brand));
+}
+
+/*
+ * Brand ACL as "brand".
+ */
+void
+_acl_brand_as(acl_t acl, int brand)
+{
+
+ assert(_acl_brand_may_be(acl, brand));
+
+ acl->ats_brand = brand;
+}
+
+void
+_entry_brand_as(const acl_entry_t entry, int brand)
+{
+
+ _acl_brand_as(entry2acl(entry), brand);
+}
+
+int
+_acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type)
+{
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_NFS4:
+ if (type == ACL_TYPE_NFS4)
+ return (0);
+ break;
+
+ case ACL_BRAND_POSIX:
+ if (type == ACL_TYPE_ACCESS || type == ACL_TYPE_DEFAULT)
+ return (0);
+ break;
+ }
+
+ return (-1);
+}
+
+void
+_acl_brand_from_type(acl_t acl, acl_type_t type)
+{
+
+ switch (type) {
+ case ACL_TYPE_NFS4:
+ _acl_brand_as(acl, ACL_BRAND_NFS4);
+ break;
+ case ACL_TYPE_ACCESS:
+ case ACL_TYPE_DEFAULT:
+ _acl_brand_as(acl, ACL_BRAND_POSIX);
+ break;
+ default:
+ /* XXX: What to do here? */
+ break;
+ }
+}
+
+int
+acl_get_brand_np(acl_t acl, int *brand_p)
+{
+
+ if (acl == NULL || brand_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *brand_p = _acl_brand(acl);
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_calc_mask.c b/lib/libc/posix1e/acl_calc_mask.c
index 085ac9c..a2d1527 100644
--- a/lib/libc/posix1e/acl_calc_mask.c
+++ b/lib/libc/posix1e/acl_calc_mask.c
@@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdio.h>
+#include "acl_support.h"
+
/*
* acl_calc_mask() (23.4.2): calculate and set the permissions
* associated with the ACL_MASK ACL entry. If the ACL already
@@ -59,6 +61,13 @@ acl_calc_mask(acl_t *acl_p)
errno = EINVAL;
return (-1);
}
+
+ if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _acl_brand_as(*acl_p, ACL_BRAND_POSIX);
+
acl_int = &(*acl_p)->ats_acl;
if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) {
errno = EINVAL;
diff --git a/lib/libc/posix1e/acl_clear_flags_np.3 b/lib/libc/posix1e/acl_clear_flags_np.3
new file mode 100644
index 0000000..b2586e1
--- /dev/null
+++ b/lib/libc/posix1e/acl_clear_flags_np.3
@@ -0,0 +1,79 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_CLEAR_FLAGS_NP 3
+.Os
+.Sh NAME
+.Nm acl_clear_flags_np
+.Nd clear flags from a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_clear_flags_np "acl_flagset_t flagset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_clear_flags_np
+function
+is a non-portable call that clears all flags from flagset
+.Fa flagset_d .
+.Sh RETURN VALUES
+.Rv -std acl_clear_flags_np
+.Sh ERRORS
+The
+.Fn acl_clear_flags_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_clear_flags_np
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_clear_flags_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_compat.c b/lib/libc/posix1e/acl_compat.c
new file mode 100644
index 0000000..c433920
--- /dev/null
+++ b/lib/libc/posix1e/acl_compat.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2008 Edward Tomasz Napierała <trasz@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$");
+
+#include <sys/acl.h>
+
+/*
+ * Compatibility wrappers for applications compiled against libc from before
+ * NFSv4 ACLs were added.
+ */
+int
+__oldacl_get_perm_np(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_get_perm_np(permset_d, perm));
+}
+
+int
+__oldacl_add_perm(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_add_perm(permset_d, perm));
+}
+
+int
+__oldacl_delete_perm(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_delete_perm(permset_d, perm));
+}
+
+__sym_compat(acl_get_perm_np, __oldacl_get_perm_np, FBSD_1.0);
+__sym_compat(acl_add_perm, __oldacl_add_perm, FBSD_1.0);
+__sym_compat(acl_delete_perm, __oldacl_delete_perm, FBSD_1.0);
diff --git a/lib/libc/posix1e/acl_copy.c b/lib/libc/posix1e/acl_copy.c
index eefa1c8..fc4c25d 100644
--- a/lib/libc/posix1e/acl_copy.c
+++ b/lib/libc/posix1e/acl_copy.c
@@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <string.h>
+#include "acl_support.h"
+
/*
* acl_copy_entry() (23.4.4): copy the contents of ACL entry src_d to
* ACL entry dest_d
@@ -48,9 +50,21 @@ acl_copy_entry(acl_entry_t dest_d, acl_entry_t src_d)
return (-1);
}
- dest_d->ae_tag = src_d->ae_tag;
- dest_d->ae_id = src_d->ae_id;
+ /*
+ * Can we brand the new entry the same as the source entry?
+ */
+ if (!_entry_brand_may_be(dest_d, _entry_brand(src_d))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _entry_brand_as(dest_d, _entry_brand(src_d));
+
+ dest_d->ae_tag = src_d->ae_tag;
+ dest_d->ae_id = src_d->ae_id;
dest_d->ae_perm = src_d->ae_perm;
+ dest_d->ae_entry_type = src_d->ae_entry_type;
+ dest_d->ae_flags = src_d->ae_flags;
return (0);
}
diff --git a/lib/libc/posix1e/acl_create_entry.3 b/lib/libc/posix1e/acl_create_entry.3
index e51bb6b..2442783 100644
--- a/lib/libc/posix1e/acl_create_entry.3
+++ b/lib/libc/posix1e/acl_create_entry.3
@@ -25,11 +25,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 16, 2001
+.Dd June 25, 2009
.Dt ACL_CREATE_ENTRY 3
.Os
.Sh NAME
.Nm acl_create_entry
+.Nm acl_create_entry_np
.Nd create a new ACL entry
.Sh LIBRARY
.Lb libc
@@ -38,6 +39,8 @@
.In sys/acl.h
.Ft int
.Fn acl_create_entry "acl_t *acl_p" "acl_entry_t *entry_p"
+.Ft int
+.Fn acl_create_entry_np "acl_t *acl_p" "acl_entry_t *entry_p" "int index"
.Sh DESCRIPTION
The
.Fn acl_create_entry
@@ -45,6 +48,16 @@ function
is a POSIX.1e call that creates a new ACL entry in the ACL
pointed to by
.Fa acl_p .
+The
+.Fn acl_create_entry_np
+function is a non-portable version that creates the ACL entry
+at position
+.Fa index .
+Positions are numbered starting from zero, i.e. calling
+.Fn acl_create_entry_np
+with
+.Fa index
+argument equal to zero will prepend the entry to the ACL.
.Sh RETURN VALUES
.Rv -std acl_create_entry
.Sh ERRORS
@@ -56,6 +69,9 @@ function fails if:
Argument
.Fa acl_p
does not point to a pointer to a valid ACL.
+Argument
+.Fa index
+is out of bounds.
.It Bq Er ENOMEM
The ACL working storage requires more memory than is
allowed by the hardware or system-imposed memory
diff --git a/lib/libc/posix1e/acl_delete.c b/lib/libc/posix1e/acl_delete.c
index a93cd7b..1bbadd5 100644
--- a/lib/libc/posix1e/acl_delete.c
+++ b/lib/libc/posix1e/acl_delete.c
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
#include <sys/errno.h>
+#include "acl_support.h"
+
int
acl_delete_def_file(const char *path_p)
{
@@ -56,6 +58,7 @@ int
acl_delete_file_np(const char *path_p, acl_type_t type)
{
+ type = _acl_type_unold(type);
return (__acl_delete_file(path_p, type));
}
@@ -63,13 +66,14 @@ int
acl_delete_link_np(const char *path_p, acl_type_t type)
{
+ type = _acl_type_unold(type);
return (__acl_delete_link(path_p, type));
}
-
int
acl_delete_fd_np(int filedes, acl_type_t type)
{
+ type = _acl_type_unold(type);
return (___acl_delete_fd(filedes, type));
}
diff --git a/lib/libc/posix1e/acl_delete_entry.3 b/lib/libc/posix1e/acl_delete_entry.3
index aafeae6..3705f07 100644
--- a/lib/libc/posix1e/acl_delete_entry.3
+++ b/lib/libc/posix1e/acl_delete_entry.3
@@ -25,11 +25,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 10, 2001
+.Dd June 25, 2009
.Dt ACL_DELETE_ENTRY 3
.Os
.Sh NAME
-.Nm acl_delete_entry
+.Nm acl_delete_entry ,
+.Nm acl_delete_entry_np ,
.Nd delete an ACL entry from an ACL
.Sh LIBRARY
.Lb libc
@@ -38,6 +39,8 @@
.In sys/acl.h
.Ft int
.Fn acl_delete_entry "acl_t acl" "acl_entry_t entry_d"
+.Ft int
+.Fn acl_delete_entry_np "acl_t acl" "int index"
.Sh DESCRIPTION
The
.Fn acl_delete_entry
@@ -46,6 +49,18 @@ is a POSIX.1e call that removes the ACL entry
.Fa entry_d
from ACL
.Fa acl .
+The
+.Fn acl_delete_entry_np
+function is a non-portable version that removes the ACL entry
+at position
+.Fa index
+from ACL
+.Fa acl .
+Positions are numbered starting from zero, i.e. calling
+.Fn acl_delete_entry_np
+with
+.Fa index
+argument equal to zero will remove the first ACL entry.
.Sh RETURN VALUES
.Rv -std acl_delete_entry
.Sh ERRORS
@@ -61,6 +76,9 @@ Argument
.Fa entry_d
is not a valid descriptor for an ACL entry in
.Fa acl .
+Argument
+.Fa index
+is out of bounds.
.El
.Sh SEE ALSO
.Xr acl 3 ,
diff --git a/lib/libc/posix1e/acl_delete_entry.c b/lib/libc/posix1e/acl_delete_entry.c
index 3195fac..7dd60b8 100644
--- a/lib/libc/posix1e/acl_delete_entry.c
+++ b/lib/libc/posix1e/acl_delete_entry.c
@@ -33,6 +33,39 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
#include <errno.h>
#include <string.h>
+#include <stdio.h>
+
+#include "acl_support.h"
+
+static int
+_entry_matches(const acl_entry_t a, const acl_entry_t b)
+{
+ /*
+ * There is a semantical difference here between NFSv4 and POSIX
+ * draft ACLs. In POSIX, there may be only one entry for the particular
+ * user or group. In NFSv4 ACL, there may be any number of them. We're
+ * trying to be more specific here in that case.
+ */
+ switch (_entry_brand(a)) {
+ case ACL_BRAND_NFS4:
+ if (a->ae_tag != b->ae_tag || a->ae_entry_type != b->ae_entry_type)
+ return (0);
+
+ /* If ae_ids matter, compare them as well. */
+ if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
+ if (a->ae_id != b->ae_id)
+ return (0);
+ }
+
+ return (1);
+
+ default:
+ if ((a->ae_tag == b->ae_tag) && (a->ae_id == b->ae_id))
+ return (1);
+ }
+
+ return (0);
+}
/*
* acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d
@@ -42,7 +75,7 @@ int
acl_delete_entry(acl_t acl, acl_entry_t entry_d)
{
struct acl *acl_int;
- int i;
+ int i, j, found = 0;
if (acl == NULL || entry_d == NULL) {
errno = EINVAL;
@@ -51,29 +84,74 @@ acl_delete_entry(acl_t acl, acl_entry_t entry_d)
acl_int = &acl->ats_acl;
+ if (_entry_brand(entry_d) != _acl_brand(acl)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
if ((acl->ats_acl.acl_cnt < 1) ||
(acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
errno = EINVAL;
return (-1);
}
- for (i = 0; i < acl->ats_acl.acl_cnt; i++) {
- /* if this is our entry... */
- if ((acl->ats_acl.acl_entry[i].ae_tag == entry_d->ae_tag) &&
- (acl->ats_acl.acl_entry[i].ae_id == entry_d->ae_id)) {
+ for (i = 0; i < acl->ats_acl.acl_cnt;) {
+ if (_entry_matches(&(acl->ats_acl.acl_entry[i]), entry_d)) {
/* ...shift the remaining entries... */
- for (; i < acl->ats_acl.acl_cnt - 1; ++i)
- acl->ats_acl.acl_entry[i] =
- acl->ats_acl.acl_entry[i+1];
+ for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j)
+ acl->ats_acl.acl_entry[j] =
+ acl->ats_acl.acl_entry[j+1];
/* ...drop the count and zero the unused entry... */
acl->ats_acl.acl_cnt--;
- bzero(&acl->ats_acl.acl_entry[i],
+ bzero(&acl->ats_acl.acl_entry[j],
sizeof(struct acl_entry));
acl->ats_cur_entry = 0;
- return (0);
- }
+
+ /* Continue with the loop to remove all maching entries. */
+ found = 1;
+ } else
+ i++;
}
+ if (found)
+ return (0);
errno = EINVAL;
return (-1);
}
+
+int
+acl_delete_entry_np(acl_t acl, int offset)
+{
+ struct acl *acl_int;
+ int i;
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &acl->ats_acl;
+
+ if (offset < 0 || offset >= acl_int->acl_cnt) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((acl->ats_acl.acl_cnt < 1) ||
+ (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* ...shift the remaining entries... */
+ for (i = offset; i < acl->ats_acl.acl_cnt - 1; ++i)
+ acl->ats_acl.acl_entry[i] =
+ acl->ats_acl.acl_entry[i+1];
+ /* ...drop the count and zero the unused entry... */
+ acl->ats_acl.acl_cnt--;
+ bzero(&acl->ats_acl.acl_entry[i],
+ sizeof(struct acl_entry));
+ acl->ats_cur_entry = 0;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_delete_flag_np.3 b/lib/libc/posix1e/acl_delete_flag_np.3
new file mode 100644
index 0000000..211a97a
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_flag_np.3
@@ -0,0 +1,84 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd March 10, 2001
+.Dt ACL_DELETE_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_delete_flag_np
+.Nd delete flags from a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_flag_np
+function
+is a non-portable call that removes specific flags from flagset
+.Fa flags .
+.Sh RETURN VALUES
+.Rv -std acl_delete_flag_np
+.Sh ERRORS
+The
+.Fn acl_delete_flag_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset.
+Argument
+.Fa flag
+does not contain a valid
+.Vt acl_flag_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flag_nps 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_delete_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_delete_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_entry.c b/lib/libc/posix1e/acl_entry.c
index f5bdbed..56396f9 100644
--- a/lib/libc/posix1e/acl_entry.c
+++ b/lib/libc/posix1e/acl_entry.c
@@ -51,7 +51,12 @@ acl_create_entry(acl_t *acl_p, acl_entry_t *entry_p)
acl_int = &(*acl_p)->ats_acl;
- if ((acl_int->acl_cnt >= ACL_MAX_ENTRIES) || (acl_int->acl_cnt < 0)) {
+ /*
+ * +1, because we are checking if there is space left for one more
+ * entry.
+ */
+ if ((acl_int->acl_cnt + 1 >= ACL_MAX_ENTRIES) ||
+ (acl_int->acl_cnt < 0)) {
errno = EINVAL;
return (-1);
}
@@ -61,6 +66,50 @@ acl_create_entry(acl_t *acl_p, acl_entry_t *entry_p)
(**entry_p).ae_tag = ACL_UNDEFINED_TAG;
(**entry_p).ae_id = ACL_UNDEFINED_ID;
(**entry_p).ae_perm = ACL_PERM_NONE;
+ (**entry_p).ae_entry_type = 0;
+ (**entry_p).ae_flags = 0;
+
+ (*acl_p)->ats_cur_entry = 0;
+
+ return (0);
+}
+
+int
+acl_create_entry_np(acl_t *acl_p, acl_entry_t *entry_p, int offset)
+{
+ int i;
+ struct acl *acl_int;
+
+ if (acl_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &(*acl_p)->ats_acl;
+
+ if ((acl_int->acl_cnt + 1 >= ACL_MAX_ENTRIES) || (acl_int->acl_cnt < 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (offset < 0 || offset >= acl_int->acl_cnt) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Make room for the new entry. */
+ for (i = acl_int->acl_cnt; i > offset; i--)
+ acl_int->acl_entry[i] = acl_int->acl_entry[i - 1];
+
+ acl_int->acl_cnt++;
+
+ *entry_p = &acl_int->acl_entry[offset];
+
+ (**entry_p).ae_tag = ACL_UNDEFINED_TAG;
+ (**entry_p).ae_id = ACL_UNDEFINED_ID;
+ (**entry_p).ae_perm = ACL_PERM_NONE;
+ (**entry_p).ae_entry_type = 0;
+ (**entry_p).ae_flags= 0;
(*acl_p)->ats_cur_entry = 0;
diff --git a/lib/libc/posix1e/acl_flag.c b/lib/libc/posix1e/acl_flag.c
new file mode 100644
index 0000000..39e258d
--- /dev/null
+++ b/lib/libc/posix1e/acl_flag.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@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$");
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+static int
+_flag_is_invalid(acl_flag_t flag)
+{
+
+ if ((flag & ACL_FLAGS_BITS) == flag)
+ return (0);
+
+ errno = EINVAL;
+
+ return (1);
+}
+
+int
+acl_add_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ *flagset_d |= flag;
+
+ return (0);
+}
+
+int
+acl_clear_flags_np(acl_flagset_t flagset_d)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *flagset_d |= 0;
+
+ return (0);
+}
+
+int
+acl_delete_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ *flagset_d &= ~flag;
+
+ return (0);
+}
+
+int
+acl_get_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ if (*flagset_d & flag)
+ return (1);
+
+ return (0);
+}
+
+int
+acl_get_flagset_np(acl_entry_t entry_d, acl_flagset_t *flagset_p)
+{
+
+ if (entry_d == NULL || flagset_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *flagset_p = &entry_d->ae_flags;
+
+ return (0);
+}
+
+int
+acl_set_flagset_np(acl_entry_t entry_d, acl_flagset_t flagset_d)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+
+ if (_flag_is_invalid(*flagset_d))
+ return (-1);
+
+ entry_d->ae_flags = *flagset_d;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_from_text.c b/lib/libc/posix1e/acl_from_text.c
index c679b17..98c5426 100644
--- a/lib/libc/posix1e/acl_from_text.c
+++ b/lib/libc/posix1e/acl_from_text.c
@@ -40,45 +40,15 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include "acl_support.h"
static int _posix1e_acl_name_to_id(acl_tag_t tag, char *name, uid_t *id);
static acl_tag_t acl_string_to_tag(char *tag, char *qualifier);
-static char *string_skip_whitespace(char *string);
-static void string_trim_trailing_whitespace(char *string);
-static char *
-string_skip_whitespace(char *string)
-{
-
- while (*string && ((*string == ' ') || (*string == '\t'))) {
- string++;
- }
- return (string);
-}
-
-static void
-string_trim_trailing_whitespace(char *string)
-{
- char *end;
-
- if (*string == '\0')
- return;
-
- end = string + strlen(string) - 1;
-
- while (end != string) {
- if ((*end == ' ') || (*end == '\t')) {
- *end = '\0';
- end--;
- } else {
- return;
- }
- }
-
- return;
-}
+int _nfs4_acl_entry_from_text(acl_t aclp, char *entry);
+int _text_could_be_nfs4_acl(const char *entry);
static acl_tag_t
acl_string_to_tag(char *tag, char *qualifier)
@@ -109,6 +79,112 @@ acl_string_to_tag(char *tag, char *qualifier)
}
}
+static int
+_posix1e_acl_entry_from_text(acl_t aclp, char *entry)
+{
+ acl_tag_t t;
+ acl_perm_t p;
+ char *tag, *qualifier, *permission;
+ uid_t id;
+ int error;
+
+ assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
+
+ /* Split into three ':' delimited fields. */
+ tag = strsep(&entry, ":");
+ if (tag == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ tag = string_skip_whitespace(tag);
+ if ((*tag == '\0') && (!entry)) {
+ /*
+ * Is an entirely comment line, skip to next
+ * comma.
+ */
+ return (0);
+ }
+ string_trim_trailing_whitespace(tag);
+
+ qualifier = strsep(&entry, ":");
+ if (qualifier == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ qualifier = string_skip_whitespace(qualifier);
+ string_trim_trailing_whitespace(qualifier);
+
+ permission = strsep(&entry, ":");
+ if (permission == NULL || entry) {
+ errno = EINVAL;
+ return (-1);
+ }
+ permission = string_skip_whitespace(permission);
+ string_trim_trailing_whitespace(permission);
+
+ t = acl_string_to_tag(tag, qualifier);
+ if (t == -1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ error = _posix1e_acl_string_to_perm(permission, &p);
+ if (error == -1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch(t) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_MASK:
+ case ACL_OTHER:
+ if (*qualifier != '\0') {
+ errno = EINVAL;
+ return (-1);
+ }
+ id = 0;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ error = _posix1e_acl_name_to_id(t, qualifier,
+ &id);
+ if (error == -1)
+ return (-1);
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ error = _posix1e_acl_add_entry(aclp, t, id, p);
+ if (error == -1)
+ return (-1);
+
+ return (0);
+}
+
+static int
+_text_is_nfs4_entry(const char *entry)
+{
+ int count = 0;
+
+ assert(strlen(entry) > 0);
+
+ while (*entry != '\0') {
+ if (*entry == ':' || *entry == '@')
+ count++;
+ entry++;
+ }
+
+ if (count <= 2)
+ return (0);
+
+ return (1);
+}
+
/*
* acl_from_text -- Convert a string into an ACL.
* Postpone most validity checking until the end and call acl_valid() to do
@@ -117,20 +193,16 @@ acl_string_to_tag(char *tag, char *qualifier)
acl_t
acl_from_text(const char *buf_p)
{
- acl_tag_t t;
- acl_perm_t p;
acl_t acl;
char *mybuf_p, *line, *cur, *notcomment, *comment, *entry;
- char *tag, *qualifier, *permission;
int error;
- uid_t id;
/* Local copy we can mess up. */
mybuf_p = strdup(buf_p);
if (mybuf_p == NULL)
return(NULL);
- acl = acl_init(3);
+ acl = acl_init(3); /* XXX: WTF, 3? */
if (acl == NULL) {
free(mybuf_p);
return(NULL);
@@ -145,77 +217,33 @@ acl_from_text(const char *buf_p)
/* Inner loop: delimit at ',' boundaries. */
while ((entry = strsep(&notcomment, ","))) {
- /* Now split into three ':' delimited fields. */
- tag = strsep(&entry, ":");
- if (tag == NULL) {
- errno = EINVAL;
- goto error_label;
- }
- tag = string_skip_whitespace(tag);
- if ((*tag == '\0') && (!entry)) {
- /*
- * Is an entirely comment line, skip to next
- * comma.
- */
- continue;
- }
- string_trim_trailing_whitespace(tag);
- qualifier = strsep(&entry, ":");
- if (qualifier == NULL) {
- errno = EINVAL;
- goto error_label;
- }
- qualifier = string_skip_whitespace(qualifier);
- string_trim_trailing_whitespace(qualifier);
-
- permission = strsep(&entry, ":");
- if (permission == NULL || entry) {
- errno = EINVAL;
- goto error_label;
- }
- permission = string_skip_whitespace(permission);
- string_trim_trailing_whitespace(permission);
+ /* Skip empty lines. */
+ if (strlen(string_skip_whitespace(entry)) == 0)
+ continue;
- t = acl_string_to_tag(tag, qualifier);
- if (t == -1) {
- errno = EINVAL;
- goto error_label;
+ if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) {
+ if (_text_is_nfs4_entry(entry))
+ _acl_brand_as(acl, ACL_BRAND_NFS4);
+ else
+ _acl_brand_as(acl, ACL_BRAND_POSIX);
}
- error = _posix1e_acl_string_to_perm(permission, &p);
- if (error == -1) {
- errno = EINVAL;
- goto error_label;
- }
-
- switch(t) {
- case ACL_USER_OBJ:
- case ACL_GROUP_OBJ:
- case ACL_MASK:
- case ACL_OTHER:
- if (*qualifier != '\0') {
- errno = EINVAL;
- goto error_label;
- }
- id = 0;
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_NFS4:
+ error = _nfs4_acl_entry_from_text(acl, entry);
break;
- case ACL_USER:
- case ACL_GROUP:
- error = _posix1e_acl_name_to_id(t, qualifier,
- &id);
- if (error == -1)
- goto error_label;
+ case ACL_BRAND_POSIX:
+ error = _posix1e_acl_entry_from_text(acl, entry);
break;
default:
- errno = EINVAL;
- goto error_label;
+ error = EINVAL;
+ break;
}
- error = _posix1e_acl_add_entry(acl, t, id, p);
- if (error == -1)
+ if (error)
goto error_label;
}
}
diff --git a/lib/libc/posix1e/acl_from_text_nfs4.c b/lib/libc/posix1e/acl_from_text_nfs4.c
new file mode 100644
index 0000000..12bfb4e
--- /dev/null
+++ b/lib/libc/posix1e/acl_from_text_nfs4.c
@@ -0,0 +1,312 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@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$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
+#include <err.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+#define MAX_ENTRY_LENGTH 512
+
+/*
+ * Parse the tag field of ACL entry passed as "str". If qualifier
+ * needs to follow, then the variable referenced by "need_qualifier"
+ * is set to 1, otherwise it's set to 0.
+ */
+static int
+parse_tag(const char *str, acl_entry_t entry, int *need_qualifier)
+{
+
+ assert(need_qualifier != NULL);
+ *need_qualifier = 0;
+
+ if (strcmp(str, "owner@") == 0)
+ return (acl_set_tag_type(entry, ACL_USER_OBJ));
+ if (strcmp(str, "group@") == 0)
+ return (acl_set_tag_type(entry, ACL_GROUP_OBJ));
+ if (strcmp(str, "everyone@") == 0)
+ return (acl_set_tag_type(entry, ACL_EVERYONE));
+
+ *need_qualifier = 1;
+
+ if (strcmp(str, "user") == 0 || strcmp(str, "u") == 0)
+ return (acl_set_tag_type(entry, ACL_USER));
+ if (strcmp(str, "group") == 0 || strcmp(str, "g") == 0)
+ return (acl_set_tag_type(entry, ACL_GROUP));
+
+ warnx("malformed ACL: invalid \"tag\" field");
+
+ return (-1);
+}
+
+/*
+ * Parse the qualifier field of ACL entry passed as "str".
+ * If user or group name cannot be resolved, then the variable
+ * referenced by "need_qualifier" is set to 1.
+ */
+static int
+parse_qualifier(char *str, acl_entry_t entry, int *need_qualifier)
+{
+ int qualifier_length, error;
+ id_t id;
+ char *end;
+ struct passwd *pwd;
+ struct group *grp;
+ acl_tag_t tag;
+
+ assert(need_qualifier != NULL);
+ *need_qualifier = 0;
+
+ qualifier_length = strlen(str);
+
+ if (qualifier_length == 0) {
+ warnx("malformed ACL: empty \"qualifier\" field");
+ return (-1);
+ }
+
+ /* XXX: Can we assume that valid username never begins with a digit? */
+ if (isdigit(str[0])) {
+ id = strtod(str, &end);
+
+ if (end - str != qualifier_length) {
+ warnx("malformed ACL: trailing characters "
+ "after numerical id");
+ return (-1);
+ }
+
+ return (acl_set_qualifier(entry, &id));
+ }
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ assert(tag == ACL_USER || tag == ACL_GROUP);
+
+ if (tag == ACL_USER) {
+ /* XXX: Thread-unsafe. */
+ pwd = getpwnam(str);
+ if (pwd == NULL) {
+ *need_qualifier = 1;
+ return (0);
+ }
+
+ return (acl_set_qualifier(entry, &(pwd->pw_uid)));
+ }
+
+ /* XXX: Thread-unsafe. */
+ grp = getgrnam(str);
+ if (grp == NULL) {
+ *need_qualifier = 1;
+ return (0);
+ }
+
+ return (acl_set_qualifier(entry, &(grp->gr_gid)));
+}
+
+static int
+parse_access_mask(char *str, acl_entry_t entry)
+{
+ int error;
+ acl_perm_t perm;
+
+ error = _nfs4_parse_access_mask(str, &perm);
+ if (error)
+ return (error);
+
+ error = acl_set_permset(entry, &perm);
+
+ return (error);
+}
+
+static int
+parse_flags(char *str, acl_entry_t entry)
+{
+ int error;
+ acl_flag_t flags;
+
+ error = _nfs4_parse_flags(str, &flags);
+ if (error)
+ return (error);
+
+ error = acl_set_flagset_np(entry, &flags);
+
+ return (error);
+}
+
+static int
+parse_entry_type(const char *str, acl_entry_t entry)
+{
+
+ if (strcmp(str, "allow") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALLOW));
+ if (strcmp(str, "deny") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_DENY));
+ if (strcmp(str, "audit") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_AUDIT));
+ if (strcmp(str, "alarm") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALARM));
+
+ warnx("malformed ACL: invalid \"type\" field");
+
+ return (-1);
+}
+
+static int
+parse_appended_id(char *str, acl_entry_t entry)
+{
+ int qualifier_length;
+ char *end;
+ id_t id;
+
+ qualifier_length = strlen(str);
+ if (qualifier_length == 0) {
+ warnx("malformed ACL: \"appended id\" field present, "
+ "but empty");
+ return (-1);
+ }
+
+ id = strtod(str, &end);
+ if (end - str != qualifier_length) {
+ warnx("malformed ACL: appended id is not a number");
+ return (-1);
+ }
+
+ return (acl_set_qualifier(entry, &id));
+}
+
+static int
+number_of_colons(const char *str)
+{
+ int count = 0;
+
+ while (*str != '\0') {
+ if (*str == ':')
+ count++;
+
+ str++;
+ }
+
+ return (count);
+}
+
+int
+_nfs4_acl_entry_from_text(acl_t aclp, char *str)
+{
+ int error, need_qualifier;
+ acl_entry_t entry;
+ char *field, *qualifier_field;
+
+ error = acl_create_entry(&aclp, &entry);
+ if (error)
+ return (error);
+
+ assert(_entry_brand(entry) == ACL_BRAND_NFS4);
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+
+ field = string_skip_whitespace(field);
+ if ((*field == '\0') && (!str)) {
+ /*
+ * Is an entirely comment line, skip to next
+ * comma.
+ */
+ return (0);
+ }
+
+ error = parse_tag(field, entry, &need_qualifier);
+ if (error)
+ goto malformed_field;
+
+ if (need_qualifier) {
+ if (str == NULL)
+ goto truncated_entry;
+ qualifier_field = field = strsep(&str, ":");
+ error = parse_qualifier(field, entry, &need_qualifier);
+ if (error)
+ goto malformed_field;
+ }
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+ error = parse_access_mask(field, entry);
+ if (error)
+ goto malformed_field;
+
+ if (str == NULL)
+ goto truncated_entry;
+ /* Do we have "flags" field? */
+ if (number_of_colons(str) > 0) {
+ field = strsep(&str, ":");
+ error = parse_flags(field, entry);
+ if (error)
+ goto malformed_field;
+ }
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+ error = parse_entry_type(field, entry);
+ if (error)
+ goto malformed_field;
+
+ if (need_qualifier) {
+ if (str == NULL) {
+ warnx("malformed ACL: unknown user or group name "
+ "\"%s\"", qualifier_field);
+ goto truncated_entry;
+ }
+
+ error = parse_appended_id(str, entry);
+ if (error)
+ goto malformed_field;
+ }
+
+ return (0);
+
+truncated_entry:
+malformed_field:
+ acl_delete_entry(aclp, entry);
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_get.3 b/lib/libc/posix1e/acl_get.3
index fa915df..651709f 100644
--- a/lib/libc/posix1e/acl_get.3
+++ b/lib/libc/posix1e/acl_get.3
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 29, 2002
+.Dd June 25, 2009
.Dt ACL_GET 3
.Os
.Sh NAME
@@ -91,6 +91,18 @@ with the object referred to by
.Va fd .
The ACL in the working storage shall not participate in any access control
decisions.
+.Pp
+Valid values for the
+.Va type
+argument are:
+.Pp
+.Bl -column -offset 3n "ACL_TYPE_DEFAULT"
+.It ACL_TYPE_ACCESS POSIX.1e access ACL
+.It ACL_TYPE_DEFAULT POSIX.1e default ACL
+.It ACL_TYPE_NFS4 NFSv4 ACL
+.El
+.Pp
+The ACL returned will be branded accordingly.
.Sh IMPLEMENTATION NOTES
.Fx Ns 's
support for POSIX.1e interfaces and features is still under
@@ -137,6 +149,7 @@ The file system does not support ACL retrieval.
.Xr acl 3 ,
.Xr acl_free 3 ,
.Xr acl_get 3 ,
+.Xr acl_get_brand_np 3 ,
.Xr acl_set 3 ,
.Xr posix1e 3
.Sh STANDARDS
diff --git a/lib/libc/posix1e/acl_get.c b/lib/libc/posix1e/acl_get.c
index 1f97baa..8a77ab1 100644
--- a/lib/libc/posix1e/acl_get.c
+++ b/lib/libc/posix1e/acl_get.c
@@ -47,8 +47,12 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
#include <errno.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+
+#include "acl_support.h"
acl_t
acl_get_file(const char *path_p, acl_type_t type)
@@ -60,12 +64,16 @@ acl_get_file(const char *path_p, acl_type_t type)
if (aclp == NULL)
return (NULL);
+ type = _acl_type_unold(type);
error = __acl_get_file(path_p, type, &aclp->ats_acl);
if (error) {
acl_free(aclp);
return (NULL);
}
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
return (aclp);
}
@@ -79,32 +87,26 @@ acl_get_link_np(const char *path_p, acl_type_t type)
if (aclp == NULL)
return (NULL);
+ type = _acl_type_unold(type);
error = __acl_get_link(path_p, type, &aclp->ats_acl);
if (error) {
acl_free(aclp);
return (NULL);
}
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
return (aclp);
}
acl_t
acl_get_fd(int fd)
{
- acl_t aclp;
- int error;
-
- aclp = acl_init(ACL_MAX_ENTRIES);
- if (aclp == NULL)
- return (NULL);
-
- error = ___acl_get_fd(fd, ACL_TYPE_ACCESS, &aclp->ats_acl);
- if (error) {
- acl_free(aclp);
- return (NULL);
- }
+ if (fpathconf(fd, _PC_ACL_NFS4) == 1)
+ return (acl_get_fd_np(fd, ACL_TYPE_NFS4));
- return (aclp);
+ return (acl_get_fd_np(fd, ACL_TYPE_ACCESS));
}
acl_t
@@ -117,12 +119,16 @@ acl_get_fd_np(int fd, acl_type_t type)
if (aclp == NULL)
return (NULL);
+ type = _acl_type_unold(type);
error = ___acl_get_fd(fd, type, &aclp->ats_acl);
if (error) {
acl_free(aclp);
return (NULL);
}
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
return (aclp);
}
@@ -213,3 +219,22 @@ acl_get_tag_type(acl_entry_t entry_d, acl_tag_t *tag_type_p)
return (0);
}
+
+int
+acl_get_entry_type_np(acl_entry_t entry_d, acl_entry_type_t *entry_type_p)
+{
+
+ if (entry_d == NULL || entry_type_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *entry_type_p = entry_d->ae_entry_type;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_get_brand_np.3 b/lib/libc/posix1e/acl_get_brand_np.3
new file mode 100644
index 0000000..20f45dd
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_brand_np.3
@@ -0,0 +1,86 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_BRAND_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_brand_np
+.Nd retrieve the ACL brand from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_brand_np "acl_t acl" "int *brand_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_brand_np
+function
+is a non-portable call that returns the ACL brand for the ACL
+.Fa acl .
+Upon successful completion, the location referred to by the argument
+.Fa brand_p
+will be set to the ACL brand of the ACL
+.Fa acl .
+.Pp
+Branding is an internal mechanism intended to prevent mixing POSIX.1e
+and NFSv4 entries by mistake.
+It's also used by the libc to determine how to print out the ACL.
+The first call to function that is specific for one particular brand - POSIX.1e
+or NFSv4 - "brands" the ACL.
+After that, calling function specific to another brand will result in error.
+.Sh RETURN VALUES
+.Rv -std acl_get_brand_np
+.Sh ERRORS
+The
+.Fn acl_get_brand_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_brand_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_brand_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_entry_type_np.3 b/lib/libc/posix1e/acl_get_entry_type_np.3
new file mode 100644
index 0000000..34d93be
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_entry_type_np.3
@@ -0,0 +1,80 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_ENTRY_TYPE_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_entry_type_np
+.Nd retrieve the ACL type from an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t *entry_type_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_entry_type_np
+function
+is a non-portable call that returns the ACL type for the NFSv4 ACL entry
+.Fa entry_d .
+Upon successful completion, the location referred to by the argument
+.Fa entry_type_p
+will be set to the ACL type of the ACL entry
+.Fa entry_d .
+.Sh RETURN VALUES
+.Rv -std acl_get_entry_type_np
+.Sh ERRORS
+The
+.Fn acl_get_entry_type_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an NFSv4 ACL entry;
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_set_entry_type_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry_type_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry_type_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_flag_np.3 b/lib/libc/posix1e/acl_get_flag_np.3
new file mode 100644
index 0000000..295ee3e
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_flag_np.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_flag_np
+.Nd check if a flag is set in a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_get_flag_np
+function
+is a non-portable function that checks if a flag is set in
+a flagset.
+.Sh RETURN VALUES
+If the flag in
+.Fa flag
+is set in the flagset
+.Fa flagset_d ,
+a value of
+1
+is returned, otherwise a value of
+0
+is returned.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_get_flag_np
+function will return a value of
+\-1
+and set global variable
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flag
+does not contain a valid ACL flag or argument
+.Fa flagset_d
+is not a valid ACL flagset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_flagset_np.3 b/lib/libc/posix1e/acl_get_flagset_np.3
new file mode 100644
index 0000000..7e72340
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_flagset_np.3
@@ -0,0 +1,83 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_FLAGSET_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_flagset_np
+.Nd retrieve flagset from an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_flagset_np "acl_entry_t entry_d" "acl_flagset_t *flagset_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_flagset_np
+function
+is a non-portable call that returns via
+.Fa flagset_np_p
+a descriptor to the flagset in the ACL entry
+.Fa entry_d .
+Subsequent operations using the returned flagset operate
+on the flagset within the ACL entry.
+.Sh RETURN VALUES
+.Rv -std acl_get_flagset_np
+.Sh ERRORS
+The
+.Fn acl_get_flagset_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
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_flagset_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_flagset_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_init.c b/lib/libc/posix1e/acl_init.c
index 6ce40de..4fe4037 100644
--- a/lib/libc/posix1e/acl_init.c
+++ b/lib/libc/posix1e/acl_init.c
@@ -38,10 +38,22 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+#ifndef CTASSERT
+#define CTASSERT(x) _CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y) __CTASSERT(x, y)
+#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1]
+#endif
+
+CTASSERT(1 << _ACL_T_ALIGNMENT_BITS > sizeof(struct acl_t_struct));
acl_t
acl_init(int count)
{
+ int error;
acl_t acl;
if (count > ACL_MAX_ENTRIES) {
@@ -53,9 +65,14 @@ acl_init(int count)
return (NULL);
}
- acl = malloc(sizeof(struct acl_t_struct));
- if (acl != NULL)
- bzero(acl, sizeof(struct acl_t_struct));
+ error = posix_memalign((void *)&acl, 1 << _ACL_T_ALIGNMENT_BITS,
+ sizeof(struct acl_t_struct));
+ if (error)
+ return (NULL);
+
+ bzero(acl, sizeof(struct acl_t_struct));
+ acl->ats_brand = ACL_BRAND_UNKNOWN;
+ acl->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
return (acl);
}
diff --git a/lib/libc/posix1e/acl_is_trivial_np.3 b/lib/libc/posix1e/acl_is_trivial_np.3
new file mode 100644
index 0000000..787e3f9
--- /dev/null
+++ b/lib/libc/posix1e/acl_is_trivial_np.3
@@ -0,0 +1,84 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_STRIP_NP 3
+.Os
+.Sh NAME
+.Nm acl_is_trivial_np
+.Nd determine whether ACL is trivial
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_is_trivial_np "const acl_t aclp" "int *trivialp"
+.Sh DESCRIPTION
+The
+.Fn acl_is_trivial
+function determines whether the ACL pointed to by the argument
+.Va acl
+is trivial.
+Upon successful completion, the location referred to by the argument
+.Fa trivialp
+will be set to 1, if the ACL
+.Fa aclp
+points to is trivial, or 0 if it's not.
+.Pp
+ACL is trivial if it can be fully expressed as a file mode without loosing
+any access rules.
+For POSIX.1e ACLs, ACL is trivial if it has the three required entries,
+one for owner, one for owning group, and one for other.
+For NFSv4 ACLs, ACL is trivial if it has the "canonical six" entries.
+Files that have non-trivial ACL have a plus sign appended after mode bits
+in "ls -l" output.
+.Sh RETURN VALUES
+.Rv -std acl_get_tag_type
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_is_trivial_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_set.3 b/lib/libc/posix1e/acl_set.3
index a2d50b8..a6134fe 100644
--- a/lib/libc/posix1e/acl_set.3
+++ b/lib/libc/posix1e/acl_set.3
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 29, 2002
+.Dd June 25, 2009
.Dt ACL_SET 3
.Os
.Sh NAME
@@ -75,6 +75,21 @@ The
.Fn acl_set_link_np
function acts on a symlink rather than its target, if the target of the
path is a symlink.
+.Pp
+Valid values for the
+.Va type
+argument are:
+.Pp
+.Bl -column -offset 3n "ACL_TYPE_DEFAULT"
+.It ACL_TYPE_ACCESS POSIX.1e access ACL
+.It ACL_TYPE_DEFAULT POSIX.1e default ACL
+.It ACL_TYPE_NFS4 NFSv4 ACL
+.El
+.Pp
+Trying to set ACL_TYPE_NFS4 with
+.Va acl
+branded as POSIX.1e, or ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT with ACL
+branded as NFSv4, will result in error.
.Sh IMPLEMENTATION NOTES
.Fx Ns 's
support for POSIX.1e interfaces and features is still under
@@ -100,7 +115,7 @@ Argument
does not point to a valid ACL for this object, or the ACL type
specified in
.Va type
-is invalid for this object, or both.
+is invalid for this object, or there is branding mismatch.
.It Bq Er ENAMETOOLONG
A component of a pathname exceeded 255 characters, or an
entire path name exceeded 1023 characters.
@@ -123,6 +138,7 @@ read-only.
.Xr acl 3 ,
.Xr acl_delete 3 ,
.Xr acl_get 3 ,
+.Xr acl_get_brand_np 3 ,
.Xr acl_valid 3 ,
.Xr posix1e 3
.Sh STANDARDS
diff --git a/lib/libc/posix1e/acl_set.c b/lib/libc/posix1e/acl_set.c
index 34d5a33..f9ee76d 100644
--- a/lib/libc/posix1e/acl_set.c
+++ b/lib/libc/posix1e/acl_set.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "acl_support.h"
@@ -58,6 +59,11 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
errno = EINVAL;
return (-1);
}
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
if (_posix1e_acl(acl, type)) {
error = _posix1e_acl_sort(acl);
if (error) {
@@ -80,6 +86,11 @@ acl_set_link_np(const char *path_p, acl_type_t type, acl_t acl)
errno = EINVAL;
return (-1);
}
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
if (_posix1e_acl(acl, type)) {
error = _posix1e_acl_sort(acl);
if (error) {
@@ -96,17 +107,11 @@ acl_set_link_np(const char *path_p, acl_type_t type, acl_t acl)
int
acl_set_fd(int fd, acl_t acl)
{
- int error;
- error = _posix1e_acl_sort(acl);
- if (error) {
- errno = error;
- return(-1);
- }
-
- acl->ats_cur_entry = 0;
+ if (fpathconf(fd, _PC_ACL_NFS4) == 1)
+ return (acl_set_fd_np(fd, acl, ACL_TYPE_NFS4));
- return (___acl_set_fd(fd, ACL_TYPE_ACCESS, &acl->ats_acl));
+ return (acl_set_fd_np(fd, acl, ACL_TYPE_ACCESS));
}
int
@@ -114,6 +119,15 @@ acl_set_fd_np(int fd, acl_t acl, acl_type_t type)
{
int error;
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
if (_posix1e_acl(acl, type)) {
error = _posix1e_acl_sort(acl);
if (error) {
@@ -140,6 +154,18 @@ acl_set_permset(acl_entry_t entry_d, acl_permset_t permset_d)
return (-1);
}
+ if ((*permset_d & ACL_POSIX1E_BITS) != *permset_d) {
+ if ((*permset_d & ACL_NFS4_PERM_BITS) != *permset_d) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+ }
+
entry_d->ae_perm = *permset_d;
return (0);
@@ -152,11 +178,11 @@ acl_set_permset(acl_entry_t entry_d, acl_permset_t permset_d)
int
acl_set_qualifier(acl_entry_t entry_d, const void *tag_qualifier_p)
{
+
if (!entry_d || !tag_qualifier_p) {
errno = EINVAL;
return (-1);
}
-
switch(entry_d->ae_tag) {
case ACL_USER:
case ACL_GROUP:
@@ -184,12 +210,31 @@ acl_set_tag_type(acl_entry_t entry_d, acl_tag_t tag_type)
}
switch(tag_type) {
+ case ACL_OTHER:
+ case ACL_MASK:
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_POSIX);
+ break;
+ case ACL_EVERYONE:
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+ break;
+ }
+
+ switch(tag_type) {
case ACL_USER_OBJ:
case ACL_USER:
case ACL_GROUP_OBJ:
case ACL_GROUP:
case ACL_MASK:
case ACL_OTHER:
+ case ACL_EVERYONE:
entry_d->ae_tag = tag_type;
return (0);
}
@@ -197,3 +242,30 @@ acl_set_tag_type(acl_entry_t entry_d, acl_tag_t tag_type)
errno = EINVAL;
return (-1);
}
+
+int
+acl_set_entry_type_np(acl_entry_t entry_d, acl_entry_type_t entry_type)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+
+ switch (entry_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ case ACL_ENTRY_TYPE_DENY:
+ case ACL_ENTRY_TYPE_AUDIT:
+ case ACL_ENTRY_TYPE_ALARM:
+ entry_d->ae_entry_type = entry_type;
+ return (0);
+ }
+
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_set_entry_type_np.3 b/lib/libc/posix1e/acl_set_entry_type_np.3
new file mode 100644
index 0000000..acfa2f5
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_entry_type_np.3
@@ -0,0 +1,95 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET_ENTRY_TYPE_NP 3
+.Os
+.Sh NAME
+.Nm acl_set_entry_type_np
+.Nd set NFSv4 ACL entry type
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t entry_type"
+.Sh DESCRIPTION
+The
+.Fn acl_set_entry_type_np
+function
+is a non-portable call that sets the type of the ACL entry
+.Fa entry_d
+to the value referred to by
+.Fa entry_type .
+.Pp
+Valid values are:
+.Pp
+.Bl -column -offset 3n "ACL_ENTRY_TYPE_ALLOW"
+.It ACL_ENTRY_TYPE_ALLOW "allow" type entry
+.It ACL_ENTRY_TYPE_DENY "deny" type entry
+.El
+.Pp
+This call brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_entry_type_np
+.Sh ERRORS
+The
+.Fn acl_set_entry_type_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.
+The value pointed to by
+.Fa entry_type
+is not valid.
+ACL is already branded as POSIX.1e.
+.It Bq Er ENOMEM
+The value to be returned requires more memory than is allowed
+by the hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_entry_type_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry_type_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry_type_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_set_flagset_np.3 b/lib/libc/posix1e/acl_set_flagset_np.3
new file mode 100644
index 0000000..d8dd622
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_flagset_np.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" 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 THE VOICES IN HIS HEAD 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET_FLAGSET_NP 3
+.Os
+.Sh NAME
+.Nm acl_set_flagset_np
+.Nd set the flags of an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_flagset_np "acl_entry_t entry_d" "acl_flagset_t flagset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_set_flagset_np
+function
+is a non-portable call that sets the flags of ACL entry
+.Fa entry_d
+with the flags contained in
+.Fa flagset_d .
+.Pp
+This call brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_flagset_np
+.Sh ERRORS
+The
+.Fn acl_set_flagset_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.
+ACL is already branded as POSIX.1e.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_set_flagset_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_set_flagset_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_set_qualifier.3 b/lib/libc/posix1e/acl_set_qualifier.3
index 5faefc8..47a60d8 100644
--- a/lib/libc/posix1e/acl_set_qualifier.3
+++ b/lib/libc/posix1e/acl_set_qualifier.3
@@ -42,7 +42,7 @@
The
.Fn acl_set_qualifier
function
-is a POSIX.1e call that sets the qualifier of the tag for the ACl entry
+is a POSIX.1e call that sets the qualifier of the tag for the ACL entry
.Fa entry_d
to the value referred to by
.Fa tag_qualifier_p .
diff --git a/lib/libc/posix1e/acl_set_tag_type.3 b/lib/libc/posix1e/acl_set_tag_type.3
index 7cbca81..2568922 100644
--- a/lib/libc/posix1e/acl_set_tag_type.3
+++ b/lib/libc/posix1e/acl_set_tag_type.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 10, 2001
+.Dd June 25, 2009
.Dt ACL_SET_TAG_TYPE 3
.Os
.Sh NAME
@@ -46,6 +46,26 @@ is a POSIX.1e call that sets the ACL tag type of ACL entry
.Fa entry_d
to the value of
.Fa tag_type .
+.Pp
+Valid values are:
+.Pp
+.Bl -column -offset 3n "ACL_OTHER_OBJ"
+.It ACL_USER_OBJ Permissions apply to file owner
+.It ACL_USER Permissions apply to additional user specified by qualifier
+.It ACL_GROUP_OBJ Permissions apply to file group
+.It ACL_GROUP Permissions apply to additional group specified by qualifier
+.It ACL_MASK Permissions specify mask
+.It ACL_OTHER Permissions apply to "other"
+.It ACL_OTHER_OBJ Same as ACL_OTHER
+.It ACL_EVERYONE Permissions apply to "everyone@"
+.El
+.Pp
+Calling
+.Fn acl_set_tag_type
+with
+.Fa tag_type
+equal to ACL_MASK, ACL_OTHER or ACL_OTHER_OBJ brands the ACL as POSIX.1e.
+Calling it with ACL_EVERYONE brands the ACL as NFSv4.
.Sh RETURN VALUES
.Rv -std acl_set_tag_type
.Sh ERRORS
@@ -60,9 +80,11 @@ is not a valid descriptor for an ACL entry.
Argument
.Fa tag_type
is not a valid ACL tag type.
+ACL is already branded differently.
.El
.Sh SEE ALSO
.Xr acl 3 ,
+.Xr acl_get_brand_np 3 ,
.Xr acl_get_tag_type 3 ,
.Xr posix1e 3
.Sh STANDARDS
diff --git a/lib/libc/posix1e/acl_strip.c b/lib/libc/posix1e/acl_strip.c
new file mode 100644
index 0000000..1dcdfcd
--- /dev/null
+++ b/lib/libc/posix1e/acl_strip.c
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * 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 THE VOICES IN HIS HEAD BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+/*
+ * These two routines from sys/kern/subr_acl_nfs4.c are used by both kernel
+ * and libc.
+ */
+void acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode,
+ int file_owner_id);
+void acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp);
+
+static acl_t
+_nfs4_acl_strip_np(const acl_t aclp, int recalculate_mask)
+{
+ acl_t newacl;
+ mode_t mode;
+
+ newacl = acl_init(ACL_MAX_ENTRIES);
+ if (newacl == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+
+ _acl_brand_as(newacl, ACL_BRAND_NFS4);
+
+ acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl));
+ acl_nfs4_sync_acl_from_mode(&(newacl->ats_acl), mode, -1);
+
+ return (newacl);
+}
+
+static acl_t
+_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
+{
+ acl_t acl_new, acl_old;
+ acl_entry_t entry, entry_new;
+ acl_permset_t perm;
+ acl_tag_t tag;
+ int entry_id, have_mask_entry;
+
+ assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
+
+ acl_old = acl_dup(aclp);
+ if (acl_old == NULL)
+ return (NULL);
+
+ assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);
+
+ have_mask_entry = 0;
+ acl_new = acl_init(ACL_MAX_ENTRIES);
+ if (acl_new == NULL)
+ return (NULL);
+ tag = ACL_UNDEFINED_TAG;
+
+ /* only save the default user/group/other entries */
+ entry_id = ACL_FIRST_ENTRY;
+ while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ assert(_entry_brand(entry) == ACL_BRAND_POSIX);
+
+ if (acl_get_tag_type(entry, &tag) == -1)
+ return (NULL);
+
+ switch(tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_OTHER:
+ if (acl_get_tag_type(entry, &tag) == -1)
+ return (NULL);
+ if (acl_get_permset(entry, &perm) == -1)
+ return (NULL);
+ if (acl_create_entry(&acl_new, &entry_new) == -1)
+ return (NULL);
+ if (acl_set_tag_type(entry_new, tag) == -1)
+ return (NULL);
+ if (acl_set_permset(entry_new, perm) == -1)
+ return (NULL);
+ if (acl_copy_entry(entry_new, entry) == -1)
+ return (NULL);
+ assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
+ break;
+ case ACL_MASK:
+ have_mask_entry = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);
+
+ if (have_mask_entry && recalculate_mask) {
+ if (acl_calc_mask(&acl_new) == -1)
+ return (NULL);
+ }
+
+ return (acl_new);
+}
+
+acl_t
+acl_strip_np(const acl_t aclp, int recalculate_mask)
+{
+ switch (_acl_brand(aclp)) {
+ case ACL_BRAND_NFS4:
+ return (_nfs4_acl_strip_np(aclp, recalculate_mask));
+
+ case ACL_BRAND_POSIX:
+ return (_posix1e_acl_strip_np(aclp, recalculate_mask));
+
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+}
+
+/*
+ * Return 1, if ACL is trivial, 0 otherwise.
+ *
+ * ACL is trivial, iff its meaning could be fully expressed using just file
+ * mode. In other words, ACL is trivial iff it doesn't have "+" to the right
+ * of the mode bits in "ls -l" output ;-)
+ */
+int
+acl_is_trivial_np(const acl_t aclp, int *trivialp)
+{
+ acl_t tmpacl;
+ int differs;
+
+ if (aclp == NULL || trivialp == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch (_acl_brand(aclp)) {
+ case ACL_BRAND_POSIX:
+ if (aclp->ats_acl.acl_cnt == 3)
+ *trivialp = 1;
+ else
+ *trivialp = 0;
+
+ return (0);
+
+ case ACL_BRAND_NFS4:
+ /*
+ * Calculate trivial ACL - using acl_strip_np - and compare
+ * with the original.
+ */
+ tmpacl = acl_strip_np(aclp, 0);
+ if (tmpacl == NULL)
+ return (-1);
+
+ differs = _acl_differs(aclp, tmpacl);
+ acl_free(tmpacl);
+
+ if (differs)
+ *trivialp = 0;
+ else
+ *trivialp = 1;
+
+ return (0);
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
diff --git a/lib/libc/posix1e/acl_strip_np.3 b/lib/libc/posix1e/acl_strip_np.3
new file mode 100644
index 0000000..7b3537d
--- /dev/null
+++ b/lib/libc/posix1e/acl_strip_np.3
@@ -0,0 +1,109 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" 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$
+.\"
+.Dd June 25, 2009
+.Dt ACL_STRIP_NP 3
+.Os
+.Sh NAME
+.Nm acl_strip_np
+.Nd strip exteneded entries from an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_strip_np "const acl_t acl" "int recalculate_mask"
+.Sh DESCRIPTION
+The
+.Fn acl_strip_np
+function returns a pointer to a trivial ACL computed from the ACL pointed
+to by the argument
+.Va acl .
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)acl_t
+as an argument.
+.Pp
+Any existing ACL pointers that refer to the ACL referred to by
+.Va acl
+shall continue to refer to the ACL.
+.Sh RETURN VALUES
+Upon successful completion, this function shall return a pointer to the
+newly allocated ACL.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_init
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.It Bq Er ENOMEM
+The
+.Va acl_t
+to be returned requires more memory than is allowed by the hardware or
+system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_is_trivial_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_strip_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_support.c b/lib/libc/posix1e/acl_support.c
index 7c1e878..680debc 100644
--- a/lib/libc/posix1e/acl_support.c
+++ b/lib/libc/posix1e/acl_support.c
@@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
#include "acl_support.h"
@@ -49,6 +51,37 @@ __FBSDID("$FreeBSD$");
#define ACL_STRING_PERM_NONE '-'
/*
+ * Return 0, if both ACLs are identical.
+ */
+int
+_acl_differs(const acl_t a, const acl_t b)
+{
+ int i;
+ struct acl_entry *entrya, *entryb;
+
+ assert(_acl_brand(a) == _acl_brand(b));
+ assert(_acl_brand(a) != ACL_BRAND_UNKNOWN);
+ assert(_acl_brand(b) != ACL_BRAND_UNKNOWN);
+
+ if (a->ats_acl.acl_cnt != b->ats_acl.acl_cnt)
+ return (1);
+
+ for (i = 0; i < b->ats_acl.acl_cnt; i++) {
+ entrya = &(a->ats_acl.acl_entry[i]);
+ entryb = &(b->ats_acl.acl_entry[i]);
+
+ if (entrya->ae_tag != entryb->ae_tag ||
+ entrya->ae_id != entryb->ae_id ||
+ entrya->ae_perm != entryb->ae_perm ||
+ entrya->ae_entry_type != entryb->ae_entry_type ||
+ entrya->ae_flags != entryb->ae_flags)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
* _posix1e_acl_entry_compare -- compare two acl_entry structures to
* determine the order they should appear in. Used by _posix1e_acl_sort to
* sort ACL entries into the kernel-desired order -- i.e., the order useful
@@ -59,6 +92,10 @@ typedef int (*compare)(const void *, const void *);
static int
_posix1e_acl_entry_compare(struct acl_entry *a, struct acl_entry *b)
{
+
+ assert(_entry_brand(a) == ACL_BRAND_POSIX);
+ assert(_entry_brand(b) == ACL_BRAND_POSIX);
+
/*
* First, sort between tags -- conveniently defined in the correct
* order for verification.
@@ -116,6 +153,9 @@ int
_posix1e_acl(acl_t acl, acl_type_t type)
{
+ if (_acl_brand(acl) != ACL_BRAND_POSIX)
+ return (0);
+
return ((type == ACL_TYPE_ACCESS) || (type == ACL_TYPE_DEFAULT));
}
@@ -124,7 +164,7 @@ _posix1e_acl(acl_t acl, acl_type_t type)
* from code in sys/kern/kern_acl.c, and if changes are made in one, they
* should be made in the other also. This copy of acl_check is made
* available * in userland for the benefit of processes wanting to check ACLs
- * for validity before submitting them to the kernel, or for performing
+ * for validity before submitting them to the kernel, or for performing
* in userland file system checking. Needless to say, the kernel makes
* the real checks on calls to get/setacl.
*
@@ -163,7 +203,7 @@ _posix1e_acl_check(acl_t acl)
stage = ACL_USER;
count_user_obj++;
break;
-
+
case ACL_USER:
/* printf("_posix1e_acl_check: %d: ACL_USER\n", i); */
if (stage > ACL_USER)
@@ -173,8 +213,8 @@ _posix1e_acl_check(acl_t acl)
return (EINVAL);
highest_uid = entry->ae_id;
count_user++;
- break;
-
+ break;
+
case ACL_GROUP_OBJ:
/* printf("_posix1e_acl_check: %d: ACL_GROUP_OBJ\n",
i); */
@@ -183,7 +223,7 @@ _posix1e_acl_check(acl_t acl)
stage = ACL_GROUP;
count_group_obj++;
break;
-
+
case ACL_GROUP:
/* printf("_posix1e_acl_check: %d: ACL_GROUP\n", i); */
if (stage > ACL_GROUP)
@@ -194,7 +234,7 @@ _posix1e_acl_check(acl_t acl)
highest_gid = entry->ae_id;
count_group++;
break;
-
+
case ACL_MASK:
/* printf("_posix1e_acl_check: %d: ACL_MASK\n", i); */
if (stage > ACL_MASK)
@@ -202,7 +242,7 @@ _posix1e_acl_check(acl_t acl)
stage = ACL_MASK;
count_mask++;
break;
-
+
case ACL_OTHER:
/* printf("_posix1e_acl_check: %d: ACL_OTHER\n", i); */
if (stage > ACL_OTHER)
@@ -210,7 +250,7 @@ _posix1e_acl_check(acl_t acl)
stage = ACL_OTHER;
count_other++;
break;
-
+
default:
/* printf("_posix1e_acl_check: %d: INVALID\n", i); */
return (EINVAL);
@@ -220,7 +260,7 @@ _posix1e_acl_check(acl_t acl)
if (count_user_obj != 1)
return (EINVAL);
-
+
if (count_group_obj != 1)
return (EINVAL);
@@ -243,7 +283,8 @@ _posix1e_acl_check(acl_t acl)
* MAY HAVE SIDE-EFFECTS
*/
int
-_posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf)
+_posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf,
+ int flags)
{
struct group *g;
struct passwd *p;
@@ -251,7 +292,10 @@ _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf)
switch(tag) {
case ACL_USER:
- p = getpwuid(id);
+ if (flags & ACL_TEXT_NUMERIC_IDS)
+ p = NULL;
+ else
+ p = getpwuid(id);
if (!p)
i = snprintf(buf, buf_len, "%d", id);
else
@@ -264,8 +308,11 @@ _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf)
return (0);
case ACL_GROUP:
- g = getgrgid(id);
- if (g == NULL)
+ if (flags & ACL_TEXT_NUMERIC_IDS)
+ g = NULL;
+ else
+ g = getgrgid(id);
+ if (g == NULL)
i = snprintf(buf, buf_len, "%d", id);
else
i = snprintf(buf, buf_len, "%s", g->gr_name);
@@ -376,3 +423,55 @@ _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm)
return (0);
}
+
+/*
+ * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
+ * counterpart. It's neccessary for the old (pre-NFSv4 ACLs) binaries
+ * to work with new libc and kernel. Fixing 'type' for old binaries with
+ * old libc and new kernel is being done by kern/vfs_acl.c:type_unold().
+ */
+int
+_acl_type_unold(acl_type_t type)
+{
+
+ switch (type) {
+ case ACL_TYPE_ACCESS_OLD:
+ return (ACL_TYPE_ACCESS);
+ case ACL_TYPE_DEFAULT_OLD:
+ return (ACL_TYPE_DEFAULT);
+ default:
+ return (type);
+ }
+}
+
+char *
+string_skip_whitespace(char *string)
+{
+
+ while (*string && ((*string == ' ') || (*string == '\t')))
+ string++;
+
+ return (string);
+}
+
+void
+string_trim_trailing_whitespace(char *string)
+{
+ char *end;
+
+ if (*string == '\0')
+ return;
+
+ end = string + strlen(string) - 1;
+
+ while (end != string) {
+ if ((*end == ' ') || (*end == '\t')) {
+ *end = '\0';
+ end--;
+ } else {
+ return;
+ }
+ }
+
+ return;
+}
diff --git a/lib/libc/posix1e/acl_support.h b/lib/libc/posix1e/acl_support.h
index a5c93c0..9826577 100644
--- a/lib/libc/posix1e/acl_support.h
+++ b/lib/libc/posix1e/acl_support.h
@@ -33,16 +33,33 @@
#define _ACL_SUPPORT_H
#define _POSIX1E_ACL_STRING_PERM_MAXSIZE 3 /* read, write, exec */
+#define _ACL_T_ALIGNMENT_BITS 13
+int _acl_type_unold(acl_type_t type);
+int _acl_differs(const acl_t a, const acl_t b);
+int _acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type);
+void _acl_brand_from_type(acl_t acl, acl_type_t type);
+int _acl_brand(const acl_t acl);
+int _entry_brand(const acl_entry_t entry);
+int _acl_brand_may_be(const acl_t acl, int brand);
+int _entry_brand_may_be(const acl_entry_t entry, int brand);
+void _acl_brand_as(acl_t acl, int brand);
+void _entry_brand_as(const acl_entry_t entry, int brand);
+int _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose);
+int _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose);
+int _nfs4_parse_flags(const char *str, acl_flag_t *var);
+int _nfs4_parse_access_mask(const char *str, acl_perm_t *var);
int _posix1e_acl_check(acl_t acl);
int _posix1e_acl_sort(acl_t acl);
int _posix1e_acl(acl_t acl, acl_type_t type);
int _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len,
- char *buf);
+ char *buf, int flags);
int _posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len,
char *buf);
int _posix1e_acl_string_to_perm(char *string, acl_perm_t *perm);
int _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id,
acl_perm_t perm);
+char *string_skip_whitespace(char *string);
+void string_trim_trailing_whitespace(char *string);
#endif
diff --git a/lib/libc/posix1e/acl_support_nfs4.c b/lib/libc/posix1e/acl_support_nfs4.c
new file mode 100644
index 0000000..c5be3d1
--- /dev/null
+++ b/lib/libc/posix1e/acl_support_nfs4.c
@@ -0,0 +1,256 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@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$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <err.h>
+#include <sys/acl.h>
+#include "acl_support.h"
+
+struct flagnames_struct {
+ uint32_t flag;
+ const char *name;
+ char letter;
+};
+
+struct flagnames_struct a_flags[] =
+ {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'},
+ { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'},
+ { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'},
+ { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'},
+ { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'},
+ { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'},
+ /*
+ * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it
+ * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or
+ * ACE_EVERYONE either, for obvious reasons.
+ */
+ { 0, 0, 0}};
+
+struct flagnames_struct a_access_masks[] =
+ {{ ACL_READ_DATA, "read_data", 'r'},
+ { ACL_WRITE_DATA, "write_data", 'w'},
+ { ACL_EXECUTE, "execute", 'x'},
+ { ACL_APPEND_DATA, "append_data", 'p'},
+ { ACL_DELETE_CHILD, "delete_child", 'D'},
+ { ACL_DELETE, "delete", 'd'},
+ { ACL_READ_ATTRIBUTES, "read_attributes", 'a'},
+ { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'},
+ { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'},
+ { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'},
+ { ACL_READ_ACL, "read_acl", 'c'},
+ { ACL_WRITE_ACL, "write_acl", 'C'},
+ { ACL_WRITE_OWNER, "write_owner", 'o'},
+ { ACL_SYNCHRONIZE, "synchronize", 's'},
+ { 0, 0, 0}};
+
+static const char *
+format_flag(uint32_t *var, const struct flagnames_struct *flags)
+{
+
+ for (; flags->name != 0; flags++) {
+ if ((flags->flag & *var) == 0)
+ continue;
+
+ *var &= ~flags->flag;
+ return (flags->name);
+ }
+
+ return (NULL);
+}
+
+static int
+format_flags_verbose(char *str, size_t size, uint32_t var,
+ const struct flagnames_struct *flags)
+{
+ size_t off = 0;
+ const char *tmp;
+
+ while ((tmp = format_flag(&var, flags)) != NULL) {
+ off += snprintf(str + off, size - off, "%s/", tmp);
+ assert (off < size);
+ }
+
+ /* If there were any flags added... */
+ if (off > 0) {
+ off--;
+ /* ... then remove the last slash. */
+ assert(str[off] == '/');
+ }
+
+ str[off] = '\0';
+
+ return (0);
+}
+
+static int
+format_flags_compact(char *str, size_t size, uint32_t var,
+ const struct flagnames_struct *flags)
+{
+ size_t i;
+
+ for (i = 0; flags[i].name != NULL; i++) {
+ assert(i < size);
+ if ((flags[i].flag & var) == 0)
+ str[i] = '-';
+ else
+ str[i] = flags[i].letter;
+ }
+
+ str[i] = '\0';
+
+ return (0);
+}
+
+static int
+parse_flags_verbose(const char *strp, uint32_t *var,
+ const struct flagnames_struct *flags, const char *flags_name,
+ int *try_compact)
+{
+ int i, found, ever_found = 0;
+ char *str, *flag;
+
+ str = strdup(strp);
+ *try_compact = 0;
+ *var = 0;
+
+ while (str != NULL) {
+ flag = strsep(&str, "/:");
+
+ found = 0;
+ for (i = 0; flags[i].name != NULL; i++) {
+ if (strcmp(flags[i].name, flag) == 0) {
+ *var |= flags[i].flag;
+ found = 1;
+ ever_found = 1;
+ }
+ }
+
+ if (!found) {
+ if (ever_found)
+ warnx("malformed ACL: \"%s\" field contains "
+ "invalid flag \"%s\"", flags_name, flag);
+ else
+ *try_compact = 1;
+ free(str);
+ return (-1);
+ }
+ }
+
+ free(str);
+ return (0);
+}
+
+static int
+parse_flags_compact(const char *str, uint32_t *var,
+ const struct flagnames_struct *flags, const char *flags_name)
+{
+ int i, j, found;
+
+ *var = 0;
+
+ for (i = 0;; i++) {
+ if (str[i] == '\0')
+ return (0);
+
+ /* Ignore minus signs. */
+ if (str[i] == '-')
+ continue;
+
+ found = 0;
+
+ for (j = 0; flags[j].name != NULL; j++) {
+ if (flags[j].letter == str[i]) {
+ *var |= flags[j].flag;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ warnx("malformed ACL: \"%s\" field contains "
+ "invalid flag \"%c\"", flags_name, str[i]);
+ return (-1);
+ }
+ }
+}
+
+int
+_nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose)
+{
+
+ if (verbose)
+ return (format_flags_verbose(str, size, var, a_flags));
+
+ return (format_flags_compact(str, size, var, a_flags));
+}
+
+int
+_nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose)
+{
+
+ if (verbose)
+ return (format_flags_verbose(str, size, var, a_access_masks));
+
+ return (format_flags_compact(str, size, var, a_access_masks));
+}
+
+int
+_nfs4_parse_flags(const char *str, acl_flag_t *flags)
+{
+ int error, try_compact;
+ int tmpflags;
+
+ error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact);
+ if (error && try_compact)
+ error = parse_flags_compact(str, &tmpflags, a_flags, "flags");
+
+ *flags = tmpflags;
+
+ return (error);
+}
+
+int
+_nfs4_parse_access_mask(const char *str, acl_perm_t *perms)
+{
+ int error, try_compact;
+ int tmpperms;
+
+ error = parse_flags_verbose(str, &tmpperms, a_access_masks,
+ "access permissions", &try_compact);
+ if (error && try_compact)
+ error = parse_flags_compact(str, &tmpperms,
+ a_access_masks, "access permissions");
+
+ *perms = tmpperms;
+
+ return (error);
+}
diff --git a/lib/libc/posix1e/acl_to_text.3 b/lib/libc/posix1e/acl_to_text.3
index 833a6d2..46ae421 100644
--- a/lib/libc/posix1e/acl_to_text.3
+++ b/lib/libc/posix1e/acl_to_text.3
@@ -27,11 +27,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 28, 2000
+.Dd June 25, 2009
.Dt ACL_TO_TEXT 3
.Os
.Sh NAME
-.Nm acl_to_text
+.Nm acl_to_text ,
+.Nm acl_to_text_np
.Nd convert an ACL to text
.Sh LIBRARY
.Lb libc
@@ -40,10 +41,14 @@
.In sys/acl.h
.Ft char *
.Fn acl_to_text "acl_t acl" "ssize_t *len_p"
+.Ft char *
+.Fn acl_to_text_np "acl_t acl" "ssize_t *len_p" "int flags"
.Sh DESCRIPTION
The
.Fn acl_to_text
-function translates the ACL pointed to by argument
+and
+.Fn acl_to_text_np
+functions translate the ACL pointed to by argument
.Va acl
into a NULL terminated character string.
If the pointer
@@ -51,9 +56,22 @@ If the pointer
is not NULL, then the function shall return the length of the string (not
including the NULL terminator) in the location pointed to by
.Va len_p .
-The format of the text string returned by
+If the ACL is POSIX.1e, the format of the text string returned by
.Fn acl_to_text
-shall be the POSIX.1e long ACL form.
+shall be the POSIX.1e long ACL form. If the ACL is NFSv4, the format
+of the text string shall be the compact form, unless the
+.Va ACL_TEXT_VERBOSE
+flag is given.
+.Pp
+The flags specified are formed by
+.Em or Ns 'ing
+the following values
+.Pp
+.Bl -column -offset 3n "ACL_TEXT_NUMERIC_IDS"
+.It ACL_TEXT_VERBOSE Format ACL using verbose form
+.It ACL_TEXT_NUMERIC_IDS Do not resolve IDs into user or group names
+.It ACL_TEXT_APPEND_ID In addition to user and group names, append numeric IDs
+.El
.Pp
This function allocates any memory necessary to contain the string and
returns a pointer to the string.
diff --git a/lib/libc/posix1e/acl_to_text.c b/lib/libc/posix1e/acl_to_text.c
index f2905c3..79a950a 100644
--- a/lib/libc/posix1e/acl_to_text.c
+++ b/lib/libc/posix1e/acl_to_text.c
@@ -50,8 +50,11 @@ __FBSDID("$FreeBSD$");
* This function will not produce nice results if it is called with
* a non-POSIX.1e semantics ACL.
*/
-char *
-acl_to_text(acl_t acl, ssize_t *len_p)
+
+char *_nfs4_acl_to_text_np(const acl_t acl, ssize_t *len_p, int flags);
+
+static char *
+_posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags)
{
struct acl *acl_int;
char *buf, *tmpbuf;
@@ -67,11 +70,6 @@ acl_to_text(acl_t acl, ssize_t *len_p)
if (buf == NULL)
return(NULL);
- if (acl == NULL) {
- errno = EINVAL;
- return(NULL);
- }
-
acl_int = &acl->ats_acl;
mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */
@@ -105,7 +103,7 @@ acl_to_text(acl_t acl, ssize_t *len_p)
goto error_label;
error = _posix1e_acl_id_to_name(ae_tag, ae_id,
- UT_NAMESIZE+1, name_buf);
+ UT_NAMESIZE+1, name_buf, flags);
if (error)
goto error_label;
@@ -165,7 +163,7 @@ acl_to_text(acl_t acl, ssize_t *len_p)
goto error_label;
error = _posix1e_acl_id_to_name(ae_tag, ae_id,
- UT_NAMESIZE+1, name_buf);
+ UT_NAMESIZE+1, name_buf, flags);
if (error)
goto error_label;
@@ -235,3 +233,30 @@ error_label:
if (buf) free(buf);
return (NULL);
}
+
+char *
+acl_to_text_np(acl_t acl, ssize_t *len_p, int flags)
+{
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return(NULL);
+ }
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_POSIX:
+ return (_posix1e_acl_to_text(acl, len_p, flags));
+ case ACL_BRAND_NFS4:
+ return (_nfs4_acl_to_text_np(acl, len_p, flags));
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+}
+
+char *
+acl_to_text(acl_t acl, ssize_t *len_p)
+{
+
+ return (acl_to_text_np(acl, len_p, 0));
+}
diff --git a/lib/libc/posix1e/acl_to_text_nfs4.c b/lib/libc/posix1e/acl_to_text_nfs4.c
new file mode 100644
index 0000000..3adbfb4
--- /dev/null
+++ b/lib/libc/posix1e/acl_to_text_nfs4.c
@@ -0,0 +1,266 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@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$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+#define MAX_ENTRY_LENGTH 512
+
+static int
+format_who(char *str, size_t size, const acl_entry_t entry, int numeric)
+{
+ int error;
+ acl_tag_t tag;
+ struct passwd *pwd;
+ struct group *grp;
+ id_t *id;
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ switch (tag) {
+ case ACL_USER_OBJ:
+ snprintf(str, size, "owner@");
+ break;
+
+ case ACL_USER:
+ id = (id_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ /* XXX: Thread-unsafe. */
+ if (!numeric)
+ pwd = getpwuid(*id);
+ else
+ pwd = NULL;
+ if (pwd == NULL)
+ snprintf(str, size, "user:%d", (unsigned int)*id);
+ else
+ snprintf(str, size, "user:%s", pwd->pw_name);
+ break;
+
+ case ACL_GROUP_OBJ:
+ snprintf(str, size, "group@");
+ break;
+
+ case ACL_GROUP:
+ id = (id_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ /* XXX: Thread-unsafe. */
+ if (!numeric)
+ grp = getgrgid(*id);
+ else
+ grp = NULL;
+ if (grp == NULL)
+ snprintf(str, size, "group:%d", (unsigned int)*id);
+ else
+ snprintf(str, size, "group:%s", grp->gr_name);
+ break;
+
+ case ACL_EVERYONE:
+ snprintf(str, size, "everyone@");
+ break;
+
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+format_entry_type(char *str, size_t size, const acl_entry_t entry)
+{
+ int error;
+ acl_entry_type_t entry_type;
+
+ error = acl_get_entry_type_np(entry, &entry_type);
+ if (error)
+ return (error);
+
+ switch (entry_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ snprintf(str, size, "allow");
+ break;
+ case ACL_ENTRY_TYPE_DENY:
+ snprintf(str, size, "deny");
+ break;
+ case ACL_ENTRY_TYPE_AUDIT:
+ snprintf(str, size, "audit");
+ break;
+ case ACL_ENTRY_TYPE_ALARM:
+ snprintf(str, size, "alarm");
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+format_additional_id(char *str, size_t size, const acl_entry_t entry)
+{
+ int error;
+ acl_tag_t tag;
+ id_t *id;
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ switch (tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_EVERYONE:
+ str[0] = '\0';
+ break;
+
+ default:
+ id = (id_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ snprintf(str, size, ":%d", (unsigned int)*id);
+ }
+
+ return (0);
+}
+
+static int
+format_entry(char *str, size_t size, const acl_entry_t entry, int flags)
+{
+ size_t off = 0, padding_length, maximum_who_field_length = 18;
+ acl_permset_t permset;
+ acl_flagset_t flagset;
+ int error, len;
+ char buf[MAX_ENTRY_LENGTH + 1];
+
+ assert(_entry_brand(entry) == ACL_BRAND_NFS4);
+
+ error = acl_get_flagset_np(entry, &flagset);
+ if (error)
+ return (error);
+
+ error = acl_get_permset(entry, &permset);
+ if (error)
+ return (error);
+
+ error = format_who(buf, sizeof(buf), entry,
+ flags & ACL_TEXT_NUMERIC_IDS);
+ if (error)
+ return (error);
+ len = strlen(buf);
+ padding_length = maximum_who_field_length - len;
+ if (padding_length > 0) {
+ memset(str, ' ', padding_length);
+ off += padding_length;
+ }
+ off += snprintf(str + off, size - off, "%s:", buf);
+
+ error = _nfs4_format_access_mask(buf, sizeof(buf), *permset,
+ flags & ACL_TEXT_VERBOSE);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s:", buf);
+
+ error = _nfs4_format_flags(buf, sizeof(buf), *flagset,
+ flags & ACL_TEXT_VERBOSE);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s:", buf);
+
+ error = format_entry_type(buf, sizeof(buf), entry);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s", buf);
+
+ if (flags & ACL_TEXT_APPEND_ID) {
+ error = format_additional_id(buf, sizeof(buf), entry);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s", buf);
+ }
+
+ off += snprintf(str + off, size - off, "\n");
+
+ /* Make sure we didn't truncate anything. */
+ assert (off < size);
+
+ return (0);
+}
+
+char *
+_nfs4_acl_to_text_np(const acl_t aclp, ssize_t *len_p, int flags)
+{
+ int error, off = 0, size, entry_id = ACL_FIRST_ENTRY;
+ char *str;
+ acl_entry_t entry;
+
+ if (aclp->ats_acl.acl_cnt == 0)
+ return strdup("");
+
+ size = aclp->ats_acl.acl_cnt * MAX_ENTRY_LENGTH;
+ str = malloc(size);
+ if (str == NULL)
+ return (NULL);
+
+ while (acl_get_entry(aclp, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ assert(off < size);
+
+ error = format_entry(str + off, size - off, entry, flags);
+ if (error) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ off = strlen(str);
+ }
+
+ assert(off < size);
+ str[off] = '\0';
+
+ if (len_p != NULL)
+ *len_p = off;
+
+ return (str);
+}
diff --git a/lib/libc/posix1e/acl_valid.c b/lib/libc/posix1e/acl_valid.c
index 9b1f9b9..f345c01 100644
--- a/lib/libc/posix1e/acl_valid.c
+++ b/lib/libc/posix1e/acl_valid.c
@@ -62,6 +62,10 @@ acl_valid(acl_t acl)
errno = EINVAL;
return (-1);
}
+ if (!_acl_brand_may_be(acl, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
_posix1e_acl_sort(acl);
error = _posix1e_acl_check(acl);
if (error) {
@@ -81,6 +85,7 @@ acl_valid_file_np(const char *pathp, acl_type_t type, acl_t acl)
errno = EINVAL;
return (-1);
}
+ type = _acl_type_unold(type);
if (_posix1e_acl(acl, type)) {
error = _posix1e_acl_sort(acl);
if (error) {
@@ -101,6 +106,7 @@ acl_valid_link_np(const char *pathp, acl_type_t type, acl_t acl)
errno = EINVAL;
return (-1);
}
+ type = _acl_type_unold(type);
if (_posix1e_acl(acl, type)) {
error = _posix1e_acl_sort(acl);
if (error) {
@@ -121,6 +127,7 @@ acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
errno = EINVAL;
return (-1);
}
+ type = _acl_type_unold(type);
if (_posix1e_acl(acl, type)) {
error = _posix1e_acl_sort(acl);
if (error) {
@@ -131,6 +138,5 @@ acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
acl->ats_cur_entry = 0;
-
return (___acl_aclcheck_fd(fd, type, &acl->ats_acl));
}
diff --git a/lib/libc/posix1e/mac.3 b/lib/libc/posix1e/mac.3
index ac6affd..c570998 100644
--- a/lib/libc/posix1e/mac.3
+++ b/lib/libc/posix1e/mac.3
@@ -1,4 +1,5 @@
.\" Copyright (c) 2001, 2003 Networks Associates Technology, Inc.
+.\" Copyright (c) 2009 Robert N. M. Watson
.\" All rights reserved.
.\"
.\" This software was developed for the FreeBSD Project by Chris
@@ -30,7 +31,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 19, 2003
+.Dd August 7, 2009
.Dt MAC 3
.Os
.Sh NAME
@@ -44,81 +45,82 @@
In the kernel configuration file:
.Cd "options MAC"
.Sh DESCRIPTION
-.Fx
-permits administrators to define Mandatory Access Control labels
-defining levels for the privacy and integrity of data,
-overriding discretionary policies
-for those objects.
-Not all objects currently provide support for MAC labels,
-and MAC support must be explicitly enabled by the administrator.
-The library calls include routines to retrieve, duplicate,
-and set MAC labels associated with files and processes.
+Mandatory Access Control labels describe confidentiality, integrity, and
+other security attributes of operating system objects, overriding
+discretionary access control.
+Not all system objects support MAC labeling, and MAC policies must be
+explicitly enabled by the administrator.
+This API, based on POSIX.1e, includes routines to retrieve, manipulate, set,
+and convert to and from text the MAC labels on files and processes.
.Pp
-POSIX.1e describes a set of MAC manipulation routines
-to manage the contents of MAC labels,
-as well as their relationships with
-files and processes;
-almost all of these support routines
-are implemented in
-.Fx .
+MAC labels consist of a set of (name, value) tuples, representing security
+attributes from MAC policies.
+For example, this label contains security labels defined by two policies,
+.Xr mac_biba 4
+and
+.Xr mac_mls 4 :
+.Bd -literal -offset indent
+biba/low,mls/low
+.Ed
+.Pp
+Further syntax and semantics of MAC labels may be found in
+.Xr maclabel 7 .
.Pp
-Available functions, sorted by behavior, include:
+Applications operate on labels stored in
+.Vt mac_t ,
+but can convert between this internal format and a text format for the
+purposes of presentation to uses or external storage.
+When querying a label on an object, a
+.Vt mac_t
+must first be prepared using the interfaces described in
+.Xr mac_prepare 3 ,
+allowing the application to declare which policies it wishes to interogate.
+The application writer can also rely on default label names declared in
+.Xr mac.conf 5 .
+.Pp
+When finished with a
+.Vt mac_t ,
+the application must call
+.Xr mac_free 3
+to release its storage.
+.Pp
+The following functions are defined:
.Bl -tag -width indent
-.It Fn mac_get_fd
-This function is described in
-.Xr mac_get 3 ,
-and may be used to retrieve the
-MAC label associated with
-a specific file descriptor.
-.It Fn mac_get_file
-This function is described in
+.It Fn mac_is_present
+This function, described in
+.Xr mac_is_present 3 ,
+allows applications to test whether MAC is configured, as well as whether
+specific policies are configured.
+.It Fn mac_get_fd , Fn mac_get_file , Fn mac_get_link , Fn mac_get_peer
+These functions, described in
.Xr mac_get 3 ,
-and may be used to retrieve the
-MAC label associated with
-a named file.
-.It Fn mac_get_proc
-This function is described in
+retrieve the MAC labels associated with file descriptors, files, and socket
+peers.
+.It Fn mac_get_pid , Fn mac_get_proc
+These functions, described in
.Xr mac_get 3 ,
-and may be used to retrieve the
-MAC label associated with
-the calling process.
-.It Fn mac_set_fd
-This function is described in
-.Xr mac_set 3 ,
-and may be used to set the
-MAC label associated with
-a specific file descriptor.
-.It Fn mac_set_file
-This function is described in
+retrieve the MAC labels associated with processes.
+.It Fn mac_set_fd , Fn mac_set_file , Fn mac_set_link
+These functions, described in
.Xr mac_set 3 ,
-and may be used to set the
-MAC label associated with
-a named file.
+set the MAC labels associated with file descriptors and files.
.It Fn mac_set_proc
-This function is described in
+This function, described in
.Xr mac_set 3 ,
-and may be used to set the
-MAC label associated with
-the calling process.
+sets the MAC label associated with the current process.
.It Fn mac_free
-This function is described in
+This function, desribed in
.Xr mac_free 3 ,
-and may be used to free
-userland working MAC label storage.
+frees working MAC label storage.
.It Fn mac_from_text
-This function is described in
+This function, described in
.Xr mac_text 3 ,
-and may be used to convert
-a text-form MAC label
-into a working
+converts a text-form MAC label into working MAC label storage,
.Vt mac_t .
-.It Fn mac_prepare
-.It Fn mac_prepare_file_label
-.It Fn mac_prepare_ifnet_label
-.It Fn mac_prepare_process_label
-These functions are described in
+.It Fn mac_prepare , Fn mac_prepare_file_label , Fn mac_prepare_ifnet_label , Fn mac_prepare_process_label , Fn mac_prepare_type
+These functions, described in
.Xr mac_prepare 3 ,
-and may be used to preallocate storage for MAC label retrieval.
+allocate working storage for MAC label operations.
.Xr mac_prepare 3
prepares a label based on caller-specified label names; the other calls
rely on the default configuration specified in
@@ -130,15 +132,6 @@ and may be used to convert a
.Vt mac_t
into a text-form MAC label.
.El
-The behavior of some of these calls is influenced by the configuration
-settings found in
-.Xr mac.conf 5 ,
-the MAC library run-time configuration file.
-.Sh IMPLEMENTATION NOTES
-.Fx Ns 's
-support for POSIX.1e interfaces and features
-is
-.Ud .
.Sh FILES
.Bl -tag -width ".Pa /etc/mac.conf" -compact
.It Pa /etc/mac.conf
@@ -150,24 +143,20 @@ system objects, but without policy-specific knowledge.
.Sh SEE ALSO
.Xr mac_free 3 ,
.Xr mac_get 3 ,
+.Xr mac_is_present 3 ,
.Xr mac_prepare 3 ,
.Xr mac_set 3 ,
.Xr mac_text 3 ,
+.Xr posix1e 3 ,
.Xr mac 4 ,
.Xr mac.conf 5 ,
.Xr mac 9
.Sh STANDARDS
-These APIs are loosely based on the APIs described in POSIX.1e.
-POSIX.1e is described in IEEE POSIX.1e draft 17.
-Discussion of the draft
-continues on the cross-platform POSIX.1e implementation mailing list.
-To join this list, see the
-.Fx
-POSIX.1e implementation page
-for more information.
-However, the resemblance of these APIs to the POSIX APIs is only loose,
-as the POSIX APIs were unable to express many notions required for
-flexible and extensible access control.
+These APIs are loosely based on the APIs described in POSIX.1e, as described
+in IEEE POSIX.1e draft 17.
+However, the resemblence of these APIS to the POSIX APIs is loose, as the
+PSOXI APIS were unable to express some notinos required for flexible and
+extensible access control.
.Sh HISTORY
Support for Mandatory Access Control was introduced in
.Fx 5.0
diff --git a/lib/libc/posix1e/mac_free.3 b/lib/libc/posix1e/mac_free.3
index 33ef9ec..78118a1 100644
--- a/lib/libc/posix1e/mac_free.3
+++ b/lib/libc/posix1e/mac_free.3
@@ -64,6 +64,7 @@ function.
.Xr mac_prepare 3 ,
.Xr mac_set 3 ,
.Xr mac_text 3 ,
+.Xr posix1e 3 ,
.Xr mac 4 ,
.Xr mac 9
.Sh STANDARDS
@@ -91,8 +92,8 @@ is a complex structure in the
.Tn TrustedBSD
implementation,
.Fn mac_free
-is specific to that type, and must not be used to free the character
-strings returned from
+is specific to
+.Vt mac_3 ,
+and must not be used to free the character strings returned from
.Fn mac_to_text .
-Doing so may result in undefined behavior,
-including application failure.
+Doing so may result in undefined behavior.
diff --git a/lib/libc/posix1e/mac_get.3 b/lib/libc/posix1e/mac_get.3
index cd498d0..35fa72b 100644
--- a/lib/libc/posix1e/mac_get.3
+++ b/lib/libc/posix1e/mac_get.3
@@ -133,6 +133,7 @@ is not a directory.
.Xr mac_prepare 3 ,
.Xr mac_set 3 ,
.Xr mac_text 3 ,
+.Xr posix1e 3 ,
.Xr mac 4 ,
.Xr mac 9
.Sh STANDARDS
diff --git a/lib/libc/posix1e/mac_set.3 b/lib/libc/posix1e/mac_set.3
index 84a1800..0b245a0 100644
--- a/lib/libc/posix1e/mac_set.3
+++ b/lib/libc/posix1e/mac_set.3
@@ -138,6 +138,7 @@ is not a directory.
.Xr mac_is_present 3 ,
.Xr mac_prepare 3 ,
.Xr mac_text 3 ,
+.Xr posix1e 3 ,
.Xr mac 4 ,
.Xr mac 9
.Sh HISTORY
diff --git a/lib/libc/posix1e/mac_text.3 b/lib/libc/posix1e/mac_text.3
index 66c1e21..dde6ccf 100644
--- a/lib/libc/posix1e/mac_text.3
+++ b/lib/libc/posix1e/mac_text.3
@@ -98,6 +98,7 @@ to allocate internal storage.
.Xr mac_is_present 3 ,
.Xr mac_prepare 3 ,
.Xr mac_set 3 ,
+.Xr posix1e 3 ,
.Xr mac 4 ,
.Xr maclabel 7
.Sh STANDARDS
diff --git a/lib/libc/posix1e/posix1e.3 b/lib/libc/posix1e/posix1e.3
index 6333b08..84ce2ec 100644
--- a/lib/libc/posix1e/posix1e.3
+++ b/lib/libc/posix1e/posix1e.3
@@ -1,5 +1,5 @@
.\"-
-.\" Copyright (c) 2000 Robert N. M. Watson
+.\" Copyright (c) 2000, 2009 Robert N. M. Watson
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 17, 2000
+.Dd August 7, 2009
.Dt POSIX1E 3
.Os
.Sh NAME
@@ -36,99 +36,77 @@
.Sh SYNOPSIS
.In sys/types.h
.In sys/acl.h
-.\" .In sys/audit.h
-.\" .In sys/capability.h
.In sys/mac.h
.Sh DESCRIPTION
-The IEEE POSIX.1e specification never left draft form, but the interfaces
-it describes are now widely used despite inherent limitations.
-Currently, only a few of the interfaces and features are implemented in
-.Fx ,
-although efforts are underway to complete the integration at this time.
+POSIX.1e describes five security extensions to the POSIX.1 API: Access
+Control Lists (ACLs), Auditing, Capabilities, Mandatory Access Control, and
+Information Flow Labels.
+While IEEE POSIX.1e D17 specification has not been standardized, several of
+its interfaces are widely used.
.Pp
-POSIX.1e describes five security extensions to the base POSIX.1 API:
-Access Control Lists (ACLs), Auditing, Capabilities, Mandatory Access
-Control, and Information Flow Labels.
.Fx
-supports POSIX.1e ACL interfaces, as well as POSIX.1e-like MAC
-interfaces.
-The TrustedBSD Project has produced but not integrated an implementation
-of POSIX.1e Capabilities.
-.Pp
-POSIX.1e defines both syntax and semantics for these features, but fairly
-substantial changes are required to implement these features in the
-operating system.
-.Pp
-As shipped,
-.Fx 4.0
-provides API and VFS support for ACLs, but not an implementation on any
-native file system.
-.Fx 5.0
-includes support for ACLs as part of UFS1 and UFS2, as well as necessary
-VFS support for additional file systems to export ACLs as appropriate.
-Available API calls relating to ACLs are described in detail in
-.Xr acl 3 .
-.Pp
-As shipped,
-.Fx 5.0
-includes support for Mandatory Access Control as well as POSIX.1e-like
-APIs for label management.
-More information on API calls relating to MAC is available in
-.Xr mac 3 .
+implements POSIX.1e interface for access control lists, described in
+.Xr acl 3 ,
+and supports ACLs on the
+.Xr ffs 7
+file system; ACLs must be administratively enabled using
+.Xr tunefs 8 .
.Pp
-Additional patches supporting POSIX.1e features are provided by the
-TrustedBSD project:
+.Fx
+implements a POSIX.1e-like mandatory access control interface, described in
+.Xr mac 3 ,
+although with a number of extensions and important semantic differences.
.Pp
-http://www.TrustedBSD.org/
-.Sh IMPLEMENTATION NOTES
-.Fx Ns 's
-support for POSIX.1e interfaces and features is still under
-development at this time, and many of these features are considered new
-or experimental.
+.Fx
+does not implement the POSIX.1e audit, privilege (capability), or information
+flow label APIs.
+However,
+.Fx
+does implement the
+.Xr libbsm
+audit API.
.Sh ENVIRONMENT
-POSIX.1e assigns security labels to all objects, extending the security
+POSIX.1e assigns security attributes to all objects, extending the security
functionality described in POSIX.1.
-These additional labels provide
-fine-grained discretionary access control, fine-grained capabilities,
-and labels necessary for mandatory access control.
-POSIX.2c describes
-a set of userland utilities for manipulating these labels.
+These additional attributes store fine-grained discretionary access control
+information and mandatory access control labels; for files, they are stored
+in extended attributes, described in
+.Xr extattr 3 .
.Pp
-Many of these services are supported by extended attributes, documented
-in
-.Xr extattr 2
+POSIX.2c describes
+a set of userland utilities for manipulating these attributes, including
+.Xr getfacl 1
+and
+.Xr setfacl 1
+for access control lists, and
+.Xr getfmac 8
and
-.Xr extattr 9 .
-While these APIs are not documented in POSIX.1e, they are similar in
-structure.
+.Xr setfmac 8
+for mandatory access control labels.
.Sh SEE ALSO
+.Xr getfacl 1 ,
+.Xr setfacl 1 ,
.Xr extattr 2 ,
.Xr acl 3 ,
+.Xr extattr 3 ,
+.Xr libbsm 3 ,
.Xr mac 3 ,
+.Xr ffs 7 ,
+.Xr getfmac 8 ,
+.Xr setfmac 8 ,
+.Xr tunefs 8 ,
.Xr acl 9 ,
.Xr extattr 9 ,
.Xr mac 9
.Sh STANDARDS
POSIX.1e is described in IEEE POSIX.1e draft 17.
-Discussion of the draft continues
-on the cross-platform POSIX.1e implementation
-mailing list.
-To join this list, see the
-.Fx
-POSIX.1e implementation
-page for more information.
.Sh HISTORY
POSIX.1e support was introduced in
.Fx 4.0 ;
-most of the features are available as of
+most features were available as of
.Fx 5.0 .
-Development continues.
.Sh AUTHORS
.An Robert N M Watson
.An Chris D. Faulhaber
.An Thomas Moestl
.An Ilmar S Habibulin
-.Sh BUGS
-Many of these features are considered new or experimental in
-.Fx 5.0
-and should be deployed with appropriate caution.
diff --git a/lib/libc/regex/engine.c b/lib/libc/regex/engine.c
index a44511b..2a1a75e 100644
--- a/lib/libc/regex/engine.c
+++ b/lib/libc/regex/engine.c
@@ -247,6 +247,8 @@ matcher(struct re_guts *g,
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);
@@ -787,6 +789,7 @@ fast( struct match *m,
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);
@@ -1072,7 +1075,7 @@ step(struct re_guts *g,
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 */
diff --git a/lib/libc/regex/grot/tests b/lib/libc/regex/grot/tests
index 95a21bb..050e7b2 100644
--- a/lib/libc/regex/grot/tests
+++ b/lib/libc/regex/grot/tests
@@ -472,3 +472,6 @@ abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop
abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv
(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11
CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11
+# PR 130504
+(.|())(b) - ab ab
+(()|.)(b) - ab ab
diff --git a/lib/libc/resolv/res_comp.c b/lib/libc/resolv/res_comp.c
index a00755f..81bce5e 100644
--- a/lib/libc/resolv/res_comp.c
+++ b/lib/libc/resolv/res_comp.c
@@ -148,7 +148,11 @@ dn_skipname(const u_char *ptr, const u_char *eom) {
#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
#define borderchar(c) (alphachar(c) || digitchar(c))
+#ifdef RES_ENFORCE_RFC1034
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#else
#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c))
+#endif
#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
int
diff --git a/lib/libc/rpc/auth_unix.c b/lib/libc/rpc/auth_unix.c
index 5801015..ff3ca7b 100644
--- a/lib/libc/rpc/auth_unix.c
+++ b/lib/libc/rpc/auth_unix.c
@@ -185,23 +185,29 @@ authunix_create(machname, uid, gid, len, aup_gids)
AUTH *
authunix_create_default()
{
- int len;
+ int ngids;
+ long ngids_max;
char machname[MAXHOSTNAMELEN + 1];
uid_t uid;
gid_t gid;
- gid_t gids[NGROUPS_MAX];
+ gid_t *gids;
+
+ ngids_max = sysconf(_SC_NGROUPS_MAX) + 1;
+ gids = malloc(sizeof(gid_t) * ngids_max);
+ if (gids == NULL)
+ return (NULL);
if (gethostname(machname, sizeof machname) == -1)
abort();
machname[sizeof(machname) - 1] = 0;
uid = geteuid();
gid = getegid();
- if ((len = getgroups(NGROUPS_MAX, gids)) < 0)
+ if ((ngids = getgroups(ngids_max, gids)) < 0)
abort();
- if (len > NGRPS)
- len = NGRPS;
+ if (ngids > NGRPS)
+ ngids = NGRPS;
/* XXX: interface problem; those should all have been unsigned */
- return (authunix_create(machname, (int)uid, (int)gid, len,
+ return (authunix_create(machname, (int)uid, (int)gid, ngids,
(int *)gids));
}
diff --git a/lib/libc/rpc/clnt_bcast.c b/lib/libc/rpc/clnt_bcast.c
index eef0ca5..612007e 100644
--- a/lib/libc/rpc/clnt_bcast.c
+++ b/lib/libc/rpc/clnt_bcast.c
@@ -461,7 +461,7 @@ rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
#ifdef RPC_DEBUG
perror("sendto");
#endif
- warnx("clnt_bcast: cannot send"
+ warnx("clnt_bcast: cannot send "
"broadcast packet");
stat = RPC_CANTSEND;
continue;
diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c
index 1bb3368..9baa224 100644
--- a/lib/libc/rpc/getnetconfig.c
+++ b/lib/libc/rpc/getnetconfig.c
@@ -130,7 +130,11 @@ static struct netconfig *dup_ncp(struct netconfig *);
static FILE *nc_file; /* for netconfig db */
+static pthread_mutex_t nc_file_lock = PTHREAD_MUTEX_INITIALIZER;
+
static struct netconfig_info ni = { 0, 0, NULL, NULL};
+static pthread_mutex_t ni_lock = PTHREAD_MUTEX_INITIALIZER;
+
#define MAXNETCONFIGLINE 1000
@@ -204,14 +208,24 @@ setnetconfig()
* For multiple calls, i.e. nc_file is not NULL, we just return the
* handle without reopening the netconfig db.
*/
+ mutex_lock(&ni_lock);
ni.ref++;
+ mutex_unlock(&ni_lock);
+
+ mutex_lock(&nc_file_lock);
if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
nc_vars->valid = NC_VALID;
nc_vars->flag = 0;
nc_vars->nc_configs = ni.head;
+ mutex_unlock(&nc_file_lock);
return ((void *)nc_vars);
}
+ mutex_unlock(&nc_file_lock);
+
+ mutex_lock(&ni_lock);
ni.ref--;
+ mutex_unlock(&ni_lock);
+
nc_error = NC_NONETCONFIG;
free(nc_vars);
return (NULL);
@@ -234,14 +248,18 @@ void *handlep;
char *stringp; /* tmp string pointer */
struct netconfig_list *list;
struct netconfig *np;
+ struct netconfig *result;
/*
* Verify that handle is valid
*/
+ mutex_lock(&nc_file_lock);
if (ncp == NULL || nc_file == NULL) {
nc_error = NC_NOTINIT;
+ mutex_unlock(&nc_file_lock);
return (NULL);
}
+ mutex_unlock(&nc_file_lock);
switch (ncp->valid) {
case NC_VALID:
@@ -255,7 +273,9 @@ void *handlep;
*/
if (ncp->flag == 0) { /* first time */
ncp->flag = 1;
+ mutex_lock(&ni_lock);
ncp->nc_configs = ni.head;
+ mutex_unlock(&ni_lock);
if (ncp->nc_configs != NULL) /* entry already exist */
return(ncp->nc_configs->ncp);
}
@@ -268,7 +288,13 @@ void *handlep;
* If we cannot find the entry in the list and is end of file,
* we give up.
*/
- if (ni.eof == 1) return(NULL);
+ mutex_lock(&ni_lock);
+ if (ni.eof == 1) {
+ mutex_unlock(&ni_lock);
+ return(NULL);
+ }
+ mutex_unlock(&ni_lock);
+
break;
default:
nc_error = NC_NOTINIT;
@@ -289,13 +315,18 @@ void *handlep;
/*
* Read a line from netconfig file.
*/
+ mutex_lock(&nc_file_lock);
do {
if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
free(stringp);
+ mutex_lock(&ni_lock);
ni.eof = 1;
+ mutex_unlock(&ni_lock);
+ mutex_unlock(&nc_file_lock);
return (NULL);
}
} while (*stringp == '#');
+ mutex_unlock(&nc_file_lock);
list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
if (list == NULL) {
@@ -325,6 +356,7 @@ void *handlep;
* Reposition the current pointer of the handle to the last entry
* in the list.
*/
+ mutex_lock(&ni_lock);
if (ni.head == NULL) { /* first entry */
ni.head = ni.tail = list;
}
@@ -333,7 +365,9 @@ void *handlep;
ni.tail = ni.tail->next;
}
ncp->nc_configs = ni.tail;
- return(ni.tail->ncp);
+ result = ni.tail->ncp;
+ mutex_unlock(&ni_lock);
+ return(result);
}
}
@@ -367,7 +401,9 @@ void *handlep;
nc_handlep->valid = NC_INVALID;
nc_handlep->flag = 0;
nc_handlep->nc_configs = NULL;
+ mutex_lock(&ni_lock);
if (--ni.ref > 0) {
+ mutex_unlock(&ni_lock);
free(nc_handlep);
return(0);
}
@@ -380,6 +416,8 @@ void *handlep;
ni.eof = ni.ref = 0;
ni.head = NULL;
ni.tail = NULL;
+ mutex_unlock(&ni_lock);
+
while (q) {
p = q->next;
if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
@@ -390,8 +428,11 @@ void *handlep;
}
free(nc_handlep);
+ mutex_lock(&nc_file_lock);
fclose(nc_file);
nc_file = NULL;
+ mutex_unlock(&nc_file_lock);
+
return (0);
}
@@ -418,18 +459,6 @@ getnetconfigent(netid)
return (NULL);
}
- if (strcmp(netid, "unix") == 0) {
- fprintf(stderr, "The local transport is called \"unix\" ");
- fprintf(stderr, "in /etc/netconfig.\n");
- fprintf(stderr, "Please change this to \"local\" manually ");
- fprintf(stderr, "or run mergemaster(8).\n");
- fprintf(stderr, "See UPDATING entry 20021216 for details.\n");
- fprintf(stderr, "Continuing in 10 seconds\n\n");
- fprintf(stderr, "This warning will be removed 20030301\n");
- sleep(10);
-
- }
-
/*
* Look up table if the entries have already been read and parsed in
* getnetconfig(), then copy this entry into a buffer and return it.
@@ -439,15 +468,20 @@ getnetconfigent(netid)
* If all the netconfig db has been read and placed into the list and
* there is no match for the netid, return NULL.
*/
+ mutex_lock(&ni_lock);
if (ni.head != NULL) {
for (list = ni.head; list; list = list->next) {
if (strcmp(list->ncp->nc_netid, netid) == 0) {
+ mutex_unlock(&ni_lock);
return(dup_ncp(list->ncp));
}
}
- if (ni.eof == 1) /* that's all the entries */
+ if (ni.eof == 1) { /* that's all the entries */
+ mutex_unlock(&ni_lock);
return(NULL);
+ }
}
+ mutex_unlock(&ni_lock);
if ((file = fopen(NETCONFIG, "r")) == NULL) {
diff --git a/lib/libc/rpc/netname.c b/lib/libc/rpc/netname.c
index 2f30530..72361ba 100644
--- a/lib/libc/rpc/netname.c
+++ b/lib/libc/rpc/netname.c
@@ -61,9 +61,6 @@ __FBSDID("$FreeBSD$");
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
-#ifndef NGROUPS
-#define NGROUPS 16
-#endif
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
diff --git a/lib/libc/rpc/netnamer.c b/lib/libc/rpc/netnamer.c
index 7e567df..772160a 100644
--- a/lib/libc/rpc/netnamer.c
+++ b/lib/libc/rpc/netnamer.c
@@ -66,10 +66,6 @@ static char *NETIDFILE = "/etc/netid";
static int getnetid( char *, char * );
static int _getgroups( char *, gid_t * );
-#ifndef NGROUPS
-#define NGROUPS 16
-#endif
-
/*
* Convert network-name into unix credential
*/
@@ -104,7 +100,7 @@ netname2user(netname, uidp, gidp, gidlenp, gidlist)
return (0);
}
*gidp = (gid_t) atol(p);
- for (gidlen = 0; gidlen < NGROUPS; gidlen++) {
+ for (gidlen = 0; gidlen < NGRPS; gidlen++) {
p = strsep(&res, "\n,");
if (p == NULL)
break;
@@ -157,7 +153,7 @@ netname2user(netname, uidp, gidp, gidlenp, gidlist)
static int
_getgroups(uname, groups)
char *uname;
- gid_t groups[NGROUPS];
+ gid_t groups[NGRPS];
{
gid_t ngroups = 0;
struct group *grp;
@@ -169,7 +165,7 @@ _getgroups(uname, groups)
while ((grp = getgrent())) {
for (i = 0; grp->gr_mem[i]; i++)
if (!strcmp(grp->gr_mem[i], uname)) {
- if (ngroups == NGROUPS) {
+ if (ngroups == NGRPS) {
#ifdef DEBUG
fprintf(stderr,
"initgroups: %s is in too many groups\n", uname);
diff --git a/lib/libc/rpc/svc_dg.c b/lib/libc/rpc/svc_dg.c
index 51facd2..a78b160 100644
--- a/lib/libc/rpc/svc_dg.c
+++ b/lib/libc/rpc/svc_dg.c
@@ -97,7 +97,9 @@ int svc_dg_enablecache(SVCXPRT *, u_int);
*/
static const char svc_dg_str[] = "svc_dg_create: %s";
static const char svc_dg_err1[] = "could not get transport information";
-static const char svc_dg_err2[] = " transport does not support data transfer";
+static const char svc_dg_err2[] = "transport does not support data transfer";
+static const char svc_dg_err3[] = "getsockname failed";
+static const char svc_dg_err4[] = "cannot set IP_RECVDSTADDR";
static const char __no_mem_str[] = "out of memory";
SVCXPRT *
@@ -146,17 +148,37 @@ svc_dg_create(fd, sendsize, recvsize)
xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
slen = sizeof ss;
- if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
- goto freedata;
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ warnx(svc_dg_str, svc_dg_err3);
+ goto freedata_nowarn;
+ }
xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage));
xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage);
xprt->xp_ltaddr.len = slen;
memcpy(xprt->xp_ltaddr.buf, &ss, slen);
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in *sin;
+ static const int true_value = 1;
+
+ sin = (struct sockaddr_in *)(void *)&ss;
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ su->su_srcaddr.buf = mem_alloc(sizeof (ss));
+ su->su_srcaddr.maxlen = sizeof (ss);
+
+ if (_setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR,
+ &true_value, sizeof(true_value))) {
+ warnx(svc_dg_str, svc_dg_err4);
+ goto freedata_nowarn;
+ }
+ }
+ }
+
xprt_register(xprt);
return (xprt);
freedata:
(void) warnx(svc_dg_str, __no_mem_str);
+freedata_nowarn:
if (xprt) {
if (su)
(void) mem_free(su, sizeof (*su));
@@ -173,6 +195,61 @@ svc_dg_stat(xprt)
return (XPRT_IDLE);
}
+static int
+svc_dg_recvfrom(int fd, char *buf, int buflen,
+ struct sockaddr *raddr, socklen_t *raddrlen,
+ struct sockaddr *laddr, socklen_t *laddrlen)
+{
+ struct msghdr msg;
+ struct iovec msg_iov[1];
+ struct sockaddr_in *lin = (struct sockaddr_in *)laddr;
+ int rlen;
+ bool_t have_lin = FALSE;
+ char tmp[CMSG_LEN(sizeof(*lin))];
+ struct cmsghdr *cmsg;
+
+ memset((char *)&msg, 0, sizeof(msg));
+ msg_iov[0].iov_base = buf;
+ msg_iov[0].iov_len = buflen;
+ msg.msg_iov = msg_iov;
+ msg.msg_iovlen = 1;
+ msg.msg_namelen = *raddrlen;
+ msg.msg_name = (char *)raddr;
+ if (laddr != NULL) {
+ msg.msg_control = (caddr_t)tmp;
+ msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+ }
+ rlen = _recvmsg(fd, &msg, 0);
+ if (rlen >= 0)
+ *raddrlen = msg.msg_namelen;
+
+ if (rlen == -1 || laddr == NULL ||
+ msg.msg_controllen < sizeof(struct cmsghdr) ||
+ msg.msg_flags & MSG_CTRUNC)
+ return rlen;
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == IPPROTO_IP &&
+ cmsg->cmsg_type == IP_RECVDSTADDR) {
+ have_lin = TRUE;
+ memcpy(&lin->sin_addr,
+ (struct in_addr *)CMSG_DATA(cmsg),
+ sizeof(struct in_addr));
+ break;
+ }
+ }
+
+ lin->sin_family = AF_INET;
+ lin->sin_port = 0;
+ *laddrlen = sizeof(struct sockaddr_in);
+
+ if (!have_lin)
+ lin->sin_addr.s_addr = INADDR_ANY;
+
+ return rlen;
+}
+
static bool_t
svc_dg_recv(xprt, msg)
SVCXPRT *xprt;
@@ -188,8 +265,9 @@ svc_dg_recv(xprt, msg)
again:
alen = sizeof (struct sockaddr_storage);
- rlen = _recvfrom(xprt->xp_fd, rpc_buffer(xprt), su->su_iosz, 0,
- (struct sockaddr *)(void *)&ss, &alen);
+ rlen = svc_dg_recvfrom(xprt->xp_fd, rpc_buffer(xprt), su->su_iosz,
+ (struct sockaddr *)(void *)&ss, &alen,
+ (struct sockaddr *)su->su_srcaddr.buf, &su->su_srcaddr.len);
if (rlen == -1 && errno == EINTR)
goto again;
if (rlen == -1 || (rlen < (ssize_t)(4 * sizeof (u_int32_t))))
@@ -223,6 +301,40 @@ again:
return (TRUE);
}
+static int
+svc_dg_sendto(int fd, char *buf, int buflen,
+ const struct sockaddr *raddr, socklen_t raddrlen,
+ const struct sockaddr *laddr, socklen_t laddrlen)
+{
+ struct msghdr msg;
+ struct iovec msg_iov[1];
+ struct sockaddr_in *laddr_in = (struct sockaddr_in *)laddr;
+ struct in_addr *lin = &laddr_in->sin_addr;
+ char tmp[CMSG_SPACE(sizeof(*lin))];
+ struct cmsghdr *cmsg;
+
+ memset((char *)&msg, 0, sizeof(msg));
+ msg_iov[0].iov_base = buf;
+ msg_iov[0].iov_len = buflen;
+ msg.msg_iov = msg_iov;
+ msg.msg_iovlen = 1;
+ msg.msg_namelen = raddrlen;
+ msg.msg_name = (char *)raddr;
+
+ if (laddr != NULL && laddr->sa_family == AF_INET &&
+ lin->s_addr != INADDR_ANY) {
+ msg.msg_control = (caddr_t)tmp;
+ msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(*lin));
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_SENDSRCADDR;
+ memcpy(CMSG_DATA(cmsg), lin, sizeof(*lin));
+ }
+
+ return _sendmsg(fd, &msg, 0);
+}
+
static bool_t
svc_dg_reply(xprt, msg)
SVCXPRT *xprt;
@@ -253,9 +365,11 @@ svc_dg_reply(xprt, msg)
}
if (stat) {
slen = XDR_GETPOS(xdrs);
- if (_sendto(xprt->xp_fd, rpc_buffer(xprt), slen, 0,
+ if (svc_dg_sendto(xprt->xp_fd, rpc_buffer(xprt), slen,
(struct sockaddr *)xprt->xp_rtaddr.buf,
- (socklen_t)xprt->xp_rtaddr.len) == (ssize_t) slen) {
+ (socklen_t)xprt->xp_rtaddr.len,
+ (struct sockaddr *)su->su_srcaddr.buf,
+ (socklen_t)su->su_srcaddr.len) == (ssize_t) slen) {
stat = TRUE;
if (su->su_cache)
cache_set(xprt, slen);
@@ -301,6 +415,8 @@ svc_dg_destroy(xprt)
(void)_close(xprt->xp_fd);
XDR_DESTROY(&(su->su_xdrs));
(void) mem_free(rpc_buffer(xprt), su->su_iosz);
+ if (su->su_srcaddr.buf)
+ (void) mem_free(su->su_srcaddr.buf, su->su_srcaddr.maxlen);
(void) mem_free(su, sizeof (*su));
if (xprt->xp_rtaddr.buf)
(void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
diff --git a/lib/libc/softfloat/fpgetmask.c b/lib/libc/softfloat/fpgetmask.c
index 27f7460..20c6928 100644
--- a/lib/libc/softfloat/fpgetmask.c
+++ b/lib/libc/softfloat/fpgetmask.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fpgetmask.c,v 1.3 2002/05/12 13:12:45 bjh21 Exp $ */
+/* $NetBSD: fpgetmask.c,v 1.4 2008/04/28 20:23:00 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
diff --git a/lib/libc/softfloat/fpgetround.c b/lib/libc/softfloat/fpgetround.c
index 4ffb71f..6ff1ffd 100644
--- a/lib/libc/softfloat/fpgetround.c
+++ b/lib/libc/softfloat/fpgetround.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fpgetround.c,v 1.2 2002/01/13 21:45:53 thorpej Exp $ */
+/* $NetBSD: fpgetround.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
diff --git a/lib/libc/softfloat/fpgetsticky.c b/lib/libc/softfloat/fpgetsticky.c
index c76f985..f7ef466 100644
--- a/lib/libc/softfloat/fpgetsticky.c
+++ b/lib/libc/softfloat/fpgetsticky.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fpgetsticky.c,v 1.2 2002/01/13 21:45:53 thorpej Exp $ */
+/* $NetBSD: fpgetsticky.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
diff --git a/lib/libc/softfloat/fpsetmask.c b/lib/libc/softfloat/fpsetmask.c
index fb8b44d..47dcc95 100644
--- a/lib/libc/softfloat/fpsetmask.c
+++ b/lib/libc/softfloat/fpsetmask.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fpsetmask.c,v 1.3 2002/05/12 13:12:45 bjh21 Exp $ */
+/* $NetBSD: fpsetmask.c,v 1.4 2008/04/28 20:23:00 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
diff --git a/lib/libc/softfloat/fpsetround.c b/lib/libc/softfloat/fpsetround.c
index ce3ef9e..ecdb6ad 100644
--- a/lib/libc/softfloat/fpsetround.c
+++ b/lib/libc/softfloat/fpsetround.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fpsetround.c,v 1.2 2002/01/13 21:45:53 thorpej Exp $ */
+/* $NetBSD: fpsetround.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
diff --git a/lib/libc/softfloat/fpsetsticky.c b/lib/libc/softfloat/fpsetsticky.c
index 99379b3..526b19f 100644
--- a/lib/libc/softfloat/fpsetsticky.c
+++ b/lib/libc/softfloat/fpsetsticky.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fpsetsticky.c,v 1.2 2002/01/13 21:45:54 thorpej Exp $ */
+/* $NetBSD: fpsetsticky.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the 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
diff --git a/lib/libc/sparc64/stdlib/Makefile.inc b/lib/libc/sparc64/stdlib/Makefile.inc
deleted file mode 100644
index e8c0da7..0000000
--- a/lib/libc/sparc64/stdlib/Makefile.inc
+++ /dev/null
@@ -1 +0,0 @@
-# $FreeBSD$
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
index fc106db..c3b60f6 100644
--- a/lib/libc/stdio/Makefile.inc
+++ b/lib/libc/stdio/Makefile.inc
@@ -4,20 +4,21 @@
# stdio sources
.PATH: ${.CURDIR}/stdio
-SRCS+= _flock_stub.c asprintf.c clrerr.c fclose.c fcloseall.c fdopen.c \
+SRCS+= _flock_stub.c asprintf.c clrerr.c dprintf.c \
+ fclose.c fcloseall.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 \
+ 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 vasprintf.c vfprintf.c \
+ tmpnam.c ungetc.c ungetwc.c vasprintf.c vdprintf.c vfprintf.c \
vfscanf.c \
vfwprintf.c vfwscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c \
vsscanf.c \
@@ -33,7 +34,8 @@ SYM_MAPS+= ${.CURDIR}/stdio/Symbol.map
MAN+= 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 \
+ fputws.3 fread.3 fseek.3 funopen.3 fwide.3 getc.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
@@ -53,11 +55,12 @@ MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \
MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3
MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \
getc.3 getchar_unlocked.3 getc.3 getw.3
+MLINKS+=getline.3 getdelim.3
MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3
MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3
-MLINKS+=printf.3 asprintf.3 printf.3 fprintf.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 vasprintf.3 printf.3 vdprintf.3 \
printf.3 vfprintf.3 printf.3 vprintf.3 printf.3 vsnprintf.3 \
printf.3 vsprintf.3
MLINKS+=putc.3 fputc.3 putc.3 putc_unlocked.3 putc.3 putchar.3 \
diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map
index ac93cb2..df66ab3 100644
--- a/lib/libc/stdio/Symbol.map
+++ b/lib/libc/stdio/Symbol.map
@@ -110,6 +110,13 @@ FBSD_1.0 {
wscanf;
};
+FBSD_1.1 {
+ dprintf;
+ getdelim;
+ getline;
+ vdprintf;
+};
+
FBSDprivate_1.0 {
_flockfile;
_flockfile_debug_stub;
diff --git a/lib/libc/stdio/asprintf.c b/lib/libc/stdio/asprintf.c
index ed86989..90c62bc 100644
--- a/lib/libc/stdio/asprintf.c
+++ b/lib/libc/stdio/asprintf.c
@@ -1,8 +1,9 @@
-/* $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
@@ -12,59 +13,37 @@
* 2. Redistributions in binary form must reproduce 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$");
#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;
- 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._orientation = 0;
- memset(&f._mbstate, 0, sizeof(mbstate_t));
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);
}
diff --git a/lib/libc/stdio/dprintf.c b/lib/libc/stdio/dprintf.c
new file mode 100644
index 0000000..7f883dd
--- /dev/null
+++ b/lib/libc/stdio/dprintf.c
@@ -0,0 +1,46 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/stdio/fgetln.3 b/lib/libc/stdio/fgetln.3
index b95c61e..4b83664 100644
--- a/lib/libc/stdio/fgetln.3
+++ b/lib/libc/stdio/fgetln.3
@@ -116,6 +116,7 @@ or
.Xr fgets 3 ,
.Xr fgetwln 3 ,
.Xr fopen 3 ,
+.Xr getline 3 ,
.Xr putc 3
.Sh HISTORY
The
diff --git a/lib/libc/stdio/fgets.3 b/lib/libc/stdio/fgets.3
index cd74fcc..aa8e2ac 100644
--- a/lib/libc/stdio/fgets.3
+++ b/lib/libc/stdio/fgets.3
@@ -147,7 +147,8 @@ the FSA.)
.Xr feof 3 ,
.Xr ferror 3 ,
.Xr fgetln 3 ,
-.Xr fgetws 3
+.Xr fgetws 3 ,
+.Xr getline 3
.Sh STANDARDS
The functions
.Fn fgets
diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c
index a8ce7af..586e15c 100644
--- a/lib/libc/stdio/findfp.c
+++ b/lib/libc/stdio/findfp.c
@@ -53,10 +53,15 @@ int __sdidinit;
#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}
- /* p r w flags file _bf z cookie close read seek write */
-
+#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 glue uglue = { NULL, FOPEN_MAX - 3, usual };
diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3
index 3d572ca..92ec1e2 100644
--- a/lib/libc/stdio/fopen.3
+++ b/lib/libc/stdio/fopen.3
@@ -96,7 +96,7 @@ or similar.
.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
diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c
index 851713b..6253856 100644
--- a/lib/libc/stdio/fread.c
+++ b/lib/libc/stdio/fread.c
@@ -67,9 +67,7 @@ __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
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);
diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c
index 999d595..cf52e42 100644
--- a/lib/libc/stdio/fwrite.c
+++ b/lib/libc/stdio/fwrite.c
@@ -57,8 +57,15 @@ fwrite(buf, size, count, fp)
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;
diff --git a/lib/libc/stdio/getdelim.c b/lib/libc/stdio/getdelim.c
new file mode 100644
index 0000000..7af154f
--- /dev/null
+++ b/lib/libc/stdio/getdelim.c
@@ -0,0 +1,160 @@
+/*-
+ * 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$");
+
+#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 (*linecapp == 0)
+ *linep = NULL;
+
+ 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);
+}
diff --git a/lib/libc/stdio/getline.3 b/lib/libc/stdio/getline.3
new file mode 100644
index 0000000..0465f93
--- /dev/null
+++ b/lib/libc/stdio/getline.3
@@ -0,0 +1,164 @@
+.\" 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$
+.\"
+.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 NUL .
+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 .
diff --git a/lib/libc/stdio/getline.c b/lib/libc/stdio/getline.c
new file mode 100644
index 0000000..3f35520
--- /dev/null
+++ b/lib/libc/stdio/getline.c
@@ -0,0 +1,39 @@
+/*-
+ * 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$");
+
+#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));
+}
diff --git a/lib/libc/stdio/printf-pos.c b/lib/libc/stdio/printf-pos.c
index 945ba61..1648957 100644
--- a/lib/libc/stdio/printf-pos.c
+++ b/lib/libc/stdio/printf-pos.c
@@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$");
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_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
};
@@ -145,7 +145,7 @@ addsarg(struct typetable *types, int flags)
if (flags & INTMAXT)
types->table[types->nextarg++] = T_INTMAXT;
else if (flags & SIZET)
- types->table[types->nextarg++] = T_SIZET;
+ types->table[types->nextarg++] = T_SSIZET;
else if (flags & PTRDIFFT)
types->table[types->nextarg++] = T_PTRDIFFT;
else if (flags & LLONGINT)
@@ -168,7 +168,7 @@ adduarg(struct typetable *types, int flags)
else if (flags & SIZET)
types->table[types->nextarg++] = T_SIZET;
else if (flags & PTRDIFFT)
- types->table[types->nextarg++] = T_PTRDIFFT;
+ types->table[types->nextarg++] = T_SIZET;
else if (flags & LLONGINT)
types->table[types->nextarg++] = T_U_LLONG;
else if (flags & LONGINT)
@@ -374,7 +374,7 @@ reswitch: switch (ch) {
else if (flags & PTRDIFFT)
error = addtype(&types, TP_PTRDIFFT);
else if (flags & SIZET)
- error = addtype(&types, TP_SIZET);
+ error = addtype(&types, TP_SSIZET);
else if (flags & LLONGINT)
error = addtype(&types, TP_LLONG);
else if (flags & LONGINT)
@@ -565,7 +565,7 @@ reswitch: switch (ch) {
else if (flags & PTRDIFFT)
error = addtype(&types, TP_PTRDIFFT);
else if (flags & SIZET)
- error = addtype(&types, TP_SIZET);
+ error = addtype(&types, TP_SSIZET);
else if (flags & LLONGINT)
error = addtype(&types, TP_LLONG);
else if (flags & LONGINT)
@@ -716,8 +716,11 @@ build_arg_table(struct typetable *types, va_list ap, union arg **argtable)
case T_SIZET:
(*argtable) [n].sizearg = va_arg (ap, size_t);
break;
- case TP_SIZET:
- (*argtable) [n].psizearg = va_arg (ap, size_t *);
+ 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);
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
index 98e26dc..27d5bf0 100644
--- a/lib/libc/stdio/printf.3
+++ b/lib/libc/stdio/printf.3
@@ -32,16 +32,17 @@
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd October 16, 2004
+.Dd March 3, 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" ...
@@ -53,6 +54,8 @@
.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" "const char * restrict format" ...
.In stdarg.h
.Ft int
.Fn vprintf "const char * restrict format" "va_list ap"
@@ -64,6 +67,8 @@
.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
@@ -83,6 +88,10 @@ and
.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 ,
@@ -771,6 +780,57 @@ for later interpolation by
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
@@ -810,7 +870,13 @@ With the same reservation, the
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
@@ -828,30 +894,13 @@ from
.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
diff --git a/lib/libc/stdio/printflocal.h b/lib/libc/stdio/printflocal.h
index 763ef9b..3cef7bd 100644
--- a/lib/libc/stdio/printflocal.h
+++ b/lib/libc/stdio/printflocal.h
@@ -79,7 +79,7 @@ union arg {
long *plongarg;
long long *plonglongarg;
ptrdiff_t *pptrdiffarg;
- size_t *psizearg;
+ ssize_t *pssizearg;
intmax_t *pintmaxarg;
#ifndef NO_FLOATING_POINT
double doublearg;
diff --git a/lib/libc/stdio/stdio.3 b/lib/libc/stdio/stdio.3
index 1a13ee9..53320b5 100644
--- a/lib/libc/stdio/stdio.3
+++ b/lib/libc/stdio/stdio.3
@@ -28,7 +28,7 @@
.\" @(#)stdio.3 8.7 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd January 10, 2003
+.Dd March 3, 2009
.Dt STDIO 3
.Os
.Sh NAME
@@ -243,6 +243,7 @@ library conforms to
.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"
@@ -276,6 +277,8 @@ library conforms to
.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"
@@ -311,6 +314,7 @@ library conforms to
.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"
diff --git a/lib/libc/stdio/vdprintf.c b/lib/libc/stdio/vdprintf.c
new file mode 100644
index 0000000..2703022
--- /dev/null
+++ b/lib/libc/stdio/vdprintf.c
@@ -0,0 +1,66 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index e3f95eb..7e5d7fe 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -399,7 +399,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
#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() \
@@ -822,22 +822,7 @@ fp_common:
}
} 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':
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c
index 054299a..f3768de 100644
--- a/lib/libc/stdio/vfwprintf.c
+++ b/lib/libc/stdio/vfwprintf.c
@@ -479,7 +479,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
#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() \
@@ -890,23 +890,7 @@ fp_common:
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':
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index 3f3622d..1d06dd3 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -16,9 +16,7 @@ MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
SYM_MAPS+= ${.CURDIR}/stdlib/Symbol.map
# machine-dependent stdlib sources
-.if exists(${.CURDIR}/${MACHINE_ARCH}/stdlib/Makefile.inc)
-.include "${.CURDIR}/${MACHINE_ARCH}/stdlib/Makefile.inc"
-.endif
+.sinclude "${.CURDIR}/${MACHINE_ARCH}/stdlib/Makefile.inc"
MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \
div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \
diff --git a/lib/libc/stdlib/atol.3 b/lib/libc/stdlib/atol.3
index bb97c6f..cc49fe2 100644
--- a/lib/libc/stdlib/atol.3
+++ b/lib/libc/stdlib/atol.3
@@ -103,7 +103,7 @@ and
is not required by
.St -isoC
or
-.St -isoC-c99 ,
+.St -isoC-99 ,
but it is allowed by all of
.St -isoC , St -isoC-99
and
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 270d641..b56b003 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -5320,6 +5320,15 @@ posix_memalign(void **memptr, size_t alignment, size_t size)
goto RETURN;
}
+ if (size == 0) {
+ if (opt_sysv == false)
+ size = 1;
+ else {
+ result = NULL;
+ ret = 0;
+ goto RETURN;
+ }
+ }
result = ipalloc(alignment, size);
}
diff --git a/lib/libc/stdlib/ptsname.3 b/lib/libc/stdlib/ptsname.3
index b9c7381..f674a54 100644
--- a/lib/libc/stdlib/ptsname.3
+++ b/lib/libc/stdlib/ptsname.3
@@ -132,12 +132,24 @@ The slave pseudo-terminal device could not be accessed.
.Xr tty 4
.Sh STANDARDS
The
-.Fn grantpt ,
.Fn ptsname
+function conforms to
+.St -p1003.1-2008 .
+.Pp
+This implementation of
+.Fn grantpt
and
.Fn unlockpt
-functions conform to
-.St -p1003.1-2001 .
+does not conform to
+.St -p1003.1-2008 ,
+because it depends on
+.Xr posix_openpt 2
+to create the pseudo-terminal device with proper permissions in place.
+It only validates whether
+.Fa fildes
+is a valid pseudo-terminal master device.
+Future revisions of the specification will likely allow this behaviour,
+as stated by the Austin Group.
.Sh HISTORY
The
.Fn grantpt ,
@@ -146,15 +158,3 @@ and
.Fn unlockpt
functions appeared in
.Fx 5.0 .
-.Sh NOTES
-The purpose of the
-.Fn grantpt
-and
-.Fn unlockpt
-functions has no meaning in
-.Fx ,
-because pseudo-terminals obtained by
-.Xr posix_openpt 2
-are created on demand.
-Because these devices are created with proper permissions in place, they
-are guaranteed to be unused by unprivileged processes.
diff --git a/lib/libc/stdtime/asctime.c b/lib/libc/stdtime/asctime.c
index 0f4212f..30606f1 100644
--- a/lib/libc/stdtime/asctime.c
+++ b/lib/libc/stdtime/asctime.c
@@ -1,12 +1,18 @@
/*
** 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$");
@@ -19,7 +25,57 @@ __FBSDID("$FreeBSD$");
#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 *
@@ -36,6 +92,8 @@ char * buf;
};
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 = "???";
@@ -44,35 +102,41 @@ char * buf;
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);
}
diff --git a/lib/libc/stdtime/difftime.c b/lib/libc/stdtime/difftime.c
index 596ea82..d16f9a0 100644
--- a/lib/libc/stdtime/difftime.c
+++ b/lib/libc/stdtime/difftime.c
@@ -1,12 +1,12 @@
/*
** 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$");
@@ -14,74 +14,56 @@ __FBSDID("$FreeBSD$");
/*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);
}
diff --git a/lib/libc/stdtime/localtime.c b/lib/libc/stdtime/localtime.c
index 5928943..9fc5f3e 100644
--- a/lib/libc/stdtime/localtime.c
+++ b/lib/libc/stdtime/localtime.c
@@ -1,20 +1,19 @@
/*
** 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#ifndef NOID
-static char elsieid[] __unused = "@(#)localtime.c 7.78";
+static char elsieid[] __unused = "@(#)localtime.c 8.9";
#endif /* !defined NOID */
#endif /* !defined lint */
__FBSDID("$FreeBSD$");
/*
-** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
-** POSIX-style TZ environment variable handling from Guy Harris
-** (guy@auspex.com).
+** Leap second handling from Bradley White.
+** POSIX-style TZ environment variable handling from Guy Harris.
*/
/*LINTLIBRARY*/
@@ -22,12 +21,27 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/types.h>
#include <sys/stat.h>
+#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include "private.h"
#include "un-namespace.h"
#include "tzfile.h"
+#include "float.h" /* for FLT_MAX and DBL_MAX */
+
+#ifndef TZ_ABBR_MAX_LEN
+#define TZ_ABBR_MAX_LEN 16
+#endif /* !defined TZ_ABBR_MAX_LEN */
+
+#ifndef TZ_ABBR_CHAR_SET
+#define TZ_ABBR_CHAR_SET \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
+#endif /* !defined TZ_ABBR_CHAR_SET */
+
+#ifndef TZ_ABBR_ERR_CHAR
+#define TZ_ABBR_ERR_CHAR '_'
+#endif /* !defined TZ_ABBR_ERR_CHAR */
#include "libc_private.h"
@@ -74,16 +88,16 @@ __FBSDID("$FreeBSD$");
** 5. They might reference tm.TM_ZONE after calling offtime.
** What's best to do in the above cases is open to debate;
** for now, we just set things up so that in any of the five cases
-** WILDABBR is used. Another possibility: initialize tzname[0] to the
+** WILDABBR is used. Another possibility: initialize tzname[0] to the
** string "tzname[0] used before set", and similarly for the other cases.
-** And another: initialize tzname[0] to "ERA", with an explanation in the
+** And another: initialize tzname[0] to "ERA", with an explanation in the
** manual page of what this "time zone abbreviation" means (doing this so
** that tzname[0] has the "normal" length of three characters).
*/
#define WILDABBR " "
#endif /* !defined WILDABBR */
-static char wildabbr[] = "WILDABBR";
+static char wildabbr[] = WILDABBR;
/*
* In June 2004 it was decided UTC was a more appropriate default time
@@ -130,6 +144,8 @@ struct state {
int timecnt;
int typecnt;
int charcnt;
+ int goback;
+ int goahead;
time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
struct ttinfo ttis[TZ_MAX_TYPES];
@@ -155,40 +171,49 @@ struct rule {
*/
static long detzcode(const char * codep);
+static time_t detzcode64(const char * codep);
+static int differ_by_repeat(time_t t1, time_t t0);
static const char * getzname(const char * strp);
+static const char * getqzname(const char * strp, const int delim);
static const char * getnum(const char * strp, int * nump, int min,
int max);
static const char * getsecs(const char * strp, long * secsp);
static const char * getoffset(const char * strp, long * offsetp);
static const char * getrule(const char * strp, struct rule * rulep);
static void gmtload(struct state * sp);
-static void gmtsub(const time_t * timep, long offset,
+static struct tm * gmtsub(const time_t * timep, long offset,
struct tm * tmp);
-static void localsub(const time_t * timep, long offset,
+static struct tm * localsub(const time_t * timep, long offset,
struct tm * tmp);
static int increment_overflow(int * number, int delta);
+static int leaps_thru_end_of(int y);
+static int long_increment_overflow(long * number, int delta);
+static int long_normalize_overflow(long * tensptr,
+ int * unitsptr, int base);
static int normalize_overflow(int * tensptr, int * unitsptr,
int base);
static void settzname(void);
static time_t time1(struct tm * tmp,
- void(*funcp) (const time_t *,
+ struct tm * (*funcp)(const time_t *,
long, struct tm *),
long offset);
static time_t time2(struct tm *tmp,
- void(*funcp) (const time_t *,
+ struct tm * (*funcp)(const time_t *,
long, struct tm*),
long offset, int * okayp);
static time_t time2sub(struct tm *tmp,
- void(*funcp) (const time_t *,
+ struct tm * (*funcp)(const time_t *,
long, struct tm*),
long offset, int * okayp, int do_norm_secs);
-static void timesub(const time_t * timep, long offset,
+static struct tm * timesub(const time_t * timep, long offset,
const struct state * sp, struct tm * tmp);
static int tmcomp(const struct tm * atmp,
const struct tm * btmp);
static time_t transtime(time_t janfirst, int year,
const struct rule * rulep, long offset);
-static int tzload(const char * name, struct state * sp);
+static int typesequiv(const struct state * sp, int a, int b);
+static int tzload(const char * name, struct state * sp,
+ int doextend);
static int tzparse(const char * name, struct state * sp,
int lastditch);
@@ -224,7 +249,7 @@ char * tzname[2] = {
** Except for the strftime function, these functions [asctime,
** ctime, gmtime, localtime] return values in one of two static
** objects: a broken-down time structure and an array of char.
-** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
+** Thanks to Paul Eggert for noting this.
*/
static struct tm tm;
@@ -245,12 +270,25 @@ const char * const codep;
long result;
int i;
- result = (codep[0] & 0x80) ? ~0L : 0L;
+ result = (codep[0] & 0x80) ? ~0L : 0;
for (i = 0; i < 4; ++i)
result = (result << 8) | (codep[i] & 0xff);
return result;
}
+static time_t
+detzcode64(codep)
+const char * const codep;
+{
+ register time_t result;
+ register int i;
+
+ result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
+ for (i = 0; i < 8; ++i)
+ result = result * 256 + (codep[i] & 0xff);
+ return result;
+}
+
static void
settzname(void)
{
@@ -299,16 +337,58 @@ settzname(void)
tzname[ttisp->tt_isdst] =
&sp->chars[ttisp->tt_abbrind];
}
+ /*
+ ** Finally, scrub the abbreviations.
+ ** First, replace bogus characters.
+ */
+ for (i = 0; i < sp->charcnt; ++i)
+ if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
+ sp->chars[i] = TZ_ABBR_ERR_CHAR;
+ /*
+ ** Second, truncate long abbreviations.
+ */
+ for (i = 0; i < sp->typecnt; ++i) {
+ register const struct ttinfo * const ttisp = &sp->ttis[i];
+ register char * cp = &sp->chars[ttisp->tt_abbrind];
+
+ if (strlen(cp) > TZ_ABBR_MAX_LEN &&
+ strcmp(cp, GRANDPARENTED) != 0)
+ *(cp + TZ_ABBR_MAX_LEN) = '\0';
+ }
+}
+
+static int
+differ_by_repeat(t1, t0)
+const time_t t1;
+const time_t t0;
+{
+ int_fast64_t _t0 = t0;
+ int_fast64_t _t1 = t1;
+
+ if (TYPE_INTEGRAL(time_t) &&
+ TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
+ return 0;
+ //turn ((int_fast64_t)(t1 - t0) == SECSPERREPEAT);
+ return _t1 - _t0 == SECSPERREPEAT;
}
static int
-tzload(name, sp)
+tzload(name, sp, doextend)
const char * name;
struct state * const sp;
+register const int doextend;
{
const char * p;
int i;
int fid;
+ int stored;
+ int nread;
+ union {
+ struct tzhead tzhead;
+ char buf[2 * sizeof(struct tzhead) +
+ 2 * sizeof *sp +
+ 4 * TZ_MAX_TIMES];
+ } u;
/* XXX The following is from OpenBSD, and I'm not sure it is correct */
if (name != NULL && issetugid() != 0)
@@ -356,18 +436,13 @@ struct state * const sp;
return -1;
}
}
- {
- struct tzhead * tzhp;
- union {
- struct tzhead tzhead;
- char buf[sizeof *sp + sizeof *tzhp];
- } u;
+ nread = _read(fid, u.buf, sizeof u.buf);
+ if (_close(fid) < 0 || nread <= 0)
+ return -1;
+ for (stored = 4; stored <= 8; stored *= 2) {
int ttisstdcnt;
int ttisgmtcnt;
- i = _read(fid, u.buf, sizeof u.buf);
- if (_close(fid) != 0)
- return -1;
ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
@@ -382,17 +457,19 @@ struct state * const sp;
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
return -1;
- if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
+ if (nread - (p - u.buf) <
+ sp->timecnt * stored + /* ats */
sp->timecnt + /* types */
- sp->typecnt * (4 + 2) + /* ttinfos */
+ sp->typecnt * 6 + /* ttinfos */
sp->charcnt + /* chars */
- sp->leapcnt * (4 + 4) + /* lsinfos */
+ sp->leapcnt * (stored + 4) + /* lsinfos */
ttisstdcnt + /* ttisstds */
ttisgmtcnt) /* ttisgmts */
return -1;
for (i = 0; i < sp->timecnt; ++i) {
- sp->ats[i] = detzcode(p);
- p += 4;
+ sp->ats[i] = (stored == 4) ?
+ detzcode(p) : detzcode64(p);
+ p += stored;
}
for (i = 0; i < sp->timecnt; ++i) {
sp->types[i] = (unsigned char) *p++;
@@ -420,8 +497,9 @@ struct state * const sp;
struct lsinfo * lsisp;
lsisp = &sp->lsis[i];
- lsisp->ls_trans = detzcode(p);
- p += 4;
+ lsisp->ls_trans = (stored == 4) ?
+ detzcode(p) : detzcode64(p);
+ p += stored;
lsisp->ls_corr = detzcode(p);
p += 4;
}
@@ -451,10 +529,127 @@ struct state * const sp;
return -1;
}
}
+ /*
+ ** Out-of-sort ats should mean we're running on a
+ ** signed time_t system but using a data file with
+ ** unsigned values (or vice versa).
+ */
+ for (i = 0; i < sp->timecnt - 2; ++i)
+ if (sp->ats[i] > sp->ats[i + 1]) {
+ ++i;
+ if (TYPE_SIGNED(time_t)) {
+ /*
+ ** Ignore the end (easy).
+ */
+ sp->timecnt = i;
+ } else {
+ /*
+ ** Ignore the beginning (harder).
+ */
+ register int j;
+
+ for (j = 0; j + i < sp->timecnt; ++j) {
+ sp->ats[j] = sp->ats[j + i];
+ sp->types[j] = sp->types[j + i];
+ }
+ sp->timecnt = j;
+ }
+ break;
+ }
+ /*
+ ** If this is an old file, we're done.
+ */
+ if (u.tzhead.tzh_version[0] == '\0')
+ break;
+ nread -= p - u.buf;
+ for (i = 0; i < nread; ++i)
+ u.buf[i] = p[i];
+ /*
+ ** If this is a narrow integer time_t system, we're done.
+ */
+ if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
+ break;
+ }
+ if (doextend && nread > 2 &&
+ u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
+ sp->typecnt + 2 <= TZ_MAX_TYPES) {
+ struct state ts;
+ register int result;
+
+ u.buf[nread - 1] = '\0';
+ result = tzparse(&u.buf[1], &ts, FALSE);
+ if (result == 0 && ts.typecnt == 2 &&
+ sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
+ for (i = 0; i < 2; ++i)
+ ts.ttis[i].tt_abbrind +=
+ sp->charcnt;
+ for (i = 0; i < ts.charcnt; ++i)
+ sp->chars[sp->charcnt++] =
+ ts.chars[i];
+ i = 0;
+ while (i < ts.timecnt &&
+ ts.ats[i] <=
+ sp->ats[sp->timecnt - 1])
+ ++i;
+ while (i < ts.timecnt &&
+ sp->timecnt < TZ_MAX_TIMES) {
+ sp->ats[sp->timecnt] =
+ ts.ats[i];
+ sp->types[sp->timecnt] =
+ sp->typecnt +
+ ts.types[i];
+ ++sp->timecnt;
+ ++i;
+ }
+ sp->ttis[sp->typecnt++] = ts.ttis[0];
+ sp->ttis[sp->typecnt++] = ts.ttis[1];
+ }
+ }
+ sp->goback = sp->goahead = FALSE;
+ if (sp->timecnt > 1) {
+ for (i = 1; i < sp->timecnt; ++i)
+ if (typesequiv(sp, sp->types[i], sp->types[0]) &&
+ differ_by_repeat(sp->ats[i], sp->ats[0])) {
+ sp->goback = TRUE;
+ break;
+ }
+ for (i = sp->timecnt - 2; i >= 0; --i)
+ if (typesequiv(sp, sp->types[sp->timecnt - 1],
+ sp->types[i]) &&
+ differ_by_repeat(sp->ats[sp->timecnt - 1],
+ sp->ats[i])) {
+ sp->goahead = TRUE;
+ break;
+ }
}
return 0;
}
+static int
+typesequiv(sp, a, b)
+const struct state * const sp;
+const int a;
+const int b;
+{
+ register int result;
+
+ if (sp == NULL ||
+ a < 0 || a >= sp->typecnt ||
+ b < 0 || b >= sp->typecnt)
+ result = FALSE;
+ else {
+ register const struct ttinfo * ap = &sp->ttis[a];
+ register const struct ttinfo * bp = &sp->ttis[b];
+ result = ap->tt_gmtoff == bp->tt_gmtoff &&
+ ap->tt_isdst == bp->tt_isdst &&
+ ap->tt_ttisstd == bp->tt_ttisstd &&
+ ap->tt_ttisgmt == bp->tt_ttisgmt &&
+ strcmp(&sp->chars[ap->tt_abbrind],
+ &sp->chars[bp->tt_abbrind]) == 0;
+ }
+ return result;
+}
+
static const int mon_lengths[2][MONSPERYEAR] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
@@ -466,7 +661,7 @@ static const int year_lengths[2] = {
/*
** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
+** a valid character in a zone name is found. Return a pointer to that
** character.
*/
@@ -483,6 +678,25 @@ const char * strp;
}
/*
+** Given a pointer into an extended time zone string, scan until the ending
+** delimiter of the zone name is located. Return a pointer to the delimiter.
+**
+** As with getzname above, the legal character set is actually quite
+** restricted, with other characters producing undefined results.
+** We don't do any checking here; checking is done later in common-case code.
+*/
+
+static const char *
+getqzname(register const char *strp, const int delim)
+{
+ register int c;
+
+ while ((c = *strp) != '\0' && c != delim)
+ ++strp;
+ return strp;
+}
+
+/*
** Given a pointer into a time zone string, extract a number from that string.
** Check that the number is within a specified range; if it is not, return
** NULL.
@@ -547,7 +761,7 @@ long * const secsp;
*secsp += num * SECSPERMIN;
if (*strp == ':') {
++strp;
- /* `SECSPERMIN' allows for leap seconds. */
+ /* `SECSPERMIN' allows for leap seconds. */
strp = getnum(strp, &num, 0, SECSPERMIN);
if (strp == NULL)
return NULL;
@@ -586,7 +800,7 @@ long * const offsetp;
/*
** Given a pointer into a time zone string, extract a rule in the form
-** date[/time]. See POSIX section 8 for the format of "date" and "time".
+** date[/time]. See POSIX section 8 for the format of "date" and "time".
** If a valid rule is not found, return NULL.
** Otherwise, return a pointer to the first character not part of the rule.
*/
@@ -705,7 +919,7 @@ const long offset;
dow += DAYSPERWEEK;
/*
- ** "dow" is the day-of-week of the first day of the month. Get
+ ** "dow" is the day-of-week of the first day of the month. Get
** the day-of-month (zero-origin) of the first "dow" day of the
** month.
*/
@@ -728,7 +942,7 @@ const long offset;
/*
** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
- ** question. To get the Epoch-relative time of the specified local
+ ** question. To get the Epoch-relative time of the specified local
** time on that day, add the transition time and the current offset
** from UTC.
*/
@@ -766,10 +980,18 @@ const int lastditch;
stdlen = (sizeof sp->chars) - 1;
stdoffset = 0;
} else {
- name = getzname(name);
- stdlen = name - stdname;
- if (stdlen < 3)
- return -1;
+ if (*name == '<') {
+ name++;
+ stdname = name;
+ name = getqzname(name, '>');
+ if (*name != '>')
+ return (-1);
+ stdlen = name - stdname;
+ name++;
+ } else {
+ name = getzname(name);
+ stdlen = name - stdname;
+ }
if (*name == '\0')
return -1; /* was "stdoffset = 0;" */
else {
@@ -778,15 +1000,22 @@ const int lastditch;
return -1;
}
}
- load_result = tzload(TZDEFRULES, sp);
+ load_result = tzload(TZDEFRULES, sp, FALSE);
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
- dstname = name;
- name = getzname(name);
- dstlen = name - dstname; /* length of DST zone name */
- if (dstlen < 3)
- return -1;
+ if (*name == '<') {
+ dstname = ++name;
+ name = getqzname(name, '>');
+ if (*name != '>')
+ return -1;
+ dstlen = name - dstname;
+ name++;
+ } else {
+ dstname = name;
+ name = getzname(name);
+ dstlen = name - dstname; /* length of DST zone name */
+ }
if (*name != '\0' && *name != ',' && *name != ';') {
name = getoffset(name, &dstoffset);
if (name == NULL)
@@ -813,11 +1042,8 @@ const int lastditch;
return -1;
sp->typecnt = 2; /* standard time and DST */
/*
- ** Two transitions per year, from EPOCH_YEAR to 2037.
+ ** Two transitions per year, from EPOCH_YEAR forward.
*/
- sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
- if (sp->timecnt > TZ_MAX_TIMES)
- return -1;
sp->ttis[0].tt_gmtoff = -dstoffset;
sp->ttis[0].tt_isdst = 1;
sp->ttis[0].tt_abbrind = stdlen + 1;
@@ -827,7 +1053,12 @@ const int lastditch;
atp = sp->ats;
typep = sp->types;
janfirst = 0;
- for (year = EPOCH_YEAR; year <= 2037; ++year) {
+ sp->timecnt = 0;
+ for (year = EPOCH_YEAR;
+ sp->timecnt + 2 <= TZ_MAX_TIMES;
+ ++year) {
+ time_t newfirst;
+
starttime = transtime(janfirst, year, &start,
stdoffset);
endtime = transtime(janfirst, year, &end,
@@ -843,8 +1074,13 @@ const int lastditch;
*atp++ = endtime;
*typep++ = 1; /* DST ends */
}
- janfirst += year_lengths[isleap(year)] *
+ sp->timecnt += 2;
+ newfirst = janfirst;
+ newfirst += year_lengths[isleap(year)] *
SECSPERDAY;
+ if (newfirst <= janfirst)
+ break;
+ janfirst = newfirst;
}
} else {
long theirstdoffset;
@@ -959,7 +1195,7 @@ static void
gmtload(sp)
struct state * const sp;
{
- if (tzload(gmt, sp) != 0)
+ if (tzload(gmt, sp, TRUE) != 0)
(void) tzparse(gmt, sp, TRUE);
}
@@ -990,7 +1226,7 @@ tzsetwall_basic(int rdlocked)
}
}
#endif /* defined ALL_STATE */
- if (tzload((char *) NULL, lclptr) != 0)
+ if (tzload((char *) NULL, lclptr, TRUE) != 0)
gmtload(lclptr);
settzname();
_RWLOCK_UNLOCK(&lcl_rwlock);
@@ -1053,7 +1289,7 @@ tzset_basic(int rdlocked)
lclptr->ttis[0].tt_gmtoff = 0;
lclptr->ttis[0].tt_abbrind = 0;
(void) strcpy(lclptr->chars, gmt);
- } else if (tzload(name, lclptr) != 0)
+ } else if (tzload(name, lclptr, TRUE) != 0)
if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
(void) gmtload(lclptr);
settzname();
@@ -1072,14 +1308,14 @@ tzset(void)
/*
** The easy way to behave "as if no library function calls" localtime
** is to not call it--so we drop its guts into "localsub", which can be
-** freely called. (And no, the PANS doesn't require the above behavior--
+** freely called. (And no, the PANS doesn't require the above behavior--
** but it *is* desirable.)
**
** The unused offset argument is for the benefit of mktime variants.
*/
/*ARGSUSED*/
-static void
+static struct tm *
localsub(timep, offset, tmp)
const time_t * const timep;
const long offset;
@@ -1088,15 +1324,53 @@ struct tm * const tmp;
struct state * sp;
const struct ttinfo * ttisp;
int i;
- const time_t t = *timep;
+ struct tm * result;
+ const time_t t = *timep;
sp = lclptr;
#ifdef ALL_STATE
- if (sp == NULL) {
- gmtsub(timep, offset, tmp);
- return;
- }
+ if (sp == NULL)
+ return gmtsub(timep, offset, tmp);
#endif /* defined ALL_STATE */
+ if ((sp->goback && t < sp->ats[0]) ||
+ (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
+ time_t newt = t;
+ register time_t seconds;
+ register time_t tcycles;
+ register int_fast64_t icycles;
+
+ if (t < sp->ats[0])
+ seconds = sp->ats[0] - t;
+ else seconds = t - sp->ats[sp->timecnt - 1];
+ --seconds;
+ tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
+ ++tcycles;
+ icycles = tcycles;
+ if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
+ return NULL;
+ seconds = icycles;
+ seconds *= YEARSPERREPEAT;
+ seconds *= AVGSECSPERYEAR;
+ if (t < sp->ats[0])
+ newt += seconds;
+ else newt -= seconds;
+ if (newt < sp->ats[0] ||
+ newt > sp->ats[sp->timecnt - 1])
+ return NULL; /* "cannot happen" */
+ result = localsub(&newt, offset, tmp);
+ if (result == tmp) {
+ register time_t newy;
+
+ newy = tmp->tm_year;
+ if (t < sp->ats[0])
+ newy -= icycles * YEARSPERREPEAT;
+ else newy += icycles * YEARSPERREPEAT;
+ tmp->tm_year = newy;
+ if (tmp->tm_year != newy)
+ return NULL;
+ }
+ return result;
+ }
if (sp->timecnt == 0 || t < sp->ats[0]) {
i = 0;
while (sp->ttis[i].tt_isdst)
@@ -1105,10 +1379,17 @@ struct tm * const tmp;
break;
}
} else {
- for (i = 1; i < sp->timecnt; ++i)
- if (t < sp->ats[i])
- break;
- i = sp->types[i - 1];
+ register int lo = 1;
+ register int hi = sp->timecnt;
+
+ while (lo < hi) {
+ register int mid = (lo + hi) >> 1;
+
+ if (t < sp->ats[mid])
+ hi = mid;
+ else lo = mid + 1;
+ }
+ i = (int) sp->types[lo - 1];
}
ttisp = &sp->ttis[i];
/*
@@ -1117,12 +1398,13 @@ struct tm * const tmp;
** t += ttisp->tt_gmtoff;
** timesub(&t, 0L, sp, tmp);
*/
- timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+ result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
tmp->tm_isdst = ttisp->tt_isdst;
tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
#ifdef TM_ZONE
tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
#endif /* defined TM_ZONE */
+ return result;
}
struct tm *
@@ -1132,13 +1414,16 @@ const time_t * const timep;
static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t localtime_key = -1;
struct tm *p_tm;
+ int r;
if (__isthreaded != 0) {
if (localtime_key < 0) {
_pthread_mutex_lock(&localtime_mutex);
if (localtime_key < 0) {
- if (_pthread_key_create(&localtime_key, free) < 0) {
+ if ((r = _pthread_key_create(&localtime_key,
+ free)) != 0) {
_pthread_mutex_unlock(&localtime_mutex);
+ errno = r;
return(NULL);
}
}
@@ -1168,40 +1453,40 @@ const time_t * const timep;
*/
struct tm *
-localtime_r(timep, tm)
+localtime_r(timep, tmp)
const time_t * const timep;
-struct tm * tm;
+struct tm * tmp;
{
_RWLOCK_RDLOCK(&lcl_rwlock);
tzset_basic(1);
- localsub(timep, 0L, tm);
+ localsub(timep, 0L, tmp);
_RWLOCK_UNLOCK(&lcl_rwlock);
- return tm;
+ return tmp;
}
/*
** gmtsub is to gmtime as localsub is to localtime.
*/
-static void
+static struct tm *
gmtsub(timep, offset, tmp)
const time_t * const timep;
const long offset;
struct tm * const tmp;
{
+ register struct tm * result;
+
+ _MUTEX_LOCK(&gmt_mutex);
if (!gmt_is_set) {
- _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);
- gmt_is_set = TRUE;
- }
- _MUTEX_UNLOCK(&gmt_mutex);
+ gmtload(gmtptr);
+ gmt_is_set = TRUE;
}
- timesub(timep, offset, gmtptr, tmp);
+ _MUTEX_UNLOCK(&gmt_mutex);
+ result = timesub(timep, offset, gmtptr, tmp);
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
@@ -1221,6 +1506,7 @@ struct tm * const tmp;
#endif /* State Farm */
}
#endif /* defined TM_ZONE */
+ return result;
}
struct tm *
@@ -1230,13 +1516,16 @@ const time_t * const timep;
static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t gmtime_key = -1;
struct tm *p_tm;
+ int r;
if (__isthreaded != 0) {
if (gmtime_key < 0) {
_pthread_mutex_lock(&gmtime_mutex);
if (gmtime_key < 0) {
- if (_pthread_key_create(&gmtime_key, free) < 0) {
+ if ((r = _pthread_key_create(&gmtime_key,
+ free)) != 0) {
_pthread_mutex_unlock(&gmtime_mutex);
+ errno = r;
return(NULL);
}
}
@@ -1267,12 +1556,11 @@ const time_t * const timep;
*/
struct tm *
-gmtime_r(timep, tm)
+gmtime_r(timep, tmp)
const time_t * const timep;
-struct tm * tm;
+struct tm * tmp;
{
- gmtsub(timep, 0L, tm);
- return tm;
+ return gmtsub(timep, 0L, tmp);
}
#ifdef STD_INSPIRED
@@ -1282,13 +1570,25 @@ offtime(timep, offset)
const time_t * const timep;
const long offset;
{
- gmtsub(timep, offset, &tm);
- return &tm;
+ return gmtsub(timep, offset, &tm);
}
#endif /* defined STD_INSPIRED */
-static void
+/*
+** Return the number of leap years through the end of the given year
+** where, to make the math easy, the answer for year zero is defined as zero.
+*/
+
+static int
+leaps_thru_end_of(y)
+register const int y;
+{
+ return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
+ -(leaps_thru_end_of(-(y + 1)) + 1);
+}
+
+static struct tm *
timesub(timep, offset, sp, tmp)
const time_t * const timep;
const long offset;
@@ -1296,10 +1596,10 @@ const struct state * const sp;
struct tm * const tmp;
{
const struct lsinfo * lp;
- long days;
+ time_t tdays;
+ int idays; /* unsigned would be so 2003 */
long rem;
- long y;
- int yleap;
+ int y;
const int * ip;
long corr;
int hit;
@@ -1333,60 +1633,93 @@ struct tm * const tmp;
break;
}
}
- days = *timep / SECSPERDAY;
- rem = *timep % SECSPERDAY;
-#ifdef mc68k
- if (*timep == 0x80000000) {
- /*
- ** A 3B1 muffs the division on the most negative number.
- */
- days = -24855;
- rem = -11648;
+ y = EPOCH_YEAR;
+ tdays = *timep / SECSPERDAY;
+ rem = *timep - tdays * SECSPERDAY;
+ while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
+ int newy;
+ register time_t tdelta;
+ register int idelta;
+ register int leapdays;
+
+ tdelta = tdays / DAYSPERLYEAR;
+ idelta = tdelta;
+ if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
+ return NULL;
+ if (idelta == 0)
+ idelta = (tdays < 0) ? -1 : 1;
+ newy = y;
+ if (increment_overflow(&newy, idelta))
+ return NULL;
+ leapdays = leaps_thru_end_of(newy - 1) -
+ leaps_thru_end_of(y - 1);
+ tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
+ tdays -= leapdays;
+ y = newy;
}
-#endif /* defined mc68k */
- rem += (offset - corr);
+ {
+ register long seconds;
+
+ seconds = tdays * SECSPERDAY + 0.5;
+ tdays = seconds / SECSPERDAY;
+ rem += seconds - tdays * SECSPERDAY;
+ }
+ /*
+ ** Given the range, we can now fearlessly cast...
+ */
+ idays = tdays;
+ rem += offset - corr;
while (rem < 0) {
rem += SECSPERDAY;
- --days;
+ --idays;
}
while (rem >= SECSPERDAY) {
rem -= SECSPERDAY;
- ++days;
+ ++idays;
}
+ while (idays < 0) {
+ if (increment_overflow(&y, -1))
+ return NULL;
+ idays += year_lengths[isleap(y)];
+ }
+ while (idays >= year_lengths[isleap(y)]) {
+ idays -= year_lengths[isleap(y)];
+ if (increment_overflow(&y, 1))
+ return NULL;
+ }
+ tmp->tm_year = y;
+ if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
+ return NULL;
+ tmp->tm_yday = idays;
+ /*
+ ** The "extra" mods below avoid overflow problems.
+ */
+ tmp->tm_wday = EPOCH_WDAY +
+ ((y - EPOCH_YEAR) % DAYSPERWEEK) *
+ (DAYSPERNYEAR % DAYSPERWEEK) +
+ leaps_thru_end_of(y - 1) -
+ leaps_thru_end_of(EPOCH_YEAR - 1) +
+ idays;
+ tmp->tm_wday %= DAYSPERWEEK;
+ if (tmp->tm_wday < 0)
+ tmp->tm_wday += DAYSPERWEEK;
tmp->tm_hour = (int) (rem / SECSPERHOUR);
- rem = rem % SECSPERHOUR;
+ rem %= SECSPERHOUR;
tmp->tm_min = (int) (rem / SECSPERMIN);
/*
** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
+ ** representation. This uses "... ??:59:60" et seq.
*/
tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
- tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
- if (tmp->tm_wday < 0)
- tmp->tm_wday += DAYSPERWEEK;
- y = EPOCH_YEAR;
-#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
- while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
- long newy;
-
- newy = y + days / DAYSPERNYEAR;
- if (days < 0)
- --newy;
- days -= (newy - y) * DAYSPERNYEAR +
- LEAPS_THRU_END_OF(newy - 1) -
- LEAPS_THRU_END_OF(y - 1);
- y = newy;
- }
- tmp->tm_year = y - TM_YEAR_BASE;
- tmp->tm_yday = (int) days;
- ip = mon_lengths[yleap];
- for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
- days = days - (long) ip[tmp->tm_mon];
- tmp->tm_mday = (int) (days + 1);
+ ip = mon_lengths[isleap(y)];
+ for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
+ idays -= ip[tmp->tm_mon];
+ tmp->tm_mday = (int) (idays + 1);
tmp->tm_isdst = 0;
#ifdef TM_GMTOFF
tmp->TM_GMTOFF = offset;
#endif /* defined TM_GMTOFF */
+ return tmp;
}
char *
@@ -1396,7 +1729,7 @@ const time_t * const timep;
/*
** Section 4.12.3.2 of X3.159-1989 requires that
** The ctime function converts the calendar time pointed to by timer
-** to local time in the form of a string. It is equivalent to
+** to local time in the form of a string. It is equivalent to
** asctime(localtime(timer))
*/
return asctime(localtime(timep));
@@ -1407,17 +1740,16 @@ ctime_r(timep, buf)
const time_t * const timep;
char * buf;
{
- struct tm tm;
+ struct tm mytm;
- return asctime_r(localtime_r(timep, &tm), buf);
+ return asctime_r(localtime_r(timep, &mytm), buf);
}
/*
** Adapted from code provided by Robert Elz, who writes:
** The "best" way to do mktime I think is based on an idea of Bob
** Kridle's (so its said...) from a long time ago.
-** [kridle@xinet.com as of 1996-01-16.]
-** It does a binary search of the time_t space. Since time_t's are
+** It does a binary search of the time_t space. Since time_t's are
** just 32 bits, its a max of 32 iterations (even at 64 bits it
** would still be very reasonable).
*/
@@ -1427,7 +1759,7 @@ char * buf;
#endif /* !defined WRONG */
/*
-** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
+** Simplified normalize logic courtesy Paul Eggert.
*/
static int
@@ -1443,6 +1775,18 @@ int delta;
}
static int
+long_increment_overflow(number, delta)
+long * number;
+int delta;
+{
+ long number0;
+
+ number0 = *number;
+ *number += delta;
+ return (*number < number0) != (delta < 0);
+}
+
+static int
normalize_overflow(tensptr, unitsptr, base)
int * const tensptr;
int * const unitsptr;
@@ -1458,6 +1802,21 @@ const int base;
}
static int
+long_normalize_overflow(tensptr, unitsptr, base)
+long * const tensptr;
+int * const unitsptr;
+const int base;
+{
+ register int tensdelta;
+
+ tensdelta = (*unitsptr >= 0) ?
+ (*unitsptr / base) :
+ (-1 - (-1 - *unitsptr) / base);
+ *unitsptr -= tensdelta * base;
+ return long_increment_overflow(tensptr, tensdelta);
+}
+
+static int
tmcomp(atmp, btmp)
const struct tm * const atmp;
const struct tm * const btmp;
@@ -1476,19 +1835,22 @@ const struct tm * const btmp;
static time_t
time2sub(tmp, funcp, offset, okayp, do_norm_secs)
struct tm * const tmp;
-void (* const funcp)(const time_t*, long, struct tm*);
+struct tm * (* const funcp)(const time_t*, long, struct tm*);
const long offset;
int * const okayp;
const int do_norm_secs;
{
const struct state * sp;
int dir;
- int bits;
- int i, j ;
+ int i, j;
int saved_seconds;
- time_t newt;
- time_t t;
- struct tm yourtm, mytm;
+ long li;
+ time_t lo;
+ time_t hi;
+ long y;
+ time_t newt;
+ time_t t;
+ struct tm yourtm, mytm;
*okayp = FALSE;
yourtm = *tmp;
@@ -1501,45 +1863,49 @@ const int do_norm_secs;
return WRONG;
if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
return WRONG;
- if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
+ y = yourtm.tm_year;
+ if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
return WRONG;
/*
- ** Turn yourtm.tm_year into an actual year number for now.
+ ** Turn y into an actual year number for now.
** It is converted back to an offset from TM_YEAR_BASE later.
*/
- if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
+ if (long_increment_overflow(&y, TM_YEAR_BASE))
return WRONG;
while (yourtm.tm_mday <= 0) {
- if (increment_overflow(&yourtm.tm_year, -1))
+ if (long_increment_overflow(&y, -1))
return WRONG;
- i = yourtm.tm_year + (1 < yourtm.tm_mon);
- yourtm.tm_mday += year_lengths[isleap(i)];
+ li = y + (1 < yourtm.tm_mon);
+ yourtm.tm_mday += year_lengths[isleap(li)];
}
while (yourtm.tm_mday > DAYSPERLYEAR) {
- i = yourtm.tm_year + (1 < yourtm.tm_mon);
- yourtm.tm_mday -= year_lengths[isleap(i)];
- if (increment_overflow(&yourtm.tm_year, 1))
+ li = y + (1 < yourtm.tm_mon);
+ yourtm.tm_mday -= year_lengths[isleap(li)];
+ if (long_increment_overflow(&y, 1))
return WRONG;
}
for ( ; ; ) {
- i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
+ i = mon_lengths[isleap(y)][yourtm.tm_mon];
if (yourtm.tm_mday <= i)
break;
yourtm.tm_mday -= i;
if (++yourtm.tm_mon >= MONSPERYEAR) {
yourtm.tm_mon = 0;
- if (increment_overflow(&yourtm.tm_year, 1))
+ if (long_increment_overflow(&y, 1))
return WRONG;
}
}
- if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
+ if (long_increment_overflow(&y, -TM_YEAR_BASE))
+ return WRONG;
+ yourtm.tm_year = y;
+ if (yourtm.tm_year != y)
return WRONG;
/* Don't go below 1900 for POLA */
if (yourtm.tm_year < 0)
return WRONG;
if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
saved_seconds = 0;
- else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
+ else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
/*
** We can't set tm_sec to 0, because that might push the
** time below the minimum representable time.
@@ -1557,33 +1923,53 @@ const int do_norm_secs;
yourtm.tm_sec = 0;
}
/*
- ** Divide the search space in half
- ** (this works whether time_t is signed or unsigned).
+ ** Do a binary search (this works whatever time_t's type is).
*/
- bits = TYPE_BIT(time_t) - 1;
- /*
- ** 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 > 48)
- bits = 48;
- /*
- ** If time_t is signed, then 0 is just above the median,
- ** assuming two's complement arithmetic.
- ** If time_t is unsigned, then (1 << bits) is just above the median.
- */
- t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
+ if (!TYPE_SIGNED(time_t)) {
+ lo = 0;
+ hi = lo - 1;
+ } else if (!TYPE_INTEGRAL(time_t)) {
+ if (sizeof(time_t) > sizeof(float))
+ hi = (time_t) DBL_MAX;
+ else hi = (time_t) FLT_MAX;
+ lo = -hi;
+ } else {
+ lo = 1;
+ for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
+ lo *= 2;
+ hi = -(lo + 1);
+ }
for ( ; ; ) {
- (*funcp)(&t, offset, &mytm);
- dir = tmcomp(&mytm, &yourtm);
+ t = lo / 2 + hi / 2;
+ if (t < lo)
+ t = lo;
+ else if (t > hi)
+ t = hi;
+ if ((*funcp)(&t, offset, &mytm) == NULL) {
+ /*
+ ** Assume that t is too extreme to be represented in
+ ** a struct tm; arrange things so that it is less
+ ** extreme on the next pass.
+ */
+ dir = (t > 0) ? 1 : -1;
+ } else dir = tmcomp(&mytm, &yourtm);
if (dir != 0) {
- if (bits-- < 0)
+ if (t == lo) {
+ ++t;
+ if (t <= lo)
+ return WRONG;
+ ++lo;
+ } else if (t == hi) {
+ --t;
+ if (t >= hi)
+ return WRONG;
+ --hi;
+ }
+ if (lo > hi)
return WRONG;
- if (bits < 0)
- --t; /* may be needed if new t is minimal */
- else if (dir > 0)
- t -= ((time_t) 1) << bits;
- else t += ((time_t) 1) << bits;
+ if (dir > 0)
+ hi = t;
+ else lo = t;
continue;
}
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
@@ -1594,7 +1980,8 @@ const int do_norm_secs;
** It's okay to guess wrong since the guess
** gets checked.
*/
- sp = (funcp == localsub) ? lclptr : gmtptr;
+ sp = (const struct state *)
+ ((funcp == localsub) ? lclptr : gmtptr);
#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
@@ -1607,7 +1994,8 @@ const int do_norm_secs;
continue;
newt = t + sp->ttis[j].tt_gmtoff -
sp->ttis[i].tt_gmtoff;
- (*funcp)(&newt, offset, &mytm);
+ if ((*funcp)(&newt, offset, &mytm) == NULL)
+ continue;
if (tmcomp(&mytm, &yourtm) != 0)
continue;
if (mytm.tm_isdst != yourtm.tm_isdst)
@@ -1626,15 +2014,15 @@ label:
if ((newt < t) != (saved_seconds < 0))
return WRONG;
t = newt;
- (*funcp)(&t, offset, tmp);
- *okayp = TRUE;
+ if ((*funcp)(&t, offset, tmp))
+ *okayp = TRUE;
return t;
}
static time_t
time2(tmp, funcp, offset, okayp)
struct tm * const tmp;
-void (* const funcp)(const time_t*, long, struct tm*);
+struct tm * (* const funcp)(const time_t*, long, struct tm*);
const long offset;
int * const okayp;
{
@@ -1652,7 +2040,7 @@ int * const okayp;
static time_t
time1(tmp, funcp, offset)
struct tm * const tmp;
-void (* const funcp)(const time_t *, long, struct tm *);
+struct tm * (* const funcp)(const time_t *, long, struct tm *);
const long offset;
{
time_t t;
@@ -1670,7 +2058,7 @@ const long offset;
t = time2(tmp, funcp, offset, &okay);
#ifdef PCTS
/*
- ** PCTS code courtesy Grant Sullivan (grant@osf.org).
+ ** PCTS code courtesy Grant Sullivan.
*/
if (okay)
return t;
@@ -1687,7 +2075,7 @@ const long offset;
** We try to divine the type they started from and adjust to the
** type they need.
*/
- sp = (funcp == localsub) ? lclptr : gmtptr;
+ sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr);
#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
@@ -1833,7 +2221,7 @@ time_t t;
tzset();
/*
** For a positive leap second hit, the result
- ** is not unique. For a negative leap second
+ ** is not unique. For a negative leap second
** hit, the corresponding time doesn't exist,
** so we return an adjacent second.
*/
diff --git a/lib/libc/stdtime/private.h b/lib/libc/stdtime/private.h
index a3c7778..dda5bef 100644
--- a/lib/libc/stdtime/private.h
+++ b/lib/libc/stdtime/private.h
@@ -4,7 +4,7 @@
/*
** 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$
*/
@@ -37,11 +37,13 @@
#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'.
@@ -63,10 +65,6 @@ static char privatehid[] = "@(#)private.h 7.53";
#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 */
@@ -104,17 +102,17 @@ static char privatehid[] = "@(#)private.h 7.53";
#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)
@@ -123,55 +121,84 @@ static char privatehid[] = "@(#)private.h 7.53";
#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.
@@ -193,6 +220,24 @@ char * scheck(const char *string, const char *format);
#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.
@@ -201,7 +246,8 @@ char * scheck(const char *string, const char *format);
** 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 */
/*
@@ -235,11 +281,11 @@ char * scheck(const char *string, const char *format);
*/
#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
@@ -252,6 +298,26 @@ char * scheck(const char *string, const char *format);
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.
diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c
index b0ba1ff..dac910b 100644
--- a/lib/libc/stdtime/strftime.c
+++ b/lib/libc/stdtime/strftime.c
@@ -7,7 +7,7 @@
* 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
@@ -17,7 +17,7 @@
#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".
@@ -42,10 +42,9 @@ __FBSDID("$FreeBSD$");
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[];
@@ -53,13 +52,12 @@ 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_DEFAULT 0
#define PAD_LESS 1
#define PAD_SPACE 2
#define PAD_ZERO 3
@@ -67,7 +65,7 @@ extern char * tzname[];
static const char* fmt_padding[][4] = {
/* DEFAULT, LESS, SPACE, ZERO */
#define PAD_FMT_MONTHDAY 0
-#define PAD_FMT_HMS 0
+#define PAD_FMT_HMS 0
#define PAD_FMT_CENTURY 0
#define PAD_FMT_SHORTYEAR 0
#define PAD_FMT_MONTH 0
@@ -170,8 +168,8 @@ label:
** something completely different.
** (ado, 1993-05-24)
*/
- pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
- fmt_padding[PAD_FMT_CENTURY][PadIndex], pt, ptlim);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+ pt, ptlim);
continue;
case 'c':
{
@@ -240,7 +238,7 @@ label:
** 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)
*/
@@ -261,7 +259,7 @@ label:
** _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)
*/
@@ -340,7 +338,7 @@ label:
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)
@@ -353,17 +351,19 @@ label:
** 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 ( ; ; ) {
@@ -371,7 +371,7 @@ label:
int bot;
int top;
- len = isleap(year) ?
+ len = isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
/*
@@ -390,7 +390,7 @@ label:
top += DAYSPERWEEK;
top += len;
if (yday >= top) {
- ++year;
+ ++base;
w = 1;
break;
}
@@ -399,26 +399,26 @@ label:
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, fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],
pt, ptlim);
else if (*format == 'g') {
*warnp = IN_ALL;
- pt = _conv(year % 100, fmt_padding[PAD_FMT_SHORTYEAR][PadIndex],
+ pt = _yconv(year, base, 0, 1,
pt, ptlim);
- } else pt = _conv(year, fmt_padding[PAD_FMT_YEAR][PadIndex],
+ } else pt = _yconv(year, base, 1, 1,
pt, ptlim);
}
continue;
@@ -456,12 +456,11 @@ label:
continue;
case 'y':
*warnp = IN_ALL;
- pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
- fmt_padding[PAD_FMT_SHORTYEAR][PadIndex], 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,
- fmt_padding[PAD_FMT_YEAR][PadIndex],
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
pt, ptlim);
continue;
case 'Z':
@@ -492,12 +491,12 @@ label:
/*
** 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
@@ -526,8 +525,10 @@ label:
diff = -diff;
} else sign = "+";
pt = _add(sign, pt, ptlim);
- diff /= 60;
- pt = _conv((diff/60)*100 + diff%60,
+ diff /= SECSPERMIN;
+ diff = (diff / MINSPERHOUR) * 100 +
+ (diff % MINSPERHOUR);
+ pt = _conv(diff,
fmt_padding[PAD_FMT_YEAR][PadIndex], pt, ptlim);
}
continue;
@@ -553,7 +554,7 @@ 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:
@@ -590,3 +591,44 @@ const char * const ptlim;
++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;
+}
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index ddf6b57..51d41ed 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -514,6 +514,34 @@ label:
}
}
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;
diff --git a/lib/libc/stdtime/time2posix.3 b/lib/libc/stdtime/time2posix.3
index ce9c68d..1a1ec95 100644
--- a/lib/libc/stdtime/time2posix.3
+++ b/lib/libc/stdtime/time2posix.3
@@ -118,3 +118,6 @@ degenerate to the identity function.
.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.
diff --git a/lib/libc/stdtime/tzfile.5 b/lib/libc/stdtime/tzfile.5
index cc7e659..15625d2 100644
--- a/lib/libc/stdtime/tzfile.5
+++ b/lib/libc/stdtime/tzfile.5
@@ -14,7 +14,9 @@ begin with the magic characters
.Dq Li TZif
to identify them as
time zone information files,
-followed by sixteen bytes reserved for future use,
+followed by a character identifying the version of the file's format
+(as of 2005, either an ASCII NUL or a '2')
+followed by fifteen bytes containing zeroes reserved for future use,
followed by four four-byte values
written in a ``standard'' byte order
(the high-order byte of the value is written first).
@@ -56,7 +58,9 @@ each one tells which of the different types of ``local time'' types
described in the file is associated with the same-indexed transition time.
These values serve as indices into an array of
.Fa ttinfo
-structures that appears next in the file;
+structures (with
+.Fa tzh_typecnt
+entries) that appears next in the file;
these structures are defined as follows:
.Pp
.Bd -literal -offset indent
@@ -129,10 +133,20 @@ if either
.Li tzh_timecnt
is zero or the time argument is less than the first transition time recorded
in the file.
+.Pp
+For version-2-format time zone files,
+the above header and data is followed by a second header and data,
+identical in format except that eight bytes are used for each
+transition time or leap second time.
+After the second header and data comes a newline-enclosed,
+POSIX-TZ-environment-variable-style string for use in handling instants
+after the last transition time stored in the file
+(with nothing between the newlines if there is no POSIX representation for
+such instants).
.Sh SEE ALSO
.Xr ctime 3 ,
.Xr time2posix 3 ,
.Xr zic 8
-.\" @(#)tzfile.5 7.2
+.\" @(#)tzfile.5 8.2
.\" 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.
diff --git a/lib/libc/stdtime/tzfile.h b/lib/libc/stdtime/tzfile.h
index 89c5694..85b945e 100644
--- a/lib/libc/stdtime/tzfile.h
+++ b/lib/libc/stdtime/tzfile.h
@@ -4,7 +4,7 @@
/*
** 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$
*/
@@ -24,7 +24,7 @@
#ifndef lint
#ifndef NOID
/*
-static char tzfilehid[] = "@(#)tzfile.h 7.14";
+static char tzfilehid[] = "@(#)tzfile.h 8.1";
*/
#endif /* !defined NOID */
#endif /* !defined lint */
@@ -52,8 +52,9 @@ static char tzfilehid[] = "@(#)tzfile.h 7.14";
#define TZ_MAGIC "TZif"
struct tzhead {
- char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_reserved[16]; /* reserved for future use */
+ char tzh_magic[4]; /* TZ_MAGIC */
+ char tzh_version[1]; /* '\0' or '2' as of 2005 */
+ char tzh_reserved[15]; /* reserved--must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
@@ -88,18 +89,22 @@ struct tzhead {
*/
/*
+** If tzh_version is '2' or greater, the above is followed by a second instance
+** of tzhead and a second instance of the data in which each coded transition
+** time uses 8 rather than 4 chars,
+** then a POSIX-TZ-environment-variable-style string for use in handling
+** instants after the last transition time stored in the file
+** (with nothing between the newlines if there is no POSIX representation for
+** such instants).
+*/
+
+/*
** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
-/*
-** The TZ_MAX_TIMES value below is enough to handle a bit more than a
-** year's worth of solar time (corrected daily to the nearest second) or
-** 138 years of Pacific Presidential Election time
-** (where there are three time zone transitions every fourth year).
-*/
-#define TZ_MAX_TIMES 370
+#define TZ_MAX_TIMES 1200
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
@@ -109,7 +114,7 @@ struct tzhead {
#ifdef NOSOLAR
/*
** Must be at least 14 for Europe/Riga as of Jan 12 1995,
-** as noted by Earl Chew <earl@hpato.aus.hp.com>.
+** as noted by Earl Chew.
*/
#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
#endif /* !defined NOSOLAR */
@@ -160,33 +165,20 @@ struct tzhead {
#define EPOCH_YEAR 1970
#define EPOCH_WDAY TM_THURSDAY
-/*
-** Accurate only for the past couple of centuries;
-** that will probably do.
-*/
-
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
-#ifndef USG
-
/*
-** Use of the underscored variants may cause problems if you move your code to
-** certain System-V-based systems; for maximum portability, use the
-** underscore-free variants. The underscored variants are provided for
-** backward compatibility only; they may disappear from future versions of
-** this file.
+** 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 SECS_PER_MIN SECSPERMIN
-#define MINS_PER_HOUR MINSPERHOUR
-#define HOURS_PER_DAY HOURSPERDAY
-#define DAYS_PER_WEEK DAYSPERWEEK
-#define DAYS_PER_NYEAR DAYSPERNYEAR
-#define DAYS_PER_LYEAR DAYSPERLYEAR
-#define SECS_PER_HOUR SECSPERHOUR
-#define SECS_PER_DAY SECSPERDAY
-#define MONS_PER_YEAR MONSPERYEAR
-
-#endif /* !defined USG */
+#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined TZFILE_H */
diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc
index dffaf87..b0a1899 100644
--- a/lib/libc/string/Makefile.inc
+++ b/lib/libc/string/Makefile.inc
@@ -8,14 +8,16 @@ CFLAGS+= -I${.CURDIR}/locale
# machine-independent string sources
MISRCS+=bcmp.c bcopy.c bzero.c ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \
index.c memccpy.c memchr.c memrchr.c memcmp.c \
- memcpy.c memmem.c memmove.c memset.c rindex.c stpcpy.c strcasecmp.c \
+ memcpy.c memmem.c memmove.c memset.c rindex.c \
+ stpcpy.c stpncpy.c strcasecmp.c \
strcat.c strcasestr.c strchr.c strcmp.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 strndup.c strnstr.c \
+ strncmp.c strncpy.c strndup.c strnlen.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 wcsdup.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 wcscat.c \
+ wcschr.c wcscmp.c wcscoll.c wcscpy.c wcscspn.c wcsdup.c \
+ wcslcat.c wcslcpy.c wcslen.c wcsncasecmp.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
@@ -47,6 +49,7 @@ MLINKS+=strcat.3 strncat.3
MLINKS+=strchr.3 strrchr.3
MLINKS+=strcmp.3 strncmp.3
MLINKS+=strcpy.3 stpcpy.3 \
+ strcpy.3 stpncpy.3 \
strcpy.3 strncpy.3
MLINKS+=strdup.3 strndup.3
MLINKS+=strerror.3 perror.3 \
@@ -54,10 +57,14 @@ MLINKS+=strerror.3 perror.3 \
strerror.3 sys_errlist.3 \
strerror.3 sys_nerr.3
MLINKS+=strlcpy.3 strlcat.3
+MLINKS+=strlen.3 strnlen.3
MLINKS+=strstr.3 strcasestr.3 \
strstr.3 strnstr.3
MLINKS+=strtok.3 strtok_r.3
-MLINKS+=wmemchr.3 wcscat.3 \
+MLINKS+=wmemchr.3 wcpcpy.3 \
+ wmemchr.3 wcpncpy.3 \
+ wmemchr.3 wcscasecmp.3 \
+ wmemchr.3 wcscat.3 \
wmemchr.3 wcschr.3 \
wmemchr.3 wcscmp.3 \
wmemchr.3 wcscpy.3 \
@@ -66,9 +73,11 @@ MLINKS+=wmemchr.3 wcscat.3 \
wmemchr.3 wcslcat.3 \
wmemchr.3 wcslcpy.3 \
wmemchr.3 wcslen.3 \
+ wmemchr.3 wcsncasecmp.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 \
diff --git a/lib/libc/string/Symbol.map b/lib/libc/string/Symbol.map
index c69f0b5..19f3382 100644
--- a/lib/libc/string/Symbol.map
+++ b/lib/libc/string/Symbol.map
@@ -81,7 +81,14 @@ FBSD_1.1 {
ffsll;
flsll;
memrchr;
+ stpncpy;
strndup;
+ strnlen;
+ wcpcpy;
+ wcpncpy;
+ wcscasecmp;
+ wcsncasecmp;
+ wcsnlen;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/string/memchr.3 b/lib/libc/string/memchr.3
index 5cbaf6c..ae883bf 100644
--- a/lib/libc/string/memchr.3
+++ b/lib/libc/string/memchr.3
@@ -83,7 +83,8 @@ bytes.
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wmemchr 3
.Sh STANDARDS
The
.Fn memchr
@@ -99,6 +100,6 @@ The
.Fn memrchr
function first appeared in GNU libc 2.1.91, this implementation
first appeared in
-.Fx 8.0 ,
+.Fx 6.4 ,
coming from
.Ox 4.3 .
diff --git a/lib/libc/string/memcmp.3 b/lib/libc/string/memcmp.3
index a7be20b..507b930 100644
--- a/lib/libc/string/memcmp.3
+++ b/lib/libc/string/memcmp.3
@@ -72,7 +72,8 @@ Zero-length strings are always identical.
.Xr strcasecmp 3 ,
.Xr strcmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wmemcmp 3
.Sh STANDARDS
The
.Fn memcmp
diff --git a/lib/libc/string/memcpy.3 b/lib/libc/string/memcpy.3
index 80a8629..3f2e2dd 100644
--- a/lib/libc/string/memcpy.3
+++ b/lib/libc/string/memcpy.3
@@ -64,7 +64,8 @@ returns the original value of
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memmove 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemcpy 3
.Sh STANDARDS
The
.Fn memcpy
diff --git a/lib/libc/string/memmove.3 b/lib/libc/string/memmove.3
index 19c2987..8a1d52b 100644
--- a/lib/libc/string/memmove.3
+++ b/lib/libc/string/memmove.3
@@ -65,7 +65,8 @@ function returns the original value of
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memcpy 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemmove 3
.Sh STANDARDS
The
.Fn memmove
diff --git a/lib/libc/string/memset.3 b/lib/libc/string/memset.3
index 58877f0..1dc287d 100644
--- a/lib/libc/string/memset.3
+++ b/lib/libc/string/memset.3
@@ -60,7 +60,8 @@ The
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
diff --git a/lib/libc/string/stpcpy.c b/lib/libc/string/stpcpy.c
index 0bee746..beb1159 100644
--- a/lib/libc/string/stpcpy.c
+++ b/lib/libc/string/stpcpy.c
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
char *
-stpcpy(char * to, const char * from)
+stpcpy(char * __restrict to, const char * __restrict from)
{
for (; (*to = *from); ++from, ++to);
diff --git a/lib/libc/string/stpncpy.c b/lib/libc/string/stpncpy.c
new file mode 100644
index 0000000..df70dc6
--- /dev/null
+++ b/lib/libc/string/stpncpy.c
@@ -0,0 +1,45 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/string/strcasecmp.3 b/lib/libc/string/strcasecmp.3
index f94abec..2b2ef3e 100644
--- a/lib/libc/string/strcasecmp.3
+++ b/lib/libc/string/strcasecmp.3
@@ -83,7 +83,8 @@ is greater than
.Xr strcmp 3 ,
.Xr strcoll 3 ,
.Xr strxfrm 3 ,
-.Xr tolower 3
+.Xr tolower 3 ,
+.Xr wcscasecmp 3
.Sh HISTORY
The
.Fn strcasecmp
diff --git a/lib/libc/string/strcat.3 b/lib/libc/string/strcat.3
index e24ed9d..0290994 100644
--- a/lib/libc/string/strcat.3
+++ b/lib/libc/string/strcat.3
@@ -144,7 +144,8 @@ foo(const char *arbitrary_string)
.Xr memmove 3 ,
.Xr strcpy 3 ,
.Xr strlcat 3 ,
-.Xr strlcpy 3
+.Xr strlcpy 3 ,
+.Xr wcscat 3
.Sh STANDARDS
The
.Fn strcat
diff --git a/lib/libc/string/strchr.3 b/lib/libc/string/strchr.3
index 7c867a3..984eb06 100644
--- a/lib/libc/string/strchr.3
+++ b/lib/libc/string/strchr.3
@@ -85,7 +85,8 @@ if the character does not appear in the string.
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcschr 3
.Sh STANDARDS
The functions
.Fn strchr
diff --git a/lib/libc/string/strcmp.3 b/lib/libc/string/strcmp.3
index 7c5877b..1e13ed8 100644
--- a/lib/libc/string/strcmp.3
+++ b/lib/libc/string/strcmp.3
@@ -89,7 +89,8 @@ is greater than
.Xr memcmp 3 ,
.Xr strcasecmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wcscmp 3
.Sh STANDARDS
The
.Fn strcmp
diff --git a/lib/libc/string/strcpy.3 b/lib/libc/string/strcpy.3
index 8284753..157abcc 100644
--- a/lib/libc/string/strcpy.3
+++ b/lib/libc/string/strcpy.3
@@ -32,18 +32,20 @@
.\" @(#)strcpy.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.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 *
@@ -63,8 +65,10 @@ to
character.)
.Pp
The
+.Fn stpncpy
+and
.Fn strncpy
-function copies at most
+functions copy at most
.Fa len
characters from
.Fa src
@@ -95,10 +99,21 @@ return
.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
@@ -174,7 +189,8 @@ and
.Xr memccpy 3 ,
.Xr memcpy 3 ,
.Xr memmove 3 ,
-.Xr strlcpy 3
+.Xr strlcpy 3 ,
+.Xr wcscpy 3
.Sh STANDARDS
The
.Fn strcpy
@@ -185,14 +201,16 @@ conform to
.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 .
diff --git a/lib/libc/string/strdup.3 b/lib/libc/string/strdup.3
index 080f4e7..04a2816 100644
--- a/lib/libc/string/strdup.3
+++ b/lib/libc/string/strdup.3
@@ -71,7 +71,8 @@ always
terminating the copied string.
.Sh SEE ALSO
.Xr free 3 ,
-.Xr malloc 3
+.Xr malloc 3 ,
+.Xr wcsdup 3
.Sh HISTORY
The
.Fn strdup
@@ -80,4 +81,4 @@ function first appeared in
The
.Fn strndup
function was added in
-.Fx 8.0 .
+.Fx 7.2 .
diff --git a/lib/libc/string/strlcat.c b/lib/libc/string/strlcat.c
index feeac3b..2d13be7 100644
--- a/lib/libc/string/strlcat.c
+++ b/lib/libc/string/strlcat.c
@@ -30,7 +30,7 @@ __FBSDID("$FreeBSD$");
* If retval >= siz, truncation occurred.
*/
size_t
-strlcat(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;
diff --git a/lib/libc/string/strlcpy.3 b/lib/libc/string/strlcpy.3
index 88af06d..19d3621 100644
--- a/lib/libc/string/strlcpy.3
+++ b/lib/libc/string/strlcpy.3
@@ -39,9 +39,9 @@
.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
@@ -192,7 +192,8 @@ As a matter of fact, the first version of this manual page got it wrong.
.Sh SEE ALSO
.Xr snprintf 3 ,
.Xr strncat 3 ,
-.Xr strncpy 3
+.Xr strncpy 3 ,
+.Xr wcslcpy 3
.Sh HISTORY
The
.Fn strlcpy
diff --git a/lib/libc/string/strlcpy.c b/lib/libc/string/strlcpy.c
index 187bdb7..451b6df 100644
--- a/lib/libc/string/strlcpy.c
+++ b/lib/libc/string/strlcpy.c
@@ -28,7 +28,7 @@ __FBSDID("$FreeBSD$");
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
-strlcpy(char *dst, const char *src, size_t siz)
+strlcpy(char * __restrict dst, const char * __restrict src, size_t siz)
{
char *d = dst;
const char *s = src;
diff --git a/lib/libc/string/strlen.3 b/lib/libc/string/strlen.3
index 29c3515..bdbf4ff 100644
--- a/lib/libc/string/strlen.3
+++ b/lib/libc/string/strlen.3
@@ -32,11 +32,11 @@
.\" @(#)strlen.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.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
@@ -44,12 +44,22 @@
.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
@@ -59,11 +69,24 @@ the number of characters that precede the
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 .
diff --git a/lib/libc/string/strmode.3 b/lib/libc/string/strmode.3
index 89d0160..1a072d8 100644
--- a/lib/libc/string/strmode.3
+++ b/lib/libc/string/strmode.3
@@ -128,9 +128,7 @@ The file is executable or the directory is searchable.
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 ,
diff --git a/lib/libc/string/strmode.c b/lib/libc/string/strmode.c
index 57295d7..3aaa77e 100644
--- a/lib/libc/string/strmode.c
+++ b/lib/libc/string/strmode.c
@@ -143,6 +143,6 @@ strmode(/* mode_t */ int mode, char *p)
*p++ = 't';
break;
}
- *p++ = ' '; /* will be a '+' if ACL's implemented */
+ *p++ = ' ';
*p = '\0';
}
diff --git a/lib/libc/string/strnlen.c b/lib/libc/string/strnlen.c
new file mode 100644
index 0000000..f44151f
--- /dev/null
+++ b/lib/libc/string/strnlen.c
@@ -0,0 +1,42 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/string/strpbrk.3 b/lib/libc/string/strpbrk.3
index 0a16757..7ed0ec7 100644
--- a/lib/libc/string/strpbrk.3
+++ b/lib/libc/string/strpbrk.3
@@ -67,7 +67,8 @@ returns NULL.
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcspbrk 3
.Sh STANDARDS
The
.Fn strpbrk
diff --git a/lib/libc/string/strspn.3 b/lib/libc/string/strspn.3
index 6fc3280..72a1d32 100644
--- a/lib/libc/string/strspn.3
+++ b/lib/libc/string/strspn.3
@@ -74,7 +74,8 @@ returns the number of characters spanned.
.Xr strrchr 3 ,
.Xr strsep 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcsspn 3
.Sh STANDARDS
The
.Fn strspn
diff --git a/lib/libc/string/strstr.3 b/lib/libc/string/strstr.3
index 7468ccc..74ebdff 100644
--- a/lib/libc/string/strstr.3
+++ b/lib/libc/string/strstr.3
@@ -135,7 +135,8 @@ ptr = strnstr(largestring, smallstring, 4);
.Xr strrchr 3 ,
.Xr strsep 3 ,
.Xr strspn 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcsstr 3
.Sh STANDARDS
The
.Fn strstr
diff --git a/lib/libc/i386/stdlib/abs.S b/lib/libc/string/wcpcpy.c
index 236a631..df63d72 100644
--- a/lib/libc/i386/stdlib/abs.S
+++ b/lib/libc/string/wcpcpy.c
@@ -1,9 +1,8 @@
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
+/*
+ * 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
@@ -13,7 +12,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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
*
@@ -31,17 +30,17 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
- .text
- .asciz "@(#)abs.s 5.2 (Berkeley) 12/17/90"
+static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
-#include <machine/asm.h>
+#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <wchar.h>
+
+wchar_t *
+wcpcpy(wchar_t * __restrict to, const wchar_t * __restrict from)
+{
-ENTRY(abs)
- movl 4(%esp),%eax
- testl %eax,%eax
- jns 1f
- negl %eax
-1: ret
-END(abs)
+ for (; (*to = *from); ++from, ++to);
+ return(to);
+}
diff --git a/lib/libc/string/wcpncpy.c b/lib/libc/string/wcpncpy.c
new file mode 100644
index 0000000..87b361c
--- /dev/null
+++ b/lib/libc/string/wcpncpy.c
@@ -0,0 +1,45 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/string/wcscasecmp.c b/lib/libc/string/wcscasecmp.c
new file mode 100644
index 0000000..0143543
--- /dev/null
+++ b/lib/libc/string/wcscasecmp.c
@@ -0,0 +1,45 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/string/wcsncasecmp.c b/lib/libc/string/wcsncasecmp.c
new file mode 100644
index 0000000..a42d98c
--- /dev/null
+++ b/lib/libc/string/wcsncasecmp.c
@@ -0,0 +1,49 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/string/wcsnlen.c b/lib/libc/string/wcsnlen.c
new file mode 100644
index 0000000..f03cf76
--- /dev/null
+++ b/lib/libc/string/wcsnlen.c
@@ -0,0 +1,42 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/lib/libc/string/wmemchr.3 b/lib/libc/string/wmemchr.3
index 26ff1df..30fb091 100644
--- a/lib/libc/string/wmemchr.3
+++ b/lib/libc/string/wmemchr.3
@@ -35,7 +35,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 13, 2005
+.Dd March 4, 2009
.Dt WMEMCHR 3
.Os
.Sh NAME
@@ -44,6 +44,9 @@
.Nm wmemcpy ,
.Nm wmemmove ,
.Nm wmemset ,
+.Nm wcpcpy ,
+.Nm wcpncpy ,
+.Nm wcscasecmp ,
.Nm wcscat ,
.Nm wcschr ,
.Nm wcscmp ,
@@ -53,9 +56,11 @@
.Nm wcslcat ,
.Nm wcslcpy ,
.Nm wcslen ,
+.Nm wcsncasecmp ,
.Nm wcsncat ,
.Nm wcsncmp ,
.Nm wcsncpy ,
+.Nm wcsnlen ,
.Nm wcspbrk ,
.Nm wcsrchr ,
.Nm wcsspn ,
@@ -76,6 +81,12 @@
.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"
@@ -93,12 +104,16 @@
.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 *
@@ -119,6 +134,9 @@ counterpart, such as
.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 ,
@@ -131,6 +149,7 @@ counterpart, such as
.Xr strncat 3 ,
.Xr strncmp 3 ,
.Xr strncpy 3 ,
+.Xr strnlen 3 ,
.Xr strpbrk 3 ,
.Xr strrchr 3 ,
.Xr strspn 3 ,
@@ -139,8 +158,17 @@ counterpart, such as
These functions conform to
.St -isoC-99 ,
with the exception of
+.Fn wcpcpy ,
+.Fn wcpncpy ,
+.Fn wcscasecmp ,
.Fn wcsdup ,
-.Fn wcslcat ,
+.Fn wcsncasecmp ,
+and
+.Fn wcsnlen ,
+which conform to
+.St -p1003.1-2008 ;
+and
+.Fn wcslcat
and
.Fn wcslcpy ,
which are extensions.
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index f84ce13..1e6059d 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -53,17 +53,19 @@ SYM_MAPS+= ${.CURDIR}/sys/Symbol.map
CLEANFILES+= ${SASM} ${SPSEUDO}
${SASM}:
- printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' > ${.TARGET}
+ printf '#include "compat.h"\n' > ${.TARGET}
+ printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' >> ${.TARGET}
${SPSEUDO}:
+ printf '#include "compat.h"\n' > ${.TARGET}
printf '#include "SYS.h"\nPSEUDO(${.PREFIX:S/_//})\n' \
- > ${.TARGET}
+ >> ${.TARGET}
MAN+= abort2.2 accept.2 access.2 acct.2 adjtime.2 \
aio_cancel.2 aio_error.2 aio_read.2 aio_return.2 \
aio_suspend.2 aio_waitcomplete.2 aio_write.2 \
bind.2 brk.2 chdir.2 chflags.2 \
- chmod.2 chown.2 chroot.2 clock_gettime.2 close.2 \
+ chmod.2 chown.2 chroot.2 clock_gettime.2 close.2 closefrom.2 \
connect.2 cpuset.2 cpuset_getaffinity.2 dup.2 execve.2 _exit.2 \
extattr_get_file.2 fcntl.2 fhopen.2 flock.2 fork.2 fsync.2 \
getdirentries.2 getdtablesize.2 \
@@ -79,6 +81,7 @@ MAN+= abort2.2 accept.2 access.2 acct.2 adjtime.2 \
mlockall.2 mmap.2 modfind.2 modnext.2 modstat.2 mount.2 mprotect.2 \
mq_close.2 mq_getattr.2 mq_notify.2 mq_open.2 mq_receive.2 mq_send.2 \
mq_setattr.2 \
+ msgctl.2 msgget.2 msgrcv.2 msgsnd.2 \
msync.2 munmap.2 nanosleep.2 nfssvc.2 ntp_adjtime.2 open.2 \
pathconf.2 pipe.2 poll.2 posix_openpt.2 profil.2 ptrace.2 quotactl.2 \
read.2 readlink.2 reboot.2 recv.2 rename.2 revoke.2 rfork.2 rmdir.2 \
@@ -137,7 +140,10 @@ MLINKS+=getsockopt.2 setsockopt.2
MLINKS+=gettimeofday.2 settimeofday.2
MLINKS+=getuid.2 geteuid.2
MLINKS+=intro.2 errno.2
-MLINKS+=jail.2 jail_attach.2
+MLINKS+=jail.2 jail_attach.2 \
+ jail.2 jail_get.2 \
+ jail.2 jail_remove.2 \
+ jail.2 jail_set.2
MLINKS+=kldunload.2 kldunloadf.2
MLINKS+=kqueue.2 kevent.2
MLINKS+=link.2 linkat.2
@@ -154,6 +160,7 @@ MLINKS+=mq_send.2 mq_timedsend.2
MLINKS+=ntp_adjtime.2 ntp_gettime.2
MLINKS+=open.2 openat.2
MLINKS+=pathconf.2 fpathconf.2
+MLINKS+=pathconf.2 lpathconf.2
MLINKS+=read.2 pread.2 read.2 preadv.2 read.2 readv.2
MLINKS+=readlink.2 readlinkat.2
MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 02ed73b..56d8aaa 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -31,7 +31,6 @@ FBSD_1.0 {
__mac_set_file;
__mac_set_link;
__mac_set_proc;
- __semctl;
__setugid;
__syscall;
__sysctl;
@@ -184,7 +183,6 @@ FBSD_1.0 {
modstat;
mount;
mprotect;
- msgctl;
msgget;
msgrcv;
msgsnd;
@@ -196,7 +194,6 @@ FBSD_1.0 {
nanosleep;
netbsd_lchown;
netbsd_msync;
- nfsclnt;
nfssvc;
nfstat;
nlstat;
@@ -265,8 +262,9 @@ FBSD_1.0 {
setsockopt;
settimeofday;
setuid;
+ shm_open;
+ shm_unlink;
shmat;
- shmctl;
shmdt;
shmget;
shmsys;
@@ -284,7 +282,6 @@ FBSD_1.0 {
socket;
socketpair;
__stack_chk_fail;
- __stack_chk_fail_local;
__stack_chk_guard;
stat;
statfs;
@@ -331,6 +328,8 @@ FBSD_1.0 {
};
FBSD_1.1 {
+ __semctl;
+ closefrom;
cpuset;
cpuset_getid;
cpuset_setid;
@@ -342,14 +341,20 @@ FBSD_1.1 {
fexecve;
fstatat;
futimesat;
+ jail_get;
+ jail_set;
+ jail_remove;
linkat;
+ lpathconf;
mkdirat;
mkfifoat;
mknodat;
+ msgctl;
openat;
readlinkat;
renameat;
setfib;
+ shmctl;
symlinkat;
unlinkat;
};
@@ -467,6 +472,8 @@ FBSDprivate_1.0 {
__sys_clock_settime;
_close;
__sys_close;
+ _closefrom;
+ __sys_closefrom;
_connect;
__sys_connect;
_cpuset;
@@ -740,8 +747,6 @@ FBSDprivate_1.0 {
__sys_netbsd_lchown;
_netbsd_msync;
__sys_netbsd_msync;
- _nfsclnt;
- __sys_nfsclnt;
_nfssvc;
__sys_nfssvc;
_nfstat;
@@ -876,6 +881,10 @@ FBSDprivate_1.0 {
__sys_settimeofday;
_setuid;
__sys_setuid;
+ _shm_open;
+ __sys_shm_open;
+ _shm_unlink;
+ __sys_shm_unlink;
_shmat;
__sys_shmat;
_shmctl;
diff --git a/lib/libc/sys/bind.2 b/lib/libc/sys/bind.2
index bd51040..fecc5fa 100644
--- a/lib/libc/sys/bind.2
+++ b/lib/libc/sys/bind.2
@@ -82,6 +82,9 @@ The
.Fa s
argument
is not a valid descriptor.
+.It Bq Er EINVAL
+The socket is already bound to an address, and the protocol does not support
+binding to a new address; or the socket has been shut down.
.It Bq Er ENOTSOCK
The
.Fa s
diff --git a/lib/libc/sys/close.2 b/lib/libc/sys/close.2
index aef0379..524322b 100644
--- a/lib/libc/sys/close.2
+++ b/lib/libc/sys/close.2
@@ -120,6 +120,7 @@ before all pending data was delivered.
.El
.Sh SEE ALSO
.Xr accept 2 ,
+.Xr closefrom 2 ,
.Xr execve 2 ,
.Xr fcntl 2 ,
.Xr flock 2 ,
diff --git a/lib/libc/sys/closefrom.2 b/lib/libc/sys/closefrom.2
new file mode 100644
index 0000000..ffaa001
--- /dev/null
+++ b/lib/libc/sys/closefrom.2
@@ -0,0 +1,53 @@
+.\" Copyright (c) 2009 Advanced Computing Technologies LLC
+.\" Written by: John H. Baldwin <jhb@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$
+.\"
+.Dd June 12, 2009
+.Dt CLOSEFROM 2
+.Os
+.Sh NAME
+.Nm closefrom
+.Nd delete open file descriptors
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft void
+.Fn closefrom "int lowfd"
+.Sh DESCRIPTION
+The
+.Fn closefrom
+system call deletes all open file descriptors greater than or equal to
+.Fa lowfd
+from the per-process object reference table.
+Any errors encountered while closing file descriptors are ignored.
+.Sh SEE ALSO
+.Xr close 2
+.Sh HISTORY
+The
+.Fn closefrom
+function first appeared in
+.Fx 8.0 .
diff --git a/lib/libc/sys/execve.2 b/lib/libc/sys/execve.2
index 8cb25bc..cdd4197 100644
--- a/lib/libc/sys/execve.2
+++ b/lib/libc/sys/execve.2
@@ -220,13 +220,11 @@ Since execute permission is checked by
.Fn fexecve ,
the file descriptor
.Fa fd
-need not have been
-opened with the
+need not have been opened with the
.Dv O_EXEC
flag.
-However, if the file to be executed denies read and write
-permission for the process preparing to do the exec, the only way to
-provide the
+However, if the file to be executed denies read permission for the process
+preparing to do the exec, the only way to provide the
.Fa fd
to
.Fn fexecve
@@ -234,6 +232,7 @@ is to use the
.Dv O_EXEC
flag when opening
.Fa fd .
+Note that the file to be executed can not be open for writing.
.Sh RETURN VALUES
As the
.Fn execve
@@ -277,7 +276,7 @@ The new process file has the appropriate access
permission, but has an invalid magic number in its header.
.It Bq Er ETXTBSY
The new process file is a pure procedure (shared text)
-file that is currently open for writing or reading by some process.
+file that is currently open for writing by some process.
.It Bq Er ENOMEM
The new process requires more virtual memory than
is allowed by the imposed maximum
diff --git a/lib/libc/sys/getgroups.2 b/lib/libc/sys/getgroups.2
index 5eadfe1..4fd8fee 100644
--- a/lib/libc/sys/getgroups.2
+++ b/lib/libc/sys/getgroups.2
@@ -58,10 +58,7 @@ The
system call
returns the actual number of groups returned in
.Fa gidset .
-No more than
-.Dv NGROUPS_MAX
-will ever
-be returned.
+At least one and as many as {NGROUPS_MAX}+1 values may be returned.
If
.Fa gidsetlen
is zero,
@@ -92,6 +89,11 @@ an invalid address.
.Sh SEE ALSO
.Xr setgroups 2 ,
.Xr initgroups 3
+.Sh STANDARDS
+The
+.Fn getgroups
+system call conforms to
+.St -p1003.1-2008 .
.Sh HISTORY
The
.Fn getgroups
diff --git a/lib/libc/sys/getrlimit.2 b/lib/libc/sys/getrlimit.2
index d3550d2..48feea0 100644
--- a/lib/libc/sys/getrlimit.2
+++ b/lib/libc/sys/getrlimit.2
@@ -97,6 +97,15 @@ mbufs, that this user may hold at any time.
The maximum size (in bytes) of the stack segment for a process;
this defines how far a program's stack segment may be extended.
Stack extension is performed automatically by the system.
+.It Dv RLIMIT_SWAP
+The maximum size (in bytes) of the swap space that may be reserved or
+used by all of this user id's processes.
+This limit is enforced only if bit 1 of the
+.Va vm.overcommit
+sysctl is set.
+Please see
+.Xr tuning 7
+for a complete description of this sysctl.
.It Dv RLIMIT_NPTS
The maximum number of pseudo-terminals created by this user id.
.El
diff --git a/lib/libc/sys/getsockopt.2 b/lib/libc/sys/getsockopt.2
index 80dc4f0..d3472d0 100644
--- a/lib/libc/sys/getsockopt.2
+++ b/lib/libc/sys/getsockopt.2
@@ -139,6 +139,11 @@ argument, defined in
.In sys/time.h .
.Pp
The following options are recognized at the socket level.
+For protocol-specific options, see protocol manual pages,
+e.g.
+.Xr ip 4
+or
+.Xr tcp 4 .
Except as noted, each may be examined with
.Fn getsockopt
and set with
@@ -499,6 +504,10 @@ on a non-listening socket was attempted.
.Xr getprotoent 3 ,
.Xr mac 3 ,
.Xr sysctl 3 ,
+.Xr ip 4 ,
+.Xr ip6 4 ,
+.Xr sctp 4 ,
+.Xr tcp 4 ,
.Xr protocols 5 ,
.Xr sysctl 8 ,
.Xr accept_filter 9 ,
diff --git a/lib/libc/sys/intro.2 b/lib/libc/sys/intro.2
index 7338f8b..1c01c39 100644
--- a/lib/libc/sys/intro.2
+++ b/lib/libc/sys/intro.2
@@ -302,7 +302,7 @@ Internet protocols.
.It Er 48 EADDRINUSE Em "Address already in use" .
Only one usage of each address is normally permitted.
.Pp
-.It Er 49 EADDRNOTAVAIL Em "Cannot assign requested address" .
+.It Er 49 EADDRNOTAVAIL Em "Can't assign requested address" .
Normally results from an attempt to create a socket with an
address not on this machine.
.It Er 50 ENETDOWN Em "Network is down" .
@@ -335,7 +335,7 @@ when already connected.
An request to send or receive data was disallowed because
the socket was not connected and (when sending on a datagram socket)
no address was supplied.
-.It Er 58 ESHUTDOWN Em "Cannot send after socket shutdown" .
+.It Er 58 ESHUTDOWN Em "Can't send after socket shutdown" .
A request to send data was disallowed because the socket
had already been shut down with a previous
.Xr shutdown 2
diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2
index cdf89dc..2e14f0d 100644
--- a/lib/libc/sys/jail.2
+++ b/lib/libc/sys/jail.2
@@ -1,19 +1,40 @@
+.\" Copyright (c) 1999 Poul-Henning Kamp.
+.\" Copyright (c) 2009 James Gritton.
+.\" All rights reserved.
.\"
-.\" ----------------------------------------------------------------------------
-.\" "THE BEER-WARE LICENSE" (Revision 42):
-.\" <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
-.\" can do whatever you want with this stuff. If we meet some day, and you think
-.\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
-.\" ----------------------------------------------------------------------------
+.\" 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$
.\"
-.Dd January 6, 2009
+.Dd June 23, 2009
.Dt JAIL 2
.Os
.Sh NAME
-.Nm jail , jail_attach
-.Nd imprison current process and future descendants
+.Nm jail ,
+.Nm jail_get ,
+.Nm jail_set ,
+.Nm jail_remove ,
+.Nm jail_attach
+.Nd create and manage system jails
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -23,6 +44,13 @@
.Fn jail "struct jail *jail"
.Ft int
.Fn jail_attach "int jid"
+.Ft int
+.Fn jail_remove "int jid"
+.In sys/uio.h
+.Ft int
+.Fn jail_get "struct iovec *iov" "u_int niov" "int flags"
+.Ft int
+.Fn jail_set "struct iovec *iov" "u_int niov" "int flags"
.Sh DESCRIPTION
The
.Fn jail
@@ -78,20 +106,147 @@ pointers can be set to an arrays of IPv4 and IPv6 addresses to be assigned to
the prison, or NULL if none.
IPv4 addresses must be in network byte order.
.Pp
+This is equivalent to the
+.Fn jail_set
+system call (see below), with the parameters
+.Va path ,
+.Va host.hostname ,
+.Va name ,
+.Va ip4.addr ,
+and
+.Va ip6.addr ,
+and with the
+.Dv JAIL_ATTACH
+flag.
+.Pp
+The
+.Fn jail_set
+system call creates a new jail, or modifies an existing one, and optionally
+locks the current process in it.
+Jail parameters are passed as an array of name-value pairs in the array
+.Fa iov ,
+containing
+.Fa niov
+elements.
+Parameter names are a null-terminated string, and values may be strings,
+integers, or other arbitrary data.
+Some parameters are boolean, and do not have a value (their length is zero)
+but are set by the name alone with or without a
+.Dq no
+prefix, e.g.
+.Va persist
+or
+.Va nopersist .
+Any parameters not set will be given default values, generally based on
+the current environment.
+.Pp
+Jails have a set of core parameters, and modules can add their own jail
+parameters.
+The current set of available parameters, and their formats, can be
+retrieved via the
+.Va security.jail.param
+sysctl MIB entry.
+Notable parameters include those mentioned in the
+.Fn jail
+description above, as well as
+.Va jid
+and
+.Va name ,
+which identify the jail being created or modified.
+See
+.Xr jail 8
+for more information on the core jail parameters.
+.Pp
+The
+.Fa flags
+arguments consists of one or more of the following flags:
+.Bl -tag -width indent
+.It Dv JAIL_CREATE
+Create a new jail.
+If a
+.Va jid
+or
+.Va name
+parameters exists, they must not refer to an existing jail.
+.It Dv JAIL_UPDATE
+Modify an existing jail.
+One of the
+.Va jid
+or
+.Va name
+parameters must exist, and must refer to an existing jail.
+If both
+.Dv JAIL_CREATE
+and
+.Dv JAIL_UPDATE
+are set, a jail will be created if it does not yet exist, and modified if it
+does exist.
+.It Dv JAIL_ATTACH
+In addition to creating or modifying the jail, attach the current process to
+it, as with the
+.Fn jail_attach
+system call.
+.It Dv JAIL_DYING
+Allow setting a jail that is in the process of being removed.
+.El
+.Pp
+The
+.Fn jail_get
+system call retrieves jail parameters, using the same name-value list as
+.Fn jail_set
+in the
+.Fa iov
+and
+.Fa niov
+arguments.
+The jail to read can be specified by either
+.Va jid
+or
+.Va name
+by including those parameters in the list.
+If they are included but are not intended to be the search key, they
+should be cleared (zero and the empty string respectively).
+.Pp
+The special parameter
+.Va lastjid
+can be used to retrieve a list of all jails.
+It will fetch the jail with the jid above and closest to the passed value.
+The first jail (usually but not always jid 1) can be found by passing a
+.Va lastjid
+of zero.
+.Pp
+The
+.Fa flags
+arguments consists of one or more following flags:
+.Bl -tag -width indent
+.It Dv JAIL_DYING
+Allow getting a jail that is in the process of being removed.
+.El
+.Pp
The
.Fn jail_attach
system call attaches the current process to an existing jail,
identified by
.Fa jid .
+.Pp
+The
+.Fn jail_remove
+system call removes the jail identified by
+.Fa jid .
+It will kill all processes belonging to the jail, and remove any children
+of that jail.
.Sh RETURN VALUES
If successful,
-.Fn jail
-returns a non-negative integer, termed the jail identifier (JID).
-It returns \-1 on failure, and sets
+.Fn jail ,
+.Fn jail_set ,
+and
+.Fn jail_get
+return a non-negative integer, termed the jail identifier (JID).
+They return \-1 on failure, and set
.Va errno
to indicate the error.
.Pp
-.Rv -std jail_attach
+.Rv -std jail_attach jail_remove
.Sh PRISON?
Once a process has been put in a prison, it and its descendants cannot escape
the prison.
@@ -128,7 +283,7 @@ of the jail for the given address family.
It is possible to identify a process as jailed by examining
.Dq Li /proc/<pid>/status :
it will show a field near the end of the line, either as
-a single hyphen for a process at large, or the hostname currently
+a single hyphen for a process at large, or the name currently
set for the prison for jailed processes.
.Sh ERRORS
The
@@ -136,15 +291,127 @@ The
system call
will fail if:
.Bl -tag -width Er
+.It Bq Er EPERM
+This process is not allowed to create a jail, either because it is not
+the super-user, or because it would exceed the jail's
+.Va children.max
+limit.
+.It Bq Er EFAULT
+.Fa jail
+points to an address outside the allocated address space of the process.
.It Bq Er EINVAL
The version number of the argument is not correct.
.It Bq Er EAGAIN
No free JID could be found.
.El
.Pp
+The
+.Fn jail_set
+system call
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EPERM
+This process is not allowed to create a jail, either because it is not
+the super-user, or because it would exceed the jail's
+.Va children.max
+limit.
+.It Bq Er EPERM
+A jail parameter was set to a less restrictive value then the current
+environment.
+.It Bq Er EFAULT
+.Fa Iov ,
+or one of the addresses contained within it,
+points to an address outside the allocated address space of the process.
+.It Bq Er ENOENT
+The jail referred to by a
+.Va jid
+or
+.Va name
+parameter does not exist, and the
+.Dv JAIL_CREATE
+flag is not set.
+.It Bq Er ENOENT
+The jail referred to by a
+.Va jid
+is not accessible by the process, because the process is in a different
+jail.
+.It Bq Er EEXIST
+The jail referred to by a
+.Va jid
+or
+.Va name
+parameter exists, and the
+.Dv JAIL_UPDATE
+flag is not set.
+.It Bq Er EINVAL
+A supplied parameter is the wrong size.
+.It Bq Er EINVAL
+A supplied parameter is out of range.
+.It Bq Er EINVAL
+A supplied string parameter is not null-terminated.
+.It Bq Er EINVAL
+A supplied parameter name does not match any known parameters.
+.It Bq Er EINVAL
+One of the
+.Dv JAIL_CREATE
+or
+.Dv JAIL_UPDATE
+flags is not set.
+.It Bq Er ENAMETOOLONG
+A supplied string parameter is longer than allowed.
+.It Bq Er EAGAIN
+There are no jail IDs left.
+.El
+.Pp
+The
+.Fn jail_get
+system call
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+.Fa Iov ,
+or one of the addresses contained within it,
+points to an address outside the allocated address space of the process.
+.It Bq Er ENOENT
+The jail referred to by a
+.Va jid
+or
+.Va name
+parameter does not exist.
+.It Bq Er ENOENT
+The jail referred to by a
+.Va jid
+is not accessible by the process, because the process is in a different
+jail.
+.It Bq Er ENOENT
+The
+.Va lastjid
+parameter is greater than the highest current jail ID.
+.It Bq Er EINVAL
+A supplied parameter is the wrong size.
+.It Bq Er EINVAL
+A supplied parameter name does not match any known parameters.
+.El
+.Pp
+The
+.Fn jail_attach
+and
+.Fn jail_remove
+system calls
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The jail specified by
+.Fa jid
+does not exist.
+.El
+.Pp
Further
-.Fn jail
-calls
+.Fn jail ,
+.Fn jail_set ,
+and
+.Fn jail_attach
+call
.Xr chroot 2
internally, so it can fail for all the same reasons.
Please consult the
@@ -152,7 +419,8 @@ Please consult the
manual page for details.
.Sh SEE ALSO
.Xr chdir 2 ,
-.Xr chroot 2
+.Xr chroot 2 ,
+.Xr jail 8
.Sh HISTORY
The
.Fn jail
@@ -162,6 +430,13 @@ The
.Fn jail_attach
system call appeared in
.Fx 5.1 .
+The
+.Fn jail_set ,
+.Fn jail_get ,
+and
+.Fn jail_remove
+system calls appeared in
+.Fx 8.0 .
.Sh AUTHORS
The jail feature was written by
.An Poul-Henning Kamp
@@ -169,3 +444,5 @@ for R&D Associates
.Dq Li http://www.rndassociates.com/
who contributed it to
.Fx .
+.An James Gritton
+added the extensible jail parameters and hierarchical jails.
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index 119ff79..e899a1b 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 6, 2007
+.Dd September 15, 2009
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -201,11 +201,25 @@ Disable the event so
.Fn kevent
will not return it.
The filter itself is not disabled.
+.It EV_DISPATCH
+Disable the event source immediately after delivery of an event.
+See
+.Dv EV_DISABLE
+above.
.It EV_DELETE
Removes the event from the kqueue.
Events which are attached to
file descriptors are automatically deleted on the last close of
the descriptor.
+.It EV_RECEIPT
+This flag is useful for making bulk changes to a kqueue without draining
+any pending events.
+When passed as input, it forces
+.Dv EV_ERROR
+to always be returned.
+When a filter is successfully added the
+.Va data
+field will be zero.
.It EV_ONESHOT
Causes the event to return only the first occurrence of the filter
being triggered.
@@ -441,6 +455,44 @@ The link state is invalid.
On return,
.Va fflags
contains the events which triggered the filter.
+.It Dv EVFILT_USER
+Establishes a user event identified by
+.Va ident
+which is not assosicated with any kernel mechanism but is triggered by
+user level code.
+The lower 24 bits of the
+.Va fflags
+may be used for user defined flags and manipulated using the following:
+.Bl -tag -width XXNOTE_FFLAGSMASK
+.It Dv NOTE_FFNOP
+Ignore the input
+.Va fflags .
+.It Dv NOTE_FFAND
+Bitwise AND
+.Va fflags .
+.It Dv NOTE_FFOR
+Bitwise OR
+.Va fflags .
+.It Dv NOTE_COPY
+Copy
+.Va fflags .
+.It Dv NOTE_FFCTRLMASK
+Control mask for
+.Va fflags .
+.It Dv NOTE_FFLAGSMASK
+User defined flag mask for
+.Va fflags .
+.El
+.Pp
+A user event is triggered for output with the following:
+.Bl -tag -width XXNOTE_FFLAGSMASK
+.It Dv NOTE_TRIGGER
+Cause the event to be triggered.
+.El
+.Pp
+On return,
+.Va fflags
+contains the users defined flags in the lower 24 bits.
.El
.Sh RETURN VALUES
The
diff --git a/lib/libc/sys/link.2 b/lib/libc/sys/link.2
index 8c0a115..e1fc317 100644
--- a/lib/libc/sys/link.2
+++ b/lib/libc/sys/link.2
@@ -110,7 +110,7 @@ are constructed by a bitwise-inclusive OR of flags from the following
list, defined in
.In fcntl.h :
.Bl -tag -width indent
-.It Dv AT_SYMLINK_NOFOLLOW
+.It Dv AT_SYMLINK_FOLLOW
If
.Fa name1
names a symbolic link, a new link for the target of the symbolic link is
diff --git a/lib/libc/sys/mmap.2 b/lib/libc/sys/mmap.2
index 196d6ae..e632748 100644
--- a/lib/libc/sys/mmap.2
+++ b/lib/libc/sys/mmap.2
@@ -28,7 +28,7 @@
.\" @(#)mmap.2 8.4 (Berkeley) 5/11/95
.\" $FreeBSD$
.\"
-.Dd October 24, 2008
+.Dd July 26, 2009
.Dt MMAP 2
.Os
.Sh NAME
@@ -306,7 +306,7 @@ resides out of the valid address space for a user process.
The
.Fa len
argument
-was negative.
+was equal to zero.
.It Bq Er EINVAL
.Dv MAP_ANON
was specified and the
@@ -353,10 +353,3 @@ Larger files may be possible on 64 bit systems.
The previous documented limit of 2GB was a documentation bug.
That limit has not existed since
.Fx 2.2 .
-.Pp
-Note that an attempt to
-.Fn mmap
-zero bytes has no effect and succeeds, while an attempt to
-.Fn munmap
-zero bytes will return
-.Bq Er EINVAL .
diff --git a/lib/libc/gen/msgctl.3 b/lib/libc/sys/msgctl.2
index ddd827c..34c5263 100644
--- a/lib/libc/gen/msgctl.3
+++ b/lib/libc/sys/msgctl.2
@@ -31,8 +31,8 @@
.\"
.\" $FreeBSD$
.\"/
-.Dd April 3, 2008
-.Dt MSGCTL 3
+.Dd July 9, 2009
+.Dt MSGCTL 2
.Os
.Sh NAME
.Nm msgctl
@@ -71,12 +71,8 @@ struct msqid_ds {
pid_t msg_lspid; /* pid of last msgsnd() */
pid_t msg_lrpid; /* pid of last msgrcv() */
time_t msg_stime; /* time of last msgsnd() */
- long msg_pad1;
time_t msg_rtime; /* time of last msgrcv() */
- long msg_pad2;
time_t msg_ctime; /* time of last msgctl() */
- long msg_pad3;
- long msg_pad4[4];
};
.Ed
.Pp
@@ -89,11 +85,11 @@ structure is defined in
and looks like this:
.Bd -literal
struct ipc_perm {
- unsigned short cuid; /* creator user id */
- unsigned short cgid; /* creator group id */
- unsigned short uid; /* user id */
- unsigned short gid; /* group id */
- unsigned short mode; /* r/w permission */
+ uid_t cuid; /* creator user id */
+ gid_t cgid; /* creator group id */
+ uid_t uid; /* user id */
+ gid_t gid; /* group id */
+ mode_t mode; /* r/w permission */
unsigned short seq; /* sequence # (to generate unique ipcid) */
key_t key; /* user specified msg/sem/shm key */
};
@@ -148,9 +144,9 @@ values in the data structure associated with the queue can do this.
.El
.Pp
The permission to read from or write to a message queue (see
-.Xr msgsnd 3
+.Xr msgsnd 2
and
-.Xr msgrcv 3 )
+.Xr msgrcv 2 )
is determined by the
.Va msg_perm.mode
field in the same way as is
@@ -206,9 +202,9 @@ argument
specifies an invalid address.
.El
.Sh SEE ALSO
-.Xr msgget 3 ,
-.Xr msgrcv 3 ,
-.Xr msgsnd 3
+.Xr msgget 2 ,
+.Xr msgrcv 2 ,
+.Xr msgsnd 2
.Sh HISTORY
Message queues appeared in the first release of
.At V .
diff --git a/lib/libc/gen/msgget.3 b/lib/libc/sys/msgget.2
index e257c60..27e1766 100644
--- a/lib/libc/gen/msgget.3
+++ b/lib/libc/sys/msgget.2
@@ -31,8 +31,8 @@
.\" $FreeBSD$
.\"
.\"/
-.Dd August 17, 1995
-.Dt MSGGET 3
+.Dd July 9, 2009
+.Dt MSGGET 2
.Os
.Sh NAME
.Nm msgget
@@ -67,7 +67,7 @@ bit is set in
If a new message queue is created, the data structure associated with it (the
.Va msqid_ds
structure, see
-.Xr msgctl 3 )
+.Xr msgctl 2 )
is initialized as follows:
.Bl -bullet
.It
@@ -133,9 +133,9 @@ and no message queue associated with
was found.
.El
.Sh SEE ALSO
-.Xr msgctl 3 ,
-.Xr msgrcv 3 ,
-.Xr msgsnd 3
+.Xr msgctl 2 ,
+.Xr msgrcv 2 ,
+.Xr msgsnd 2
.Sh HISTORY
Message queues appeared in the first release of
.At V .
diff --git a/lib/libc/gen/msgrcv.3 b/lib/libc/sys/msgrcv.2
index e554dcd..917a953 100644
--- a/lib/libc/gen/msgrcv.3
+++ b/lib/libc/sys/msgrcv.2
@@ -31,8 +31,8 @@
.\" $FreeBSD$
.\"
.\"/
-.Dd June 15, 2005
-.Dt MSGRCV 3
+.Dd July 9, 2009
+.Dt MSGRCV 2
.Os
.Sh NAME
.Nm msgrcv
@@ -214,9 +214,9 @@ is set in
.Fa msgflg .
.El
.Sh SEE ALSO
-.Xr msgctl 3 ,
-.Xr msgget 3 ,
-.Xr msgsnd 3
+.Xr msgctl 2 ,
+.Xr msgget 2 ,
+.Xr msgsnd 2
.Sh HISTORY
Message queues appeared in the first release of
.At V .
diff --git a/lib/libc/gen/msgsnd.3 b/lib/libc/sys/msgsnd.2
index fc802b3..d6333bb 100644
--- a/lib/libc/gen/msgsnd.3
+++ b/lib/libc/sys/msgsnd.2
@@ -31,8 +31,8 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 12, 2006
-.Dt MSGSND 3
+.Dd July 9, 2009
+.Dt MSGSND 2
.Os
.Sh NAME
.Nm msgsnd
@@ -63,7 +63,7 @@ consist of the following members:
.Pp
.Va mtype
is an integer greater than 0 that can be used for selecting messages (see
-.Xr msgrcv 3 ) ,
+.Xr msgrcv 2 ) ,
.Va mtext
is an array of
.Fa msgsz
@@ -78,7 +78,7 @@ If the number of bytes already on the message queue plus
is bigger than the maximum number of bytes on the message queue
.Pf ( Va msg_qbytes ,
see
-.Xr msgctl 3 ) ,
+.Xr msgctl 2 ) ,
or the number of messages on all queues system-wide is already equal to
the system limit,
.Fa msgflg
diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2
index 8fc6d76..3a5979f 100644
--- a/lib/libc/sys/open.2
+++ b/lib/libc/sys/open.2
@@ -28,7 +28,7 @@
.\" @(#)open.2 8.2 (Berkeley) 11/16/93
.\" $FreeBSD$
.\"
-.Dd April 10, 2008
+.Dd February 28, 2009
.Dt OPEN 2
.Os
.Sh NAME
@@ -116,6 +116,7 @@ O_FSYNC synchronous writes
O_SYNC synchronous writes
O_NOFOLLOW do not follow symlinks
O_NOCTTY don't assign controlling terminal
+O_TTY_INIT restore default terminal attributes
.Ed
.Pp
Opening a file with
@@ -208,6 +209,19 @@ The
system call will not assign controlling terminals on
.Fx .
.Pp
+.Dv O_TTY_INIT
+may be used to ensure the OS restores the terminal attributes when
+initially opening a TTY.
+This is the default on
+.Fx ,
+but is present for
+.Tn POSIX
+compatibility.
+The initial call to
+.Fn open
+on a TTY will always restore default terminal attributes on
+.Fx .
+.Pp
If successful,
.Fn open
returns a non-negative integer, termed a file descriptor.
diff --git a/lib/libc/sys/pathconf.2 b/lib/libc/sys/pathconf.2
index 7a16a4d..495bc65 100644
--- a/lib/libc/sys/pathconf.2
+++ b/lib/libc/sys/pathconf.2
@@ -28,11 +28,12 @@
.\" @(#)pathconf.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd April 5, 2007
+.Dd July 7, 2009
.Dt PATHCONF 2
.Os
.Sh NAME
.Nm pathconf ,
+.Nm lpathconf ,
.Nm fpathconf
.Nd get configurable pathname variables
.Sh LIBRARY
@@ -42,10 +43,13 @@
.Ft long
.Fn pathconf "const char *path" "int name"
.Ft long
+.Fn lpathconf "const char *path" "int name"
+.Ft long
.Fn fpathconf "int fd" "int name"
.Sh DESCRIPTION
The
-.Fn pathconf
+.Fn pathconf ,
+.Fn lpathconf
and
.Fn fpathconf
system calls provide a method for applications to determine the current
@@ -53,7 +57,9 @@ value of a configurable system limit or option variable associated
with a pathname or file descriptor.
.Pp
For
-.Fn pathconf ,
+.Fn pathconf
+and
+.Fn lpathconf ,
the
.Fa path
argument is the name of a file or directory.
@@ -68,6 +74,18 @@ argument specifies the system variable to be queried.
Symbolic constants for each name value are found in the include file
.Li <unistd.h> .
.Pp
+The
+.Fn lpathconf
+system call is like
+.Fn pathconf
+except in the case where the named file is a symbolic link,
+in which case
+.Fn lpathconf
+returns information about the link,
+while
+.Fn pathconf
+returns information about the file the link references.
+.Pp
The available values are as follows:
.Pp
.Bl -tag -width 6n
@@ -133,6 +151,9 @@ Maximum number of bytes in a symbolic link.
.It Li _PC_ACL_EXTENDED
Returns 1 if an Access Control List (ACL) can be set on the specified
file, otherwise 0.
+.It Li _PC_ACL_NFS4
+Returns 1 if an NFSv4 ACLs can be set on the specified
+file, otherwise 0.
.It Li _PC_ACL_PATH_MAX
Maximum number of ACL entries per file.
.It Li _PC_CAP_PRESENT
@@ -236,3 +257,7 @@ and
.Fn fpathconf
system calls first appeared in
.Bx 4.4 .
+The
+.Fn lpathconf
+system call first appeared in
+.Fx 8.0 .
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index 44fc1ea..9d8f550 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd April 9, 2007
+.Dd March 27, 2009
.Dt PTRACE 2
.Os
.Sh NAME
@@ -77,7 +77,8 @@ special case noted below, all
.Fn ptrace
calls are made by the tracing process, and the
.Fa pid
-argument specifies the process ID of the traced process.
+argument specifies the process ID of the traced process
+or a corresponding thread ID.
The
.Fa request
argument
@@ -311,6 +312,21 @@ with the array size specified by
The return value from
.Fn ptrace
is the count of array entries filled in.
+.It PT_SETSTEP
+This request will turn on single stepping of the specified process.
+.It PT_CLEARSTEP
+This request will turn off single stepping of the specified process.
+.It PT_SUSPEND
+This request will suspend the specified thread.
+.It PT_RESUME
+This request will resume the specified thread.
+.It PT_TO_SCE
+This request will trace the specified process on each system call entry.
+.It PT_TO_SCX
+This request will trace the specified process on each system call exit.
+.It PT_SYSCALL
+This request will trace the specified process
+on each system call entry and exit.
.El
.Pp
Additionally, machine-specific requests can exist.
diff --git a/lib/libc/sys/revoke.2 b/lib/libc/sys/revoke.2
index c88222e..57abdbb 100644
--- a/lib/libc/sys/revoke.2
+++ b/lib/libc/sys/revoke.2
@@ -97,7 +97,8 @@ operation on the named file.
The caller is neither the owner of the file nor the super user.
.El
.Sh SEE ALSO
-.Xr close 2
+.Xr close 2 ,
+.Xr revoke 1
.Sh HISTORY
The
.Fn revoke
diff --git a/lib/libc/sys/sctp_generic_recvmsg.2 b/lib/libc/sys/sctp_generic_recvmsg.2
index 97a8f70..ccdb9db 100644
--- a/lib/libc/sys/sctp_generic_recvmsg.2
+++ b/lib/libc/sys/sctp_generic_recvmsg.2
@@ -70,5 +70,5 @@ The argument
is not a socket.
.El
.Sh SEE ALSO
-.Xr sctp 4 ,
.Xr sctp_recvmsg 3 ,
+.Xr sctp 4
diff --git a/lib/libc/sys/sctp_generic_sendmsg.2 b/lib/libc/sys/sctp_generic_sendmsg.2
index b9d95b8..d7050f2 100644
--- a/lib/libc/sys/sctp_generic_sendmsg.2
+++ b/lib/libc/sys/sctp_generic_sendmsg.2
@@ -79,8 +79,8 @@ The argument
is not a socket.
.El
.Sh SEE ALSO
-.Xr sctp 4 ,
.Xr sctp_send 3 ,
-.Xr sctp_sendx 3 ,
.Xr sctp_sendmsg 3 ,
.Xr sctp_sendmsgx 3 ,
+.Xr sctp_sendx 3 ,
+.Xr sctp 4
diff --git a/lib/libc/sys/sctp_peeloff.2 b/lib/libc/sys/sctp_peeloff.2
index 0ae20d6..0ac5be6 100644
--- a/lib/libc/sys/sctp_peeloff.2
+++ b/lib/libc/sys/sctp_peeloff.2
@@ -78,4 +78,4 @@ The argument
is not a socket.
.El
.Sh SEE ALSO
-.Xr sctp 4 ,
+.Xr sctp 4
diff --git a/lib/libc/sys/semctl.2 b/lib/libc/sys/semctl.2
index 01a984a..adfb9ef 100644
--- a/lib/libc/sys/semctl.2
+++ b/lib/libc/sys/semctl.2
@@ -148,12 +148,9 @@ struct semid_ds {
struct sem *sem_base; /* pointer to first semaphore in set */
u_short sem_nsems; /* number of sems in set */
time_t sem_otime; /* last operation time */
- long sem_pad1; /* SVABI/386 says I need this here */
time_t sem_ctime; /* last change time */
/* Times measured in secs since */
/* 00:00:00 GMT, Jan. 1, 1970 */
- long sem_pad2; /* SVABI/386 says I need this here */
- long sem_pad3[4]; /* SVABI/386 says I need this here */
};
.Ed
.Sh RETURN VALUES
diff --git a/lib/libc/sys/setfib.2 b/lib/libc/sys/setfib.2
index a9e23fd..ca08202 100644
--- a/lib/libc/sys/setfib.2
+++ b/lib/libc/sys/setfib.2
@@ -81,4 +81,4 @@ have been added to many other
The
.Fn setfib
function appeared in
-.Fx 8.0 .
+.Fx 7.1 .
diff --git a/lib/libc/sys/setgroups.2 b/lib/libc/sys/setgroups.2
index e56e95f..ef4c34c 100644
--- a/lib/libc/sys/setgroups.2
+++ b/lib/libc/sys/setgroups.2
@@ -53,9 +53,7 @@ The
argument
indicates the number of entries in the array and must be no
more than
-.Dv NGROUPS ,
-as defined in
-.In sys/param.h .
+.Dv {NGROUPS_MAX}+1 .
.Pp
Only the super-user may set a new group list.
.Sh RETURN VALUES
@@ -71,7 +69,7 @@ The caller is not the super-user.
The number specified in the
.Fa ngroups
argument is larger than the
-.Dv NGROUPS
+.Dv {NGROUPS_MAX}+1
limit.
.It Bq Er EFAULT
The address specified for
diff --git a/lib/libc/sys/shmctl.2 b/lib/libc/sys/shmctl.2
index 90c61c9..d3299af 100644
--- a/lib/libc/sys/shmctl.2
+++ b/lib/libc/sys/shmctl.2
@@ -100,14 +100,13 @@ structure is defined as follows:
.Bd -literal
struct shmid_ds {
struct ipc_perm shm_perm; /* operation permission structure */
- int shm_segsz; /* size of segment in bytes */
+ size_t shm_segsz; /* size of segment in bytes */
pid_t shm_lpid; /* process ID of last shared memory op */
pid_t shm_cpid; /* process ID of creator */
- short shm_nattch; /* number of current attaches */
+ int shm_nattch; /* number of current attaches */
time_t shm_atime; /* time of last shmat() */
time_t shm_dtime; /* time of last shmdt() */
time_t shm_ctime; /* time of last change by shmctl() */
- void *shm_internal; /* sysv stupidity */
};
.Ed
.Sh RETURN VALUES
diff --git a/lib/libc/sys/stack_protector.c b/lib/libc/sys/stack_protector.c
index f753fcd..14c20eb 100644
--- a/lib/libc/sys/stack_protector.c
+++ b/lib/libc/sys/stack_protector.c
@@ -47,7 +47,6 @@ static void __guard_setup(void) __attribute__((__constructor__, __used__));
static void __fail(const char *);
void __stack_chk_fail(void);
void __chk_fail(void);
-void __stack_chk_fail_local(void);
/*LINTED used*/
static void
@@ -109,8 +108,8 @@ __chk_fail(void)
__fail("buffer overflow detected; terminated");
}
-void
-__stack_chk_fail_local(void)
-{
- __stack_chk_fail();
-}
+#ifdef PIC
+__sym_compat(__stack_chk_fail_local, __stack_chk_fail, FBSD_1.0);
+#else
+__weak_reference(__stack_chk_fail, __stack_chk_fail_local);
+#endif
OpenPOWER on IntegriCloud