--- /dev/null
+.upstream_base_commits merge=union
#freebsd = https://github.com/freebsd/freebsd.git
-#openbsd = https://github.com/robertbachmann/openbsd-libc.git
+#openbsd = https://github.com/openbsd/src.git
+#netbsd = https://github.com/NetBSD/src.git
gen/FreeBSD/basename.c freebsd lib/libc/gen/basename.c 26f49abeef12bd43e9671edee6df7b9905c97a47
gen/FreeBSD/basename.3 freebsd lib/libc/gen/basename.3 26f49abeef12bd43e9671edee6df7b9905c97a47
gen/FreeBSD/clock.3 freebsd lib/libc/gen/clock.3 5b882020081a138285227631c46a406c08e17bc8
gen/FreeBSD/ctermid.3 freebsd lib/libc/gen/ctermid.3 5b882020081a138285227631c46a406c08e17bc8
gen/FreeBSD/getbsize.c freebsd lib/libc/gen/getbsize.c 5b882020081a138285227631c46a406c08e17bc8
+gen/FreeBSD/getcwd.3 freebsd lib/libc/gen/getcwd.3 898928e8d0a0bab201c1ef232e01cafa27322dae
+gen/FreeBSD/getpeereid.c freebsd lib/libc/gen/getpeereid.c 898928e8d0a0bab201c1ef232e01cafa27322dae
+gen/FreeBSD/glob.c freebsd lib/libc/gen/glob.c ececcb3d95a00665500a1f799a118fc4eaf6750b
+gen/FreeBSD/glob.3 freebsd lib/libc/gen/glob.3 ececcb3d95a00665500a1f799a118fc4eaf6750b
gen/FreeBSD/raise3 freebsd lib/libc/gen/raise.3 6b42c90c1ff5f7c35431eced41b6213401521d3d
gen/FreeBSD/readpassphrase.c freebsd lib/libc/gen/readpassphrase.c 1f19a8fc755a14865a5a5b67d5fa895c4b7cf622
gen/FreeBSD/readpassphrase.3 freebsd lib/libc/gen/readpassphrase.3 e0a2d4f15ed9e93fcb62544ed65f7a98e2339c3b
gen/FreeBSD/times.3 freebsd lib/libc/gen/times.3 5b882020081a138285227631c46a406c08e17bc8
+gen/FreeBSD/ttyslot.c freebsd lib/libc/gen/ttyslot.c 898928e8d0a0bab201c1ef232e01cafa27322dae
gen/FreeBSD/unvis.c freebsd contrib/libc-vis/unvis.c 9e3e4b88576d01efe1f56469cac79e116bb62c67
gen/FreeBSD/unvis.3 freebsd contrib/libc-vis/unvis.3 9e3e4b88576d01efe1f56469cac79e116bb62c67
gen/FreeBSD/usleep.3 freebsd lib/libc/gen/usleep.3 5b882020081a138285227631c46a406c08e17bc8
gen/FreeBSD/vis.c freebsd contrib/libc-vis/unvis.c 9e3e4b88576d01efe1f56469cac79e116bb62c67
gen/FreeBSD/vis.3 freebsd contrib/libc-vis/unvis.3 9e3e4b88576d01efe1f56469cac79e116bb62c67
gen/FreeBSD/vis.h freebsd contrib/libc-vis/unvis.3 9e3e4b88576d01efe1f56469cac79e116bb62c67
-gen/fts.c openbsd gen/fts.c 2a32c97c979d267fa99a362943265700bfcac5fd
+gen/NetBSD/rbtree.3 netbsd share/man/man3/rbtree.3 a6d78d4a28be21d6006d3c609f31967c0e536779
+gen/fts.c openbsd gen/fts.c 9936a0e983044822375a0d5cdebec20c3623866c
+include/glob.h freebsd include/glob.h ececcb3d95a00665500a1f799a118fc4eaf6750b
include/readpassphrase.h freebsd include/readpassphrase.h e0a2d4f15ed9e93fcb62544ed65f7a98e2339c3b
locale/FreeBSD/ascii.c freebsd lib/libc/locale/ascii.c 93e484e00e1e2dc498a7f4c45c0019e43b8ec5b2
locale/FreeBSD/isspecial.3 freebsd freebsd/lib/libc/locale/isspecial.3 5b882020081a138285227631c46a406c08e17bc8
locale/FreeBSD/setlocale.3 freebsd lib/libc/locale/setlocale.3 2131182e401759b74104a541a3b43cf2ee6a7434
man/FreeBSD/environ.7 freebsd share/man/man7/environ.7 5b882020081a138285227631c46a406c08e17bc8
net/FreeBSD/linkaddr.c freebsd lib/libc/net/linkaddr.c 9240f72512c0357636b2e19554d6141ee21edc5f
+stdio/FreeBSD/fopen.3 freebsd lib/libc/stdio/fopen.3 89c1fcc0d088065021703b658ef547f46b5481f0
+stdio/FreeBSD/fmemopen.c freebsd lib/libc/stdio/fmemopen.c 89c1fcc0d088065021703b658ef547f46b5481f0
+stdio/FreeBSD/open_memstream.3 freebsd lib/libc/stdio/open_memstream.3 89c1fcc0d088065021703b658ef547f46b5481f0
+stdio/FreeBSD/open_memstream.c freebsd lib/libc/stdio/open_memstream.c 89c1fcc0d088065021703b658ef547f46b5481f0
+stdio/FreeBSD/open_wmemstream.c freebsd lib/libc/stdio/open_wmemstream.c 89c1fcc0d088065021703b658ef547f46b5481f0
stdio/FreeBSD/mktemp.3 freebsd lib/libc/stdio/mktemp.3 2895e1352cf3788606924d800c3a5c589520ea00
stdio/FreeBSD/mktemp.c freebsd lib/libc/stdio/mktemp.c 2895e1352cf3788606924d800c3a5c589520ea00
stdio/FreeBSD/printf.3 freebsd lib/libc/stdio/printf.3 cfc3df2b8f708ce8494d9d556e3472a5c8c21b8a
stdio/FreeBSD/wprintf.3 freebsd lib/libc/stdio/wprintf.3 5b882020081a138285227631c46a406c08e17bc8
+stdlib/FreeBSD/atexit.3 freebsd lib/libc/stdlib/atexit 956381ee95fa01eefc74c9228bdc474ba267750d
stdlib/FreeBSD/getenv.3 freebsd lib/libc/stdlib/getenv.3 3eb0ea4663f0ae19c4983e80963a121463224508
stdlib/FreeBSD/getopt_long.3 freebsd lib/libc/stdlib/getopt_long.3 5b882020081a138285227631c46a406c08e17bc8
+stdlib/FreeBSD/qsort.c freebsd lib/libc/stdlib/qsort.c 4127dd6b50348062f74679dbb43008d0a2985a09
stdlib/FreeBSD/reallocf.c freebsd lib/libc/stdlib/reallocf.c 3dc97c4341b6c5a0163c12badc7f50628cecf4e6
+stdtime/FreeBSD/localtime.c freebsd contrib/tzcode/stdtime/localtime.c a931eab7f4cf8a9614505540fb523b59f693cc6e
+stdtime/FreeBSD/private.h freebsd contrib/tzcode/stdtime/private.h a931eab7f4cf8a9614505540fb523b59f693cc6e
stdtime/FreeBSD/strptime.c freebsd lib/libc/stdtime/strptime.c 52d53d171566c2cd975d2db86a291e516d34d9fe
stdtime/FreeBSD/strptime.3 freebsd lib/libc/stdtime/strptime.3 52d53d171566c2cd975d2db86a291e516d34d9fe
+stdtime/FreeBSD/tzfile.h freebsd contrib/tzcode/stdtime/tzfile.h 000663e80955a044c229f9274011b828a788ee4b
+stdtime/FreeBSD/tzfile.5 freebsd contrib/tzcode/stdtime/tzfile.5 000663e80955a044c229f9274011b828a788ee4b
string/FreeBSD/bcmp.3 freebsd lib/libc/string/bcmp.3 408f4a1ab49f89368c80edb4485895658fc81598
string/FreeBSD/memcmp.3 freebsd lib/libc/string/memcmp.3 3eb0ea4663f0ae19c4983e80963a121463224508
string/FreeBSD/strcpy.3 freebsd lib/libc/string/strcpy.3 cfc3df2b8f708ce8494d9d556e3472a5c8c21b8a
+string/FreeBSD/strlcpy.3 freebsd lib/libc/string/strlcpy.3 e3c83e4556db162d5b54833d2e9974a1152394eb
string/FreeBSD/strpbrk.3 freebsd lib/libc/string/strpbrk.3 5b882020081a138285227631c46a406c08e17bc8
string/FreeBSD/strspn.3 freebsd lib/libc/string/strspn.3 5b882020081a138285227631c46a406c08e17bc8
string/FreeBSD/strstr.3 freebsd lib/libc/string/strstr.3 cfc3df2b8f708ce8494d9d556e3472a5c8c21b8a
string/FreeBSD/timingsafe_bcmp.3 freebsd lib/libc/string/timingsafe_bcmp.3 408f4a1ab49f89368c80edb4485895658fc81598
string/FreeBSD/timingsafe_bcmp.c freebsd lib/libc/string/timingsafe_bcmp.c 408f4a1ab49f89368c80edb4485895658fc81598
+tests/freebsd_fmemopen.c freebsd lib/libc/tests/stdio/fmemopen2_test.c 89c1fcc0d088065021703b658ef547f46b5481f0
+tests/freebsd_glob.c freebsd lib/libc/tests/gen/glob2_test.c ececcb3d95a00665500a1f799a118fc4eaf6750b
+tests/freebsd_open_memstream.c freebsd lib/libc/tests/stdio/open_memstream2_test.c 89c1fcc0d088065021703b658ef547f46b5481f0
+tests/freebsd_open_wmemstream.c freebsd lib/libc/tests/stdio/open_wmemstream_test.c 89c1fcc0d088065021703b658ef547f46b5481f0
+tests/freebsd_qsort.c freebsd ./lib/libc/tests/stdlib/qsort_test.c 4127dd6b50348062f74679dbb43008d0a2985a09
+tests/freebsd_qsort.h freebsd ./lib/libc/tests/stdlib/test-sort.h 4127dd6b50348062f74679dbb43008d0a2985a09
+tests/netbsd_fmemopen.c freebsd contrib/netbsd-tests/lib/libc/stdio/t_fmemopen.c 89c1fcc0d088065021703b658ef547f46b5481f0
+tests/netbsd_open_memstream.c freebsd contrib/netbsd-tests/lib/libc/stdio/t_open_memstream.c 89c1fcc0d088065021703b658ef547f46b5481f0
tests/netbsd_getcwd.c freebsd contrib/netbsd-tests/lib/libc/gen/t_getcwd.c 6f5b3c1fa3e9554a26cbf6401366ff8b0f0506fe
tests/netbsd_getenv_thread.c freebsd contrib/netbsd-tests/lib/libc/stdlib/t_getenv_thread.c 3f09b8d0af642c2aeb96a4d667cefb7fe3bce443
+tests/netbsd_glob.c freebsd contrib/netbsd-tests/lib/libc/gen/t_glob.c ececcb3d95a00665500a1f799a118fc4eaf6750b
+tests/netbsd_printf.c freebsd contrib/netbsd-tests/lib/libc/stdio/t_printf.c 6ea6500b7eba4165c351cbbfcdec7f2fe776f8ac
tests/netbsd_stat.c freebsd contrib/netbsd-tests/lib/libc/sys/t_stat.c 6f5b3c1fa3e9554a26cbf6401366ff8b0f0506fe
tests/netbsd_strptime.c freebsd contrib/netbsd-tests/lib/libc/time/t_strptime.c 52d53d171566c2cd975d2db86a291e516d34d9fe
tests/netbsd_vis.c freebsd contrib/netbsd-tests/lib/libc/gen/t_vis.c 52d53d171566c2cd975d2db86a291e516d34d9fe
+gen/FreeBSD/closedir.c freebsd lib/libc/gen/closedir.c b717fb9f083afdfbc50a14ced6ddc971ca583f02
+gen/FreeBSD/opendir.c freebsd lib/libc/gen/opendir.c 6e91d78151e10ed31c475cafe6a1e1f11950c1d9
+gen/FreeBSD/readdir.c freebsd lib/libc/gen/readdir.c 74c1506b3359ee725c9031331908b717460830dc
+gen/FreeBSD/rewinddir.c freebsd lib/libc/gen/rewinddir.c 74c1506b3359ee725c9031331908b717460830dc
+gen/FreeBSD/scandir.c freebsd lib/libc/gen/scandir.c 0127b103f27578fc7f9cc3389b299f221deb1d4c
+gen/FreeBSD/scandir_b.c freebsd lib/libc/gen/scandir_b.c 0127b103f27578fc7f9cc3389b299f221deb1d4c
+gen/FreeBSD/seekdir.c freebsd lib/libc/gen/seekdir.c 74c1506b3359ee725c9031331908b717460830dc
+gen/FreeBSD/telldir.c freebsd lib/libc/gen/telldir.c 74c1506b3359ee725c9031331908b717460830dc
name = Libc_tests;
productName = Libc_tests;
};
+ 926F739D1E046E55001E049D /* Libc_darwin */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 926F739E1E046E56001E049D /* Build configuration list for PBXAggregateTarget "Libc_darwin" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 926F73A21E046E69001E049D /* PBXTargetDependency */,
+ );
+ name = Libc_darwin;
+ productName = libdarwin;
+ };
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
63D4061113DDF4340094DD56 /* strncat.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4060F13DDF4340094DD56 /* strncat.c */; };
63D4061313DDF6A30094DD56 /* strlcat.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4061213DDF6A20094DD56 /* strlcat.c */; };
63D4061413DDF6A30094DD56 /* strlcat.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4061213DDF6A20094DD56 /* strlcat.c */; };
+ 926F73981E03E8C4001E049D /* variant.c in Sources */ = {isa = PBXBuildFile; fileRef = 926F73971E03E8C4001E049D /* variant.c */; };
+ 926F739A1E03E8D6001E049D /* variant_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 926F73991E03E8D6001E049D /* variant_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 92767C841E0A7E2700AB9C76 /* init.c in Sources */ = {isa = PBXBuildFile; fileRef = 92767C821E0A7E2100AB9C76 /* init.c */; };
+ 928841361EA75555001064D1 /* dirstat_collection.c in Sources */ = {isa = PBXBuildFile; fileRef = 928841341EA7554D001064D1 /* dirstat_collection.c */; };
+ 92888B161EA5BE7400BA923E /* fmemopen.c in Sources */ = {isa = PBXBuildFile; fileRef = 92888B0F1EA5BE6D00BA923E /* fmemopen.c */; };
+ 92888B171EA5BE8000BA923E /* open_memstream.c in Sources */ = {isa = PBXBuildFile; fileRef = 92888B111EA5BE6D00BA923E /* open_memstream.c */; };
+ 92888B181EA5BE8600BA923E /* open_wmemstream.c in Sources */ = {isa = PBXBuildFile; fileRef = 92888B121EA5BE6D00BA923E /* open_wmemstream.c */; };
928BD1001D76072200EC01FC /* timingsafe_bcmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 928BD0FE1D7606EA00EC01FC /* timingsafe_bcmp.c */; };
928BD1011D76072200EC01FC /* timingsafe_bcmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 928BD0FE1D7606EA00EC01FC /* timingsafe_bcmp.c */; };
928BD1021D76072C00EC01FC /* timingsafe_bcmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 928BD0FE1D7606EA00EC01FC /* timingsafe_bcmp.c */; };
928BD1071D76073600EC01FC /* timingsafe_bcmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 928BD0FE1D7606EA00EC01FC /* timingsafe_bcmp.c */; };
928BD1081D76073600EC01FC /* timingsafe_bcmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 928BD0FE1D7606EA00EC01FC /* timingsafe_bcmp.c */; };
92ABC7E91D375FC2000DF880 /* compatibility_hacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 92ABC7E81D375FC2000DF880 /* compatibility_hacks.c */; };
+ 92D763E01EA6DA3A001467FC /* dirstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 92D763DC1EA6D9FB001467FC /* dirstat.c */; };
B10BC41C14338AEB005E4366 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = B122F2B11432B95B00AF95D0 /* regcomp.c */; settings = {COMPILER_FLAGS = "-DHAVE_CONFIG_H -I$(SRCROOT)/regex/TRE -I$(SRCROOT)/regex/FreeBSD"; }; };
B122F2C71432B95B00AF95D0 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = B122F2B11432B95B00AF95D0 /* regcomp.c */; };
B122F2C91432B95B00AF95D0 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = B122F2B21432B95B00AF95D0 /* regexec.c */; };
C0E345571C582ECB00E749C2 /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C0E345581C582ECB00E749C2 /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C0E345591C582ECB00E749C2 /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C0E3455A1C582ECB00E749C2 /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C0E3455A1C582ECB00E749C2 /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C0E3455B1C582ECB00E749C2 /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C0E3455C1C582ECB00E749C2 /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C0E3455D1C582ECB00E749C2 /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C0E345C11C582ECB00E749C2 /* (null) in Sources */ = {isa = PBXBuildFile; };
C0E345C21C582ECB00E749C2 /* (null) in Sources */ = {isa = PBXBuildFile; };
C0E345C31C582ECB00E749C2 /* scandir_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9EB350E138F769B0075BB52 /* scandir_b.c */; settings = {COMPILER_FLAGS = "$(FreeBSD_CFLAGS) -include gen/__dirent.h"; }; };
- C0E345C41C582ECB00E749C2 /* init_cpu_capabilities.c in Sources */ = {isa = PBXBuildFile; fileRef = C921D3831395B7DD001CE070 /* init_cpu_capabilities.c */; };
- C0E345C51C582ECB00E749C2 /* pthread_getspecific.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3841395B7DD001CE070 /* pthread_getspecific.s */; };
- C0E345C61C582ECB00E749C2 /* pthread_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3851395B7DD001CE070 /* pthread_self.s */; };
- C0E345C71C582ECB00E749C2 /* pthread_set_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3861395B7DD001CE070 /* pthread_set_self.s */; };
- C0E345C81C582ECB00E749C2 /* start_wqthread.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3871395B7DD001CE070 /* start_wqthread.s */; };
- C0E345C91C582ECB00E749C2 /* thread_start.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3881395B7DD001CE070 /* thread_start.s */; };
C0E345CA1C582ECB00E749C2 /* strcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6310518613D4D966004F7BA8 /* strcpy.c */; };
C0E345CB1C582ECB00E749C2 /* strlcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6310518B13D4DABD004F7BA8 /* strlcpy.c */; };
C0E345CC1C582ECB00E749C2 /* strncpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6310518E13D4DAEA004F7BA8 /* strncpy.c */; };
C0E345DC1C582ECB00E749C2 /* libFreeBSD.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C9257ED0138E1B5000B3107C /* libFreeBSD.a */; };
C0E345DD1C582ECB00E749C2 /* libvCancelable.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C9D94360138EC3E300FB7ACC /* libvCancelable.a */; };
C0E345DE1C582ECB00E749C2 /* libTRE.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B122F2AD1432B8E600AF95D0 /* libTRE.a */; };
- C921D3891395B7DD001CE070 /* init_cpu_capabilities.c in Sources */ = {isa = PBXBuildFile; fileRef = C921D3831395B7DD001CE070 /* init_cpu_capabilities.c */; };
- C921D38A1395B7DD001CE070 /* pthread_getspecific.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3841395B7DD001CE070 /* pthread_getspecific.s */; };
- C921D38B1395B7DD001CE070 /* pthread_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3851395B7DD001CE070 /* pthread_self.s */; };
- C921D38C1395B7DD001CE070 /* pthread_set_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3861395B7DD001CE070 /* pthread_set_self.s */; };
- C921D38D1395B7DD001CE070 /* start_wqthread.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3871395B7DD001CE070 /* start_wqthread.s */; };
- C921D38E1395B7DD001CE070 /* thread_start.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3881395B7DD001CE070 /* thread_start.s */; };
C9257ED5138E1C2E00B3107C /* creat.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B535F8138D9E980028D27C /* creat.c */; };
C9257ED6138E1C2E00B3107C /* gethostid.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B535FC138D9E980028D27C /* gethostid.c */; };
C9257ED7138E1C2E00B3107C /* getwd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B535FE138D9E980028D27C /* getwd.c */; };
C942123913900C8A004BA536 /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C942123A13900C8A004BA536 /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C942123B13900C8A004BA536 /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C942123C13900C8A004BA536 /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C942123C13900C8A004BA536 /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C942123D13900C8A004BA536 /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C942123E13900C8A004BA536 /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C942123F13900C8A004BA536 /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C95B80E4138F3C55004311DA /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C95B80E5138F3C55004311DA /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C95B80E6138F3C55004311DA /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C95B80E7138F3C55004311DA /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C95B80E7138F3C55004311DA /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C95B80E8138F3C55004311DA /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C95B80E9138F3C55004311DA /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C95B80EA138F3C55004311DA /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C95B838F138F52B0004311DA /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C95B8390138F52B0004311DA /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C95B8391138F52B0004311DA /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C95B8392138F52B0004311DA /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C95B8392138F52B0004311DA /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C95B8393138F52B0004311DA /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C95B8394138F52B0004311DA /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C95B8395138F52B0004311DA /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C95B8635138F53DB004311DA /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C95B8636138F53DB004311DA /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C95B8637138F53DB004311DA /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C95B8638138F53DB004311DA /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C95B8638138F53DB004311DA /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C95B8639138F53DB004311DA /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C95B863A138F53DB004311DA /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C95B863B138F53DB004311DA /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C97660B9138EC61A00741512 /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C97660BA138EC61A00741512 /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C97660BB138EC61A00741512 /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C97660BC138EC61A00741512 /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C97660BC138EC61A00741512 /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C97660BD138EC61A00741512 /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C97660BE138EC61A00741512 /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C97660BF138EC61A00741512 /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C97A71771517AF53005E1998 /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C97A71781517AF53005E1998 /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C97A71791517AF53005E1998 /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C97A717A1517AF53005E1998 /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C97A717A1517AF53005E1998 /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C97A717B1517AF53005E1998 /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C97A717C1517AF53005E1998 /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C97A717D1517AF53005E1998 /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C97A71F91517AF53005E1998 /* (null) in Sources */ = {isa = PBXBuildFile; };
C97A71FA1517AF53005E1998 /* (null) in Sources */ = {isa = PBXBuildFile; };
C97A71FD1517AF53005E1998 /* scandir_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9EB350E138F769B0075BB52 /* scandir_b.c */; settings = {COMPILER_FLAGS = "$(FreeBSD_CFLAGS) -include gen/__dirent.h"; }; };
- C97A71FF1517AF53005E1998 /* init_cpu_capabilities.c in Sources */ = {isa = PBXBuildFile; fileRef = C921D3831395B7DD001CE070 /* init_cpu_capabilities.c */; };
- C97A72001517AF53005E1998 /* pthread_getspecific.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3841395B7DD001CE070 /* pthread_getspecific.s */; };
- C97A72011517AF53005E1998 /* pthread_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3851395B7DD001CE070 /* pthread_self.s */; };
- C97A72021517AF53005E1998 /* pthread_set_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3861395B7DD001CE070 /* pthread_set_self.s */; };
- C97A72031517AF53005E1998 /* start_wqthread.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3871395B7DD001CE070 /* start_wqthread.s */; };
- C97A72041517AF53005E1998 /* thread_start.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3881395B7DD001CE070 /* thread_start.s */; };
C97A720D1517AF53005E1998 /* strcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6310518613D4D966004F7BA8 /* strcpy.c */; };
C97A720E1517AF53005E1998 /* strlcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6310518B13D4DABD004F7BA8 /* strlcpy.c */; };
C97A720F1517AF53005E1998 /* strncpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6310518E13D4DAEA004F7BA8 /* strncpy.c */; };
C97A72171517AF53005E1998 /* dirfd.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FB7E1B4146EF2E000843438 /* dirfd.c */; };
C98373971395989E00E5C052 /* OSMemoryNotification.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53DAC138D9E9A0028D27C /* OSMemoryNotification.c */; };
C98373981395989E00E5C052 /* OSThermalNotification.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53DAD138D9E9A0028D27C /* OSThermalNotification.c */; };
- C98E2B4C139851B7002A3ABB /* init_cpu_capabilities.c in Sources */ = {isa = PBXBuildFile; fileRef = C921D3831395B7DD001CE070 /* init_cpu_capabilities.c */; };
- C98E2B4D139851B7002A3ABB /* pthread_getspecific.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3841395B7DD001CE070 /* pthread_getspecific.s */; };
- C98E2B4E139851B7002A3ABB /* pthread_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3851395B7DD001CE070 /* pthread_self.s */; };
- C98E2B4F139851B7002A3ABB /* pthread_set_self.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3861395B7DD001CE070 /* pthread_set_self.s */; };
- C98E2B50139851B7002A3ABB /* start_wqthread.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3871395B7DD001CE070 /* start_wqthread.s */; };
- C98E2B51139851B7002A3ABB /* thread_start.s in Sources */ = {isa = PBXBuildFile; fileRef = C921D3881395B7DD001CE070 /* thread_start.s */; };
C9A12853138E0BE00003880A /* gmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B5380B138D9E990028D27C /* gmon.c */; };
C9A12854138E0C1C0003880A /* isctype.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B539E5138D9E990028D27C /* isctype.c */; };
C9A12855138E0C1C0003880A /* iswctype.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B539E7138D9E990028D27C /* iswctype.c */; };
C9EB31D4138F6D880075BB52 /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C9EB31D5138F6D880075BB52 /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C9EB31D6138F6D880075BB52 /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C9EB31D7138F6D880075BB52 /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C9EB31D7138F6D880075BB52 /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C9EB31D8138F6D880075BB52 /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C9EB31D9138F6D880075BB52 /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C9EB31DA138F6D880075BB52 /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C9EB347B138F75580075BB52 /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
C9EB347C138F75580075BB52 /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C9EB347D138F75580075BB52 /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C9EB347E138F75580075BB52 /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C9EB347E138F75580075BB52 /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C9EB347F138F75580075BB52 /* asctime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC2138D9E9A0028D27C /* asctime.c */; };
C9EB3480138F75580075BB52 /* difftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC6138D9E9A0028D27C /* difftime.c */; };
C9EB3481138F75580075BB52 /* ftime.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CC9138D9E9A0028D27C /* ftime.c */; };
C9FA3348138E4D040089A94B /* l64a.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CAD138D9E9A0028D27C /* l64a.c */; };
C9FA334A138E4D040089A94B /* ecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB7138D9E9A0028D27C /* ecvt.c */; };
C9FA334B138E4D040089A94B /* gcvt.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB9138D9E9A0028D27C /* gcvt.c */; };
- C9FA334C138E4D040089A94B /* qsort_b-fbsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */; };
+ C9FA334C138E4D040089A94B /* qsort_b.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CBD138D9E9A0028D27C /* qsort_b.c */; };
C9FA334D138E4D0C0089A94B /* strfmon.c in Sources */ = {isa = PBXBuildFile; fileRef = C9B53CB2138D9E9A0028D27C /* strfmon.c */; };
FC2ED610157D4BE80098EC69 /* inet_ntop.c in Sources */ = {isa = PBXBuildFile; fileRef = FC2ED60E157D4BE70098EC69 /* inet_ntop.c */; };
FC2ED611157D4BE80098EC69 /* inet_ntop.c in Sources */ = {isa = PBXBuildFile; fileRef = FC2ED60E157D4BE70098EC69 /* inet_ntop.c */; };
remoteGlobalIDString = 3F51206A16C3174300AFB431;
remoteInfo = FortifySource;
};
+ 926F73A11E046E69001E049D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = C9B53597138D9A690028D27C /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 926F73911E03E2A3001E049D;
+ remoteInfo = libsystem_darwin.dylib;
+ };
928F25D41BEAD2AE007B13C7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C9B53597138D9A690028D27C /* Project object */;
63D4060C13DDF26A0094DD56 /* strcat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strcat.c; sourceTree = "<group>"; };
63D4060F13DDF4340094DD56 /* strncat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strncat.c; sourceTree = "<group>"; };
63D4061213DDF6A20094DD56 /* strlcat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strlcat.c; sourceTree = "<group>"; };
+ 926F73921E03E2A3001E049D /* libsystem_darwin.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_darwin.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+ 926F73971E03E8C4001E049D /* variant.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = variant.c; sourceTree = "<group>"; };
+ 926F73991E03E8D6001E049D /* variant_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = variant_private.h; path = os/variant_private.h; sourceTree = "<group>"; };
+ 92767C821E0A7E2100AB9C76 /* init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = init.c; sourceTree = "<group>"; };
+ 9280EA171E59BC8A007A6F58 /* AppleInternalVariant.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AppleInternalVariant.plist; sourceTree = "<group>"; };
+ 928841341EA7554D001064D1 /* dirstat_collection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dirstat_collection.c; sourceTree = "<group>"; };
+ 92888B0F1EA5BE6D00BA923E /* fmemopen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmemopen.c; sourceTree = "<group>"; };
+ 92888B101EA5BE6D00BA923E /* open_memstream.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = open_memstream.3; sourceTree = "<group>"; };
+ 92888B111EA5BE6D00BA923E /* open_memstream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = open_memstream.c; sourceTree = "<group>"; };
+ 92888B121EA5BE6D00BA923E /* open_wmemstream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = open_wmemstream.c; sourceTree = "<group>"; };
928BD0FD1D7606EA00EC01FC /* timingsafe_bcmp.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = timingsafe_bcmp.3; sourceTree = "<group>"; };
928BD0FE1D7606EA00EC01FC /* timingsafe_bcmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timingsafe_bcmp.c; sourceTree = "<group>"; };
928BD1091D7608A400EC01FC /* environ.7 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = environ.7; sourceTree = "<group>"; };
92ABC7E81D375FC2000DF880 /* compatibility_hacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compatibility_hacks.c; sourceTree = "<group>"; };
+ 92D763DC1EA6D9FB001467FC /* dirstat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dirstat.c; sourceTree = "<group>"; };
+ 92D763E41EA6F887001467FC /* dirstat_collection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirstat_collection.h; sourceTree = "<group>"; };
+ 92D763E51EA6F887001467FC /* dirstat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirstat.h; sourceTree = "<group>"; };
B122F2AD1432B8E600AF95D0 /* libTRE.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTRE.a; sourceTree = BUILT_PRODUCTS_DIR; };
B122F2AF1432B95B00AF95D0 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
B122F2B11432B95B00AF95D0 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = "<group>"; };
B1795372158B0E35008990E8 /* xprintf_exec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xprintf_exec.c; sourceTree = "<group>"; };
B19C64591450F8B900032373 /* sync_volume_np.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = sync_volume_np.3; sourceTree = "<group>"; };
B19C645B1450F90200032373 /* sync_volume_np.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sync_volume_np.c; sourceTree = "<group>"; };
+ C00AC1181E04B7E000286B61 /* legacy_opendir_alias.list */ = {isa = PBXFileReference; lastKnownFileType = text; path = legacy_opendir_alias.list; sourceTree = "<group>"; };
C06E02D11CA0C9CA00B07322 /* tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tests; sourceTree = "<group>"; };
C0E343811C58299D00E749C2 /* skip_installhdrs.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = skip_installhdrs.sh; sourceTree = "<group>"; };
C0E345E21C582ECB00E749C2 /* libc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libc.a; sourceTree = BUILT_PRODUCTS_DIR; };
C0E345E31C58300F00E749C2 /* libc_static.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = libc_static.xcconfig; sourceTree = "<group>"; };
C9194B4C140E3BC700BE0C3A /* build_linklists.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_linklists.sh; sourceTree = "<group>"; };
- C921D3831395B7DD001CE070 /* init_cpu_capabilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = init_cpu_capabilities.c; sourceTree = "<group>"; };
- C921D3841395B7DD001CE070 /* pthread_getspecific.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = pthread_getspecific.s; sourceTree = "<group>"; };
- C921D3851395B7DD001CE070 /* pthread_self.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = pthread_self.s; sourceTree = "<group>"; };
- C921D3861395B7DD001CE070 /* pthread_set_self.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = pthread_set_self.s; sourceTree = "<group>"; };
- C921D3871395B7DD001CE070 /* start_wqthread.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = start_wqthread.s; sourceTree = "<group>"; };
- C921D3881395B7DD001CE070 /* thread_start.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = thread_start.s; sourceTree = "<group>"; };
C9257ED0138E1B5000B3107C /* libFreeBSD.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFreeBSD.a; sourceTree = BUILT_PRODUCTS_DIR; };
C9258105138E2D3100B3107C /* libNetBSD.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNetBSD.a; sourceTree = BUILT_PRODUCTS_DIR; };
C925D1FB151805C6003D315B /* eos_stubs.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = eos_stubs.c; sourceTree = "<group>"; };
C9B53CB5138D9E9A0028D27C /* ecvt.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = ecvt.3; sourceTree = "<group>"; };
C9B53CB7138D9E9A0028D27C /* ecvt.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ecvt.c; sourceTree = "<group>"; };
C9B53CB9138D9E9A0028D27C /* gcvt.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = gcvt.c; sourceTree = "<group>"; };
- C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "qsort_b-fbsd.c"; sourceTree = "<group>"; };
+ C9B53CBD138D9E9A0028D27C /* qsort_b.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = qsort_b.c; sourceTree = "<group>"; };
C9B53CBE138D9E9A0028D27C /* strtod_l.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = strtod_l.3; sourceTree = "<group>"; };
C9B53CBF138D9E9A0028D27C /* strtol_l.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = strtol_l.3; sourceTree = "<group>"; };
C9B53CC2138D9E9A0028D27C /* asctime.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = asctime.c; sourceTree = "<group>"; };
C9ECE2761950E384008E8672 /* atexit_receipt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atexit_receipt.c; sourceTree = "<group>"; };
C9FA32F8138E4A5C0089A94B /* utf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utf2.c; sourceTree = "<group>"; };
C9FACC591ACDBA54009F33F1 /* Makefile.inc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.pascal; name = Makefile.inc; path = Platforms/appletvos/Makefile.inc; sourceTree = SOURCE_ROOT; };
+ E40EA6C01EAA8F9300B2FA36 /* _strings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _strings.h; sourceTree = "<group>"; };
E41BEA97178E72E100E348BB /* Libc.order */ = {isa = PBXFileReference; lastKnownFileType = text; path = Libc.order; sourceTree = "<group>"; };
E4A877A6174D82FB000DBB55 /* alias.list */ = {isa = PBXFileReference; lastKnownFileType = text; path = alias.list; sourceTree = "<group>"; };
FC2ED60E157D4BE70098EC69 /* inet_ntop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inet_ntop.c; sourceTree = "<group>"; };
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 926F738F1E03E2A3001E049D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
B122F2A91432B8E600AF95D0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
4B2C64A015519B0500342BFA /* os */ = {
isa = PBXGroup;
children = (
+ 926F73991E03E8D6001E049D /* variant_private.h */,
2DF67CE7184F9CD000B83A3D /* debug_private.h */,
2DF67CDD184F9CBE00B83A3D /* debug_private.c */,
4B2C64AB15519C3400342BFA /* assumes.h */,
name = os;
sourceTree = "<group>";
};
+ 926F73961E03E8C4001E049D /* libdarwin */ = {
+ isa = PBXGroup;
+ children = (
+ 9280EA171E59BC8A007A6F58 /* AppleInternalVariant.plist */,
+ 928841341EA7554D001064D1 /* dirstat_collection.c */,
+ 92D763E41EA6F887001467FC /* dirstat_collection.h */,
+ 92D763DC1EA6D9FB001467FC /* dirstat.c */,
+ 92D763E51EA6F887001467FC /* dirstat.h */,
+ 92767C821E0A7E2100AB9C76 /* init.c */,
+ 926F73971E03E8C4001E049D /* variant.c */,
+ );
+ path = libdarwin;
+ sourceTree = "<group>";
+ };
B122F2AE1432B95B00AF95D0 /* TRE */ = {
isa = PBXGroup;
children = (
C9B53595138D9A690028D27C = {
isa = PBXGroup;
children = (
+ 926F73961E03E8C4001E049D /* libdarwin */,
C9B535AE138D9E980028D27C /* APPLE_LICENSE */,
C9B535AF138D9E980028D27C /* arm */,
- C9B535E2138D9E980028D27C /* arm */,
+ C9B535E2138D9E980028D27C /* arm64 */,
C9B535F5138D9E980028D27C /* compat-43 */,
C9B53612138D9E980028D27C /* darwin */,
C9B5361D138D9E980028D27C /* db */,
C97A721C1517AF53005E1998 /* libc_eOS.a */,
3F5120F116C3174300AFB431 /* libFortifySource.a */,
C0E345E21C582ECB00E749C2 /* libc.a */,
+ 926F73921E03E2A3001E049D /* libsystem_darwin.dylib */,
);
name = Products;
sourceTree = "<group>";
path = string;
sourceTree = "<group>";
};
- C9B535E2138D9E980028D27C /* arm */ = {
+ C9B535E2138D9E980028D27C /* arm64 */ = {
isa = PBXGroup;
children = (
C9B535EB138D9E980028D27C /* string */,
);
- path = arm;
+ path = arm64;
sourceTree = "<group>";
};
C9B535EB138D9E980028D27C /* string */ = {
C9B538A9138D9E990028D27C /* _common.h */,
C9B538AA138D9E990028D27C /* _stdio.h */,
C9B538AB138D9E990028D27C /* _string.h */,
+ E40EA6C01EAA8F9300B2FA36 /* _strings.h */,
);
path = secure;
sourceTree = "<group>";
C9B53B55138D9E990028D27C /* flags.c */,
C9B53B57138D9E990028D27C /* floatio.h */,
C9B53B58138D9E990028D27C /* flockfile.3 */,
+ 92888B0F1EA5BE6D00BA923E /* fmemopen.c */,
C9B53B5A138D9E990028D27C /* fopen.3 */,
C9B53B5C138D9E990028D27C /* fopen.c */,
C9B53B5E138D9E990028D27C /* fprintf.c */,
C9B53B9C138D9E990028D27C /* makebuf.c */,
C9B53B9E138D9E990028D27C /* mktemp.3 */,
C9B53BA0138D9E990028D27C /* mktemp.c */,
+ 92888B101EA5BE6D00BA923E /* open_memstream.3 */,
+ 92888B111EA5BE6D00BA923E /* open_memstream.c */,
+ 92888B121EA5BE6D00BA923E /* open_wmemstream.c */,
C9B53BA2138D9E990028D27C /* perror.c */,
C9B53BA3138D9E990028D27C /* printf-pos.c */,
C9B53BA5138D9E990028D27C /* printf.3 */,
C9B53CAD138D9E9A0028D27C /* l64a.c */,
C9B53CAF138D9E9A0028D27C /* NetBSD */,
C9B53CB4138D9E9A0028D27C /* OpenBSD */,
- C9B53CBD138D9E9A0028D27C /* qsort_b-fbsd.c */,
+ C9B53CBD138D9E9A0028D27C /* qsort_b.c */,
C9B53CBE138D9E9A0028D27C /* strtod_l.3 */,
C9B53CBF138D9E9A0028D27C /* strtol_l.3 */,
);
isa = PBXGroup;
children = (
E4A877A6174D82FB000DBB55 /* alias.list */,
+ C00AC1181E04B7E000286B61 /* legacy_opendir_alias.list */,
C9C2A948138DF7DD00287F00 /* libc.xcconfig */,
C9766153138ECF0000741512 /* variants.xcconfig */,
C9AE91AE1517CDAC00A2626C /* eos.xcconfig */,
};
/* End PBXGroup section */
+/* Begin PBXHeadersBuildPhase section */
+ 926F73901E03E2A3001E049D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 926F739A1E03E8D6001E049D /* variant_private.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
/* Begin PBXLegacyTarget section */
928F25D01BEACED7007B13C7 /* darwintests */ = {
isa = PBXLegacyTarget;
productReference = 3F5120F116C3174300AFB431 /* libFortifySource.a */;
productType = "com.apple.product-type.library.static";
};
+ 926F73911E03E2A3001E049D /* libsystem_darwin.dylib */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 926F73951E03E2A4001E049D /* Build configuration list for PBXNativeTarget "libsystem_darwin.dylib" */;
+ buildPhases = (
+ 926F738E1E03E2A3001E049D /* Sources */,
+ 926F738F1E03E2A3001E049D /* Frameworks */,
+ 926F73901E03E2A3001E049D /* Headers */,
+ 9280EA241E5A5D6F007A6F58 /* Copy AppleInternalVariant.plist */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libsystem_darwin.dylib;
+ productName = libsystem_darwin;
+ productReference = 926F73921E03E2A3001E049D /* libsystem_darwin.dylib */;
+ productType = "com.apple.product-type.library.dynamic";
+ };
B122F0E71432B8E600AF95D0 /* TRE */ = {
isa = PBXNativeTarget;
buildConfigurationList = B122F2AA1432B8E600AF95D0 /* Build configuration list for PBXNativeTarget "TRE" */;
925E7FE619E8945900AC7889 = {
CreatedOnToolsVersion = 6.1;
};
+ 926F73911E03E2A3001E049D = {
+ CreatedOnToolsVersion = 8.2;
+ ProvisioningStyle = Automatic;
+ };
+ 926F739D1E046E55001E049D = {
+ CreatedOnToolsVersion = 8.2;
+ ProvisioningStyle = Automatic;
+ };
928F25D01BEACED7007B13C7 = {
CreatedOnToolsVersion = 7.1;
};
3F51206A16C3174300AFB431 /* FortifySource */,
925E7FE619E8945900AC7889 /* Libc_tests */,
928F25D01BEACED7007B13C7 /* darwintests */,
+ 926F739D1E046E55001E049D /* Libc_darwin */,
+ 926F73911E03E2A3001E049D /* libsystem_darwin.dylib */,
);
};
/* End PBXProject section */
shellPath = /bin/bash;
shellScript = ". \"${SCRIPT_INPUT_FILE_0}\"";
};
+ 9280EA241E5A5D6F007A6F58 /* Copy AppleInternalVariant.plist */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Copy AppleInternalVariant.plist";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "set -ex\nINSTALL_PATH=${DSTROOT}/System/Library/CoreServices\n\nif [ \"${PLATFORM_NAME}\" = \"macosx\" ]; then\ninstall -d ${INSTALL_PATH}\ninstall -m 0444 ${SRCROOT}/libdarwin/AppleInternalVariant.plist ${INSTALL_PATH}\nfi";
+ showEnvVarsInLog = 0;
+ };
B122F0E81432B8E600AF95D0 /* Generate libc-features.h */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 926F738E1E03E2A3001E049D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 926F73981E03E8C4001E049D /* variant.c in Sources */,
+ 92D763E01EA6DA3A001467FC /* dirstat.c in Sources */,
+ 92767C841E0A7E2700AB9C76 /* init.c in Sources */,
+ 928841361EA75555001064D1 /* dirstat_collection.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
B122F0E91432B8E600AF95D0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
C0E345571C582ECB00E749C2 /* strfmon.c in Sources */,
C0E345581C582ECB00E749C2 /* ecvt.c in Sources */,
C0E345591C582ECB00E749C2 /* gcvt.c in Sources */,
- C0E3455A1C582ECB00E749C2 /* qsort_b-fbsd.c in Sources */,
+ C0E3455A1C582ECB00E749C2 /* qsort_b.c in Sources */,
C0E3455B1C582ECB00E749C2 /* asctime.c in Sources */,
C0E3455C1C582ECB00E749C2 /* difftime.c in Sources */,
C0E3455D1C582ECB00E749C2 /* ftime.c in Sources */,
C0E345C11C582ECB00E749C2 /* (null) in Sources */,
C0E345C21C582ECB00E749C2 /* (null) in Sources */,
C0E345C31C582ECB00E749C2 /* scandir_b.c in Sources */,
- C0E345C41C582ECB00E749C2 /* init_cpu_capabilities.c in Sources */,
- C0E345C51C582ECB00E749C2 /* pthread_getspecific.s in Sources */,
- C0E345C61C582ECB00E749C2 /* pthread_self.s in Sources */,
- C0E345C71C582ECB00E749C2 /* pthread_set_self.s in Sources */,
- C0E345C81C582ECB00E749C2 /* start_wqthread.s in Sources */,
- C0E345C91C582ECB00E749C2 /* thread_start.s in Sources */,
C0E345CA1C582ECB00E749C2 /* strcpy.c in Sources */,
C0E345CB1C582ECB00E749C2 /* strlcpy.c in Sources */,
C0E345CC1C582ECB00E749C2 /* strncpy.c in Sources */,
C9257F93138E1C9700B3107C /* addr2ascii.c in Sources */,
C9257F94138E1C9700B3107C /* ascii2addr.c in Sources */,
C9257F95138E1C9700B3107C /* inet_addr.c in Sources */,
+ 92888B171EA5BE8000BA923E /* open_memstream.c in Sources */,
C9257F96138E1C9700B3107C /* inet_lnaof.c in Sources */,
C9257F97138E1C9700B3107C /* inet_makeaddr.c in Sources */,
C9257F98138E1C9700B3107C /* inet_net_ntop.c in Sources */,
C9258002138E1CC000B3107C /* wprintf.c in Sources */,
C9258003138E1CC000B3107C /* wscanf.c in Sources */,
C9258004138E1CC000B3107C /* wsetup.c in Sources */,
+ 92888B181EA5BE8600BA923E /* open_wmemstream.c in Sources */,
C9258005138E1CC000B3107C /* asctime.c in Sources */,
C9258006138E1CC000B3107C /* difftime.c in Sources */,
C9258007138E1CC000B3107C /* ftime.c in Sources */,
C925804A138E1CD200B3107C /* wcspbrk.c in Sources */,
C925804B138E1CD200B3107C /* wcsrchr.c in Sources */,
C925804C138E1CD200B3107C /* wcsspn.c in Sources */,
+ 92888B161EA5BE7400BA923E /* fmemopen.c in Sources */,
C925804D138E1CD200B3107C /* wcsstr.c in Sources */,
C925804E138E1CD200B3107C /* wcstok.c in Sources */,
C925804F138E1CD200B3107C /* wcswidth.c in Sources */,
C9FA3348138E4D040089A94B /* l64a.c in Sources */,
C9FA334A138E4D040089A94B /* ecvt.c in Sources */,
C9FA334B138E4D040089A94B /* gcvt.c in Sources */,
- C9FA334C138E4D040089A94B /* qsort_b-fbsd.c in Sources */,
+ C9FA334C138E4D040089A94B /* qsort_b.c in Sources */,
C9D94359138EC0C600FB7ACC /* heapsort_b.c in Sources */,
C9D9435A138EC0C600FB7ACC /* heapsort_r.c in Sources */,
C9421021138F2602004BA536 /* _ldtoa.c in Sources */,
C942123913900C8A004BA536 /* strfmon.c in Sources */,
C942123A13900C8A004BA536 /* ecvt.c in Sources */,
C942123B13900C8A004BA536 /* gcvt.c in Sources */,
- C942123C13900C8A004BA536 /* qsort_b-fbsd.c in Sources */,
+ C942123C13900C8A004BA536 /* qsort_b.c in Sources */,
C942123D13900C8A004BA536 /* asctime.c in Sources */,
C942123E13900C8A004BA536 /* difftime.c in Sources */,
C942123F13900C8A004BA536 /* ftime.c in Sources */,
C94212BA13900C8A004BA536 /* unpack.c in Sources */,
C94212BB13900C8A004BA536 /* unparse.c in Sources */,
C94212C613900C8A004BA536 /* scandir_b.c in Sources */,
- C98E2B4C139851B7002A3ABB /* init_cpu_capabilities.c in Sources */,
- C98E2B4D139851B7002A3ABB /* pthread_getspecific.s in Sources */,
- C98E2B4E139851B7002A3ABB /* pthread_self.s in Sources */,
- C98E2B4F139851B7002A3ABB /* pthread_set_self.s in Sources */,
- C98E2B50139851B7002A3ABB /* start_wqthread.s in Sources */,
- C98E2B51139851B7002A3ABB /* thread_start.s in Sources */,
6310518713D4D966004F7BA8 /* strcpy.c in Sources */,
6310518C13D4DABD004F7BA8 /* strlcpy.c in Sources */,
6310518F13D4DAEA004F7BA8 /* strncpy.c in Sources */,
C95B80E4138F3C55004311DA /* strfmon.c in Sources */,
C95B80E5138F3C55004311DA /* ecvt.c in Sources */,
C95B80E6138F3C55004311DA /* gcvt.c in Sources */,
- C95B80E7138F3C55004311DA /* qsort_b-fbsd.c in Sources */,
+ C95B80E7138F3C55004311DA /* qsort_b.c in Sources */,
C95B80E8138F3C55004311DA /* asctime.c in Sources */,
C95B80E9138F3C55004311DA /* difftime.c in Sources */,
C95B80EA138F3C55004311DA /* ftime.c in Sources */,
C95B838F138F52B0004311DA /* strfmon.c in Sources */,
C95B8390138F52B0004311DA /* ecvt.c in Sources */,
C95B8391138F52B0004311DA /* gcvt.c in Sources */,
- C95B8392138F52B0004311DA /* qsort_b-fbsd.c in Sources */,
+ C95B8392138F52B0004311DA /* qsort_b.c in Sources */,
C95B8393138F52B0004311DA /* asctime.c in Sources */,
C95B8394138F52B0004311DA /* difftime.c in Sources */,
C95B8395138F52B0004311DA /* ftime.c in Sources */,
C95B8635138F53DB004311DA /* strfmon.c in Sources */,
C95B8636138F53DB004311DA /* ecvt.c in Sources */,
C95B8637138F53DB004311DA /* gcvt.c in Sources */,
- C95B8638138F53DB004311DA /* qsort_b-fbsd.c in Sources */,
+ C95B8638138F53DB004311DA /* qsort_b.c in Sources */,
C95B8639138F53DB004311DA /* asctime.c in Sources */,
C95B863A138F53DB004311DA /* difftime.c in Sources */,
C95B863B138F53DB004311DA /* ftime.c in Sources */,
C97A71771517AF53005E1998 /* strfmon.c in Sources */,
C97A71781517AF53005E1998 /* ecvt.c in Sources */,
C97A71791517AF53005E1998 /* gcvt.c in Sources */,
- C97A717A1517AF53005E1998 /* qsort_b-fbsd.c in Sources */,
+ C97A717A1517AF53005E1998 /* qsort_b.c in Sources */,
C97A717B1517AF53005E1998 /* asctime.c in Sources */,
C97A717C1517AF53005E1998 /* difftime.c in Sources */,
C97A717D1517AF53005E1998 /* ftime.c in Sources */,
C97A71F91517AF53005E1998 /* (null) in Sources */,
C97A71FA1517AF53005E1998 /* (null) in Sources */,
C97A71FD1517AF53005E1998 /* scandir_b.c in Sources */,
- C97A71FF1517AF53005E1998 /* init_cpu_capabilities.c in Sources */,
- C97A72001517AF53005E1998 /* pthread_getspecific.s in Sources */,
- C97A72011517AF53005E1998 /* pthread_self.s in Sources */,
- C97A72021517AF53005E1998 /* pthread_set_self.s in Sources */,
- C97A72031517AF53005E1998 /* start_wqthread.s in Sources */,
- C97A72041517AF53005E1998 /* thread_start.s in Sources */,
C97A720D1517AF53005E1998 /* strcpy.c in Sources */,
C97A720E1517AF53005E1998 /* strlcpy.c in Sources */,
C97A720F1517AF53005E1998 /* strncpy.c in Sources */,
C9B53E77138DA59F0028D27C /* strcpy.s in Sources */,
C9B53E7A138DA59F0028D27C /* strlen.s in Sources */,
C9B53E7C138DA59F0028D27C /* strncpy.s in Sources */,
- C921D3891395B7DD001CE070 /* init_cpu_capabilities.c in Sources */,
- C921D38A1395B7DD001CE070 /* pthread_getspecific.s in Sources */,
- C921D38B1395B7DD001CE070 /* pthread_self.s in Sources */,
- C921D38C1395B7DD001CE070 /* pthread_set_self.s in Sources */,
- C921D38D1395B7DD001CE070 /* start_wqthread.s in Sources */,
- C921D38E1395B7DD001CE070 /* thread_start.s in Sources */,
63505E3D1548525D00B637D7 /* strnlen.s in Sources */,
639D126C15595DDE00D0403A /* strnlen.s in Sources */,
);
C97660B9138EC61A00741512 /* strfmon.c in Sources */,
C97660BA138EC61A00741512 /* ecvt.c in Sources */,
C97660BB138EC61A00741512 /* gcvt.c in Sources */,
- C97660BC138EC61A00741512 /* qsort_b-fbsd.c in Sources */,
+ C97660BC138EC61A00741512 /* qsort_b.c in Sources */,
C97660BD138EC61A00741512 /* asctime.c in Sources */,
C97660BE138EC61A00741512 /* difftime.c in Sources */,
C97660BF138EC61A00741512 /* ftime.c in Sources */,
C9EB31D4138F6D880075BB52 /* strfmon.c in Sources */,
C9EB31D5138F6D880075BB52 /* ecvt.c in Sources */,
C9EB31D6138F6D880075BB52 /* gcvt.c in Sources */,
- C9EB31D7138F6D880075BB52 /* qsort_b-fbsd.c in Sources */,
+ C9EB31D7138F6D880075BB52 /* qsort_b.c in Sources */,
C9EB31D8138F6D880075BB52 /* asctime.c in Sources */,
C9EB31D9138F6D880075BB52 /* difftime.c in Sources */,
C9EB31DA138F6D880075BB52 /* ftime.c in Sources */,
C9EB347B138F75580075BB52 /* strfmon.c in Sources */,
C9EB347C138F75580075BB52 /* ecvt.c in Sources */,
C9EB347D138F75580075BB52 /* gcvt.c in Sources */,
- C9EB347E138F75580075BB52 /* qsort_b-fbsd.c in Sources */,
+ C9EB347E138F75580075BB52 /* qsort_b.c in Sources */,
C9EB347F138F75580075BB52 /* asctime.c in Sources */,
C9EB3480138F75580075BB52 /* difftime.c in Sources */,
C9EB3481138F75580075BB52 /* ftime.c in Sources */,
target = 3F51206A16C3174300AFB431 /* FortifySource */;
targetProxy = 3F51211616C318EB00AFB431 /* PBXContainerItemProxy */;
};
+ 926F73A21E046E69001E049D /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 926F73911E03E2A3001E049D /* libsystem_darwin.dylib */;
+ targetProxy = 926F73A11E046E69001E049D /* PBXContainerItemProxy */;
+ };
928F25D51BEAD2AE007B13C7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 928F25D01BEACED7007B13C7 /* darwintests */;
};
name = Release;
};
+ 926F73931E03E2A4001E049D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_ENABLE_CPP_EXCEPTIONS = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "_LIBC_NO_FEATURE_VERIFICATION=1",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ LIBRARY_SEARCH_PATHS = /usr/lib/system;
+ OTHER_LDFLAGS = "$(LIBSYSTEM_DARWIN_LDFLAGS)";
+ PRIVATE_HEADERS_FOLDER_PATH = "$(DARWIN_PRIVATE_HEADERS_FOLDER_PATH)";
+ PRODUCT_NAME = darwin;
+ PUBLIC_HEADERS_FOLDER_PATH = "$(DARWIN_PUBLIC_HEADERS_FOLDER_PATH)";
+ SKIP_INSTALL = NO;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 926F73941E03E2A4001E049D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_ENABLE_CPP_EXCEPTIONS = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "_LIBC_NO_FEATURE_VERIFICATION=1",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ LIBRARY_SEARCH_PATHS = /usr/lib/system;
+ OTHER_LDFLAGS = "$(LIBSYSTEM_DARWIN_LDFLAGS)";
+ PRIVATE_HEADERS_FOLDER_PATH = "$(DARWIN_PRIVATE_HEADERS_FOLDER_PATH)";
+ PRODUCT_NAME = darwin;
+ PUBLIC_HEADERS_FOLDER_PATH = "$(DARWIN_PUBLIC_HEADERS_FOLDER_PATH)";
+ SKIP_INSTALL = NO;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+ 926F739F1E046E56001E049D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 926F73A01E046E56001E049D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
928F25D21BEACED7007B13C7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
buildSettings = {
EXCLUDED_SOURCE_FILE_NAMES = "$(BASE_EXCLUDED_SOURCE_FILE_NAMES)";
EXECUTABLE_PREFIX = lib;
- GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
buildSettings = {
EXCLUDED_SOURCE_FILE_NAMES = "$(BASE_EXCLUDED_SOURCE_FILE_NAMES)";
EXECUTABLE_PREFIX = lib;
- GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
PRODUCT_NAME = NetBSD;
};
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 926F73951E03E2A4001E049D /* Build configuration list for PBXNativeTarget "libsystem_darwin.dylib" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 926F73931E03E2A4001E049D /* Debug */,
+ 926F73941E03E2A4001E049D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 926F739E1E046E56001E049D /* Build configuration list for PBXAggregateTarget "Libc_darwin" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 926F739F1E046E56001E049D /* Debug */,
+ 926F73A01E046E56001E049D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
928F25D11BEACED7007B13C7 /* Build configuration list for PBXLegacyTarget "darwintests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
# OSThermalNotification APIs
FEATURE_THERM_NOTIFICATION_APIS = 1
-# Move localtime to /var/db/timezone
-FEATURE_MOVE_LOCALTIME = 1
-
-# Use TZDIR symlink in /var/db
-FEATURE_TZDIR_SYMLINK = 1
-
-.if RC_ProjectName _Sim$
-FEATURE_MOVE_LOCALTIME = 0
-FEATURE_TZDIR_SYMLINK = 0
-.endif
-
# No pre-1050 variants (should match sys/cdefs.h)
FEATURE_ONLY_1050_VARIANTS = 1
#
-# Selectable features for Apple Watch
+# Selectable features for bridgeOS
#
# Legacy *64 APIs
# OSThermalNotification APIs
FEATURE_THERM_NOTIFICATION_APIS = 1
-# Move localtime to /var/db/timezone
-FEATURE_MOVE_LOCALTIME = 0
-
-# Use TZDIR symlink in /var/db
-FEATURE_TZDIR_SYMLINK = 0
-
# No pre-1050 variants (should match sys/cdefs.h)
FEATURE_ONLY_1050_VARIANTS = 1
# OSThermalNotification APIs
FEATURE_THERM_NOTIFICATION_APIS = 1
-# Move localtime to /var/db/timezone
-FEATURE_MOVE_LOCALTIME = 1
-
-# Use TZDIR symlink in /var/db
-FEATURE_TZDIR_SYMLINK = 1
-
-.if RC_ProjectName _Sim$
-FEATURE_MOVE_LOCALTIME = 0
-FEATURE_TZDIR_SYMLINK = 0
-.endif
-
# No pre-1050 variants (should match sys/cdefs.h)
FEATURE_ONLY_1050_VARIANTS = 1
# OSThermalNotification APIs
FEATURE_THERM_NOTIFICATION_APIS = 1
-# Move localtime to /var/db/timezone
-#FEATURE_MOVE_LOCALTIME = 1
-
-# Use TZDIR symlink in /var/db
-#FEATURE_TZDIR_SYMLINK = 1
-
# No pre-1050 variants (should match sys/cdefs.h)
#FEATURE_ONLY_1050_VARIANTS = 1
# OSThermalNotification APIs
FEATURE_THERM_NOTIFICATION_APIS = 1
-# Move localtime to /var/db/timezone
-FEATURE_MOVE_LOCALTIME = 1
-
-# Use TZDIR symlink in /var/db
-FEATURE_TZDIR_SYMLINK = 1
-
-.if RC_ProjectName _Sim$
-FEATURE_MOVE_LOCALTIME = 0
-FEATURE_TZDIR_SYMLINK = 0
-.endif
-
# No pre-1050 variants (should match sys/cdefs.h)
FEATURE_ONLY_1050_VARIANTS = 1
+++ /dev/null
-/*
- * Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#define __APPLE_API_PRIVATE
-#include <machine/cpu_capabilities.h>
-#undef __APPLE_API_PRIVATE
-
-extern int _get_cpu_capabilities(void);
-
-int _cpu_capabilities = 0;
-int _cpu_has_altivec = 0; // DEPRECATED: use _cpu_capabilities instead
-
-__private_extern__ void
-_init_cpu_capabilities( void )
-{
-}
{
to->f_bsize = from->f_iosize;
to->f_frsize = from->f_bsize;
- to->f_blocks = from->f_blocks;
- to->f_bfree = from->f_bfree;
- to->f_bavail = from->f_bavail;
- to->f_files = from->f_files;
- to->f_ffree = from->f_ffree;
- to->f_favail = from->f_ffree;
+ to->f_blocks = (fsblkcnt_t)from->f_blocks;
+ to->f_bfree = (fsblkcnt_t)from->f_bfree;
+ to->f_bavail = (fsblkcnt_t)from->f_bavail;
+ to->f_files = (fsfilcnt_t)from->f_files;
+ to->f_ffree = (fsfilcnt_t)from->f_ffree;
+ to->f_favail = (fsfilcnt_t)from->f_ffree;
to->f_fsid = from->f_fsid.val[0]; /* XXX bad if non-root */
to->f_namemax = NAME_MAX; /* XXX should be per FS */
#define __wait wait
#define __waitpid waitpid
+/*
+ * The _GENERIC_DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This returns the amount of space in struct direct
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
#define _GENERIC_DIRSIZ(dp) \
(((unsigned long)&((struct dirent *)0)->d_name + (dp)->d_namlen+1 + 3) & ~3)
(a)[0] = (uint32_t)(u).bits.manl; \
(a)[1] = (uint32_t)(u).bits.manh; \
} while(0)
-#elif defined(__arm__)
+#elif defined(__arm__) || defined(__arm64__)
union IEEEl2bits {
long double e;
#ifndef _SPINLOCK_H_
#define _SPINLOCK_H_
#ifdef __APPLE__
-#include <pthread_spinlock.h>
+#include <os/lock.h>
-typedef pthread_lock_t spinlock_t;
+typedef os_unfair_lock spinlock_t;
-#define _SPINLOCK_INITIALIZER LOCK_INITIALIZER
+#define _SPINLOCK_INITIALIZER OS_UNFAIR_LOCK_INIT
#define _SPINLOCK(_lck) \
do { \
- _DO_SPINLOCK_LOCK(_lck); \
+ os_unfair_lock_lock(_lck); \
} while (0)
#define _SPINUNLOCK(_lck) \
do { \
- _DO_SPINLOCK_UNLOCK(_lck); \
+ os_unfair_lock_unlock(_lck); \
} while (0)
#else /* ! __APPLE__ */
__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
char **rve)
{
-#if defined(__arm__)
+#if defined(__arm__) || defined(__arm64__)
/* On arm, double == long double, so short circuit this */
char * ret = __dtoa((double)*ld, mode, ndigits, decpt, sign, rve);
if (*decpt == 9999)
else { /* long double */
union IEEEl2bits u;
u.e = nanl(cp);
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
x0[1] = (ULong)u.bits.manh;
x0[0] = (ULong)u.bits.manl;
#else
#define IEEE_MC68k
#endif
#define Arith_Kind_ASL 1
+#elif defined(__arm64__)
+#define IEEE_8087
+#define Arith_Kind_ASL 1
+#define Long int
+#define Intcast (int)(long)
+#define Double_Align
+#define X64_bit_pointers
#else
#error Unsupported architecture
#endif
#define ldus_QNAN3 0x0
#define ldus_QNAN4 0x0
-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
#define f_QNAN 0x7fc00000
#define d_QNAN0 0x0
.Xr random 3 ,
and
.Xr rand48 3 .
-They can be called in almost environments, including
-.Xr chroot 2
+They can be called in almost all environments, including
+.Xr chroot 2 ,
and their use is encouraged over all other standard library functions for
random numbers.
.Pp
uint8_t entropy[BUFFERSIZE];
int ret;
- rng_custom.ecb = ccaes_ecb_encrypt_mode();
+ rng_custom.ctr_info = ccaes_ctr_crypt_mode();
rng_custom.keylen = 16;
rng_custom.strictFIPS = 0;
rng_custom.use_df = 1;
static char sccsid[] = "@(#)closedir.c 8.1 (Berkeley) 6/10/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/closedir.c,v 1.13 2007/12/03 14:33:50 des Exp $");
+__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/types.h>
/*
* close a directory.
*/
-int
-closedir(dirp)
- DIR *dirp;
+static int
+_fdclosedir(DIR *dirp)
{
int fd;
if (__isthreaded)
_pthread_mutex_lock(&dirp->dd_lock);
-#if !__DARWIN_UNIX03
- _seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */
-#endif /* __DARWIN_UNIX03 */
fd = dirp->dd_fd;
dirp->dd_fd = -1;
dirp->dd_loc = 0;
_pthread_mutex_destroy(&dirp->dd_lock);
}
free((void *)dirp);
- return(_close(fd));
+ return (fd);
+}
+
+int
+closedir(DIR *dirp)
+{
+
+ return (_close(_fdclosedir(dirp)));
}
void
err_set_exit(void (*ef)(int))
{
+#ifdef __BLOCKS__
+ if (_e_err_exit.type == ERR_EXIT_BLOCK) {
+ Block_release(_e_err_exit.block);
+ _e_err_exit.block = NULL;
+ }
+#endif /* __BLOCKS__ */
_e_err_exit.type = ef ? ERR_EXIT_FUNC : ERR_EXIT_UNDEF;
_e_err_exit.func = ef;
}
void
err_set_exit_b(void (^ef)(int))
{
+ if (_e_err_exit.type == ERR_EXIT_BLOCK) {
+ Block_release(_e_err_exit.block);
+ }
_e_err_exit.type = ef ? ERR_EXIT_BLOCK : ERR_EXIT_UNDEF;
_e_err_exit.block = Block_copy(ef);
}
.\" SUCH DAMAGE.
.\"
.\" @(#)getcwd.3 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/lib/libc/gen/getcwd.3,v 1.17 2007/01/09 00:27:53 imp Exp $
+.\" $FreeBSD$
.\"
-.Dd November 24, 1997
+.Dd April 17, 2010
.Dt GETCWD 3
.Os
.Sh NAME
.Fa buf
is
.Dv NULL ,
-space is allocated as necessary to store the pathname.
+space is allocated as necessary to store the pathname and
+.Fa size
+is ignored.
This space may later be
.Xr free 3 Ns 'd .
.Pp
function
will fail if:
.Bl -tag -width Er
-.It Bq Er EACCES
-Read or search permission was denied for a component of the pathname.
.It Bq Er EINVAL
The
.Fa size
argument is greater than zero but smaller than the length of the pathname
plus 1.
.El
+.Pp
+The
+.Fn getcwd
+function
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Read or search permission was denied for a component of the pathname.
+This is only checked in limited cases, depending on implementation details.
+.El
.Sh SEE ALSO
.Xr chdir 2 ,
.Xr fchdir 2 ,
getlogin_r(char *logname, size_t namelen)
{
char *result;
- int len;
int status;
pthread_mutex_lock(&__logname_mutex);
.\" @(#)getmntinfo.3 8.1 (Berkeley) 6/9/93
.\" $FreeBSD: src/lib/libc/gen/getmntinfo.3,v 1.13 2007/01/09 00:27:54 imp Exp $
.\"
-.Dd May 4, 2010
+.Dd April 12, 2017
.Dt GETMNTINFO 3
.Os
.Sh NAME
.Nm getmntinfo
+.Nm getmntinfo_r_np
.Nm getmntinfo64
.Nd get information about mounted file systems
.Sh SYNOPSIS
.In sys/mount.h
.Ft int
.Fn getmntinfo "struct statfs **mntbufp" "int flags"
+.Ft int
+.Fn getmntinfo_r_np "struct statfs **mntbufp" "int flags"
.Sh TRANSITIIONAL SYNOPSIS (NOW DEPRECATED)
.Ft int
.br
.Pp
The
.Fn getmntinfo
-function
-passes its
+and
+.Fn getmntinfo_r_np
+functions
+pass their
.Fa flags
argument transparently to
.Xr getfsstat 2 .
+.Pp
+The
+.Fn getmntinfo
+function maintains ownership of the results buffer it allocates,
+and may overwrite or free this buffer in subsequent calls to
+.Fn getmntinfo .
+For this reason,
+.Fn getmntinfo
+is not thread-safe.
+.Pp
+The
+.Fn getmntinfo_r_np
+function is a thread-safe equivalent of
+.Fn getmntinfo
+that allocates a new results buffer on every call and transfers ownership
+of this buffer to the caller.
+The caller is responsible for freeing this memory with
+.Xr free 3 .
.Sh RETURN VALUES
On successful completion,
.Fn getmntinfo
-returns a count of the number of elements in the array.
+and
+.Fn getmntinfo_r_np
+return a count of the number of elements in the array.
The pointer to the array is stored into
.Fa mntbufp .
.Pp
If an error occurs, zero is returned and the external variable
.Va errno
is set to indicate the error.
-Although the pointer
-.Fa mntbufp
-will be unmodified, any information previously returned by
+The
+.Fn getmntinfo
+function may modify the
+.Fa mbtbufp
+pointer even in the case of an error.
+In this situation, callers should consider any previous information
+returned by
.Fn getmntinfo
-will be lost.
+to be lost.
+The
+.Fn getmntinfo_r_np
+function will not modify the
+.Fa mntbufp
+pointer in the case of an error.
.Sh ERRORS
The
.Fn getmntinfo
-function
+and
+.Fn getmntinfo_r_np
+functions
may fail and set errno for any of the errors specified for the library
routines
.Xr getfsstat 2
.Fn getmntinfo
function first appeared in
.Bx 4.4 .
+The
+.Fn getmntinfo_r_np
+function first appeared in macOS 10.13.
.Sh BUGS
The
.Fn getmntinfo
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
+#include <errno.h>
#include <stdlib.h>
+struct getmntinfo_vars {
+ struct statfs *mntbuf;
+ int mntsize;
+ long bufsize;
+};
+
/*
* Return information about mounted filesystems.
*/
-int
-getmntinfo(mntbufp, flags)
- struct statfs **mntbufp;
- int flags;
+static int
+getmntinfo_internal(struct getmntinfo_vars *vars, int flags)
{
- static struct statfs *mntbuf;
- static int mntsize;
- static long bufsize;
- if (mntsize <= 0 && (mntsize = getfsstat(0, 0, MNT_NOWAIT)) < 0)
+ if (vars->mntsize <= 0 &&
+ (vars->mntsize = getfsstat(0, 0, MNT_NOWAIT)) < 0) {
return (0);
- if (bufsize > 0 && (mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+ }
+ if (vars->bufsize > 0 &&
+ (vars->mntsize =
+ getfsstat(vars->mntbuf, vars->bufsize, flags)) < 0) {
return (0);
- while (bufsize <= mntsize * sizeof(struct statfs)) {
- if (mntbuf)
- free(mntbuf);
- bufsize = (mntsize + 1) * sizeof(struct statfs);
- if ((mntbuf = (struct statfs *)malloc(bufsize)) == 0)
+ }
+ while (vars->bufsize <= vars->mntsize * sizeof(struct statfs)) {
+ if (vars->mntbuf) {
+ free(vars->mntbuf);
+ }
+ vars->bufsize = (vars->mntsize + 1) * sizeof(struct statfs);
+ if ((vars->mntbuf =
+ (struct statfs *)malloc(vars->bufsize)) == 0) {
return (0);
- if ((mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+ }
+ if ((vars->mntsize =
+ getfsstat(vars->mntbuf, vars->bufsize, flags)) < 0) {
return (0);
+ }
+ }
+ return (vars->mntsize);
+}
+
+/* Legacy version that keeps the buffer around. */
+int
+getmntinfo(struct statfs **mntbufp, int flags)
+{
+ static struct getmntinfo_vars vars;
+ int rv;
+
+ rv = getmntinfo_internal(&vars, flags);
+ /* Unconditional assignment matches legacy behavior. */
+ *mntbufp = vars.mntbuf;
+ return (rv);
+}
+
+/* Thread-safe version where the caller owns the newly-allocated buffer. */
+int
+getmntinfo_r_np(struct statfs **mntbufp, int flags)
+{
+ struct getmntinfo_vars vars = { 0 };
+ int rv, save_errno;
+
+ if ((rv = getmntinfo_internal(&vars, flags)) != 0) {
+ *mntbufp = vars.mntbuf;
+ } else {
+ save_errno = errno;
+ free(vars.mntbuf);
+ errno = save_errno;
}
- *mntbufp = mntbuf;
- return (mntsize);
+ return (rv);
}
error = getsockopt(s, 0, LOCAL_PEERCRED, &xuc, &xuclen);
if (error != 0)
return (error);
- if (xuc.cr_version != XUCRED_VERSION)
- return (EINVAL);
+ if (xuc.cr_version != XUCRED_VERSION) {
+ errno = EINVAL;
+ return (-1);
+ }
*euid = xuc.cr_uid;
*egid = xuc.cr_gid;
return (0);
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 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.
.\"
.\" SUCH DAMAGE.
.\"
.\" @(#)glob.3 8.3 (Berkeley) 4/16/94
-.\" $FreeBSD: src/lib/libc/gen/glob.3,v 1.32 2007/01/09 00:27:54 imp Exp $
+.\" $FreeBSD$
.\"
-.Dd May 20, 2008
+.Dd June 11, 2017
.Dt GLOB 3
.Os
.Sh NAME
.Nm glob ,
-#ifdef UNIFDEF_BLOCKS
.Nm glob_b ,
-#endif
.Nm globfree
.Nd generate pathnames matching a pattern
.Sh SYNOPSIS
.In glob.h
.Ft int
-.Fo glob
-.Fa "const char *restrict pattern"
-.Fa "int flags"
-.Fa "int (*errfunc)(const char *epath, int errno)"
-.Fa "glob_t *restrict pglob"
-.Fc
-#ifdef UNIFDEF_BLOCKS
+.Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *epath, int errno)" "glob_t * restrict pglob"
.Ft int
-.Fo glob_b
-.Fa "const char *restrict pattern"
-.Fa "int flags"
-.Fa "int (^errblk)(const char *epath, int errno)"
-.Fa "glob_t *restrict pglob"
-.Fc
-#endif
+.Fn glob "const char * restrict pattern" "int flags" "int (^errblk)(const char *epath, int errno)" "glob_t * restrict pglob"
.Ft void
-.Fo globfree
-.Fa "glob_t *pglob"
-.Fc
+.Fn globfree "glob_t *pglob"
.Sh DESCRIPTION
The
.Fn glob
is set, backslash escaping is disabled.
.It Dv GLOB_NOSORT
By default, the pathnames are sorted in ascending
-.Tn ASCII
+collation
order;
this flag prevents that sorting (speeding up
.Fn glob ) .
or
.Fa errfunc
returns zero, the error is ignored.
-#ifdef UNIFDEF_BLOCKS
.Pp
The
.Fn glob_b
.Fn glob
except that the error callback is a block pointer instead of a function
pointer.
-#endif
.Pp
The
.Fn globfree
function frees any space associated with
.Fa pglob
from a previous call(s) to
-#ifdef UNIFDEF_BLOCKS
.Fn glob
or
.Fn glob_b .
-#else
-.Fn glob .
-#endif
.Sh RETURN VALUES
On successful completion,
.Fn glob
-#ifdef UNIFDEF_BLOCKS
and
.Fn glob_b
return zero.
-#else
-returns zero.
-#endif
In addition, the fields of
.Fa pglob
contain the values described below:
contains the total number of matched pathnames so far.
This includes other matches from previous invocations of
.Fn glob
-#ifdef UNIFDEF_BLOCKS
or
.Fn glob_b
-#endif
if
.Dv GLOB_APPEND
was specified.
.It Fa gl_matchc
contains the number of matched pathnames in the current invocation of
-#ifdef UNIFDEF_BLOCKS
.Fn glob
or
.Fn glob_b .
-#else
-.Fn glob .
-#endif
.It Fa gl_flags
contains a copy of the
.Fa flags
.Pp
If
.Fn glob
-#ifdef UNIFDEF_BLOCKS
or
.Fn glob_b
-#endif
terminates due to an error, it sets errno and returns one of the
following non-zero constants, which are defined in the include
file
.It Dv GLOB_NOSPACE
An attempt to allocate memory failed, or if
.Fa errno
-was 0
+was E2BIG,
.Dv GLOB_LIMIT
was specified in the flags and
.Fa pglob\->gl_matchc
.Sh CAVEATS
The
.Fn glob
-#ifdef UNIFDEF_BLOCKS
and
.Fn glob_b
functions
-#else
-function
-#endif
will not match filenames that begin with a period
unless this is specifically requested (e.g., by ".*").
.Sh SEE ALSO
.Fn globfree
functions first appeared in
.Bx 4.4 .
-#ifdef UNIFDEF_BLOCKS
The
.Fn glob_b
function first appeared in Mac OS X 10.6.
-#endif
.Sh BUGS
Patterns longer than
.Dv MAXPATHLEN
.Pp
The
.Fn glob
-#ifdef UNIFDEF_BLOCKS
and
.Fn glob_b
functions
-#else
-function
-#endif
may fail and set errno for any of the errors specified for the
library routines
.Xr stat 2 ,
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 2. Redistributions in binary form must 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.
*
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Exp $");
+__FBSDID("$FreeBSD$");
#include "xlocale_private.h"
* 1. Patterns with illegal byte sequences match nothing - even if
* GLOB_NOCHECK is specified.
* 2. Illegal byte sequences in filenames are handled by treating them as
- * single-byte characters with a value of the first byte of the sequence
+ * single-byte characters with a values of such bytes of the sequence
* cast to wchar_t.
* 3. State-dependent encodings are not currently supported.
*/
#include <string.h>
#include <unistd.h>
#include <wchar.h>
+#include <malloc_private.h>
#include "collate.h"
-#define GLOB_LIMIT_STRING 65536 /* number of readdirs */
-#define GLOB_LIMIT_STAT 128 /* number of stat system calls */
-#define GLOB_LIMIT_READDIR 16384 /* total buffer size of path strings */
-#define GLOB_LIMIT_PATH 1024 /* number of path elements */
-#define GLOB_LIMIT_BRACE 128 /* Number of brace calls */
+/*
+ * glob(3) expansion limits. Stop the expansion if any of these limits
+ * is reached. This caps the runtime in the face of DoS attacks. See
+ * also CVE-2010-2632
+ */
+#define GLOB_LIMIT_BRACE 128 /* number of brace calls */
+#define GLOB_LIMIT_PATH 1024 /* number of path elements */
+#define GLOB_LIMIT_READDIR 16384 /* number of readdirs */
+#define GLOB_LIMIT_STAT 128 /* number of stat system calls */
+#define GLOB_LIMIT_STRING 65536 /* maximum total size for paths */
struct glob_limit {
- size_t l_string;
- size_t l_stat;
- size_t l_readdir;
- size_t l_brace;
+ size_t l_brace_cnt;
+ size_t l_path_lim;
+ size_t l_readdir_cnt;
+ size_t l_stat_cnt;
+ size_t l_string_cnt;
};
-#define DOLLAR '$'
-#define DOT '.'
-#define EOS '\0'
-#define LBRACKET '['
-#define NOT '!'
-#define QUESTION '?'
-#define QUOTE '\\'
-#define RANGE '-'
-#define RBRACKET ']'
-#define SEP '/'
-#define STAR '*'
-#define TILDE '~'
-#define UNDERSCORE '_'
-#define LBRACE '{'
-#define RBRACE '}'
-#define SLASH '/'
-#define COMMA ','
-
-#ifndef DEBUG
+#define DOT L'.'
+#define EOS L'\0'
+#define LBRACKET L'['
+#define NOT L'!'
+#define QUESTION L'?'
+#define QUOTE L'\\'
+#define RANGE L'-'
+#define RBRACKET L']'
+#define SEP L'/'
+#define STAR L'*'
+#define TILDE L'~'
+#define LBRACE L'{'
+#define RBRACE L'}'
+#define COMMA L','
#define M_QUOTE 0x8000000000ULL
#define M_PROTECT 0x4000000000ULL
typedef uint_fast64_t Char;
-#else
-
-#define M_QUOTE 0x80
-#define M_PROTECT 0x40
-#define M_MASK 0xff
-#define M_CHAR 0x7f
-
-typedef char Char;
-
-#endif
-
-
#define CHAR(c) ((Char)((c)&M_CHAR))
#define META(c) ((Char)((c)|M_QUOTE))
-#define M_ALL META('*')
-#define M_END META(']')
-#define M_NOT META('!')
-#define M_ONE META('?')
-#define M_RNG META('-')
-#define M_SET META('[')
+#define UNPROT(c) ((c) & ~M_PROTECT)
+#define M_ALL META(L'*')
+#define M_END META(L']')
+#define M_NOT META(L'!')
+#define M_ONE META(L'?')
+#define M_RNG META(L'-')
+#define M_SET META(L'[')
#define ismeta(c) (((c)&M_QUOTE) != 0)
+#ifdef DEBUG
+#define isprot(c) (((c)&M_PROTECT) != 0)
+#endif
#define compare __gl_compare
#define globextend __gl_globextend
#define globtilde __gl_globtilde
#define match __gl_match
+
__private_extern__ int compare(const void *, const void *);
__private_extern__ int g_Ctoc(const Char *, char *, size_t, locale_t);
-__private_extern__ const Char *g_strchr(const Char *, wchar_t);
-__private_extern__ int globextend(const Char *, glob_t *, struct glob_limit *, locale_t);
-__private_extern__ const Char *
- globtilde(const Char *, Char *, size_t, glob_t *);
-__private_extern__ int match(Char *, Char *, Char *, locale_t);
-
-
static int g_lstat(Char *, struct stat *, glob_t *, locale_t);
static DIR *g_opendir(Char *, glob_t *, locale_t);
+__private_extern__ const Char *g_strchr(const Char *, wchar_t);
#ifdef notdef
static Char *g_strcat(Char *, const Char *);
#endif
static int g_stat(Char *, struct stat *, glob_t *, locale_t);
-static int glob0(const Char *, glob_t *, struct glob_limit *, locale_t);
+static int glob0(const Char *, glob_t *, struct glob_limit *,
+ const char *,locale_t);
static int glob1(Char *, glob_t *, struct glob_limit *, locale_t);
-static int glob2(Char *, Char *, Char *, Char *, glob_t *, struct glob_limit *, locale_t);
-static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, struct glob_limit *, locale_t);
+static int glob2(Char *, Char *, Char *, Char *, glob_t *,
+ struct glob_limit *, locale_t);
+static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *,
+ struct glob_limit *, locale_t);
+__private_extern__ int globextend(const Char *, glob_t *, struct glob_limit *,
+ const char *, locale_t);
+__private_extern__ const Char * globtilde(const Char *, Char *, size_t, glob_t *,
+ locale_t);
+static int globexp0(const Char *, glob_t *, struct glob_limit *,
+ const char *, locale_t);
static int globexp1(const Char *, glob_t *, struct glob_limit *, locale_t);
-static int globexp2(const Char *, const Char *, glob_t *, int *, struct glob_limit *, locale_t);
+static int globexp2(const Char *, const Char *, glob_t *,
+ struct glob_limit *, locale_t);
+static int globfinal(glob_t *, struct glob_limit *, size_t,
+ const char *, locale_t);
+__private_extern__ int match(Char *, Char *, Char *, locale_t);
+static int err_nomatch(glob_t *, struct glob_limit *, const char *, locale_t loc);
+static int err_aborted(glob_t *, int, char *);
#ifdef DEBUG
static void qprintf(const char *, Char *);
#endif
static int
__glob(const char *pattern, glob_t *pglob)
{
+ struct glob_limit limit = { 0, 0, 0, 0, 0 };
const char *patnext;
- struct glob_limit limit = { 0, 0, 0, 0 };
Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
mbstate_t mbs;
wchar_t wc;
size_t clen;
+ int too_long;
locale_t loc = __current_locale();
int mb_cur_max = MB_CUR_MAX_L(loc);
if (!(pglob->gl_flags & GLOB_DOOFFS))
pglob->gl_offs = 0;
}
+ if (pglob->gl_flags & GLOB_LIMIT) {
+ limit.l_path_lim = pglob->gl_matchc;
+ if (limit.l_path_lim == 0)
+ limit.l_path_lim = GLOB_LIMIT_PATH;
+ }
pglob->gl_matchc = 0;
bufnext = patbuf;
bufend = bufnext + MAXPATHLEN - 1;
+ too_long = 1;
if (pglob->gl_flags & GLOB_NOESCAPE) {
memset(&mbs, 0, sizeof(mbs));
while (bufend - bufnext >= mb_cur_max) {
clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc);
if (clen == (size_t)-1 || clen == (size_t)-2)
- return (GLOB_NOMATCH);
- else if (clen == 0)
+ return (err_nomatch(pglob, &limit, pattern, loc));
+ else if (clen == 0) {
+ too_long = 0;
break;
+ }
*bufnext++ = wc;
patnext += clen;
}
/* Protect the quoted characters. */
memset(&mbs, 0, sizeof(mbs));
while (bufend - bufnext >= mb_cur_max) {
- if (*patnext == QUOTE) {
- if (*++patnext == EOS) {
- *bufnext++ = QUOTE | M_PROTECT;
+ if (*patnext == '\\') {
+ if (*++patnext == '\0') {
+ *bufnext++ = QUOTE;
continue;
}
prot = M_PROTECT;
prot = 0;
clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc);
if (clen == (size_t)-1 || clen == (size_t)-2)
- return (GLOB_NOMATCH);
- else if (clen == 0)
+ return (err_nomatch(pglob, &limit, pattern, loc));
+ else if (clen == 0) {
+ too_long = 0;
break;
+ }
*bufnext++ = wc | prot;
patnext += clen;
}
}
+ if (too_long)
+ return (err_nomatch(pglob, &limit, pattern, loc));
*bufnext = EOS;
if (pglob->gl_flags & GLOB_BRACE)
- return globexp1(patbuf, pglob, &limit, loc);
+ return globexp0(patbuf, pglob, &limit, pattern, loc);
else
- return glob0(patbuf, pglob, &limit, loc);
+ return glob0(patbuf, pglob, &limit, pattern, loc);
}
int
}
#endif /* __BLOCKS__ */
+static int
+globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat, locale_t loc) {
+ int rv;
+ size_t oldpathc;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (glob0(pattern, pglob, limit, origpat, loc));
+ }
+
+ oldpathc = pglob->gl_pathc;
+
+ if ((rv = globexp1(pattern, pglob, limit, loc)) != 0)
+ return rv;
+
+ return (globfinal(pglob, limit, oldpathc, origpat, loc));
+}
+
/*
* Expand recursively a glob {} pattern. When there is no more expansion
* invoke the standard globbing routine to glob the rest of the magic
static int
globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
{
- const Char* ptr = pattern;
- int rv;
+ const Char* ptr;
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- limit->l_brace++ >= GLOB_LIMIT_BRACE) {
- errno = 0;
- return GLOB_NOSPACE;
+ if ((ptr = g_strchr(pattern, LBRACE)) != NULL) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (globexp2(ptr, pattern, pglob, limit, loc));
}
- /* Protect a single {}, for find(1), like csh */
- if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
- return glob0(pattern, pglob, limit, loc);
-
- while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
- if (!globexp2(ptr, pattern, pglob, &rv, limit, loc))
- return rv;
-
- return glob0(pattern, pglob, limit, loc);
+ return (glob0(pattern, pglob, limit, NULL, loc));
}
* If it fails then it tries to glob the rest of the pattern and returns.
*/
static int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, struct glob_limit *limit, locale_t loc)
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
+ struct glob_limit *limit, locale_t loc)
{
- int i;
+ int i, rv;
Char *lm, *ls;
const Char *pe, *pm, *pm1, *pl;
Char patbuf[MAXPATHLEN];
ls = lm;
/* Find the balanced brace */
- for (i = 0, pe = ++ptr; *pe; pe++)
+ for (i = 0, pe = ++ptr; *pe != EOS; pe++)
if (*pe == LBRACKET) {
/* Ignore everything between [] */
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
}
/* Non matching braces; just glob the pattern */
- if (i != 0 || *pe == EOS) {
- *rv = glob0(patbuf, pglob, limit, loc);
- return 0;
- }
+ if (i != 0 || *pe == EOS)
+ return (glob0(pattern, pglob, limit, NULL, loc));
for (i = 0, pl = pm = ptr; pm <= pe; pm++)
switch (*pm) {
#ifdef DEBUG
qprintf("globexp2:", patbuf);
#endif
- *rv = globexp1(patbuf, pglob, limit, loc);
+ rv = globexp1(patbuf, pglob, limit, loc);
+ if (rv)
+ return (rv);
/* move after the comma, to the next string */
pl = pm + 1;
default:
break;
}
- *rv = 0;
- return 0;
+ return (0);
}
* expand tilde from the passwd file.
*/
__private_extern__ const Char *
-globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
+globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob, locale_t loc)
{
struct passwd *pwd;
- char *h;
+ char *h, *sc;
const Char *p;
Char *b, *eb;
+ wchar_t wc;
+ wchar_t wbuf[MAXPATHLEN];
+ wchar_t *wbufend, *dc;
+ size_t clen;
+ mbstate_t mbs;
+ int too_long;
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
- return pattern;
+ return (pattern);
/*
* Copy up to the end of the string or /
*/
eb = &patbuf[patbuf_len - 1];
- for (p = pattern + 1, h = (char *) patbuf;
- h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
+ for (p = pattern + 1, b = patbuf;
+ b < eb && *p != EOS && UNPROT(*p) != SEP; *b++ = *p++)
continue;
- *h = EOS;
+ if (*p != EOS && UNPROT(*p) != SEP)
+ return (NULL);
+
+ *b = EOS;
+ h = NULL;
- if (((char *) patbuf)[0] == EOS) {
+ if (patbuf[0] == EOS) {
/*
* handle a plain ~ or ~/ by expanding $HOME first (iff
* we're not running setuid or setgid) and then trying
(pwd = getpwuid(getuid())) != NULL)
h = pwd->pw_dir;
else
- return pattern;
+ return (pattern);
}
}
else {
/*
* Expand a ~user
*/
- if ((pwd = getpwnam((char*) patbuf)) == NULL)
- return pattern;
+ if (g_Ctoc(patbuf, (char *)wbuf, sizeof(wbuf), loc))
+ return (NULL);
+ if ((pwd = getpwnam((char *)wbuf)) == NULL)
+ return (pattern);
else
h = pwd->pw_dir;
}
/* Copy the home directory */
- for (b = patbuf; b < eb && *h; *b++ = *h++)
+ dc = wbuf;
+ sc = h;
+ wbufend = wbuf + MAXPATHLEN - 1;
+ too_long = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ while (dc <= wbufend) {
+ clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
+ break;
+ }
+ sc += clen;
+ }
+ if (too_long)
+ return (NULL);
+
+ dc = wbuf;
+ for (b = patbuf; b < eb && *dc != EOS; *b++ = *dc++ | M_PROTECT)
continue;
+ if (*dc != EOS)
+ return (NULL);
/* Append the rest of the pattern */
- while (b < eb && (*b++ = *p++) != EOS)
- continue;
- *b = EOS;
+ if (*p != EOS) {
+ too_long = 1;
+ while (b <= eb) {
+ if ((*b++ = *p++) == EOS) {
+ too_long = 0;
+ break;
+ }
+ }
+ if (too_long)
+ return (NULL);
+ } else
+ *b = EOS;
- return patbuf;
+ return (patbuf);
}
#endif /* BUILDING_VARIANT */
* if things went well, nonzero if errors occurred.
*/
static int
-glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
+glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat, locale_t loc)
{
const Char *qpatnext;
int err;
size_t oldpathc;
Char *bufnext, c, patbuf[MAXPATHLEN];
- qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+ qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob, loc);
+ if (qpatnext == NULL) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
/* We don't need to check for buffer overflow any more. */
while ((c = *qpatnext++) != EOS) {
- if (c & M_PROTECT) {
- *bufnext++ = CHAR(c);
- continue;
- } /* else */
switch (c) {
case LBRACKET:
c = *qpatnext;
case STAR:
pglob->gl_flags |= GLOB_MAGCHAR;
/* collapse adjacent stars to one,
- * to avoid exponential behavior
+ * to ensure "**" at the end continues to match the
+ * empty string
*/
if (bufnext == patbuf || bufnext[-1] != M_ALL)
*bufnext++ = M_ALL;
if ((err = glob1(patbuf, pglob, limit, loc)) != 0)
return(err);
- /*
- * If there was no match we are going to append the pattern
- * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
- * and the pattern did not contain any magic characters
- * GLOB_NOMAGIC is there just for compatibility with csh.
- */
- if (pglob->gl_pathc == oldpathc) {
- if (((pglob->gl_flags & GLOB_NOCHECK) ||
- ((pglob->gl_flags & GLOB_NOMAGIC) &&
- !(pglob->gl_flags & GLOB_MAGCHAR))))
- return(globextend(pattern, pglob, limit, loc));
- else
- return(GLOB_NOMATCH);
- }
+ if (origpat != NULL)
+ return (globfinal(pglob, limit, oldpathc, origpat, loc));
+
+ return (0);
+}
+
+static int
+globfinal(glob_t *pglob, struct glob_limit *limit, size_t oldpathc,
+ const char *origpat, locale_t loc) {
+ if (pglob->gl_pathc == oldpathc)
+ return (err_nomatch(pglob, limit, origpat, loc));
+
if (!(pglob->gl_flags & GLOB_NOSORT))
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
- return(0);
+
+ return (0);
}
#ifndef BUILDING_VARIANT
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
if (*pattern == EOS)
- return(0);
- return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
+ return (0);
+ return (glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
pattern, pglob, limit, loc));
}
if (*pattern == EOS) { /* End of pattern? */
*pathend = EOS;
if (g_lstat(pathbuf, &sb, pglob, loc))
- return(0);
+ return (0);
if ((pglob->gl_flags & GLOB_LIMIT) &&
- limit->l_stat++ >= GLOB_LIMIT_STAT) {
- errno = 0;
- *pathend++ = SEP;
- *pathend = EOS;
- return GLOB_NOSPACE;
+ limit->l_stat_cnt++ >= GLOB_LIMIT_STAT) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
}
- if (((pglob->gl_flags & GLOB_MARK) &&
- pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
- || (S_ISLNK(sb.st_mode) &&
- (g_stat(pathbuf, &sb, pglob, loc) == 0) &&
- S_ISDIR(sb.st_mode)))) {
- if (pathend + 1 > pathend_last)
- return (GLOB_ABORTED);
+ if ((pglob->gl_flags & GLOB_MARK) &&
+ UNPROT(pathend[-1]) != SEP &&
+ (S_ISDIR(sb.st_mode) ||
+ (S_ISLNK(sb.st_mode) &&
+ g_stat(pathbuf, &sb, pglob, loc) == 0 &&
+ S_ISDIR(sb.st_mode)))) {
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*pathend++ = SEP;
*pathend = EOS;
}
++pglob->gl_matchc;
- return(globextend(pathbuf, pglob, limit, loc));
+ return (globextend(pathbuf, pglob, limit, NULL, loc));
}
/* Find end of next segment, copy tentatively to pathend. */
q = pathend;
p = pattern;
- while (*p != EOS && *p != SEP) {
+ while (*p != EOS && UNPROT(*p) != SEP) {
if (ismeta(*p))
anymeta = 1;
- if (q + 1 > pathend_last)
- return (GLOB_ABORTED);
+ if (q + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*q++ = *p++;
}
if (!anymeta) { /* No expansion, do next segment. */
pathend = q;
pattern = p;
- while (*pattern == SEP) {
- if (pathend + 1 > pathend_last)
- return (GLOB_ABORTED);
+ while (UNPROT(*pattern) == SEP) {
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*pathend++ = *pattern++;
}
} else /* Need expansion, recurse. */
- return(glob3(pathbuf, pathend, pathend_last, pattern, p,
- pglob, limit, loc));
+ return(glob3(pathbuf, pathend, pathend_last, pattern,
+ p, pglob, limit, loc));
}
/* NOTREACHED */
}
{
struct dirent *dp;
DIR *dirp;
- int err;
- char buf[MAXPATHLEN];
+ int err, too_long, saverrno, saverrno2;
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
/*
* The readdirfunc declaration can't be prototyped, because it is
*/
struct dirent *(*readdirfunc)();
- if (pathend > pathend_last)
- return (GLOB_ABORTED);
+ if (pathend > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*pathend = EOS;
+ if ((pglob->gl_errfunc != NULL || pglob->gl_errblk != NULL) &&
+ g_Ctoc(pathbuf, buf, sizeof(buf), loc)) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+
+ saverrno = errno;
errno = 0;
if ((dirp = g_opendir(pathbuf, pglob, loc)) == NULL) {
- /* TODO: don't call for ENOENT or ENOTDIR? */
- if (pglob->gl_errfunc) {
- if (g_Ctoc(pathbuf, buf, sizeof(buf), loc))
- return (GLOB_ABORTED);
-#ifdef __BLOCKS__
- if (pglob->gl_flags & _GLOB_ERR_BLOCK) {
- if (pglob->gl_errblk(buf, errno))
- return (GLOB_ABORTED);
- } else
-#endif /* __BLOCKS__ */
- if (pglob->gl_errfunc(buf, errno))
- return (GLOB_ABORTED);
- }
- if (pglob->gl_flags & GLOB_ERR)
- return (GLOB_ABORTED);
- return(0);
+ if (errno == ENOENT || errno == ENOTDIR)
+ return (0);
+
+ err = err_aborted(pglob, errno, buf);
+ if (errno == 0)
+ errno = saverrno;
+ return (err);
}
err = 0;
- /* Search directory for matching names. */
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
readdirfunc = pglob->gl_readdir;
else
readdirfunc = readdir;
- while ((dp = (*readdirfunc)(dirp))) {
+
+ errno = 0;
+ /* Search directory for matching names. */
+ while ((dp = (*readdirfunc)(dirp)) != NULL) {
char *sc;
Char *dc;
wchar_t wc;
mbstate_t mbs;
if ((pglob->gl_flags & GLOB_LIMIT) &&
- limit->l_readdir++ >= GLOB_LIMIT_READDIR) {
- errno = 0;
- *pathend++ = SEP;
- *pathend = EOS;
- return GLOB_NOSPACE;
+ limit->l_readdir_cnt++ >= GLOB_LIMIT_READDIR) {
+ errno = E2BIG;
+ err = GLOB_NOSPACE;
+ break;
}
/* Initial DOT must be matched literally. */
- if (dp->d_name[0] == DOT && *pattern != DOT)
+ if (dp->d_name[0] == '.' && UNPROT(*pattern) != DOT) {
+ errno = 0;
continue;
+ }
memset(&mbs, 0, sizeof(mbs));
dc = pathend;
sc = dp->d_name;
- while (dc < pathend_last) {
+ too_long = 1;
+ while (dc <= pathend_last) {
clen = mbrtowc_l(&wc, sc, MB_LEN_MAX, &mbs, loc);
if (clen == (size_t)-1 || clen == (size_t)-2) {
- wc = *sc;
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
clen = 1;
memset(&mbs, 0, sizeof(mbs));
}
- if ((*dc++ = wc) == EOS)
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
break;
+ }
sc += clen;
}
- if (!match(pathend, pattern, restpattern, loc)) {
+ if (too_long && (err = err_aborted(pglob, ENAMETOOLONG,
+ buf))) {
+ errno = ENAMETOOLONG;
+ break;
+ }
+ if (too_long || !match(pathend, pattern, restpattern, loc)) {
*pathend = EOS;
+ errno = 0;
continue;
}
+ if (errno == 0)
+ errno = saverrno;
err = glob2(pathbuf, --dc, pathend_last, restpattern,
pglob, limit, loc);
if (err)
break;
+ errno = 0;
}
+ saverrno2 = errno;
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
(*pglob->gl_closedir)(dirp);
else
closedir(dirp);
- return(err);
+ errno = saverrno2;
+
+ if (err)
+ return (err);
+
+ if (dp == NULL && errno != 0 &&
+ (err = err_aborted(pglob, errno, buf)))
+ return (err);
+
+ if (errno == 0)
+ errno = saverrno;
+ return (0);
}
#ifndef BUILDING_VARIANT
/*
- * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
* add the new item, and update gl_pathc.
*
* This assumes the BSD realloc, which only copies the block when its size
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
__private_extern__ int
-globextend(const Char *path, glob_t *pglob, struct glob_limit *limit, locale_t loc)
+globextend(const Char *path, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat, locale_t loc)
{
char **pathv;
- size_t i, newsize, len;
+ size_t i, newn, len;
char *copy;
const Char *p;
- newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
if ((pglob->gl_flags & GLOB_LIMIT) &&
- newsize > GLOB_LIMIT_PATH * sizeof(*pathv))
- goto nospace;
- pathv = pglob->gl_pathv ?
- realloc((char *)pglob->gl_pathv, newsize) :
- malloc(newsize);
- if (pathv == NULL) {
- if (pglob->gl_pathv) {
- free(pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
- return(GLOB_NOSPACE);
+ pglob->gl_matchc > limit->l_path_lim) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
}
+ newn = 2 + pglob->gl_pathc + pglob->gl_offs;
+ /* reallocarray(NULL, newn, size) is equivalent to malloc(newn*size). */
+ pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv));
+ if (pathv == NULL)
+ return (GLOB_NOSPACE);
+
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
pathv += pglob->gl_offs;
}
pglob->gl_pathv = pathv;
- for (p = path; *p++;)
- continue;
- len = MB_CUR_MAX_L(loc) * (size_t)(p - path); /* XXX overallocation */
- limit->l_string += len;
- if ((copy = malloc(len)) != NULL) {
- if (g_Ctoc(path, copy, len, loc)) {
+ if (origpat != NULL)
+ copy = strdup(origpat);
+ else {
+ for (p = path; *p++ != EOS;)
+ continue;
+ len = MB_CUR_MAX_L(loc) * (size_t)(p - path); /* XXX overallocation */
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len, loc)) {
+ free(copy);
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ }
+ }
+ if (copy != NULL) {
+ limit->l_string_cnt += strlen(copy) + 1;
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_string_cnt >= GLOB_LIMIT_STRING) {
free(copy);
+ errno = E2BIG;
return (GLOB_NOSPACE);
}
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
}
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- (newsize + limit->l_string) >= GLOB_LIMIT_STRING)
- goto nospace;
-
- return(copy == NULL ? GLOB_NOSPACE : 0);
-nospace:
- errno = 0;
- return GLOB_NOSPACE;
+ return (copy == NULL ? GLOB_NOSPACE : 0);
}
/*
- * pattern matching function for filenames. Each occurrence of the *
- * pattern causes a recursion level.
+ * pattern matching function for filenames.
*/
__private_extern__ int
match(Char *name, Char *pat, Char *patend, locale_t loc)
{
int ok, negate_range;
- Char c, k;
-
- while (pat < patend) {
- c = *pat++;
- switch (c & M_MASK) {
- case M_ALL:
- if (pat == patend)
- return(1);
- do
- if (match(name, pat, patend, loc))
- return(1);
- while (*name++ != EOS);
- return(0);
- case M_ONE:
- if (*name++ == EOS)
- return(0);
- break;
- case M_SET:
- ok = 0;
- if ((k = *name++) == EOS)
- return(0);
- if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
- ++pat;
- while (((c = *pat++) & M_MASK) != M_END)
- if ((*pat & M_MASK) == M_RNG) {
- if (loc->__collate_load_error ?
- CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
- __collate_range_cmp(CHAR(c), CHAR(k), loc) <= 0
- && __collate_range_cmp(CHAR(k), CHAR(pat[1]), loc) <= 0
- )
+ Char c, k, *nextp, *nextn;
+
+ nextn = NULL;
+ nextp = NULL;
+
+ while (1) {
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return (1);
+ if (*name == EOS)
+ return (0);
+ nextn = name + 1;
+ nextp = pat - 1;
+ break;
+ case M_ONE:
+ if (*name++ == EOS)
+ goto fail;
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ goto fail;
+ negate_range = ((*pat & M_MASK) == M_NOT);
+ if (negate_range != 0)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (loc->__collate_load_error ?
+ CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
+ __collate_range_cmp(CHAR(c), CHAR(k), loc) <= 0
+ && __collate_range_cmp(CHAR(k), CHAR(pat[1]), loc) <= 0
+ ) {
+ ok = 1;
+ }
+ pat += 2;
+ } else if (c == k)
ok = 1;
- pat += 2;
- } else if (c == k)
- ok = 1;
- if (ok == negate_range)
- return(0);
- break;
- default:
- if (*name++ != c)
- return(0);
- break;
+ if (ok == negate_range)
+ goto fail;
+ break;
+ default:
+ if (*name++ != c)
+ goto fail;
+ break;
+ }
}
+ if (*name == EOS)
+ return (1);
+
+ fail:
+ if (nextn == NULL)
+ break;
+ pat = nextp;
+ name = nextn;
}
- return(*name == EOS);
+ return (0);
}
/* Free allocated data belonging to a glob_t structure. */
static DIR *
g_opendir(Char *str, glob_t *pglob, locale_t loc)
{
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
- if (!*str)
+ if (*str == EOS)
strcpy(buf, ".");
else {
- if (g_Ctoc(str, buf, sizeof(buf), loc))
+ if (g_Ctoc(str, buf, sizeof(buf), loc)) {
+ errno = ENAMETOOLONG;
return (NULL);
+ }
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_opendir)(buf));
+ return ((*pglob->gl_opendir)(buf));
- return(opendir(buf));
+ return (opendir(buf));
}
static int
g_lstat(Char *fn, struct stat *sb, glob_t *pglob, locale_t loc)
{
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
if (g_Ctoc(fn, buf, sizeof(buf), loc)) {
errno = ENAMETOOLONG;
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_lstat)(buf, sb));
- return(lstat(buf, sb));
+ return (lstat(buf, sb));
}
static int
g_stat(Char *fn, struct stat *sb, glob_t *pglob, locale_t loc)
{
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
if (g_Ctoc(fn, buf, sizeof(buf), loc)) {
errno = ENAMETOOLONG;
return (-1);
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_stat)(buf, sb));
- return(stat(buf, sb));
+ return ((*pglob->gl_stat)(buf, sb));
+ return (stat(buf, sb));
}
#ifndef BUILDING_VARIANT
memset(&mbs, 0, sizeof(mbs));
while (len >= mb_cur_max) {
clen = wcrtomb_l(buf, *str, &mbs, loc);
- if (clen == (size_t)-1)
- return (1);
- if (*str == L'\0')
+ if (clen == (size_t)-1) {
+ /* XXX See initial comment #2. */
+ *buf = (char)CHAR(*str);
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if (CHAR(*str) == EOS)
return (0);
str++;
buf += clen;
}
#endif /* !BUILDING_VARIANT */
+static int
+err_nomatch(glob_t *pglob, struct glob_limit *limit, const char *origpat, locale_t loc) {
+ /*
+ * If there was no match we are going to append the origpat
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the origpat did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR)))
+ return (globextend(NULL, pglob, limit, origpat, loc));
+ return (GLOB_NOMATCH);
+}
+
+static int
+err_aborted(glob_t *pglob, int err, char *buf) {
+#ifdef __BLOCKS__
+ if (pglob->gl_flags & _GLOB_ERR_BLOCK && pglob->gl_errblk(buf, errno)) {
+ return (GLOB_ABORTED);
+ } else
+#endif /* __BLOCKS__ */
+ if (pglob->gl_errfunc != NULL && pglob->gl_errfunc(buf, errno)) {
+ return (GLOB_ABORTED);
+ } else if (pglob->gl_flags & GLOB_ERR) {
+ return (GLOB_ABORTED);
+ }
+ return (0);
+}
+
#ifdef DEBUG
static void
qprintf(const char *str, Char *s)
{
Char *p;
- (void)printf("%s:\n", str);
- for (p = s; *p; p++)
- (void)printf("%c", CHAR(*p));
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", ismeta(*p) ? '_' : ' ');
- (void)printf("\n");
+ (void)printf("%s\n", str);
+ if (s != NULL) {
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (char)CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (isprot(*p) ? '\\' : ' '));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (ismeta(*p) ? '_' : ' '));
+ (void)printf("\n");
+ }
}
#endif
#include "telldir.h"
-static DIR * __opendir_common(int, const char *, int);
+static DIR * __opendir_common(int, int, bool);
/*
* Open a directory.
errno = ENOTDIR;
return (NULL);
}
+ /* Make sure CLOEXEC is set on the fd */
if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
return (NULL);
- return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP));
+ return (__opendir_common(fd, DTF_HIDEW|DTF_NODUP, true));
}
DIR *
__opendir2(const char *name, int flags)
{
int fd;
+ DIR *dir;
+ int saved_errno;
+ if ((flags & (__DTF_READALL | __DTF_SKIPREAD)) != 0)
+ return (NULL);
if ((fd = _open(name,
O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1)
return (NULL);
- return __opendir_common(fd, name, flags);
+ dir = __opendir_common(fd, flags, false);
+ if (dir == NULL) {
+ saved_errno = errno;
+ _close(fd);
+ errno = saved_errno;
+ }
+ return (dir);
}
static int
(*(const struct dirent **)p2)->d_name));
}
+/*
+ * For a directory at the top of a unionfs stack, the entire directory's
+ * contents are read and cached locally until the next call to rewinddir().
+ * For the fdopendir() case, the initial seek position must be preserved.
+ * For rewinddir(), the full directory should always be re-read from the
+ * beginning.
+ *
+ * If an error occurs, the existing buffer and state of 'dirp' is left
+ * unchanged.
+ */
+bool
+_filldir(DIR *dirp, bool use_current_pos)
+{
+ struct dirent **dpv;
+ char *buf, *ddptr, *ddeptr;
+ off_t pos;
+ int fd2, incr, len, n, saved_errno, space;
+
+ len = 0;
+ space = 0;
+ buf = NULL;
+ ddptr = NULL;
+
+ /*
+ * Use the system page size if that is a multiple of DIRBLKSIZ.
+ * Hopefully this can be a big win someday by allowing page
+ * trades to user space to be done by _getdirentries().
+ */
+ incr = getpagesize();
+ if ((incr % DIRBLKSIZ) != 0)
+ incr = DIRBLKSIZ;
+
+ /*
+ * The strategy here is to read all the directory
+ * entries into a buffer, sort the buffer, and
+ * remove duplicate entries by setting the inode
+ * number to zero.
+ *
+ * We reopen the directory because _getdirentries()
+ * on a MNT_UNION mount modifies the open directory,
+ * making it refer to the lower directory after the
+ * upper directory's entries are exhausted.
+ * This would otherwise break software that uses
+ * the directory descriptor for fchdir or *at
+ * functions, such as fts.c.
+ */
+ if ((fd2 = openat(dirp->dd_fd, ".", O_RDONLY | O_CLOEXEC)) == -1)
+ return (false);
+
+ if (use_current_pos) {
+ pos = lseek(dirp->dd_fd, 0, SEEK_CUR);
+ if (pos == -1 || lseek(fd2, pos, SEEK_SET) == -1) {
+ saved_errno = errno;
+ _close(fd2);
+ errno = saved_errno;
+ return (false);
+ }
+ }
+
+ do {
+ /*
+ * Always make at least DIRBLKSIZ bytes
+ * available to _getdirentries
+ */
+ if (space < DIRBLKSIZ) {
+ space += incr;
+ len += incr;
+ buf = reallocf(buf, len);
+ if (buf == NULL) {
+ saved_errno = errno;
+ _close(fd2);
+ errno = saved_errno;
+ return (false);
+ }
+ ddptr = buf + (len - space);
+ }
+
+#if __DARWIN_64_BIT_INO_T
+ n = (int)__getdirentries64(fd2, ddptr, space, &dirp->dd_td->seekoff);
+#else /* !__DARWIN_64_BIT_INO_T */
+ n = _getdirentries(fd2, ddptr, space, &dirp->dd_seek);
+#endif /* __DARWIN_64_BIT_INO_T */
+ if (n > 0) {
+ ddptr += n;
+ space -= n;
+ }
+ if (n < 0) {
+ saved_errno = errno;
+ _close(fd2);
+ errno = saved_errno;
+ return (false);
+ }
+ } while (n > 0);
+ _close(fd2);
+
+ ddeptr = ddptr;
+
+ /*
+ * There is now a buffer full of (possibly) duplicate
+ * names.
+ */
+ dirp->dd_buf = buf;
+
+ /*
+ * Go round this loop twice...
+ *
+ * Scan through the buffer, counting entries.
+ * On the second pass, save pointers to each one.
+ * Then sort the pointers and remove duplicate names.
+ */
+ for (dpv = NULL;;) {
+ n = 0;
+ ddptr = buf;
+ while (ddptr < ddeptr) {
+ struct dirent *dp;
+
+ dp = (struct dirent *) ddptr;
+ if ((long)dp & 03L)
+ break;
+ if ((dp->d_reclen <= 0) ||
+ (dp->d_reclen > (ddeptr + 1 - ddptr)))
+ break;
+ ddptr += dp->d_reclen;
+ if (dp->d_fileno) {
+ if (dpv)
+ dpv[n] = dp;
+ n++;
+ }
+ }
+
+ if (dpv) {
+ struct dirent *xp;
+
+ /*
+ * This sort must be stable.
+ */
+ mergesort(dpv, n, sizeof(*dpv), opendir_compar);
+
+ dpv[n] = NULL;
+ xp = NULL;
+
+ /*
+ * Scan through the buffer in sort order,
+ * zapping the inode number of any
+ * duplicate names.
+ */
+ for (n = 0; dpv[n]; n++) {
+ struct dirent *dp = dpv[n];
+
+ if ((xp == NULL) ||
+ strcmp(dp->d_name, xp->d_name)) {
+ xp = dp;
+ } else {
+ dp->d_fileno = 0;
+ }
+ if (dp->d_type == DT_WHT &&
+ (dirp->dd_flags & DTF_HIDEW))
+ dp->d_fileno = 0;
+ }
+
+ free(dpv);
+ break;
+ } else {
+ dpv = malloc((n+1) * sizeof(struct dirent *));
+ if (dpv == NULL)
+ break;
+ }
+ }
+
+ dirp->dd_len = len;
+ dirp->dd_size = ddptr - dirp->dd_buf;
+ return (true);
+}
+
+
/*
* Common routine for opendir(3), __opendir2(3) and fdopendir(3).
*/
static DIR *
-__opendir_common(int fd, const char *name, int flags)
+__opendir_common(int fd, int flags, bool use_current_pos)
{
DIR *dirp;
int incr;
if ((dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL)
return (NULL);
+ dirp->dd_buf = NULL;
+ dirp->dd_fd = fd;
+ dirp->dd_flags = flags;
+ dirp->dd_loc = 0;
+ dirp->dd_lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR));
LIST_INIT(&dirp->dd_td->td_locq);
dirp->dd_td->td_loccnt = 0;
}
if (unionstack) {
- int len = 0;
- int space = 0;
- char *buf = 0;
- char *ddptr = 0;
- char *ddeptr;
- int n;
- struct dirent **dpv;
-
- /*
- * The strategy here is to read all the directory
- * entries into a buffer, sort the buffer, and
- * remove duplicate entries by setting the inode
- * number to zero.
- */
-
- do {
+ if (!_filldir(dirp, use_current_pos))
+ goto fail;
+ dirp->dd_flags |= __DTF_READALL;
+ } else {
+ dirp->dd_len = incr;
+ dirp->dd_buf = malloc(dirp->dd_len);
+ if (dirp->dd_buf == NULL)
+ goto fail;
+ if (use_current_pos) {
/*
- * Always make at least DIRBLKSIZ bytes
- * available to _getdirentries
+ * Read the first batch of directory entries
+ * to prime dd_seek. This also checks if the
+ * fd passed to fdopendir() is a directory.
*/
- if (space < DIRBLKSIZ) {
- space += incr;
- len += incr;
- buf = reallocf(buf, len);
- if (buf == NULL)
- goto fail;
- ddptr = buf + (len - space);
- }
-
#if __DARWIN_64_BIT_INO_T
- n = (int)__getdirentries64(fd, ddptr, space, &dirp->dd_td->seekoff);
+ dirp->dd_size = (long)__getdirentries64(dirp->dd_fd,
+ dirp->dd_buf, dirp->dd_len, &dirp->dd_td->seekoff);
#else /* !__DARWIN_64_BIT_INO_T */
- n = _getdirentries(fd, ddptr, space, &dirp->dd_seek);
+ dirp->dd_size = _getdirentries(dirp->dd_fd,
+ dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
#endif /* __DARWIN_64_BIT_INO_T */
- if (n > 0) {
- ddptr += n;
- space -= n;
- }
- } while (n > 0);
-
- ddeptr = ddptr;
- flags |= __DTF_READALL;
-
- /*
- * Re-open the directory.
- * This has the effect of rewinding back to the
- * top of the union stack and is needed by
- * programs which plan to fchdir to a descriptor
- * which has also been read -- see fts.c.
- */
- if (flags & DTF_REWIND) {
- (void)_close(fd);
- if ((fd = _open(name, O_RDONLY | O_DIRECTORY)) == -1) {
- saved_errno = errno;
- free(buf);
- free(dirp);
- errno = saved_errno;
- return (NULL);
- }
- }
-
- /*
- * There is now a buffer full of (possibly) duplicate
- * names.
- */
- dirp->dd_buf = buf;
-
- /*
- * Go round this loop twice...
- *
- * Scan through the buffer, counting entries.
- * On the second pass, save pointers to each one.
- * Then sort the pointers and remove duplicate names.
- */
- for (dpv = 0;;) {
- n = 0;
- ddptr = buf;
- while (ddptr < ddeptr) {
- struct dirent *dp;
-
- dp = (struct dirent *) ddptr;
- if ((long)dp & 03L)
- break;
- if ((dp->d_reclen <= 0) ||
- (dp->d_reclen > (ddeptr + 1 - ddptr)))
- break;
- ddptr += dp->d_reclen;
- if (dp->d_fileno) {
- if (dpv)
- dpv[n] = dp;
- n++;
- }
+ if (dirp->dd_size < 0) {
+ if (errno == EINVAL)
+ errno = ENOTDIR;
+ goto fail;
}
-
- if (dpv) {
- struct dirent *xp;
-
- /*
- * This sort must be stable.
- */
- mergesort(dpv, n, sizeof(*dpv),
- opendir_compar);
-
- dpv[n] = NULL;
- xp = NULL;
-
- /*
- * Scan through the buffer in sort order,
- * zapping the inode number of any
- * duplicate names.
- */
- for (n = 0; dpv[n]; n++) {
- struct dirent *dp = dpv[n];
-
- if ((xp == NULL) ||
- strcmp(dp->d_name, xp->d_name)) {
- xp = dp;
- } else {
- dp->d_fileno = 0;
- }
- if (dp->d_type == DT_WHT &&
- (flags & DTF_HIDEW))
- dp->d_fileno = 0;
- }
-
- free(dpv);
- break;
- } else {
- dpv = malloc((n+1) * sizeof(struct dirent *));
- if (dpv == NULL)
- break;
- }
- }
-
- dirp->dd_len = len;
- dirp->dd_size = ddptr - dirp->dd_buf;
- } else {
- dirp->dd_len = incr;
- dirp->dd_size = 0;
- dirp->dd_buf = malloc(dirp->dd_len);
- if (dirp->dd_buf == NULL)
- goto fail;
+ dirp->dd_flags |= __DTF_SKIPREAD;
+ } else {
+ dirp->dd_size = 0;
#if __DARWIN_64_BIT_INO_T
- dirp->dd_td->seekoff = 0;
+ dirp->dd_td->seekoff = 0;
#else /* !__DARWIN_64_BIT_INO_T */
- dirp->dd_seek = 0;
+ dirp->dd_seek = 0;
#endif /* __DARWIN_64_BIT_INO_T */
- flags &= ~DTF_REWIND;
+ }
}
- dirp->dd_loc = 0;
- dirp->dd_fd = fd;
- dirp->dd_flags = flags;
- dirp->dd_lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
-
- /*
- * Set up seek point for rewinddir.
- */
- dirp->dd_rewind = telldir(dirp);
-
return (dirp);
fail:
saved_errno = errno;
+ free(dirp->dd_buf);
free(dirp);
- (void)_close(fd);
errno = saved_errno;
return (NULL);
}
static char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/readdir.c,v 1.15 2008/05/05 14:05:23 kib Exp $");
+__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/param.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
-#include <unistd.h>
#include "un-namespace.h"
#include "libc_private.h"
* get next entry in a directory.
*/
struct dirent *
-_readdir_unlocked(dirp, skip)
- DIR *dirp;
- int skip;
+_readdir_unlocked(DIR *dirp, int skip)
{
struct dirent *dp;
+ long initial_seek;
+ long initial_loc = 0;
for (;;) {
if (dirp->dd_loc >= dirp->dd_size) {
if (dirp->dd_flags & __DTF_READALL)
return (NULL);
+ initial_loc = dirp->dd_loc;
+ dirp->dd_flags &= ~__DTF_SKIPREAD;
dirp->dd_loc = 0;
}
- if (dirp->dd_loc == 0 && !(dirp->dd_flags & __DTF_READALL)) {
+ if (dirp->dd_loc == 0 &&
+ !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) {
#if __DARWIN_64_BIT_INO_T
- dirp->dd_size = __getdirentries64(dirp->dd_fd,
+ initial_seek = dirp->dd_td->seekoff;
+ dirp->dd_size = (long)__getdirentries64(dirp->dd_fd,
dirp->dd_buf, dirp->dd_len, &dirp->dd_td->seekoff);
#else /* !__DARWIN_64_BIT_INO_T */
+ initial_seek = dirp->dd_seek;
dirp->dd_size = _getdirentries(dirp->dd_fd,
dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
#endif /* __DARWIN_64_BIT_INO_T */
if (dirp->dd_size <= 0)
return (NULL);
+ _fixtelldir(dirp, initial_seek, initial_loc);
}
+ dirp->dd_flags &= ~__DTF_SKIPREAD;
dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
if ((long)dp & 03L) /* bogus pointer check */
return (NULL);
}
struct dirent *
-readdir(dirp)
- DIR *dirp;
+readdir(DIR *dirp)
{
struct dirent *dp;
}
int
-readdir_r(dirp, entry, result)
- DIR *dirp;
- struct dirent *entry;
- struct dirent **result;
+readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
{
struct dirent *dp;
int saved_errno;
static char sccsid[] = "@(#)rewinddir.c 8.1 (Berkeley) 6/8/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/rewinddir.c,v 1.6 2007/01/09 00:27:55 imp Exp $");
+__FBSDID("$FreeBSD$");
+#include "namespace.h"
#include <sys/types.h>
#include <dirent.h>
+#include <pthread.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "libc_private.h"
#include "telldir.h"
void
-rewinddir(dirp)
- DIR *dirp;
+rewinddir(DIR *dirp)
{
- _seekdir(dirp, dirp->dd_rewind);
- dirp->dd_rewind = telldir(dirp);
+ if (__isthreaded)
+ _pthread_mutex_lock(&dirp->dd_lock);
+ dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */
+ if (dirp->dd_flags & __DTF_READALL)
+ _filldir(dirp, false);
+ else {
+ (void) lseek(dirp->dd_fd, 0, SEEK_SET);
+#if __DARWIN_64_BIT_INO_T
+ dirp->dd_td->seekoff = 0;
+#else /* !__DARWIN_64_BIT_INO_T */
+ dirp->dd_seek = 0;
+#endif /* __DARWIN_64_BIT_INO_T */
+ }
+ dirp->dd_loc = 0;
+ _reclaim_telldir(dirp);
+ if (__isthreaded)
+ _pthread_mutex_unlock(&dirp->dd_lock);
}
static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.9 2008/03/16 19:08:53 das Exp $");
+__FBSDID("$FreeBSD$");
/*
* Scan the directory dirname calling select to make a list of selected
#include "un-namespace.h"
/*
- * The _GENERIC_DIRSIZ macro is the minimum record length which will hold the directory
+ * The DIRSIZ macro is the minimum record length which will hold the directory
* entry. This requires the amount of space in struct dirent without the
* d_name field, plus enough space for the name and a terminating nul byte
* (dp->d_namlen + 1), rounded up to a 4 byte boundary.
*/
+#undef DIRSIZ
+#define DIRSIZ(dp) \
+ ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
+ (((dp)->d_namlen + 1 + 3) &~ 3))
int
-scandir(dirname, namelist, select, _dcomp)
- const char *dirname;
- struct dirent ***namelist;
- int (*select)(const struct dirent *);
- int (*_dcomp)(const struct dirent **, const struct dirent **);
+#ifdef I_AM_SCANDIR_B
+scandir_b(const char *dirname, struct dirent ***namelist,
+ int (^select)(const struct dirent *),
+ int (^_dcomp)(const struct dirent **, const struct dirent **))
+#else
+scandir(const char *dirname, struct dirent ***namelist,
+ int (*select)(const struct dirent *),
+ int (*_dcomp)(const struct dirent **, const struct dirent **))
+#endif
{
struct dirent *d, *p, **names = NULL;
size_t nitems = 0;
long arraysz;
DIR *dirp;
- int (*dcomp)(const void *, const void *) = (void *)_dcomp; /* see <rdar://problem/10293482> */
+
+ /* see <rdar://problem/10293482> */
+#ifdef I_AM_SCANDIR_B
+ int (^dcomp)(const void *, const void *) = (void *)_dcomp;
+#else
+ int (*dcomp)(const void *, const void *) = (void *)_dcomp;
+#endif
if ((dirp = opendir(dirname)) == NULL)
return(-1);
goto fail;
while ((d = readdir(dirp)) != NULL) {
- if (select != NULL && !(*select)(d))
+ if (select != NULL && !select(d))
continue; /* just selected names */
/*
* Make a minimum size copy of the data
*/
- p = (struct dirent *)malloc(_GENERIC_DIRSIZ(d));
+ p = (struct dirent *)malloc(DIRSIZ(d));
if (p == NULL)
goto fail;
p->d_fileno = d->d_fileno;
}
closedir(dirp);
if (nitems && dcomp != NULL)
+#ifdef I_AM_SCANDIR_B
+ qsort_b(names, nitems, sizeof(struct dirent *), dcomp);
+#else
qsort(names, nitems, sizeof(struct dirent *), dcomp);
+#endif
*namelist = names;
- return(nitems);
+ return (int) (nitems);
fail:
while (nitems > 0)
free(names[--nitems]);
free(names);
closedir(dirp);
- return -1;
+ return (-1);
}
+#ifndef I_AM_SCANDIR_B
/*
* Alphabetic order comparison routine for those who want it.
+ * POSIX 2008 requires that alphasort() uses strcoll().
*/
int
-alphasort(d1, d2)
- const struct dirent **d1;
- const struct dirent **d2;
+alphasort(const struct dirent **d1, const struct dirent **d2)
{
- return(strcmp((*(struct dirent **)d1)->d_name,
- (*(struct dirent **)d2)->d_name));
+
+ return (strcoll((*d1)->d_name, (*d2)->d_name));
}
+#endif // I_AM_SCANDIR_B
+
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
+/*-
+ * Copyright (c) 2014 David Chisnall
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the 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)
* 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$
*/
+#ifdef __BLOCKS__
+#define I_AM_SCANDIR_B
+#include "scandir.c"
+#endif /* __BLOCKS__ */
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/scandir.c,v 1.9 2008/03/16 19:08:53 das Exp $");
-
-/*
- * Scan the directory dirname calling select to make a list of selected
- * directory entries then sort using qsort and compare routine dcomp.
- * Returns the number of entries and a pointer to a list of pointers to
- * struct dirent (through namelist). Returns -1 if there were any errors.
- */
-
-#include "namespace.h"
-#include <dirent.h>
-#include <stdlib.h>
-#include <string.h>
-#include "un-namespace.h"
-
-/*
- * The _GENERIC_DIRSIZ macro is the minimum record length which will hold the directory
- * entry. This requires the amount of space in struct dirent without the
- * d_name field, plus enough space for the name and a terminating nul byte
- * (dp->d_namlen + 1), rounded up to a 4 byte boundary.
- */
-
-int
-scandir_b(dirname, namelist, select, _dcomp)
- const char *dirname;
- struct dirent ***namelist;
- int (^select)(const struct dirent *);
- int (^_dcomp)(const struct dirent **, const struct dirent **);
-{
- struct dirent *d, *p, **names = NULL;
- size_t nitems = 0;
- long arraysz;
- DIR *dirp;
- int (^dcomp)(const void *, const void *) = (void *)_dcomp; /* see <rdar://problem/10293482> */
-
- if ((dirp = opendir(dirname)) == NULL)
- return(-1);
-
- arraysz = 32; /* initial estimate of the array size */
- names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
- if (names == NULL)
- goto fail;
-
- while ((d = readdir(dirp)) != NULL) {
- if (select != NULL && !select(d))
- continue; /* just selected names */
- /*
- * Make a minimum size copy of the data
- */
- p = (struct dirent *)malloc(_GENERIC_DIRSIZ(d));
- if (p == NULL)
- goto fail;
- p->d_fileno = d->d_fileno;
- p->d_type = d->d_type;
- p->d_reclen = d->d_reclen;
- p->d_namlen = d->d_namlen;
- bcopy(d->d_name, p->d_name, p->d_namlen + 1);
- /*
- * Check to make sure the array has space left and
- * realloc the maximum size.
- */
- if (nitems >= arraysz) {
- struct dirent **names2;
-
- names2 = (struct dirent **)realloc((char *)names,
- (arraysz * 2) * sizeof(struct dirent *));
- if (names2 == NULL) {
- free(p);
- goto fail;
- }
- names = names2;
- arraysz *= 2;
- }
- names[nitems++] = p;
- }
- closedir(dirp);
- if (nitems && dcomp != NULL)
- qsort_b(names, nitems, sizeof(struct dirent *), dcomp);
- *namelist = names;
- return(nitems);
-
-fail:
- while (nitems > 0)
- free(names[--nitems]);
- free(names);
- closedir(dirp);
- return -1;
-}
static char sccsid[] = "@(#)seekdir.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/seekdir.c,v 1.7 2007/12/03 14:33:51 des Exp $");
+__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/param.h>
* _seekdir is in telldir.c so that it can share opaque data structures.
*/
void
-seekdir(dirp, loc)
- DIR *dirp;
- long loc;
+seekdir(DIR *dirp, long loc)
{
if (__isthreaded)
_pthread_mutex_lock(&dirp->dd_lock);
static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/telldir.c,v 1.11 2008/05/05 14:05:23 kib Exp $");
+__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/param.h>
#include "libc_private.h"
#include "telldir.h"
-/*
- * The option SINGLEUSE may be defined to say that a telldir
- * cookie may be used only once before it is freed. This option
- * is used to avoid having memory usage grow without bound.
- */
-#if !__DARWIN_UNIX03
-#define SINGLEUSE
-#endif /* !__DARWIN_UNIX03 */
-
/*
* return a pointer into a directory
*/
long
-telldir(dirp)
- DIR *dirp;
+telldir(DIR *dirp)
{
struct ddloc *lp;
+ long idx;
-#if __DARWIN_UNIX03
if (__isthreaded)
_pthread_mutex_lock(&dirp->dd_lock);
LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) {
- if (
#if __DARWIN_64_BIT_INO_T
- (lp->loc_seek == dirp->dd_td->seekoff)
+ if (lp->loc_seek == dirp->dd_td->seekoff &&
#else /* !__DARWIN_64_BIT_INO_T */
- (lp->loc_seek == dirp->dd_seek)
+ if (lp->loc_seek == dirp->dd_seek &&
#endif /* __DARWIN_64_BIT_INO_T */
- && (lp->loc_loc == dirp->dd_loc))
- goto found;
- }
- if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) {
- if (__isthreaded)
- _pthread_mutex_unlock(&dirp->dd_lock);
- return (-1);
+ lp->loc_loc == dirp->dd_loc)
+ break;
}
-#else /* !__DARWIN_UNIX03 */
- if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
- return (-1);
- if (__isthreaded)
- _pthread_mutex_lock(&dirp->dd_lock);
-#endif /* __DARWIN_UNIX03 */
- lp->loc_index = dirp->dd_td->td_loccnt++;
+ if (lp == NULL) {
+ lp = malloc(sizeof(struct ddloc));
+ if (lp == NULL) {
+ if (__isthreaded)
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ return (-1);
+ }
+ lp->loc_index = dirp->dd_td->td_loccnt++;
#if __DARWIN_64_BIT_INO_T
- lp->loc_seek = dirp->dd_td->seekoff;
+ lp->loc_seek = dirp->dd_td->seekoff;
#else /* !__DARWIN_64_BIT_INO_T */
- lp->loc_seek = dirp->dd_seek;
+ lp->loc_seek = dirp->dd_seek;
#endif /* __DARWIN_64_BIT_INO_T */
- lp->loc_loc = dirp->dd_loc;
- LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe);
-#if __DARWIN_UNIX03
-found:
-#endif /* __DARWIN_UNIX03 */
+ lp->loc_loc = dirp->dd_loc;
+ LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe);
+ }
+ idx = lp->loc_index;
if (__isthreaded)
_pthread_mutex_unlock(&dirp->dd_lock);
- return (lp->loc_index);
+ return (idx);
}
/*
* Only values returned by "telldir" should be passed to seekdir.
*/
void
-_seekdir(dirp, loc)
- DIR *dirp;
- long loc;
+_seekdir(DIR *dirp, long loc)
{
struct ddloc *lp;
struct dirent *dp;
}
if (lp == NULL)
return;
- if (lp->loc_loc == dirp->dd_loc &&
#if __DARWIN_64_BIT_INO_T
- lp->loc_seek == dirp->dd_td->seekoff
+ if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_td->seekoff)
#else /* !__DARWIN_64_BIT_INO_T */
- lp->loc_seek == dirp->dd_seek
+ if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
#endif /* __DARWIN_64_BIT_INO_T */
- )
- goto found;
+ return;
+
+ /* If it's within the same chunk of data, don't bother reloading. */
+#if __DARWIN_64_BIT_INO_T
+ if (lp->loc_seek == dirp->dd_td->seekoff) {
+#else /* !__DARWIN_64_BIT_INO_T */
+ if (lp->loc_seek == dirp->dd_seek) {
+#endif /* __DARWIN_64_BIT_INO_T */
+ /*
+ * If we go back to 0 don't make the next readdir
+ * trigger a call to getdirentries().
+ */
+ if (lp->loc_loc == 0)
+ dirp->dd_flags |= __DTF_SKIPREAD;
+ dirp->dd_loc = lp->loc_loc;
+ return;
+ }
(void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET);
#if __DARWIN_64_BIT_INO_T
dirp->dd_td->seekoff = lp->loc_seek;
dirp->dd_seek = lp->loc_seek;
#endif /* __DARWIN_64_BIT_INO_T */
dirp->dd_loc = 0;
+ dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */
while (dirp->dd_loc < lp->loc_loc) {
dp = _readdir_unlocked(dirp, 0);
if (dp == NULL)
break;
}
-found:;
-#ifdef SINGLEUSE
- LIST_REMOVE(lp, loc_lqe);
- free((caddr_t)lp);
-#endif
+}
+
+/*
+ * After readdir returns the last entry in a block, a call to telldir
+ * returns a location that is after the end of that last entry.
+ * However, that location doesn't refer to a valid directory entry.
+ * Ideally, the call to telldir would return a location that refers to
+ * the first entry in the next block. That location is not known
+ * until the next block is read, so readdir calls this function after
+ * fetching a new block to fix any such telldir locations.
+ */
+void
+_fixtelldir(DIR *dirp, long oldseek, long oldloc)
+{
+ struct ddloc *lp;
+
+ lp = LIST_FIRST(&dirp->dd_td->td_locq);
+ if (lp != NULL) {
+ if (lp->loc_loc == oldloc &&
+ lp->loc_seek == oldseek) {
+#if __DARWIN_64_BIT_INO_T
+ lp->loc_seek = dirp->dd_td->seekoff;
+#else /* !__DARWIN_64_BIT_INO_T */
+ lp->loc_seek = dirp->dd_seek;
+#endif /* __DARWIN_64_BIT_INO_T */
+ lp->loc_loc = dirp->dd_loc;
+ }
+ }
}
#ifndef BUILDING_VARIANT
* Reclaim memory for telldir cookies which weren't used.
*/
void
-_reclaim_telldir(dirp)
- DIR *dirp;
+_reclaim_telldir(DIR *dirp)
{
struct ddloc *lp;
struct ddloc *templp;
}
LIST_INIT(&dirp->dd_td->td_locq);
}
-#endif /* !BUILDING_VARIANT */
+#endif
#define _TELLDIR_H_
#include <sys/queue.h>
+#include <stdbool.h>
/*
* One of these structures is malloced to describe the current directory
#if __DARWIN_64_BIT_INO_T
size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep);
#endif /* __DARWIN_64_BIT_INO_T */
+__attribute__ ((visibility ("hidden")))
+bool _filldir(DIR *, bool) __DARWIN_INODE64(_filldir);
struct dirent *_readdir_unlocked(DIR *, int) __DARWIN_INODE64(_readdir_unlocked);
void _reclaim_telldir(DIR *);
void _seekdir(DIR *, long) __DARWIN_ALIAS_I(_seekdir);
+__attribute__ ((visibility ("hidden")))
+void _fixtelldir(DIR *dirp, long oldseek, long oldloc) __DARWIN_INODE64(_fixtelldir);
long telldir(DIR *) __DARWIN_ALIAS_I(telldir);
#endif
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\" SUCH DAMAGE.
.\"
.\" @(#)ttyname.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/ttyname.3,v 1.10 2002/12/18 13:33:02 ru Exp $
+.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd July 18, 2014
.Dt TTYNAME 3
.Os
.Sh NAME
-.Nm isatty ,
.Nm ttyname ,
-.Nm ttyslot
+.Nm ttyname_r ,
+.Nm isatty
.Nd get name of associated terminal (tty) from file descriptor
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In unistd.h
-.Ft int
-.Fo isatty
-.Fa "int fildes"
-.Fc
.Ft char *
-.Fo ttyname
-.Fa "int fildes"
-.Fc
+.Fn ttyname "int fd"
+.Ft int
+.Fn ttyname_r "int fd" "char *buf" "size_t len"
.Ft int
-.Fo ttyslot
-.Fa void
-.Fc
+.Fn isatty "int fd"
.Sh DESCRIPTION
-These functions operate on the system file descriptors for terminal
-type devices.
-These descriptors are not related to the standard
-.Tn I/O
-.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 .
-(See
-.Xr ttys 5 . )
+These functions operate on file descriptors for terminal type devices.
.Pp
The
.Fn isatty
function
determines if the file descriptor
-.Fa fildes
+.Fa fd
refers to a valid
terminal type device.
.Pp
is true.
.Pp
The
-.Fn ttyslot
+.Fn ttyname
function
-fetches the current process' control terminal number from the
-.Xr ttys 5
-file entry.
+returns the name stored in a static buffer which will be overwritten
+on subsequent calls.
+The
+.Fn ttyname_r
+function
+takes a buffer and length as arguments to avoid this problem.
.Sh RETURN VALUES
The
+.Fn isatty
+function returns 1 if
+.Fa fd
+refers to a terminal type device;
+otherwise, it returns 0 and may set
+.Va errno
+to indicate the error.
+The
.Fn ttyname
function
returns the null terminated name if the device is found and
.Fn isatty
-is true; otherwise, a
+is true; otherwise
+a
.Dv NULL
pointer is returned.
+The
+.Fn ttyname_r
+function returns 0 if successful.
+Otherwise an error number is returned.
+.Sh ERRORS
+These functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument
+is not a valid file descriptor.
+.It Bq Er ENOTTY
+The file associated with
+.Fa fd
+is not a terminal.
+.El
.Pp
+Additionally,
+.Fn ttyname_r
+may fail if:
+.Bl -tag -width Er
+.It Bq Er ERANGE
The
-.Fn ttyslot
-function returns the unit number of the device file if found;
-otherwise, the value zero is returned.
-.Sh FILES
-.Bl -tag -width /etc/ttys -compact
-.It Pa /dev/\(**
-.It Pa /etc/ttys
+.Fa bufsize
+argument
+is smaller than the length of the string to be returned.
.El
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr ttys 5
.Sh HISTORY
-A
-.Fn isatty ,
-.Fn ttyname ,
+The
+.Fn isatty
and
-.Fn ttyslot
-function
+.Fn ttyname
+functions
appeared in
.At v7 .
-.Sh BUGS
The
-.Fn ttyname
-function leaves its result in an internal static object and returns
-a pointer to that object.
-Subsequent calls to
-.Fn ttyname
-will modify the same object.
+.Fn ttyname_r
+function
+appeared in
+.Fx 6.0 .
static char sccsid[] = "@(#)ttyslot.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/gen/ttyslot.c,v 1.6 2009/02/12 19:00:13 ed Exp $");
+__FBSDID("$FreeBSD$");
#include <paths.h>
#include <ttyent.h>
int
ttyslot()
{
- struct ttyent *ttyp;
- int slot;
- int cnt;
- char *name;
- setttyent();
- for (cnt = 0; cnt < 3; ++cnt)
- if ( (name = ttyname(cnt)) ) {
- if (strncmp(name, _PATH_DEV, sizeof _PATH_DEV - 1) != 0)
- break;
- name += sizeof _PATH_DEV - 1;
- for (slot = 1; (ttyp = getttyent()); ++slot)
- if (!strcmp(ttyp->ty_name, name)) {
- endttyent();
- return(slot);
- }
- break;
- }
- endttyent();
- return(0);
+ return (0);
}
#define MAXEXTRAS 10
-_Static_assert(MB_LEN_MAX <= sizeof(uint64_t));
+_Static_assert(MB_LEN_MAX <= sizeof(uint64_t), "MB_LEN_MAX is less than 64-bits");
/*
* This is do_hvis, for HTTP style (RFC 1808)
-/* $NetBSD: rb.c,v 1.11 2011/06/20 09:11:16 mrg Exp $ */
+/* $NetBSD: rb.c,v 1.13 2014/08/22 17:19:48 matt Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
-.\" $NetBSD: rbtree.3,v 1.7 2012/08/19 19:31:13 wiz Exp $
+.\" $NetBSD: rbtree.3,v 1.12 2016/08/30 05:12:00 dholland Exp $
.\"
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd August 19, 2012
+.Dd August 29, 2016
.Dt RBTREE 3
.Os
.Sh NAME
-.Nm rbtree
+.Nm rbtree ,
+.Nm rb_tree_init ,
+.Nm rb_tree_insert_node ,
+.Nm rb_tree_remove_node ,
+.Nm rb_tree_find_node ,
+.Nm rb_tree_find_node_geq ,
+.Nm rb_tree_find_node_leq ,
+.Nm rb_tree_iterate ,
+.Nm rb_tree_count ,
+.Nm RB_TREE_MIN ,
+.Nm RB_TREE_MAX ,
+.Nm RB_TREE_FOREACH ,
+.Nm RB_TREE_FOREACH_REVERSE
.Nd red-black tree
.Sh LIBRARY
.Lb libc
.Fn rb_tree_iterate "rb_tree_t *rbt" "void *rb" "const unsigned int direction"
.Ft size_t
.Fn rb_tree_count "rb_tree_t *rbt"
+.Ft void *
+.Fn RB_TREE_MIN "rb_tree_t *rbt"
+.Ft void *
+.Fn RB_TREE_MAX "rb_tree_t *rbt"
+.Fn RB_TREE_FOREACH "void *rb" "rb_tree_t *rbt"
+.Fn RB_TREE_FOREACH_REVERSE "void *rb" "rb_tree_t *rbt"
.Sh DESCRIPTION
.Nm
provides red-black trees.
A red-black tree.
.It Vt typedef signed int \
(* rbto_compare_nodes_fn)(void *context, const void *node1, const void *node2);
-The node-comparison operator.
+The node-comparison function.
Defines an ordering on nodes.
Returns a negative value if the first node
.Ar node1
are identical according to the ordering.
.It Vt typedef signed int \
(* rbto_compare_key_fn)(void *context, const void *node, const void *key);
-The node-key comparison operator.
+The node-key comparison function.
Defines the order of nodes and keys.
Returns a negative value if the node
.Ar node
.Ar key
according to the ordering.
.It Vt rb_tree_ops_t
-Defines the operator for comparing two nodes in the same tree,
-the operator for comparing a node in the tree with a key,
+Defines the function for comparing two nodes in the same tree,
+the function for comparing a node in the tree with a key,
the offset of member
.Vt rb_node_t
-within a node,
-and the opaque context passed to the operators.
+within the node type,
+and the opaque context pointer passed to the comparison functions.
Members of
.Vt rb_tree_ops_t
are
.Ed
.It Vt rb_node_t
A node in a red-black tree has this structure as a member.
+The offset of the
+.Vt rb_node_t
+member in the caller's node structure should be provided as
+.Va rbto_node_offset .
+(None of the functions in the
+.Nm
+interface are meant to take pointers directly to the
+.Vt rb_node_t
+member.)
.El
.Sh FUNCTIONS
.Bl -tag -width compact
.It Fn rb_tree_init "rbt" "ops"
Initialize the red-black tree
.Fa rbt .
-Let the comparison operators given by
+Let the comparison functions given by
.Fa ops
define the order of nodes in the tree for
the purposes of insertion, search, and iteration.
.Fa rb
is
.Dv NULL ,
-return the last node in
+return the first node in
.Fa rbt
or, if the tree is empty, return
.Dv NULL .
.Fa rb
is
.Dv NULL ,
-return the first node in
+return the last node in
.Fa rbt
or, if the tree is empty, return
.Dv NULL .
.It Fn rb_tree_count "rbt"
Return the number of nodes in the tree
.Fa rbt .
-If
+If
.Fa rbt
is
.Dv NULL ,
0 is returned.
+.It Fn RB_TREE_MIN "rbt"
+Return the first node in
+.Fa rbt ,
+i.e. the node with the least key, or
+.Dv NULL
+if
+.Fa rbt
+is empty.
+.It Fn RB_TREE_MAX "rbt"
+Return the last node in
+.Fa rbt ,
+i.e. the node with the greatest key, or
+.Dv NULL
+if
+.Fa rbt
+is empty.
+.It Fn RB_TREE_FOREACH "rb" "rbt"
+.Nm RB_TREE_FOREACH
+is a macro to be used in the place of a
+.Dv for
+header preceding a statement to traverse the nodes in
+.Fa rbt
+from least to greatest, assigning
+.Fa rb
+to each node in turn and executing the statement.
+.It Fn RB_TREE_FOREACH_REVERSE "rb" "rbt"
+.Nm RB_TREE_FOREACH_REVERSE
+is a macro to be used in the place of a
+.Dv for
+header preceding a statement to traverse the nodes in
+.Fa rbt
+from greatest to least, assigning
+.Fa rb
+to each node in turn and executing the statement.
.El
-.Sh IMPLEMENTATION DETAILS
-.Nx 6.0
-included a version of this API that returned the wrong result when using
-.Fn rb_tree_iterate
-to find the first or last node.
-This implementation does not have this bug.
-If you wish to maintain portability with
-.Nx 6.0 ,
-it is recomended that you use the
-.Fn RB_TREE_MIN
-and
-.Fn RB_TREE_MAX
-macros rather than using
-.Fn rb_tree_iterate
-directly.
.Sh SEE ALSO
-.Xr queue 3
+.Xr queue 3 ,
+.Xr tree 3
.Sh HISTORY
The
.Nm
interface first appeared in
.Nx 6.0 .
.Sh AUTHORS
-.An Matt Thomas Aq matt@NetBSD.org
+.An Matt Thomas Aq Mt matt@NetBSD.org
wrote
.Nm .
.Pp
-.An Niels Provos Aq provos@citi.umich.edu
+.An Niels Provos Aq Mt provos@citi.umich.edu
wrote the
.Xr tree 3
manual page.
#define dd_buf __dd_buf
#define dd_len __dd_len
#define dd_seek __dd_seek
-#define dd_rewind __dd_rewind
#define dd_flags __dd_flags
#define dd_lock __dd_lock
#define dd_td __dd_td
{
switch(clk_id){
case CLOCK_REALTIME: {
- struct timeval tv;
- TIMESPEC_TO_TIMEVAL(&tv,tp)
+ struct timeval tv = {
+ .tv_sec = (time_t)tp->tv_sec,
+ .tv_usec = (suseconds_t)(tp->tv_nsec / NSEC_PER_USEC)
+ };
return settimeofday(&tv, NULL);
}
default:
#ifndef BUILDING_VARIANT
__private_extern__ int __crypt_des_setkey_called = 0;
#else /* BUILDING_VARIANT */
-__private_extern__ int __crypt_des_setkey_called;
+extern int __crypt_des_setkey_called;
#endif /* BUILDING_VARIANT */
/* ===== (mostly) Standard DES Tables ==================== */
#ifdef unused
static int error(int);
#endif // unused
-static int gettype(char *, char **);
+static int gettype(const char *, const char **);
struct disklabel *
getdiskbyname(const char *name)
dp->d_flags |= D_BADSECT;
#define getnumdflt(field, dname, dflt) \
- { long f; (field) = (cgetnum(buf, dname, &f) == -1) ? (dflt) : f; }
+ { long f; (field) = (typeof(field))((cgetnum(buf, dname, &f) == -1) ? (dflt) : f); }
getnumdflt(dp->d_secsize, "se", DEV_BSIZE);
cgetnum(buf, "nt",(long *) &dp->d_ntracks);
}
static int
-gettype(t, names)
- char *t;
- char **names;
+gettype(const char *t, const char **names)
{
- register char **nm;
+ const char **nm;
for (nm = names; *nm; nm++)
if (strcasecmp(t, *nm) == 0)
- return (nm - names);
+ return (int)(nm - names);
if (isdigit(*t))
return (atoi(t));
return (0);
#include <sys/param.h>
#include <sys/stat.h>
-#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/vnode.h>
#include <sys/attr.h>
+#include <os/assumes.h>
#ifdef __BLOCKS__
#include <Block.h>
#endif /* __BLOCKS__ */
#include <malloc_private.h>
-static FTSENT *fts_alloc(FTS *, char *, int);
+static FTSENT *fts_alloc(FTS *, char *, ssize_t);
static FTSENT *fts_build(FTS *, int);
static void fts_lfree(FTSENT *);
static void fts_load(FTS *, FTSENT *);
FTSENT *p, *root;
int nitems;
FTSENT *parent, *tmp;
- int len;
+ ssize_t len;
/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
if (ISSET(FTS_LOGICAL))
/* Allocate/initialize root(s). */
for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
- /* Don't allow zero-length paths. */
- if ((len = strlen(*argv)) == 0) {
- errno = ENOENT;
- goto mem3;
- }
-
+ len = strlen(*argv);
if ((p = fts_alloc(sp, *argv, len)) == NULL)
goto mem3;
p->fts_level = FTS_ROOTLEVEL;
static void
fts_load(FTS *sp, FTSENT *p)
{
- int len;
+ ssize_t len;
char *cp;
/*
return (sp->fts_child);
}
-typedef struct __attribute__((packed)) {
+typedef struct __attribute__((packed)) __attribute__((__aligned__(4))) {
uint32_t length;
/* common attributes */
{
if (handle->done) return true;
- assert(handle->dirfd != -1);
+ os_assert(handle->dirfd != -1);
handle->entry_count = getattrlistbulk(handle->dirfd, &handle->requested_attrs,
handle->attrbuf, ATTR_BUF_SIZE, FSOPT_PACK_INVAL_ATTRS);
if (handle->entry_count == -1) {
curattr_stat = handle->curattr;
handle->cur_entry++;
handle->curattr = (attrListAttributes*)(((char*)curattr_stat) + curattr_stat->length);
+ os_assert((handle->cur_entry == handle->entry_count) ||
+ (void*)handle->curattr + handle->curattr->length <= (void*)handle->attrbuf + ATTR_BUF_SIZE);
+ os_assert(curattr_stat->name.attr_length > 0);
entry->d_name = ((char*)&curattr_stat->name) + curattr_stat->name.attr_dataoffset;
/* attr_length includes the null terminator, but readdir's d_namlen doesn't. */
entry->d_namlen = curattr_stat->name.attr_length - 1;
+ os_assert((void*)entry->d_name + curattr_stat->name.attr_length <= (void*)handle->attrbuf + ATTR_BUF_SIZE);
} else {
curattr_nostat = handle->curattr_nostat;
handle->cur_entry++;
handle->curattr_nostat = (attrListAttributes_nostat*)(((char*)curattr_nostat) + curattr_nostat->length);
+ os_assert((handle->cur_entry == handle->entry_count) ||
+ (void*)handle->curattr + handle->curattr->length <= (void*)handle->attrbuf + ATTR_BUF_SIZE);
+ os_assert(curattr_nostat->name.attr_length > 0);
entry->d_name = ((char*)&curattr_nostat->name) + curattr_nostat->name.attr_dataoffset;
/* attr_length includes the null terminator, but readdir's d_namlen doesn't. */
entry->d_namlen = curattr_nostat->name.attr_length - 1;
+ os_assert((void*)entry->d_name + curattr_nostat->name.attr_length <= (void*)handle->attrbuf + ATTR_BUF_SIZE);
}
int stat_type = 0;
requiredFile &= ~ATTR_FILE_DEVTYPE;
}
+ if ((curattr_stat->attrset.commonattr & ATTR_CMN_CRTIME) == 0) {
+ /* Many (most?) file systems don't support create time (see vn_stat_noauth in xnu) */
+ curattr_stat->st_birthtimespec.tv_sec = curattr_stat->st_birthtimespec.tv_nsec = 0;
+ requiredCommon &= ~ ATTR_CMN_CRTIME;
+ }
+
if ((curattr_stat->attrset.commonattr & requiredCommon) != requiredCommon ||
(curattr_stat->attrset.fileattr & requiredFile) != requiredFile) {
/* Some of our required attributes are missing. */
}
static FTSENT *
-fts_alloc(FTS *sp, char *name, int namelen)
+fts_alloc(FTS *sp, char *name, ssize_t namelen)
{
FTSENT *p;
size_t len;
ret = -1;
goto bail;
}
+ /*
+ * On Darwin this check causes us to not correctly descend into automounts,
+ * since the mount point and trigger will have a different devices and
+ * inodes. It would be preferable to find a way to use
+ * ATTR_DIR_MOUNTSTATUS and DIR_MNTSTATUS_TRIGGER to detect these cases,
+ * but plumbing that through will be challenging. Instead, will just
+ * disable it for now.
+ */
+#if 0
if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
errno = ENOENT; /* disinformation */
ret = -1;
goto bail;
}
+#endif
+
ret = fchdir(newfd);
bail:
oerrno = errno;
goto restart;
/* seq->first is already less than slot, so just leave it */
- seq->count = e - b + 1;
- seq->index = b;
+ seq->count = (int)(e - b + 1);
+ seq->index = (int)(b);
/*
* The fmt string contains the characters before the bracket, the
* a format specifier (either decimal or hex) and any characters
abort();
}
- kr = semaphore_create(mach_task_self_, &clock_sem, SYNC_POLICY_FIFO, 0);
+ kr = semaphore_create(mach_task_self(), &clock_sem, SYNC_POLICY_FIFO, 0);
if (kr != KERN_SUCCESS) {
abort();
}
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
+#include <malloc_private.h>
/* Stuff lifted from <a.out.h> and <sys/exec.h> since they are gone */
/*
fh.nfat_arch = OSSwapBigToHostInt32(fh.nfat_arch);
/* Read in the fat archs */
- fat_archs = (struct fat_arch *)malloc(fh.nfat_arch *
- sizeof(struct fat_arch));
+ fat_archs = (struct fat_arch *)reallocarray(NULL, fh.nfat_arch,
+ sizeof(struct fat_arch));
if (fat_archs == NULL) {
return (-1);
}
fap = cpusubtype_getbestarch(hbi.cpu_type, hbi.cpu_subtype,
fat_archs, fh.nfat_arch);
#else
-#warning Use the cpusubtype functions!!!
fap = NULL;
for (i = 0; i < fh.nfat_arch; i++) {
if (fat_archs[i].cputype == hbi.cpu_type) {
#ifndef lint
#if 0
static char sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93";
-#else
static const char rcsid[] =
"$FreeBSD: src/lib/libc/gen/strtofflags.c,v 1.18.2.1 2000/06/28 01:52:24 joe Exp $";
#endif
{ "noopaque", UF_OPAQUE, 0 },
{ "nohidden", UF_HIDDEN, 0 },
{ "nocompressed", UF_COMPRESSED, 0 },
+ { "nodatavault", UF_DATAVAULT, 0 },
};
#define longestflaglen 12
#define nmappings (sizeof(mapping) / sizeof(mapping[0]))
full_sync |= FSCTL_SYNC_WAIT;
terrno = errno;
- rv = (fsctl(path, FSCTL_SYNC_VOLUME, &full_sync, 0) == -1) ? errno : 0;
+ rv = (fsctl(path, FSIOC_SYNC_VOLUME, &full_sync, 0) == -1) ? errno : 0;
errno = terrno;
return rv;
}
#include <stdlib.h>
#include "stack_logging.h"
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
#define FP_LINK_OFFSET 1
#elif defined(__ppc__) || defined(__ppc64__)
#define FP_LINK_OFFSET 2
#define INSTACK(a) ((a) >= stackbot && (a) <= stacktop)
#if defined(__ppc__) || defined(__ppc64__) || defined(__x86_64__)
#define ISALIGNED(a) ((((uintptr_t)(a)) & 0xf) == 0)
-#elif defined(__arm__)
+#elif defined(__arm__) || defined(__arm64__)
#define ISALIGNED(a) ((((uintptr_t)(a)) & 0x1) == 0)
#elif defined(__i386__)
#define ISALIGNED(a) ((((uintptr_t)(a)) & 0xf) == 8)
* optimization). We now inline the code to get the stack frame pointer,
* so we are consistent about the stack frame.
*/
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
frame = __builtin_frame_address(0);
#elif defined(__ppc__) || defined(__ppc64__)
/* __builtin_frame_address IS BROKEN IN BEAKER: RADAR #2340421 */
#include <ttyent.h>
#endif /* UTMP_COMPAT */
-#if ASL_API_VERSION < 20131108
-#include <asl_private.h>
-#include <asl_store.h>
-#endif
-
__private_extern__ const char __utx_magic__[UTMPX_MAGIC] = __UTX_MAGIC__;
extern const char _utmpx_vers[]; /* in utmpx.c */
-#if ASL_API_VERSION < 20131108
-static void msg2lastlogx(const aslmsg, struct lastlogx *);
-static void msg2utmpx(const aslmsg, struct utmpx *);
-static void utmpx2msg(const struct utmpx *, aslmsg);
-#else
static void msg2lastlogx(asl_object_t, struct lastlogx *);
static void msg2utmpx(asl_object_t, struct utmpx *);
static void utmpx2msg(const struct utmpx *, asl_object_t);
-#endif
static size_t pw_size = 0;
/* indirection causes argument to be substituted before stringification */
#define STR(x) __STRING(x)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
#ifdef UTMP_COMPAT
static char *
_pwnam_r(const char *user, struct passwd *pw)
struct lastlogx *
getlastlogxbyname(const char *user, struct lastlogx *lx)
{
-#if ASL_API_VERSION < 20131108
- aslmsg m;
- asl_msg_t *qm[1];
- asl_search_result_t query, *res;
- uint32_t status;
- asl_store_t *store = NULL;
- uint64_t cmax;
-#else
asl_object_t m, query, res;
size_t cmax;
-#endif
struct lastlogx *result = NULL;
if (!user || !*user) return NULL;
-#if ASL_API_VERSION < 20131108
- status = asl_store_open_read(NULL, &store);
- if (status != 0) return NULL;
- if (store == NULL) return NULL;
-#endif
-
/*
* We search for the last LASTLOG_FACILITY entry that has the
* ut_user entry matching the user's name.
m = asl_new(ASL_TYPE_QUERY);
if (m == NULL)
{
-#if ASL_API_VERSION < 20131108
- asl_store_close(store);
-#endif
return NULL;
}
asl_set_query(m, FACILITY, LASTLOG_FACILITY, ASL_QUERY_OP_EQUAL);
asl_set_query(m, "ut_user", user, ASL_QUERY_OP_EQUAL);
-#if ASL_API_VERSION < 20131108
- qm[0] = (asl_msg_t *)m;
- query.count = 1;
- query.msg = qm;
-#else
query = asl_new(ASL_TYPE_LIST);
if (query == NULL)
{
asl_append(query, m);
asl_release(m);
-#endif
res = NULL;
cmax = 0;
-#if ASL_API_VERSION < 20131108
- asl_store_match_timeout(store, &query, &res, &cmax, -1, 1, -1, ASL_QUERY_TIMEOUT);
- asl_store_close(store);
- asl_free(m);
-#else
res = asl_match(NULL, query, &cmax, -1, 1, ASL_QUERY_TIMEOUT, ASL_MATCH_DIRECTION_REVERSE);
asl_release(query);
-#endif
if (res == NULL) return NULL;
-#if ASL_API_VERSION < 20131108
- m = aslresponse_next(res);
-#else
m = asl_next(res);
-#endif
if (m == NULL)
{
-#if ASL_API_VERSION < 20131108
- aslresponse_free(res);
-#else
asl_release(res);
-#endif
return NULL;
}
{
if ((lx = (struct lastlogx *)malloc(sizeof(*lx))) == NULL)
{
-#if ASL_API_VERSION < 20131108
- aslresponse_free(res);
-#else
asl_release(res);
-#endif
return NULL;
}
}
msg2lastlogx(m, lx);
-#if ASL_API_VERSION < 20131108
- aslresponse_free(res);
-#else
asl_release(res);
-#endif
result = lx;
return result;
}
-#define IGET(e,p) if ((cp = asl_get(m, __STRING(ut_##e))) != NULL) \
- u->p##_##e = strtol(cp, NULL, 10);
-#define LGET(e,p) IGET(e,p)
-#define SGET(e,p) if ((cp = asl_get(m, __STRING(ut_##e))) != NULL) \
- strncpy(u->p##_##e, cp, sizeof(u->p##_##e))
+#define IGET(e,p) do { if ((cp = asl_get(m, __STRING(ut_##e))) != NULL) \
+ u->p##_##e = (int)strtol(cp, NULL, 10); } while (0)
+#define LGET(e,p) do { if ((cp = asl_get(m, __STRING(ut_##e))) != NULL) \
+ u->p##_##e = strtol(cp, NULL, 10); } while (0)
+#define SGET(e,p) do { if ((cp = asl_get(m, __STRING(ut_##e))) != NULL) \
+ strncpy(u->p##_##e, cp, sizeof(u->p##_##e)); } while (0)
/* fill in a struct lastlogx from an ASL message */
static void
-#if ASL_API_VERSION < 20131108
-msg2lastlogx(const aslmsg m, struct lastlogx *u)
-#else
msg2lastlogx(asl_object_t m, struct lastlogx *u)
-#endif
{
const char *cp;
/* fill in a struct utmpx from an ASL message */
static void
-#if ASL_API_VERSION < 20131108
-msg2utmpx(aslmsg m, struct utmpx *u)
-#else
msg2utmpx(asl_object_t m, struct utmpx *u)
-#endif
{
const char *cp;
/* fill in an ASL message from a struct utmpx */
static void
-#if ASL_API_VERSION < 20131108
-utmpx2msg(const struct utmpx *u, aslmsg m)
-#else
utmpx2msg(const struct utmpx *u, asl_object_t m)
-#endif
{
char buf[_UTX_HOSTSIZE + 1]; /* the largest string in struct utmpx */
const char *cp;
__private_extern__ void
_utmpx_asl(const struct utmpx *u)
{
-#if ASL_API_VERSION < 20131108
- aslclient asl = asl_open(NULL, NULL, ASL_OPT_NO_REMOTE); /* could be NULL, but still works */
- aslmsg m;
-#else
asl_object_t asl = asl_open(NULL, NULL, ASL_OPT_NO_REMOTE);
asl_object_t m;
-#endif
char msg[64];
if (u->ut_type == EMPTY)
return;
if ((m = asl_new(ASL_TYPE_MSG)) == NULL) {
-#if ASL_API_VERSION < 20131108
- asl_close(asl);
-#else
asl_release(asl);
-#endif
return;
}
/*
}
asl_set(m, ASL_KEY_MSG, msg);
asl_send(asl, m);
-#if ASL_API_VERSION < 20131108
- asl_free(m);
- asl_close(asl);
-#else
asl_release(m);
asl_release(asl);
-#endif
}
#define UT_USER (1 << 0)
/* UT_ID is set only if we already know we need to add it */
if ((which & UT_ID)) {
char *cp;
- int i = sizeof(temp->ut_line);
+ ssize_t i = sizeof(temp->ut_line);
for(cp = temp->ut_line; i > 0 && *cp; i--)
cp++;
static struct {
uint64_t start;
int dir;
-#if ASL_API_VERSION < 20131108
- asl_search_result_t *res;
-#else
asl_object_t res;
-#endif
char *str;
uint32_t len;
char inited;
{
if (wtmp_asl.res != NULL)
{
-#if ASL_API_VERSION < 20131108
- aslresponse_free(wtmp_asl.res);
-#else
asl_release(wtmp_asl.res);
-#endif
wtmp_asl.res = NULL;
}
static struct utmpx *
get_asl(void)
{
-#if ASL_API_VERSION < 20131108
- aslmsg m;
-#else
asl_object_t m;
-#endif
static struct utmpx utx;
if (wtmp_asl.inited == 0) set_asl(-1);
if (wtmp_asl.done != 0) return NULL;
-#if ASL_API_VERSION < 20131108
- m = aslresponse_next(wtmp_asl.res);
-#else
m = asl_next(wtmp_asl.res);
-#endif
if (m == NULL)
{
-#if ASL_API_VERSION < 20131108
- aslresponse_free(wtmp_asl.res);
-#else
asl_release(wtmp_asl.res);
-#endif
wtmp_asl.res = NULL;
wtmp_asl.done = 1;
return NULL;
static void
set_asl(int forward)
{
-#if ASL_API_VERSION < 20131108
- aslmsg q0, q1;
- asl_msg_t *m[2];
- asl_search_result_t query;
- asl_store_t *store = NULL;
- uint32_t status;
- uint64_t cmax;
-#else
asl_object_t q0, q1, query;
size_t cmax;
-#endif
_set_dir(forward);
if (wtmp_asl.res != NULL)
{
-#if ASL_API_VERSION < 20131108
- aslresponse_free(wtmp_asl.res);
-#else
asl_release(wtmp_asl.res);
-#endif
wtmp_asl.res = NULL;
}
-#if ASL_API_VERSION < 20131108
- status = asl_store_open_read(NULL, &store);
- if (status != 0) return;
- if (store == NULL) return;
-#endif
-
/*
* Create a search query that matches either UTMPX_FACILITY
* or LASTLOG_FACILITY.
q1 = asl_new(ASL_TYPE_QUERY);
if (q1 == NULL)
{
-#if ASL_API_VERSION < 20131108
- asl_free(q0);
-#else
asl_release(q0);
-#endif
return;
}
asl_set_query(q1, FACILITY, LASTLOG_FACILITY, ASL_QUERY_OP_EQUAL);
-#if ASL_API_VERSION < 20131108
- m[0] = (asl_msg_t *)q0;
- m[1] = (asl_msg_t *)q1;
- query.count = 2;
- query.msg = m;
-#else
query = asl_new(ASL_TYPE_LIST);
if (query == NULL)
{
asl_release(q0);
asl_release(q1);
-#endif
cmax = 0;
-#if ASL_API_VERSION < 20131108
- asl_store_match_timeout(store, &query, &(wtmp_asl.res), &cmax, wtmp_asl.start, 0, wtmp_asl.dir, ASL_QUERY_TIMEOUT);
- asl_store_close(store);
- asl_free(q0);
- asl_free(q1);
-#else
wtmp_asl.res = asl_match(NULL, query, &cmax, wtmp_asl.start, 0, ASL_QUERY_TIMEOUT, wtmp_asl.dir);
asl_release(query);
-#endif
if (wtmp_asl.res == NULL) return;
free(U);
return 0;
}
+
+#pragma clang diagnostic pop
#define __TYPES_H_
#include <sys/_types.h>
+#include <machine/_types.h> /* __uint32_t */
#if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7
#define __strfmonlike(fmtarg, firstvararg) \
#ifndef _NL_ITEM
#define _NL_ITEM
+#include <_types.h>
typedef __darwin_nl_item nl_item;
#endif /* _NL_ITEM */
\ No newline at end of file
#ifndef _WCTRANS_T
#define _WCTRANS_T
+#include <_types.h>
typedef __darwin_wctrans_t wctrans_t;
#endif /* _WCTRANS_T */
\ No newline at end of file
#ifndef _WCTYPE_T
#define _WCTYPE_T
+#include <_types.h>
typedef __darwin_wctype_t wctype_t;
#endif /* _WCTYPE_T */
\ No newline at end of file
#else /* __GNUC__ */
__BEGIN_DECLS
-void __assert_rtn(const char *, const char *, int, const char *) __dead2;
+void __assert_rtn(const char *, const char *, int, const char *) __dead2 __disable_tail_calls;
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1070)
void __eprintf(const char *, const char *, unsigned, const char *) __dead2;
#endif
#include <sys/dirent.h>
#include <sys/cdefs.h>
#include <Availability.h>
+#include <sys/_pthread/_pthread_types.h> /* __darwin_pthread_mutex_t */
struct _telldir; /* forward reference */
char *__dd_buf; /* data buffer */
int __dd_len; /* size of data buffer */
long __dd_seek; /* magic cookie returned */
- long __dd_rewind; /* magic cookie for rewinding */
+ __unused long __padding; /* (__dd_rewind space left for bincompat) */
int __dd_flags; /* flags for readdir */
__darwin_pthread_mutex_t __dd_lock; /* for thread locking */
struct _telldir *__dd_td; /* telldir position recording */
#define DTF_NODUP 0x0002 /* don't return duplicate names */
#define DTF_REWIND 0x0004 /* rewind after reading union stack */
#define __DTF_READALL 0x0008 /* everything has been read */
+#define __DTF_SKIPREAD 0x0010 /* assume internal buffer is populated */
#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
#define kFSSubTypeKey "FSSubType"
#define kFSXMLOutputArgumentKey "FSXMLOutputArgument"
+#define kFSEncryptNameKey "FSEncryptionName"
+ /* Deprecated - use kFSEncryptNameKey for HFS/APFS */
#define kFSCoreStorageEncryptNameKey "FSCoreStorageEncryptionName"
#endif /* _FSPROPERTIES_H_ */
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
*
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
#define PTHREAD_KEYS_MAX 512
-#if defined(__arm__)
+#if defined(__arm__) || defined(__arm64__)
#define PTHREAD_STACK_MIN 16384
#else
#define PTHREAD_STACK_MIN 8192
/*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007,2017 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#ifndef _SECURE__STRING_H_
#define _SECURE__STRING_H_
-#include <Availability.h>
#include <sys/cdefs.h>
+#include <Availability.h>
#include <secure/_common.h>
#if _USE_FORTIFY_LEVEL > 0
-#ifndef __has_builtin
-#define _undef__has_builtin
-#define __has_builtin(x) 0
-#endif
-
/* <rdar://problem/12622659> */
#if defined(__clang__) && \
- ((defined(__apple_build_version__) && __apple_build_version__ >= 4260006) || \
- (!defined(__apple_build_version__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 3))))
+ ((defined(__apple_build_version__) && __apple_build_version__ >= 4260006) || \
+ (!defined(__apple_build_version__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 3))))
#define __HAS_FIXED_CHK_PROTOTYPES 1
#else
#define __HAS_FIXED_CHK_PROTOTYPES 0
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
#if __has_builtin(__builtin___memccpy_chk) && __HAS_FIXED_CHK_PROTOTYPES
#undef memccpy
-#define memccpy(dest, src, c, len) \
- __builtin___memccpy_chk (dest, src, c, len, __darwin_obsz0 (dest))
+/* void *memccpy(void *dst, const void *src, int c, size_t n) */
+#define memccpy(dest, ...) \
+ __builtin___memccpy_chk (dest, __VA_ARGS__, __darwin_obsz0 (dest))
#endif
#endif
#if __has_builtin(__builtin___memcpy_chk) || defined(__GNUC__)
#undef memcpy
-#define memcpy(dest, src, len) \
- __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
+/* void *memcpy(void *dst, const void *src, size_t n) */
+#define memcpy(dest, ...) \
+ __builtin___memcpy_chk (dest, __VA_ARGS__, __darwin_obsz0 (dest))
#endif
#if __has_builtin(__builtin___memmove_chk) || defined(__GNUC__)
#undef memmove
-#define memmove(dest, src, len) \
- __builtin___memmove_chk (dest, src, len, __darwin_obsz0 (dest))
+/* void *memmove(void *dst, const void *src, size_t len) */
+#define memmove(dest, ...) \
+ __builtin___memmove_chk (dest, __VA_ARGS__, __darwin_obsz0 (dest))
#endif
#if __has_builtin(__builtin___memset_chk) || defined(__GNUC__)
#undef memset
-#define memset(dest, val, len) \
- __builtin___memset_chk (dest, val, len, __darwin_obsz0 (dest))
+/* void *memset(void *b, int c, size_t len) */
+#define memset(dest, ...) \
+ __builtin___memset_chk (dest, __VA_ARGS__, __darwin_obsz0 (dest))
#endif
#if __has_builtin(__builtin___strcpy_chk) || defined(__GNUC__)
#undef strcpy
-#define strcpy(dest, src) \
- __builtin___strcpy_chk (dest, src, __darwin_obsz (dest))
+/* char *strcpy(char *dst, const char *src) */
+#define strcpy(dest, ...) \
+ __builtin___strcpy_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
#if __DARWIN_C_LEVEL >= 200809L
#if __has_builtin(__builtin___stpcpy_chk) || defined(__GNUC__)
#undef stpcpy
-#define stpcpy(dest, src) \
- __builtin___stpcpy_chk (dest, src, __darwin_obsz (dest))
+/* char *stpcpy(char *dst, const char *src) */
+#define stpcpy(dest, ...) \
+ __builtin___stpcpy_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
#if __has_builtin(__builtin___stpncpy_chk) || __APPLE_CC__ >= 5666 || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
#undef stpncpy
-#define stpncpy(dest, src, len) \
- __builtin___stpncpy_chk (dest, src, len, __darwin_obsz (dest))
+/* char *stpncpy(char *dst, const char *src, size_t n) */
+#define stpncpy(dest, ...) \
+ __builtin___stpncpy_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
#endif /* _DARWIN_C_LEVEL >= 200809L */
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
#if __has_builtin(__builtin___strlcpy_chk) && __HAS_FIXED_CHK_PROTOTYPES
#undef strlcpy
-#define strlcpy(dest, src, len) \
- __builtin___strlcpy_chk (dest, src, len, __darwin_obsz (dest))
+/* size_t strlcpy(char *dst, const char *source, size_t size) */
+#define strlcpy(dest, ...) \
+ __builtin___strlcpy_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
#if __has_builtin(__builtin___strlcat_chk) && __HAS_FIXED_CHK_PROTOTYPES
#undef strlcat
-#define strlcat(dest, src, len) \
- __builtin___strlcat_chk (dest, src, len, __darwin_obsz (dest))
+/* size_t strlcat(char *dst, const char *source, size_t size) */
+#define strlcat(dest, ...) \
+ __builtin___strlcat_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 */
#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */
#if __has_builtin(__builtin___strncpy_chk) || defined(__GNUC__)
#undef strncpy
-#define strncpy(dest, src, len) \
- __builtin___strncpy_chk (dest, src, len, __darwin_obsz (dest))
+/* char *strncpy(char *dst, const char *src, size_t n) */
+#define strncpy(dest, ...) \
+ __builtin___strncpy_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
#if __has_builtin(__builtin___strcat_chk) || defined(__GNUC__)
#undef strcat
-#define strcat(dest, src) \
- __builtin___strcat_chk (dest, src, __darwin_obsz (dest))
+/* char *strcat(char *s1, const char *s2) */
+#define strcat(dest, ...) \
+ __builtin___strcat_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
#if ! (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 32000)
#if __has_builtin(__builtin___strncat_chk) || defined(__GNUC__)
#undef strncat
-#define strncat(dest, src, len) \
- __builtin___strncat_chk (dest, src, len, __darwin_obsz (dest))
-#endif
+/* char *strncat(char *s1, const char *s2, size_t n) */
+#define strncat(dest, ...) \
+ __builtin___strncat_chk (dest, __VA_ARGS__, __darwin_obsz (dest))
#endif
-
-#ifdef _undef__has_builtin
-#undef _undef__has_builtin
-#undef __has_builtin
#endif
#undef __HAS_FIXED_CHK_PROTOTYPES
--- /dev/null
+/*
+ * Copyright (c) 2017 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _STRINGS_H_
+# error "Never use <secure/_strings.h> directly; include <strings.h> instead."
+#endif
+
+#ifndef _SECURE__STRINGS_H_
+#define _SECURE__STRINGS_H_
+
+#include <sys/cdefs.h>
+#include <Availability.h>
+#include <secure/_common.h>
+
+#if _USE_FORTIFY_LEVEL > 0
+
+/* bcopy and bzero */
+
+/* Removed in Issue 7 */
+#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L
+
+#if __has_builtin(__builtin___memmove_chk) || defined(__GNUC__)
+#undef bcopy
+/* void bcopy(const void *src, void *dst, size_t len) */
+#define bcopy(src, dest, ...) \
+ __builtin___memmove_chk (dest, src, __VA_ARGS__, __darwin_obsz0 (dest))
+#endif
+
+#if __has_builtin(__builtin___memset_chk) || defined(__GNUC__)
+#undef bzero
+/* void bzero(void *s, size_t n) */
+#define bzero(dest, ...) \
+ __builtin___memset_chk (dest, 0, __VA_ARGS__, __darwin_obsz0 (dest))
+#endif
+
+#endif
+
+#endif /* _USE_FORTIFY_LEVEL > 0 */
+#endif /* _SECURE__STRINGS_H_ */
/* 7.18.2 Limits of specified-width integer types:
* These #defines specify the minimum and maximum limits
* of each of the types declared above.
+ *
+ * They must have "the same type as would an expression that is an
+ * object of the corresponding type converted according to the integer
+ * promotion".
*/
/* 7.18.2.4 Limits of integer types capable of holding object pointers */
#if __WORDSIZE == 64
-#define INTPTR_MIN INT64_MIN
-#define INTPTR_MAX INT64_MAX
+#define INTPTR_MAX 9223372036854775807L
#else
-#define INTPTR_MIN INT32_MIN
-#define INTPTR_MAX INT32_MAX
+#define INTPTR_MAX 2147483647L
#endif
+#define INTPTR_MIN (-INTPTR_MAX-1)
#if __WORDSIZE == 64
-#define UINTPTR_MAX UINT64_MAX
+#define UINTPTR_MAX 18446744073709551615UL
#else
-#define UINTPTR_MAX UINT32_MAX
+#define UINTPTR_MAX 4294967295UL
#endif
/* 7.18.2.5 Limits of greatest-width integer types */
#define PTRDIFF_MAX INT32_MAX
#endif
-#if __WORDSIZE == 64
-#define SIZE_MAX UINT64_MAX
-#else
-#define SIZE_MAX UINT32_MAX
-#endif
+#define SIZE_MAX UINTPTR_MAX
#if defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1
#define RSIZE_MAX (SIZE_MAX >> 1)
#define INT32_C(v) (v)
#define INT64_C(v) (v ## LL)
-#define UINT8_C(v) (v ## U)
-#define UINT16_C(v) (v ## U)
+#define UINT8_C(v) (v)
+#define UINT16_C(v) (v)
#define UINT32_C(v) (v ## U)
#define UINT64_C(v) (v ## ULL)
int vdprintf(int, const char * __restrict, va_list) __printflike(2, 0) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
ssize_t getdelim(char ** __restrict __linep, size_t * __restrict __linecapp, int __delimiter, FILE * __restrict __stream) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
ssize_t getline(char ** __restrict __linep, size_t * __restrict __linecapp, FILE * __restrict __stream) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
+FILE *fmemopen(void * __restrict __buf, size_t __size, const char * __restrict __mode) __API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
+FILE *open_memstream(char **__bufp, size_t *__sizep) __API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
__END_DECLS
#endif /* __DARWIN_C_LEVEL >= 200809L */
#define LIBC_ABORT(f,...) abort_report_np("%s:%s:%u: " f, __FILE__, __func__, __LINE__, ## __VA_ARGS__)
//End-Libc
+#ifndef __alloc_size
+#if __has_attribute(alloc_size)
+#define __alloc_size(...) __attribute__((alloc_size(__VA_ARGS__)))
+#else
+#define __alloc_size(...)
+#endif
+#endif // __alloc_size
+
__BEGIN_DECLS
void abort(void) __dead2;
int abs(int) __pure2;
#endif /* !__DARWIN_NO_LONG_LONG */
void *bsearch(const void *__key, const void *__base, size_t __nel,
size_t __width, int (* _Nonnull __compar)(const void *, const void *));
-void *calloc(size_t __count, size_t __size) __result_use_check;
+void *calloc(size_t __count, size_t __size) __result_use_check __alloc_size(1,2);
div_t div(int, int) __pure2;
void exit(int) __dead2;
void free(void *);
llabs(long long);
lldiv_t lldiv(long long, long long);
#endif /* !__DARWIN_NO_LONG_LONG */
-void *malloc(size_t __size) __result_use_check;
+void *malloc(size_t __size) __result_use_check __alloc_size(1);
int mblen(const char *__s, size_t __n);
size_t mbstowcs(wchar_t * __restrict , const char * __restrict, size_t);
int mbtowc(wchar_t * __restrict, const char * __restrict, size_t);
void qsort(void *__base, size_t __nel, size_t __width,
int (* _Nonnull __compar)(const void *, const void *));
int rand(void) __swift_unavailable("Use arc4random instead.");
-void *realloc(void *__ptr, size_t __size) __result_use_check;
+void *realloc(void *__ptr, size_t __size) __result_use_check __alloc_size(2);
void srand(unsigned) __swift_unavailable("Use arc4random instead.");
double strtod(const char *, char **) __DARWIN_ALIAS(strtod);
float strtof(const char *, char **) __DARWIN_ALIAS(strtof);
#endif
__swift_unavailable_on("Use posix_spawn APIs or NSTask instead.", "Process spawning is unavailable")
-__OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_0,__MAC_NA,__IPHONE_2_0,__IPHONE_8_0, "Use posix_spawn APIs instead.")
+__API_AVAILABLE(macos(10.0)) __IOS_PROHIBITED
__WATCHOS_PROHIBITED __TVOS_PROHIBITED
int system(const char *) __DARWIN_ALIAS_C(system);
//Begin-Libc
unsigned __endbyte);
void sranddev(void);
void srandomdev(void);
-void *reallocf(void *__ptr, size_t __size);
+void *reallocf(void *__ptr, size_t __size) __alloc_size(2);
#if !__DARWIN_NO_LONG_LONG
long long
strtoq(const char *__str, char **__endptr, int __base);
strtouq(const char *__str, char **__endptr, int __base);
#endif /* !__DARWIN_NO_LONG_LONG */
extern char *suboptarg; /* getsubopt(3) external variable */
-void *valloc(size_t);
+void *valloc(size_t) __alloc_size(1);
#endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */
/* Poison the following routines if -fshort-wchar is set */
/* SUS places swab() in unistd.h. It is listed here for source compatibility */
void swab(const void * __restrict, void * __restrict, ssize_t);
-#ifndef __CUDACC__
__OSX_AVAILABLE(10.12.1) __IOS_AVAILABLE(10.1)
__TVOS_AVAILABLE(10.0.1) __WATCHOS_AVAILABLE(3.1)
-#endif
int timingsafe_bcmp(const void *__b1, const void *__b2, size_t __len);
__END_DECLS
#include <string.h>
#endif
+#if defined (__GNUC__) && _FORTIFY_SOURCE > 0 && !defined (__cplusplus)
+/* Security checking functions. */
+#include <secure/_strings.h>
+#endif
+
#endif /* _STRINGS_H_ */
*/
#include_next <sys/cdefs.h>
#ifndef _LIBC_NO_FEATURE_VERIFICATION
-#if defined(__arm__) || defined(__i386__) || defined(__x86_64__)
+#if defined(__arm64__) || defined(__arm__) || defined(__i386__) || defined(__x86_64__)
# include "libc-features.h"
#else
# error "Unknown architecture."
#define RB_TREE_FOREACH(N, T) \
for ((N) = RB_TREE_MIN(T); (N); \
(N) = rb_tree_iterate((T), (N), RB_DIR_RIGHT))
+#define RB_TREE_FOREACH_SAFE(N, T, TVAR) \
+ for ((N) = RB_TREE_MIN(T); (N) && ((TVAR) = rb_tree_iterate((T), (N), RB_DIR_RIGHT)); \
+ (N) = (TVAR))
#define RB_TREE_FOREACH_REVERSE(N, T) \
for ((N) = RB_TREE_MAX(T); (N); \
(N) = rb_tree_iterate((T), (N), RB_DIR_LEFT))
+#define RB_TREE_FOREACH_REVERSE_SAFE(N, T, TVAR) \
+ for ((N) = RB_TREE_MAX(T); (N) && ((TVAR) = rb_tree_iterate((T), (N), RB_DIR_LEFT)); \
+ (N) = (TVAR))
+
/*
* rbto_compare_nodes_fn:
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
- long tm_gmtoff; /* offset from CUT in seconds */
+ long tm_gmtoff; /* offset from UTC in seconds */
char *tm_zone; /* timezone abbreviation */
};
int mkstemp_dprotected_np(char *path, int dpclass, int dpflags)
__OSX_UNAVAILABLE __IOS_AVAILABLE(10.0)
__TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);
+char *mkdtempat_np(int dfd, char *path)
+ __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0)
+ __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0);
+int mkstempsat_np(int dfd, char *path, int slen)
+ __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0)
+ __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0);
+int mkostempsat_np(int dfd, char *path, int slen, int oflags)
+ __OSX_AVAILABLE(10.13) __IOS_AVAILABLE(11.0)
+ __TVOS_AVAILABLE(11.0) __WATCHOS_AVAILABLE(4.0);
int nfssvc(int, void *);
int profil(char *, size_t, unsigned long, unsigned int);
+
+__deprecated_msg("Use of per-thread security contexts is error-prone and discouraged.")
int pthread_setugid_np(uid_t, gid_t);
int pthread_getugid_np( uid_t *, gid_t *);
+
int reboot(int);
int revoke(const char *);
int setattrlist(const char*,void*,void*,size_t,unsigned long) LIBC_ALIAS(setattrlist);
#endif /* !LIBC_ALIAS_SETATTRLIST */
//End-Libc
-int exchangedata(const char*,const char*,unsigned long) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
+int exchangedata(const char*,const char*,unsigned long)
+ __OSX_DEPRECATED(10.0, 10.13, "use renamex_np with the RENAME_SWAP flag")
+ __IOS_DEPRECATED(2.0, 11.0, "use renamex_np with the RENAME_SWAP flag")
+ __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
int getdirentriesattr(int,void*,void*,size_t,unsigned long*,unsigned long*,unsigned long*,unsigned long) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
#endif /* __LP64__ */
size_t wcsnlen(const wchar_t *, size_t) __pure __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
size_t wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t,
size_t, mbstate_t * __restrict);
+FILE *open_wmemstream(wchar_t ** __bufp, size_t * __sizep) __API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0));
__END_DECLS
#endif /* __DARWIN_C_LEVEL >= 200809L */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>AppleInternal</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+/*
+ * Copyright (c) 2017 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <strings.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/fsctl.h>
+#include <sys/vnode.h>
+#include <sys/errno.h>
+
+#include <os/assumes.h>
+
+#include <TargetConditionals.h>
+
+#include "dirstat.h"
+#include "dirstat_collection.h"
+
+#if !TARGET_OS_SIMULATOR
+#define HAS_APFS
+#endif
+
+#ifdef HAS_APFS
+#include <apfs/apfs_fsctl.h>
+#endif
+
+#if DEBUG
+#define DEBUGPRINT(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define DEBUGPRINT(...) do { } while(0)
+#endif
+
+static int
+fdirstat_fallback(int fd, int flags, struct dirstat *ds);
+
+#ifdef HAS_APFS
+static int
+fdirstat(int fd, int flags, struct dirstat *ds)
+{
+ struct apfs_dir_stats_ext dstats = {0};
+ if (flags & DIRSTAT_FAST_ONLY) {
+ dstats.flags |= APFS_DIR_STATS_FAST_PATH;
+ }
+
+ int err = ffsctl(fd, APFSIOC_GET_DIR_STATS_EXT, &dstats, 0);
+ if (err == -1) {
+ if (errno == ENOENT) {
+ // <rdar://problem/31696225>
+ errno = ENOTSUP;
+ }
+ return -1;
+ }
+
+ ds->total_size = dstats.total_size;
+ ds->descendants = dstats.num_children;
+
+ return 0;
+}
+#endif
+
+int
+dirstatat_np(int dfd, const char *path, int flags, struct dirstat *ds_out, size_t ds_size)
+{
+#ifdef HAS_APFS
+ // <rdar://problem/32794924>
+ // Until APFS directory sizing is fixed, only the fallback path is
+ // available.
+ flags |= DIRSTAT_FORCE_FALLBACK;
+
+ // FORCE_FALLBACK trumps FAST_ONLY. Make sure to set errno accordingly in
+ // the case that a confused caller asks for both.
+ if ((flags & (DIRSTAT_FAST_ONLY)) && (flags & DIRSTAT_FORCE_FALLBACK)) {
+ errno = ENOTSUP;
+ return -1;
+ }
+#endif
+
+ int fd = openat(dfd, path, O_RDONLY | O_DIRECTORY);
+ DEBUGPRINT("Opened %d:%s as %d\n", dfd, path, fd);
+ if (fd == -1) return -1;
+
+ struct dirstat ds = {};
+ int ret = -1;
+
+#ifdef HAS_APFS
+ if (!(flags & DIRSTAT_FORCE_FALLBACK)) {
+ ret = fdirstat(fd, flags, &ds);
+ }
+
+ if (ret == -1 && ((flags & DIRSTAT_FORCE_FALLBACK) || ((errno == ENOTTY) && !(flags & DIRSTAT_FAST_ONLY)))) {
+ ret = fdirstat_fallback(fd, flags, &ds);
+ }
+#else
+ ret = fdirstat_fallback(fd, flags, &ds);
+#endif
+ int saved_errno = errno;
+
+ if (ds_size >= sizeof(ds)) {
+ memcpy(ds_out, &ds, sizeof(ds));
+ } else {
+ memcpy(ds_out, &ds, ds_size);
+ }
+
+ close(fd);
+
+ errno = saved_errno;
+ return ret;
+}
+
+int
+dirstat_np(const char *path, int flags, struct dirstat *ds, size_t ds_size)
+{
+ return dirstatat_np(AT_FDCWD, path, flags, ds, ds_size);
+}
+
+#pragma mark Fallback
+
+struct dirqueue_entry {
+ STAILQ_ENTRY(dirqueue_entry) entries;
+ char *path;
+};
+
+static int
+fdirstat_fallback(int parent_fd, int flags, struct dirstat *ds)
+{
+ int reterror = 0;
+
+ /*
+ * This method of gathering disk usage is the fastest by far over other
+ * methods using fts or opendir/readdir + getattrlist or stat to gather
+ * information about filesystem usage. That's because this method avoids
+ * creating vnodes for each item in a directory. We implement a recursive
+ * filesystem search by appending each directory child found to a
+ * processing queue, and then process each child directory in that queue on
+ * a FIFO basis resulting in a breadth-first traversal of the filesystem.
+ * This keeps our actual implementation iterative to avoid deep filesystem
+ * hierarchies overflowing our stack.
+ */
+
+ dirstat_fileid_set_t fileid_seen = _dirstat_fileid_set_create();
+ STAILQ_HEAD(, dirqueue_entry) dirqueue_head = STAILQ_HEAD_INITIALIZER(dirqueue_head);
+
+ struct attrlist attrlist = {
+ .bitmapcount = ATTR_BIT_MAP_COUNT,
+ .commonattr = ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_ERROR |
+ ATTR_CMN_NAME | ATTR_CMN_OBJTYPE | ATTR_CMN_FILEID,
+ .dirattr = ATTR_DIR_ENTRYCOUNT,
+ .fileattr = ATTR_FILE_LINKCOUNT | ATTR_FILE_ALLOCSIZE |
+ ATTR_FILE_DATAALLOCSIZE,
+ };
+
+ typedef struct {
+ /*
+ * fields are in order of possible return in buffer (but note that data
+ * is packed in the actual buffer, and only relevant fields are
+ * returned)
+ */
+ uint32_t length;
+ attribute_set_t returned; //ATTR_CMN_RETURNED_ATTRS
+ uint32_t error; //ATTR_CMN_ERROR
+ attrreference_t item_name_info; //ATTR_CMN_NAME
+ fsobj_type_t type; //ATTR_CMN_OBJTYPE
+ uint64_t fileid; //ATTR_CMN_FILEID
+ union {
+ struct {
+ u_int32_t entry_count; //ATTR_DIR_ENTRYCOUNT
+ };
+ struct {
+ u_int32_t link_count; //ATTR_FILE_LINKCOUNT
+ off_t alloc_size; //ATTR_FILE_ALLOCSIZE
+ off_t data_alloc_size; //ATTR_FILE_DATAALLOCSIZE
+ };
+ };
+ } max_attr_entry_t;
+
+ size_t attrbuf_len = (32 * 1024);
+ char *attrbuf = alloca(attrbuf_len);
+
+#ifdef HAS_APFS
+ os_assert(!(flags & DIRSTAT_FAST_ONLY));
+#endif
+
+ do {
+ int fd = -1;
+ char *path;
+
+ if (STAILQ_EMPTY(&dirqueue_head)) {
+ fd = parent_fd;
+ path = NULL;
+ } else {
+ struct dirqueue_entry *dqe = STAILQ_FIRST(&dirqueue_head);
+ STAILQ_REMOVE_HEAD(&dirqueue_head, entries);
+ path = dqe->path;
+ free(dqe);
+
+ fd = openat(parent_fd, path, O_RDONLY | O_DIRECTORY);
+
+ if (fd < 0) {
+ DEBUGPRINT( "Unable to open directory %d:%s => %s\n", parent_fd, path, strerror(errno));
+ continue;
+ }
+ }
+
+ while (1) {
+ int ret_entry_count = getattrlistbulk(fd, &attrlist, attrbuf, attrbuf_len, 0);
+ if (-1 == ret_entry_count) {
+ if (fd == parent_fd) {
+ reterror = errno;
+ }
+ DEBUGPRINT( "getattrlistbulk on in %s returned error %s\n", path, strerror(errno));
+ break;
+ } else if (0 == ret_entry_count) {
+ break;
+ } else {
+ char *cursor = NULL; //pointer into attrbuf
+ char *entry_start = attrbuf;
+
+ for (int index = 0; index < ret_entry_count; index++) {
+ max_attr_entry_t attrs = {0};
+ char *name = NULL;
+
+ cursor = entry_start;
+
+ memcpy(&attrs.length, cursor, sizeof(attrs.length));
+ cursor += sizeof(attrs.length);
+
+ /* set starting point for next entry */
+ entry_start += attrs.length;
+
+ memcpy(&attrs.returned, cursor, sizeof(attrs.returned));
+ cursor += sizeof(attrs.returned);
+
+ if (attrs.returned.commonattr & ATTR_CMN_ERROR) {
+ memcpy(&attrs.error, cursor, sizeof(attrs.error));
+ cursor += sizeof(attrs.error);
+ }
+
+ if (attrs.error) {
+ DEBUGPRINT( "Got error %s while processing in %s\n", strerror(errno), path);
+ continue;
+ }
+
+ if (attrs.returned.commonattr & ATTR_CMN_NAME) {
+ memcpy(&attrs.item_name_info, cursor, sizeof(attrs.item_name_info));
+ name = cursor + attrs.item_name_info.attr_dataoffset;
+ if (name + attrs.item_name_info.attr_length > entry_start) {
+ name = NULL;
+ }
+ cursor += sizeof(attrs.item_name_info);
+ }
+
+ if (attrs.returned.commonattr & ATTR_CMN_OBJTYPE) {
+ memcpy(&attrs.type, cursor, sizeof(attrs.type));
+ cursor += sizeof(attrs.type);
+ }
+
+ if (attrs.returned.commonattr & ATTR_CMN_FILEID) {
+ memcpy(&attrs.fileid, cursor, sizeof(attrs.fileid));
+ cursor += sizeof(attrs.fileid);
+ }
+
+ if (VDIR == attrs.type) {
+ if (attrs.returned.dirattr & ATTR_DIR_ENTRYCOUNT) {
+ memcpy(&attrs.entry_count, cursor, sizeof(attrs.entry_count));
+ cursor += sizeof(attrs.entry_count);
+ } else {
+ // Fake it so we go down the right path below
+ attrs.entry_count = -1;
+ }
+
+ // avoid descending into empty directories
+ if (attrs.entry_count && name) {
+ struct dirqueue_entry *dqe = malloc(sizeof(struct dirqueue_entry));
+ if (path == NULL) {
+ dqe->path = strdup(name);
+ } else {
+ asprintf(&dqe->path, "%s/%s", path, name);
+ }
+
+ if (dqe->path != NULL) {
+ STAILQ_INSERT_TAIL(&dirqueue_head, dqe, entries);
+ } else {
+ DEBUGPRINT( "Unable to create dqe\n");
+ free(dqe);
+ }
+ } else if (attrs.entry_count != 0) {
+ DEBUGPRINT( "Failed to get name for item in %s\n", path);
+ } else if (attrs.entry_count == 0) {
+ // Empty directory, nothing to do
+ }
+ } else {
+ off_t object_size = 0;
+
+ if (attrs.returned.fileattr & ATTR_FILE_LINKCOUNT) {
+ memcpy(&attrs.link_count, cursor, sizeof(attrs.link_count));
+ cursor += sizeof(attrs.link_count);
+ }
+
+ if (attrs.returned.fileattr & ATTR_FILE_ALLOCSIZE) {
+ memcpy(&attrs.alloc_size, cursor, sizeof(attrs.alloc_size));
+ cursor += sizeof(attrs.alloc_size);
+ object_size = attrs.alloc_size;
+ }
+
+ if (attrs.returned.fileattr & ATTR_FILE_DATAALLOCSIZE) {
+ memcpy(&attrs.data_alloc_size, cursor, sizeof(attrs.data_alloc_size));
+ cursor += sizeof(attrs.data_alloc_size);
+ if (0 == object_size) {
+ object_size = attrs.data_alloc_size;
+ }
+ }
+
+ if (1 == attrs.link_count) {
+ ds->total_size += object_size;
+ } else {
+ bool new_fileid = _dirstat_fileid_set_add(fileid_seen, attrs.fileid);
+ if (new_fileid) {
+ ds->total_size += object_size;
+ } else {
+ DEBUGPRINT( "Skipping hardlinked file at %s/%s\n", path, name);
+ }
+ }
+ }
+ ds->descendants++;
+ }
+ }
+ }
+
+ if (path) {
+ close(fd);
+ free(path);
+ }
+ } while (!STAILQ_EMPTY(&dirqueue_head));
+
+ _dirstat_fileid_set_destroy(fileid_seen);
+
+ if (reterror) {
+ errno = reterror;
+ return -1;
+ } else {
+ return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DIRSTAT_H__
+#define __DIRSTAT_H__
+
+#include <sys/types.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+/* Fail if the file system does not support fast directory sizing on the provided directory */
+#define DIRSTAT_FAST_ONLY 0x1
+
+/* Do not use filesystem support for directory sizing. */
+#define DIRSTAT_FORCE_FALLBACK 0x2
+
+/*
+ * NOT ABI: the size of this structure may grow. You must pass the current
+ * size of this structure in as the dirstat_size argument to the functions
+ * below.
+ */
+struct dirstat {
+ off_t total_size;
+ uint64_t descendants;
+};
+
+/* Returns -1 on error and sets errno. Does not cross file-system boundaries. */
+__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+int dirstat_np(const char *path, int flags, struct dirstat *ds, size_t dirstat_size);
+
+__API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+int dirstatat_np(int dfd, const char *path, int flags, struct dirstat *ds, size_t dirstat_size);
+
+__END_DECLS
+
+#endif // __DIRSTAT_H__
--- /dev/null
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Newcomb.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2017 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Taken from file_cmds:du.c
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "dirstat_collection.h"
+
+struct fileid_entry {
+ struct fileid_entry *next;
+ struct fileid_entry *previous;
+ //int links;
+ uint64_t fileid;
+};
+
+
+struct dirstat_fileid_set_s {
+ struct fileid_entry **buckets;
+ struct fileid_entry *free_list;
+ size_t number_buckets;
+ unsigned long number_entries;
+ bool stop_allocating;
+};
+
+static const size_t links_hash_initial_size = 8192;
+
+dirstat_fileid_set_t
+_dirstat_fileid_set_create(void)
+{
+ dirstat_fileid_set_t ds = calloc(1, sizeof(dirstat_fileid_set_s));
+ ds->number_buckets = links_hash_initial_size;
+ ds->buckets = calloc(ds->number_buckets, sizeof(ds->buckets[0]));
+ if (ds->buckets == NULL) {
+ free(ds);
+ return NULL;
+ }
+ return ds;
+}
+
+void
+_dirstat_fileid_set_destroy(dirstat_fileid_set_t ds)
+{
+ struct fileid_entry *le;
+ for (size_t i = 0; i < ds->number_buckets; i++) {
+ while (ds->buckets[i] != NULL) {
+ le = ds->buckets[i];
+ ds->buckets[i] = le->next;
+ free(le);
+ }
+ }
+ free(ds->buckets);
+ free(ds);
+}
+
+bool
+_dirstat_fileid_set_add(dirstat_fileid_set_t ds, uint64_t fileid)
+{
+ struct fileid_entry *le, **new_buckets;
+ size_t i, new_size;
+ int hash;
+
+ /* If the hash table is getting too full, enlarge it. */
+ if (ds->number_entries > ds->number_buckets * 10 && !ds->stop_allocating) {
+ new_size = ds->number_buckets * 2;
+ new_buckets = calloc(new_size, sizeof(struct fileid_entry *));
+
+ /* Try releasing the free list to see if that helps. */
+ if (new_buckets == NULL && ds->free_list != NULL) {
+ while (ds->free_list != NULL) {
+ le = ds->free_list;
+ ds->free_list = le->next;
+ free(le);
+ }
+ new_buckets = calloc(new_size, sizeof(new_buckets[0]));
+ }
+
+ if (new_buckets == NULL) {
+ ds->stop_allocating = 1;
+ } else {
+ for (i = 0; i < ds->number_buckets; i++) {
+ while (ds->buckets[i] != NULL) {
+ /* Remove entry from old bucket. */
+ le = ds->buckets[i];
+ ds->buckets[i] = le->next;
+
+ /* Add entry to new bucket. */
+ hash = (int)(fileid % new_size);
+
+ if (new_buckets[hash] != NULL)
+ new_buckets[hash]->previous =
+ le;
+ le->next = new_buckets[hash];
+ le->previous = NULL;
+ new_buckets[hash] = le;
+ }
+ }
+ free(ds->buckets);
+ ds->buckets = new_buckets;
+ ds->number_buckets = new_size;
+ }
+ }
+
+ /* Try to locate this entry in the hash table. */
+ hash = (int)(fileid % ds->number_buckets);
+ for (le = ds->buckets[hash]; le != NULL; le = le->next) {
+ if (le->fileid == fileid) {
+#if 0 // TODO
+ /*
+ * Save memory by releasing an entry when we've seen
+ * all of its links.
+ */
+ if (--le->links <= 0) {
+ if (le->previous != NULL)
+ le->previous->next = le->next;
+ if (le->next != NULL)
+ le->next->previous = le->previous;
+ if (buckets[hash] == le)
+ buckets[hash] = le->next;
+ number_entries--;
+ /* Recycle this node through the free list */
+ if (stop_allocating) {
+ free(le);
+ } else {
+ le->next = free_list;
+ free_list = le;
+ }
+ }
+#endif
+ return true;
+ }
+ }
+
+ if (ds->stop_allocating)
+ return false;
+
+ /* Add this entry to the links cache. */
+ if (ds->free_list != NULL) {
+ /* Pull a node from the free list if we can. */
+ le = ds->free_list;
+ ds->free_list = le->next;
+ } else {
+ /* Malloc one if we have to. */
+ le = malloc(sizeof(struct fileid_entry));
+ }
+ if (le == NULL) {
+ ds->stop_allocating = 1;
+ return false;
+ }
+ le->fileid = fileid;
+ ds->number_entries++;
+ le->next = ds->buckets[hash];
+ le->previous = NULL;
+ if (ds->buckets[hash] != NULL)
+ ds->buckets[hash]->previous = le;
+ ds->buckets[hash] = le;
+ return false;
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+typedef struct dirstat_fileid_set_s dirstat_fileid_set_s;
+typedef dirstat_fileid_set_s *dirstat_fileid_set_t;
+
+dirstat_fileid_set_t _dirstat_fileid_set_create(void);
+void _dirstat_fileid_set_destroy(dirstat_fileid_set_t set);
+bool _dirstat_fileid_set_add(dirstat_fileid_set_t set, uint64_t fileid);
+
+__END_DECLS
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+void
+__libdarwin_init(void)
+{
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <dispatch/dispatch.h>
+#include <xpc/xpc.h>
+#include <xpc/private.h>
+#include <System/sys/csr.h>
+#include <System/machine/cpu_capabilities.h>
+
+#include <os/assumes.h>
+#include <os/variant_private.h>
+
+enum variant_property {
+ VP_ALL = 0,
+ VP_CONTENT,
+ VP_DIAGNOSTICS,
+ VP_UI,
+ VP_SECURITY,
+ VP_MAX
+};
+
+enum check_status {
+ S_UNKNOWN = 0,
+ S_NO = 2,
+ S_YES = 3
+};
+
+static bool
+status2bool(enum check_status status) {
+ switch (status) {
+ case S_NO:
+ return false;
+ case S_YES:
+ return true;
+ default:
+ os_crash("os_variant had unexpected status");
+ }
+}
+
+#define VAR_FILE_LEGACY "/var/db/disableAppleInternal"
+
+#if TARGET_OS_OSX
+#define VAR_FILE_OVERRIDE "/var/db/os_variant_override"
+#else
+#define VAR_FILE_OVERRIDE "/usr/share/misc/os_variant_override"
+#endif
+
+#if !TARGET_OS_SIMULATOR
+#define INTERNAL_CONTENT_PATH "/System/Library/CoreServices/AppleInternalVariant.plist"
+#else
+#define INTERNAL_CONTENT_PATH "/AppleInternal"
+#endif
+
+#define SYSTEM_VERSION_PLIST_PATH "/System/Library/CoreServices/SystemVersion.plist"
+#define SYSTEM_VERSION_PLIST_KEY "ReleaseType"
+
+#if TARGET_OS_IPHONE
+#define INTERNAL_SETTINGS_PATH "/AppleInternal/Library/PreferenceBundles/Internal Settings.bundle"
+#else
+#define INTERNAL_DIAGS_PROFILE_PATH "/var/db/ConfigurationProfiles/Settings/com.apple.InternalDiagnostics.plist"
+#endif
+
+#if !TARGET_OS_SIMULATOR
+#define CACHE_SYSCTL_NAME "kern.osvariant_status"
+
+static void _restore_cached_check_status(uint64_t status);
+static uint64_t _get_cached_check_status(void);
+
+static char * _read_file(const char *path, size_t *size_out)
+{
+ char *buf = NULL;
+
+ int fd = open(path, O_RDONLY);
+ if (fd == -1) return NULL;
+
+ struct stat sb;
+ int rc = fstat(fd, &sb);
+ if (rc != 0 || sb.st_size == 0) {
+ goto error;
+ }
+
+ size_t size_limit = (size_out && *size_out != 0) ? *size_out : 1024;
+ size_t size = (size_t)sb.st_size;
+ if (size_out) *size_out = (size_t)sb.st_size;
+ if (size > size_limit) {
+ goto error;
+ }
+
+ buf = malloc(size + 1);
+ if (!buf) {
+ goto error;
+ }
+
+ ssize_t bytes_read = read(fd, buf, size);
+ buf[size] = '\0';
+
+
+ if (bytes_read == (ssize_t)size) {
+ close(fd);
+ return buf;
+ }
+
+error:
+ close(fd);
+ free(buf);
+ return NULL;
+}
+
+static xpc_object_t read_plist(const char *path)
+{
+ size_t size = 16 * 1024;
+ uint8_t *buf = (uint8_t*)_read_file(path, &size);
+ if (!buf) return NULL;
+
+ xpc_object_t plist = xpc_create_from_plist(buf, size);
+ if (plist && xpc_get_type(plist) != XPC_TYPE_DICTIONARY) {
+ xpc_release(plist);
+ plist = NULL;
+ }
+
+ free(buf);
+
+ return plist;
+}
+#endif
+
+#if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+static enum check_status internal_content = S_UNKNOWN;
+#endif
+#if !TARGET_OS_SIMULATOR
+static enum check_status can_has_debugger = S_UNKNOWN;
+#if TARGET_OS_IPHONE
+static enum check_status internal_release_type = S_UNKNOWN;
+#else // TARGET_OS_IPHONE
+static enum check_status internal_diags_profile = S_UNKNOWN;
+#endif // TARGET_OS_IPHONE
+#endif // !TARGET_OS_SIMULATOR
+
+static bool disabled_status[VP_MAX] = {};
+
+static void _parse_disabled_status(char *test_string)
+{
+#if TARGET_OS_SIMULATOR
+#pragma unused(test_string)
+#else // TARGET_OS_SIMULATOR
+ char *override_str = NULL;
+
+ bzero(disabled_status, sizeof(disabled_status));
+
+ if (test_string != NULL) {
+ /* used for unit tests */
+ override_str = strdup(test_string);
+ } else {
+ if (access(VAR_FILE_LEGACY, F_OK) == 0) {
+ goto disable_all;
+ } else if (access(VAR_FILE_OVERRIDE, F_OK) != 0) {
+ return;
+ }
+
+ override_str = _read_file(VAR_FILE_OVERRIDE, NULL);
+ }
+
+ if (override_str == NULL) goto disable_all;
+
+ char *token, *string = override_str;
+ while ((token = strsep(&string, ",\n")) != NULL) {
+ if (strcmp(token, "content") == 0) {
+ disabled_status[VP_CONTENT] = true;
+ } else if (strcmp(token, "diagnostics") == 0) {
+ disabled_status[VP_DIAGNOSTICS] = true;
+ } else if (strcmp(token, "ui") == 0) {
+ disabled_status[VP_UI] = true;
+ } else if (strcmp(token, "security") == 0) {
+ disabled_status[VP_SECURITY] = true;
+ }
+ }
+
+ free(override_str);
+ return;
+
+disable_all:
+ for (int i = 0; i < VP_MAX; i++) {
+ disabled_status[i] = true;
+ }
+#endif //!TARGET_OS_SIMULATOR
+}
+
+#if !TARGET_OS_SIMULATOR
+static bool _load_cached_status(void)
+{
+ uint64_t status = 0;
+ size_t status_size = sizeof(status);
+ int ret = sysctlbyname(CACHE_SYSCTL_NAME, &status, &status_size, NULL, 0);
+ if (ret != 0) {
+ return false;
+ }
+
+ if (status) {
+ _restore_cached_check_status(status);
+ return true;
+ }
+
+ if (status == 0 && getpid() == 1) {
+ /*
+ * Looks like we are in launchd; try to set the status.
+ *
+ * We don't actually care if this works because we'll have warmed our state.
+ */
+ status = _get_cached_check_status();
+ sysctlbyname(CACHE_SYSCTL_NAME, NULL, 0, &status, status_size);
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+static void _initialize_status(void * __unused ctx)
+{
+#if !TARGET_OS_SIMULATOR
+ if (!_load_cached_status()) {
+ _parse_disabled_status(NULL);
+ }
+#else
+ _parse_disabled_status(NULL);
+#endif
+}
+
+static bool _check_disabled(enum variant_property variant_property)
+{
+ static dispatch_once_t disabled_status_pred;
+ dispatch_once_f(&disabled_status_pred, NULL, _initialize_status);
+
+ return disabled_status[variant_property];
+}
+
+#if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+static bool _check_internal_content(void)
+{
+ if (internal_content == S_UNKNOWN) {
+#if !TARGET_OS_SIMULATOR
+ const char * path = INTERNAL_CONTENT_PATH;
+#else
+ char *simulator_root = getenv("IPHONE_SIMULATOR_ROOT");
+ char *to_free = NULL, *path = NULL;
+ if (simulator_root) {
+ asprintf(&path, "%s/%s", simulator_root, INTERNAL_CONTENT_PATH);
+ if (path == NULL) {
+ return false;
+ }
+ to_free = path;
+ }
+#endif
+ internal_content = (access(path, F_OK) == 0) ? S_YES : S_NO;
+#if TARGET_OS_SIMULATOR
+ free(to_free);
+#endif
+ }
+ return status2bool(internal_content);
+}
+#endif // !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+
+#if TARGET_OS_IPHONE
+
+/*
+ * This set of criteria was taken from copyInternalBuild in MobileGestalt.c
+ */
+static bool _check_internal_release_type(void)
+{
+#if TARGET_OS_SIMULATOR
+ return _check_internal_content();
+#else // TARGET_OS_SIMULATOR
+ if (internal_release_type == S_UNKNOWN) {
+ xpc_object_t system_version_plist = read_plist(SYSTEM_VERSION_PLIST_PATH);
+ if (system_version_plist) {
+ const char *release_type =
+ xpc_dictionary_get_string(system_version_plist,
+ SYSTEM_VERSION_PLIST_KEY);
+
+ if (release_type == NULL) {
+ /*
+ * Confusingly, customer images are just completely missing this key.
+ */
+ internal_release_type = S_NO;
+ } else if (strcmp(release_type, "Internal") == 0 ||
+ strcmp(release_type, "Lite Internal") == 0 ||
+ strcmp(release_type, "NonUI") == 0) {
+ internal_release_type = S_YES;
+ } else {
+ internal_release_type = S_NO;
+ }
+
+ xpc_release(system_version_plist);
+ } else {
+ internal_release_type = (access(INTERNAL_SETTINGS_PATH, F_OK) == 0) ? S_YES : S_NO;
+ }
+ }
+
+ return status2bool(internal_release_type);
+#endif // TARGET_OS_SIMULATOR
+}
+
+#else
+
+static bool _check_internal_diags_profile() {
+ static enum check_status internal_diags_profile = S_UNKNOWN;
+
+ if (internal_diags_profile == S_UNKNOWN) {
+ xpc_object_t profile_settings = read_plist(INTERNAL_DIAGS_PROFILE_PATH);
+ if (profile_settings) {
+ internal_diags_profile = xpc_dictionary_get_bool(profile_settings, "AppleInternal") ? S_YES : S_NO;
+ xpc_release(profile_settings);
+ } else {
+ internal_diags_profile = S_NO;
+ }
+ }
+
+ return status2bool(internal_diags_profile);
+}
+
+#endif
+
+static bool _check_can_has_debugger(void)
+{
+#if TARGET_OS_SIMULATOR
+ return _check_internal_content();
+#else
+ if (can_has_debugger == S_UNKNOWN) {
+#if TARGET_OS_IPHONE
+ can_has_debugger = *((uint32_t *)_COMM_PAGE_DEV_FIRM) ? S_YES : S_NO;
+#else
+ /*
+ * The comm page bit does exist on macOS, but also requires kernel
+ * debugging in the CSR configuration. We don't need to be that strict
+ * here.
+ */
+ can_has_debugger = (csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0) ? S_YES : S_NO;
+#endif
+ }
+ return status2bool(can_has_debugger);
+#endif // TARGET_OS_SIMULATOR
+}
+
+// For unit tests
+#ifndef VARIANT_SKIP_EXPORTED
+
+bool
+os_variant_has_internal_content(const char * __unused subsystem)
+{
+ if (_check_disabled(VP_CONTENT)) {
+ return false;
+ }
+
+#if TARGET_OS_IPHONE
+ return _check_internal_release_type();
+#else
+ return _check_internal_content();
+#endif
+}
+
+
+bool
+os_variant_has_internal_diagnostics(const char * __unused subsystem)
+{
+ if (_check_disabled(VP_DIAGNOSTICS)) {
+ return false;
+ }
+
+#if TARGET_OS_IPHONE
+ return _check_internal_release_type();
+#else
+ return _check_internal_content() || _check_internal_diags_profile();
+#endif
+}
+
+bool
+os_variant_has_internal_ui(const char * __unused subsystem)
+{
+ if (_check_disabled(VP_UI)) {
+ return false;
+ }
+
+#if TARGET_OS_IPHONE
+ return _check_internal_release_type();
+#else
+ return _check_internal_content();
+#endif
+}
+
+bool
+os_variant_allows_internal_security_policies(const char * __unused subsystem)
+{
+ if (_check_disabled(VP_SECURITY)) {
+ return false;
+ }
+
+ return _check_can_has_debugger();
+}
+
+#endif // VARIANT_SKIP_EXPORTED
+
+#define STATUS_INITIAL_BITS 0x70000000F0000000ULL
+#define STATUS_BIT_WIDTH 2
+#define STATUS_SET 0x2
+#define STATUS_MASK 0x3
+
+enum status_flags_positions {
+ SFP_INTERNAL_CONTENT = 0,
+ SFP_CAN_HAS_DEBUGGER = 1,
+ SFP_INTERNAL_RELEASE_TYPE = 2,
+ SFP_INTERNAL_DIAGS_PROFILE = 3
+};
+
+#if !TARGET_OS_SIMULATOR
+static uint64_t _get_cached_check_status(void)
+{
+ uint64_t res = STATUS_INITIAL_BITS;
+
+#if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+ _check_internal_content();
+ if (internal_content != S_UNKNOWN)
+ res |= internal_content << SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH;
+#endif
+
+ _check_can_has_debugger();
+ if (can_has_debugger != S_UNKNOWN)
+ res |= can_has_debugger << SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH;
+
+#if TARGET_OS_IPHONE
+ _check_internal_release_type();
+ if (internal_release_type != S_UNKNOWN)
+ res |= internal_release_type << SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH;
+#else
+ _check_internal_diags_profile();
+ if (internal_diags_profile != S_UNKNOWN)
+ res |= internal_diags_profile << SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH;
+#endif
+
+ _parse_disabled_status(NULL);
+ for (int i = 0; i < VP_MAX; i++) {
+ if (disabled_status[i]) {
+ res |= 0x1ULL << (i + 32);
+ }
+ }
+
+ return res;
+}
+
+static void _restore_cached_check_status(uint64_t status)
+{
+#if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
+ if ((status >> (SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET)
+ internal_content = (status >> (SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK;
+#endif
+ if ((status >> (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH)) & STATUS_SET)
+ can_has_debugger = (status >> (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH)) & STATUS_MASK;
+#if TARGET_OS_IPHONE
+ if ((status >> (SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET)
+ internal_release_type = (status >> (SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK;
+#else
+ if ((status >> (SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH)) & STATUS_SET)
+ internal_diags_profile = (status >> (SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH)) & STATUS_MASK;
+#endif
+
+ for (int i = 0; i < VP_MAX; i++) {
+ disabled_status[i] = (status >> (32 + i)) & 0x1;
+ }
+}
+#endif // !TARGET_OS_SIMULATOR
__private_extern__ int
__collate_load_tables(const char *encoding, locale_t loc)
{
+ int fd;
FILE *fp;
int i, saverr, chains, z;
char strbuf[STR_LEN], buf[PATH_MAX];
/* Range checking not needed, encoding has fixed size */
(void)strcpy(buf, encoding);
(void)strcat(buf, "/LC_COLLATE");
- if ((fp = fdopen(__open_path_locale(buf), "r")) == NULL) {
+ fd = __open_path_locale(buf);
+ if (fd == -1) {
+ return (_LDP_ERROR);
+ }
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ close(fd);
return (_LDP_ERROR);
}
}
ncopy = MIN(MIN(n, GB18030_MB_CUR_MAX), sizeof(gs->bytes) - gs->count);
- strncpy(gs->bytes + gs->count, s, ncopy);
+ strncpy((char*)(gs->bytes + gs->count), s, ncopy);
ocount = gs->count;
gs->count += ncopy;
s = (char *)gs->bytes;
}
ncopy = MIN(MIN(n, GB2312_MB_CUR_MAX), sizeof(gs->bytes) - gs->count);
- strncpy(gs->bytes + gs->count, s, ncopy);
+ strncpy((char*)(gs->bytes + gs->count), s, ncopy);
ocount = gs->count;
gs->count += ncopy;
s = (char *)gs->bytes;
static struct __xlocale_st_runelocale *CachedRuneLocale;
extern int __mb_cur_max;
extern int __mb_sb_limit;
- static pthread_lock_t cache_lock = LOCK_INITIALIZER;
+ static os_unfair_lock cache_lock = OS_UNFAIR_LOCK_INIT;
/*
* The "C" and "POSIX" locale are always here.
/*
* If the locale name is the same as our cache, use the cache.
*/
- LOCK(cache_lock);
+ os_unfair_lock_lock(&cache_lock);
if (CachedRuneLocale != NULL &&
strcmp(encoding, CachedRuneLocale->__ctype_encoding) == 0) {
XL_RELEASE(loc->__lc_ctype);
__mb_cur_max = loc->__lc_ctype->__mb_cur_max;
__mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
}
- UNLOCK(cache_lock);
+ os_unfair_lock_unlock(&cache_lock);
return (0);
}
- UNLOCK(cache_lock);
+ os_unfair_lock_unlock(&cache_lock);
/*
* Slurp the locale file into the cache.
__mb_cur_max = loc->__lc_ctype->__mb_cur_max;
__mb_sb_limit = loc->__lc_ctype->__mb_sb_limit;
}
- LOCK(cache_lock);
+ os_unfair_lock_lock(&cache_lock);
XL_RELEASE(CachedRuneLocale);
CachedRuneLocale = xrl;
XL_RETAIN(CachedRuneLocale);
- UNLOCK(cache_lock);
+ os_unfair_lock_unlock(&cache_lock);
} else
XL_RELEASE(xrl);
#include "xlocale_private.h"
+#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
0, XPERMANENT, \
{}, {}, {}, {}, {}, \
{}, {}, {}, {}, {}, \
- LOCK_INITIALIZER, \
+ OS_UNFAIR_LOCK_INIT, \
XMAGIC, \
1, 0, 0, 0, 0, 0, 1, 1, 0, \
NULL, \
return NULL;
new->__refcount = 1;
new->__free_extra = (__free_extra_t)_releaselocale;
- new->__lock = LOCK_INITIALIZER;
+ new->__lock = OS_UNFAIR_LOCK_INIT;
if (loc == NULL)
loc = __current_locale();
else if (loc == LC_GLOBAL_LOCALE)
*new = __c_locale;
new->__refcount = 1;
new->__free_extra = (__free_extra_t)_releaselocale;
- new->__lock = LOCK_INITIALIZER;
+ new->__lock = OS_UNFAIR_LOCK_INIT;
return new;
}
XL_LOCK(loc);
#include <locale.h>
#include <libkern/OSAtomic.h>
#include <pthread.h>
-#include <pthread_spinlock.h>
#include <limits.h>
+#include <os/lock.h>
#include "setlocale.h"
#include "collate.h"
#include "runetype.h"
__darwin_mbstate_t __mbs_wcsnrtombs;
__darwin_mbstate_t __mbs_wcsrtombs;
__darwin_mbstate_t __mbs_wctomb;
- pthread_lock_t __lock;
+ os_unfair_lock __lock;
/* magic (Here up to the end is copied when duplicating locale_t's) */
int64_t __magic;
/* flags */
(x) = &__global_locale; \
}
-#define XL_LOCK(x) LOCK((x)->__lock);
+#define XL_LOCK(x) os_unfair_lock_lock(&(x)->__lock);
#define XL_RELEASE(x) if ((x) && (x)->__free_extra != XPERMANENT && OSAtomicDecrement32Barrier(&(x)->__refcount) == 0) { \
if ((x)->__free_extra) \
(*(x)->__free_extra)((x)); \
(x) = NULL; \
}
#define XL_RETAIN(x) if ((x) && (x)->__free_extra != XPERMANENT) { OSAtomicIncrement32Barrier(&(x)->__refcount); }
-#define XL_UNLOCK(x) UNLOCK((x)->__lock);
+#define XL_UNLOCK(x) os_unfair_lock_unlock(&(x)->__lock);
__attribute__((visibility("hidden")))
extern struct __xlocale_st_runelocale _DefaultRuneXLocale;
clock.3 clock.3
clock_gettime.3 clock_gettime.3 clock_settime.3 clock_getres.3 clock_gettime_nsec_np.3
confstr.3 confstr.3
+open_memstream.3 open_memstream.3 open_wmemstream.3
crypt.3 crypt.3 encrypt.3 setkey.3
ctermid.3 ctermid.3 ctermid_r.3
-ctime.3 ctime.3 asctime.3 asctime_r.3 asctime_r.3 ctime_r.3 difftime.3 gmtime.3 gmtime.3 gmtime_r.3 gmtime_r.3 localtime.3 localtime_r.3 mktime.3 mktime.3
+ctime.3 ctime.3 asctime.3 asctime_r.3 asctime_r.3 ctime_r.3 difftime.3 gmtime.3 gmtime.3 gmtime_r.3 gmtime_r.3 localtime.3 localtime_r.3 mktime.3 mktime.3 timegm.3 timelocal.3
ctype.3 ctype.3
ctype_l.3 ctype_l.3
daemon.3 daemon.3
fmtcheck.3 fmtcheck.3
fmtmsg.3 fmtmsg.3
fnmatch.3 fnmatch.3
-fopen.3 fopen.3 fdopen.3 freopen.3
+fopen.3 fopen.3 fdopen.3 freopen.3 fmemopen.3
fparseln.3 fparseln.3
fputs.3 fputs.3 puts.3
fputws.3 fputws.3 fputws_l.3
getlastlogx.3 getlastlogx.3 getlastlogxbyname.3 getutmp.3 getutmpx.3 utmpxname.3
getline.3 getline.3 getdelim.3
getloadavg.3 getloadavg.3
-getmntinfo.3 getmntinfo.3
+getmntinfo.3 getmntinfo.3 getmntinfo_r_np.3
getopt.3 getopt.3
getopt_long.3 getopt_long.3 getopt_long_only.3
getpagesize.3 getpagesize.3
memset_s.3 memset_s.3
memset_pattern.3 memset_pattern.3 memset_pattern4.3 memset_pattern8.3 memset_pattern16.3
mkpath_np.3 mkpath_np.3
-mktemp.3 mktemp.3 mkdtemp.3 mkstemp.3 mkstemps.3
+mktemp.3 mktemp.3 mkdtemp.3 mkstemp.3 mkstemps.3 mkostemp.3 mkostemps.3 mkdtempat_np.3 mkstempsat_np.3 mkostempsat_np.3
mpool.3 mpool.3 mpool_close.3 mpool_filter.3 mpool_get.3 mpool_new.3 mpool_open.3 mpool_put.3 mpool_sync.3
multibyte.3 multibyte.3
newlocale.3 newlocale.3
rand.3 rand.3 rand_r.3 srand.3 sranddev.3
rand48.3 rand48.3 _rand48.3 drand48.3 erand48.3 jrand48.3 lcong48.3 lrand48.3 mrand48.3 nrand48.3 seed48.3 srand48.3
random.3 random.3 initstate.3 setstate.3 srandom.3 srandomdev.3
-rbtree.3 rbtree.3
+rbtree.3 rbtree.3 rb_tree_init.3 rb_tree_insert_node.3 rb_tree_remove_node.3 rb_tree_find_node.3 rb_tree_find_node_geq.3 rb_tree_find_node_leq.3 rb_tree_iterate.3 rb_tree_count.3 RB_TREE_MIN.3 RB_TREE_MAX.3 RB_TREE_FOREACH.3 RB_TREE_FOREACH_REVERSE.3
readpassphrase.3 readpassphrase.3
realpath.3 realpath.3
recno.3 recno.3
tcsetpgrp.3 tcsetpgrp.3
time.3 time.3
time2posix.3 time2posix.3 posix2time.3
-timegm.3 timegm.3 timelocal.3
times.3 times.3
timezone.3 timezone.3
timingsafe_bcmp.3 timingsafe_bcmp.3
.Nm inet_netof ,
.Nm inet_network ,
.Nm inet_ntoa ,
-.Nm inet_ntoa_r ,
.Nm inet_ntop ,
.Nm inet_pton
.Nd Internet address manipulation routines
.Fo inet_ntoa
.Fa "struct in_addr in"
.Fc
-.Ft char *
-.Fo inet_ntoa_r
-.Fa "struct in_addr in"
-.Fa "char *buf"
-.Fa "socklen_t size"
-.Fc
.Ft const char *
.Fo inet_ntop
.Fa "int af"
.Ql .\&
notation.
The routine
-.Fn inet_ntoa_r
-is the reentrant version of
-.Fn inet_ntoa .
-The routine
.Fn inet_makeaddr
takes an Internet network number and a local
network address and constructs an Internet address
#include <mach-o/getsect.h>
#include <pthread.h>
#include <sys/types.h>
+#include <sys/reason.h>
#include <execinfo.h>
#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
#include "os/assumes.h"
#include <os/debug_private.h>
+#include <os/log.h>
+#include <os/log_private.h>
+#include <os/reason_private.h>
+
+#include <CrashReporterClient.h>
+#define os_set_crash_message(arg) CRSetCrashLogMessage(arg)
#define OSX_ASSUMES_LOG_REDIRECT_SECT_NAME "__osx_log_func"
#define os_atomic_cmpxchg(p, o, n) __sync_bool_compare_and_swap((p), (o), (n))
}
}
+__attribute__((always_inline))
+static inline bool
+_os_crash_fmt_impl(os_log_pack_t pack, size_t pack_size)
+{
+ /*
+ * We put just the format string into the CrashReporter buffer so that we
+ * can get at least that on customer builds.
+ */
+ const char *message = pack->olp_format;
+ _os_crash_impl(message);
+
+ char *(*_os_log_pack_send_and_compose)(os_log_pack_t, os_log_t,
+ os_log_type_t, char *, size_t) = NULL;
+ _os_log_pack_send_and_compose = dlsym(RTLD_DEFAULT, "os_log_pack_send_and_compose");
+ if (!_os_log_pack_send_and_compose) return false;
+
+ os_log_t __os_log_default = NULL;
+ __os_log_default = dlsym(RTLD_DEFAULT, "_os_log_default");
+ if (!__os_log_default) return false;
+
+ char *composed = _os_log_pack_send_and_compose(pack, __os_log_default,
+ OS_LOG_TYPE_FAULT, NULL, 0);
+
+ abort_with_payload(OS_REASON_LIBSYSTEM, OS_REASON_LIBSYSTEM_CODE_FAULT, pack, pack_size, composed, 0);
+}
+
__attribute__((always_inline))
static inline void
_os_assumes_log_impl(uint64_t code)
result = strdup(message);
}
-#if LIBC_NO_LIBCRASHREPORTERCLIENT
- /* There is no crash report information facility on embedded, which is
- * really regrettable. Fortunately, all we need to capture is the value
- * which tripped up the assertion. We can just stuff that into the thread's
- * name.
- */
- char name[64];
- (void)pthread_getname_np(pthread_self(), name, sizeof(name));
-
- char newname[64];
- if (strlen(name) == 0) {
- (void)snprintf(newname, sizeof(newname), "[Fatal bug: 0x%llx]", code);
- } else {
- (void)snprintf(newname, sizeof(newname), "%s [Fatal bug: 0x%llx]", name, code);
- }
-
- (void)pthread_setname_np(newname);
-#endif
-
return result;
}
_os_crash_impl(message);
}
+void _os_crash_fmt(os_log_pack_t pack, size_t pack_size)
+{
+ _os_crash_fmt_impl(pack, pack_size);
+}
+
void
_os_assumes_log(uint64_t code)
{
#define __OS_ASSUMES_H__
#include <sys/cdefs.h>
+#include <stdalign.h>
__BEGIN_DECLS
#define __OS_COMPILETIME_ASSERT__(e) (e)
#endif /* __GNUC__ */
+#pragma mark os_crash
-/* os_crash() is like os_hardware_trap(), except you get to pass in a crash
+/*
+ * os_crash() is like os_hardware_trap(), except you get to pass in a crash
* message, and it can be redirected to a callback function using
- * os_set_crash_callback() */
-#define os_crash(msg) \
+ * os_set_crash_callback()
+ */
+
+#define __os_crash_simple(msg) \
({ \
_os_crash(msg); \
os_hardware_trap(); \
})
-/* This is useful for clients who wish for the messages generated by assumes()
- * failures to go somewhere other than (or in addition to) the system log. If
- * you don't wish for the message to be logged to the system log, then return
- * true (to indicate that the message has been handled). If you want the default
- * behavior, return false.
- */
-typedef bool (*os_redirect_t)(const char *);
-struct _os_redirect_assumes_s {
- os_redirect_t redirect;
-};
+#if defined(OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE)
+#include <os/log_private.h>
+
+#define __os_crash_fmt(...) \
+ ({ \
+ const size_t size = os_log_pack_size(__VA_ARGS__); \
+ uint8_t buf[size] __attribute__((aligned(alignof(os_log_pack_s)))); \
+ os_log_pack_t pack = (os_log_pack_t)&buf; \
+ os_log_pack_fill(pack, size, errno, __VA_ARGS__); \
+ _os_crash_fmt(pack, size); \
+ os_hardware_trap(); \
+ })
-#define OS_ASSUMES_REDIRECT_SEG "__DATA"
-#define OS_ASSUMES_REDIRECT_SECT "__os_assumes_log"
+#define __os_crash_N(msg) __os_crash_simple(msg)
+#define __os_crash_Y(...) __os_crash_fmt(__VA_ARGS__)
-#define os_redirect_assumes(func) \
- __attribute__((__used__)) \
- __attribute__((__section__(OS_ASSUMES_REDIRECT_SEG "," OS_ASSUMES_REDIRECT_SECT))) \
- static struct _os_redirect_assumes_s _os_redirect_##func = { \
- .redirect = &func, \
- };
+// Returns Y if >1 argument, N if just one argument.
+#define __thirty_second_argument(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, \
+ _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, \
+ _26, _27, _28, _29, _30, _31, _32, ...) _32
+#define __has_more_than_one_argument(...) __thirty_second_argument(__VA_ARGS__, \
+ Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, Y, \
+ Y, Y, Y, Y, Y, Y, Y, N, EXTRA)
+
+#define __os_crash_invoke(variant, ...) \
+ OS_CONCAT(__os_crash_, variant)(__VA_ARGS__)
+
+#define os_crash(...) \
+ __os_crash_invoke(__has_more_than_one_argument(__VA_ARGS__), __VA_ARGS__)
+
+extern void
+_os_crash_fmt(os_log_pack_t, size_t);
+
+#else // OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE
+#define os_crash(msg) __os_crash_simple(msg)
+
+#endif // OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE
+
+/*
+ * An executable can register a callback to be made upon a crash using the
+ * os_set_crash_callback function. If a crash callback is not set, the symbol
+ * `os_crash_function` will be called in the main binary, if it exists.
+ */
typedef void (*os_crash_callback_t) (const char *);
-/* private. use os_get_crash_callback and os_set_crash_callback */
+/* private: use accessors below */
extern os_crash_callback_t _os_crash_callback;
static inline os_crash_callback_t
_os_crash_callback = callback;
}
-/* The asl_message argument is a _SIMPLE_STRING that, when given to _simple_asl_send(), will
- * direct the message to the MessageTracer diagnostic messages store rather than
- * the default system log store.
- */
-typedef bool (*os_log_callout_t)(_SIMPLE_STRING asl_message, void *ctx, const char *);
+#pragma mark os_assert
-#include <CrashReporterClient.h>
-#define os_set_crash_message(arg) CRSetCrashLogMessage(arg)
+#if defined(OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE)
-#define os_assumes(e) __extension__({ \
- __typeof__(e) _e = os_fastpath(e); \
- if (!_e) { \
- if (os_constant(e)) { \
- __OS_COMPILETIME_ASSERT__(e); \
- } \
- _os_assumes_log((uint64_t)(uintptr_t)_e); \
- _os_avoid_tail_call(); \
+#define _os_assert_crash(value, expression) ({ \
+ os_crash("assertion failure: \"" expression "\" -> %lld", value); \
+})
+
+#define _os_assert_crash_errno(value, expression) ({ \
+ os_crash("assertion failure: \"" expression "\" -> %{errno}d", value); \
+})
+
+#else // OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE
+
+#define _os_assert_crash(e, ...) ({ \
+ char *_fail_message = _os_assert_log(e); \
+ os_crash(_fail_message); \
+ free(_fail_message); \
+})
+
+#define _os_assert_crash_errno(...) _os_assert_crash(__VA_ARGS__)
+
+#endif // OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE
+
+#define __os_assert(e) __extension__({ \
+ __typeof__(e) _e = (e); \
+ if (os_unlikely(!_e)) { \
+ if (os_constant(e)) { __OS_COMPILETIME_ASSERT__((e)); } \
+ _os_assert_crash((uint64_t)(uintptr_t)_e, #e); \
} \
- _e; \
})
-#define os_assumes_zero(e) __extension__({ \
- __typeof__(e) _e = os_slowpath(e); \
- if (_e) { \
- if (os_constant(e)) { \
- __OS_COMPILETIME_ASSERT__(!(e)); \
- } \
- _os_assumes_log((uint64_t)(uintptr_t)_e); \
- _os_avoid_tail_call(); \
+#define __os_assert_zero(e) __extension__({ \
+ __typeof__(e) _e = (e); \
+ if (os_unlikely(_e)) { \
+ if (os_constant(e)) { __OS_COMPILETIME_ASSERT__(!(e)); } \
+ _os_assert_crash((uint64_t)(uintptr_t)_e, #e); \
} \
- _e; \
})
-/* This variant is for use with old-style POSIX APIs that return -1 on failure
+/*
+ * This variant is for use with old-style POSIX APIs that return -1 on failure
* and set errno. If the return code is -1, the value logged will be as though
- * os_assumes_zero(errno) was used. It encapsulates the following pattern:
+ * os_assert_zero(errno) was used. It encapsulates the following pattern:
*
* int tubes[2];
* if (pipe(tubes) == -1) {
- * (void)os_assumes_zero(errno);
+ * (void)os_assert_zero(errno);
* }
*/
-#define posix_assumes_zero(e) __extension__({ \
- __typeof__(e) _e = os_slowpath(e); \
- if (_e == (typeof(e))-1) { \
- _os_assumes_log((uint64_t)(uintptr_t)errno); \
- _os_avoid_tail_call(); \
+#define __posix_assert_zero(e) __extension__({ \
+ __typeof__(e) _e = (e); \
+ if (os_unlikely(_e == (__typeof__(e))-1)) { \
+ _os_assert_crash_errno(errno, #e); \
} \
- _e; \
})
-#define os_assert(e) __extension__({ \
+#if defined(OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE)
+
+#define __os_assert_msg(e, fmt, ...) __extension__({ \
+ __typeof__(e) _e = (e); \
+ if (os_unlikely(!_e)) { \
+ os_crash("assertion failure: " fmt, ##__VA_ARGS__); \
+ } \
+})
+
+#define __os_assert_zero_msg(e, fmt, ...) __extension__({ \
+ __typeof__(e) _e = (e); \
+ if (os_unlikely(_e)) { \
+ os_crash("assertion failure (%lld): " fmt, value, ##__VA_ARGS__); \
+ } \
+})
+
+#define __posix_assert_zero_msg(e, fmt, ...) __extension__({ \
+ __typeof__(e) _e = (e); \
+ if (os_unlikely(_e == (__typeof__(e))-1)) { \
+ os_crash("assertion failure (%{errno}d): " fmt, errno, ##__VA_ARGS__); \
+ } \
+})
+
+#define __os_assert_N(e) __os_assert(e)
+#define __os_assert_Y(...) __os_assert_msg(__VA_ARGS__)
+#define __os_assert_zero_N(e) __os_assert_zero(e)
+#define __os_assert_zero_Y(...) __os_assert_zero_msg(__VA_ARGS__)
+#define __posix_assert_zero_N(e) __posix_assert_zero(e)
+#define __posix_assert_zero_Y(...) __posix_assert_zero_msg(__VA_ARGS__)
+
+#define __os_assert_invoke(function, variant, ...) \
+ OS_CONCAT(function, variant)(__VA_ARGS__)
+
+#define os_assert(...) \
+ __os_assert_invoke(__os_assert_, \
+ __has_more_than_one_argument(__VA_ARGS__), __VA_ARGS__)
+#define os_assert_zero(...) \
+ __os_assert_invoke(__os_assert_zero_, \
+ __has_more_than_one_argument(__VA_ARGS__), __VA_ARGS__)
+#define posix_assert_zero(...) \
+ __os_assert_invoke(__posix_assert_zero_, \
+ __has_more_than_one_argument(__VA_ARGS__), __VA_ARGS__)
+
+#else // OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE
+
+#define os_assert(e) __os_assert(e)
+#define os_assert_zero(e) __os_assert_zero(e)
+#define posix_assert_zero(e) __posix_assert_zero(e)
+
+#endif
+
+#pragma mark os_assumes
+
+
+#define os_assumes(e) __extension__({ \
__typeof__(e) _e = os_fastpath(e); \
if (!_e) { \
if (os_constant(e)) { \
__OS_COMPILETIME_ASSERT__(e); \
} \
-\
- char *_fail_message = _os_assert_log((uint64_t)(uintptr_t)_e); \
- os_crash(_fail_message); \
- free(_fail_message); \
+ _os_assumes_log((uint64_t)(uintptr_t)_e); \
+ _os_avoid_tail_call(); \
} \
+ _e; \
})
-#define os_assert_zero(e) __extension__({ \
+#define os_assumes_zero(e) __extension__({ \
__typeof__(e) _e = os_slowpath(e); \
if (_e) { \
if (os_constant(e)) { \
__OS_COMPILETIME_ASSERT__(!(e)); \
} \
-\
- char *_fail_message = _os_assert_log((uint64_t)(uintptr_t)_e); \
- os_crash(_fail_message); \
- free(_fail_message); \
+ _os_assumes_log((uint64_t)(uintptr_t)_e); \
+ _os_avoid_tail_call(); \
} \
+ _e; \
})
-#define posix_assert_zero(e) __extension__({ \
+#define posix_assumes_zero(e) __extension__({ \
__typeof__(e) _e = os_slowpath(e); \
if (_e == (__typeof__(e))-1) { \
- char *_fail_message = _os_assert_log((uint64_t)(uintptr_t)errno); \
- os_crash(_fail_message); \
- free(_fail_message); \
+ _os_assumes_log((uint64_t)(uintptr_t)errno); \
+ _os_avoid_tail_call(); \
} \
+ _e; \
})
-/* These are for defining your own assumes()-like wrapper calls so that you can
+#pragma mark assumes redirection
+
+/* This is useful for clients who wish for the messages generated by assumes()
+ * failures to go somewhere other than (or in addition to) the system log. If
+ * you don't wish for the message to be logged to the system log, then return
+ * true (to indicate that the message has been handled). If you want the default
+ * behavior, return false.
+ */
+typedef bool (*os_redirect_t)(const char *);
+struct _os_redirect_assumes_s {
+ os_redirect_t redirect;
+};
+
+#define OS_ASSUMES_REDIRECT_SEG "__DATA"
+#define OS_ASSUMES_REDIRECT_SECT "__os_assumes_log"
+
+#define os_redirect_assumes(func) \
+ __attribute__((__used__)) \
+ __attribute__((__section__(OS_ASSUMES_REDIRECT_SEG "," OS_ASSUMES_REDIRECT_SECT))) \
+ static struct _os_redirect_assumes_s _os_redirect_##func = { \
+ .redirect = &func, \
+ };
+
+#pragma mark _ctx variants
+
+/*
+ * These are for defining your own assumes()-like wrapper calls so that you can
* log additional information, such as the about-PID, sender, etc. They're
* generally not useful for direct inclusion in your code.
*/
+
+/*
+ * The asl_message argument is a _SIMPLE_STRING that, when given to _simple_asl_send(), will
+ * direct the message to the MessageTracer diagnostic messages store rather than
+ * the default system log store.
+ */
+typedef bool (*os_log_callout_t)(_SIMPLE_STRING asl_message, void *ctx, const char *);
+
+
#define os_assumes_ctx(f, ctx, e) __extension__({ \
__typeof__(e) _e = os_fastpath(e); \
if (!_e) { \
} \
})
+#pragma mark internal symbols
+
__OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0)
extern void
_os_crash(const char *);
--- /dev/null
+/*
+ * Copyright (c) 2017 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __OS_VARIANT_H__
+#define __OS_VARIANT_H__
+
+#include <stdbool.h>
+
+#include <os/base.h>
+#include <os/availability.h>
+
+/*! @header
+ * OS Variant SPI
+ *
+ * Provides a mechanism to determine the currently running OS variant.
+ *
+ * Any of these APIs may be overridden to its non-internal behavior on a
+ * device by creating on override file. On macOS, this file is placed
+ * at:
+ * /var/db/os_variant_override
+ * On embedded platforms, this file is placed at:
+ * /usr/share/misc/os_variant_override
+ *
+ * Individual internal behaviors can be selectively disabled (ie.
+ * individual os_variant_has_internal_*() predicates can be overriden to
+ * false) by writing the file with a comma- or newline-delimited list of
+ * names to disable. To disable all internal behaviors, empty the file.
+ *
+ * Each of these functions takes a constant string argument for the requesting
+ * subsystem. This should be a reverse-DNS string describing the subsystem
+ * performing the check. This may be used in the future for auditing and
+ * selective overriding of checks.
+ *
+ */
+
+__BEGIN_DECLS
+
+/*!
+ * @function os_variant_has_internal_content
+ *
+ * @abstract returns whether this system variant has internal content installed
+ * ("content")
+ *
+ * @result
+ * Returns true if this build has this property. False otherwise or upon error.
+ */
+API_AVAILABLE(macosx(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+OS_EXPORT OS_WARN_RESULT
+bool
+os_variant_has_internal_content(const char *subsystem);
+
+/*!
+ * @function os_variant_has_internal_diagnostics
+ *
+ * @abstract returns whether this system variant has internal diagnostics
+ * enabled ("diagnostics")
+ *
+ * @description
+ *
+ * Internal diagnostics include behaviors that emit extra diagnostic or
+ * debugging information when an error occurs.
+ *
+ * On macOS, this check will look for presence of AppleInternal content or the
+ * AppleInternalDiagnostics profile to be installed.
+ *
+ * On embedded platforms, this check will look for an internal install variant
+ * in a manner similar to the MobileGestalt check for InternalBuild.
+ *
+ * @result
+ * Returns true if this build has this property. False otherwise or upon error.
+ */
+API_AVAILABLE(macosx(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+OS_EXPORT OS_WARN_RESULT
+bool
+os_variant_has_internal_diagnostics(const char *subsystem);
+
+/*!
+ * @function os_variant_has_internal_ui
+ *
+ * @abstract returns whether this system variant has internal UI visible ("ui")
+ *
+ * @description
+ *
+ * Internal UI includes debug menus and internal settings.
+ *
+ * On macOS, this will check for the presence of AppleInternal content. On
+ * embedded platforms, this check will look for an internal install variant in
+ * a manor similar to the MobileGestalt check for InternalBuild.
+ *
+ * @result
+ * Returns true if this build has this property. False otherwise or upon error.
+ */
+API_AVAILABLE(macosx(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+OS_EXPORT OS_WARN_RESULT
+bool
+os_variant_has_internal_ui(const char *subsystem);
+
+/*!
+ * @function os_variant_allows_internal_security_policies
+ *
+ * @abstract returns whether this system variant allows internal security policies
+ * ("security")
+ *
+ * @description
+ *
+ * On macOS, this will check the CSR status for whether AppleInternal policies
+ * are enabled.
+ *
+ * On embedded platforms, this will check for a build/device combination that
+ * allows for removal of codesigning and debugging restrictions. This usually
+ * returns whether the hardware is development fused and may return true on
+ * such hardware even if a customer build is installed.
+ *
+ * n.b. The result of this API should /not/ be used to automatically enable
+ * relaxed security policies, only to signal that other mechanisms to enable
+ * them are allowed, e.g. a "defaults write".
+ *
+ * @result
+ * Returns true if this build has this property. False otherwise or upon error.
+ */
+API_AVAILABLE(macosx(10.13), ios(11.0), tvos(11.0), watchos(4.0))
+OS_EXPORT OS_WARN_RESULT
+bool
+os_variant_allows_internal_security_policies(const char *subsystem);
+
+__END_DECLS
+
+#endif // __os_variant_H__
#include <stdlib.h>
#include <TargetConditionals.h>
+
+#if !defined(PR_13085474_CHECK)
+#define PR_13085474_CHECK 1
+
+/* Some shipped applications fail this check and were tested against
+ * versions of these functions that supported overlapping buffers.
+ *
+ * We would rather let such applications run, using the old memmove
+ * implementation, than abort() because they can't use the new
+ * implementation.
+ */
+
+#include <libkern/OSAtomic.h>
+#include <mach-o/dyld.h>
+#include <mach-o/dyld_priv.h>
+#define DYLD_OS_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
+#if TARGET_OS_IPHONE
+#define START_VERSION DYLD_OS_VERSION(7,0,0)
+#else
+#define START_VERSION DYLD_OS_VERSION(10,9,0)
+#endif
+#endif /* !PR_13085474_CHECK */
+
+/* For PR_13085474_CHECK set, we initialize __chk_assert_no_overlap to
+ * a value neither 0 or 1. We call _dyld_register_func_for_add_image()
+ * to register a callback, and use the non-one value of
+ * __chk_assert_no_overlap to skip sdk version checks (but we do
+ * perform overlap checks). To detect if the main program was built
+ * prior to START_VERSION, we call dyld_get_program_sdk_version(),
+ * which we do before setting up the callback (since we don't need it
+ * if the main program is older).
+ *
+ * After _dyld_register_func_for_add_image() returns, we set
+ * __chk_assert_no_overlap to 1, which enables the sdk version checking
+ * for subsequent loaded shared objects. If we then find an old version,
+ * we set __chk_assert_no_overlap to 0 to turn off overlap checking.
+ *
+ * If PR_13085474_CHECK is zero, then we never do any sdk version checking
+ * and always do overlap checks.
+ */
+__attribute__ ((visibility ("hidden")))
+uint32_t __chk_assert_no_overlap
+#if PR_13085474_CHECK
+ = 42;
+#else
+ = 1;
+#endif
+
+#if PR_13085474_CHECK
+static void
+__chk_assert_no_overlap_callback(const struct mach_header *mh, intptr_t vmaddr_slide __unused) {
+ if (__chk_assert_no_overlap != 1) return;
+ if (dyld_get_sdk_version(mh) < START_VERSION) OSAtomicAnd32(0U, &__chk_assert_no_overlap);
+}
+#endif
+
+__attribute__ ((visibility ("hidden")))
+void __chk_init(void) {
+#if PR_13085474_CHECK
+ if (dyld_get_program_sdk_version() < START_VERSION) {
+ __chk_assert_no_overlap = 0;
+ } else {
+ _dyld_register_func_for_add_image(__chk_assert_no_overlap_callback);
+ __chk_assert_no_overlap = 1;
+ }
+#endif
+}
+
+__attribute__ ((noreturn))
+static void
+__chk_fail (const char *message)
+{
+ syslog(LOG_CRIT, "%s", message);
+ abort_report_np("%s", message);
+}
+
+__attribute__ ((visibility ("hidden")))
+__attribute__ ((noreturn))
+void
+__chk_fail_overflow (void) {
+ __chk_fail("detected buffer overflow");
+}
+
+__attribute__ ((visibility ("hidden")))
+__attribute__ ((noreturn))
+void
+__chk_fail_overlap (void) {
+ __chk_fail("detected source and destination buffer overlap");
+}
+
+
+__attribute__ ((visibility ("hidden")))
+void
+__chk_overlap (const void *_a, size_t an, const void *_b, size_t bn) {
+ uintptr_t a = (uintptr_t)_a;
+ uintptr_t b = (uintptr_t)_b;
+
+ if (__builtin_expect(an == 0 || bn == 0, 0)) {
+ return;
+ } else if (__builtin_expect(a == b, 0)) {
+ __chk_fail_overlap();
+ } else if (a < b) {
+ if (__builtin_expect(a + an > b, 0))
+ __chk_fail_overlap();
+ } else { // b < a
+ if (__builtin_expect(b + bn > a, 0))
+ __chk_fail_overlap();
+ }
+}
__FBSDID("$FreeBSD: src/lib/libc/stdio/_flock_stub.c,v 1.16 2008/04/17 22:17:53 jhb Exp $");
#include "namespace.h"
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "local.h"
-
/*
* Weak symbols for externally visible functions in this file:
*/
void
_flockfile(FILE *fp)
{
+ // <rdar://problem/21533199> - preserve errno.
+ int save_errno = errno;
_pthread_mutex_lock(&fp->_fl_mutex);
+ errno = save_errno;
}
/*
{
int ret = 0;
+ // <rdar://problem/21533199> - preserve errno.
+ int save_errno = errno;
if (_pthread_mutex_trylock(&fp->_fl_mutex) != 0)
ret = -1;
-
+ errno = save_errno;
+
return (ret);
}
void
_funlockfile(FILE *fp)
{
+ // <rdar://problem/21533199> - preserve errno.
+ int save_errno = errno;
_pthread_mutex_unlock(&fp->_fl_mutex);
+ errno = save_errno;
}
return (wc);
}
do {
- nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate, loc);
+ nconv = __mbrtowc(&wc, (char*)fp->_p, fp->_r, &fp->_mbstate, loc);
if (nconv == (size_t)-1)
break;
else if (nconv == (size_t)-2)
#define FILELIST_UNLOCK() do { pthread_mutex_unlock(&filelist_lock); } while(0)
static struct glue *
-moreglue(n)
- int n;
+moreglue(int n)
{
struct glue *g;
FILE *p;
struct __sFILEX *fx;
+ size_t align;
- g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE) +
+ align = __alignof__( (struct { FILE f; struct __sFILEX s; }){} );
+ g = (struct glue *)malloc(sizeof(*g) + align + n * sizeof(FILE) +
n * sizeof(struct __sFILEX));
if (g == NULL)
return (NULL);
- p = (FILE *)ALIGN(g + 1);
+ p = (FILE *)roundup((uintptr_t)(g + 1), align);
fx = (struct __sFILEX *)&p[n];
g->next = NULL;
g->niobs = n;
pthread_once(&__sdidinit, __sinit);
if (count) {
- if (__scounted >= __stream_max) {
- if (__scounted >= (__stream_max = sysconf(_SC_STREAM_MAX))){
+ int32_t new = OSAtomicIncrement32(&__scounted);
+ if (new > __stream_max) {
+ if (new > (__stream_max = sysconf(_SC_STREAM_MAX))){
+ OSAtomicDecrement32(&__scounted);
errno = EMFILE;
return NULL;
}
}
- OSAtomicIncrement32(&__scounted);
}
/*
* The list must be locked because a FILE may be updated.
* The name `_cleanup' is, alas, fairly well known outside stdio.
*/
void
-_cleanup()
+_cleanup(void)
{
/* (void) _fwalk(fclose); */
(void) _fwalk(__sflush); /* `cheating' */
* __sinit() is called whenever stdio's internal variables must be set up.
*/
void
-__sinit()
+__sinit(void)
{
#if !TARGET_OS_EMBEDDED
int i;
--- /dev/null
+/*-
+ * Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
+ *
+ * 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 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 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 <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "local.h"
+
+struct fmemopen_cookie
+{
+ char *buf; /* pointer to the memory region */
+ bool own; /* did we allocate the buffer ourselves? */
+ char bin; /* is this a binary buffer? */
+ size_t size; /* buffer length in bytes */
+ size_t len; /* data length in bytes */
+ size_t off; /* current offset into the buffer */
+};
+
+static int fmemopen_read(void *cookie, char *buf, int nbytes);
+static int fmemopen_write(void *cookie, const char *buf, int nbytes);
+static fpos_t fmemopen_seek(void *cookie, fpos_t offset, int whence);
+static int fmemopen_close(void *cookie);
+
+FILE *
+fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
+{
+ struct fmemopen_cookie *ck;
+ FILE *f;
+ int flags, rc;
+
+ /*
+ * POSIX says we shall return EINVAL if size is 0.
+ */
+ if (size == 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Retrieve the flags as used by open(2) from the mode argument, and
+ * validate them.
+ */
+ rc = __sflags(mode, &flags);
+ if (rc == 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * There's no point in requiring an automatically allocated buffer
+ * in write-only mode.
+ */
+ if (!(flags & O_RDWR) && buf == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ ck = malloc(sizeof(struct fmemopen_cookie));
+ if (ck == NULL) {
+ return (NULL);
+ }
+
+ ck->off = 0;
+ ck->size = size;
+
+ /* Check whether we have to allocate the buffer ourselves. */
+ ck->own = ((ck->buf = buf) == NULL);
+ if (ck->own) {
+ ck->buf = malloc(size);
+ if (ck->buf == NULL) {
+ free(ck);
+ return (NULL);
+ }
+ }
+
+ /*
+ * POSIX distinguishes between w+ and r+, in that w+ is supposed to
+ * truncate the buffer.
+ */
+ if (ck->own || mode[0] == 'w') {
+ ck->buf[0] = '\0';
+ }
+
+ /* Check for binary mode. */
+ ck->bin = strchr(mode, 'b') != NULL;
+
+ /*
+ * The size of the current buffer contents is set depending on the
+ * mode:
+ *
+ * for append (text-mode), the position of the first NULL byte, or the
+ * size of the buffer if none is found
+ *
+ * for append (binary-mode), the size of the buffer
+ *
+ * for read, the size of the buffer
+ *
+ * for write, 0
+ */
+ switch (mode[0]) {
+ case 'a':
+ ck->off = ck->len = strnlen(ck->buf, ck->size);
+ break;
+ case 'r':
+ ck->len = size;
+ break;
+ case 'w':
+ ck->len = 0;
+ break;
+ }
+
+ f = funopen(ck,
+ flags & O_WRONLY ? NULL : fmemopen_read,
+ flags & O_RDONLY ? NULL : fmemopen_write,
+ fmemopen_seek, fmemopen_close);
+
+ if (f == NULL) {
+ if (ck->own)
+ free(ck->buf);
+ free(ck);
+ return (NULL);
+ }
+
+ if (mode[0] == 'a')
+ f->_flags |= __SAPP;
+
+ /*
+ * Turn off buffering, so a write past the end of the buffer
+ * correctly returns a short object count.
+ */
+ setvbuf(f, NULL, _IONBF, 0);
+
+ return (f);
+}
+
+static int
+fmemopen_read(void *cookie, char *buf, int nbytes)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+ if (nbytes > ck->len - ck->off)
+ nbytes = ck->len - ck->off;
+
+ if (nbytes == 0)
+ return (0);
+
+ memcpy(buf, ck->buf + ck->off, nbytes);
+
+ ck->off += nbytes;
+
+ return (nbytes);
+}
+
+static int
+fmemopen_write(void *cookie, const char *buf, int nbytes)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+ if (nbytes > ck->size - ck->off)
+ nbytes = ck->size - ck->off;
+
+ if (nbytes == 0)
+ return (0);
+
+ memcpy(ck->buf + ck->off, buf, nbytes);
+
+ ck->off += nbytes;
+
+ if (ck->off > ck->len)
+ ck->len = ck->off;
+
+ /*
+ * We append a NULL byte if all these conditions are met:
+ * - the buffer is not binary
+ * - the buffer is not full
+ * - the data just written doesn't already end with a NULL byte
+ */
+ if (!ck->bin && ck->off < ck->size && ck->buf[ck->off - 1] != '\0')
+ ck->buf[ck->off] = '\0';
+
+ return (nbytes);
+}
+
+static fpos_t
+fmemopen_seek(void *cookie, fpos_t offset, int whence)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+
+ switch (whence) {
+ case SEEK_SET:
+ if (offset > ck->size) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ck->off = offset;
+ break;
+
+ case SEEK_CUR:
+ if (ck->off + offset > ck->size) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ck->off += offset;
+ break;
+
+ case SEEK_END:
+ if (offset > 0 || -offset > ck->len) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ck->off = ck->len + offset;
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (ck->off);
+}
+
+static int
+fmemopen_close(void *cookie)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+ if (ck->own)
+ free(ck->buf);
+
+ free(ck);
+
+ return (0);
+}
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 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.
.\"
.\" SUCH DAMAGE.
.\"
.\" @(#)fopen.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdio/fopen.3,v 1.21 2009/09/09 19:38:19 ed Exp $
+.\" $FreeBSD$
.\"
-.Dd January 26, 2003
+.Dd January 30, 2013
.Dt FOPEN 3
.Os
.Sh NAME
-.Nm fdopen ,
.Nm fopen ,
-.Nm freopen
+.Nm fdopen ,
+.Nm freopen ,
+.Nm fmemopen
.Nd stream open functions
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In stdio.h
.Ft FILE *
-.Fo fdopen
-.Fa "int fildes"
-.Fa "const char *mode"
-.Fc
+.Fn fopen "const char * restrict path" "const char * restrict mode"
.Ft FILE *
-.Fo fopen
-.Fa "const char *restrict filename"
-.Fa "const char *restrict mode"
-.Fc
+.Fn fdopen "int fildes" "const char *mode"
.Ft FILE *
-.Fo freopen
-.Fa "const char *restrict filename"
-.Fa "const char *restrict mode"
-.Fa "FILE *restrict stream"
-.Fc
+.Fn freopen "const char *path" "const char *mode" "FILE *stream"
+.Ft FILE *
+.Fn fmemopen "void *restrict *buf" "size_t size" "const char * restrict mode"
.Sh DESCRIPTION
The
.Fn fopen
function
opens the file whose name is the string pointed to by
-.Fa filename
+.Fa path
and associates a stream with it.
.Pp
The argument
.Fa mode
-points to a string beginning with one of the following
-sequences (Additional characters may follow these sequences.):
+points to a string beginning with one of the following letters:
.Bl -tag -width indent
.It Dq Li r
-Open text file for reading.
-The stream is positioned at the beginning of the file.
-.It Dq Li r+
-Open for reading and writing.
+Open for reading.
The stream is positioned at the beginning of the file.
+Fail if the file does not exist.
.It Dq Li w
-Truncate to zero length or create text file for writing.
-The stream is positioned at the beginning of the file.
-.It Dq Li w+
-Open for reading and writing.
-The file is created if it does not exist, otherwise it is truncated.
+Open for writing.
The stream is positioned at the beginning of the file.
+Create the file if it does not exist.
.It Dq Li a
Open for writing.
-The file is created if it does not exist.
-The stream is positioned at the end of the file.
-Subsequent writes to the file will always end up at the then current
-end of file, irrespective of any intervening
-.Xr fseek 3
-or similar.
-.It Dq Li a+
-Open for reading and writing.
-The file is created if it does not exist.
The stream is positioned at the end of the file.
Subsequent writes to the file will always end up at the then current
end of file, irrespective of any intervening
.Xr fseek 3
or similar.
+Create the file if it does not exist.
.El
.Pp
+An optional
+.Dq Li +
+following
+.Dq Li r ,
+.Dq Li w ,
+or
+.Dq Li a
+opens the file for both reading and writing.
+An optional
+.Dq Li x
+following
+.Dq Li w
+or
+.Dq Li w+
+causes the
+.Fn fopen
+call to fail if the file already exists.
+An optional
+.Dq Li e
+following the above
+causes the
+.Fn fopen
+call to set the
+.Dv FD_CLOEXEC
+flag on the underlying file descriptor.
+.Pp
The
.Fa mode
-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.
+string can also include the letter
+.Dq Li b
+after either the
+.Dq Li +
+or the first letter.
This is strictly for compatibility with
.St -isoC
-and has no effect; the ``b'' is ignored.
-.Pp
-Finally, as an extension to the standards (and thus may not be portable),
-.Fa mode
-string may end with the letter ``x'', which insists on creating a new file
-when used with ``w'' or ``a''.
-If
-.Fa path
-exists, then an error is returned (this is the equivalent of specifying
-.Dv O_EXCL
-with
-.Xr open 2 ) .
+and has effect only for
+.Fn fmemopen
+; otherwise
+.Dq Li b
+is ignored.
.Pp
Any created files will have mode
-.Pf \\*q Dv S_IRUSR
+.Do Dv S_IRUSR
\&|
.Dv S_IWUSR
\&|
\&|
.Dv S_IROTH
\&|
-.Dv S_IWOTH Ns \\*q
+.Dv S_IWOTH Dc
.Pq Li 0666 ,
as modified by the process'
umask value (see
.Xr umask 2 ) .
-.\" C11 §7.21.5.3p7
.Pp
Reads and writes may be intermixed on read/write streams in any order; however,
a file positioning function must be called when switching between output and
.Fa fildes .
The mode
of the stream must be compatible with the mode of the file descriptor.
+The
+.Dq Li x
+mode option is ignored.
+If the
+.Dq Li e
+mode option is present, the
+.Dv FD_CLOEXEC
+flag is set, otherwise it remains unchanged.
When the stream is closed via
.Xr fclose 3 ,
.Fa fildes
.Fn freopen
function
opens the file whose name is the string pointed to by
-.Fa filename
+.Fa path
and associates the stream pointed to by
.Fa stream
with it.
function.
.Pp
If the
-.Fa filename
+.Fa path
argument is
.Dv NULL ,
.Fn freopen
with a new mode.
The new mode must be compatible with the mode that the stream was originally
opened with:
-.Bl -bullet -offset indent
-.It
-Streams originally opened with mode
-.Dq Li r
-can only be reopened with that same mode.
-.It
-Streams originally opened with mode
-.Dq Li a
-can be reopened with the same mode, or mode
-.Dq Li w .
-.It
-Streams originally opened with mode
-.Dq Li w
-can be reopened with the same mode, or mode
-.Dq Li a .
-.It
-Streams originally opened with mode
-.Dq Li r+ ,
-.Dq Li w+ ,
-or
-.Dq Li a+
-can be reopened with any mode.
-.El
+Streams open for reading can only be re-opened for reading,
+streams open for writing can only be re-opened for writing,
+and streams open for reading and writing can be re-opened in any mode.
+The
+.Dq Li x
+mode option is not meaningful in this context.
.Pp
The primary use of the
.Fn freopen
.Dv ( stderr , stdin ,
or
.Dv stdout ) .
+.Pp
+The
+.Fn fmemopen
+function
+associates the buffer given by the
+.Fa buf
+and
+.Fa size
+arguments with a stream.
+The
+.Fa buf
+argument is either a null pointer or a pointer to a buffer that
+is at least
+.Fa size
+bytes long.
+If a null pointer is specified as the
+.Fa buf
+argument,
+.Fn fmemopen
+allocates
+.Fa size
+bytes of memory, and this allocation is automatically freed when the stream is
+closed.
+If a non-null pointer is specified, the caller retains ownership of
+the buffer and is responsible for disposing of it after the stream has been
+closed.
+Buffers can be opened in text-mode (default) or binary-mode
+(if
+.Dq Li b
+is present in the second or third position of the
+.Fa mode
+argument). Buffers opened in text-mode make sure that writes are terminated with
+a NULL byte, if the last write hasn't filled up the whole buffer. Buffers
+opened in binary-mode never append a NULL byte.
.Sh RETURN VALUES
Upon successful completion
.Fn fopen ,
.Fn fdopen ,
-and
.Fn freopen
+and
+.Fn fmemopen
return a
.Tn FILE
pointer.
to
.Fn fopen ,
.Fn fdopen ,
+.Fn freopen ,
or
-.Fn freopen
+.Fn fmemopen
was invalid.
.El
.Pp
The
.Fn fopen ,
-.Fn fdopen
-and
+.Fn fdopen ,
.Fn freopen
+and
+.Fn fmemopen
functions
may also fail and set
.Va errno
.Xr fclose 3
and
.Xr fflush 3 .
+.Pp
+The
+.Fn fmemopen
+function
+may also fail and set
+.Va errno
+if the
+.Fa size
+argument is 0.
.Sh SEE ALSO
.Xr open 2 ,
.Xr fclose 3 ,
.Fn freopen
functions
conform to
-.St -isoC .
+.St -isoC ,
+with the exception of the
+.Dq Li x
+mode option which conforms to
+.St -isoC-2011 .
The
.Fn fdopen
function
conforms to
.St -p1003.1-88 .
+The
+.Dq Li e
+mode option does not conform to any standard
+but is also supported by glibc.
+The
+.Fn fmemopen
+function
+conforms to
+.St -p1003.1-2008 .
+The
+.Dq Li b
+mode does not conform to any standard
+but is also supported by glibc.
#include "local.h"
// 3340719: __puts_null__ is used if string is NULL. Defined in puts.c
-__private_extern__ char const __puts_null__[];
+extern char const __puts_null__[];
/*
* Write the given string to the given file.
linelen = 0;
while ((endp = memchr(fp->_p, delim, fp->_r)) == NULL) {
- if (sappend(linep, &linelen, linecapp, fp->_p, fp->_r))
+ if (sappend(linep, &linelen, linecapp, (char*)fp->_p, fp->_r))
goto error;
if (__srefill(fp)) {
if (__sferror(fp))
}
}
endp++; /* snarf the delimiter, too */
- if (sappend(linep, &linelen, linecapp, fp->_p, endp - fp->_p))
+ if (sappend(linep, &linelen, linecapp, (char*)fp->_p, endp - fp->_p))
goto error;
fp->_r -= endp - fp->_p;
fp->_p = endp;
.Nm mktemp ,
.Nm mkstemp ,
.Nm mkdtemp ,
+.Nm mkdtempat_np ,
.Nm mkstemps ,
+.Nm mkstempsat_np ,
.Nm mkostemp ,
-.Nm mkostemps
+.Nm mkostemps ,
+.Nm mkostempsat_np
.Nd make temporary file name (unique)
.Sh LIBRARY
.Lb libc
.Fo mkdtemp
.Fa "char *template"
.Fc
+.Ft char *
+.Fo mkdtempat_np
+.Fa "int dfd"
+.Fa "char *template"
+.Fc
.Ft int
.Fo mkstemps
.Fa "char *template"
.Fa "int suffixlen"
.Fc
.Ft int
+.Fo mkstempsat_np
+.Fa "int dfd"
+.Fa "char *template"
+.Fa "int suffixlen"
+.Fc
+.Ft int
.Fo mkostemp
.Fa "char *template"
.Fa "int oflags"
.Fa "int suffixlen"
.Fa "int oflags"
.Fc
+.Ft int
+.Fo mkostempsat_np
+.Fa "int dfd"
+.Fa "char *template"
+.Fa "int suffixlen"
+.Fa "int oflags"
+.Fc
.Sh DESCRIPTION
The
.Fn mktemp
.Fn mkostemps
functions
are told the length of the suffix string.
+.Pp
+The
+.Fn mkdtempat_np ,
+.Fn mkstempsat_np ,
+and
+.Fn mkostempsat_np
+functions
+act the same as
+.Fn mkdtemp ,
+.Fn mkstemps ,
+and
+.Fn mkostemps
+respectively,
+except in the case where the
+.Ar path
+specifies a relative path.
+In this case, path is treated as relative to the directory associated with the file descriptor
+.Ar fd
+instead of the current working directory.
.Sh RETURN VALUES
The
.Fn mktemp
#include <sys/cdefs.h>
#include "namespace.h"
+#include <assert.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <fcntl.h>
* Otherwise return FTPP_TRY_NEXT.
*/
typedef find_temp_path_progress_t (*find_temp_path_action_t)(
- char *path, void *ctx, void *result);
+ int dfd, char *path, void *ctx, void *result);
-static int find_temp_path(char *path, int slen, bool stat_base_dir,
+static int find_temp_path(int dfd, char *path, int slen, bool stat_base_dir,
find_temp_path_action_t action, void *action_ctx, void *action_result);
static find_temp_path_progress_t _mkostemps_action(
- char *path, void *ctx, void *result);
+ int dfd, char *path, void *ctx, void *result);
static find_temp_path_progress_t _mktemp_action(
- char *path, void *ctx, void *result);
+ int dfd, char *path, void *ctx, void *result);
static find_temp_path_progress_t _mkdtemp_action(
- char *path, void *ctx, void *result);
+ int dfd, char *path, void *ctx, void *result);
static find_temp_path_progress_t _mkstemp_dprotected_np_action(
- char *path, void *ctx, void *result);
+ int dfd, char *path, void *ctx, void *result);
static const char padchar[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
errno = EINVAL;
return -1;
}
- return (find_temp_path(path, slen, TRUE, _mkostemps_action, &oflags, &fd) ? fd : -1);
+ return (find_temp_path(AT_FDCWD, path, slen, TRUE, _mkostemps_action, &oflags, &fd) ? fd : -1);
+}
+
+int
+mkostempsat_np(int dfd, char *path, int slen, int oflags)
+{
+ int fd;
+ if (oflags & ~ALLOWED_MKOSTEMP_FLAGS) {
+ errno = EINVAL;
+ return -1;
+ }
+ return (find_temp_path(dfd, path, slen, TRUE, _mkostemps_action, &oflags, &fd) ? fd : -1);
}
int
{
int fd;
- return (find_temp_path(path, slen, TRUE, _mkostemps_action, NULL, &fd) ? fd : -1);
+ return (find_temp_path(AT_FDCWD, path, slen, TRUE, _mkostemps_action, NULL, &fd) ? fd : -1);
+}
+
+int
+mkstempsat_np(int dfd, char *path, int slen)
+{
+ int fd;
+
+ return (find_temp_path(dfd, path, slen, TRUE, _mkostemps_action, NULL, &fd) ? fd : -1);
}
int
errno = EINVAL;
return -1;
}
- return (find_temp_path(path, 0, TRUE, _mkostemps_action, &oflags, &fd) ? fd : -1);
+ return (find_temp_path(AT_FDCWD, path, 0, TRUE, _mkostemps_action, &oflags, &fd) ? fd : -1);
}
int
{
int fd;
- return (find_temp_path(path, 0, TRUE, _mkostemps_action, NULL, &fd) ? fd : -1);
+ return (find_temp_path(AT_FDCWD, path, 0, TRUE, _mkostemps_action, NULL, &fd) ? fd : -1);
}
char *
mkdtemp(char *path)
{
- return (find_temp_path(path, 0, TRUE, _mkdtemp_action, NULL, NULL) ?
+ return (find_temp_path(AT_FDCWD, path, 0, TRUE, _mkdtemp_action, NULL, NULL) ?
+ path : (char *)NULL);
+}
+
+char *
+mkdtempat_np(int dfd, char *path)
+{
+ return (find_temp_path(dfd, path, 0, TRUE, _mkdtemp_action, NULL, NULL) ?
path : (char *)NULL);
}
char *
_mktemp(char *path)
{
- return (find_temp_path(path, 0, FALSE, _mktemp_action, NULL, NULL) ?
+ return (find_temp_path(AT_FDCWD, path, 0, FALSE, _mktemp_action, NULL, NULL) ?
path : (char *)NULL);
}
int fd;
int ctx[2] = { class, dpflags };
- return (find_temp_path(path, 0, TRUE, _mkstemp_dprotected_np_action, &ctx, &fd) ? fd : -1);
+ return (find_temp_path(AT_FDCWD, path, 0, TRUE, _mkstemp_dprotected_np_action, &ctx, &fd) ? fd : -1);
}
/* For every path matching a given template, invoke an action. Depending on
* Returns 1 if succeeds, 0 and sets errno if fails.
*/
static int
-find_temp_path(char *path, int slen, bool stat_base_dir,
+find_temp_path(int dfd, char *path, int slen, bool stat_base_dir,
find_temp_path_action_t action, void *action_ctx, void *action_result)
{
char *start, *trv, *suffp, *carryp;
for (; trv > path; --trv) {
if (*trv == '/') {
*trv = '\0';
- rval = stat(path, &sbuf);
+ rval = fstatat(dfd, path, &sbuf, 0);
*trv = '/';
if (rval != 0)
return (0);
}
for (;;) {
- switch (action(path, action_ctx, action_result)) {
+ switch (action(dfd, path, action_ctx, action_result)) {
case FTPP_DONE:
return (1);
case FTPP_ERROR:
}
static find_temp_path_progress_t
-_mkostemps_action(char *path, void *ctx, void *result)
+_mkostemps_action(int dfd, char *path, void *ctx, void *result)
{
int oflags = (ctx != NULL) ? *((int *) ctx) : 0;
- int fd = _open(path, O_CREAT|O_EXCL|O_RDWR|oflags, 0600);
+ int fd = openat(dfd, path, O_CREAT|O_EXCL|O_RDWR|oflags, 0600);
if (fd >= 0) {
*((int *) result) = fd;
return FTPP_DONE;
}
static find_temp_path_progress_t
-_mktemp_action(char *path, void *ctx __unused, void *result __unused)
+_mktemp_action(int dfd, char *path, void *ctx __unused, void *result __unused)
{
struct stat sbuf;
- if (lstat(path, &sbuf)) {
+ if (fstatat(dfd, path, &sbuf, AT_SYMLINK_NOFOLLOW)) {
// stat failed
return (errno == ENOENT) ?
FTPP_DONE : // path is vacant, done
}
static find_temp_path_progress_t
-_mkdtemp_action(char *path, void *ctx __unused, void *result __unused)
+_mkdtemp_action(int dfd, char *path, void *ctx __unused, void *result __unused)
{
- if (mkdir(path, 0700) == 0)
+ if (mkdirat(dfd, path, 0700) == 0)
return FTPP_DONE;
return (errno == EEXIST) ?
FTPP_TRY_NEXT :
}
static find_temp_path_progress_t
-_mkstemp_dprotected_np_action(char *path, void *ctx, void *result)
+_mkstemp_dprotected_np_action(int dfd, char *path, void *ctx, void *result)
{
+ assert(dfd == AT_FDCWD);
+
int class = ((int *) ctx)[0];
int dpflags = ((int *) ctx)[1];
int fd = open_dprotected_np(path, O_CREAT|O_EXCL|O_RDWR, class, dpflags, 0600);
--- /dev/null
+.\" Copyright (c) 2013 Hudson River Trading 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 August 1, 2015
+.Dt OPEN_MEMSTREAM 3
+.Os
+.Sh NAME
+.Nm open_memstream ,
+.Nm open_wmemstream
+.Nd dynamic memory buffer stream open functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft FILE *
+.Fn open_memstream "char **bufp" "size_t *sizep"
+.In wchar.h
+.Ft FILE *
+.Fn open_wmemstream "wchar_t **bufp" "size_t *sizep"
+.Sh DESCRIPTION
+The
+.Fn open_memstream
+and
+.Fn open_wmemstream
+functions create a write-only, seekable stream backed by a dynamically
+allocated memory buffer.
+The
+.Fn open_memstream
+function creates a byte-oriented stream,
+while the
+.Fn open_wmemstream
+function creates a wide-oriented stream.
+.Pp
+Each stream maintains a current position and size.
+Initially,
+the position and size are set to zero.
+Each write begins at the current position and advances it the number of
+successfully written bytes for
+.Fn open_memstream
+or wide characters for
+.Fn open_wmemstream .
+If a write moves the current position beyond the length of the buffer,
+the length of the buffer is extended and a null character is appended to the
+buffer.
+.Pp
+A stream's buffer always contains a null character at the end of the buffer
+that is not included in the current length.
+.Pp
+If a stream's current position is moved beyond the current length via a
+seek operation and a write is performed,
+the characters between the current length and the current position are filled
+with null characters before the write is performed.
+.Pp
+After a successful call to
+.Xr fclose 3
+or
+.Xr fflush 3 ,
+the pointer referenced by
+.Fa bufp
+will contain the start of the memory buffer and the variable referenced by
+.Fa sizep
+will contain the smaller of the current position and the current buffer length.
+.Pp
+After a successful call to
+.Xr fflush 3 ,
+the pointer referenced by
+.Fa bufp
+and the variable referenced by
+.Fa sizep
+are only valid until the next write operation or a call to
+.Xr fclose 3 .
+.Pp
+Once a stream is closed,
+the allocated buffer referenced by
+.Fa bufp
+should be released via a call to
+.Xr free 3
+when it is no longer needed.
+.Sh IMPLEMENTATION NOTES
+Internally all I/O streams are effectively byte-oriented,
+so using wide-oriented operations to write to a stream opened via
+.Fn open_wmemstream
+results in wide characters being expanded to a stream of multibyte characters
+in stdio's internal buffers.
+These multibyte characters are then converted back to wide characters when
+written into the stream.
+As a result,
+the wide-oriented streams maintain an internal multibyte character conversion
+state that is cleared on any seek opertion that changes the current position.
+This should have no effect as long as wide-oriented output operations are used
+on a wide-oriented stream.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn open_memstream
+and
+.Fn open_wmemstream
+return a
+.Tn FILE
+pointer.
+Otherwise,
+.Dv NULL
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa bufp
+or
+.Fa sizep
+argument was
+.Dv NULL .
+.It Bq Er ENOMEM
+Memory for the stream or buffer could not be allocated.
+.El
+.Sh SEE ALSO
+.Xr fclose 3 ,
+.Xr fflush 3 ,
+.Xr fopen 3 ,
+.Xr free 3 ,
+.Xr fseek 3 ,
+.Xr stdio 3 ,
+.Xr sbuf 9
+.Sh STANDARDS
+The
+.Fn open_memstream
+and
+.Fn open_wmemstream
+functions conform to
+.St -p1003.1-2008 .
--- /dev/null
+/*-
+ * Copyright (c) 2013 Hudson River Trading 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#ifdef DEBUG
+#include <stdint.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+/* XXX: There is no FPOS_MAX. This assumes fpos_t is an off_t. */
+#define FPOS_MAX OFF_MAX
+
+struct memstream {
+ char **bufp;
+ size_t *sizep;
+ ssize_t len;
+ fpos_t offset;
+};
+
+static int
+memstream_grow(struct memstream *ms, fpos_t newoff)
+{
+ char *buf;
+ ssize_t newsize;
+
+ if (newoff < 0 || newoff >= SSIZE_MAX)
+ newsize = SSIZE_MAX - 1;
+ else
+ newsize = newoff;
+ if (newsize > ms->len) {
+ buf = realloc(*ms->bufp, newsize + 1);
+ if (buf != NULL) {
+#ifdef DEBUG
+ fprintf(stderr, "MS: %p growing from %zd to %zd\n",
+ ms, ms->len, newsize);
+#endif
+ memset(buf + ms->len + 1, 0, newsize - ms->len);
+ *ms->bufp = buf;
+ ms->len = newsize;
+ return (1);
+ }
+ return (0);
+ }
+ return (1);
+}
+
+static void
+memstream_update(struct memstream *ms)
+{
+
+ assert(ms->len >= 0 && ms->offset >= 0);
+ *ms->sizep = ms->len < ms->offset ? ms->len : ms->offset;
+}
+
+static int
+memstream_write(void *cookie, const char *buf, int len)
+{
+ struct memstream *ms;
+ ssize_t tocopy;
+
+ ms = cookie;
+ if (!memstream_grow(ms, ms->offset + len))
+ return (-1);
+ tocopy = ms->len - ms->offset;
+ if (len < tocopy)
+ tocopy = len;
+ memcpy(*ms->bufp + ms->offset, buf, tocopy);
+ ms->offset += tocopy;
+ memstream_update(ms);
+#ifdef DEBUG
+ fprintf(stderr, "MS: write(%p, %d) = %zd\n", ms, len, tocopy);
+#endif
+ return (tocopy);
+}
+
+static fpos_t
+memstream_seek(void *cookie, fpos_t pos, int whence)
+{
+ struct memstream *ms;
+#ifdef DEBUG
+ fpos_t old;
+#endif
+
+ ms = cookie;
+#ifdef DEBUG
+ old = ms->offset;
+#endif
+ switch (whence) {
+ case SEEK_SET:
+ /* _fseeko() checks for negative offsets. */
+ assert(pos >= 0);
+ ms->offset = pos;
+ break;
+ case SEEK_CUR:
+ /* This is only called by _ftello(). */
+ assert(pos == 0);
+ break;
+ case SEEK_END:
+ if (pos < 0) {
+ if (pos + ms->len < 0) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "MS: bad SEEK_END: pos %jd, len %zd\n",
+ (intmax_t)pos, ms->len);
+#endif
+ errno = EINVAL;
+ return (-1);
+ }
+ } else {
+ if (FPOS_MAX - ms->len < pos) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "MS: bad SEEK_END: pos %jd, len %zd\n",
+ (intmax_t)pos, ms->len);
+#endif
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ }
+ ms->offset = ms->len + pos;
+ break;
+ }
+ memstream_update(ms);
+#ifdef DEBUG
+ fprintf(stderr, "MS: seek(%p, %jd, %d) %jd -> %jd\n", ms, (intmax_t)pos,
+ whence, (intmax_t)old, (intmax_t)ms->offset);
+#endif
+ return (ms->offset);
+}
+
+static int
+memstream_close(void *cookie)
+{
+
+ free(cookie);
+ return (0);
+}
+
+FILE *
+open_memstream(char **bufp, size_t *sizep)
+{
+ struct memstream *ms;
+ int save_errno;
+ FILE *fp;
+
+ if (bufp == NULL || sizep == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ *bufp = calloc(1, 1);
+ if (*bufp == NULL)
+ return (NULL);
+ ms = malloc(sizeof(*ms));
+ if (ms == NULL) {
+ save_errno = errno;
+ free(*bufp);
+ *bufp = NULL;
+ errno = save_errno;
+ return (NULL);
+ }
+ ms->bufp = bufp;
+ ms->sizep = sizep;
+ ms->len = 0;
+ ms->offset = 0;
+ memstream_update(ms);
+ fp = funopen(ms, NULL, memstream_write, memstream_seek,
+ memstream_close);
+ if (fp == NULL) {
+ save_errno = errno;
+ free(ms);
+ free(*bufp);
+ *bufp = NULL;
+ errno = save_errno;
+ return (NULL);
+ }
+ fwide(fp, -1);
+ return (fp);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2013 Hudson River Trading 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#ifdef DEBUG
+#include <stdint.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <malloc_private.h>
+
+/* XXX: There is no FPOS_MAX. This assumes fpos_t is an off_t. */
+#define FPOS_MAX OFF_MAX
+
+struct wmemstream {
+ wchar_t **bufp;
+ size_t *sizep;
+ ssize_t len;
+ fpos_t offset;
+ mbstate_t mbstate;
+};
+
+static int
+wmemstream_grow(struct wmemstream *ms, fpos_t newoff)
+{
+ wchar_t *buf;
+ ssize_t newsize;
+
+ if (newoff < 0 || newoff >= SSIZE_MAX / sizeof(wchar_t))
+ newsize = SSIZE_MAX / sizeof(wchar_t) - 1;
+ else
+ newsize = newoff;
+ if (newsize > ms->len) {
+ buf = reallocarray(*ms->bufp, newsize + 1, sizeof(wchar_t));
+ if (buf != NULL) {
+#ifdef DEBUG
+ fprintf(stderr, "WMS: %p growing from %zd to %zd\n",
+ ms, ms->len, newsize);
+#endif
+ wmemset(buf + ms->len + 1, 0, newsize - ms->len);
+ *ms->bufp = buf;
+ ms->len = newsize;
+ return (1);
+ }
+ return (0);
+ }
+ return (1);
+}
+
+static void
+wmemstream_update(struct wmemstream *ms)
+{
+
+ assert(ms->len >= 0 && ms->offset >= 0);
+ *ms->sizep = ms->len < ms->offset ? ms->len : ms->offset;
+}
+
+/*
+ * Based on a starting multibyte state and an input buffer, determine
+ * how many wchar_t's would be output. This doesn't use mbsnrtowcs()
+ * so that it can handle embedded null characters.
+ */
+static size_t
+wbuflen(const mbstate_t *state, const char *buf, int len)
+{
+ mbstate_t lenstate;
+ size_t charlen, count;
+
+ count = 0;
+ lenstate = *state;
+ while (len > 0) {
+ charlen = mbrlen(buf, len, &lenstate);
+ if (charlen == (size_t)-1)
+ return (-1);
+ if (charlen == (size_t)-2)
+ break;
+ if (charlen == 0)
+ /* XXX: Not sure how else to handle this. */
+ charlen = 1;
+ len -= charlen;
+ buf += charlen;
+ count++;
+ }
+ return (count);
+}
+
+static int
+wmemstream_write(void *cookie, const char *buf, int len)
+{
+ struct wmemstream *ms;
+ ssize_t consumed, wlen;
+ size_t charlen;
+
+ ms = cookie;
+ wlen = wbuflen(&ms->mbstate, buf, len);
+ if (wlen < 0) {
+ errno = EILSEQ;
+ return (-1);
+ }
+ if (!wmemstream_grow(ms, ms->offset + wlen))
+ return (-1);
+
+ /*
+ * This copies characters one at a time rather than using
+ * mbsnrtowcs() so it can properly handle embedded null
+ * characters.
+ */
+ consumed = 0;
+ while (len > 0 && ms->offset < ms->len) {
+ charlen = mbrtowc(*ms->bufp + ms->offset, buf, len,
+ &ms->mbstate);
+ if (charlen == (size_t)-1) {
+ if (consumed == 0) {
+ errno = EILSEQ;
+ return (-1);
+ }
+ /* Treat it as a successful short write. */
+ break;
+ }
+ if (charlen == 0)
+ /* XXX: Not sure how else to handle this. */
+ charlen = 1;
+ if (charlen == (size_t)-2) {
+ consumed += len;
+ len = 0;
+ } else {
+ consumed += charlen;
+ buf += charlen;
+ len -= charlen;
+ ms->offset++;
+ }
+ }
+ wmemstream_update(ms);
+#ifdef DEBUG
+ fprintf(stderr, "WMS: write(%p, %d) = %zd\n", ms, len, consumed);
+#endif
+ return (consumed);
+}
+
+static fpos_t
+wmemstream_seek(void *cookie, fpos_t pos, int whence)
+{
+ struct wmemstream *ms;
+ fpos_t old;
+
+ ms = cookie;
+ old = ms->offset;
+ switch (whence) {
+ case SEEK_SET:
+ /* _fseeko() checks for negative offsets. */
+ assert(pos >= 0);
+ ms->offset = pos;
+ break;
+ case SEEK_CUR:
+ /* This is only called by _ftello(). */
+ assert(pos == 0);
+ break;
+ case SEEK_END:
+ if (pos < 0) {
+ if (pos + ms->len < 0) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "WMS: bad SEEK_END: pos %jd, len %zd\n",
+ (intmax_t)pos, ms->len);
+#endif
+ errno = EINVAL;
+ return (-1);
+ }
+ } else {
+ if (FPOS_MAX - ms->len < pos) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "WMS: bad SEEK_END: pos %jd, len %zd\n",
+ (intmax_t)pos, ms->len);
+#endif
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ }
+ ms->offset = ms->len + pos;
+ break;
+ }
+ /* Reset the multibyte state if a seek changes the position. */
+ if (ms->offset != old)
+ memset(&ms->mbstate, 0, sizeof(ms->mbstate));
+ wmemstream_update(ms);
+#ifdef DEBUG
+ fprintf(stderr, "WMS: seek(%p, %jd, %d) %jd -> %jd\n", ms,
+ (intmax_t)pos, whence, (intmax_t)old, (intmax_t)ms->offset);
+#endif
+ return (ms->offset);
+}
+
+static int
+wmemstream_close(void *cookie)
+{
+
+ free(cookie);
+ return (0);
+}
+
+FILE *
+open_wmemstream(wchar_t **bufp, size_t *sizep)
+{
+ struct wmemstream *ms;
+ int save_errno;
+ FILE *fp;
+
+ if (bufp == NULL || sizep == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ *bufp = calloc(1, sizeof(wchar_t));
+ if (*bufp == NULL)
+ return (NULL);
+ ms = malloc(sizeof(*ms));
+ if (ms == NULL) {
+ save_errno = errno;
+ free(*bufp);
+ *bufp = NULL;
+ errno = save_errno;
+ return (NULL);
+ }
+ ms->bufp = bufp;
+ ms->sizep = sizep;
+ ms->len = 0;
+ ms->offset = 0;
+ memset(&ms->mbstate, 0, sizeof(mbstate_t));
+ wmemstream_update(ms);
+ fp = funopen(ms, NULL, wmemstream_write, wmemstream_seek,
+ wmemstream_close);
+ if (fp == NULL) {
+ save_errno = errno;
+ free(ms);
+ free(*bufp);
+ *bufp = NULL;
+ errno = save_errno;
+ return (NULL);
+ }
+ fwide(fp, 1);
+ return (fp);
+}
.Vt "int *"
(or variant) pointer argument.
No argument is converted.
+The
+.Fa format
+argument must be in write-protected memory if this specifier is used; see
+.Sx SECURITY CONSIDERATIONS
+below.
.It Cm %
A
.Ql %
as the resulting string may still contain user-supplied conversion specifiers
for later interpolation by
.Fn printf .
+For this reason, a
+.Fa format
+argument containing
+.Cm %n
+is assumed to be untrustworthy if located in writable memory (i.e. memory with
+protection PROT_WRITE; see
+.Xr mprotect 2 )
+and any attempt to use such an argument is fatal.
+Practically, this means that
+.Cm %n
+is permitted in literal
+.Fa format
+strings but disallowed in
+.Fa format
+strings located in normal stack- or heap-allocated memory.
.Pp
Always use the proper secure idiom:
.Pp
#include <stdarg.h>
#include "un-namespace.h"
+#include <os/assumes.h>
+#include <mach-o/dyld_priv.h>
+#include <mach/vm_region.h>
+
#include "libc_private.h"
#include "local.h"
#include "fvwrite.h"
#error "BUF must be large enough to format a uintmax_t"
#endif
+__private_extern__ bool
+__printf_is_memory_read_only(void *addr, size_t __unused size)
+{
+ vm_address_t address = addr;
+ vm_size_t vmsize = 0;
+ vm_region_basic_info_data_64_t info;
+ mach_msg_type_number_t info_cnt = VM_REGION_BASIC_INFO_COUNT_64;
+ memory_object_name_t object = MACH_PORT_NULL;
+ kern_return_t kr = KERN_SUCCESS;
+
+ kr = vm_region_64(mach_task_self(),
+ &address,
+ &vmsize,
+ VM_REGION_BASIC_INFO_64,
+ (vm_region_info_t) &info,
+ &info_cnt,
+ &object);
+ return (kr == KERN_SUCCESS) && !(info.protection & VM_PROT_WRITE);
+}
+
/*
* Non-MT-safe version
*/
{
char *fmt; /* format string */
int ch; /* character from fmt */
- int n, n2; /* handy integer (short term usage) */
+ ssize_t n, n2; /* handy integer (short term usage) */
char *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */
- int ret; /* return value accumulator */
- int width; /* width from format (%8d), or 0 */
- int prec; /* precision from format; <0 for N/A */
+ ssize_t ret; /* return value accumulator */
+ ssize_t width; /* width from format (%8d), or 0 */
+ ssize_t prec; /* precision from format; <0 for N/A */
char sign; /* sign prefix (' ', '+', '-', or \0) */
struct grouping_state gs; /* thousands' grouping info */
+#ifndef ALLOW_DYNAMIC_PERCENT_N
+ bool static_format_checked = false;
+#endif // ALLOW_DYNAMIC_PERCENT_N
+
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int base; /* base for [diouxX] conversion */
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
- int realsz; /* field size expanded by dprec, sign, etc */
- int size; /* size of converted field or string */
- int prsize; /* max size of printed field */
+ ssize_t realsz; /* field size expanded by dprec, sign, etc */
+ ssize_t size; /* size of converted field or string */
+ ssize_t prsize; /* max size of printed field */
const char *xdigs; /* digits for %[xX] conversion */
struct io_state io; /* I/O buffering state */
char buf[BUF]; /* buffer with space for digits of uintmax_t */
for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
/* void */;
if ((n = fmt - cp) != 0) {
- if ((unsigned)ret + n > INT_MAX) {
+ if (ret + n >= INT_MAX) {
ret = EOF;
+ errno = EOVERFLOW;
goto error;
}
PRINT(cp, n);
void *ptr = GETARG(void *);
if (ptr == NULL)
continue;
- else if (flags & LLONGINT)
+
+#ifndef ALLOW_DYNAMIC_PERCENT_N
+ if (!static_format_checked) {
+ static_format_checked = __printf_is_memory_read_only((void*)fmt0, strlen(fmt0));
+ }
+ if (!static_format_checked) {
+ os_crash("%n used in a non-immutable format string");
+ }
+#endif // ALLOW_DYNAMIC_PERCENT_N
+
+ if (flags & LLONGINT)
*(long long *)ptr = ret;
else if (flags & SIZET)
*(ssize_t *)ptr = (ssize_t)ret;
}
} else if ((cp = GETARG(char *)) == NULL)
cp = "(null)";
- size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
+ {
+ size_t cp_len = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
+ if (cp_len < INT_MAX) {
+ size = cp_len;
+ } else {
+ ret = EOF;
+ goto error;
+ }
+ }
sign = '\0';
break;
case 'U':
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
- LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
+ LIBC_ABORT("size (%zd) > BUF (%d)", size, BUF);
if ((flags & GROUPING) && size != 0)
size += grouping_init(&gs, size, loc);
break;
realsz += 2;
prsize = width > realsz ? width : realsz;
- if ((unsigned)ret + prsize > INT_MAX) {
+ if (ret + prsize >= INT_MAX) {
ret = EOF;
+ errno = EOVERFLOW;
goto error;
}
ret = EOF;
if ((argtable != NULL) && (argtable != statargtable))
free (argtable);
- return (ret);
+ return (ret < 0 || ret >= INT_MAX) ? -1 : (int)ret;
/* NOTREACHED */
}
#include <errno.h>
#include "un-namespace.h"
+#include <os/assumes.h>
+#include <mach-o/dyld_priv.h>
+
#include "libc_private.h"
#include "local.h"
#include "fvwrite.h"
return vfwprintf_l(fp, __current_locale(), fmt0, ap);
}
+// Defined in vfprintf.c
+bool __printf_is_memory_read_only(void *addr, size_t size);
+
/*
* The size of the buffer we use as scratch space for integer
* conversions, among other things. We need enough space to
{
wchar_t *fmt; /* format string */
wchar_t ch; /* character from fmt */
- int n, n2; /* handy integer (short term usage) */
+ ssize_t n, n2; /* handy integer (short term usage) */
wchar_t *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */
- int ret; /* return value accumulator */
- int width; /* width from format (%8d), or 0 */
- int prec; /* precision from format; <0 for N/A */
+ ssize_t ret; /* return value accumulator */
+ ssize_t width; /* width from format (%8d), or 0 */
+ ssize_t prec; /* precision from format; <0 for N/A */
wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
struct grouping_state gs; /* thousands' grouping info */
+
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
int base; /* base for [diouxX] conversion */
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
- int realsz; /* field size expanded by dprec, sign, etc */
- int size; /* size of converted field or string */
- int prsize; /* max size of printed field */
+ ssize_t realsz; /* field size expanded by dprec, sign, etc */
+ ssize_t size; /* size of converted field or string */
+ ssize_t prsize; /* max size of printed field */
const char *xdigs; /* digits for [xX] conversion */
struct io_state io; /* I/O buffering state */
wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */
for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
/* void */;
if ((n = fmt - cp) != 0) {
- if ((unsigned)ret + n > INT_MAX) {
+ if (ret + n > INT_MAX) {
ret = EOF;
+ errno = EOVERFLOW;
goto error;
}
PRINT(cp, n);
void *ptr = GETARG(void *);
if (ptr == NULL)
continue;
- else if (flags & LLONGINT)
+
+ if (flags & LLONGINT)
*(long long *)ptr = ret;
else if (flags & SIZET)
*(ssize_t *)ptr = (ssize_t)ret;
size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp);
#else
size = wcslen(cp);
+ if (size >= INT_MAX) {
+ ret = EOF;
+ errno = EOVERFLOW;
+ goto error;
+ }
if(prec >= 0 && prec < size)
size = prec;
#endif
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
- LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
+ LIBC_ABORT("size (%zd) > BUF (%d)", size, BUF);
if ((flags & GROUPING) && size != 0)
size += grouping_init(&gs, size, loc);
break;
realsz += 2;
prsize = width > realsz ? width : realsz;
- if ((unsigned)ret + prsize > INT_MAX) {
+ if (ret + prsize > INT_MAX) {
ret = EOF;
+ errno = EOVERFLOW;
goto error;
}
ret = EOF;
if ((argtable != NULL) && (argtable != statargtable))
free (argtable);
- return (ret);
+ return (ret < 0 || ret >= INT_MAX) ? -1 : (int)ret;
/* NOTREACHED */
}
return (-1);
}
*f._p = '\0';
- mbp = f._bf._base;
+ mbp = (char*)f._bf._base;
/*
* XXX Undo the conversion from wide characters to multibyte that
* fputwc() did in __vfwprintf().
#include <namespace.h>
#include "xlocale_private.h"
#include <stdio.h>
+#include <string.h>
#include <wchar.h>
#include <assert.h>
#include <locale.h>
const union arg *argp;
char buf[BUF];
char *p, *pe;
- char ns, l;
- int rdx, sign, zext, ngrp;
+ char ns;
+ int rdx, sign, zext, ngrp, l;
const char *nalt, *digit;
const char *thousands_sep; /* locale specific thousands separator */
int thousands_sep_len; /* locale specific thousands separator length */
.\" 2. Redistributions in binary form must 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.
.\"
.\" SUCH DAMAGE.
.\"
.\" @(#)atexit.3 8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/stdlib/atexit.3,v 1.11 2007/01/09 00:28:09 imp Exp $
+.\" $FreeBSD$
.\"
-.Dd May 20, 2008
+.Dd September 6, 2002
.Dt ATEXIT 3
.Os
.Sh NAME
.Sh SYNOPSIS
.In stdlib.h
.Ft int
-.Fn atexit "void (*func)(void)"
+.Fn atexit "void (*function)(void)"
#ifdef UNIFDEF_BLOCKS
.Ft int
-.Fn atexit_b "void (^block)(void)"
+.Fn atexit_b "void (^function)(void)"
#endif
.Sh DESCRIPTION
The
.Fn atexit
function
-registers the function
-.Fa func
+registers the given
+.Fa function
to be called at program exit, whether via
.Xr exit 3
or via return from the program's
.Fn main .
Functions so registered are called in reverse order;
no arguments are passed.
+.Pp
+If the provided
+.Fa function
+is located in a library that has been dynamically loaded (e.g. by
+.Fn dlopen ) Ns ,
+it will be called when the library is unloaded (due to a call
+to
+.Fn dlclose )
+or at program exit.
#ifdef UNIFDEF_BLOCKS
.Pp
The
.Ed
#endif
.Pp
-These callbacks must not call
+These functions must not call
.Fn exit ;
if it should be necessary to terminate the process while in such a
function, the
.Xr _exit 2
function should be used.
-(Alternatively, the callbacks may cause abnormal
+(Alternatively, the function may cause abnormal
process termination, for example by calling
.Xr abort 3 . )
.Pp
-At least 32 callbacks can always be registered;
-more are allowed as long as sufficient memory can be allocated.
+At least 32 functions can always be registered,
+and more are allowed as long as sufficient memory can be allocated.
.\" XXX {ATEXIT_MAX} is not implemented yet
.Sh RETURN VALUES
#ifdef UNIFDEF_BLOCKS
void
exit(int status)
{
+#if !TARGET_IPHONE_SIMULATOR && (__i386__ || __x86_64__)
+ _tlv_exit(); // C++11 requires thread_local objects to be destroyed before global objects
+#endif
+ __cxa_finalize(NULL);
+ if (__cleanup)
+ (*__cleanup)();
+ __exit(status);
+}
__private_extern__ void
__environ_lock(void)
{
-#if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
- os_unfair_lock_lock_with_options_4Libc(
+ os_unfair_lock_lock_with_options(
&__environ_lock_obj, OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION);
-#else // TARGET_OS_IOS && !TARGET_OS_SIMULATOR
- os_unfair_lock_lock(&__environ_lock_obj);
-#endif // TARGET_OS_IOS && !TARGET_OS_SIMULATOR
}
__private_extern__ void
__environ_unlock(void)
{
-#if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
- os_unfair_lock_unlock_4Libc(&__environ_lock_obj);
-#else // TARGET_OS_IOS && !TARGET_OS_SIMULATOR
os_unfair_lock_unlock(&__environ_lock_obj);
-#endif // TARGET_OS_IOS && !TARGET_OS_SIMULATOR
}
__private_extern__ void
__environ_lock_fork_child(void)
#include <libkern/OSAtomic.h>
#include <sys/mman.h>
#include <errno.h>
+#include <os/lock.h>
#define __APPLE_API_PRIVATE
#include <machine/cpu_capabilities.h>
size_t turnoff;
dispatch_queue_t queue;
dispatch_group_t group;
- OSSpinLock sharedlock;
+ os_unfair_lock sharedlock;
};
static union args *
{
union args *args;
- OSSpinLockLock(&shared->sharedlock);
+ os_unfair_lock_lock(&shared->sharedlock);
if(!shared->freelist) {
struct page *page;
union args *prev;
}
args = shared->freelist;
shared->freelist = args->next;
- OSSpinLockUnlock(&shared->sharedlock);
+ os_unfair_lock_unlock(&shared->sharedlock);
return args;
}
static void
returnargs(struct shared *shared, union args *args)
{
- OSSpinLockLock(&shared->sharedlock);
+ os_unfair_lock_lock(&shared->sharedlock);
args->next = shared->freelist;
shared->freelist = args;
- OSSpinLockUnlock(&shared->sharedlock);
+ os_unfair_lock_unlock(&shared->sharedlock);
}
/*
union args *args;
bzero(&shared, sizeof(shared));
- shared.sharedlock = OS_SPINLOCK_INIT;
+ shared.sharedlock = OS_UNFAIR_LOCK_INIT;
if ((args = getargs(&shared)) != NULL) {
struct page *p, *pp;
#ifdef I_AM_PSORT_R
#include <libkern/OSAtomic.h>
#include <sys/mman.h>
#include <errno.h>
+#include <os/lock.h>
#define __APPLE_API_PRIVATE
#include <machine/cpu_capabilities.h>
size_t turnoff;
dispatch_queue_t queue;
dispatch_group_t group;
- OSSpinLock sharedlock;
+ os_unfair_lock sharedlock;
};
static union args *
{
union args *args;
- OSSpinLockLock(&shared->sharedlock);
+ os_unfair_lock_lock(&shared->sharedlock);
if(!shared->freelist) {
struct page *page;
union args *prev;
}
args = shared->freelist;
shared->freelist = args->next;
- OSSpinLockUnlock(&shared->sharedlock);
+ os_unfair_lock_unlock(&shared->sharedlock);
return args;
}
static void
returnargs(struct shared *shared, union args *args)
{
- OSSpinLockLock(&shared->sharedlock);
+ os_unfair_lock_lock(&shared->sharedlock);
args->next = shared->freelist;
shared->freelist = args;
- OSSpinLockUnlock(&shared->sharedlock);
+ os_unfair_lock_unlock(&shared->sharedlock);
}
/*
union args *args;
bzero(&shared, sizeof(shared));
- shared.sharedlock = OS_SPINLOCK_INIT;
+ shared.sharedlock = OS_UNFAIR_LOCK_INIT;
if ((args = getargs(&shared)) != NULL) {
struct page *p, *pp;
#ifdef I_AM_PSORT_R
#include <libkern/OSAtomic.h>
#include <sys/mman.h>
#include <errno.h>
+#include <os/lock.h>
#define __APPLE_API_PRIVATE
#include <machine/cpu_capabilities.h>
size_t turnoff;
dispatch_queue_t queue;
dispatch_group_t group;
- OSSpinLock sharedlock;
+ os_unfair_lock sharedlock;
};
static union args *
{
union args *args;
- OSSpinLockLock(&shared->sharedlock);
+ os_unfair_lock_lock(&shared->sharedlock);
if(!shared->freelist) {
struct page *page;
union args *prev;
}
args = shared->freelist;
shared->freelist = args->next;
- OSSpinLockUnlock(&shared->sharedlock);
+ os_unfair_lock_unlock(&shared->sharedlock);
return args;
}
static void
returnargs(struct shared *shared, union args *args)
{
- OSSpinLockLock(&shared->sharedlock);
+ os_unfair_lock_lock(&shared->sharedlock);
args->next = shared->freelist;
shared->freelist = args;
- OSSpinLockUnlock(&shared->sharedlock);
+ os_unfair_lock_unlock(&shared->sharedlock);
}
/*
union args *args;
bzero(&shared, sizeof(shared));
- shared.sharedlock = OS_SPINLOCK_INIT;
+ shared.sharedlock = OS_UNFAIR_LOCK_INIT;
if ((args = getargs(&shared)) != NULL) {
struct page *p, *pp;
#ifdef I_AM_PSORT_R
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 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.
*
static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.15 2008/01/14 09:21:34 das Exp $");
+__FBSDID("$FreeBSD$");
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#else
typedef int cmp_t(const void *, const void *);
#endif
-#ifdef I_AM_QSORT_B
-static inline char *med3(char *, char *, char *, cmp_t ^, void *) __attribute__((always_inline));
-#else
-static inline char *med3(char *, char *, char *, cmp_t *, void *) __attribute__((always_inline));
-#endif
-static inline void swapfunc(char *, char *, int, int) __attribute__((always_inline));
+static inline char *med3(char *, char *, char *, cmp_t *, void *);
+static inline void swapfunc(char *, char *, size_t, int, int);
-#define min(a, b) (a) < (b) ? a : b
+#define MIN(a, b) ((a) < (b) ? a : b)
/*
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
*/
-#define swapcode(TYPE, parmi, parmj, n) { \
- long i = (n) / sizeof (TYPE); \
- TYPE *pi = (TYPE *) (parmi); \
- TYPE *pj = (TYPE *) (parmj); \
+#define swapcode(TYPE, parmi, parmj, n) { \
+ size_t i = (n) / sizeof (TYPE); \
+ TYPE *pi = (TYPE *) (parmi); \
+ TYPE *pj = (TYPE *) (parmj); \
do { \
TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
- } while (--i > 0); \
+ } while (--i > 0); \
}
-#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
- es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+#define SWAPINIT(TYPE, a, es) swaptype_ ## TYPE = \
+ ((char *)a - (char *)0) % sizeof(TYPE) || \
+ es % sizeof(TYPE) ? 2 : es == sizeof(TYPE) ? 0 : 1;
static inline void
-swapfunc(a, b, n, swaptype)
- char *a, *b;
- int n, swaptype;
+swapfunc(char *a, char *b, size_t n, int swaptype_long, int swaptype_int)
{
- if(swaptype <= 1)
+ if (swaptype_long <= 1)
swapcode(long, a, b, n)
+ else if (swaptype_int <= 1)
+ swapcode(int, a, b, n)
else
swapcode(char, a, b, n)
}
-#define swap(a, b) \
- if (swaptype == 0) { \
+#define swap(a, b) \
+ if (swaptype_long == 0) { \
long t = *(long *)(a); \
*(long *)(a) = *(long *)(b); \
*(long *)(b) = t; \
+ } else if (swaptype_int == 0) { \
+ int t = *(int *)(a); \
+ *(int *)(a) = *(int *)(b); \
+ *(int *)(b) = t; \
} else \
- swapfunc(a, b, es, swaptype)
+ swapfunc(a, b, es, swaptype_long, swaptype_int)
-#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+#define vecswap(a, b, n) \
+ if ((n) > 0) swapfunc(a, b, n, swaptype_long, swaptype_int)
#ifdef I_AM_QSORT_R
#define CMP(t, x, y) (cmp((t), (x), (y)))
#define CMP(t, x, y) (cmp((x), (y)))
#endif
+/*
+ * Find the median of 3 elements
+ */
static inline char *
-med3(char *a, char *b, char *c,
-#ifdef I_AM_QSORT_B
-cmp_t ^cmp,
-#else
-cmp_t *cmp,
-#endif
-void *thunk
+med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
#ifndef I_AM_QSORT_R
__unused
#endif
{
return CMP(thunk, a, b) < 0 ?
(CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
- :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+ :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
}
#ifdef __LP64__
int __heapsort_r(void *, size_t, size_t, void *, int (*)(void *, const void *, const void *));
#endif
-static void
-_qsort(void *a, size_t n, size_t es,
+/*
+ * Simple insertion sort routine.
+ */
+static bool
+_isort(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp, int swap_limit, int swaptype_long, int swaptype_int)
+{
+ int swap_cnt = 0;
+ for (char *pm = (char *)a + es; pm < (char *)a + n * es; pm += es) {
+ for (char *pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es) {
+ swap(pl, pl - es);
+ if (swap_limit && ++swap_cnt > swap_limit) return false;
+ }
+ }
+ return true;
+}
+
#ifdef I_AM_QSORT_R
-void *thunk,
-#else
-#define thunk NULL
-#endif
-#ifdef I_AM_QSORT_B
-cmp_t ^cmp,
+static void
+_qsort(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp, int depth_limit)
#else
-cmp_t *cmp,
+#define thunk NULL
+static void
+_qsort(void *a, size_t n, size_t es, cmp_t *cmp, int depth_limit)
#endif
-int depth_limit)
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
- size_t d, r;
+ size_t d1, d2;
int cmp_result;
- int swaptype, swap_cnt;
+ int swaptype_long, swaptype_int, swap_cnt;
loop:
+ SWAPINIT(long, a, es);
+ SWAPINIT(int, a, es);
+ swap_cnt = 0;
+
if (depth_limit-- <= 0) {
-#ifdef I_AM_QSORT_B
- heapsort_b(a, n, es, cmp);
-#elif defined(I_AM_QSORT_R)
+ /*
+ * We've hit our recursion limit, switch to heapsort
+ */
+#ifdef I_AM_QSORT_R
__heapsort_r(a, n, es, thunk, cmp);
#else
heapsort(a, n, es, cmp);
#endif
return;
}
- SWAPINIT(a, es);
- swap_cnt = 0;
- if (n < 7) {
- for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
- for (pl = pm;
- pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
- pl -= es)
- swap(pl, pl - es);
+
+ if (n <= 7) {
+ /*
+ * For sufficiently small inputs, we'll just insertion sort.
+ *
+ * Pass 0 as swap limit, since this must complete.
+ */
+ _isort(a, n, es, thunk, cmp, 0, swaptype_long, swaptype_int);
return;
}
+
+ /*
+ * Compute the pseudomedian. Small arrays use 3 samples, large ones use 9.
+ */
+ pl = a;
pm = (char *)a + (n / 2) * es;
- if (n > 7) {
- pl = a;
- pn = (char *)a + (n - 1) * es;
- if (n > 40) {
- d = (n / 8) * es;
- pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
- pm = med3(pm - d, pm, pm + d, cmp, thunk);
- pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
- }
- pm = med3(pl, pm, pn, cmp, thunk);
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ size_t d = (n / 8) * es;
+
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+ pm = med3(pm - d, pm, pm + d, cmp, thunk);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
}
+ pm = med3(pl, pm, pn, cmp, thunk);
+
+ /*
+ * Pull the median to the front, starting us with:
+ *
+ * +-+-------------+
+ * |=| ? |
+ * +-+-------------+
+ * a pa,pb pc,pd
+ */
swap(a, pm);
pa = pb = (char *)a + es;
-
pc = pd = (char *)a + (n - 1) * es;
+
for (;;) {
+ /*
+ * - Move b forward while it's less than the median
+ * - Move c backwards while it's greater than the median
+ * - When equal to the median, swap to the outside
+ */
while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
if (cmp_result == 0) {
swap_cnt = 1;
pc -= es;
}
+ /*
+ * Now we've got:
+ *
+ * +---+-----+-----+---+
+ * | = | < | > | = |
+ * +---+-----+-----+---+
+ * a pa pc,pb pd pn
+ *
+ * So swap the '=' into the middle
+ */
+
pn = (char *)a + n * es;
- r = min(pa - (char *)a, pb - pa);
- vecswap(a, pb - r, r);
- r = min(pd - pc, pn - pd - es);
- vecswap(pb, pn - r, r);
+ d1 = MIN(pa - (char *)a, pb - pa);
+ vecswap(a, pb - d1, d1);
+ d1 = MIN(pd - pc, pn - pd - es);
+ vecswap(pb, pn - d1, d1);
+
+ /*
+ * +-----+---+---+-----+
+ * | < | = | > |
+ * +-----+---+---+-----+
+ * a pn
+ */
if (swap_cnt == 0) { /* Switch to insertion sort */
- r = 1 + n / 4; /* n >= 7, so r >= 2 */
- for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
- for (pl = pm;
- pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
- pl -= es) {
- swap(pl, pl - es);
- if (++swap_cnt > r) goto nevermind;
- }
+ int r = 1 + n / 4; /* n > 7, so r >= 2 */
+ if (!_isort(a, n, es, thunk, cmp, r, swaptype_long, swaptype_int)) {
+ goto nevermind;
+ }
return;
}
-
nevermind:
- if ((r = pb - pa) > es)
+
+ d1 = pb - pa;
+ d2 = pd - pc;
+ if (d1 <= d2) {
+ /* Recurse on left partition, then iterate on right partition */
+ if (d1 > es) {
+#ifdef I_AM_QSORT_R
+ _qsort(a, d1 / es, es, thunk, cmp, depth_limit);
+#else
+ _qsort(a, d1 / es, es, cmp, depth_limit);
+#endif
+ }
+ if (d2 > es) {
+ /* Iterate rather than recurse to save stack space */
+ /* qsort(pn - d2, d2 / es, es, cmp); */
+ a = pn - d2;
+ n = d2 / es;
+ goto loop;
+ }
+ } else {
+ /* Recurse on right partition, then iterate on left partition */
+ if (d2 > es) {
#ifdef I_AM_QSORT_R
- _qsort(a, r / es, es, thunk, cmp, depth_limit);
+ _qsort(pn - d2, d2 / es, es, thunk, cmp, depth_limit);
#else
- _qsort(a, r / es, es, cmp, depth_limit);
+ _qsort(pn - d2, d2 / es, es, cmp, depth_limit);
#endif
- if ((r = pd - pc) > es) {
- /* Iterate rather than recurse to save stack space */
- a = pn - r;
- n = r / es;
- goto loop;
+ }
+ if (d1 > es) {
+ /* Iterate rather than recurse to save stack space */
+ /* qsort(a, d1 / es, es, cmp); */
+ n = d1 / es;
+ goto loop;
+ }
}
-/* qsort(pn - r, r / es, es, cmp);*/
}
void
#ifdef I_AM_QSORT_R
qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
-#elif defined(I_AM_QSORT_B)
-qsort_b(void *a, size_t n, size_t es, cmp_t ^cmp)
#else
qsort(void *a, size_t n, size_t es, cmp_t *cmp)
#endif
If
.Fa resolved_name
was non-NULL, it will
-contains the pathname which caused the problem.
+contain the pathname which caused the problem.
.Sh VARIANTS
Defining
.Dv _DARWIN_C_SOURCE
0,
};
#else /* BUILDING_VARIANT */
-__private_extern__ const struct attrlist _rp_alist;
+extern const struct attrlist _rp_alist;
#endif /* BUILDING_VARIANT */
extern char * __private_getcwd(char *, size_t, int);
{
struct attrs attrs;
struct stat sb;
- char *p, *q, *s;
- size_t left_len, resolved_len, save_resolved_len;
+ char *p, *q;
+ size_t left_len, resolved_len, save_resolved_len, next_token_len;
unsigned symlinks;
- int serrno, slen, useattrs, islink;
+ int serrno, useattrs, islink;
+ ssize_t slen;
char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
dev_t dev, lastdev;
struct statfs sfs;
* and its length.
*/
p = strchr(left, '/');
- s = p ? p : left + left_len;
- if (s - left >= sizeof(next_token)) {
- errno = ENAMETOOLONG;
- goto error_return;
+ next_token_len = p ? p - left : left_len;
+ memcpy(next_token, left, next_token_len);
+ next_token[next_token_len] = '\0';
+
+ if (p != NULL) {
+ left_len -= next_token_len + 1;
+ memmove(left, p + 1, left_len + 1);
+ } else {
+ left[0] = '\0';
+ left_len = 0;
}
- memcpy(next_token, left, s - left);
- next_token[s - left] = '\0';
- left_len -= s - left;
- if (p != NULL)
- memmove(left, s + 1, left_len + 1);
+
if (resolved[resolved_len - 1] != '/') {
if (resolved_len + 1 >= PATH_MAX) {
errno = ENAMETOOLONG;
resolved[resolved_len++] = '/';
resolved[resolved_len] = '\0';
}
- if (next_token[0] == '\0')
+ if (next_token[0] == '\0') {
+ /* Handle consequential slashes. */
continue;
- else if (strcmp(next_token, ".") == 0)
+ } else if (strcmp(next_token, ".") == 0) {
continue;
- else if (strcmp(next_token, "..") == 0) {
+ } else if (strcmp(next_token, "..") == 0) {
/*
* Strip the last path component except when we have
* single "/"
errno = ELOOP;
goto error_return;
}
- slen = readlink(resolved, symlink, sizeof(symlink) - 1);
- if (slen < 0) {
+ slen = readlink(resolved, symlink, sizeof(symlink));
+ if (slen <= 0 || slen >= sizeof(symlink)) {
+ if (slen < 0)
+ ; /* keep errno from readlink(2) call */
+ else if (slen == 0)
+ errno = ENOENT;
+ else
+ errno = ENAMETOOLONG;
goto error_return;
}
symlink[slen] = '\0';
resolved[1] = 0;
resolved_len = 1;
lastdev = rootdev;
- } else if (resolved_len > 1) {
+ } else {
/* Strip the last path component. */
- resolved[resolved_len - 1] = '\0';
q = strrchr(resolved, '/') + 1;
*q = '\0';
resolved_len = q - resolved;
symlink[slen + 1] = 0;
}
left_len = strlcat(symlink, left, sizeof(symlink));
- if (left_len >= sizeof(left)) {
+ if (left_len >= sizeof(symlink)) {
errno = ENAMETOOLONG;
goto error_return;
}
#include <fcntl.h>
struct owned_ptr;
-__private_extern__ char *__findenv_locked(const char *, int *, char **);
-__private_extern__ int __setenv_locked(const char *, const char *, int, int, char ***, struct owned_ptr *);
-__private_extern__ void __unsetenv_locked(const char *, char **, struct owned_ptr *);
+extern char *__findenv_locked(const char *, int *, char **);
+extern int __setenv_locked(const char *, const char *, int, int, char ***, struct owned_ptr *);
+extern void __unsetenv_locked(const char *, char **, struct owned_ptr *);
-__private_extern__ void __environ_lock(void);
-__private_extern__ void __environ_unlock(void);
+extern void __environ_lock(void);
+extern void __environ_unlock(void);
-__private_extern__ struct owned_ptr *__env_owned;
-__private_extern__ int __init__env_owned_locked(int);
+extern struct owned_ptr *__env_owned;
+extern int __init__env_owned_locked(int);
/*
* _cthread_init_routine used to be called from crt1.o to initialize threads.
#if __DARWIN_UNIX03
#include <pthread.h>
+#if !(TARGET_OS_IPHONE && (TARGET_OS_SIMULATOR || !TARGET_OS_IOS))
static pthread_mutex_t __systemfn_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
extern int __unix_conforming;
#endif /* __DARWIN_UNIX03 */
+++ /dev/null
-/*
- * This file is in the public domain. Originally written by Garrett
- * A. Wollman.
- *
- * $FreeBSD: src/lib/libc/stdlib/qsort_r.c,v 1.1 2002/09/10 02:04:49 wollman Exp $
- */
-#define I_AM_QSORT_B
-#include "FreeBSD/qsort.c"
--- /dev/null
+#include <stdlib.h>
+#include <Block_private.h>
+
+typedef int cmp_t(const void *, const void *);
+
+void
+qsort_b(void *base, size_t nel, size_t width, cmp_t ^cmp_b)
+{
+ void *cmp_f = ((struct Block_layout *)cmp_b)->invoke;
+ qsort_r(base, nel, width, cmp_b, (void*)cmp_f);
+}
.Nm localtime ,
.Nm localtime_r ,
.Nm mktime ,
-.Nm timegm
+.Nm timegm ,
+.Nm timelocal
.Nd transform binary date and time values
.Sh LIBRARY
.Lb libc
.Fn mktime "struct tm *timeptr"
.Ft time_t
.Fn timegm "struct tm *timeptr"
+.Ft time_t
+.Fn timelocal "struct tm *timeptr"
.Sh DESCRIPTION
The functions
.Fn ctime ,
as representing Universal Coordinated Time
.Pq Tn UTC .
.Pp
+The
+.Fn timelocal
+function is like
+.Fn timegm ,
+but uses the current timezone setting.
+This makes
+.Fn timelocal
+equivalent to
+.Fn mktime .
+.Pp
The original values of the
.Fa tm_wday
and
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
+#if 0
static char rcsid[] = "$FreeBSD: /repoman/r/ncvs/src/lib/libcompat/4.1/ftime.c,v 1.5 1999/08/28 00:04:12 peter Exp $";
#endif /* not lint */
/*
** 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.14";
#endif /* !defined NOID */
#endif /* !defined lint */
-__FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.43 2008/04/01 06:56:11 davidxu Exp $");
+__FBSDID("$FreeBSD: head/contrib/tzcode/stdtime/localtime.c 289027 2015-10-08 11:42:15Z rodrigc $");
/*
-** 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*/
#include "namespace.h"
#include <sys/types.h>
#include <sys/stat.h>
+#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
-#include <errno.h>
#ifdef NOTIFY_TZ
//#define NOTIFY_TZ_DEBUG
//#define NOTIFY_TZ_DEBUG_FILE "/var/log/localtime.debug"
#include "un-namespace.h"
#include "tzfile.h"
+#include "float.h" /* for FLT_MAX and DBL_MAX */
+
+#ifndef TZ_ABBR_MAX_LEN
+/* UNIX03 requires this to be the same as sysconf(_SC_TZNAME_MAX) */
+#define TZ_ABBR_MAX_LEN 255
+#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"
** 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 const char wildabbr[] = "WILDABBR";
+__used static const char wildabbr[] = WILDABBR;
/*
* In June 2004 it was decided UTC was a more appropriate default time
* zone than GMT.
*/
-static const char gmt[] = "UTC";
+__used static const char gmt[] = "UTC";
/*
** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
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];
#if !BUILDING_VARIANT
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, char **name, size_t *len);
+static const char * getqzname(const char * strp, const int delim)
+ ATTRIBUTE_PURE;
static const char * getnum(const char * strp, int * nump, int min,
int max);
static const char * getsecs(const char * strp, long * secsp);
struct tm * tmp);
#endif /* __LP64__ */
static int increment_overflow(int * number, int delta);
+static int leaps_thru_end_of(int y) ATTRIBUTE_PURE;
+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);
#ifdef NOTIFY_TZ
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);
+ const struct rule * rulep, long offset)
+ ATTRIBUTE_PURE;
+static int typesequiv(const struct state * sp, int a, int b);
#ifdef NOTIFY_TZ
-static int tzload(const char * name, struct state * sp, char *path);
+static int tzload(const char * name, struct state * sp, char *path, int doextend);
#else /* ! NOTIFY_TZ */
-static int tzload(const char * name, struct state * sp);
+static int tzload(const char * name, struct state * sp, int doextend);
#endif /* NOTIFY_TZ */
static int tzparse(const char * name, struct state * sp,
int lastditch);
#define gmt_is_set (gmt_notify.is_set)
#else /* ! NOTIFY_TZ */
static int lcl_is_set;
-static int gmt_is_set;
#endif /* NOTIFY_TZ */
+static pthread_once_t gmt_once = PTHREAD_ONCE_INIT;
__private_extern__ pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
-static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_once_t gmtime_once = PTHREAD_ONCE_INIT;
+static pthread_key_t gmtime_key;
+static int gmtime_key_error;
+static pthread_once_t localtime_once = PTHREAD_ONCE_INIT;
+static pthread_key_t localtime_key;
+static int localtime_key_error;
char * tzname[2] = {
(char *)wildabbr,
** 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;
#endif /* NOTIFY_TZ */
static long
-detzcode(codep)
-const char * const codep;
+detzcode(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(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)
{
}
#endif /* defined(ALTZONE) || defined(USG_COMPAT) */
}
+ /*
+ ** 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';
+ }
}
#ifdef NOTIFY_TZ
}
#endif /* NOTIFY_TZ */
+static int
+differ_by_repeat(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
#ifdef NOTIFY_TZ
-tzload(name, sp, path)
+tzload(name, sp, path, doextend)
#else /* ! NOTIFY_TZ */
-tzload(name, sp)
+tzload(name, sp, doextend)
#endif /* NOTIFY_TZ */
const char * name;
struct state * const sp;
#ifdef NOTIFY_TZ
char * path; /* copy full path if non-NULL */
#endif /* NOTIFY_TZ */
+register const int doextend;
{
const char * p;
int i;
int fid;
+ int stored;
+ int nread;
+ int res;
+ union {
+ struct tzhead tzhead;
+ char buf[2 * sizeof(struct tzhead) +
+ 2 * sizeof *sp +
+ 4 * TZ_MAX_TIMES];
+ } *u;
+
+ u = NULL;
+ res = -1;
+ sp->goback = sp->goahead = FALSE;
#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("tzload: name=%s\n", name);
** to hold the longest file name string that the implementation
** guarantees can be opened."
*/
- char fullname[FILENAME_MAX + 1];
+ char *fullname;
+
+ fullname = malloc(FILENAME_MAX + 1);
+ if (fullname == NULL)
+ goto out;
if (name[0] == ':')
++name;
doaccess = name[0] == '/';
if (!doaccess) {
- if ((p = TZDIR) == NULL)
+ if ((p = TZDIR) == NULL) {
+ free(fullname);
return -1;
- if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname)
+ }
+ if (strlen(p) + 1 + strlen(name) >= FILENAME_MAX) {
+ free(fullname);
return -1;
+ }
(void) strcpy(fullname, p);
(void) strcat(fullname, "/");
(void) strcat(fullname, name);
strcpy(path, name);
}
#endif /* NOTIFY_TZ */
- if (doaccess && access(name, R_OK) != 0)
+ if (doaccess && access(name, R_OK) != 0) {
+ free(fullname);
return -1;
- if ((fid = _open(name, OPEN_MODE)) == -1)
+ }
+ if ((fid = _open(name, OPEN_MODE)) == -1) {
+ free(fullname);
return -1;
+ }
if ((_fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
+ free(fullname);
_close(fid);
return -1;
}
+ free(fullname);
}
- {
- struct tzhead * tzhp;
- union {
- struct tzhead tzhead;
- char buf[sizeof *sp + sizeof *tzhp];
- } u;
+ u = malloc(sizeof(*u));
+ if (u == NULL)
+ goto out;
+#ifdef NOTIFY_TZ_DEBUG
+ NOTIFY_TZ_PRINTF("tzload: reading %s\n", name);
+#endif /* NOTIFY_TZ_DEBUG */
+ nread = _read(fid, u->buf, sizeof u->buf);
+ if (_close(fid) < 0 || nread <= 0)
+ goto out;
+ for (stored = 4; stored <= 8; stored *= 2) {
int ttisstdcnt;
int ttisgmtcnt;
-#ifdef NOTIFY_TZ_DEBUG
- NOTIFY_TZ_PRINTF("tzload: reading %s\n", name);
-#endif /* NOTIFY_TZ_DEBUG */
- 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);
- sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
- sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
- sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
- p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
+ ttisstdcnt = (int) detzcode(u->tzhead.tzh_ttisstdcnt);
+ ttisgmtcnt = (int) detzcode(u->tzhead.tzh_ttisgmtcnt);
+ sp->leapcnt = (int) detzcode(u->tzhead.tzh_leapcnt);
+ sp->timecnt = (int) detzcode(u->tzhead.tzh_timecnt);
+ sp->typecnt = (int) detzcode(u->tzhead.tzh_typecnt);
+ sp->charcnt = (int) detzcode(u->tzhead.tzh_charcnt);
+ p = u->tzhead.tzh_charcnt + sizeof u->tzhead.tzh_charcnt;
if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
- return -1;
- if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
+ goto out;
+ 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;
+ goto out;
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++;
if (sp->types[i] >= sp->typecnt)
- return -1;
+ goto out;
}
for (i = 0; i < sp->typecnt; ++i) {
struct ttinfo * ttisp;
p += 4;
ttisp->tt_isdst = (unsigned char) *p++;
if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
- return -1;
+ goto out;
ttisp->tt_abbrind = (unsigned char) *p++;
if (ttisp->tt_abbrind < 0 ||
ttisp->tt_abbrind > sp->charcnt)
- return -1;
+ goto out;
}
for (i = 0; i < sp->charcnt; ++i)
sp->chars[i] = *p++;
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;
}
ttisp->tt_ttisstd = *p++;
if (ttisp->tt_ttisstd != TRUE &&
ttisp->tt_ttisstd != FALSE)
- return -1;
+ goto out;
}
}
for (i = 0; i < sp->typecnt; ++i) {
ttisp->tt_ttisgmt = *p++;
if (ttisp->tt_ttisgmt != TRUE &&
ttisp->tt_ttisgmt != FALSE)
- return -1;
+ goto out;
}
}
+ /*
+ ** 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;
}
- return 0;
+ 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;
+
+ ts = malloc(sizeof(*ts));
+ if (ts == NULL)
+ goto out;
+ 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];
+ }
+ free(ts);
+ }
+ 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;
+ }
+ }
+ res = 0;
+out:
+ free(u);
+ return (res);
+}
+
+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] = {
/*
** 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.
*/
return 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
*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;
/*
** 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.
*/
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.
*/
/*
** "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.
*/
stdoffset = 0;
} else {
name = getzname(name, (char **)&stdname, &stdlen);
- if (stdlen < 3)
- return -1;
if (*name == '\0')
return -1; /* was "stdoffset = 0;" */
else {
}
}
#ifdef NOTIFY_TZ
- load_result = tzload(TZDEFRULES, sp, NULL);
+ load_result = tzload(TZDEFRULES, sp, NULL, FALSE);
#else /* !NOTIFY_TZ */
- load_result = tzload(TZDEFRULES, sp);
+ load_result = tzload(TZDEFRULES, sp, FALSE);
#endif /* NOTIFY_TZ */
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
- dstname = name;
- name = getzname(name, (char **)&dstname, &dstlen);
- 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, (char **)&dstname, &dstlen);
+ }
if (*name != '\0' && *name != ',' && *name != ';') {
name = getoffset(name, &dstoffset);
if (name == NULL)
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;
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,
*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;
#endif /* NOTIFY_TZ */
{
#ifdef NOTIFY_TZ
- if (tzload(gmt, sp, path) != 0)
+ if (tzload(gmt, sp, path, TRUE) != 0)
#else /* ! NOTIFY_TZ */
- if (tzload(gmt, sp) != 0)
+ if (tzload(gmt, sp, TRUE) != 0)
#endif /* NOTIFY_TZ */
(void) tzparse(gmt, sp, TRUE);
}
#ifdef NOTIFY_TZ
notify_check_tz(&lcl_notify);
#else
- if (TZDEFAULT) {
- static struct timespec last_mtimespec = {0, 0};
- struct stat statbuf;
-
- if (lstat(TZDEFAULT, &statbuf) == 0) {
- if (statbuf.st_mtimespec.tv_sec > last_mtimespec.tv_sec ||
- (statbuf.st_mtimespec.tv_sec == last_mtimespec.tv_sec &&
- statbuf.st_mtimespec.tv_nsec > last_mtimespec.tv_nsec)) {
- /* Trigger resetting the local TZ */
- lcl_is_set = 0;
- }
- last_mtimespec = statbuf.st_mtimespec;
- }
- }
+ if (TZDEFAULT) {
+ static struct timespec last_mtimespec = {0, 0};
+ struct stat statbuf;
+
+ if (lstat(TZDEFAULT, &statbuf) == 0) {
+ if (statbuf.st_mtimespec.tv_sec > last_mtimespec.tv_sec ||
+ (statbuf.st_mtimespec.tv_sec == last_mtimespec.tv_sec &&
+ statbuf.st_mtimespec.tv_nsec > last_mtimespec.tv_nsec)) {
+ /* Trigger resetting the local TZ */
+ lcl_is_set = 0;
+ }
+ last_mtimespec = statbuf.st_mtimespec;
+ }
+ }
#endif /* NOTIFY_TZ */
if (!rdlocked)
_RWLOCK_RDLOCK(&lcl_rwlock);
#ifdef ALL_STATE
if (lclptr == NULL) {
- lclptr = (struct state *) malloc(sizeof *lclptr);
+ lclptr = calloc(1, sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
_RWLOCK_UNLOCK(&lcl_rwlock);
#ifdef NOTIFY_TZ
{
char fullname[FILENAME_MAX + 1];
- if (tzload((char *) NULL, lclptr, fullname) != 0)
+ if (tzload((char *) NULL, lclptr, fullname, TRUE) != 0)
/*
* If fullname is empty (an error occurred) then
* default to the UTC path
*/
gmtload(lclptr, *fullname ? NULL : fullname);
- notify_register_tz(fullname, &lcl_notify);
+ notify_register_tz(fullname, &lcl_notify);
}
#else /* ! NOTIFY_TZ */
- if (tzload((char *) NULL, lclptr) != 0)
+ if (tzload((char *) NULL, lclptr, TRUE) != 0)
gmtload(lclptr);
#endif /* NOTIFY_TZ */
settzname();
#ifdef ALL_STATE
if (lclptr == NULL) {
- lclptr = (struct state *) malloc(sizeof *lclptr);
+ lclptr = (struct state *) calloc(1, sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
_RWLOCK_UNLOCK(&lcl_rwlock);
#endif /* NOTIFY_TZ */
} else
#ifdef NOTIFY_TZ
- {
+ {
char fullname[FILENAME_MAX + 1];
/*
* parsedOK indicates whether tzparse() was called and
* notifications.
*/
int parsedOK = FALSE;
- if (tzload(name, lclptr, fullname) != 0)
+ if (tzload(name, lclptr, fullname, TRUE) != 0)
if (name[0] == ':' || !(parsedOK = tzparse(name, lclptr, FALSE) == 0))
/*
* If fullname is empty (an error occurred) then
* default to the UTC path
*/
(void) gmtload(lclptr, *fullname ? NULL : fullname);
- notify_register_tz(parsedOK ? NULL : fullname, &lcl_notify);
- }
+ notify_register_tz(parsedOK ? NULL : fullname, &lcl_notify);
+ }
#else /* ! NOTIFY_TZ */
- if (tzload(name, lclptr) != 0)
+ if (tzload(name, lclptr, TRUE) != 0)
if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
(void) gmtload(lclptr);
#endif /* NOTIFY_TZ */
/*
** 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.
#else /* !__LP64__ */
__private_extern__ void
#endif /* __LP64__ */
-localsub(timep, offset, tmp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
+localsub(const time_t *const timep, const long offset, struct tm *const tmp)
{
struct state * sp;
const struct ttinfo * ttisp;
int i;
- const time_t t = *timep;
+#ifdef __LP64__
+ struct tm * result;
+#endif /* __LP64__ */
+ const time_t t = *timep;
#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("localsub called\n");
#endif /* __LP64__ */
}
#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) {
+#ifdef __LP64__
+ return NULL;
+#else /* !__LP64__ */
+ return;
+#endif /* __LP64__ */
+ }
+ 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])
+#ifdef __LP64__
+ return NULL; /* "cannot happen" */
+ result = localsub(&newt, offset, tmp);
+ if (result == tmp) {
+#else /* !__LP64__ */
+ return;
+ localsub(&newt, offset, tmp);
+ {
+#endif /* __LP64__ */
+ 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)
+#ifdef __LP64__
+ return NULL;
+ }
+ return result;
+#else /* !__LP64__ */
+ return;
+ }
+ return;
+#endif /* __LP64__ */
+ }
if (sp->timecnt == 0 || t < sp->ats[0]) {
i = 0;
while (sp->ttis[i].tt_isdst)
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];
/*
** timesub(&t, 0L, sp, tmp);
*/
#ifdef __LP64__
- if (timesub(&t, ttisp->tt_gmtoff, sp, tmp) == NULL)
+ result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+ if (result == NULL)
return NULL;
#else /* !__LP64__ */
timesub(&t, ttisp->tt_gmtoff, sp, tmp);
tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
#endif /* defined TM_ZONE */
#ifdef __LP64__
- return tmp;
+ return result;
#endif /* __LP64__ */
}
+static void
+localtime_key_init(void)
+{
+
+ localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
+ localtime_key_error = pthread_key_init_np(localtime_key, free);
+}
+
struct tm *
-localtime(timep)
-const time_t * const timep;
+localtime(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;
if (__isthreaded != 0) {
- if (localtime_key == (pthread_key_t)-1) {
- _pthread_mutex_lock(&localtime_mutex);
- if (localtime_key == (pthread_key_t)-1) {
- localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
- if (pthread_key_init_np(localtime_key, free) < 0) {
- _pthread_mutex_unlock(&localtime_mutex);
- return(NULL);
- }
- }
- _pthread_mutex_unlock(&localtime_mutex);
+ _pthread_once(&localtime_once, localtime_key_init);
+ if (localtime_key_error != 0) {
+ errno = localtime_key_error;
+ return(NULL);
}
p_tm = _pthread_getspecific(localtime_key);
if (p_tm == NULL) {
*/
struct tm *
-localtime_r(const time_t * const __restrict timep, struct tm * __restrict tm)
+localtime_r(const time_t *const __restrict timep, struct tm * __restrict tmp)
{
_RWLOCK_RDLOCK(&lcl_rwlock);
tzset_basic(1);
#ifdef __LP64__
- tm = localsub(timep, 0L, tm);
+ tmp = localsub(timep, 0L, tmp);
#else /* !__LP64__ */
- localsub(timep, 0L, tm);
+ localsub(timep, 0L, tmp);
#endif /* __LP64__ */
_RWLOCK_UNLOCK(&lcl_rwlock);
- return tm;
+ return tmp;
+}
+
+static void
+gmt_init(void)
+{
+
+#ifdef ALL_STATE
+#ifdef NOTIFY_TZ
+ if (gmtptr == NULL)
+#endif /* NOTIFY_TZ */
+ gmtptr = (struct state *) calloc(1, sizeof *gmtptr);
+ if (gmtptr != NULL)
+#endif /* defined ALL_STATE */
+#ifdef NOTIFY_TZ
+ {
+ char fullname[FILENAME_MAX + 1];
+ gmtload(gmtptr, fullname);
+ notify_register_tz(fullname, &gmt_notify);
+ }
+#else /* ! NOTIFY_TZ */
+ gmtload(gmtptr);
+#endif /* NOTIFY_TZ */
}
/*
const long offset;
struct tm * const tmp;
{
+#ifdef __LP64__
+ register struct tm * result;
+#endif /* __LP64__ */
+
#ifdef NOTIFY_TZ_DEBUG
NOTIFY_TZ_PRINTF("gmtsub called\n");
#endif /* NOTIFY_TZ_DEBUG */
#ifdef NOTIFY_TZ
notify_check_tz(&gmt_notify);
#endif /* NOTIFY_TZ */
- if (!gmt_is_set) {
- _MUTEX_LOCK(&gmt_mutex);
- if (!gmt_is_set) {
-#ifdef ALL_STATE
-#ifdef NOTIFY_TZ
- if (gmtptr == NULL)
-#endif /* NOTIFY_TZ */
- gmtptr = (struct state *) malloc(sizeof *gmtptr);
- if (gmtptr != NULL)
-#endif /* defined ALL_STATE */
-#ifdef NOTIFY_TZ
- {
- char fullname[FILENAME_MAX + 1];
- gmtload(gmtptr, fullname);
- notify_register_tz(fullname, &gmt_notify);
- }
-#else /* ! NOTIFY_TZ */
- gmtload(gmtptr);
-#endif /* NOTIFY_TZ */
- gmt_is_set = TRUE;
- }
- _MUTEX_UNLOCK(&gmt_mutex);
- }
+ pthread_once(&gmt_once, gmt_init);
#ifdef __LP64__
- if(timesub(timep, offset, gmtptr, tmp) == NULL)
+ result = timesub(timep, offset, gmtptr, tmp);
+ if (result == NULL)
return NULL;
#else /* !__LP64__ */
timesub(timep, offset, gmtptr, tmp);
** but this is no time for a treasure hunt.
*/
if (offset != 0)
- tmp->TM_ZONE = wildabbr;
+ tmp->TM_ZONE = (char*)wildabbr;
else {
#ifdef ALL_STATE
if (gmtptr == NULL)
}
#endif /* defined TM_ZONE */
#ifdef __LP64__
- return tmp;
+ return result;
#endif /* __LP64__ */
}
+static void
+gmtime_key_init(void)
+{
+
+ gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
+ gmtime_key_error = pthread_key_init_np(gmtime_key, free);
+}
+
struct tm *
-gmtime(timep)
-const time_t * const timep;
+gmtime(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;
if (__isthreaded != 0) {
- if (gmtime_key == (pthread_key_t)-1) {
- _pthread_mutex_lock(&gmtime_mutex);
- if (gmtime_key == (pthread_key_t)-1) {
- gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
- if (pthread_key_init_np(gmtime_key, free) < 0) {
- _pthread_mutex_unlock(&gmtime_mutex);
- return(NULL);
- }
- }
- _pthread_mutex_unlock(&gmtime_mutex);
+ _pthread_once(&gmtime_once, gmtime_key_init);
+ if (gmtime_key_error != 0) {
+ errno = gmtime_key_error;
+ return(NULL);
}
/*
* Changed to follow POSIX.1 threads standard, which
*/
struct tm *
-gmtime_r(timep, tm)
-const time_t * const timep;
-struct tm * tm;
+gmtime_r(const time_t *const timep, struct tm *tmp)
{
#ifdef __LP64__
- return gmtsub(timep, 0L, tm);
+ return gmtsub(timep, 0L, tmp);
#else /* !__LP64__ */
- gmtsub(timep, 0L, tm);
- return tm;
+ gmtsub(timep, 0L, tmp);
+ return tmp;
#endif /* __LP64__ */
}
#ifdef STD_INSPIRED
struct tm *
-offtime(timep, offset)
-const time_t * const timep;
-const long offset;
+offtime(const time_t *const timep, const long offset)
{
#ifdef __LP64__
return gmtsub(timep, offset, &tm);
#endif /* defined STD_INSPIRED */
+/*
+** 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.
+*/
+
+__unused static int
+leaps_thru_end_of(y)
+register const int y;
+{
+#ifdef __LP64__
+ return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
+ -(leaps_thru_end_of(-(y + 1)) + 1);
+#else /* !__LP64__ */
+ return (y / 4 - y / 100 + y / 400);
+#endif /* __LP64__ */
+}
+
#ifdef __LP64__
static struct tm *
#else /* !__LP64__ */
}
char *
-ctime(timep)
-const time_t * const timep;
+ctime(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))
*/
#ifdef __LP64__
}
char *
-ctime_r(timep, buf)
-const time_t * const timep;
-char * buf;
+ctime_r(const time_t *const timep, char *buf)
{
- struct tm tm;
+ struct tm mytm;
#ifdef __LP64__
/*
* that exceeds 32-bits in size (won't fit in struct tm), so localtime_r
* will return NULL.
*/
- if (localtime_r(timep, &tm) == NULL)
+ if (localtime_r(timep, &mytm) == NULL)
return NULL;
- return asctime_r(&tm, buf);
+ return asctime_r(&mytm, buf);
#else /* !__LP64__ */
- return asctime_r(localtime_r(timep, &tm), buf);
+ return asctime_r(localtime_r(timep, &mytm), buf);
#endif /* __LP64__ */
}
** 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).
*/
#endif /* !defined WRONG */
/*
-** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
+** Simplified normalize logic courtesy Paul Eggert.
*/
static int
}
static int
-normalize_overflow(tensptr, unitsptr, base)
-int * const tensptr;
-int * const unitsptr;
-const int base;
+long_increment_overflow(number, delta)
+long * number;
+int delta;
+{
+ long number0;
+
+ number0 = *number;
+ *number += delta;
+ return (*number < number0) != (delta < 0);
+}
+
+static int
+normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
{
int tensdelta;
return increment_overflow(tensptr, tensdelta);
}
+static int
+long_normalize_overflow(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;
}
static time_t
-time2sub(tmp, funcp, offset, okayp, do_norm_secs, unix03)
-struct tm * const tmp;
+time2sub(struct tm *const tmp,
#ifdef __LP64__
-struct tm *(* const funcp)(const time_t*, long, struct tm*);
+ struct tm *(*const funcp)(const time_t *, long, struct tm *),
#else /* !__LP64__ */
-void (* const funcp)(const time_t*, long, struct tm*);
+ void(*funcp) (const time_t *, long, struct tm*),
#endif /* __LP64__ */
-const long offset;
-int * const okayp;
-const int do_norm_secs;
-int unix03;
+ const long offset,
+ int *const okayp,
+ const int do_norm_secs,
+ int unix03)
{
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;
-#ifdef __LP64__
- long year, il;
-#endif /* __LP64__ */
+ long li;
+ time_t lo;
+ time_t hi;
+ long y;
+ time_t newt;
+ time_t t;
+ struct tm yourtm, mytm;
*okayp = FALSE;
yourtm = *tmp;
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.
*/
-#ifdef __LP64__
- year = (long)yourtm.tm_year + TM_YEAR_BASE;
-#else /* !__LP64__ */
- if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
+ if (long_increment_overflow(&y, TM_YEAR_BASE))
return WRONG;
-#endif /* __LP64__ */
while (yourtm.tm_mday <= 0) {
-#ifdef __LP64__
- year--;
- il = year + (1 < yourtm.tm_mon);
- yourtm.tm_mday += year_lengths[isleap(il)];
-#else /* !__LP64__ */
- 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)];
-#endif /* __LP64__ */
+ li = y + (1 < yourtm.tm_mon);
+ yourtm.tm_mday += year_lengths[isleap(li)];
}
while (yourtm.tm_mday > DAYSPERLYEAR) {
-#ifdef __LP64__
- il = year + (1 < yourtm.tm_mon);
- yourtm.tm_mday -= year_lengths[isleap(il)];
- year++;
-#else /* !__LP64__ */
- 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;
-#endif /* __LP64__ */
}
for ( ; ; ) {
-#ifdef __LP64__
- i = mon_lengths[isleap(year)][yourtm.tm_mon];
-#else /* !__LP64__ */
- i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
-#endif /* __LP64__ */
+ 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;
-#ifdef __LP64__
- year++;
-#else /* !__LP64__ */
- if (increment_overflow(&yourtm.tm_year, 1))
+ if (long_increment_overflow(&y, 1))
return WRONG;
-#endif /* __LP64__ */
}
}
-#ifdef __LP64__
- year -= TM_YEAR_BASE;
- if (year > INT_MAX || year < INT_MIN)
+ if (long_increment_overflow(&y, -TM_YEAR_BASE))
return WRONG;
- yourtm.tm_year = year;
-#else /* !__LP64__ */
- if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
+ yourtm.tm_year = y;
+ if (yourtm.tm_year != y)
return WRONG;
-#endif /* __LP64__ */
/* 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.
yourtm.tm_sec = 0;
}
/*
- ** Divide the search space in half
- ** (this works whether time_t is signed or unsigned).
- */
-#ifdef __LP64__
- /* optimization: see if the value is 31-bit (signed) */
- t = (((time_t) 1) << (TYPE_BIT(int) - 1)) - 1;
- bits = ((*funcp)(&t, offset, &mytm) == NULL || tmcomp(&mytm, &yourtm) < 0) ? TYPE_BIT(time_t) - 1 : TYPE_BIT(int) - 1;
-#else /* !__LP64__ */
- bits = TYPE_BIT(time_t) - 1;
-#endif /* __LP64__ */
- /*
- ** In 64-bit, we now return an error if we cannot represent the
- ** struct tm value in a time_t. And tmcomp() is fixed to avoid
- ** overflow in tm_year. So we only put a cap on bits because time_t
- ** can't be larger that 56 bit (when tm_year == INT_MAX).
+ ** Do a binary search (this works whatever time_t's type is).
*/
- if (bits > 56)
- bits = 56;
- /*
- ** 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 ( ; ; ) {
+ t = lo / 2 + hi / 2;
+ if (t < lo)
+ t = lo;
+ else if (t > hi)
+ t = hi;
#ifdef __LP64__
if ((*funcp)(&t, offset, &mytm) == NULL) {
- /* we overflowed, so t is too big */
- dir = 1;
- goto skip_tmcomp;
- }
+ /*
+ ** 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);
#else /* !__LP64__ */
(*funcp)(&t, offset, &mytm);
-#endif /* __LP64__ */
dir = tmcomp(&mytm, &yourtm);
-#ifdef __LP64__
-skip_tmcomp:
+ // If we have searched the entire space without a match, exit
+ if (dir != 0 && t == lo && t == hi)
+ return WRONG;
#endif /* __LP64__ */
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;
}
sp = (funcp == localsub) ? lclptr : gmtptr;
sp->ttis[i].tt_gmtoff;
#ifdef __LP64__
if ((*funcp)(&newt, offset, &mytm) == NULL)
- return WRONG;
+ continue;
#else /* !__LP64__ */
(*funcp)(&newt, offset, &mytm);
#endif /* __LP64__ */
#else /* !__LP64__ */
(*funcp)(&t, offset, tmp);
#endif /* __LP64__ */
- *okayp = TRUE;
+ *okayp = TRUE;
return t;
}
static time_t
-time2(tmp, funcp, offset, okayp, unix03)
-struct tm * const tmp;
+time2(struct tm * const tmp,
#ifdef __LP64__
-struct tm *(* const funcp)(const time_t*, long, struct tm*);
+ struct tm * (*const funcp)(const time_t *, long, struct tm *),
#else /* !__LP64__ */
-void (* const funcp)(const time_t*, long, struct tm*);
+ void (*const funcp)(const time_t *, long, struct tm *),
#endif /* __LP64__ */
-const long offset;
-int * const okayp;
-int unix03;
+ const long offset,
+ int *const okayp,
+ int unix03)
{
time_t t;
time1(tmp, funcp, offset, unix03)
struct tm * const tmp;
#ifdef __LP64__
-struct tm *(* const funcp)(const time_t *, long, struct tm *);
+struct tm * (* const funcp)(const time_t *, long, struct tm *);
#else /* !__LP64__ */
-void (* const funcp)(const time_t *, long, struct tm *);
+void (* const funcp)(const time_t *, long, struct tm *);
#endif /* __LP64__ */
const long offset;
int unix03;
int types[TZ_MAX_TYPES];
int okay;
+ if (tmp == NULL) {
+ errno = EINVAL;
+ return WRONG;
+ }
+
if (tmp->tm_isdst > 1)
tmp->tm_isdst = 1;
t = time2(tmp, funcp, offset, &okay, unix03);
#ifdef PCTS
/*
- ** PCTS code courtesy Grant Sullivan (grant@osf.org).
+ ** PCTS code courtesy Grant Sullivan.
*/
if (okay)
return t;
** 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;
return WRONG;
}
#else /* BUILDING_VARIANT */
-__private_extern__ pthread_rwlock_t lcl_rwlock;
+extern pthread_rwlock_t lcl_rwlock;
#endif /* BUILDING_VARIANT */
time_t
-mktime(tmp)
-struct tm * const tmp;
+mktime(struct tm *const tmp)
{
time_t mktime_return_value;
int serrno = errno;
#ifdef STD_INSPIRED
time_t
-timelocal(tmp)
-struct tm * const tmp;
+timelocal(struct tm *const tmp)
{
- tmp->tm_isdst = -1; /* in case it wasn't initialized */
+ if (tmp != NULL)
+ tmp->tm_isdst = -1; /* in case it wasn't initialized */
return mktime(tmp);
}
time_t
-timegm(tmp)
-struct tm * const tmp;
+timegm(struct tm *const tmp)
{
- tmp->tm_isdst = 0;
+ if (tmp != NULL)
+ tmp->tm_isdst = 0;
return time1(tmp, gmtsub, 0L, __DARWIN_UNIX03);
}
time_t
-timeoff(tmp, offset)
-struct tm * const tmp;
-const long offset;
+timeoff(struct tm *const tmp, const long offset)
{
- tmp->tm_isdst = 0;
+ if (tmp != NULL)
+ tmp->tm_isdst = 0;
return time1(tmp, gmtsub, offset, __DARWIN_UNIX03);
}
*/
long
-gtime(tmp)
-struct tm * const tmp;
+gtime(struct tm *const tmp)
{
const time_t t = mktime(tmp);
*/
static long
-leapcorr(timep)
-time_t * timep;
+leapcorr(time_t *timep)
{
struct state * sp;
struct lsinfo * lp;
}
time_t
-time2posix(t)
-time_t t;
+time2posix(time_t t)
{
tzset();
return t - leapcorr(&t);
}
time_t
-posix2time(t)
-time_t t;
+posix2time(time_t t)
{
time_t x;
time_t y;
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.
*/
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
**
-** $FreeBSD: src/lib/libc/stdtime/private.h,v 1.11 2009/05/23 06:31:50 edwin Exp $
+** $FreeBSD: head/contrib/tzcode/stdtime/private.h 289027 2015-10-08 11:42:15Z rodrigc $
*/
/* Stuff moved from Makefile.inc to reduce clutter */
#define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */
+#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
+# define ATTRIBUTE_PURE __attribute__ ((__pure__))
+#else
+# define ATTRIBUTE_PURE /* empty */
+#endif
+
/*
** Workarounds for compilers/systems.
*/
** 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);
const char * scheck(const char * string, const char * format);
/*
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#ifndef lint
-#ifndef NOID
+#if 0
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".
*/
-#endif /* !defined NOID */
-#endif /* !defined lint */
+#endif
#include "xlocale_private.h"
int *, struct lc_time_T *, locale_t);
extern char * tzname[];
-__private_extern__ long __darwin_altzone; /* DST timezone offset */
+extern long __darwin_altzone; /* DST timezone offset */
#define altzone __darwin_altzone
__private_extern__ long _st_get_timezone(void);
* XXX This is bogus if parsed before hour-related
* specifiers.
*/
+ if (tm->tm_hour > 12)
+ return (NULL);
+
len = strlen(tptr->am);
if (strncasecmp_l(buf, tptr->am, len, locale) == 0) {
- if (tm->tm_hour > 12)
- return (NULL);
if (tm->tm_hour == 12)
tm->tm_hour = 0;
buf += len;
len = strlen(tptr->pm);
if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) {
- if (tm->tm_hour > 12)
- return (NULL);
if (tm->tm_hour != 12)
tm->tm_hour += 12;
buf += len;
return (NULL);
i = *buf - '0';
- if (i > 6 + (c == 'u'))
+ if (i < 0 || i > 7 || (c == 'u' && i < 1) ||
+ (c == 'w' && i > 6))
return (NULL);
- if (i == 7)
- i = 0;
- tm->tm_wday = i;
+ tm->tm_wday = i % 7;
flags |= FLAG_WDAY;
buf++;
TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1);
flags |= FLAG_YDAY;
} else if (flags & FLAG_WEEK){
+ int day_offset = week_kind == WEEK_U ? TM_SUNDAY : TM_MONDAY;
+ int fwo = first_wday_of(tm->tm_year + TM_YEAR_BASE);
+
+ /* No incomplete week (week 0). */
+ if (week_number == 0 && fwo == day_offset)
+ return (NULL);
+
if (!(flags & FLAG_WDAY)) {
- tm->tm_wday = week_kind == WEEK_U ? TM_SUNDAY : TM_MONDAY;
+ /*
+ * Set the date to the first Sunday (or Monday)
+ * of the specified week of the year.
+ */
+ tm->tm_wday = day_offset;
flags |= FLAG_WDAY;
}
- struct tm t = {0};
- t.tm_mday = week_kind == WEEK_V ? 4 : 1;
- t.tm_hour = 12; /* avoid any DST effects */
- t.tm_year = tm->tm_year;
- if (timegm(&t) == (time_t)-1) return 0;
-
- int off = t.tm_wday;
- int wday = tm->tm_wday;
+ /*
+ * Start our yday at the first day of the relevant week type.
+ */
+ int tmpyday = (7 - fwo + day_offset) % 7;
- if (week_kind != WEEK_U) {
- off = (off + 6) % 7;
- wday = (wday + 6) % 7;
+ /*
+ * ISO Weeks start counting from the first week with at least
+ * four days. If our first week had that, subtract off a week.
+ */
+ if (week_kind == WEEK_V && fwo > TM_MONDAY && fwo <= TM_THURSDAY) {
+ tmpyday -= 7;
}
-
- if (week_kind == WEEK_V) {
- t.tm_mday = 7 * week_number + wday - off - 3;
- } else {
- if(off == 0) off = 7;
- t.tm_mday = 7 * week_number + wday - off + 1;
+ /* Advance the relevant number of weeks */
+ tmpyday += (week_number - 1) * 7;
+ /* And go to the right day of week */
+ tmpyday += (tm->tm_wday - day_offset + 7) % 7;
+
+ /* Impossible yday for incomplete week (week 0). */
+ if (tmpyday < 0) {
+ if (flags & FLAG_WDAY)
+ return (NULL);
+ tmpyday = 0;
}
- if (timegm(&t) == (time_t)-1) return 0;
-
- tm->tm_yday = t.tm_yday;
-
+ tm->tm_yday = tmpyday;
flags |= FLAG_YDAY;
}
}
flags |= FLAG_MDAY;
}
if (!(flags & FLAG_WDAY)) {
- i = 0;
- wday_offset = first_wday_of(tm->tm_year);
- while (i++ <= tm->tm_yday) {
- if (wday_offset++ >= 6)
- wday_offset = 0;
- }
- tm->tm_wday = wday_offset;
+ wday_offset = first_wday_of(tm->tm_year + TM_YEAR_BASE);
+ tm->tm_wday = (wday_offset + tm->tm_yday) % 7;
flags |= FLAG_WDAY;
}
}
-.\" $FreeBSD: src/lib/libc/stdtime/tzfile.5,v 1.10 2001/07/10 13:41:23 ru Exp $
+.\" $FreeBSD: head/contrib/tzcode/stdtime/tzfile.5 259446 2013-12-16 01:58:12Z bjk $
.Dd September 13, 1994
.Dt TZFILE 5
.Os
.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).
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
.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.3
.\" This file is in the public domain, so clarified as of
-.\" 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+.\" 1996-06-05 by Arthur David Olson.
/*
** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+** 1996-06-05 by Arthur David Olson.
**
-** $FreeBSD: src/lib/libc/stdtime/tzfile.h,v 1.8 2002/03/22 23:42:05 obrien Exp $
+** $FreeBSD: head/contrib/tzcode/stdtime/tzfile.h 192625 2009-05-23 06:31:50Z edwin $
*/
/*
#ifndef lint
#ifndef NOID
/*
-static char tzfilehid[] = "@(#)tzfile.h 7.14";
+static char tzfilehid[] = "@(#)tzfile.h 8.1";
*/
#endif /* !defined NOID */
#endif /* !defined lint */
** Information about time zone files.
*/
-#ifndef TZDIR
-#ifdef UNIFDEF_TZDIR_SYMLINK
-#define TZDIR "/var/db/timezone/zoneinfo" /* Time zone object file directory */
-#else /* !UNIFDEF_TZDIR_SYMLINK */
-#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
-#endif /* UNIFDEF_TZDIR_SYMLINK */
-#endif /* !defined TZDIR */
+#include <TargetConditionals.h>
+#include <Availability.h>
+/* Time zone object file directory */
+#ifndef TZDIR
+# if TARGET_OS_SIMULATOR || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_13)
+# define TZDIR "/usr/share/zoneinfo"
+# else
+# define TZDIR "/var/db/timezone/zoneinfo"
+# endif
+#endif
+
+/* No gurantee is made that the TZDEFAULT symlink will have TZDIR as a prefix.
+ * However, clients can assume that the final path component of the prefix will
+ * be "zoneinfo"
+ */
#ifndef TZDEFAULT
-#ifdef UNIFDEF_MOVE_LOCALTIME
-#define TZDEFAULT "/var/db/timezone/localtime"
-#else /* !UNIFDEF_MOVE_LOCALTIME */
-#define TZDEFAULT "/etc/localtime"
-#endif /* UNIFDEF_MOVE_LOCALTIME */
-#endif /* !defined TZDEFAULT */
+# if TARGET_OS_SIMULATOR || TARGET_OS_OSX
+# define TZDEFAULT "/etc/localtime"
+# else
+# define TZDEFAULT "/var/db/timezone/localtime"
+# endif
+#endif
#ifndef TZDEFRULES
#define TZDEFRULES "posixrules"
#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 */
** assumed to be local time
*/
+/*
+** 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
#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 */
#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))
/*
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
-#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.
-*/
-
-#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 */
-
#endif /* !defined TZFILE_H */
+++ /dev/null
-.\" Copyright (C) 2001 Andries Brouwer <aeb@cwi.nl>
-.\"
-.\" Permission is granted to make and distribute verbatim copies of this
-.\" manual provided the copyright notice and this permission notice are
-.\" preserved on all copies.
-.\"
-.\" Permission is granted to copy and distribute modified versions of this
-.\" manual under the conditions for verbatim copying, provided that the
-.\" entire resulting derived work is distributed under the terms of a
-.\" permission notice identical to this one
-.\"
-.\" Since the Linux kernel and libraries are constantly changing, this
-.\" manual page may be incorrect or out-of-date. The author(s) assume no
-.\" responsibility for errors or omissions, or for damages resulting from
-.\" the use of the information contained herein. The author(s) may not
-.\" have taken the same level of care in the production of this manual,
-.\" which is licensed free of charge, as they might when working
-.\" professionally.
-.\"
-.\" Formatted or processed versions of this manual, if unaccompanied by
-.\" the source, must acknowledge the copyright and authors of this work.
-.\"
-.TH TIMEGM 3 2001-12-26 "GNU" "Linux Programmer's Manual"
-.SH NAME
-timegm, timelocal \- inverses for gmtime and localtime
-.SH SYNOPSIS
-.nf
-.B #include <time.h>
-.sp
-.BI "time_t timelocal (struct tm *" tm );
-.sp
-.BI "time_t timegm (struct tm *" tm );
-.SH DESCRIPTION
-The functions
-.B timelocal()
-and
-.B timegm()
-are the inverses to
-.BR localtime (3)
-and
-.BR gmtime (3).
-.SH NOTES
-These functions are GNU extensions.
-The
-.B timelocal()
-function is equivalent to the POSIX standard function
-.BR mktime (3).
-There is no reason to ever use it.
-.LP
-For a portable version of
-.BR timegm() ,
-set the
-.B TZ
-environment variable to UTC, call
-.B mktime()
-and restore the value of
-.BR TZ .
-Something like
-
-.RS
-.nf
-#include <time.h>
-#include <stdlib.h>
-
-time_t my_timegm (struct tm *tm) {
- time_t ret;
- char *tz;
-
- tz = getenv("TZ");
- setenv("TZ", "", 1);
- tzset();
- ret = mktime(tm);
- if (tz)
- setenv("TZ", tz, 1);
- else
- unsetenv("TZ");
- tzset();
- return ret;
-}
-.fi
-.RE
-.SH "SEE ALSO"
-.BR gmtime (3),
-.BR localtime (3),
-.BR mktime (3),
-.BR tzset (3)
*/
#define EBUFSIZE (20 + 2 + sizeof(UPREFIX))
-#ifndef BUILDING_VARIANT
/*
* Doing this by hand instead of linking with stdio(3) avoids bloat for
* statically linked binaries.
return (retval);
}
-__private_extern__ char *__strerror_ebuf = NULL;
-#else /* BUILDING_VARIANT */
-__private_extern__ void __errstr(int, char *, size_t);
-
-extern char *__strerror_ebuf;
-#endif /* !BUILDING_VARIANT */
+static char *__strerror_ebuf = NULL;
char *
strerror(int num)
{
- // Dynamically allocate a big buffer to receive the text then shrink it
- // down to the actual size needed.
- size_t ebufsiz = NL_TEXTMAX;
+#if !defined(NLS)
+ if (num >= 0 && num < sys_nerr) {
+ return (char*)sys_errlist[num];
+ }
+#endif
if (__strerror_ebuf == NULL) {
- __strerror_ebuf = calloc(1, ebufsiz);
+ __strerror_ebuf = calloc(1, NL_TEXTMAX);
if (__strerror_ebuf == NULL) {
return NULL;
}
}
-
- if (strerror_r(num, __strerror_ebuf, ebufsiz) != 0) {
-#if !__DARWIN_UNIX03
+
+ if (strerror_r(num, __strerror_ebuf, NL_TEXTMAX) != 0) {
errno = EINVAL;
-#endif
}
return __strerror_ebuf;
}
-.\" $OpenBSD: strlcpy.3,v 1.19 2007/05/31 19:19:32 jmc Exp $
+.\" $OpenBSD: strlcpy.3,v 1.26 2013/09/30 12:02:35 millert Exp $
.\"
.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
.\"
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libc/string/strlcpy.3,v 1.16 2009/04/07 13:42:53 trasz Exp $
+.\" $FreeBSD$
.\"
-.Dd June 22, 1998
+.Dd February 26, 2016
.Dt STRLCPY 3
.Os
.Sh NAME
.Sh SYNOPSIS
.In string.h
.Ft size_t
-.Fn strlcpy "char * restrict dst" "const char * restrict src" "size_t size"
+.Fn strlcpy "char * restrict dst" "const char * restrict src" "size_t dstsize"
.Ft size_t
-.Fn strlcat "char * restrict dst" "const char * restrict src" "size_t size"
+.Fn strlcat "char * restrict dst" "const char * restrict src" "size_t dstsize"
.Sh DESCRIPTION
The
.Fn strlcpy
and
.Fn strlcat
-functions copy and concatenate strings respectively.
-They are designed
-to be safer, more consistent, and less error prone replacements for
+functions copy and concatenate strings with the
+same input parameters and output result as
+.Xr snprintf 3 .
+They are designed to be safer, more consistent, and less error
+prone replacements for the easily misused functions
.Xr strncpy 3
and
.Xr strncat 3 .
-Unlike those functions,
-.Fn strlcpy
-and
-.Fn strlcat
-take the full size of the buffer (not just the length) and guarantee to
-NUL-terminate the result (as long as
-.Fa size
-is larger than 0 or, in the case of
-.Fn strlcat ,
-as long as there is at least one byte free in
-.Fa dst ) .
-Note that a byte for the NUL should be included in
-.Fa size .
-Also note that
+.Pp
.Fn strlcpy
and
.Fn strlcat
-only operate on true
-.Dq C
-strings.
-This means that for
-.Fn strlcpy
-.Fa src
-must be NUL-terminated and for
-.Fn strlcat
-both
-.Fa src
-and
-.Fa dst
-must be NUL-terminated.
+take the full size of the destination buffer and guarantee
+NUL-termination if there is room.
+Note that room for the NUL should be included in
+.Fa dstsize .
.Pp
-The
.Fn strlcpy
-function copies up to
-.Fa size
-- 1 characters from the NUL-terminated string
+copies up to
+.Fa dstsize
+\- 1 characters from the string
.Fa src
to
.Fa dst ,
-NUL-terminating the result.
+NUL-terminating the result if
+.Fa dstsize
+is not 0.
.Pp
-The
.Fn strlcat
-function appends the NUL-terminated string
+appends string
.Fa src
to the end of
.Fa dst .
It will append at most
-.Fa size
-- strlen(dst) - 1 bytes, NUL-terminating the result.
+.Fa dstsize
+\- strlen(dst) \- 1 characters.
+It will then NUL-terminate, unless
+.Fa dstsize
+is 0 or the original
+.Fa dst
+string was longer than
+.Fa dstsize
+(in practice this should not happen
+as it means that either
+.Fa dstsize
+is incorrect or that
+.Fa dst
+is not a proper string).
.Pp
-The source and destination strings should not overlap, as the
-behavior is undefined.
+If the
+.Fa src
+and
+.Fa dst
+strings overlap, the behavior is undefined.
.Sh RETURN VALUES
-The
+Besides quibbles over the return type
+.Pf ( Va size_t
+versus
+.Va int )
+and signal handler safety
+.Pf ( Xr snprintf 3
+is not entirely safe on some systems), the
+following two are equivalent:
+.Bd -literal -offset indent
+n = strlcpy(dst, src, len);
+n = snprintf(dst, len, "%s", src);
+.Ed
+.Pp
+Like
+.Xr snprintf 3 ,
+the
.Fn strlcpy
and
.Fn strlcat
-functions return the total length of the string they tried to
-create.
+functions return the total length of the string they tried to create.
For
.Fn strlcpy
that means the length of
plus
the length of
.Fa src .
-While this may seem somewhat confusing, it was done to make
-truncation detection simple.
.Pp
-Note however, that if
-.Fn strlcat
-traverses
-.Fa size
-characters without finding a NUL, the length of the string is considered
-to be
-.Fa size
-and the destination string will not be NUL-terminated (since there was
-no space for the NUL).
-This keeps
-.Fn strlcat
-from running off the end of a string.
-In practice this should not happen (as it means that either
-.Fa size
-is incorrect or that
-.Fa dst
-is not a proper
-.Dq C
-string).
-The check exists to prevent potential security problems in incorrect code.
+If the return value is
+.Cm >=
+.Va dstsize ,
+the output string has been truncated.
+It is the caller's responsibility to handle this.
.Sh EXAMPLES
The following code fragment illustrates the simple case:
.Bd -literal -offset indent
.Ed
.Pp
Since it is known how many characters were copied the first time, things
-can be sped up a bit by using a copy instead of an append
+can be sped up a bit by using a copy instead of an append:
.Bd -literal -offset indent
char *dir, *file, pname[MAXPATHLEN];
size_t n;
.Fn strlcat
functions first appeared in
.Ox 2.4 ,
-and made their appearance in
+and
.Fx 3.3 .
bytes of the memory buffer whose starting address is given by
.Fa s .
.Pp
-It is a runtime-consrtaints violation if
+It is a runtime-constraints violation if
.Fa s
is a null pointer,
or if either of
static type * var ## _pointer = 0
#define DECLARE_PROGNAME(var, type) \
static type * var ## _pointer = 0; \
- static type _priv_ ## var = 0
+ __unused static type _priv_ ## var = 0
#define USE_VAR(var) (var ## _pointer)
#else
#define DECLARE_VAR(var, type) extern type var
struct timeval atv;
if (tp == NULL) {
- if (tzp == NULL)
- return (0);
- tp = &atv;
+ if (tzp == NULL)
+ return (0);
+ tp = &atv;
}
if (__commpage_gettimeofday(tp)) { /* first try commpage */
#include <sys/time.h>
#include <notify.h>
#include <notify_keys.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "_simple.h"
#ifndef kNotifyClockSet
#define kNotifyClockSet "com.apple.system.clock_set"
int ret = __settimeofday(tp, tzp);
if (ret == 0) notify_post(kNotifyClockSet);
+ char *msg = NULL;
+ asprintf(&msg, "settimeofday({%#lx,%#x}) == %d", tp->tv_sec, tp->tv_usec, ret);
+ _simple_asl_log(ASL_LEVEL_NOTICE, "com.apple.settimeofday", msg);
+ free(msg);
+
return ret;
}
include $(DEVELOPER_DIR)/AppleInternal/Makefiles/darwintest/Makefile.common
-OTHER_CFLAGS := -DDARWINTEST -Weverything -Wno-vla -Wno-missing-field-initializers -Wno-padded -Wno-gnu-flexible-array-initializer --std=gnu11 -Wno-gnu-empty-initializer
+ifeq ($(PLATFORM),BridgeOS)
+EXCLUDED_SOURCES += locale.c
+endif
+
+WARNING_CFLAGS := -Weverything \
+ -Wno-vla -Wno-missing-field-initializers -Wno-padded \
+ -Wno-gnu-flexible-array-initializer -Wno-gnu-empty-initializer \
+ -Wno-partial-availability -Wno-used-but-marked-unused \
+ -Wno-reserved-id-macro -fmacro-backtrace-limit=0 \
+ -Wno-c++98-compat
+OTHER_CFLAGS := -DDARWINTEST --std=gnu11 $(WARNING_CFLAGS)
OTHER_LDFLAGS := -ldarwintest_utils
+ASAN_DYLIB_PATH := /usr/local/lib/sanitizers/
nxheap: OTHER_CFLAGS += -Wno-cast-align
strlcat: OTHER_CFLAGS += -Wno-pointer-arith
psort: OTHER_CFLAGS += -Wno-cast-qual -Wno-sign-conversion
net: OTHER_CFLAGS += -Wno-sign-conversion -Wno-cast-align -Wno-incompatible-pointer-types-discards-qualifiers -Wno-sign-compare
+printf: OTHER_CFLAGS += -Wno-format-nonliteral
+strlcpy: OTHER_CFLAGS += -D_FORTIFY_SOURCE=0
+realpath_edge: OTHER_CFLAGS += -fsanitize=address -I../fbsdcompat
+realpath_edge: OTHER_LDFLAGS += -Wl,-rpath -Wl,$(ASAN_DYLIB_PATH)
+qsort freebsd_qsort: OTHER_CFLAGS += -Wno-unused-function
+ifeq ($(PLATFORM),MacOSX)
+qsort_perf: OTHER_CFLAGS += -Wno-sign-compare -Wno-sign-conversion -Wno-cast-align -Wno-shorten-64-to-32
+else
+EXCLUDED_SOURCES += qsort_perf.c
+endif
include $(DEVELOPER_DIR)/AppleInternal/Makefiles/darwintest/Makefile.targets
+
--- /dev/null
+#define OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE 1
+#include <os/assumes.h>
+
+#include <darwintest.h>
+
+void os_crash_function(const char *message);
+
+static const char *expected_message = NULL;
+
+void os_crash_function(const char *message) {
+ if (expected_message) {
+ T_ASSERT_EQ_STR(message, expected_message, NULL);
+ T_END;
+ } else {
+ T_PASS("Got crash message: %s", message);
+ T_END;
+ }
+}
+
+T_DECL(os_crash_sanity, "sanity check for os_crash")
+{
+ expected_message = "My AWESOME assertion message.";
+ os_crash(expected_message);
+}
+
+extern int two;
+int two = 2;
+
+T_DECL(os_assert_no_msg, "sanity check for os_assert w/o a message")
+{
+ expected_message = "assertion failure: \"two + two == 5\" -> %lld";
+ os_assert(two + two == 5);
+}
+
+#define DOGMA "Today, we celebrate the first glorious anniversary of the Information Purification Directives."
+T_DECL(os_assert_msg, "sanity check for os_assert with a message")
+{
+ expected_message = "assertion failure: " DOGMA;
+ os_assert(two + two == 5, DOGMA);
+}
--- /dev/null
+#include <os/assumes.h>
+
+#include <darwintest.h>
+
+void os_crash_function(const char *message);
+
+static const char *expected_message = NULL;
+
+void os_crash_function(const char *message) {
+ if (expected_message) {
+ T_ASSERT_EQ_STR(message, expected_message, NULL);
+ T_END;
+ } else {
+ T_PASS("Got crash message: %s", message);
+ T_END;
+ }
+}
+
+T_DECL(os_crash_sanity, "sanity check for os_crash")
+{
+ expected_message = "My AWESOME assertion message.";
+ os_crash(expected_message);
+}
--- /dev/null
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <darwintest.h>
+#include <darwintest_utils.h>
+
+T_DECL(seekdir_basic, "seekdir")
+{
+ const char *path = dt_tmpdir();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ int fd = open(path, O_RDONLY | O_DIRECTORY);
+ openat(fd, "a", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "b", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "c", O_CREAT | O_WRONLY, 0600);
+
+ DIR *dirp = fdopendir(fd);
+ struct dirent *entry = NULL;
+
+ T_ASSERT_NOTNULL(dirp, NULL);
+
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL); // .
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL); // ..
+
+ // we can get any entry -- no ordering
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ // remember position for the second entry
+ long second_pos = telldir(dirp);
+ // read the second entry
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ char *second_name = strdup(entry->d_name);
+ T_ASSERT_NOTNULL(second_name, NULL);
+ // read the third entry
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ // go back to the second entry and read it
+ seekdir(dirp, second_pos);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ // make sure the name matches the old copy
+ T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
+
+ // return to 2nd once again, reinitializing second_pos and re-reading
+ seekdir(dirp, second_pos);
+ second_pos = telldir(dirp);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ // make sure the name matches the old copy
+ T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
+
+ // verify that last pos
+ seekdir(dirp, second_pos);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
+
+ free(second_name);
+ T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
+}
+
+T_DECL(readdir, "readdir")
+{
+ const char *path = dt_tmpdir();
+ int fd = open(path, O_RDONLY | O_DIRECTORY);
+ openat(fd, "foobarbaz", O_CREAT | O_WRONLY, 0600);
+
+ DIR *dirp = fdopendir(fd);
+ T_ASSERT_NOTNULL(dirp, NULL);
+
+ struct dirent *entry = NULL;
+ while ((entry = readdir(dirp)) != NULL) {
+ if (strcmp(entry->d_name, "foobarbaz")) {
+ break;
+ }
+ }
+
+ T_ASSERT_NOTNULL(entry, "found the entry");
+
+ T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
+}
+
+T_DECL(tell_seek_tell, "tell-seek-tell returns the same location")
+{
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/telldir.html
+ // If the most recent operation on the directory stream was a seekdir(),
+ // the directory position returned from the telldir() shall be the same as
+ // that supplied as a loc argument for seekdir().
+
+ const char *path = dt_tmpdir();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ {
+ int fd = open(path, O_RDONLY | O_DIRECTORY);
+ openat(fd, "a", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "b", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "c", O_CREAT | O_WRONLY, 0600);
+ close(fd);
+ }
+
+ DIR *dirp = opendir(path);
+ T_ASSERT_NOTNULL(dirp, NULL);
+ struct dirent *entry = NULL;
+
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ long pos1 = telldir(dirp);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ seekdir(dirp, pos1);
+ long pos2 = telldir(dirp);
+
+ T_ASSERT_EQ(pos1, pos2, NULL);
+
+ T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
+}
+
+T_DECL(rewinddir, "rewinddir")
+{
+ const char *path = dt_tmpdir();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ {
+ int fd = open(path, O_RDONLY | O_DIRECTORY);
+ openat(fd, "a", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "b", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "c", O_CREAT | O_WRONLY, 0600);
+ close(fd);
+ }
+
+ DIR *dirp = opendir(path);
+ T_ASSERT_NOTNULL(dirp, NULL);
+ struct dirent *entry = NULL;
+
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ char *third_name = strdup(entry->d_name);
+
+ rewinddir(dirp);
+
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ T_ASSERT_EQ_STR(third_name, entry->d_name, NULL);
+
+ free(third_name);
+ T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
+}
+
+
+T_DECL(rewinddir_dup, "rewinddir dup")
+{
+ // An older implementation of rewinddir failed to seek the fd which was
+ // passed to fdopendir()
+
+ const char *path = dt_tmpdir();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ int fd = open(path, O_RDONLY | O_DIRECTORY);
+ openat(fd, "a", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "b", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "c", O_CREAT | O_WRONLY, 0600);
+
+ // prep an fd with a non-zero seek
+ DIR *dirp = fdopendir(fd);
+ T_ASSERT_NOTNULL(dirp, NULL);
+ struct dirent *entry = NULL;
+
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ // remember the entry name and dup the fd
+ char *third_name = strdup(entry->d_name);
+ int fd2 = dup(fd);
+
+ T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
+
+ dirp = fdopendir(fd2);
+ // rewind back to 0
+ rewinddir(dirp);
+
+ T_ASSERT_NOTNULL(dirp, NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ T_ASSERT_EQ_STR(third_name, entry->d_name, NULL);
+
+ free(third_name);
+ T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
+}
+
+static int
+_select_abc(const struct dirent *entry)
+{
+ return strcmp(entry->d_name, "a") == 0 ||
+ strcmp(entry->d_name, "b") == 0 ||
+ strcmp(entry->d_name, "c") == 0;
+}
+
+T_DECL(scandir, "scandir")
+{
+ const char *path = dt_tmpdir();
+ {
+ int fd = open(path, O_RDONLY | O_DIRECTORY);
+ openat(fd, "a", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "b", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "c", O_CREAT | O_WRONLY, 0600);
+ close(fd);
+ }
+
+ struct dirent **entries = NULL;
+ int found = scandir(path, &entries, _select_abc, alphasort);
+
+ T_ASSERT_EQ(found, 3, NULL);
+
+ T_ASSERT_EQ_STR(entries[0]->d_name, "a", NULL);
+ T_ASSERT_EQ_STR(entries[1]->d_name, "b", NULL);
+ T_ASSERT_EQ_STR(entries[2]->d_name, "c", NULL);
+
+ free(entries[0]);
+ free(entries[1]);
+ free(entries[2]);
+ free(entries);
+}
+
+T_DECL(scandir_b, "scandir_b")
+{
+ const char *path = dt_tmpdir();
+ {
+ int fd = open(path, O_RDONLY | O_DIRECTORY);
+ openat(fd, "a", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "b", O_CREAT | O_WRONLY, 0600);
+ openat(fd, "c", O_CREAT | O_WRONLY, 0600);
+ close(fd);
+ }
+
+ const struct dirent **entries = NULL;
+ int found = scandir_b(path, &entries,
+ ^(const struct dirent *entry) {
+ return strcmp(entry->d_name, "a") == 0 ||
+ strcmp(entry->d_name, "b") == 0 ||
+ strcmp(entry->d_name, "c") == 0;
+ },
+ ^(const struct dirent **d1, const struct dirent **d2) {
+ return strcoll((*d1)->d_name, (*d2)->d_name);
+ });
+
+ T_ASSERT_EQ(found, 3, NULL);
+
+ T_ASSERT_EQ_STR(entries[0]->d_name, "a", NULL);
+ T_ASSERT_EQ_STR(entries[1]->d_name, "b", NULL);
+ T_ASSERT_EQ_STR(entries[2]->d_name, "c", NULL);
+
+ free(entries[0]);
+ free(entries[1]);
+ free(entries[2]);
+ free(entries);
+}
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirstat.h>
+#include <darwintest.h>
+#include <darwintest_utils.h>
+#include <sys/stat.h>
+
+#include <TargetConditionals.h>
+
+#if !TARGET_OS_SIMULATOR
+#define HAS_APFS
+#endif
+
+#ifdef HAS_APFS
+#include <apfs/apfs_fsctl.h>
+#endif
+
+T_DECL(dirstat, "Runs dirstat(3)")
+{
+ bool fast_only = false;
+ bool force_fallback = false;
+ char *path = "/System/Library/Frameworks";
+
+ // <rdar://problem/26400444> Libdarwintest passes argv without progname and flags starting in argv[0]
+ optind = 0;
+
+ int ch;
+ while ((ch = getopt(argc, argv, "fup:")) != -1){
+ switch (ch){
+ case 'f':
+ fast_only = true;
+ break;
+ case 'u':
+ force_fallback = true;
+ break;
+ case 'p':
+ path = optarg;
+ break;
+ case '?':
+ T_ASSERT_FAIL("Usage: [-f] [-p <path>]");
+ }
+ }
+
+ T_LOG("Path: %s", path);
+
+ int flags = 0;
+ if (fast_only) {
+ T_LOG("Using DIRSTAT_FAST_ONLY");
+ flags |= DIRSTAT_FAST_ONLY;
+ }
+ if (force_fallback) {
+ T_LOG("Using DIRSTAT_FORCE_FALLBACK");
+ flags |= DIRSTAT_FORCE_FALLBACK;
+ }
+
+ struct dirstat ds = {0};
+
+ T_ASSERT_POSIX_SUCCESS(dirstat_np(path, flags, &ds, sizeof(ds)), NULL);
+
+ T_LOG("Size: %zd bytes", ds.total_size);
+ T_LOG("Descendants: %llu objects", ds.descendants);
+}
+
+T_DECL(dirstat_fallback, "Tests dirstat(3) fallback")
+{
+ char *path = "/System/Library/Frameworks";
+
+ struct dirstat ds = {0};
+
+ off_t native_size = 0;
+ off_t fallback_size = 0;
+
+ T_LOG("dirstat_np(\"%s\", 0, ...)", path);
+ T_EXPECT_POSIX_SUCCESS(dirstat_np(path, 0, &ds, sizeof(ds)), NULL);
+ T_LOG("Size: %zd bytes", ds.total_size);
+ T_LOG("Descendants: %llu objects", ds.descendants);
+ native_size = ds.total_size;
+
+ T_LOG("dirstat_np(\"%s\", DIRSTAT_FORCE_FALLBACK, ...)", path);
+ T_EXPECT_POSIX_SUCCESS(dirstat_np(path, DIRSTAT_FORCE_FALLBACK, &ds, sizeof(ds)), NULL);
+ T_LOG("Size: %zd bytes", ds.total_size);
+ T_LOG("Descendants: %llu objects", ds.descendants);
+ fallback_size = ds.total_size;
+
+ T_EXPECT_EQ(native_size, fallback_size, "Native and fallback sizes match");
+}
+
+T_DECL(dirstat_flags, "Tests dirstat(3)'s behavior flags")
+{
+ int err;
+ struct dirstat ds = {0};
+
+ char *not_fast = "/System/Library/Frameworks";
+
+ T_LOG("dirstat_np(\"%s\", DIRSTAT_FAST_ONLY, ...)", not_fast);
+ T_EXPECT_EQ(dirstat_np(not_fast, DIRSTAT_FAST_ONLY, &ds, sizeof(ds)), -1, "Fast-only fails on non-fast-enabled directory");
+
+#ifdef HAS_APFS
+ char *fast_tmpdir;
+ uint64_t flags = 0;
+
+ T_SETUPBEGIN;
+ T_ASSERT_NE(asprintf(&fast_tmpdir, "%s/%s", dt_tmpdir(), "fast-XXXXXX"), -1, "Generate fast dir stats directory name");
+ T_ASSERT_EQ((void *)mkdtemp(fast_tmpdir), (void *)fast_tmpdir, "Make fast dir stats directory");
+ err = fsctl(fast_tmpdir, APFSIOC_MAINTAIN_DIR_STATS, &flags, 0);
+ if (err != 0) {
+ rmdir(fast_tmpdir);
+ free(fast_tmpdir);
+ T_SKIP("Couldn't enable fast dir stats for directory (not on APFS?)");
+ }
+ T_SETUPEND;
+
+ T_LOG("dirstat_np(\"%s\", DIRSTAT_FAST_ONLY, ...)", fast_tmpdir);
+ T_EXPECTFAIL;
+ T_EXPECT_POSIX_SUCCESS(dirstat_np(fast_tmpdir, DIRSTAT_FAST_ONLY, &ds, sizeof(ds)), "Fast-only works on fast-enabled directory");
+
+ T_ASSERT_POSIX_SUCCESS(rmdir(fast_tmpdir), NULL);
+ free(fast_tmpdir);
+#endif
+}
--- /dev/null
+#include <Block.h>
+#include <darwintest.h>
+#include <err.h>
+
+#define ITERATIONS 100
+
+T_DECL(err_multiple_exit_b, "Repeated set exit blocks doesn't leak copied blocks")
+{
+ int __block num = 0;
+ for (int i = 0; i < ITERATIONS; ++i) {
+ err_set_exit_b(^(int j) { num += j; });
+ }
+ err_set_exit_b(NULL);
+ // Dummy expect is necessary to run leaks on this test.
+ T_EXPECT_NULL(NULL, "DUMMY EXPECT");
+}
+
+T_DECL(err_multiple_exit, "Setting exit w/o block after setting exit with block doesn't leak copied block")
+{
+ int __block num = 0;
+ err_set_exit_b(^(int j) { num += j; });
+ err_set_exit(NULL);
+ // Dummy expect is necessary to run leaks on this test.
+ T_EXPECT_NULL(NULL, "DUMMY EXPECT");
+}
--- /dev/null
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "darwintest.h"
+
+T_DECL(flockfile_preserve_errno, "flockfile preserves errno")
+{
+ errno = EBUSY;
+ flockfile(stderr);
+ T_ASSERT_EQ(errno, EBUSY, "flockfile preserves errno");
+}
+
+T_DECL(funlockfile_preserve_errno, "funlockfile preserves errno")
+{
+ errno = EBUSY;
+ funlockfile(stderr);
+ T_ASSERT_EQ(errno, EBUSY, "funlockfile preserves errno");
+}
+
+T_DECL(ftrylockfile_preserve_errno, "ftrylockfile preserves errno")
+{
+ errno = EBUSY;
+ ftrylockfile(stderr);
+ T_ASSERT_EQ(errno, EBUSY, "ftrylockfile preserves errno");
+}
+
--- /dev/null
+/*-
+Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
+
+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 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 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.
+*/
+
+/*
+ * Test basic FILE * functions (fread, fwrite, fseek, fclose) against
+ * a FILE * retrieved using fmemopen()
+ */
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#include <darwintest.h>
+
+T_DECL(freebsd_fmemopen_test_preexisting, "")
+{
+ /* Use a pre-existing buffer. */
+ char buf[512];
+ char buf2[512];
+ char str[] = "Test writing some stuff";
+ char str2[] = "AAAAAAAAA";
+ char str3[] = "AAAA writing some stuff";
+ FILE *fp;
+ size_t nofw, nofr;
+ int rc;
+
+ /* Open a FILE * using fmemopen. */
+ fp = fmemopen(buf, sizeof(buf), "w");
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ /* Write to the buffer. */
+ nofw = fwrite(str, 1, sizeof(str), fp);
+ T_ASSERT_EQ(nofw, sizeof(str), NULL);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+
+ /* Re-open the FILE * to read back the data. */
+ fp = fmemopen(buf, sizeof(buf), "r");
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ /* Read from the buffer. */
+ bzero(buf2, sizeof(buf2));
+ nofr = fread(buf2, 1, sizeof(buf2), fp);
+ T_ASSERT_EQ(nofr, sizeof(buf2), NULL);
+
+ /*
+ * Since a write on a FILE * retrieved by fmemopen
+ * will add a '\0' (if there's space), we can check
+ * the strings for equality.
+ */
+ T_ASSERT_EQ_STR(str, buf2, NULL);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+
+ /* Now open a FILE * on the first 4 bytes of the string. */
+ fp = fmemopen(str, 4, "w");
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ /*
+ * Try to write more bytes than we shoud, we'll get a short count (4).
+ */
+ nofw = fwrite(str2, 1, sizeof(str2), fp);
+ T_ASSERT_EQ(nofw, 4UL, NULL);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+
+ /* Check that the string was not modified after the first 4 bytes. */
+ T_ASSERT_EQ_STR(str, str3, NULL);
+}
+
+T_DECL(freebsd_fmemopen_test_autoalloc, "")
+{
+ /* Let fmemopen allocate the buffer. */
+ FILE *fp;
+ long pos;
+ size_t nofw, i;
+ int rc;
+
+ /* Open a FILE * using fmemopen. */
+ fp = fmemopen(NULL, 512, "w+");
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ /* fill the buffer */
+ for (i = 0; i < 512; i++) {
+ nofw = fwrite("a", 1, 1, fp);
+ T_ASSERT_EQ(nofw, 1UL, NULL);
+ }
+
+ /* Get the current position into the stream. */
+ pos = ftell(fp);
+ T_ASSERT_EQ(pos, 512L, NULL);
+
+ /* Try to write past the end, we should get a short object count (0) */
+ nofw = fwrite("a", 1, 1, fp);
+ T_ASSERT_POSIX_ZERO(nofw, NULL);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+
+ /* Open a FILE * using a wrong mode */
+ fp = fmemopen(NULL, 512, "r");
+ T_ASSERT_NULL(fp, NULL);
+
+ fp = fmemopen(NULL, 512, "w");
+ T_ASSERT_NULL(fp, NULL);
+}
+
+T_DECL(freebsd_fmemopen_test_data_length, "")
+{
+ /*
+ * Here we test that a read operation doesn't go past the end of the
+ * data actually written, and that a SEEK_END seeks from the end of the
+ * data, not of the whole buffer.
+ */
+ FILE *fp;
+ char buf[512] = {'\0'};
+ char str[] = "Test data length. ";
+ char str2[] = "Do we have two sentences?";
+ char str3[sizeof(str) + sizeof(str2) -1];
+ long pos;
+ size_t nofw, nofr;
+ int rc;
+
+ /* Open a FILE * for updating our buffer. */
+ fp = fmemopen(buf, sizeof(buf), "w+");
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ /* Write our string into the buffer. */
+ nofw = fwrite(str, 1, sizeof(str), fp);
+ T_ASSERT_EQ(nofw, sizeof(str), NULL);
+
+ /* Now seek to the end and check that ftell gives us sizeof(str). */
+ rc = fseek(fp, 0, SEEK_END);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+ pos = ftell(fp);
+ T_ASSERT_EQ(pos, (long)sizeof(str), NULL);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+
+ /* Reopen the buffer for appending. */
+ fp = fmemopen(buf, sizeof(buf), "a+");
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ /* We should now be writing after the first string. */
+ nofw = fwrite(str2, 1, sizeof(str2), fp);
+ T_ASSERT_EQ(nofw, sizeof(str2), NULL);
+
+ /* Rewind the FILE *. */
+ rc = fseek(fp, 0, SEEK_SET);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+
+ /* Make sure we're at the beginning. */
+ pos = ftell(fp);
+ T_ASSERT_EQ(pos, 0L, NULL);
+
+ /* Read the whole buffer. */
+ nofr = fread(str3, 1, sizeof(buf), fp);
+ T_ASSERT_EQ(nofr, sizeof(str3), NULL);
+
+ /* Make sure the two strings are there. */
+ T_ASSERT_EQ(strncmp(str3, str, sizeof(str) - 1), 0, NULL);
+ T_ASSERT_EQ(strncmp(str3 + sizeof(str) - 1, str2, sizeof(str2)), 0, NULL);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+}
+
+T_DECL(freebsd_fmemopen_test_binary, "")
+{
+ /*
+ * Make sure that NULL bytes are never appended when opening a buffer
+ * in binary mode.
+ */
+
+ FILE *fp;
+ char buf[20];
+ char str[] = "Test";
+ size_t nofw;
+ int rc;
+
+ /* Pre-fill the buffer. */
+ memset(buf, 'A', sizeof(buf));
+
+ /* Open a FILE * in binary mode. */
+ fp = fmemopen(buf, sizeof(buf), "w+b");
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ /* Write some data into it. */
+ nofw = fwrite(str, 1, strlen(str), fp);
+ T_ASSERT_EQ(nofw, strlen(str), NULL);
+
+ /* Make sure that the buffer doesn't contain any NULL bytes. */
+ for (size_t i = 0; i < sizeof(buf); i++)
+ T_ASSERT_NE(buf[i], '\0', NULL);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+}
+
+T_DECL(freebsd_fmemopen_test_append_binary_pos, "")
+{
+ /*
+ * For compatibility with other implementations (glibc), we set the
+ * position to 0 when opening an automatically allocated binary stream
+ * for appending.
+ */
+
+ FILE *fp;
+
+ fp = fmemopen(NULL, 16, "ab+");
+ T_ASSERT_NOTNULL(fp, NULL);
+ T_ASSERT_EQ(ftell(fp), 0L, NULL);
+ fclose(fp);
+
+ /* Make sure that a pre-allocated buffer behaves correctly. */
+ char buf[] = "Hello";
+ fp = fmemopen(buf, sizeof(buf), "ab+");
+ T_ASSERT_NOTNULL(fp, NULL);
+ T_ASSERT_EQ(ftell(fp), (long)strlen(buf), NULL);
+ fclose(fp);
+}
+
+T_DECL(freebsd_fmemopen_test_size_0, "")
+{
+ /* POSIX mandates that we return EINVAL if size is 0. */
+
+ FILE *fp;
+
+ fp = fmemopen(NULL, 0, "r+");
+ T_ASSERT_NULL(fp, NULL);
+ T_ASSERT_EQ(errno, EINVAL, NULL);
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Dell EMC Isilon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <darwintest.h>
+#include <darwintest_utils.h>
+
+/*
+ * Derived from Russ Cox' pathological case test program used for the
+ * https://research.swtch.com/glob article.
+ */
+T_DECL(glob_pathological_test, "Russ Cox's pathological test program")
+{
+ struct timespec t, t2;
+ glob_t g;
+ const char *longname = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ char pattern[1000], *p;
+ double dt;
+ unsigned i, j, k, mul = 10;
+ int fd, rc;
+
+ T_SETUPBEGIN;
+ rc = chdir(dt_tmpdir());
+ T_ASSERT_POSIX_ZERO(rc, NULL);
+ fd = open(longname, O_CREAT | O_RDWR, 0666);
+ T_ASSERT_POSIX_SUCCESS(fd, NULL);
+ T_SETUPEND;
+
+ /*
+ * Test up to 100 a* groups. Exponential implementations typically go
+ * bang at i=7 or 8.
+ */
+ for (i = 0; i < 100; i++) {
+ /*
+ * Create a*...b pattern with i 'a*' groups.
+ */
+ p = pattern;
+ for (k = 0; k < i; k++) {
+ *p++ = 'a';
+ *p++ = '*';
+ }
+ *p++ = 'b';
+ *p = '\0';
+
+ clock_gettime(CLOCK_MONOTONIC_RAW, &t);
+ for (j = 0; j < mul; j++) {
+ memset(&g, 0, sizeof g);
+ rc = glob(pattern, 0, 0, &g);
+ if (rc == GLOB_NOSPACE || rc == GLOB_ABORTED) {
+ T_ASSERT_EQ(rc, GLOB_NOMATCH,
+ "an unexpected error occurred: "
+ "rc=%d errno=%d", rc, errno);
+ /* NORETURN */
+ }
+
+ if (rc != GLOB_NOMATCH) {
+ T_FAIL("A bogus match occurred: '%s' ~ '%s'", pattern, g.gl_pathv ? g.gl_pathv[0] : "(NULL)");
+ }
+ globfree(&g);
+ }
+ clock_gettime(CLOCK_MONOTONIC_RAW, &t2);
+
+ t2.tv_sec -= t.tv_sec;
+ t2.tv_nsec -= t.tv_nsec;
+ dt = t2.tv_sec + (double)t2.tv_nsec/1e9;
+ dt /= mul;
+
+ T_ASSERT_LE(dt, 1.0, "glob(3) completes in reasonable time (%d): %.9f sec/match", i,
+ dt);
+
+ if (dt >= 0.0001)
+ mul = 1;
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2013 Hudson River Trading 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.
+ */
+
+#include <sys/cdefs.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <darwintest.h>
+
+static char *buf;
+static size_t len;
+
+static void
+assert_stream(const char *contents)
+{
+ T_EXPECT_EQ(strlen(contents), len,
+ "bad length %zd for \"%s\"\n", len, contents);
+ T_EXPECT_EQ(strncmp(buf, contents, strlen(contents)), 0,
+ "bad buffer \"%s\" for \"%s\"\n", buf, contents);
+}
+
+T_DECL(freebsd_open_memstream_open_group_test, "")
+{
+ FILE *fp;
+ off_t eob;
+
+ fp = open_memstream(&buf, &len);
+ T_ASSERT_NOTNULL(fp, "open_memstream failed");
+
+ fprintf(fp, "hello my world");
+ fflush(fp);
+ assert_stream("hello my world");
+ eob = ftello(fp);
+ rewind(fp);
+ fprintf(fp, "good-bye");
+ fseeko(fp, eob, SEEK_SET);
+ fclose(fp);
+ assert_stream("good-bye world");
+ free(buf);
+}
+
+T_DECL(freebsd_open_memstream_simple_tests, "")
+{
+ static const char zerobuf[] =
+ { 'f', 'o', 'o', 0, 0, 0, 0, 'b', 'a', 'r', 0 };
+ char c;
+ FILE *fp;
+
+ fp = open_memstream(&buf, NULL);
+ T_ASSERT_NULL(fp, "open_memstream did not fail");
+ T_ASSERT_EQ(errno, EINVAL, "open_memstream didn't fail with EINVAL");
+ fp = open_memstream(NULL, &len);
+ T_ASSERT_NULL(fp, "open_memstream did not fail");
+ T_ASSERT_EQ(errno, EINVAL, "open_memstream didn't fail with EINVAL");
+ fp = open_memstream(&buf, &len);
+ T_ASSERT_NOTNULL(fp, "open_memstream failed, errno=%d", errno);
+ fflush(fp);
+ assert_stream("");
+ if (fwide(fp, 0) >= 0)
+ printf("stream is not byte-oriented\n");
+
+ fprintf(fp, "fo");
+ fflush(fp);
+ assert_stream("fo");
+ fputc('o', fp);
+ fflush(fp);
+ assert_stream("foo");
+ rewind(fp);
+ fflush(fp);
+ assert_stream("");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream("foo");
+
+ /*
+ * Test seeking out past the current end. Should zero-fill the
+ * intermediate area.
+ */
+ fseek(fp, 4, SEEK_END);
+ fprintf(fp, "bar");
+ fflush(fp);
+
+ /*
+ * Can't use assert_stream() here since this should contain
+ * embedded null characters.
+ */
+ if (len != 10)
+ printf("bad length %zd for zero-fill test\n", len);
+ else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0)
+ printf("bad buffer for zero-fill test\n");
+
+ fseek(fp, 3, SEEK_SET);
+ fprintf(fp, " in ");
+ fflush(fp);
+ assert_stream("foo in ");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream("foo in bar");
+
+ rewind(fp);
+ if (fread(&c, sizeof(c), 1, fp) != 0)
+ printf("fread did not fail\n");
+ else if (!ferror(fp))
+ printf("error indicator not set after fread\n");
+ else
+ clearerr(fp);
+
+ fseek(fp, 4, SEEK_SET);
+ fprintf(fp, "bar baz");
+ fclose(fp);
+ assert_stream("foo bar baz");
+ free(buf);
+}
+
+T_DECL(freebsd_open_memstream_seek_tests, "")
+{
+ FILE *fp;
+
+ fp = open_memstream(&buf, &len);
+ T_ASSERT_NOTNULL(fp, "open_memstream failed: %d", errno);
+
+#define SEEK_FAIL(offset, whence, error) do { \
+ errno = 0; \
+ T_ASSERT_NE(fseeko(fp, (offset), (whence)), 0, \
+ "fseeko(%s, %s) did not fail, set pos to %jd", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp)); \
+ T_ASSERT_EQ(errno, (error), \
+ "fseeko(%s, %s) failed with %d rather than %s", \
+ __STRING(offset), __STRING(whence), errno, \
+ __STRING(error)); \
+} while (0)
+
+#define SEEK_OK(offset, whence, result) do { \
+ T_ASSERT_EQ(fseeko(fp, (offset), (whence)), 0, \
+ "fseeko(%s, %s) failed: %s", \
+ __STRING(offset), __STRING(whence), strerror(errno)); \
+ T_ASSERT_EQ(ftello(fp), (off_t)(result), \
+ "fseeko(%s, %s) seeked to %jd rather than %s", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp), __STRING(result)); \
+} while (0)
+
+ SEEK_FAIL(-1, SEEK_SET, EINVAL);
+ SEEK_FAIL(-1, SEEK_CUR, EINVAL);
+ SEEK_FAIL(-1, SEEK_END, EINVAL);
+ fprintf(fp, "foo");
+ SEEK_OK(-1, SEEK_CUR, 2);
+ SEEK_OK(0, SEEK_SET, 0);
+ SEEK_OK(-1, SEEK_END, 2);
+ SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
+ SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
+ fclose(fp);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2013 Hudson River Trading 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.
+ */
+
+#include <sys/cdefs.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <darwintest.h>
+
+static wchar_t *buf;
+static size_t len;
+
+static void
+assert_stream(const wchar_t *contents)
+{
+ if (wcslen(contents) != len)
+ printf("bad length %zd for \"%ls\"\n", len, contents);
+ else if (wcsncmp(buf, contents, wcslen(contents)) != 0)
+ printf("bad buffer \"%ls\" for \"%ls\"\n", buf, contents);
+}
+
+T_DECL(freebsd_open_wmemstream_open_group_test, "")
+{
+ FILE *fp;
+ off_t eob;
+
+ fp = open_wmemstream(&buf, &len);
+ T_ASSERT_NOTNULL(fp, "open_wmemstream failed");
+
+ fwprintf(fp, L"hello my world");
+ fflush(fp);
+ assert_stream(L"hello my world");
+ eob = ftello(fp);
+ rewind(fp);
+ fwprintf(fp, L"good-bye");
+ fseeko(fp, eob, SEEK_SET);
+ fclose(fp);
+ assert_stream(L"good-bye world");
+ free(buf);
+}
+
+T_DECL(freebsd_open_wmemstream_simple_tests, "")
+{
+ static const wchar_t zerobuf[] =
+ { L'f', L'o', L'o', 0, 0, 0, 0, L'b', L'a', L'r', 0 };
+ wchar_t c;
+ FILE *fp;
+
+ fp = open_wmemstream(&buf, NULL);
+ T_ASSERT_NULL(fp, "open_wmemstream did not fail");
+ T_ASSERT_EQ(errno, EINVAL, "open_wmemstream didn't fail with EINVAL");
+ fp = open_wmemstream(NULL, &len);
+ T_ASSERT_NULL(fp, "open_wmemstream did not fail");
+ T_ASSERT_EQ(errno, EINVAL, "open_wmemstream didn't fail with EINVAL");
+ fp = open_wmemstream(&buf, &len);
+ T_ASSERT_NOTNULL(fp, "open_memstream failed, errno=%d", errno);
+ fflush(fp);
+ assert_stream(L"");
+ if (fwide(fp, 0) <= 0)
+ printf("stream is not wide-oriented\n");
+
+ fwprintf(fp, L"fo");
+ fflush(fp);
+ assert_stream(L"fo");
+ fputwc(L'o', fp);
+ fflush(fp);
+ assert_stream(L"foo");
+ rewind(fp);
+ fflush(fp);
+ assert_stream(L"");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream(L"foo");
+
+ /*
+ * Test seeking out past the current end. Should zero-fill the
+ * intermediate area.
+ */
+ fseek(fp, 4, SEEK_END);
+ fwprintf(fp, L"bar");
+ fflush(fp);
+
+ /*
+ * Can't use assert_stream() here since this should contain
+ * embedded null characters.
+ */
+ if (len != 10)
+ printf("bad length %zd for zero-fill test\n", len);
+ else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0)
+ printf("bad buffer for zero-fill test\n");
+
+ fseek(fp, 3, SEEK_SET);
+ fwprintf(fp, L" in ");
+ fflush(fp);
+ assert_stream(L"foo in ");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream(L"foo in bar");
+
+ rewind(fp);
+ if (fread(&c, sizeof(c), 1, fp) != 0)
+ printf("fread did not fail\n");
+ else if (!ferror(fp))
+ printf("error indicator not set after fread\n");
+ else
+ clearerr(fp);
+
+ fseek(fp, 4, SEEK_SET);
+ fwprintf(fp, L"bar baz");
+ fclose(fp);
+ assert_stream(L"foo bar baz");
+ free(buf);
+}
+
+T_DECL(freebsd_open_wmemstream_seek_tests, "")
+{
+ FILE *fp;
+
+ fp = open_wmemstream(&buf, &len);
+ T_ASSERT_NOTNULL(fp, "open_wmemstream failed, errno=%d", errno);
+
+#define SEEK_FAIL(offset, whence, error) do { \
+ errno = 0; \
+ T_ASSERT_NE(fseeko(fp, (offset), (whence)), 0, \
+ "fseeko(%s, %s) did not fail, set pos to %jd", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp)); \
+ T_ASSERT_EQ(errno, (error), \
+ "fseeko(%s, %s) failed with %d rather than %s", \
+ __STRING(offset), __STRING(whence), errno, \
+ __STRING(error)); \
+} while (0)
+
+#define SEEK_OK(offset, whence, result) do { \
+ T_ASSERT_EQ(fseeko(fp, (offset), (whence)), 0, \
+ "fseeko(%s, %s) failed: %s", \
+ __STRING(offset), __STRING(whence), strerror(errno)); \
+ T_ASSERT_EQ(ftello(fp), (off_t)(result), \
+ "fseeko(%s, %s) seeked to %jd rather than %s", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp), __STRING(result)); \
+} while (0)
+
+ SEEK_FAIL(-1, SEEK_SET, EINVAL);
+ SEEK_FAIL(-1, SEEK_CUR, EINVAL);
+ SEEK_FAIL(-1, SEEK_END, EINVAL);
+ fwprintf(fp, L"foo");
+ SEEK_OK(-1, SEEK_CUR, 2);
+ SEEK_OK(0, SEEK_SET, 0);
+ SEEK_OK(-1, SEEK_END, 2);
+ SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
+ SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
+ fclose(fp);
+}
--- /dev/null
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@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.
+ */
+
+/*
+ * Test for qsort() routine.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <darwintest.h>
+
+#include "freebsd_qsort.h"
+
+T_DECL(qsort, "qsort sanity check")
+{
+ int testvector[IVEC_LEN];
+ int sresvector[IVEC_LEN];
+ size_t i, j;
+
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++) {
+ testvector[i] = sresvector[i] = initvector[i];
+ }
+
+ /* Sort using qsort(3) */
+ qsort(testvector, j, sizeof(testvector[0]), sorthelp);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, (int)j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++){
+ T_QUIET;
+ T_EXPECT_EQ(testvector[i], sresvector[i],
+ "item at index %zd should match", i);
+ }
+ }
+}
+
+T_DECL(qsort_b, "qsort_b sanity check")
+{
+ int testvector[IVEC_LEN];
+ int sresvector[IVEC_LEN];
+ size_t i, j;
+
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++) {
+ testvector[i] = sresvector[i] = initvector[i];
+ }
+
+ /* Sort using qsort(3) */
+ qsort_b(testvector, j, sizeof(testvector[0]), sorthelp_b);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, (int)j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++){
+ T_QUIET;
+ T_EXPECT_EQ(testvector[i], sresvector[i],
+ "item at index %zd should match", i);
+ }
+ }
+}
--- /dev/null
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@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$
+ */
+
+#ifndef _TEST_SORT_H
+#define _TEST_SORT_H
+
+#include <sys/param.h>
+
+#define nitems(x) (sizeof((x)) / sizeof((x)[0]))
+
+static int
+sorthelp(const void *a, const void *b)
+{
+ const int *oa, *ob;
+
+ oa = a;
+ ob = b;
+ /* Don't use "return *oa - *ob" since it's easy to cause overflow! */
+ if (*oa > *ob)
+ return (1);
+ if (*oa < *ob)
+ return (-1);
+ return (0);
+}
+
+static int
+szsorthelp(void *sz, const void *a, const void *b)
+{
+ size_t elmsz = (size_t)sz;
+ return memcmp(a, b, elmsz);
+}
+
+static int (^sorthelp_b)(const void *a, const void *b) =
+ ^(const void *a, const void *b){
+ const int *oa, *ob;
+
+ oa = a;
+ ob = b;
+ /* Don't use "return *oa - *ob" since it's easy to cause overflow! */
+ if (*oa > *ob)
+ return (1);
+ if (*oa < *ob)
+ return (-1);
+ return (0);
+};
+
+/* Reference sorting routine (slooow!) */
+static void
+ssort(int v[], int nmemb)
+{
+ int i, j, k;
+
+ for (i = 0; i < nmemb; i++) {
+ for (j = i + 1; j < nmemb; j++) {
+ if (v[j] < v[i]) {
+ k = v[i];
+ v[i] = v[j];
+ v[j] = k;
+ }
+ }
+ }
+}
+
+/* with element size */
+static void
+szsort(char v[], size_t nmemb, size_t sz)
+{
+ size_t i, j;
+ char temp[sz];
+
+ for (i = 0; i < nmemb; i++) {
+ for (j = i + 1; j < nmemb; j++) {
+ if (memcmp(v + (j * sz), v + (i * sz), sz) < 0) {
+ memcpy(temp, v + (i * sz), sz);
+ memcpy(v + (i * sz), v + (j * sz), sz);
+ memcpy(v + (j * sz), temp, sz);
+ }
+ }
+ }
+}
+
+/* Some random data */
+static int initvector[1024] = {
+ 599853225, 371951333, -428880425, 1450668530, 85530178, -460170550,
+ -270680269, 717137591, 106244401, -1138072905, -113532586,
+ 599690958, 464993720, 107690177, 24249019, -1151018550, 794225588,
+ 1494905642, -62951716, -734531757, 1197251494, 1020063925,
+ -634536734, -216634704, 617366508, -18840190, 481010395,
+ -1555785724, 128221950, -1747743676, 1119012320, -252160437,
+ 617137855, 1159833073, -106647920, -1570719046, -769400990,
+ -130308848, 1186546396, 215253591, 445832488, 160263176, 777264170,
+ -274636650, -696134447, 1057957088, -626175254, 188632134,
+ -98941793, -1602334908, -373717125, 885013862, 571258221,
+ -399572192, 407761463, -733249776, 12094800, -367046815, 178974501,
+ -452638559, -516580143, -94282073, 1411115180, -1151792797,
+ 1442815268, 1106583674, 515269284, -74019972, 598818901, 696848474,
+ -657910766, -287309335, 1538095746, 143543003, 851444033,
+ -947573348, 296222973, 1339592140, -947505360, 872027891,
+ -418844714, -583075597, -324758197, -964531573, 1016795914,
+ -866842580, -304084402, -286930819, 338975583, 803597943,
+ -452483372, 1525283506, -1185830826, -596405894, 905191340,
+ -1638026278, 106749913, 582771197, -730713796, 56052422,
+ 1498040174, 644967266, 182541575, 280483468, -1932835017,
+ -435546874, 940106007, 1753388509, -340355019, -231577358,
+ -714879035, 1051182949, 204261785, 1321346243, -895289878,
+ -240369893, 566608506, -350777580, -1384849829, -876816409,
+ 1013787299, -1408035937, -222626650, 1708168486, -645148461,
+ 1854654, -393012507, 179327030, -1607975548, -715202732, 730588290,
+ 246968517, -550975254, -101136772, -174103176, 1188941016,
+ 2004650834, -1501389866, -2021225998, 1219042515, -464113898,
+ 268565342, 126451123, -1045877126, -198918003, 310177444,
+ 1578314812, 1828867082, 453336898, -908485523, 749777130,
+ -1028565802, 61360571, 241484853, -175693399, 1816211059,
+ 533940889, -1496933703, 385185125, -821132413, -8923391,
+ -1429546239, 46190992, 449247332, -20432494, 778761611, -178782699,
+ -811194695, -632276211, 70196094, 890817525, -1447776908,
+ -323783741, -62333222, 954929503, 247668507, -1394420605,
+ 367913886, 1364926759, 1298781924, 357923028, -73644747,
+ -319744305, 61718202, -1454549286, 387493522, 2018321449,
+ 861026653, 289973298, 1755939093, -84772204, 43425266, -1325753781,
+ -679938775, 1228500370, -763816405, 548903035, 1765563727,
+ 425183052, 1424621863, -188287424, 554385654, 751831998,
+ 1377088085, 66622090, 139224450, -1305816167, 650140724, 593988868,
+ -444913321, 589045097, 1261428989, 101292769, -780376786,
+ 559307348, 1644593236, -1838606833, 53570301, -680576100,
+ -44969538, 268718267, -632104125, 276904628, 626299449, -11761453,
+ 545899086, -1027343598, -432251872, 539353494, -399575006,
+ -568383580, -677802882, 1296513472, 801202048, 806425805, 1983363,
+ 850487421, 38046173, 1535399484, 1998285544, -1301751898,
+ -46561973, 56545408, -1107662676, 456041145, -452923904,
+ -262219453, -371849200, 392524281, 1650231392, 1185585356,
+ 126610511, -1125389657, 1015981177, -1318481342, -213835789,
+ 1263484054, -654361441, 1408272041, -231555284, -1121778152,
+ -395512897, 332277674, -349703586, 1809474399, -223731607,
+ -1342224737, 736165236, 67535587, 89879082, 471445838, 423788300,
+ -384354470, 907475706, 154886390, -1406736539, -8558766,
+ -203405718, -422127884, 1048520863, 747418501, 87438975, 727668160,
+ -914936981, 428266976, -455742009, -949014605, 487159058,
+ -262526850, -309451504, -76928461, 1072951428, -1370953830,
+ 238231681, -1831047244, -405735199, -35941848, 469048670,
+ 505307987, -660553590, 876537439, -314195871, 999234339,
+ -1405846240, -579885695, 629067031, 863481510, -742301385,
+ -1723403128, -153070386, 782682839, -343111818, -877101810,
+ 1438467302, -319951459, -1585702508, -338381888, 484108815,
+ -1726935191, -749923706, 1657932127, -816151395, -566321865,
+ -133542331, 84961164, 598275578, 1302065347, -533098653,
+ -1766383037, 53169714, -464201288, 617735133, 862536123,
+ -141730724, -1967377125, -1023736305, -1012511106, 64484992,
+ -1250856831, 426409332, -355670055, -298251663, -867634978,
+ -776124819, 74018333, -425385214, -108004251, -1192766130,
+ 1294193867, -109867195, -78667637, 1164855393, -826007552,
+ -522528066, 1160283046, -1095276403, -1218917472, -396475366,
+ -77394733, -425603169, 251928357, -393559355, 1488845184,
+ 898455978, -773338691, -37627855, -345014717, 204298578, 209084274,
+ 1047080643, -414348222, 26496664, 705759824, 575149152, 604904761,
+ 624988690, 1446041250, 1000757225, -1354896151, 1422958189,
+ -1607165311, -832757521, 365074225, 1171764999, 1200795217,
+ -203957828, 23166236, -846818698, -547439867, -790192498,
+ -122123561, 914298013, 66225525, -36163174, -480698856,
+ -1269421818, 624641703, 254923102, 1564329013, -583609221,
+ -649433551, -743396069, 1182455435, 102658744, 285599336,
+ 692480463, -852737563, -660090184, 1374350065, 72300985, 690541659,
+ -1194212957, -1151816525, 157415641, 487398246, 1030153072,
+ 933723020, 1359181027, -1303457764, -1543773272, 774306017,
+ -854382652, 755485667, -864943584, -63242545, -1271480354,
+ 157720215, -205001173, 889984130, -581583822, -473779111,
+ -932136577, 735326252, 428638717, 1888884222, 561493709,
+ -1966427364, -1710208603, 340121869, 918894036, 927172509,
+ 904178436, 1476687667, 90796414, 651591731, -550913123, -42218158,
+ 637756529, 1091478400, 124976584, -48739309, -798898083, 393581349,
+ -1078624722, -789291577, 1010582542, -512317005, 1222773656,
+ 466454593, 1183558811, 822782663, -851624703, -850404012,
+ 1473672600, 852527073, 1073953362, 137635828, 936104739, -86567759,
+ -882563252, 1845232980, -737978404, -104703380, 149802989,
+ -349118325, 1479797538, 1966007488, 1254228842, 414304661,
+ -790805785, 31583329, -76864151, 558202855, -1447047313, 716720607,
+ -404224238, -54107627, 1747385914, -657407390, 202940208,
+ 1083067056, -532861378, 163426933, -130289277, 1301785258,
+ -302920320, -637947485, -644895903, -1668027530, 391890467,
+ -126586485, -536836984, -1154536413, -339505118, -1187229462,
+ -670985870, -601310813, -1350055158, -482479784, 139847714,
+ -253955849, 5190414, -542857077, 1175835684, -584165057,
+ 1132775766, -592091269, -891445655, -340995936, 736395810,
+ 779967964, 515095845, -1138437307, -259226729, -167820100,
+ -801611617, -282451622, -1313679283, -1436126694, 1258773990,
+ -717601098, -583559645, -1307478759, 1238647247, 1589011223,
+ -1029216445, -107030650, 400152690, -1349079913, 1428582247,
+ 21546946, 208807686, -169450574, -1086213374, -1242715198,
+ 669098277, 416626722, -1122525014, -1389466669, -391843085,
+ -56318357, 421040094, 212303518, 738666684, -1185364904,
+ -506192760, 646735912, -1424722633, 745226976, 1019191717,
+ -190891744, -310320868, -373655022, -665117060, 830760000,
+ 583906512, -330536027, 611092636, -321344259, -1255008904,
+ -777959046, -523043472, 88896910, 346062204, -163734816, 336635665,
+ 906060268, -128891583, 740952564, 916767203, 296514859, 198670559,
+ 358136672, -152253676, 12038867, -1469916749, -1020980597,
+ -897143313, 354240970, -97959800, 814172811, 1983363241, 264990663,
+ 105154676, 1060463014, 430172143, 375111946, -824526943,
+ -708877751, -1377442616, -236559551, 684724584, 1602131358,
+ -42140186, -763499840, -605167, 98575879, -376577598, 1689746083,
+ -777973879, -1396984691, -187780326, 281040966, 1858859521,
+ 158395760, 1022807978, -218458812, 811779708, 1495113833,
+ 1192561226, 629539535, -1365196683, -1120253162, 1091681956,
+ 134286445, 1172218369, -34093658, -137087343, -27869226,
+ -180889478, 55705436, 52362743, -1745516232, -926564477,
+ -513701675, -1666272054, 1457952810, 843953275, -478275722,
+ -1240291080, 101859661, -1606687523, 916365333, 314713310,
+ -22002688, 1019022641, -1171741314, -129050627, -211955813,
+ -1020176299, 1357865293, -609819628, 724533854, -1141449545,
+ 22285231, -97731145, -302329687, 191910894, -1300709885,
+ -644951895, 640448036, -1289009824, 1445456129, 846416471,
+ 1821291740, -1639640821, -712724532, -447475807, 132156847,
+ 258067455, 324301319, 278586969, -1544082357, 636007277, 977122066,
+ 127462480, 365126129, 1086276825, -432124148, 896598926,
+ -388550179, 273357331, -845018695, -1089465389, 384439820,
+ -558419772, 1476422025, 730712769, 190665059, -764968927,
+ -789708218, 637873581, 348429858, 1386000168, -638123594,
+ -842010345, -607926448, 19535163, -742771490, -18323344, 246155488,
+ 350409468, 1290907730, -492566468, 300358636, 501876267, 252441807,
+ 1233551975, -1431067042, 517177374, -1540299707, -948380761,
+ 1253997663, 693795998, 148707823, 152894502, 98729538, -30042824,
+ -563057441, 723726409, 367338961, 1395435261, 217868876,
+ 1220652431, 953572083, -1134905155, -734486813, -587470130,
+ -864647866, 1030737023, 781798521, -321076732, -460548153,
+ 122681678, -873728847, -1286304399, -75472885, 113390881,
+ -1556849198, -1070802176, 924389470, 957478910, 5974049, 709413506,
+ 476334647, 572869787, 776298405, -8822420, -99326499, -707855342,
+ -1187216303, 668038414, 262454769, -1120293198, -32011040,
+ 249812104, -101835410, 1082281087, -570183855, -954535179,
+ 1384361473, -983199686, 2017611313, 328926483, -878162849,
+ -1202254181, -225604951, 966898955, 247213529, -1257544612,
+ -197005970, -1039902730, -1947925142, 1752780907, -313410699,
+ -464474556, 416580338, -1063356643, -292212702, 57509168,
+ 1034124629, 1059212593, 468522867, 845369497, 1872717306,
+ -1216544764, -1419907623, 1376869956, -66585488, -1590974467,
+ -367070705, -1456529060, 791844031, 336217635, -1106832215,
+ 1476739427, -751018210, -1411671555, -1880387375, -1714242595,
+ 1169006474, -479442380, -892267555, -1471250266, -267888858,
+ 808634418, 1324777189, -585449929, 1127186951, 468768901,
+ -2002989138, -52352849, 186493053, 1258464606, 117157186,
+ 445919258, 908401949, -1112221136, 863904453, -942718649,
+ 796754809, -38943966, -781978872, -56814078, 1273857459,
+ -1781920832, 209979504, 811828269, -1150814437, 850061883,
+ -532968763, 252506408, -885025629, 391567580, -1295702482,
+ 574894420, 1462248349, 1622584325, -88443443, -1122006092,
+ -169758578, 456282338, -443233309, 436693483, -956563815,
+ -480221349, 435252860, -1114099391, 1060053979, -470893945,
+ -1273682879, -734596176, 639950927, -1278648701, 306274747,
+ -410562146, 1137869228, -1970746553, 1313830798, 1248071822,
+ -247297704, 1015218053, -1607348116, -261817613, -821413148,
+ -782942639, -628711083, 240953091, -629550668, -1584736319,
+ 856616893, -186759752, 197905373, 541638393, 603407919, -278480495,
+ 410077039, 544065371, -1509627427, 402918436, -450463799,
+ -131169308, 249920630, 1079548609, -927911828, 1444577689,
+ -353002528, -224292462, 1247795279, -790844631, -40427503,
+ 59829765, -332587567, 1319862109, -1261340753, 121711726,
+ 1342756342, -643495787, 100326201, -934436714, -69134888,
+ -898880561, -379524737, -577234570, -805827092, -1575493557,
+ -289920678, -476605057, 1235714994, -317239591, 418553949,
+ 410053338, -204985448, 1206503615, 202610372, -932244873,
+ 782207875, -288661931, -806814809, 1270953679, 2060991595,
+ -311412846, 327279979, 1148562672, 55239149, -610114433,
+ -1511688434, 87619740, -433503545, 326150519, -581293393,
+ -97417688, -289736140, -1543886029, -1251976119, 1585774446,
+ 1570011421, 432602745, 486343696, -834680922, 265004849,
+ -1132107706, 502627197, -815873818, 249635389, 1985714127,
+ -1095817653, -130743522, -645266828, -334621094, 199921747,
+ 1059256177, 378031303, 1519740920, 925540689, 1405957844,
+ 1387748290, -56138046, -770637828, -187984510, -1361735163,
+ 1294823206, -608941238, 451860688, -510549867, 1143516283,
+ -779090703, 1459305047, -600335915, -1684168049, 1516622316,
+ -631733335, -4360068, 499778796, 587600402, -1296000335, -37959743,
+ -1084203927, 1162902556, 246374600, -515103645, 341724568,
+ -702303954, 452229900, 485108287, 1170048553, -1510148355,
+ 611133912, 1997927484, -142022671, -724776653, -336090522,
+ 708283514, -1409637378, -2052637687, 376055110, 226628105,
+ -1714452033, -1776158002, 369167930, 1800807012, 710680889,
+ -69951947, -1223849766, -1862239787, 218536127, -656411794,
+ -1202269188, 609634805, -224425858, 519797951, 284223080,
+ 869408930, 270750206, -544967439, 2097168510, 31650971, -600985417,
+ -165303097, -257809088, -1043223971, 1827891621, -156827355,
+ 499719603
+};
+
+#define IVEC_LEN (nitems(initvector))
+
+#endif
int fts_find_main(int argc, char *argv[]);
+#ifndef DARWINTEST
static char *
stat_str(struct stat *st)
{
st->st_blocks, st->st_blksize, st->st_flags, st->st_gen);
return charbuf;
}
+#endif // DARWINTEST
int
fts_find_main(int argc, char *argv[])
bool print_children = false;
int fts_options = FTS_COMFOLLOW | FTS_XDEV;
+ optind = 1;
+ optreset = 1;
int ch;
while ((ch = getopt(argc, argv, "lpcdsS")) != -1){
printf("%s (%s): 0x%x\n", ftse->fts_path, ftse->fts_name, ftse->fts_info);
if (!(fts_options & (FTS_NOSTAT|FTS_NOSTAT_TYPE))) printf("\t\t%s\n", stat_str(ftse->fts_statp));
}
-#endif
+#endif // DARWINTEST
if (print_children){
FTSENT *child = fts_children(fts, 0);
while (child){
printf("\t%s (%s): 0x%x\n", child->fts_path, child->fts_name, child->fts_info);
if (!(fts_options & (FTS_NOSTAT|FTS_NOSTAT_TYPE))) printf("\t\t%s\n", stat_str(child->fts_statp));
}
-#endif
+#endif // DARWINTEST
child = child->fts_link;
}
}
T_FAIL("fts_find() exited with error");
}
}
-#endif
+
+T_DECL(fts_find_empty_path, "Test result for empty path"){
+ char *paths[] = {"/System", "", NULL};
+
+ FTS *fts = fts_open_b(paths, 0, ^(const FTSENT **a, const FTSENT **b){
+ return strcmp((*a)->fts_name, (*b)->fts_name);
+ });
+ if (fts == NULL) {
+ T_FAIL("fts_open() failed");
+ return;
+ }
+
+ // The first entry name should be the empty string, because of the sort
+ // order. The second entry should be "System".
+ FTSENT *entry = fts_read(fts);
+ T_ASSERT_NOTNULL(entry, "First fts_read() returned NULL");
+ T_ASSERT_EQ_STR(entry->fts_name, "", "First entry name is empty");
+ T_ASSERT_EQ((int)entry->fts_info, FTS_NS, "First fts_info is FTS_NS");
+ T_ASSERT_EQ(entry->fts_errno, ENOENT, "First fts_errno is ENOENT");
+
+ entry = fts_read(fts);
+ T_ASSERT_NOTNULL(entry, "Second fts_read() returned NULL");
+ T_ASSERT_EQ_STR(entry->fts_name, "System", "Second entry name is System");
+ T_ASSERT_EQ((int)entry->fts_info, FTS_D, "Second fts_info is FTS_D");
+ T_ASSERT_EQ(entry->fts_errno, 0, "Second fts_errno is 0");
+
+ fts_close(fts);
+}
+#endif // DARWINTEST
#include <darwintest.h>
-T_DECL(PR_23679075, "converts a cyrillic a to uppercase")
+T_DECL(locale_PR_23679075, "converts a cyrillic a to uppercase")
{
locale_t loc = newlocale(LC_COLLATE_MASK|LC_CTYPE_MASK, "ru_RU", 0);
T_ASSERT_NOTNULL(loc, "newlocale(LC_COLLATE_MASK|LC_CTYPE_MASK, \"ru_RU\", 0) should return a locale");
freelocale(loc);
}
-T_DECL(PR_24165555, "swprintf with Russian chars")
+T_DECL(locale_PR_24165555, "swprintf with Russian chars")
{
setlocale(LC_ALL, "ru_RU.UTF-8");
setlocale(LC_ALL, "");
}
+
+T_DECL(locale_PR_28774201, "return code on bad locale")
+{
+ T_EXPECT_NULL(newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, "foobar", NULL), NULL);
+ T_EXPECT_EQ(errno, ENOENT, NULL);
+}
static void test_mkostemp(int oflags);
-T_DECL(test_mkstemp, "basic mkstemp test")
+T_DECL(mkstemp, "basic mkstemp test")
{
char path[sizeof(template)];
struct stat path_stat;
"close must succeed for the second fd");
}
-T_DECL(test_mktemp, "basic mktemp test")
+T_DECL(mktemp, "basic mktemp test")
{
char path[sizeof(template)];
template, path);
}
-T_DECL(test_mkdtemp, "basic mkdtemp test")
+T_DECL(mkdtemp, "basic mkdtemp test")
{
char path[sizeof(template)];
struct stat dstat;
// always does T_SKIP on OS X yields another issue. The compiler starts
// demanding to mark the test function definition as noreturn. Just
// don't compile the testcase for OS X.
-T_DECL(test_mkstemp_dprotected_np, "basic mkstemp_dprotected_np test")
+T_DECL(mkstemp_dprotected_np, "basic mkstemp_dprotected_np test")
{
char path[sizeof(template)];
int fd;
T_DECL(inet_ntop, "inet_ntop")
{
char *addresses4[] = { "1.2.3.4", "10.0.0.1", "2.2.2.2" };
- char *addresses6[] = {
- "2001:db8:85a3::8a2e:370:7334",
- "::1", "::"
- };
+ char *addresses6[] = { "2001:db8:85a3::8a2e:370:7334", "::1", "::" };
for (int i = 0; i < sizeof(addresses4)/sizeof(addresses4[0]); i++){
struct in_addr addr4;
char buf[64];
char buf[64];
T_EXPECT_EQ(inet_pton(AF_INET6, addresses6[i], &addr6), 1, "inet_pton(AF_INET6, %s)", addresses6[i]);
char *str = inet_ntop(AF_INET6, &addr6, buf, sizeof(buf));
- T_EXPECT_NOTNULL(str, "inet_ntop(AF_INET) of %s", addresses6[i]);
+ T_EXPECT_NOTNULL(str, "inet_ntop(AF_INET6) of %s", addresses6[i]);
T_EXPECT_EQ_STR(str, addresses6[i], "round-trip of %s", addresses6[i]);
}
}
+
+struct testcase {
+ const char *in_addr;
+ const char *expected_out_addr;
+};
+
+static const struct testcase test_addrs[] = {
+ { "1:2:3:4:5::1.2.3.4", "1:2:3:4:5:0:102:304" },
+ { "1:0:3:0:5:0:7:8", "1:0:3:0:5:0:7:8" },
+ { "0:0:3:0:0:0:7:8", "0:0:3::7:8" },
+ { "0:0:3:0:5:0:7:8", "::3:0:5:0:7:8" },
+ { "0:0:0:0:0:0:0:0", "::" },
+ { "0:0:0:0:0:1:0:0", "::1:0:0" },
+ { "1:0:0:0:0:0:0:0", "1::" },
+ { "0:0:0:1:0:0:0:0", "0:0:0:1::" },
+ { "1:0:0:0:0:0:0:1", "1::1" },
+ { "1:2:3:4:5:6:0:0", "1:2:3:4:5:6::" },
+ { "1:2:3:4:5:0:0:0", "1:2:3:4:5::" },
+};
+
+T_DECL(inet_ntop_resolve_zeroes, "Check for proper behavior when shortening zeroes w/ inet_ntop")
+{
+ // Take ip addrs as text, convert to binary and back.
+ // Upon converting back, they should adhere to the IPv6 guidelines.
+ for (int i = 0; i < sizeof(test_addrs)/sizeof(struct testcase); ++i) {
+ struct in6_addr addr6;
+ char buf[64];
+ char *in_addr = test_addrs[i].in_addr;
+ char *expected_out_addr = test_addrs[i].expected_out_addr;
+ T_EXPECT_EQ(inet_pton(AF_INET6, in_addr, &addr6), 1, "inet_pton(AF_INET6, %s)", in_addr);
+ char *str = inet_ntop(AF_INET6, &addr6, buf, sizeof(buf));
+ T_EXPECT_NOTNULL(str, "inet_ntop(AF_INET6) of %s", in_addr);
+ // <rdar://problem/32825795> Single-zero tests will fail until change
+ // implemented.
+ if (i < 2) {
+ T_EXPECTFAIL;
+ }
+ T_EXPECT_EQ_STR(str, expected_out_addr, NULL);
+ }
+
+ // Same test, but step through the possible range of ipv6 values.
+ for (int i = 0x0; i < 0x10000; ++i) {
+ struct in6_addr addr6;
+ char buf[64];
+ char in_addr[64];
+ sprintf(in_addr, "1:1:1:1:1:1:1:%x", i);
+ char *expected_out_addr = in_addr;
+ T_QUIET;
+ T_EXPECT_EQ(inet_pton(AF_INET6, in_addr, &addr6), 1, "inet_pton(AF_INET6, %s)", in_addr);
+ char *str = inet_ntop(AF_INET6, &addr6, buf, sizeof(buf));
+ T_QUIET;
+ T_EXPECT_NOTNULL(str, "inet_ntop(AF_INET6) of %s", in_addr);
+ T_QUIET;
+ // <rdar://problem/32825795>
+ if (i == 0) {
+ T_PASS("Never displayed"); // Cancel out the T_QUIET
+ T_EXPECTFAIL;
+ }
+ T_EXPECT_EQ_STR(str, expected_out_addr, NULL);
+ }
+ T_PASS("Passed ipv6 value testing");
+
+}
--- /dev/null
+/* $NetBSD: t_fmemopen.c,v 1.4 2013/10/19 17:45:00 christos Exp $ */
+
+/*-
+ * Copyright (c)2010 Takehiko NOZAKI,
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <darwintest.h>
+
+static const char *mode_rwa[] = {
+ "r", "rb", "r+", "rb+", "r+b",
+ "w", "wb", "w+", "wb+", "w+b",
+ "a", "ab", "a+", "ab+", "a+b",
+ NULL
+};
+
+static const char *mode_r[] = { "r", "rb", "r+", "rb+", "r+b", NULL };
+static const char *mode_w[] = { "w", "wb", "w+", "wb+", "w+b", NULL };
+static const char *mode_a[] = { "a", "ab", "a+", "ab+", "a+b", NULL };
+
+static struct testcase {
+ const char *s;
+ off_t n;
+} testcases[] = {
+#define TESTSTR(s) { s, sizeof(s)-1 }
+ TESTSTR("\0he quick brown fox jumps over the lazy dog"),
+ TESTSTR("T\0e quick brown fox jumps over the lazy dog"),
+ TESTSTR("Th\0 quick brown fox jumps over the lazy dog"),
+ TESTSTR("The\0quick brown fox jumps over the lazy dog"),
+ TESTSTR("The \0uick brown fox jumps over the lazy dog"),
+ TESTSTR("The q\0ick brown fox jumps over the lazy dog"),
+ TESTSTR("The qu\0ck brown fox jumps over the lazy dog"),
+ TESTSTR("The qui\0k brown fox jumps over the lazy dog"),
+ TESTSTR("The quic\0 brown fox jumps over the lazy dog"),
+ TESTSTR("The quick\0brown fox jumps over the lazy dog"),
+ TESTSTR("The quick \0rown fox jumps over the lazy dog"),
+ TESTSTR("The quick b\0own fox jumps over the lazy dog"),
+ TESTSTR("The quick br\0wn fox jumps over the lazy dog"),
+ TESTSTR("The quick bro\0n fox jumps over the lazy dog"),
+ TESTSTR("The quick brow\0 fox jumps over the lazy dog"),
+ TESTSTR("The quick brown\0fox jumps over the lazy dog"),
+ TESTSTR("The quick brown \0ox jumps over the lazy dog"),
+ TESTSTR("The quick brown f\0x jumps over the lazy dog"),
+ TESTSTR("The quick brown fo\0 jumps over the lazy dog"),
+ TESTSTR("The quick brown fox\0jumps over the lazy dog"),
+ TESTSTR("The quick brown fox \0umps over the lazy dog"),
+ TESTSTR("The quick brown fox j\0mps over the lazy dog"),
+ TESTSTR("The quick brown fox ju\0ps over the lazy dog"),
+ TESTSTR("The quick brown fox jum\0s over the lazy dog"),
+ TESTSTR("The quick brown fox jump\0 over the lazy dog"),
+ TESTSTR("The quick brown fox jumps\0over the lazy dog"),
+ TESTSTR("The quick brown fox jumps \0ver the lazy dog"),
+ TESTSTR("The quick brown fox jumps o\0er the lazy dog"),
+ TESTSTR("The quick brown fox jumps ov\0r the lazy dog"),
+ TESTSTR("The quick brown fox jumps ove\0 the lazy dog"),
+ TESTSTR("The quick brown fox jumps over\0the lazy dog"),
+ TESTSTR("The quick brown fox jumps over \0he lazy dog"),
+ TESTSTR("The quick brown fox jumps over t\0e lazy dog"),
+ TESTSTR("The quick brown fox jumps over th\0 lazy dog"),
+ TESTSTR("The quick brown fox jumps over the\0lazy dog"),
+ TESTSTR("The quick brown fox jumps over the \0azy dog"),
+ TESTSTR("The quick brown fox jumps over the l\0zy dog"),
+ TESTSTR("The quick brown fox jumps over the la\0y dog"),
+ TESTSTR("The quick brown fox jumps over the laz\0 dog"),
+ TESTSTR("The quick brown fox jumps over the lazy\0dog"),
+ TESTSTR("The quick brown fox jumps over the lazy \0og"),
+ TESTSTR("The quick brown fox jumps over the lazy d\0g"),
+ TESTSTR("The quick brown fox jumps over the lazy do\0"),
+ TESTSTR("The quick brown fox jumps over the lazy dog"),
+ { NULL, 0 },
+};
+
+T_DECL(netbsd_fmemopen_test00, "")
+{
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (p = &mode_rwa[0]; *p != NULL; ++p) {
+ fp = fmemopen(&buf[0], sizeof(buf), *p);
+/*
+ * Upon successful completion, fmemopen() shall return a pointer to the
+ * object controlling the stream.
+ */
+ T_EXPECT_NOTNULL(fp, NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+}
+
+T_DECL(netbsd_fmemopen_test01, "")
+{
+ const char **p;
+ const char *mode[] = {
+ "r+", "rb+", "r+b",
+ "w+", "wb+", "w+b",
+ "a+", "ab+", "a+b",
+ NULL
+ };
+ FILE *fp;
+
+ for (p = &mode[0]; *p != NULL; ++p) {
+/*
+ * If a null pointer is specified as the buf argument, fmemopen() shall
+ * allocate size bytes of memory as if by a call to malloc().
+ */
+ fp = fmemopen(NULL, BUFSIZ, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+
+/*
+ * If buf is a null pointer, the initial position shall always be set
+ * to the beginning of the buffer.
+ */
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+}
+
+T_DECL(netbsd_fmemopen_test02, "")
+{
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (p = &mode_r[0]; *p != NULL; ++p) {
+
+ memset(&buf[0], 0x1, sizeof(buf));
+ fp = fmemopen(&buf[0], sizeof(buf), *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+
+/*
+ * This position is initially set to either the beginning of the buffer
+ * (for r and w modes)
+ */
+ T_EXPECT_EQ((unsigned char)buf[0], 0x1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+/*
+ * The stream also maintains the size of the current buffer contents.
+ * For modes r and r+ the size is set to the value given by the size argument.
+ */
+#if !defined(__GLIBC__)
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)sizeof(buf), NULL);
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+}
+
+T_DECL(netbsd_fmemopen_test03, "")
+{
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (p = &mode_w[0]; *p != NULL; ++p) {
+
+ memset(&buf[0], 0x1, sizeof(buf));
+ fp = fmemopen(&buf[0], sizeof(buf), *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+
+/*
+ * This position is initially set to either the beginning of the buffer
+ * (for r and w modes)
+ */
+ T_EXPECT_EQ(buf[0], '\0', NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+/*
+ * For modes w and w+ the initial size is zero
+ */
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+}
+
+T_DECL(netbsd_fmemopen_test04, "")
+{
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+/*
+ * or to the first null byte in the buffer (for a modes)
+ */
+ for (p = &mode_a[0]; *p != NULL; ++p) {
+
+ memset(&buf[0], 0x1, sizeof(buf));
+ fp = fmemopen(&buf[0], sizeof(buf), *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+
+ T_EXPECT_EQ((unsigned char)buf[0], 0x1, NULL);
+
+/* If no null byte is found in append mode,
+ * the initial position is set to one byte after the end of the buffer.
+ */
+#if !defined(__GLIBC__)
+ T_EXPECT_EQ(ftello(fp), (off_t)sizeof(buf), NULL);
+#endif
+
+/*
+ * and for modes a and a+ the initial size is either the position of the
+ * first null byte in the buffer or the value of the size argument
+ * if no null byte is found.
+ */
+#if !defined(__GLIBC__)
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)sizeof(buf), NULL);
+#endif
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+}
+
+T_DECL(netbsd_fmemopen_test05, "")
+{
+ const char **p;
+ FILE *fp;
+ char buf[BUFSIZ];
+
+ for (p = &mode_rwa[0]; *p != NULL; ++p) {
+/*
+ * Otherwise, a null pointer shall be returned, and errno shall be set
+ * to indicate the error.
+ */
+ errno = 0;
+ fp = fmemopen(NULL, (size_t)0, *p);
+ T_EXPECT_NULL(fp, NULL);
+ T_EXPECT_EQ(errno, EINVAL, NULL);
+
+ errno = 0;
+ fp = fmemopen((void *)&buf[0], 0, *p);
+ T_EXPECT_NULL(fp, NULL);
+ T_EXPECT_EQ(errno, EINVAL, NULL);
+ }
+}
+
+T_DECL(netbsd_fmemopen_test06, "")
+{
+ const char **p;
+ const char *mode[] = { "", " ", "???", NULL };
+ FILE *fp;
+
+ for (p = &mode[0]; *p != NULL; ++p) {
+/*
+ * The value of the mode argument is not valid.
+ */
+ fp = fmemopen(NULL, 1, *p);
+ T_EXPECT_NULL(fp, NULL);
+ T_EXPECT_EQ(errno, EINVAL, NULL);
+ }
+}
+
+T_DECL(netbsd_fmemopen_test07, "")
+{
+#if !defined(__GLIBC__)
+ const char **p;
+ const char *mode[] = {
+ "r", "rb",
+ "w", "wb",
+ "a", "ab",
+ NULL
+ };
+ FILE *fp;
+
+ for (p = &mode[0]; *p != NULL; ++p) {
+/*
+ * Because this feature is only useful when the stream is opened for updating
+ * (because there is no way to get a pointer to the buffer) the fmemopen()
+ * call may fail if the mode argument does not include a '+' .
+ */
+ errno = 0;
+ fp = fmemopen(NULL, 1, *p);
+ T_EXPECT_NULL(fp, NULL);
+ T_EXPECT_EQ(errno, EINVAL, NULL);
+ }
+#endif
+}
+
+T_DECL(netbsd_fmemopen_test08, "")
+{
+#if !defined(__GLIBC__)
+ const char **p;
+ const char *mode[] = {
+ "r+", "rb+", "r+b",
+ "w+", "wb+", "w+b",
+ "a+", "ab+", "a+b",
+ NULL
+ };
+ FILE *fp;
+
+ for (p = &mode[0]; *p != NULL; ++p) {
+/*
+ * The buf argument is a null pointer and the allocation of a buffer of
+ * length size has failed.
+ */
+ fp = fmemopen(NULL, SIZE_MAX, *p);
+ T_EXPECT_NULL(fp, NULL);
+ T_EXPECT_EQ(errno, ENOMEM, NULL);
+ }
+#endif
+}
+
+/*
+ * test09 - test14:
+ * An attempt to seek a memory buffer stream to a negative position or to a
+ * position larger than the buffer size given in the size argument shall fail.
+ */
+
+T_DECL(netbsd_fmemopen_test09, "")
+{
+ struct testcase *t;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+ off_t i;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ for (p = &mode_rwa[0]; *p != NULL; ++p) {
+
+ memcpy(&buf[0], t->s, t->n);
+ fp = fmemopen(&buf[0], (size_t)t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+
+/*
+ * test fmemopen_seek(SEEK_SET)
+ */
+ /* zero */
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_SET), NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ /* positive */
+ for (i = (off_t)1; i <= (off_t)t->n; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, i, SEEK_SET), NULL);
+ T_EXPECT_EQ(ftello(fp), i, NULL);
+ }
+ /* positive + OOB */
+ T_EXPECT_EQ(fseeko(fp, t->n + 1, SEEK_SET), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), t->n, NULL);
+
+ /* negative + OOB */
+ T_EXPECT_EQ(fseeko(fp, (off_t)-1, SEEK_SET), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), t->n, NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+static const char *mode_rw[] = {
+ "r", "rb", "r+", "rb+", "r+b",
+ "w", "wb", "w+", "wb+", "w+b",
+ NULL
+};
+
+T_DECL(netbsd_fmemopen_test10, "")
+{
+ struct testcase *t;
+ off_t i;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ for (p = &mode_rw[0]; *p != NULL; ++p) {
+
+ memcpy(&buf[0], t->s, t->n);
+ fp = fmemopen(&buf[0], (size_t)t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+
+/*
+ * test fmemopen_seek(SEEK_CUR)
+ */
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ /* zero */
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_CUR), NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ /* negative & OOB */
+ T_EXPECT_EQ(fseeko(fp, (off_t)-1, SEEK_CUR), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ /* positive */
+ for (i = 0; i < (off_t)t->n; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)1, SEEK_CUR), NULL);
+ T_EXPECT_EQ(ftello(fp), i + 1, NULL);
+ }
+
+ /* positive & OOB */
+ T_EXPECT_EQ(fseeko(fp, (off_t)1, SEEK_CUR), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+T_DECL(netbsd_fmemopen_test11, "")
+{
+ struct testcase *t;
+ off_t len, rest, i;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ /* test fmemopen_seek(SEEK_CUR) */
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ len = (off_t)strnlen(t->s, (size_t)t->n);
+ rest = (off_t)t->n - len;
+ for (p = &mode_a[0]; *p != NULL; ++p) {
+
+ memcpy(&buf[0], t->s, t->n);
+ fp = fmemopen(&buf[0], (size_t)t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+/*
+ * test fmemopen_seek(SEEK_CUR)
+ */
+#if defined(__GLIBC__)
+ if (i < (off_t)t->n) {
+#endif
+ /* zero */
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_CUR), NULL);
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+ /* posive */
+ for (i = (off_t)1; i <= rest; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)1, SEEK_CUR), NULL);
+ T_EXPECT_EQ(ftello(fp), len + i, NULL);
+ }
+
+ /* positive + OOB */
+ T_EXPECT_EQ(fseeko(fp, (off_t)1, SEEK_CUR), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+
+ /* negative */
+ for (i = (off_t)1; i <= (off_t)t->n; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)-1, SEEK_CUR), NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n - i, NULL);
+ }
+
+ /* negative + OOB */
+ T_EXPECT_EQ(fseeko(fp, (off_t)-1, SEEK_CUR), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+#if defined(__GLIBC__)
+ }
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+#if 0
+T_DECL(netbsd_fmemopen_test12, "")
+{
+ struct testcase *t;
+ off_t len, rest, i;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ /* test fmemopen_seek(SEEK_END) */
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ len = (off_t)strnlen(t->s, t->n);
+ rest = t->n - len;
+ for (p = &mode_r[0]; *p != NULL; ++p) {
+
+ memcpy(buf, t->s, t->n);
+ fp = fmemopen(&buf[0], t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+
+/*
+ * test fmemopen_seek(SEEK_END)
+ */
+#if !defined(__GLIBC__)
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ /* zero */
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+ /* positive + OOB */
+ T_EXPECT_EQ(fseeko(fp, rest + 1, SEEK_END), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+ /* negative + OOB */
+ T_EXPECT_EQ(fseeko(fp, -(len + 1), SEEK_END), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+ /* positive */
+ for (i = 1; i <= rest; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, i, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), len + i, NULL);
+ }
+
+ /* negative */
+ for (i = 1; i < len; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, -i, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), len - i, NULL);
+ }
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+#endif // 0
+
+T_DECL(netbsd_fmemopen_test13, "")
+{
+ struct testcase *t;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ /* test fmemopen_seek(SEEK_END) */
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ for (p = &mode_w[0]; *p != NULL; ++p) {
+
+ memcpy(buf, t->s, t->n);
+ fp = fmemopen(&buf[0], (size_t)t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+/*
+ * test fmemopen_seek(SEEK_END)
+ */
+#if !defined(__GLIBC__)
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+ T_EXPECT_EQ(buf[0], '\0', NULL);
+
+ /* zero */
+ T_EXPECT_POSIX_ZERO(fseeko(fp, (off_t)0, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ /* positive + OOB */
+ T_EXPECT_EQ(fseeko(fp, (off_t)t->n + 1, SEEK_END), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+
+ /* negative + OOB */
+ T_EXPECT_EQ(fseeko(fp, -1, SEEK_END), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+#endif
+
+#if 0
+ /* positive */
+ for (int i = 1; i <= t->n; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, i, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), i, NULL);
+ }
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+T_DECL(netbsd_fmemopen_test14, "")
+{
+ struct testcase *t;
+ off_t len, rest, i;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ /* test fmemopen_seek(SEEK_END) */
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ len = (off_t)strnlen(t->s, (size_t)t->n);
+ rest = (off_t)t->n - len;
+ for (p = &mode_a[0]; *p != NULL; ++p) {
+
+ memcpy(buf, t->s, t->n);
+ fp = fmemopen(&buf[0], (size_t)t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+/*
+ * test fmemopen_seek(SEEK_END)
+ */
+#if !defined(__GLIBC__)
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+ /* zero */
+ T_EXPECT_POSIX_ZERO(fseeko(fp, 0, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+ /* positive + OOB */
+ T_EXPECT_EQ(fseeko(fp, rest + 1, SEEK_END), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+ /* negative + OOB */
+ T_EXPECT_EQ(fseeko(fp, -(len + 1), SEEK_END), -1, NULL);
+ T_EXPECT_EQ(ftello(fp), len, NULL);
+
+#if 0
+ /* positive */
+ for (i = 1; i <= rest; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, i, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), len + i, NULL);
+ }
+#endif
+
+ /* negative */
+ for (i = 1; i < len; ++i) {
+ T_EXPECT_POSIX_ZERO(fseeko(fp, -i, SEEK_END), NULL);
+ T_EXPECT_EQ(ftello(fp), len - i, NULL);
+ }
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+#if 0
+
+static const char *mode_rw1[] = {
+ "r", "rb", "r+", "rb+", "r+b",
+ "w+", "wb+",
+ NULL
+};
+
+/* test15 - 18:
+ * When a stream open for writing is flushed or closed, a null byte is written
+ * at the current position or at the end of the buffer, depending on the size
+ * of the contents.
+ */
+
+T_DECL(netbsd_fmemopen_test15, "")
+{
+ struct testcase *t;
+ const char **p;
+ char buf0[BUFSIZ];
+ FILE *fp;
+ int i;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ for (p = &mode_rw1[0]; *p != NULL; ++p) {
+
+ memcpy(&buf0[0], t->s, t->n);
+ fp = fmemopen(&buf0[0], t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+/*
+ * test fmemopen_read + fgetc(3)
+ */
+ for (i = 0; i < t->n; ++i) {
+ T_EXPECT_EQ(ftello(fp), (off_t)i, NULL);
+ T_EXPECT_EQ(fgetc(fp), buf0[i], NULL);
+ T_EXPECT_EQ(feof(fp), 0, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)i + 1, NULL);
+ }
+ T_EXPECT_EQ(fgetc(fp), EOF, NULL);
+ T_EXPECT_NE(feof(fp), 0, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+T_DECL(netbsd_fmemopen_test16, "")
+{
+ struct testcase *t;
+ const char **p;
+ char buf0[BUFSIZ], buf1[BUFSIZ];
+ FILE *fp;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ for (p = &mode_rw1[0]; *p != NULL; ++p) {
+
+ memcpy(&buf0[0], t->s, t->n);
+ buf1[t->n] = 0x1;
+ fp = fmemopen(&buf0[0], t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+/*
+ * test fmemopen_read + fread(4)
+ */
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+ T_EXPECT_EQ(fread(&buf1[0], 1, sizeof(buf1), fp), (size_t)t->n, NULL);
+ T_EXPECT_NE(feof(fp), 0, NULL);
+ T_EXPECT_EQ(memcmp(&buf0[0], &buf1[0], t->n), 0, NULL);
+ T_EXPECT_EQ((unsigned char)buf1[t->n], 0x1, NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+const char *mode_a1[] = { "a+", "ab+", NULL };
+
+T_DECL(netbsd_fmemopen_test17, "")
+{
+ struct testcase *t;
+ size_t len;
+ int i;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ len = strnlen(t->s, t->n);
+ for (p = &mode_a1[0]; *p != NULL; ++p) {
+
+ memcpy(&buf[0], t->s, t->n);
+ fp = fmemopen(&buf[0], t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+/*
+ * test fmemopen_read + fgetc(3)
+ */
+#if defined(__GLIBC__)
+ if (i < t->n) {
+#endif
+ for (i = len; i < t->n; ++i) {
+ T_EXPECT_EQ(ftello(fp), (off_t)i, NULL);
+ T_EXPECT_EQ(fgetc(fp), buf[i], NULL);
+ T_EXPECT_EQ(feof(fp), 0, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)i + 1, NULL);
+ }
+ T_EXPECT_EQ(fgetc(fp), EOF, NULL);
+ T_EXPECT_NE(feof(fp), 0, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+ rewind(fp);
+ for (i = 0; i < t->n; ++i) {
+ T_EXPECT_EQ(ftello(fp), (off_t)i, NULL);
+ T_EXPECT_EQ(fgetc(fp), buf[i], NULL);
+ T_EXPECT_EQ(feof(fp), 0, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)i + 1, NULL);
+ }
+ T_EXPECT_EQ(fgetc(fp), EOF, NULL);
+ T_EXPECT_NE(feof(fp), 0, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+#if defined(__GLIBC__)
+ }
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+T_DECL(netbsd_fmemopen_test18, "")
+{
+ struct testcase *t;
+ size_t len;
+ const char **p;
+ char buf0[BUFSIZ], buf1[BUFSIZ];
+ FILE *fp;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ len = strnlen(t->s, t->n);
+ for (p = &mode_a1[0]; *p != NULL; ++p) {
+
+ memcpy(&buf0[0], t->s, t->n);
+ buf1[t->n - len] = 0x1;
+ fp = fmemopen(&buf0[0], t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+/*
+ * test fmemopen_read + fread(3)
+ */
+#if defined(__GLIBC__)
+ if (i < t->n) {
+#endif
+ T_EXPECT_EQ(ftello(fp), (off_t)len, NULL);
+ T_EXPECT_EQ(fread(&buf1[0], 1, sizeof(buf1), fp)
+ , t->n - len, NULL);
+ T_EXPECT_NE(feof(fp), 0, NULL);
+ T_EXPECT_FALSE(memcmp(&buf0[len], &buf1[0], t->n - len));
+ T_EXPECT_EQ((unsigned char)buf1[t->n - len], 0x1, NULL);
+ rewind(fp);
+ buf1[t->n] = 0x1;
+ T_EXPECT_EQ(ftello(fp), (off_t)0, NULL);
+ T_EXPECT_EQ(fread(&buf1[0], 1, sizeof(buf1), fp)
+ , (size_t)t->n, NULL);
+ T_EXPECT_NE(feof(fp), 0, NULL);
+ T_EXPECT_FALSE(memcmp(&buf0[0], &buf1[0], t->n));
+ T_EXPECT_EQ((unsigned char)buf1[t->n], 0x1, NULL);
+#if defined(__GLIBC__)
+ }
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+/*
+ * test19 - test22:
+ * If a stream open for update is flushed or closed and the last write has
+ * advanced the current buffer size, a null byte is written at the end of the
+ * buffer if it fits.
+ */
+
+const char *mode_rw2[] = {
+ "r+", "rb+", "r+b",
+ "w", "wb", "w+", "wb+", "w+b",
+ NULL
+};
+
+T_DECL(netbsd_fmemopen_test19, "")
+{
+ struct testcase *t;
+ int i;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ for (p = &mode_rw2[0]; *p != NULL; ++p) {
+
+ memcpy(&buf[0], t->s, t->n);
+ buf[t->n] = 0x1;
+ fp = fmemopen(&buf[0], t->n + 1, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+ setbuf(fp, NULL);
+/*
+ * test fmemopen_write + fputc(3)
+ */
+ for (i = 0; i < t->n; ++i) {
+ T_EXPECT_EQ(ftello(fp), (off_t)i, NULL);
+ T_EXPECT_EQ(fputc(t->s[i], fp), t->s[i], NULL);
+ T_EXPECT_EQ(buf[i], t->s[i], NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)i + 1, NULL);
+ T_EXPECT_EQ(buf[i], t->s[i], NULL);
+#if !defined(__GLIBC__)
+ T_EXPECT_EQ(buf[i + 1], '\0', NULL);
+#endif
+ }
+
+/* don't accept non nul character at end of buffer */
+ T_EXPECT_EQ(fputc(0x1, fp), EOF, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+ T_EXPECT_EQ(feof(fp), 0, NULL);
+
+/* accept nul character at end of buffer */
+ T_EXPECT_EQ(fputc('\0', fp), '\0', NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n + 1, NULL);
+ T_EXPECT_EQ(feof(fp), 0, NULL);
+
+/* reach EOF */
+ T_EXPECT_EQ(fputc('\0', fp), EOF, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n + 1, NULL);
+
+ /* compare */
+ T_EXPECT_EQ(memcmp(&buf[0], t->s, t->n), 0, NULL);
+ T_EXPECT_EQ(buf[t->n], '\0', NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+T_DECL(netbsd_fmemopen_test20, "")
+{
+ struct testcase *t;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ for (p = &mode_rw2[0]; *p != NULL; ++p) {
+
+ memcpy(&buf[0], t->s, t->n);
+ buf[t->n] = 0x1;
+ fp = fmemopen(&buf[0], t->n + 1, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+ setbuf(fp, NULL);
+ T_EXPECT_EQ(fwrite(t->s, 1, t->n, fp), (size_t)t->n, NULL);
+/*
+ * test fmemopen_write + fwrite(3)
+ */
+#if !defined(__GLIBC__)
+ T_EXPECT_EQ(buf[t->n], '\0', NULL);
+
+/* don't accept non nul character at end of buffer */
+ T_EXPECT_EQ(fwrite("\x1", 1, 1, fp), 0, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+ T_EXPECT_EQ(feof(fp), 0, NULL);
+#endif
+
+/* accept nul character at end of buffer */
+ T_EXPECT_EQ(fwrite("\x0", 1, 1, fp), 1, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n + 1, NULL);
+ T_EXPECT_EQ(feof(fp), 0, NULL);
+
+/* reach EOF */
+ T_EXPECT_EQ(fputc('\0', fp), EOF, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n + 1, NULL);
+
+/* compare */
+ T_EXPECT_EQ(memcmp(&buf[0], t->s, t->n), 0, NULL);
+ T_EXPECT_EQ(buf[t->n], '\0', NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+T_DECL(netbsd_fmemopen_test21, "")
+{
+ struct testcase *t;
+ int len, i;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (t = &testcases[0]; t->s != NULL; ++t) {
+ len = strnlen(t->s, t->n);
+ for (p = &mode_a[0]; *p != NULL; ++p) {
+ memcpy(&buf[0], t->s, t->n);
+ fp = fmemopen(&buf[0], t->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+ setbuf(fp, NULL);
+/*
+ * test fmemopen_write + fputc(3)
+ */
+ if (len < t->n) {
+ for (i = len; i < t->n - 1; ++i) {
+ T_EXPECT_EQ(ftello(fp), (off_t)i, NULL);
+ T_EXPECT_EQ(fputc(t->s[i - len], fp)
+ , t->s[i - len], NULL);
+ T_EXPECT_EQ(buf[i], t->s[i - len], NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)i + 1, NULL);
+#if !defined(__GLIBC__)
+ T_EXPECT_EQ(buf[i + 1], '\0', NULL);
+#endif
+ }
+
+/* don't accept non nul character at end of buffer */
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n - 1, NULL);
+ T_EXPECT_EQ(fputc(0x1, fp), EOF, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n - 1, NULL);
+
+/* accept nul character at end of buffer */
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n - 1, NULL);
+ T_EXPECT_EQ(fputc('\0', fp), '\0', NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+ }
+
+/* reach EOF */
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+ T_EXPECT_EQ(fputc('\0', fp), EOF, NULL);
+ T_EXPECT_EQ(ftello(fp), (off_t)t->n, NULL);
+
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+}
+
+T_DECL(netbsd_fmemopen_test22, "")
+{
+ struct testcase *t0, *t1;
+ size_t len0, len1, nleft;
+ const char **p;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ for (t0 = &testcases[0]; t0->s != NULL; ++t0) {
+ len0 = strnlen(t0->s, t0->n);
+ for (t1 = &testcases[0]; t1->s != NULL; ++t1) {
+ len1 = strnlen(t1->s, t1->n);
+ for (p = &mode_a[0]; *p != NULL; ++p) {
+
+ memcpy(&buf[0], t0->s, t0->n);
+ fp = fmemopen(&buf[0], t0->n, *p);
+ T_EXPECT_NOTNULL(fp, NULL);
+ setbuf(fp, NULL);
+/*
+ * test fmemopen_write + fwrite(3)
+ */
+ nleft = t0->n - len0;
+#if !defined(__GLIBC__)
+ if (nleft == 0 || len1 == nleft - 1) {
+ T_EXPECT_EQ(fwrite(t1->s, 1, t1->n, fp)
+ , nleft, NULL);
+ T_EXPECT_EQ(ftell(fp), t1->n, NULL);
+ } else {
+ T_EXPECT_EQ(fwrite(t1->s, 1, t1->n, fp)
+ , nleft - 1, NULL);
+ T_EXPECT_EQ(ftell(fp), t1->n - 1, NULL);
+ }
+#endif
+ T_EXPECT_POSIX_ZERO(fclose(fp), NULL);
+ }
+ }
+ }
+}
+#endif //0
T_PASS("setenv_thread() completed successfully");
}
-T_DECL(unsetenv_thread, "Test unsetenv(3) with threads")
+T_DECL(unsetenv_thread, "Test unsetenv(3) with threads",
+ T_META_ENVVAR("MallocStackLogging=lite"))
{
pthread_t threads[THREADED_NUM_THREADS];
time_t endtime = time(NULL) + THREADED_RUN_TIME;
--- /dev/null
+/* $NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos Exp $ */
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas
+ *
+ * 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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>
+__RCSID("$NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos Exp $");
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <glob.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <darwintest.h>
+
+#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0]))
+
+#ifdef DEBUG
+#define DPRINTF(a) printf a
+#else
+#define DPRINTF(a)
+#endif
+
+struct gl_file {
+ const char *name;
+ int dir;
+};
+
+static struct gl_file a[] = {
+ { "1", 0 },
+ { "b", 1 },
+ { "3", 0 },
+ { "4", 0 },
+};
+
+static struct gl_file b[] = {
+ { "x", 0 },
+ { "y", 0 },
+ { "z", 0 },
+ { "w", 0 },
+};
+
+struct gl_dir {
+ const char *name; /* directory name */
+ const struct gl_file *dir;
+ size_t len, pos;
+};
+
+static struct gl_dir d[] = {
+ { "a", a, __arraycount(a), 0 },
+ { "a/b", b, __arraycount(b), 0 },
+};
+
+#ifdef GLOB_STAR
+static const char *glob_star[] = {
+ "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z",
+};
+#endif
+
+static const char *glob_star_not[] = {
+ "a/1", "a/3", "a/4", "a/b",
+};
+
+static void
+trim(char *buf, size_t len, const char *name)
+{
+ char *path = buf, *epath = buf + len;
+ while (path < epath && (*path++ = *name++) != '\0')
+ continue;
+ path--;
+ while (path > buf && *--path == '/')
+ *path = '\0';
+}
+
+static void *
+gl_opendir(const char *dir)
+{
+ size_t i;
+ char buf[MAXPATHLEN];
+ trim(buf, sizeof(buf), dir);
+
+ for (i = 0; i < __arraycount(d); i++)
+ if (strcmp(buf, d[i].name) == 0) {
+ DPRINTF(("opendir %s %zu\n", buf, i));
+ return &d[i];
+ }
+ errno = ENOENT;
+ return NULL;
+}
+
+static struct dirent *
+gl_readdir(void *v)
+{
+ static struct dirent dir;
+ struct gl_dir *dd = v;
+ if (dd->pos < dd->len) {
+ const struct gl_file *f = &dd->dir[dd->pos++];
+ strcpy(dir.d_name, f->name);
+ dir.d_namlen = (uint16_t)strlen(f->name);
+ dir.d_ino = dd->pos;
+ dir.d_type = f->dir ? DT_DIR : DT_REG;
+ DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type));
+#if defined(__FreeBSD__) || defined(__APPLE__)
+ dir.d_reclen = (uint16_t)-1; /* Does not have _DIRENT_RECLEN */
+#else
+ dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen);
+#endif
+ return &dir;
+ }
+ return NULL;
+}
+
+static int
+gl_stat(const char *name , struct stat *st)
+{
+ char buf[MAXPATHLEN];
+ trim(buf, sizeof(buf), name);
+ memset(st, 0, sizeof(*st));
+
+ if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) {
+ st->st_mode |= S_IFDIR;
+ return 0;
+ }
+
+ if (buf[0] == 'a' && buf[1] == '/') {
+ struct gl_file *f;
+ size_t offs, count;
+
+ if (buf[2] == 'b' && buf[3] == '/') {
+ offs = 4;
+ count = __arraycount(b);
+ f = b;
+ } else {
+ offs = 2;
+ count = __arraycount(a);
+ f = a;
+ }
+
+ for (size_t i = 0; i < count; i++)
+ if (strcmp(f[i].name, buf + offs) == 0)
+ return 0;
+ }
+ DPRINTF(("stat %s %d\n", buf, st->st_mode));
+ errno = ENOENT;
+ return -1;
+}
+
+static int
+gl_lstat(const char *name , struct stat *st)
+{
+ return gl_stat(name, st);
+}
+
+static void
+gl_closedir(void *v)
+{
+ struct gl_dir *dd = v;
+ dd->pos = 0;
+ DPRINTF(("closedir %p\n", dd));
+}
+
+static void
+run(const char *p, int flags, const char **res, size_t len)
+{
+ glob_t gl;
+ size_t i;
+
+ memset(&gl, 0, sizeof(gl));
+ gl.gl_opendir = gl_opendir;
+ gl.gl_readdir = gl_readdir;
+ gl.gl_closedir = gl_closedir;
+ gl.gl_stat = gl_stat;
+ gl.gl_lstat = gl_lstat;
+
+ T_ASSERT_POSIX_ZERO(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl), NULL);
+
+ for (i = 0; i < gl.gl_pathc; i++)
+ DPRINTF(("%s\n", gl.gl_pathv[i]));
+
+ T_EXPECT_EQ(len, gl.gl_pathc, NULL);
+ for (i = 0; i < gl.gl_pathc; i++)
+ T_EXPECT_EQ_STR(gl.gl_pathv[i], res[i], NULL);
+
+ globfree(&gl);
+}
+
+
+#ifdef GLOB_STAR
+T_DECL(glob_star, "Test glob(3) ** with GLOB_STAR")
+{
+ run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star));
+}
+#endif
+
+T_DECL(glob_star_not, "Test glob(3) ** without GLOB_STAR")
+{
+ run("a/**", 0, glob_star_not, __arraycount(glob_star_not));
+}
+
+#if 0
+/*
+ * Remove this test for now - the GLOB_NOCHECK return value has been
+ * re-defined to return a modified pattern in revision 1.33 of glob.c
+ *
+ * ATF_TP_ADD_TC(tp, glob_nocheck);
+ */
+T_DECL(glob_nocheck, "Test glob(3) pattern with backslash and GLOB_NOCHECK")
+{
+ static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a',
+ 'r', '\0' };
+ static const char *glob_nocheck[] = {
+ pattern
+ };
+ run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck));
+}
+#endif
--- /dev/null
+/*
+ * Based on the OpenBSD test
+ * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_open_memstream.c,v 1.2 2014/10/19 11:17:43 justin Exp $");
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <darwintest.h>
+
+#define OFFSET 16384
+
+static const char start[] = "start";
+static const char hello[] = "hello";
+
+T_DECL(netbsd_open_memstream_test_open_memstream, "")
+{
+ FILE *fp;
+ char *buf = (char *)0xff;
+ size_t size = 0;
+ off_t off;
+ int i;
+
+ fp = open_memstream(&buf, &size);
+ T_ASSERT_NOTNULL(fp, NULL);
+
+ off = ftello(fp);
+ T_EXPECT_EQ(off, 0LL, NULL);
+
+ T_EXPECT_POSIX_ZERO(fflush(fp), NULL);
+ T_EXPECT_EQ(size, 0UL, NULL);
+ T_EXPECT_NE((void*)buf, (void *)0xff, NULL);
+ T_EXPECT_EQ(fseek(fp, -6, SEEK_SET), -1, NULL);
+ T_EXPECT_POSIX_ZERO(fseek(fp, OFFSET, SEEK_SET), NULL);
+ T_EXPECT_NE(fprintf(fp, hello), EOF, NULL);
+ T_EXPECT_NE(fflush(fp), EOF, NULL);
+ T_EXPECT_EQ(size, OFFSET + sizeof(hello)-1, NULL);
+ T_EXPECT_POSIX_ZERO(fseek(fp, 0, SEEK_SET), NULL);
+ T_EXPECT_NE(fprintf(fp, start), EOF, NULL);
+ T_EXPECT_NE(fflush(fp), EOF, NULL);
+ T_EXPECT_EQ(size, sizeof(start)-1, NULL);
+
+ /* Needed for sparse files */
+ T_EXPECT_EQ(strncmp(buf, start, sizeof(start)-1), 0, NULL);
+ for (i = sizeof(start)-1; i < OFFSET; i++)
+ T_EXPECT_EQ(buf[i], '\0', NULL);
+
+ T_EXPECT_EQ(memcmp(buf + OFFSET, hello, sizeof(hello)-1), 0, NULL);
+
+ /* verify that simply seeking past the end doesn't increase the size */
+ T_EXPECT_POSIX_ZERO(fseek(fp, 100, SEEK_END), NULL);
+ T_EXPECT_NE(fflush(fp), EOF, NULL);
+ T_EXPECT_EQ(size, OFFSET + sizeof(hello)-1, NULL);
+ T_EXPECT_POSIX_ZERO(fseek(fp, 8, SEEK_SET), NULL);
+ T_EXPECT_EQ(ftell(fp), 8L, NULL);
+
+ /* Try to seek backward */
+ T_EXPECT_POSIX_ZERO(fseek(fp, -1, SEEK_CUR), NULL);
+ T_EXPECT_EQ(ftell(fp), 7L, NULL);
+ T_EXPECT_POSIX_ZERO(fseek(fp, 5, SEEK_CUR), NULL);
+ T_EXPECT_NE(fclose(fp), EOF, NULL);
+ T_EXPECT_EQ(size, 12UL, NULL);
+
+ free(buf);
+}
--- /dev/null
+/* $NetBSD: t_printf.c,v 1.8 2012/04/11 16:21:42 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include "darwintest.h"
+
+T_DECL(netbsd_snprintf_c99, "Test printf(3) C99 conformance (PR lib/22019)")
+{
+ char s[4];
+
+ (void)memset(s, '\0', sizeof(s));
+ (void)snprintf(s, sizeof(s), "%#.o", 0);
+ (void)printf("printf = %#.o\n", 0);
+ (void)fprintf(stderr, "snprintf = %s", s);
+
+ T_ASSERT_EQ(strlen(s), (size_t)1, NULL);
+ T_ASSERT_EQ(s[0], '0', NULL);
+}
+
+T_DECL(netbsd_snprintf_dotzero, "PR lib/32951: %%.0f formats (0.0,0.5] to \"0.\"")
+{
+ char s[4];
+
+ T_WITH_ERRNO; T_EXPECT_EQ(snprintf(s, sizeof(s), "%.0f", 0.1), 1, NULL);
+ T_EXPECT_EQ_STR(s, "0", NULL);
+}
+
+T_DECL(netbsd_snprintf_float, "test that floating conversions don't leak memory")
+{
+ union {
+ double d;
+ uint64_t bits;
+ } u;
+ uint32_t ul, uh;
+ time_t now;
+ char buf[1000];
+ struct rlimit rl;
+
+ rl.rlim_cur = rl.rlim_max = 1 * 1024 * 1024;
+ T_WITH_ERRNO; T_EXPECT_NE(setrlimit(RLIMIT_AS, &rl), -1, NULL);
+ rl.rlim_cur = rl.rlim_max = 1 * 1024 * 1024;
+ T_EXPECT_POSIX_SUCCESS(setrlimit(RLIMIT_DATA, &rl), NULL);
+
+ time(&now);
+ srand((unsigned int)now);
+ for (size_t i = 0; i < 10000; i++) {
+ ul = (uint32_t)rand();
+ uh = (uint32_t)rand();
+ u.bits = (uint64_t)uh << 32 | ul;
+ T_EXPECT_POSIX_SUCCESS(snprintf(buf, sizeof buf, " %.2f", u.d), NULL);
+ }
+}
+
+T_DECL(netbsd_sprintf_zeropad, "Test output format zero padding (PR lib/44113)")
+{
+ char str[1024];
+
+ T_WITH_ERRNO; T_EXPECT_EQ(sprintf(str, "%010f", 0.0), 10, NULL);
+ T_EXPECT_EQ_STR(str, "000.000000", NULL);
+
+ /* ieeefp */
+#ifndef __vax__
+ /* printf(3) should ignore zero padding for nan/inf */
+ T_WITH_ERRNO; T_EXPECT_EQ(sprintf(str, "%010f", NAN), 10, NULL);
+ T_EXPECT_EQ_STR(str, " nan", NULL);
+ T_WITH_ERRNO; T_EXPECT_EQ(sprintf(str, "%010f", INFINITY), 10, NULL);
+ T_EXPECT_EQ_STR(str, " inf", NULL);
+#endif
+}
atf_tc_set_md_var(tc, "descr", "Test errors from the stat(2) family");
}
-ATF_TC_BODY(stat_err, tc)
+T_DECL(stat_err, "")
{
char buf[NAME_MAX + 1];
struct stat st;
atf_tc_set_md_var(tc, "descr", "Test modification times with stat(2)");
}
-ATF_TC_BODY(stat_mtime, tc)
+T_DECL(stat_mtime, "")
{
struct stat sa, sb;
int fd[3];
fd[i] = open(path, O_WRONLY | O_CREAT);
- ATF_REQUIRE(fd[i] != -1);
- ATF_REQUIRE(write(fd[i], "X", 1) == 1);
- ATF_REQUIRE(stat(path, &sa) == 0);
+ T_ASSERT_POSIX_SUCCESS(fd[i], NULL);
+ T_ASSERT_EQ(write(fd[i], "X", 1), 1, NULL);
+ T_ASSERT_POSIX_ZERO(stat(path, &sa), NULL);
(void)sleep(1);
- ATF_REQUIRE(write(fd[i], "X", 1) == 1);
- ATF_REQUIRE(stat(path, &sb) == 0);
+ T_ASSERT_EQ(write(fd[i], "X", 1), 1, NULL);
+ T_ASSERT_POSIX_ZERO(stat(path, &sb), NULL);
- ATF_REQUIRE(close(fd[i]) == 0);
- ATF_REQUIRE(unlink(path) == 0);
+ T_ASSERT_POSIX_ZERO(close(fd[i]), NULL);
+ T_ASSERT_POSIX_ZERO(unlink(path), NULL);
if (sa.st_mtime == sb.st_mtime)
atf_tc_fail("mtimes did not change");
atf_tc_set_md_var(tc, "require.user", "root");
}
-ATF_TC_BODY(stat_perm, tc)
+T_DECL(stat_perm, "")
{
struct stat sa, sb;
gid_t gid;
fd = open(path, O_RDONLY | O_CREAT);
- ATF_REQUIRE(fd != -1);
- ATF_REQUIRE(fstat(fd, &sa) == 0);
- ATF_REQUIRE(stat(path, &sb) == 0);
+ T_ASSERT_POSIX_SUCCESS(fd, NULL);
+ T_ASSERT_POSIX_ZERO(fstat(fd, &sa), NULL);
+ T_ASSERT_POSIX_ZERO(stat(path, &sb), NULL);
if (gid != sa.st_gid || sa.st_gid != sb.st_gid)
atf_tc_fail("invalid GID");
if (uid != sa.st_uid || sa.st_uid != sb.st_uid)
atf_tc_fail("invalid UID");
- ATF_REQUIRE(close(fd) == 0);
- ATF_REQUIRE(unlink(path) == 0);
+ T_ASSERT_POSIX_ZERO(close(fd), NULL);
+ T_ASSERT_POSIX_ZERO(unlink(path), NULL);
}
ATF_TC_CLEANUP(stat_perm, tc)
atf_tc_set_md_var(tc, "descr", "Test file sizes with stat(2)");
}
-ATF_TC_BODY(stat_size, tc)
+T_DECL(stat_size, "")
{
struct stat sa, sb, sc;
const size_t n = 10;
(void)memset(&sb, 0, sizeof(struct stat));
(void)memset(&sc, 0, sizeof(struct stat));
- ATF_REQUIRE(fstat(fd, &sa) == 0);
- ATF_REQUIRE(write(fd, "X", 1) == 1);
- ATF_REQUIRE(fstat(fd, &sb) == 0);
- ATF_REQUIRE(stat(path, &sc) == 0);
+ T_ASSERT_POSIX_ZERO(fstat(fd, &sa), NULL);
+ T_ASSERT_EQ(write(fd, "X", 1), 1, NULL);
+ T_ASSERT_POSIX_ZERO(fstat(fd, &sb), NULL);
+ T_ASSERT_POSIX_ZERO(stat(path, &sc), NULL);
if (sa.st_size + 1 != sb.st_size)
atf_tc_fail("invalid file size");
atf_tc_fail("stat(2) and fstat(2) mismatch");
}
- ATF_REQUIRE(close(fd) == 0);
- ATF_REQUIRE(unlink(path) == 0);
+ T_ASSERT_POSIX_ZERO(close(fd), NULL);
+ T_ASSERT_POSIX_ZERO(unlink(path), NULL);
}
ATF_TC_CLEANUP(stat_size, tc)
"a socket (PR kern/46077)");
}
-ATF_TC_BODY(stat_socket, tc)
+T_DECL(stat_socket, "")
{
struct sockaddr_in addr;
struct stat st;
flags = fcntl(fd, F_GETFL);
- ATF_REQUIRE(flags != -1);
- ATF_REQUIRE(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1);
- ATF_REQUIRE(inet_pton(AF_INET, "127.0.0.1", &iaddr) == 1);
+ T_ASSERT_POSIX_SUCCESS(flags, NULL);
+ T_ASSERT_POSIX_SUCCESS(fcntl(fd, F_SETFL, flags | O_NONBLOCK), NULL);
+ T_ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &iaddr), 1, NULL);
addr.sin_port = htons(42);
addr.sin_family = AF_INET;
atf_tc_set_md_var(tc, "descr", "Test symbolic links with stat(2)");
}
-ATF_TC_BODY(stat_symlink, tc)
+T_DECL(stat_symlink, "")
{
const char *pathlink = "pathlink";
struct stat sa, sb;
fd = open(path, O_WRONLY | O_CREAT);
ATF_REQUIRE(fd >= 0);
- ATF_REQUIRE(symlink(path, pathlink) == 0);
- ATF_REQUIRE(stat(pathlink, &sa) == 0);
- ATF_REQUIRE(lstat(pathlink, &sb) == 0);
+ T_ASSERT_POSIX_ZERO(symlink(path, pathlink), NULL);
+ T_ASSERT_POSIX_ZERO(stat(pathlink, &sa), NULL);
+ T_ASSERT_POSIX_ZERO(lstat(pathlink, &sb), NULL);
if (S_ISLNK(sa.st_mode) != 0)
atf_tc_fail("stat(2) detected symbolic link");
if (sa.st_mode == sb.st_mode)
atf_tc_fail("inconsistencies between stat(2) and lstat(2)");
- ATF_REQUIRE(unlink(path) == 0);
- ATF_REQUIRE(unlink(pathlink) == 0);
+ T_ASSERT_POSIX_ZERO(unlink(path), NULL);
+ T_ASSERT_POSIX_ZERO(unlink(pathlink), NULL);
}
ATF_TC_CLEANUP(stat_symlink, tc)
--- /dev/null
+/* $NetBSD: t_strerror.c,v 1.3 2011/05/10 06:55:27 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_strerror.c,v 1.3 2011/05/10 06:55:27 jruoho Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "darwintest.h"
+
+T_DECL(netbsd_strerror_basic, "A basic test of strerror(3)")
+{
+ int i;
+
+ for (i = 1; i < sys_nerr; i++)
+ T_EXPECT_NULL(strstr(strerror(i), "Unknown error:"), NULL);
+
+ for (; i < sys_nerr + 10; i++)
+ T_EXPECT_NOTNULL(strstr(strerror(i), "Unknown error:"), NULL);
+}
+
+T_DECL(netbsd_strerror_err, "Test errors from strerror(3)")
+{
+ (void)setlocale(LC_ALL, "C");
+
+ errno = 0;
+
+ T_ASSERT_NOTNULL(strstr(strerror(INT_MAX), "Unknown error:"), NULL);
+ T_ASSERT_EQ(errno, EINVAL, NULL);
+
+ errno = 0;
+
+ T_ASSERT_NOTNULL(strstr(strerror(INT_MIN), "Unknown error:"), NULL);
+ T_ASSERT_EQ(errno, EINVAL, NULL);
+}
+
+T_DECL(netbsd_strerror_r_basic, "A basic test of strerror_r(3)")
+{
+ char buf[512];
+ int i;
+
+ (void)setlocale(LC_ALL, "C");
+
+ for (i = 1; i < sys_nerr; i++) {
+ T_ASSERT_EQ(strerror_r(i, buf, sizeof(buf)), 0, NULL);
+ T_ASSERT_NULL(strstr(buf, "Unknown error:"), NULL);
+ }
+
+ for (; i < sys_nerr + 10; i++) {
+ T_ASSERT_EQ(strerror_r(i, buf, sizeof(buf)), EINVAL, NULL);
+ T_ASSERT_NOTNULL(strstr(buf, "Unknown error:"), NULL);
+ }
+}
+
+T_DECL(netbsd_strerror_r_err, "Test errors from strerror_r(3)")
+{
+ char buf[512];
+ int rv;
+
+ (void)setlocale(LC_ALL, "C");
+
+ rv = strerror_r(EPERM, buf, 1);
+ T_ASSERT_EQ(rv, ERANGE, NULL);
+
+ rv = strerror_r(INT_MAX, buf, sizeof(buf));
+
+ T_ASSERT_EQ(rv, EINVAL, NULL);
+ T_ASSERT_NOTNULL(strstr(buf, "Unknown error:"), NULL);
+
+ rv = strerror_r(INT_MIN, buf, sizeof(buf));
+
+ T_ASSERT_EQ(rv, EINVAL, NULL);
+ T_ASSERT_NOTNULL(strstr(buf, "Unknown error:"), NULL);
+}
if (dstbuf[j] != (char)j)
T_FAIL("Failed for style %x, char %d [%d]", styles[i], j, dstbuf[j]);
if (dstbuf[SIZE] != '\0')
- T_FAIL("Failed for style %x, the result must be null-terminated [%d]", dstbuf[SIZE]);
+ T_FAIL("Failed for style %x, the result must be null-terminated [%d]", styles[i], dstbuf[SIZE]);
}
free(dstbuf);
free(srcbuf);
--- /dev/null
+#include <os/variant_private.h>
+
+#include <darwintest.h>
+
+/*
+ * Most of these are MAYFAIL because the test might sometimes run on non-internal devices.
+ */
+
+T_DECL(os_variant_basic, "Just calls all the APIs")
+{
+ T_MAYFAIL;
+ T_EXPECT_TRUE(os_variant_has_internal_content("com.apple.Libc.tests"), NULL);
+
+ T_MAYFAIL;
+ T_EXPECT_TRUE(os_variant_has_internal_diagnostics("com.apple.Libc.tests"), NULL);
+
+ T_MAYFAIL;
+ T_EXPECT_TRUE(os_variant_has_internal_ui("com.apple.Libc.tests"), NULL);
+
+ T_MAYFAIL;
+ T_EXPECT_TRUE(os_variant_allows_internal_security_policies("com.apple.Libc.tests"), NULL);
+}
+
+#define VARIANT_SKIP_EXPORTED
+
+#include "../libdarwin/variant.c"
+
+T_DECL(os_variant_detailed, "Looks at individual checks")
+{
+ T_MAYFAIL;
+ T_EXPECT_FALSE(_check_disabled(VP_ALL), NULL);
+
+ T_MAYFAIL;
+ T_EXPECT_FALSE(_check_disabled(VP_CONTENT), NULL);
+
+ T_MAYFAIL;
+ T_EXPECT_FALSE(_check_disabled(VP_DIAGNOSTICS), NULL);
+
+ T_MAYFAIL;
+ T_EXPECT_FALSE(_check_disabled(VP_UI), NULL);
+
+ T_MAYFAIL;
+ T_EXPECT_FALSE(_check_disabled(VP_SECURITY), NULL);
+
+#if !TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+ T_MAYFAIL;
+ T_EXPECT_TRUE(_check_internal_content(), NULL);
+#endif
+
+#if TARGET_OS_IPHONE
+ T_MAYFAIL;
+ T_EXPECT_TRUE(_check_internal_release_type(), NULL);
+#else
+ T_MAYFAIL;
+ T_EXPECT_FALSE(_check_internal_diags_profile(), NULL);
+#endif
+
+ T_MAYFAIL;
+ T_EXPECT_TRUE(_check_can_has_debugger(), NULL);
+}
+
+T_DECL(os_variant_override_parse, "Checks the parsing of the override file")
+{
+ // Warm up the dispatch_once
+ _check_disabled(VP_ALL);
+
+ T_LOG("Override: NULL"); // Live system
+ _parse_disabled_status(NULL);
+ T_MAYFAIL; T_EXPECT_FALSE(_check_disabled(VP_CONTENT), NULL);
+ T_MAYFAIL; T_EXPECT_FALSE(_check_disabled(VP_DIAGNOSTICS), NULL);
+ T_MAYFAIL; T_EXPECT_FALSE(_check_disabled(VP_UI), NULL);
+ T_MAYFAIL; T_EXPECT_FALSE(_check_disabled(VP_SECURITY), NULL);
+
+ T_LOG("Override: \"content\"");
+ _parse_disabled_status("content");
+ T_EXPECT_TRUE(_check_disabled(VP_CONTENT), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_DIAGNOSTICS), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_UI), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_SECURITY), NULL);
+
+ T_LOG("Override: \"ui\"");
+ _parse_disabled_status("ui");
+ T_EXPECT_FALSE(_check_disabled(VP_CONTENT), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_DIAGNOSTICS), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_UI), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_SECURITY), NULL);
+
+ T_LOG("Override: \"security,diagnostics\"");
+ _parse_disabled_status("security,diagnostics");
+ T_EXPECT_FALSE(_check_disabled(VP_CONTENT), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_DIAGNOSTICS), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_UI), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_SECURITY), NULL);
+
+ T_LOG("Override: \"content,diagnostics,ui,security\"");
+ _parse_disabled_status("content,diagnostics,ui,security");
+ T_EXPECT_TRUE(_check_disabled(VP_CONTENT), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_DIAGNOSTICS), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_UI), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_SECURITY), NULL);
+
+ T_LOG("Override: \"diagnostics\\n"); // Now check newline-handling.
+ _parse_disabled_status("diagnostics\n");
+ T_EXPECT_FALSE(_check_disabled(VP_CONTENT), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_DIAGNOSTICS), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_UI), NULL);
+ T_EXPECT_FALSE(_check_disabled(VP_SECURITY), NULL);
+
+ T_LOG("Override: \"content,diagnostics\\nui,security\\n\"");
+ _parse_disabled_status("content,diagnostics\nui,security\n");
+ T_EXPECT_TRUE(_check_disabled(VP_CONTENT), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_DIAGNOSTICS), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_UI), NULL);
+ T_EXPECT_TRUE(_check_disabled(VP_SECURITY), NULL);
+}
+
+T_DECL(os_status_cache, "Checks saving and restoring of state")
+{
+ uint64_t status = 0;
+ size_t status_size = sizeof(status);
+ int ret = sysctlbyname(CACHE_SYSCTL_NAME, &status, &status_size, NULL, 0);
+ T_EXPECT_POSIX_ZERO(ret, "sysctlbyname(kern.osvariant_status)");
+ T_EXPECT_GT(status, 0ULL, "Kernel's status has bits set");
+ T_EXPECT_EQ(status & STATUS_INITIAL_BITS, STATUS_INITIAL_BITS, "Kernel's status has initial bits set");
+
+ T_MAYFAIL;
+ T_EXPECT_TRUE(_check_can_has_debugger(), NULL);
+
+ status = _get_cached_check_status();
+ T_LOG("Cached status: %llx", status);
+
+ T_EXPECT_EQ(status & STATUS_INITIAL_BITS, STATUS_INITIAL_BITS, "Our status has initial bits set");
+
+ _restore_cached_check_status(status);
+
+ T_MAYFAIL;
+ T_EXPECT_TRUE(os_variant_allows_internal_security_policies(NULL), NULL);
+
+ status = STATUS_INITIAL_BITS |
+ (S_NO << (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH));
+ T_LOG("Restoring status without can_has_debugger: %llx", status);
+ _restore_cached_check_status(status);
+
+ T_EXPECT_FALSE(_check_can_has_debugger(), NULL);
+
+ // Trigger dispatch_once internally with known state
+ _check_disabled(VP_SECURITY);
+
+ status = STATUS_INITIAL_BITS |
+ (0x1ULL << (VP_SECURITY + 32));
+ T_LOG("Restoring status with override: %llx", status);
+ _restore_cached_check_status(status);
+
+ T_EXPECT_TRUE(_check_disabled(VP_SECURITY), NULL);
+}
--- /dev/null
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <os/assumes.h>
+
+#include "darwintest.h"
+#include "darwintest_utils.h"
+
+static void crash_callback(const char *str) {
+ T_PASS("Crashed with \"%s\"", str);
+ T_END;
+}
+
+T_DECL(sprintf_percent_n, "Test of %n")
+{
+ char str[1024];
+ int len, ret;
+
+ char *fmt = "%010d%n";
+
+ T_EXPECT_POSIX_SUCCESS((ret = snprintf(str, sizeof(str), fmt, 0, &len)), NULL);
+ T_EXPECT_EQ(len, ret, NULL);
+
+ char fmt_buf[32];
+ strlcpy(fmt_buf, fmt, sizeof(fmt_buf));
+
+ os_set_crash_callback(crash_callback);
+ snprintf(str, sizeof(str), fmt_buf, 0, &len);
+ T_ASSERT_FAIL("Should have crashed on dynamic %%n");
+}
+
+#if !TARGET_OS_IPHONE
+#define STRSIZE (1024 * 1024 * 256)
+
+T_DECL(printf_PR_30663523, "Test for PR-30663523",
+ T_META_CHECK_LEAKS(NO))
+{
+ char *temp_path;
+ asprintf(&temp_path, "%s/%s", dt_tmpdir(), "big_file");
+
+ {
+ char *x = calloc(1, 0x80000001);
+ memset(x, 0x41, 0x80000001);
+
+ FILE *f = fopen(temp_path, "w");
+ int len = fprintf(f, "%s", x);
+ T_EXPECT_EQ(len, EOF, "fprintf should return EOF when string is longer than INT_MAX");
+ fclose(f);
+ }
+
+ {
+ char *x = calloc(1, STRSIZE);
+ memset(x, 0x41, STRSIZE - 1);
+
+ FILE *f = fopen(temp_path, "w");
+ int len = fprintf(f, "%s%s%s%s%s%s%s%s%s%s", x,x,x,x,x,x,x,x,x,x);
+ T_EXPECT_EQ(len, EOF, "fprintf should return EOF when output string is longer than INT_MAX");
+ fclose(f);
+ }
+}
+#endif // !TARGET_OS_IPHONE
#include <stdlib.h>
#include <sys/time.h>
#include <mach/clock_types.h>
+#include <TargetConditionals.h>
#include <darwintest.h>
{
struct timeval tv_start, tv_stop;
struct rusage ru_start, ru_stop;
- unsigned long pwt, put, qwt, qut;
+ uint64_t pwt, put, qwt, qut;
T *buf, *sorted;
+#if TARGET_OS_BRIDGE
+ const size_t nel = 2048000;
+#else
const size_t nel = 20480000;
+#endif
const size_t width = sizeof(T), bufsiz = nel * width;
buf = malloc(bufsiz);
((uint64_t)tv_start.tv_sec * USEC_PER_SEC + tv_start.tv_usec);
put = ((uint64_t)ru_stop.ru_utime.tv_sec * USEC_PER_SEC + ru_stop.ru_utime.tv_usec) -
((uint64_t)ru_start.ru_utime.tv_sec * USEC_PER_SEC + ru_start.ru_utime.tv_usec);
+ T_LOG("psort: wall-time=%llu us; user-time=%llu us", pwt, put);
getrusage(RUSAGE_SELF, &ru_start);
gettimeofday(&tv_start, NULL);
((uint64_t)tv_start.tv_sec * USEC_PER_SEC + tv_start.tv_usec);
qut = ((uint64_t)ru_stop.ru_utime.tv_sec * USEC_PER_SEC + ru_stop.ru_utime.tv_usec) -
((uint64_t)ru_start.ru_utime.tv_sec * USEC_PER_SEC + ru_start.ru_utime.tv_usec);
+ T_LOG("qsort: wall-time=%llu us; user-time=%llu us", qwt, qut);
- bool match = true;
for (size_t i = 0; i < nel; i++) {
- if (!(match = (buf[i] == sorted[i]))) break;
+ if (buf[i] != sorted[i]) {
+ T_ASSERT_EQ(buf[i], sorted[i], NULL);
+ }
}
free(sorted);
free(buf);
- T_MAYFAIL; T_EXPECT_LE((double)pwt/qwt, 1.0, "psort/qsort wall time");
- T_MAYFAIL; T_EXPECT_LE((double)qut/put, 1.0, "qsort/psort user time");
- T_EXPECT_TRUE(match, "psort matches qsort");
+ T_EXPECT_LE((double)pwt/qwt, 1.2, "psort/qsort wall time");
+ T_EXPECT_LE((double)qut/put, 1.2, "qsort/psort user time");
}
--- /dev/null
+/*
+ * Randomized test for qsort() routine.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <darwintest.h>
+#include <darwintest_utils.h>
+
+#include "freebsd_qsort.h"
+
+#define BUFLEN (32 * 1024)
+
+static int tests = 10;
+
+T_DECL(qsort_random, "qsort random test", T_META_CHECK_LEAKS(NO))
+{
+ char testvector[BUFLEN];
+ char sresvector[BUFLEN];
+ size_t i;
+
+ while (--tests >= 0) {
+ size_t elmsize = (tests % 32) + 1;
+ size_t elmcount = sizeof(testvector) / elmsize;
+ T_LOG("%d: size = %zu, count = %zu", tests, elmsize, elmcount);
+
+ /* Populate test vectors */
+ arc4random_buf(testvector, sizeof(testvector));
+ memcpy(sresvector, testvector, sizeof(testvector));
+
+ /* Sort using qsort(3) */
+ qsort_r(testvector, elmcount, elmsize, (void*)elmsize, szsorthelp);
+ /* Sort using reference slow sorting routine */
+ szsort(sresvector, elmcount, elmsize);
+
+ /* Compare results */
+ for (i = 0; i < elmcount; i++){
+ if (memcmp(testvector + (i * elmsize), sresvector + (i * elmsize), elmsize) != 0) {
+ T_LOG("testvector =");
+ dt_print_hex_dump((uint8_t*)testvector, sizeof(testvector));
+ T_LOG("sresvector =");
+ dt_print_hex_dump((uint8_t*)sresvector, sizeof(sresvector));
+ T_ASSERT_FAIL("%d: item at index %zd should match", tests, i);
+ break;
+ }
+ }
+ if (i == elmcount) {
+ T_PASS("%d: Sorted successfully.", tests);
+ }
+ }
+}
--- /dev/null
+/*
+ * Randomized test for qsort() routine.
+ *
+ * Includes code derived from stdlib/FreeBSD/qsort.c and the copyright header
+ * in that file applies.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <darwintest.h>
+#include <darwintest_utils.h>
+
+static void qsort1(void *aa, size_t n, size_t es,
+ int (*cmp)(const void *, const void *));
+
+static int
+cmp_int(const void *aa, const void *bb)
+{
+ int a, b;
+
+ a = *(const int *)aa;
+ b = *(const int *)bb;
+ return(a - b);
+}
+
+#define nelm 1000000
+
+T_DECL(qsort_perf, "qsort perf test", T_META_CHECK_LEAKS(NO))
+{
+ int i;
+ int arr[nelm];
+ int save[nelm];
+ uint64_t time_elapsed;
+
+ // ----- 25-75 -----
+
+ int k = nelm/4;
+ for (i = 0; i < k; i++) {
+ save[i] = i;
+ }
+ for (i = k; i < nelm; i++) {
+ save[i] = i - k;
+ }
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("25-75 (qsort)");
+ qsort(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("25-75 (qsort)");
+ T_LOG("25-75 (qsort): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ break;
+ }
+ }
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("25-75 (Bentley)");
+ qsort1(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("25-75 (Bentley)");
+ T_LOG("25-75 (Bentley): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ break;
+ }
+ }
+ // ----- 50-50 -----
+
+ k = nelm/2;
+ for (i = 0; i < k; i++) {
+ save[i] = i;
+ }
+ for (i = k; i < nelm; i++) {
+ save[i] = i - k;
+ }
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("50-50 (qsort)");
+ qsort(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("50-50 (qsort)");
+ T_LOG("50-50 (qsort): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ break;
+ }
+ }
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("50-50 (Bentley)");
+ qsort1(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("50-50 (Bentley)");
+ T_LOG("50-50 (Bentley): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ break;
+ }
+ }
+
+ // ----- median-of-3 killer -----
+
+ k = nelm / 2;
+ for (i = 1; i <= k; i++) {
+ if(i % 2 == 1) {
+ save[i - 1] = i;
+ save[i] = k + i;
+ }
+ save[k + i - 1] = 2 * i;
+ }
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("median-of-3 killer (qsort)");
+ qsort(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("median-of-3 killer (qsort)");
+ T_LOG("median-of-3 (qsort): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ }
+ }
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("median-of-3 killer (Bentley)");
+ qsort1(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("median-of-3 killer (Bentley)");
+ T_LOG("median-of-3 (Bentley): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ }
+ }
+
+ // ----- random -----
+
+ for (i = 0; i < nelm; i++) {
+ save[i] = random();
+ }
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("random (qsort)");
+ qsort(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("random (qsort)");
+ T_LOG("random (qsort): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ }
+ }
+
+
+ bcopy(save, arr, sizeof(arr));
+ dt_timer_start("random (Bentley)");
+ qsort1(arr, nelm, sizeof(arr[0]), cmp_int);
+ time_elapsed = dt_timer_stop("random (Bentley)");
+ T_LOG("random (Bentley): %lld ms", time_elapsed / NSEC_PER_MSEC);
+ for (i = 1; i < nelm; i++) {
+ if(arr[i - 1] > arr[i]) {
+ T_ASSERT_FAIL("arr[%d]=%d > arr[%d]=%d", i - 1, arr[i - 1], i, arr[i]);
+ }
+ }
+
+ T_PASS("All tests completed successfully.");
+}
+
+/* qsort1 -- qsort interface implemented by faster quicksort */
+
+#define SWAPINIT(a, es) swaptype = \
+ (a - (char*) 0) % sizeof(long) || es % sizeof(long) ? 2 : \
+ es == sizeof(long) ? 0 : 1;
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof(TYPE); \
+ register TYPE *pi = (TYPE *) (parmi); \
+ register TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ register TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+static void swapfunc(char *a, char *b, int n, int swaptype)
+{ if (swaptype <= 1) swapcode(long, a, b, n)
+ else swapcode(char, a, b, n)
+}
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = * (long *) (a); \
+ * (long *) (a) = * (long *) (b); \
+ * (long *) (b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+#define vecswap(a, b, n) if (n > 0) swapfunc(a, b, n, swaptype)
+
+#define min(x, y) ((x)<=(y) ? (x) : (y))
+
+static char *med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
+{
+ return cmp(a, b) < 0 ?
+ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ) )
+ : (cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ) );
+}
+
+static void
+qsort1(void *aa, size_t n, size_t es,
+ int (*cmp)(const void *, const void *))
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype;
+ char *a = aa;
+
+ SWAPINIT(a, es);
+ if (n < 7) { /* Insertion sort on small arrays */
+ for (pm = a + es; pm < a + n*es; pm += es)
+ for (pl = pm; pl > a && cmp(pl-es, pl) > 0; pl -= es)
+ swap(pl, pl-es);
+ return;
+ }
+ pm = a + (n/2) * es;
+ if (n > 7) {
+ pl = a;
+ pn = a + (n-1) * es;
+ if (n > 40) { /* On big arrays, pseudomedian of 9 */
+ d = (n/8) * es;
+ pl = med3(pl, pl+d, pl+2*d, cmp);
+ pm = med3(pm-d, pm, pm+d, cmp);
+ pn = med3(pn-2*d, pn-d, pn, cmp);
+ }
+ pm = med3(pl, pm, pn, cmp); /* On mid arrays, med of 3 */
+ }
+ swap(a, pm); /* On tiny arrays, partition around middle */
+ pa = pb = a + es;
+ pc = pd = a + (n-1)*es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a)) <= 0) {
+ if (r == 0) { swap(pa, pb); pa += es; }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+ if (r == 0) { swap(pc, pd); pd -= es; }
+ pc -= es;
+ }
+ if (pb > pc) break;
+ swap(pb, pc);
+ pb += es;
+ pc -= es;
+ }
+ pn = a + n*es;
+ r = min(pa-a, pb-pa); vecswap(a, pb-r, r);
+ r = min(pd-pc, pn-pd-es); vecswap(pb, pn-r, r);
+ if ((r = pb-pa) > es) qsort1(a, r/es, es, cmp);
+ if ((r = pd-pc) > es) qsort1(pn-r, r/es, es, cmp);
+}
--- /dev/null
+/* $NetBSD: t_realpath.c,v 1.2 2012/03/27 07:54:58 njoly Exp $ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_realpath.c,v 1.2 2012/03/27 07:54:58 njoly Exp $");
+
+#include <sys/param.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <darwintest.h>
+#include <darwintest_utils.h>
+
+struct testcase {
+ const char *path;
+ const char *result;
+};
+
+static const struct testcase paths[] = {
+ { "/", "/" },
+ { "///////", "/" },
+ { "", NULL },
+ { " ", NULL },
+ { "/ ", NULL },
+ { " /", NULL },
+ { "/usr/bin///", "/usr/bin" },
+ { "///////usr", "/usr" },
+ { "/a/b/c/d/e", NULL },
+ { " /usr/bin ", NULL },
+ { "\\//////usr//bin", NULL },
+ { "//usr//bin//", "/usr/bin" },
+ { "//////usr//bin//", "/usr/bin" },
+ { "/usr/bin//////////", "/usr/bin" },
+};
+
+T_DECL(realpath_basic, "Resolve various short directory paths")
+{
+ char buf[MAXPATHLEN];
+ char *ptr;
+ size_t i;
+
+ size_t num_cases = sizeof(paths) / sizeof(struct testcase);
+ for (i = 0; i < num_cases; i++) {
+
+ (void)memset(buf, '\0', sizeof(buf));
+
+ ptr = realpath(paths[i].path, buf);
+
+ if (paths[i].result == NULL) {
+ T_EXPECT_NULL(ptr, NULL);
+ } else {
+ T_EXPECT_EQ_STR(ptr, paths[i].result, "Real path matches expected path");
+ }
+ }
+}
+
+T_DECL(realpath_trailing, "Trailing . and .. should fail after non-directories")
+{
+ char result[MAXPATHLEN] = { 0 };
+
+ T_EXPECT_NULL(realpath("/usr/null/.", result), NULL);
+ T_EXPECT_NULL(realpath("/usr/null/..", result), NULL);
+}
+
+T_DECL(realpath_huge, "Test realpath with maximum path size")
+{
+ char result[MAXPATHLEN] = { 0 };
+ char buffer[MAXPATHLEN] = { 0 };
+
+ (void)memset(buffer, '/', sizeof(buffer) - 1);
+
+ T_EXPECT_NOTNULL(realpath(buffer, result), NULL);
+ T_EXPECT_EQ(strlen(result), (size_t) 1, NULL);
+ T_EXPECT_EQ(result[0], '/', NULL);
+}
+
+T_DECL(realpath_symlink, "Resolve symlinked paths")
+{
+ char *resolved_tmpdir;
+ char path[MAXPATHLEN] = { 0 };
+ char slnk[MAXPATHLEN] = { 0 };
+ char resb[MAXPATHLEN] = { 0 };
+ int fd;
+
+ // We have to use the realpath for this symlink test.
+ // Otherwise, when trying to resolve a symlink, it won't match.
+ resolved_tmpdir = realpath(dt_tmpdir(), NULL);
+ snprintf(path, sizeof(path), "%s%s", resolved_tmpdir, "/real");
+ snprintf(slnk, sizeof(path), "%s%s", resolved_tmpdir, "/sym");
+
+ fd = open(path, O_RDONLY | O_CREAT, 0600);
+
+ T_WITH_ERRNO;
+ T_ASSERT_GE(fd, 0, NULL);
+ T_ASSERT_POSIX_ZERO(symlink(path, slnk), NULL);
+ T_ASSERT_POSIX_ZERO(close(fd), NULL);
+
+ T_ASSERT_NOTNULL(realpath(slnk, resb), NULL);
+ T_ASSERT_EQ_STR(resb, path, NULL);
+
+ T_ASSERT_POSIX_ZERO(unlink(path), NULL);
+ T_ASSERT_POSIX_ZERO(unlink(slnk), NULL);
+ free(resolved_tmpdir);
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Jan Kokemüller
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <darwintest.h>
+
+// Required for ASan
+#include "../fbsdcompat/_fbsd_compat_.h"
+#include "../stdlib/FreeBSD/realpath.c"
+#include "../gen/FreeBSD/getcwd.c"
+
+
+T_DECL(realpath_buffer_overflow, "Test for out of bounds read from 'left' array (compile realpath.c with '-fsanitize=address')")
+{
+ char path[MAXPATHLEN] = { 0 };
+ char resb[MAXPATHLEN] = { 0 };
+ size_t i;
+
+ path[0] = 'a';
+ path[1] = '/';
+ for (i = 2; i < sizeof(path) - 1; ++i) {
+ path[i] = 'a';
+ }
+
+ T_ASSERT_NULL(realpath(path, resb), NULL);
+}
+
#define FILE_LIMIT 100
-T_DECL(PR_22813396, "STREAM_MAX is affected by changes to RLIMIT_NOFILE")
+T_DECL(stdio_PR_22813396, "STREAM_MAX is affected by changes to RLIMIT_NOFILE")
{
struct rlimit theLimit;
getrlimit( RLIMIT_NOFILE, &theLimit );
f = fdopen(0, "r");
T_EXPECT_NOTNULL(f, "fdopen succeed after RLIMIT_NOFILE increased");
}
+
+T_DECL(stdio_PR_22813396_close, "STREAM_MAX is enforced properly after fclose")
+{
+ struct rlimit theLimit;
+ getrlimit( RLIMIT_NOFILE, &theLimit );
+ theLimit.rlim_cur = FILE_LIMIT;
+ setrlimit( RLIMIT_NOFILE, &theLimit );
+
+ long stream_max = sysconf(_SC_STREAM_MAX);
+ T_EXPECT_EQ_LONG(stream_max, (long)FILE_LIMIT, "stream_max = FILE_LIMIT");
+
+ FILE *f;
+ for(int i = 3; i < stream_max - 1; i++) {
+ if((f = fdopen(0, "r")) == NULL) {
+ T_FAIL("Failed after %d streams", i);
+ }
+ }
+
+ // the last stream is for dup(0), it needs to be fclose'd
+ FILE *dupf = NULL;
+ T_EXPECT_NOTNULL(dupf = fdopen(dup(0), "r"), NULL);
+
+ T_EXPECT_NULL(f = fdopen(0, "r"), "fdopen fail after stream_max streams");
+
+ T_EXPECT_POSIX_ZERO(fclose(dupf), "fclose succeeds");
+
+ f = fdopen(0, "r");
+ T_WITH_ERRNO; T_EXPECT_NOTNULL(f, "fdopen succeed after fclose");
+}
+
--- /dev/null
+/*-
+ * Copyright (c) 2001 Wes Peters <wes@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$
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "darwintest.h"
+
+static char buf[64];
+static char *sret;
+static int iret;
+
+T_DECL(strerror, "")
+{
+ //T_DECL(strerror_unknown_error, "")
+ errno = 0;
+ sret = strerror(INT_MAX);
+ snprintf(buf, sizeof(buf), "Unknown error: %d", INT_MAX);
+ T_EXPECT_EQ_STR(sret, buf, NULL);
+ T_EXPECT_EQ(errno, EINVAL, NULL);
+
+ //T_DECL(strerror_no_error, "")
+ errno = 0;
+ sret = strerror(0);
+ T_EXPECT_EQ_STR(sret, "Undefined error: 0", NULL);
+ T_EXPECT_EQ(errno, 0, NULL);
+
+ //T_DECL(strerror_EPERM_test, "")
+ errno = 0;
+ sret = strerror(EPERM);
+ T_EXPECT_EQ_STR(sret, "Operation not permitted", NULL);
+ T_EXPECT_EQ(errno, 0, NULL);
+
+ //T_DECL(strerror_EPFNOSUPPORT_test, "")
+ errno = 0;
+ sret = strerror(EPFNOSUPPORT);
+ T_EXPECT_EQ_STR(sret, "Protocol family not supported", NULL);
+ T_EXPECT_EQ(errno, 0, NULL);
+
+ //T_DECL(strerror_ELAST_test, "")
+ errno = 0;
+ sret = strerror(ELAST);
+ T_EXPECT_EQ(errno, 0, NULL);
+}
+
+T_DECL(strerror_r, "")
+{
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(-1, buf, sizeof(buf));
+ T_EXPECT_EQ_STR(buf, "Unknown error: -1", NULL);
+ T_EXPECT_EQ(iret, EINVAL, NULL);
+
+ //T_DECL(strerror_r__EPERM_one_byte_short, "")
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(EPERM, buf, strlen("Operation not permitted"));
+ T_EXPECT_EQ_STR(buf, "Operation not permitte", NULL);
+ T_EXPECT_EQ(iret, ERANGE, NULL);
+
+ //T_DECL(strerror_r__EPERM_unknown_error_one_byte_short, "")
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(-1, buf, strlen("Unknown error: -1"));
+ T_EXPECT_EQ_STR(buf, "Unknown error: -", NULL);
+ T_EXPECT_EQ(iret, EINVAL, NULL);
+
+ //T_DECL(strerror_r__EPERM_unknown_error_two_bytes_short, "")
+ memset(buf, '*', sizeof(buf));
+ /* Two bytes too short. */
+ iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 1);
+ T_EXPECT_EQ_STR(buf, "Unknown error: ", NULL);
+ T_EXPECT_EQ(iret, EINVAL, NULL);
+
+ //T_DECL(strerror_r__EPERM_unknown_error_three_bytes_short, "")
+ memset(buf, '*', sizeof(buf));
+ /* Three bytes too short. */
+ iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 2);
+ T_EXPECT_EQ_STR(buf, "Unknown error:", NULL);
+ T_EXPECT_EQ(iret, EINVAL, NULL);
+
+ //T_DECL(strerror_r__EPERM_unknown_error_12345_one_byte_short, "")
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(12345, buf, strlen("Unknown error: 12345"));
+ T_EXPECT_EQ_STR(buf, "Unknown error: 1234", NULL);
+ T_EXPECT_EQ(iret, EINVAL, NULL);
+
+ //T_DECL(strerror_r__no_error, "")
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(0, buf, sizeof(buf));
+ T_EXPECT_EQ_STR(buf, "Undefined error: 0", NULL);
+ T_EXPECT_EQ(iret, 0, NULL);
+
+ //T_DECL(strerror_r__EDEADLK, "")
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(EDEADLK, buf, sizeof(buf));
+ T_EXPECT_EQ_STR(buf, "Resource deadlock avoided", NULL);
+ T_EXPECT_EQ(iret, 0, NULL);
+
+ //T_DECL(strerror_r__EPROCLIM, "")
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(EPROCLIM, buf, sizeof(buf));
+ T_EXPECT_EQ_STR(buf, "Too many processes", NULL);
+ T_EXPECT_EQ(iret, 0, NULL);
+}
--- /dev/null
+#include <string.h>
+
+#include <darwintest.h>
+
+T_DECL(strlcpy_PR_30745460, "Test return value of strlcpy(2)",
+ T_META_CHECK_LEAKS(NO))
+{
+ char buf[1];
+ T_EXPECT_EQ(strlcpy(buf, "text", 1), 4UL, NULL);
+ T_EXPECT_EQ(strlcpy(NULL, "text", 0), 4UL, NULL);
+}
#include <darwintest.h>
#include <darwintest_utils.h>
-T_DECL(PR_27004626, "strptime() should fail when a %t doesn't match anything")
+T_DECL(strptime_PR_27004626, "strptime() should fail when a %t doesn't match anything")
{
struct tm tm;
T_ASSERT_NULL(strptime("there'snotemplateforthis", "%t", &tm), NULL);
}
+
+T_DECL(strptime_PR_29381762, "strptime() sets the tm_wday field incorrectly")
+{
+ time_t epoch = 0;
+ struct tm t = *localtime(&epoch);
+
+ T_LOG("2015-01-01 12:00:00 -> Thursday");
+ (void)strptime("2015-01-01 12:00:00", "%F %T", &t);
+ T_EXPECT_EQ(t.tm_wday, 4, NULL);
+
+ T_LOG("2015-04-19 12:00:00 -> Sunday");
+ (void)strptime("2015-04-19 12:00:00", "%F %T", &t);
+ T_EXPECT_EQ(t.tm_wday, 0, NULL);
+
+ T_LOG("2009-03-03 12:00:00 -> Tuesday");
+ (void)strptime("2009-03-03 12:00:00", "%F %T", &t);
+ T_EXPECT_EQ(t.tm_wday, 2, NULL);
+
+ T_LOG("1990-02-15 12:00:00 -> Thursday");
+ (void)strptime("1990-02-15 12:00:00", "%F %T", &t);
+ T_EXPECT_EQ(t.tm_wday, 4, NULL);
+
+ T_LOG("1993-03-02 12:00:00 -> Sunday");
+ (void)strptime("1993-03-02 12:00:00", "%F %T", &t);
+ T_EXPECT_EQ(t.tm_wday, 2, NULL);
+}
* Test courtesy of Roel Standaert
* Source: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=209907
*/
-T_DECL(PR_26556792, "wcsrtombs neglects to set src pointer on EILSEQ error")
+T_DECL(wchar_PR_26556792, "wcsrtombs neglects to set src pointer on EILSEQ error")
{
char out[64];
wchar_t *in = L"Hello! \x20AC Hello!";
}
-T_DECL(PR_26828480, "double free in __vfwprintf")
+T_DECL(wchar_PR_26828480, "double free in __vfwprintf")
{
wchar_t *test;
int ret;
#include <utmpx.h>
#include <utmpx-darwin.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
void
login(struct utmp *ut)
{
pututxline(&ux);
endutxent();
}
+
+#pragma clang diagnostic pop
LZeroBuffer:
movq %rdx,%rsi // remaining buffer size (2nd argument)
- subq $8,%rsp // align stack to 16B before call
+ pushq %r8 // save r8 and align stack to 16B
call _bzero
- addq $8,%rsp // restore stack
+ popq %r8
LDone:
movq %r8,%rax // original dest ptr is return value
EXCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*] = $(VARIANT_EOS_EXCLUDED_FILES)
EXCLUDED_SOURCE_FILE_NAMES[sdk=watchos*] = $(VARIANT_EOS_EXCLUDED_FILES)
EXCLUDED_SOURCE_FILE_NAMES[sdk=appletvos*] = $(VARIANT_EOS_EXCLUDED_FILES)
+EXCLUDED_SOURCE_FILE_NAMES[sdk=bridgeos*] = $(VARIANT_EOS_EXCLUDED_FILES)
INCLUDED_SOURCE_FILE_NAMES =
INCLUDED_SOURCE_FILE_NAMES[sdk=iphoneos*] = $(VARIANT_EOS_INCLUDED_FILES)
INCLUDED_SOURCE_FILE_NAMES[sdk=watchos*] = $(VARIANT_EOS_INCLUDED_FILES)
INCLUDED_SOURCE_FILE_NAMES[sdk=appletvos*] = $(VARIANT_EOS_INCLUDED_FILES)
+INCLUDED_SOURCE_FILE_NAMES[sdk=bridgeos*] = $(VARIANT_EOS_INCLUDED_FILES)
VARIANT_PREPROCESSOR_MACROS = -UBUILDING_VARIANT -DVARIANT_STATIC -DVARIANT_EOS -DVARIANT_CANCELABLE -DVARIANT_DARWINEXTSN -U__DARWIN_NON_CANCELABLE -D__DARWIN_NON_CANCELABLE=0
SYSTEM_FRAMEWORK_HEADERS = $(DERIVED_FILES_DIR)/System.framework/Versions/B/PrivateHeaders
}
elsif ($unifdef == 1) {
- if ($platformName eq "macosx") {
- $unifdefs{"__OSX_OPEN_SOURCE__"} = 1;
- }
# assume FEATURE_BLOCKS was on by default
$unifdefs{"UNIFDEF_BLOCKS"} = 1;
$unifdefs{"UNIFDEF_LEGACY_64_APIS"} = defined($features{"FEATURE_LEGACY_64_APIS"});
$unifdefs{"UNIFDEF_LEGACY_RUNE_APIS"} = defined($features{"FEATURE_LEGACY_RUNE_APIS"});
$unifdefs{"UNIFDEF_LEGACY_UTMP_APIS"} = defined($features{"FEATURE_LEGACY_UTMP_APIS"});
- $unifdefs{"UNIFDEF_MOVE_LOCALTIME"} = defined($features{"FEATURE_MOVE_LOCALTIME"});
- $unifdefs{"UNIFDEF_TZDIR_SYMLINK"} = defined($features{"FEATURE_TZDIR_SYMLINK"});
my $output = "";
for my $d (keys %unifdefs) {
my $shortarch = $arch;
$shortarch =~ s/armv\d+[a-z]?/arm/g;
- $shortarch =~ s/arm64_32/arm64/g;
+
+ # map all arm64 subtypes to arm64
+ $shortarch =~ s/arm64[_a-z0-9]?/arm64/g;
printf HEADER "#if !defined(__".$shortarch."__)\n";
printf HEADER "#error Mismatched libc-features.h architecture\n";
printf HEADER "/* #undef UNIFDEF_LEGACY_UTMP_APIS */\n";
}
- if (defined($features{"FEATURE_MOVE_LOCALTIME"})) {
- printf HEADER "#define UNIFDEF_MOVE_LOCALTIME 1\n";
- } else {
- printf HEADER "/* #undef UNIFDEF_MOVE_LOCALTIME */\n";
- }
-
- if (defined($features{"FEATURE_TZDIR_SYMLINK"})) {
- printf HEADER "#define UNIFDEF_TZDIR_SYMLINK 1\n";
- } else {
- printf HEADER "/* #undef UNIFDEF_TZDIR_SYMLINK */\n";
- }
-
if (defined($features{"FEATURE_ONLY_1050_VARIANTS"})) {
printf HEADER "#if !__DARWIN_ONLY_VERS_1050\n";
printf HEADER "# error Feature mismatch: __DARWIN_ONLY_VERS_1050 == 0\n";
printf HEADER "/* #undef NOTIFY_TZ */\n";
}
- if (defined($features{"FEATURE_NO_LIBCRASHREPORTERCLIENT"})) {
- printf HEADER "#define LIBC_NO_LIBCRASHREPORTERCLIENT 1\n";
- } else {
- printf HEADER "/* #undef LIBC_NO_LIBCRASHREPORTERCLIENT */\n";
- }
-
if (defined($features{"FEATURE_SMALL_STDIOBUF"})) {
printf HEADER "#define FEATURE_SMALL_STDIOBUF 1\n";
} else {
INC_PROTO_INSTHDRS=( routed.h rwhod.h talkd.h timed.h )
PROTO_INSTHDRS=( "${INC_PROTO_INSTHDRS[@]/#/${SRCROOT}/include/protocols/}" )
-INC_SECURE_INSTHDRS=( _common.h _string.h _stdio.h )
+INC_SECURE_INSTHDRS=( _common.h _string.h _strings.h _stdio.h )
SECURE_INSTHDRS=( "${INC_SECURE_INSTHDRS[@]/#/${SRCROOT}/include/secure/}" )
SYS_INSTHDRS=( ${SRCROOT}/include/sys/acl.h ${SRCROOT}/include/sys/statvfs.h )
${SRCROOT}/darwin/libc_private.h
${SRCROOT}/gen/utmpx_thread.h
${SRCROOT}/nls/FreeBSD/msgcat.h
+ ${SRCROOT}/libdarwin/dirstat.h
)
OS_LOCALHDRS=( ${SRCROOT}/os/assumes.h ${SRCROOT}/os/debug_private.h )
--- /dev/null
+# (i386 only)
+# There used to be legacy versions of various funciotns, but we've removed them
+# and just given everyone the UNIX2003 behavior. The legacy variant doesn't
+# build those functions anymore, they are just aliased to corresponding 32-bit
+# non-legacy symbols. e.g.:
+# _opendir legacy, aliased to _opendir$UNIX2003
+# _opendir$UNIX2003 32-bit inodes
+# _opendir$INODE64$UNIX2003 64-bit inodes
+
+___opendir2$UNIX2003 ___opendir2
+__seekdir$UNIX2003 __seekdir
+_closedir$UNIX2003 _closedir
+_fdopendir$UNIX2003 _fdopendir
+_opendir$UNIX2003 _opendir
+_rewinddir$UNIX2003 _rewinddir
+_seekdir$UNIX2003 _seekdir
+_telldir$UNIX2003 _telldir
+
+_strerror$UNIX2003 _strerror
#include "<DEVELOPER_DIR>/Makefiles/CoreOS/Xcode/BSD.xcconfig"
// Standard settings
-SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator iphoneosnano iphonesimulatornano
+SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator iphoneosnano iphonesimulatornano bridgeos
SRCROOT_SEARCH_PATHS = $(SRCROOT) $(SRCROOT)/include $(SRCROOT)/gen $(SRCROOT)/locale $(SRCROOT)/locale/FreeBSD $(SRCROOT)/stdtime/FreeBSD $(SRCROOT)/darwin
SYSTEM_FRAMEWORK_HEADERS = $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
HEADER_SEARCH_PATHS = $($(TARGET_NAME)_SEARCH_PATHS) $(DERIVED_FILES_DIR)/dtrace $(SRCROOT_SEARCH_PATHS) $(SYSTEM_FRAMEWORK_HEADERS) $(SDKROOT)/usr/local/include $(inherited)
GCC_WARN_UNUSED_VARIABLE = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
//WARNING_CFLAGS = -Wall -Wextra
-WARNING_CFLAGS = -Wall -Werror=incompatible-pointer-types -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-nullability-completeness
+WARNING_CFLAGS = -Wall -Werror -Wno-error=shorten-64-to-32 -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-nullability-completeness
COPY_PHASE_STRIP = NO
SKIP_INSTALL = YES
PUBLIC_HEADERS_FOLDER_PATH = /usr/include
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include
+DARWIN_PUBLIC_HEADERS_FOLDER_PATH = /usr/include/os
+DARWIN_PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/os
+
// Simulator
BASE_PREPROCESSOR_MACROS = __LIBC__ __DARWIN_UNIX03=1 __DARWIN_64_BIT_INO_T=1 __DARWIN_NON_CANCELABLE=1 __DARWIN_VERS_1050=1 _FORTIFY_SOURCE=0
OTHER_CFLAGS = -fdollars-in-identifiers -fno-common -fverbose-asm $($(TARGET_NAME)_CFLAGS) $(VARIANT_PREPROCESSOR_MACROS)
SIM_SUFFIX[sdk=*simulator*] = _sim
GCC_PREPROCESSOR_DEFINITIONS = $(BASE_PREPROCESSOR_MACROS)
-GCC_PREPROCESSOR_DEFINITIONS[sdk=iphone*] = $(BASE_PREPROCESSOR_MACROS) LIBC_NO_LIBCRASHREPORTERCLIENT=1
// libsystem_c.dylib linking
CR_LDFLAGS = -lCrashReporterClient
LIBCOMPILER_RT_LDFLAGS = -lcompiler_rt
LIBMALLOC_LDFLAGS = -lsystem_malloc
+LIBC_LDFLAGS = -lsystem_c
+LIBDISPATCH_LDFLAGS = -ldispatch
+LIBXPC_LDFLAGS = -lxpc
LIBPLATFORM_LDFLAGS = -lsystem$(SIM_SUFFIX)_platform
LIBPTHREAD_LDFLAGS = -lsystem$(SIM_SUFFIX)_pthread
LIBSYSCALL_LDFLAGS = -lsystem$(SIM_SUFFIX)_kernel
LIBM_LDFLAGS = -lsystem$(SIM_SUFFIX)_m
LIBDYLD_LDFLAGS = -ldyld
-LIBSYSTEM_C_LDFLAGS = -all_load -nostdlib -L/usr/lib/system -umbrella System $(CR_LDFLAGS) $(LIBCOMPILER_RT_LDFLAGS) $(LIBDYLD_LDFLAGS) $(LIBSYSCALL_LDFLAGS) $(LIBM_LDFLAGS) $(LIBMALLOC_LDFLAGS) $(LIBPLATFORM_LDFLAGS) $(LIBPTHREAD_LDFLAGS) $(UPWARD_LDFLAGS) -Wl,-interposable_list,$(DERIVED_FILES_DIR)/interposable.list -Wl,-unexported_symbols_list,$(DERIVED_FILES_DIR)/unexport.list -Wl,-alias_list,$(SRCROOT)/xcodescripts/alias.list -Wl,-order_file,$(SRCROOT)/xcodescripts/Libc.order -Wl,-sectalign,__DATA,__data,1000 @$(BUILT_PRODUCTS_DIR)/$(CURRENT_VARIANT).linklist
+LIBSYSTEM_C_LDFLAGS = -all_load -nostdlib -L/usr/lib/system -umbrella System $(CR_LDFLAGS) $(LIBCOMPILER_RT_LDFLAGS) $(LIBDYLD_LDFLAGS) $(LIBSYSCALL_LDFLAGS) $(LIBM_LDFLAGS) $(LIBMALLOC_LDFLAGS) $(LIBPLATFORM_LDFLAGS) $(LIBPTHREAD_LDFLAGS) $(UPWARD_LDFLAGS) $(LIBSYSTEM_C_EXTRA_LDFLAGS_$(CURRENT_ARCH)) -Wl,-interposable_list,$(DERIVED_FILES_DIR)/interposable.list -Wl,-unexported_symbols_list,$(DERIVED_FILES_DIR)/unexport.list -Wl,-alias_list,$(SRCROOT)/xcodescripts/alias.list -Wl,-order_file,$(SRCROOT)/xcodescripts/Libc.order -Wl,-sectalign,__DATA,__data,1000 @$(BUILT_PRODUCTS_DIR)/$(CURRENT_VARIANT).linklist
+LIBSYSTEM_C_EXTRA_LDFLAGS_i386 = -Wl,-alias_list,$(SRCROOT)/xcodescripts/legacy_alias.list
// TODO: Remove upward links - mostly <rdar://problem/13183469>, macho is for assumes.c
UPWARD_LDFLAGS = -Wl,-upward-ldispatch -Wl,-upward-llaunch -Wl,-upward-lmacho -Wl,-upward-lsystem_asl -Wl,-upward-lsystem_blocks -Wl,-upward-lsystem_info -Wl,-upward-lsystem_notify -Wl,-upward-lxpc -Wl,-upward-lcorecrypto
UPWARD_LDFLAGS[sdk=*simulator*] = -Wl,-upward-ldispatch -Wl,-upward-lmacho_sim -Wl,-upward-lsystem_asl -Wl,-upward-lsystem_sim_blocks -Wl,-upward-lsystem_sim_info -Wl,-upward-lsystem_notify -Wl,-upward-lxpc -Wl,-upward-lcorecrypto
+LIBSYSTEM_DARWIN_LDFLAGS = -all_load -nostdlib -L/usr/lib/system -umbrella System $(LIBCOMPILER_RT_LDFLAGS) $(LIBDYLD_LDFLAGS) $(LIBSYSCALL_LDFLAGS) $(LIBM_LDFLAGS) $(LIBMALLOC_LDFLAGS) $(LIBPLATFORM_LDFLAGS) $(LIBPTHREAD_LDFLAGS) $(LIBPLATFORM_LDFLAGS) $(LIBC_LDFLAGS) $(LIBDISPATCH_LDFLAGS) $(LIBXPC_LDFLAGS)
+
// libPlatform.a architectures
ARCH_FAMILY = $(ARCH_FAMILY_$(CURRENT_ARCH))
ARCH_FAMILY_x86_64 = x86_64
ARCH_FAMILY_armv7s = arm
ARCH_FAMILY_armv7f = arm
ARCH_FAMILY_armv7k = arm
+ARCH_FAMILY_arm64 = arm64
+ARCH_FAMILY_arm64_32 = arm64
// Platform target
Platform_INCLUDED_SOURCE_FILE_NAMES = $(Platform_INCLUDED_SOURCE_FILE_NAMES_gen) $(Platform_INCLUDED_SOURCE_FILE_NAMES_stdlib) $(Platform_INCLUDED_SOURCE_FILE_NAMES_string)
FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7k = $(FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7)
FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7f = $(FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7)
FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv6 = $(FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7)
+FreeBSD_INCLUDED_SOURCE_FILE_NAMES_arm64 = $(FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7)
+FreeBSD_INCLUDED_SOURCE_FILE_NAMES_arm64_32 = $(FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7)
+FreeBSD_INCLUDED_SOURCE_FILE_NAMES_arm64e = $(FreeBSD_INCLUDED_SOURCE_FILE_NAMES_armv7)
// NetBSD target
NetBSD_CFLAGS = -include $(SRCROOT)/nbsdcompat/_nbsd_compat_.h
BASE_EXCLUDED_SOURCE_FILE_NAMES_armv7k = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_armv7)
BASE_EXCLUDED_SOURCE_FILE_NAMES_armv7f = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_armv7)
BASE_EXCLUDED_SOURCE_FILE_NAMES_armv6 = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_armv7)
+BASE_EXCLUDED_SOURCE_FILE_NAMES_arm64 = strlen.c strnlen.c kvm.c nlist.c
+BASE_EXCLUDED_SOURCE_FILE_NAMES_arm64_32 = strlen.c strnlen.c kvm.c nlist.c
+BASE_EXCLUDED_SOURCE_FILE_NAMES_arm64e = strlen.c strnlen.c kvm.c nlist.c
// Rune support isn't included on iOS but there's no better way to exclude their complication
BASE_EXCLUDED_SOURCE_FILE_NAMES_macosx = OSMemoryNotification.c
BASE_EXCLUDED_SOURCE_FILE_NAMES_appletvsimulator = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_iphonesimulator)
BASE_EXCLUDED_SOURCE_FILE_NAMES_watchos = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_iphoneos)
BASE_EXCLUDED_SOURCE_FILE_NAMES_watchsimulator = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_iphonesimulator)
+BASE_EXCLUDED_SOURCE_FILE_NAMES_bridgeos = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_iphoneos)
// TODO: Remove these legacy platform names:
BASE_EXCLUDED_SOURCE_FILE_NAMES_iphoneosnano = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_watchos)
if [ "$ACTION" = installhdrs ]; then exit 0; fi
if [ "${PLATFORM_NAME}" != "macosx" ]; then exit 0; fi
+if [ "${SKIP_MANPAGES}" = "YES" ]; then exit 0; fi
UNIFDEF_FLAGS=`${SRCROOT}/xcodescripts/generate_features.pl --unifdef`
MANPAGES_LIST="${SRCROOT}/man/manpages.lst"
my $sym;
if($n > 0) {
my($sym) = ($save[$n - 1] =~ /__DARWIN_(?:10\d+|ALIAS|EXTSN|INODE64)[^(]*\(([^)]*)\)/);
+ if($save[$n - 1] =~ /__DARWIN_ALIAS_STARTING/) {
+ undef $sym;
+ }
if(defined($sym)) {
if(defined($path)) {
print " $path\n";
VARIANT_LEGACY_INCLUDE = $(VARIANT_LEGACY_INCLUDE_$(PLATFORM_NAME))
VARIANT_LEGACY_INCLUDE_macosx = $(VARIANT_LEGACY_INCLUDE_$(PLATFORM_NAME)_$(CURRENT_ARCH))
-VARIANT_LEGACY_INCLUDE_macosx_i386 = $(VARIANT_LEGACY_INCLUDE_compat) $(VARIANT_LEGACY_INCLUDE_gdtoa) $(VARIANT_LEGACY_INCLUDE_gen) $(VARIANT_LEGACY_INCLUDE_locale) $(VARIANT_LEGACY_INCLUDE_net) $(VARIANT_LEGACY_INCLUDE_regex) $(VARIANT_LEGACY_INCLUDE_stdio) $(VARIANT_LEGACY_INCLUDE_stdlib) $(VARIANT_LEGACY_INCLUDE_stdtime) $(VARIANT_LEGACY_INCLUDE_string) $(VARIANT_LEGACY_INCLUDE_sys)
+VARIANT_LEGACY_INCLUDE_macosx_i386 = $(VARIANT_LEGACY_INCLUDE_compat) $(VARIANT_LEGACY_INCLUDE_gdtoa) $(VARIANT_LEGACY_INCLUDE_gen) $(VARIANT_LEGACY_INCLUDE_locale) $(VARIANT_LEGACY_INCLUDE_net) $(VARIANT_LEGACY_INCLUDE_regex) $(VARIANT_LEGACY_INCLUDE_stdio) $(VARIANT_LEGACY_INCLUDE_stdlib) $(VARIANT_LEGACY_INCLUDE_stdtime) $(VARIANT_LEGACY_INCLUDE_sys)
VARIANT_LEGACY_INCLUDE_compat = creat.c setregid.c setreuid.c sigcompat.c killpg.c
VARIANT_LEGACY_INCLUDE_gdtoa = gdtoa-strtof.c gdtoa-strtod.c gdtoa-strtodg.c
-VARIANT_LEGACY_INCLUDE_gen = clock.c closedir.c confstr.c crypt.c fnmatch.c lockf.c nanosleep.c nftw.c nice.c opendir.c pause.c popen.c rewinddir.c seekdir.c setmode.c sleep.c telldir.c termios.c timezone.c ttyname.c usleep.c wait.c waitpid.c
+VARIANT_LEGACY_INCLUDE_gen = clock.c confstr.c crypt.c fnmatch.c lockf.c nanosleep.c nftw.c nice.c pause.c popen.c setmode.c sleep.c termios.c timezone.c ttyname.c usleep.c wait.c waitpid.c
VARIANT_LEGACY_INCLUDE_locale = wcsftime.c
VARIANT_LEGACY_INCLUDE_net = recv.c send.c
VARIANT_LEGACY_INCLUDE_regex = regcomp.c
VARIANT_LEGACY_INCLUDE_stdio = fdopen.c fopen.c fputs.c freopen.c fwrite.c tempnam.c
VARIANT_LEGACY_INCLUDE_stdlib = getopt.c putenv.c realpath.c setenv.c system.c
VARIANT_LEGACY_INCLUDE_stdtime = localtime.c strftime.c strptime.c
-VARIANT_LEGACY_INCLUDE_string = strerror.c
VARIANT_LEGACY_INCLUDE_sys = msgctl.c semctl.c shmctl.c
// INODE32 symbols
VARIANT_DYLD_INCLUDE_x86_64 = x86_64/string/strcpy.s x86_64/string/strlen.s x86_64/string/strncpy.s x86_64/string/strnlen.s strstr.c
VARIANT_DYLD_INCLUDE_i386 = i386/string/strcpy.s i386/string/strlen.s i386/string/strncpy.s strnlen.c strstr.c
VARIANT_DYLD_INCLUDE_armv7 = strcpy.c arm/string/strlen.s strncpy.c arm/string/strnlen.s arm/string/strstr.s
+VARIANT_DYLD_INCLUDE_arm64 = strcpy.c strncpy.c arm64/string/strnlen.s strstr.c
+VARIANT_DYLD_INCLUDE_arm64_32 = strcpy.c strncpy.c arm64/string/strnlen.s strstr.c
VARIANT_DYLD_INCLUDE_armv7s = $(VARIANT_DYLD_INCLUDE_armv7)
VARIANT_DYLD_INCLUDE_armv7k = $(VARIANT_DYLD_INCLUDE_armv7)