From 507116e319a1470bb0a5040d4d23e5c76955ef97 Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 31 Jan 2020 02:17:07 +0000 Subject: [PATCH] Libc-1353.11.2.tar.gz --- .upstream_base_commits | 6 + Libc.xcodeproj/project.pbxproj | 318 +++++++++++++++++----- Platforms/appletvos/Makefile.inc | 3 + Platforms/bridgeos/Makefile.inc | 3 + Platforms/driverkit/Makefile.inc | 48 ++++ Platforms/iphoneos/Makefile.inc | 3 + Platforms/macosx/Makefile.inc | 3 + Platforms/watchos/Makefile.inc | 3 + darwin/compatibility_hacks.c | 4 +- darwin/libc_private.h | 2 +- gen/FreeBSD/arc4random.c | 215 ++++++--------- gen/FreeBSD/assert.c | 9 +- gen/FreeBSD/dirname.c | 2 +- gen/FreeBSD/glob.3 | 2 +- gen/FreeBSD/opendir.c | 73 +++-- gen/FreeBSD/pause.3 | 5 +- gen/FreeBSD/readdir.c | 38 ++- gen/FreeBSD/rewinddir.c | 2 +- gen/FreeBSD/telldir.c | 2 +- gen/FreeBSD/telldir.h | 11 +- gen/FreeBSD/timespec_get.3 | 81 ++++++ gen/FreeBSD/timespec_get.c | 54 ++++ gen/NetBSD/rbtree.3 | 20 +- gen/backtrace.c | 128 +++++---- gen/confstr.3 | 2 +- gen/directory.3 | 51 +++- gen/nftw.c | 1 + gen/strtofflags.c | 1 + gen/thread_stack_pcs.c | 54 ++-- include/_ctermid.h | 27 ++ include/_stdio.h | 2 + include/_types.h | 2 + include/alloca.h | 2 + include/assert.h | 18 +- include/dirent.h | 13 +- include/err.h | 24 +- include/fts.h | 11 +- include/glob.h | 9 +- include/limits.h | 2 + include/regex.h | 14 +- include/secure/_stdio.h | 4 + include/secure/_string.h | 12 +- include/stdint.h | 49 ++-- include/stdio.h | 25 +- include/stdlib.h | 69 ++++- include/string.h | 6 + include/struct.h | 7 + include/time.h | 20 ++ include/unistd.h | 11 +- include/wchar.h | 22 ++ include/xlocale.h | 1 + libdarwin/bsd.c | 186 +++++-------- libdarwin/ctl.c | 289 ++++++++++++++++++++ libdarwin/h/cleanup.h | 93 +++++-- libdarwin/h/ctl.h | 430 +++++++++++++++++++++++++++++ libdarwin/h/err.h | 12 +- libdarwin/h/mach_utils.h | 6 +- libdarwin/h/stdio.h | 200 ++++++++++++++ libdarwin/h/stdlib.h | 89 +++++- libdarwin/h/string.h | 6 +- libdarwin/internal.h | 10 +- libdarwin/mach.c | 2 +- libdarwin/stdio.c | 176 ++++++++++++ libdarwin/stdlib.c | 37 ++- libdarwin/variant.c | 210 +++++++++++++- locale/xlocale.3 | 4 + locale/xlocale_private.h | 2 +- man/manpages.lst | 1 + net/inet_ntop.c | 275 ++++++++----------- os/api.h | 25 +- os/assumes.c | 35 ++- os/assumes.h | 30 +- os/debug_private.h | 4 +- os/linker_set.h | 252 +++++++++++++++++ os/variant_private.h | 97 ++++++- posix1e/acl_translate.c | 2 +- secure/chk_fail.c | 87 +----- secure/snprintf_chk.c | 19 ++ secure/sprintf_chk.c | 22 ++ stdio/FreeBSD/fclose.c | 2 +- stdio/FreeBSD/fflush.3 | 27 +- stdio/FreeBSD/fflush.c | 115 ++++---- stdio/FreeBSD/makebuf.c | 2 +- stdio/FreeBSD/vfprintf.c | 7 + stdlib/FreeBSD/abort.c | 18 +- stdlib/FreeBSD/atexit.c | 7 +- stdlib/FreeBSD/realpath.c | 2 + stdtime/FreeBSD/asctime.c | 3 +- stdtime/FreeBSD/strptime.c | 171 ++++++------ string/FreeBSD/rpmatch.3 | 65 +++++ string/FreeBSD/rpmatch.c | 57 ++++ string/FreeBSD/timingsafe_bcmp.c | 9 +- sys/OSThermalNotification.c | 6 +- sys/OpenBSD/stack_protector.c | 31 +-- sys/_libc_fork_child.c | 4 + sys/_libc_init.c | 2 - sys/settimeofday.c | 7 +- sys/sigaction.c | 4 + tests/Makefile | 19 +- tests/abort_tests.c | 119 ++++++++ tests/acl_tests.c | 9 + tests/backtrace.c | 40 ++- tests/darwin_bsd.c | 61 +++++ tests/fflush.c | 437 ++++++++++++++++++++++++++++++ tests/net.c | 44 ++- tests/netbsd_getcwd.c | 2 + tests/os_simple_hash.c | 23 ++ tests/os_variant.c | 11 +- tests/osvariantutil.c | 80 ++++++ tests/rpmatch.c | 158 +++++++++++ tests/stdtime.c | 4 +- tests/strlcpy.c | 2 +- tests/strptime.c | 70 +++++ tests/timespec_get.c | 19 ++ tests/timingsafe_bcmp.c | 21 +- xcodescripts/generate_features.pl | 2 + xcodescripts/headers.sh | 136 ++++++++-- xcodescripts/libc.xcconfig | 42 ++- xcodescripts/manpages.sh | 1 + xcodescripts/variants.xcconfig | 4 +- 120 files changed, 4839 insertions(+), 1099 deletions(-) create mode 100644 Platforms/driverkit/Makefile.inc create mode 100644 gen/FreeBSD/timespec_get.3 create mode 100644 gen/FreeBSD/timespec_get.c create mode 100644 include/_ctermid.h create mode 100755 libdarwin/ctl.c create mode 100644 libdarwin/h/ctl.h create mode 100644 os/linker_set.h create mode 100644 string/FreeBSD/rpmatch.3 create mode 100644 string/FreeBSD/rpmatch.c create mode 100644 tests/abort_tests.c create mode 100644 tests/acl_tests.c create mode 100644 tests/darwin_bsd.c create mode 100644 tests/fflush.c create mode 100644 tests/osvariantutil.c create mode 100644 tests/rpmatch.c create mode 100644 tests/timespec_get.c diff --git a/.upstream_base_commits b/.upstream_base_commits index cfc62c5..f1fa5e8 100644 --- a/.upstream_base_commits +++ b/.upstream_base_commits @@ -14,6 +14,8 @@ gen/FreeBSD/raise3 freebsd lib/libc/gen/raise.3 6b42c90c1ff5f7c35431eced41b62134 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/timespec_get.c freebsd lib/libc/gen/timespec_get.c 7cbaa4254c0f10f7c00014ce9591ca60abfa57fb +gen/FreeBSD/timespec_get.3 freebsd lib/libc/gen/timespec_get.3 7cbaa4254c0f10f7c00014ce9591ca60abfa57fb gen/FreeBSD/ttyname.3 freebsd lib/libc/gen/ttyname.3 84be924362c6e5f469564d418c928c5b1b4a2457 gen/FreeBSD/ttyslot.c freebsd lib/libc/gen/ttyslot.c 898928e8d0a0bab201c1ef232e01cafa27322dae gen/FreeBSD/unvis.c freebsd contrib/libc-vis/unvis.c 9e3e4b88576d01efe1f56469cac79e116bb62c67 @@ -23,6 +25,7 @@ gen/FreeBSD/vis.c freebsd contrib/libc-vis/unvis.c 9e3e4b88576d01efe1f56469cac79 gen/FreeBSD/vis.3 freebsd contrib/libc-vis/unvis.3 9e3e4b88576d01efe1f56469cac79e116bb62c67 gen/FreeBSD/vis.h freebsd contrib/libc-vis/unvis.3 9e3e4b88576d01efe1f56469cac79e116bb62c67 gen/NetBSD/rbtree.3 netbsd share/man/man3/rbtree.3 a6d78d4a28be21d6006d3c609f31967c0e536779 +gen/directory.3 freebsd lib/libc/gen/directory.3 7cbaa4254c0f10f7c00014ce9591ca60abfa57fb gen/fts.c openbsd gen/fts.c 9936a0e983044822375a0d5cdebec20c3623866c include/glob.h freebsd include/glob.h ececcb3d95a00665500a1f799a118fc4eaf6750b include/readpassphrase.h freebsd include/readpassphrase.h e0a2d4f15ed9e93fcb62544ed65f7a98e2339c3b @@ -56,6 +59,8 @@ stdtime/FreeBSD/tzfile.h freebsd contrib/tzcode/stdtime/tzfile.h 000663e80955a04 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/rpmatch.c freebsd lib/libc/locale/rpmatch.c 8919cfa0b0054509fb3e01f3b22e140645bc6407 +string/FreeBSD/rpmatch.3 freebsd lib/libc/locale/rpmatch.3 8919cfa0b0054509fb3e01f3b22e140645bc6407 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 @@ -86,3 +91,4 @@ gen/FreeBSD/scandir.c freebsd lib/libc/gen/scandir.c 0127b103f27578fc7f9cc3389b2 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 +net/inet_ntop.c freebsd lib/libc/inet/inet_ntop.c f0171d33b464dee5ac308f1d13ede2ddd9d030a7 diff --git a/Libc.xcodeproj/project.pbxproj b/Libc.xcodeproj/project.pbxproj index b0eedf2..8576016 100644 --- a/Libc.xcodeproj/project.pbxproj +++ b/Libc.xcodeproj/project.pbxproj @@ -29,6 +29,31 @@ name = Libc_darwin; productName = libdarwin; }; + E47E980E22150EAD006E312E /* Libc */ = { + isa = PBXAggregateTarget; + buildConfigurationList = E47E981122150EAD006E312E /* Build configuration list for PBXAggregateTarget "Libc" */; + buildPhases = ( + ); + dependencies = ( + E47E981722150F0A006E312E /* PBXTargetDependency */, + E47E981922150F2C006E312E /* PBXTargetDependency */, + E47E981B22150F2F006E312E /* PBXTargetDependency */, + E47E981D22150F32006E312E /* PBXTargetDependency */, + ); + name = Libc; + productName = Libc; + }; + E47E981222150EBB006E312E /* Libc_driverkit */ = { + isa = PBXAggregateTarget; + buildConfigurationList = E47E981322150EBB006E312E /* Build configuration list for PBXAggregateTarget "Libc_driverkit" */; + buildPhases = ( + ); + dependencies = ( + E47E981F22150F3C006E312E /* PBXTargetDependency */, + ); + name = Libc_driverkit; + productName = Libc_driverkit; + }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ @@ -94,6 +119,7 @@ 3FD4D48E1472F4B200075CCE /* dirfd.c in Sources */ = {isa = PBXBuildFile; fileRef = 3FB7E1B4146EF2E000843438 /* dirfd.c */; }; 4B075C8E208BE9F200FD4F23 /* variant_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 926F73991E03E8D6001E049D /* variant_private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4B0899BC2046258F001360A4 /* cleanup.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0899B920460FAC001360A4 /* cleanup.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4B09323421C9C08F006063D6 /* mach_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B09323321C9C088006063D6 /* mach_utils.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4B20DB4D202B81A4005C2327 /* bsd.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA6E56A202ACF7A00F38D3A /* bsd.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4B20DB50202B81A4005C2327 /* err.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA6E563202AC0C200F38D3A /* err.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4B20DB51202B81A4005C2327 /* errno.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA6E55B202AB1F100F38D3A /* errno.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -109,18 +135,21 @@ 4B2C64A915519BC800342BFA /* assumes.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B2C64A215519BAF00342BFA /* assumes.c */; }; 4B2C64AA15519BCB00342BFA /* assumes.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B2C64A215519BAF00342BFA /* assumes.c */; }; 4B2C64BA1551B03700342BFA /* assumes.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B2C64A215519BAF00342BFA /* assumes.c */; }; + 4B450FFB211A56DD0029AF5D /* ctl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B450FFA211A56DC0029AF5D /* ctl.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4B450FFD211A56EC0029AF5D /* ctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B450FFC211A56EC0029AF5D /* ctl.c */; }; 4B4E643F2069E94A00C4D8D5 /* internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B2C50E41F8453FA005DA2B6 /* internal.h */; }; 4B69E81320800D47008D13D2 /* libdarwin_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B69E81220800BE9008D13D2 /* libdarwin_init.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4B6CFC042065B9FF0022DBAD /* mach.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B6CFC032065B9FF0022DBAD /* mach.c */; }; 4B6D181D206DEFBD00C00E37 /* mach_exception.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6D181C206DEFBD00C00E37 /* mach_exception.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4B6D181F206DF1E200C00E37 /* exception.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B6D181E206DF1E200C00E37 /* exception.c */; }; 4B782979208926A80070E1FF /* api.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B782978208926A70070E1FF /* api.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4B8A6F3221C99ACC00D00D67 /* linker_set.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8A6F3121C99A0E00D00D67 /* linker_set.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4BA6E55F202AB35900F38D3A /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BA6E55E202AB35900F38D3A /* string.c */; }; 4BA6E562202AC06300F38D3A /* err.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BA6E561202AC06300F38D3A /* err.c */; }; 4BA6E566202AC94800F38D3A /* stdlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BA6E565202AC94800F38D3A /* stdlib.c */; }; 4BA6E569202ACDAA00F38D3A /* stdio.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BA6E568202ACDAA00F38D3A /* stdio.c */; }; 4BA6E56C202AD02900F38D3A /* bsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BA6E56B202AD02900F38D3A /* bsd.c */; }; - 4BCC350F20659AD500A4CBAA /* mach_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCC350E20659AD500A4CBAA /* mach_utils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4BCC350F20659AD500A4CBAA /* linker_set.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCC350E20659AD500A4CBAA /* linker_set.h */; settings = {ATTRIBUTES = (Private, ); }; }; 63D4060613DDEDF10094DD56 /* stpcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4060513DDEDF10094DD56 /* stpcpy.c */; }; 63D4060813DDEDFF0094DD56 /* stpcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4060513DDEDF10094DD56 /* stpcpy.c */; }; 63D4060A13DDEEA20094DD56 /* stpncpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4060913DDEEA10094DD56 /* stpncpy.c */; }; @@ -129,6 +158,26 @@ 63D4060E13DDF26A0094DD56 /* strcat.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4060C13DDF26A0094DD56 /* strcat.c */; }; 63D4061013DDF4340094DD56 /* strncat.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4060F13DDF4340094DD56 /* strncat.c */; }; 63D4061113DDF4340094DD56 /* strncat.c in Sources */ = {isa = PBXBuildFile; fileRef = 63D4060F13DDF4340094DD56 /* strncat.c */; }; + 7756338822F3B539002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756338922F3B53A002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756338A22F3B53B002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756338B22F3B546002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756338C22F3B549002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756338D22F3B54A002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756338E22F3B54A002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756338F22F3B54B002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756339022F3B54E002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 7756339122F3B550002F1707 /* rpmatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 7711D82422F37DB600E7296B /* rpmatch.c */; }; + 922D0C0A21BFA1530072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C0B21BFA19A0072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C0C21BFA19A0072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C0D21BFA19B0072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C0E21BFA1A10072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C0F21BFA1A20072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C1021BFA1A30072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C1121BFA1A30072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C1221BFA1A40072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; + 922D0C1321BFA1A40072834D /* timespec_get.c in Sources */ = {isa = PBXBuildFile; fileRef = 922D0C0921BFA1530072834D /* timespec_get.c */; }; 926F73981E03E8C4001E049D /* variant.c in Sources */ = {isa = PBXBuildFile; fileRef = 926F73971E03E8C4001E049D /* variant.c */; }; 92767C841E0A7E2700AB9C76 /* init.c in Sources */ = {isa = PBXBuildFile; fileRef = 92767C821E0A7E2100AB9C76 /* init.c */; }; 928841361EA75555001064D1 /* dirstat_collection.c in Sources */ = {isa = PBXBuildFile; fileRef = 928841341EA7554D001064D1 /* dirstat_collection.c */; }; @@ -5522,13 +5571,6 @@ remoteGlobalIDString = C95B7ED9138F3C55004311DA; remoteInfo = Variant_DarwinExtsn; }; - C0E345E51C58323000E749C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C9B53597138D9A690028D27C /* Project object */; - proxyType = 1; - remoteGlobalIDString = C0E343831C582ECB00E749C2; - remoteInfo = libc_static; - }; C925D2001518FA5D003D315B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = C9B53597138D9A690028D27C /* Project object */; @@ -5536,20 +5578,6 @@ remoteGlobalIDString = C95B7ED9138F3C55004311DA; remoteInfo = Variant_DarwinExtsn; }; - C925D2021518FEBE003D315B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C9B53597138D9A690028D27C /* Project object */; - proxyType = 1; - remoteGlobalIDString = C97A6F1E1517AF53005E1998; - remoteInfo = libc_eOS.a; - }; - C942130813901709004BA536 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C9B53597138D9A690028D27C /* Project object */; - proxyType = 1; - remoteGlobalIDString = C942102D13900C8A004BA536; - remoteInfo = libc.a; - }; C95B817C138F3F72004311DA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = C9B53597138D9A690028D27C /* Project object */; @@ -5648,6 +5676,41 @@ remoteGlobalIDString = C9258093138E2D3100B3107C; remoteInfo = NetBSD; }; + E47E981622150F0A006E312E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9B53597138D9A690028D27C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C9D9432E138DB73300FB7ACC; + remoteInfo = libsystem_c.dylib; + }; + E47E981822150F2C006E312E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9B53597138D9A690028D27C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C942102D13900C8A004BA536; + remoteInfo = libc_dyld; + }; + E47E981A22150F2F006E312E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9B53597138D9A690028D27C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C0E343831C582ECB00E749C2; + remoteInfo = libc_static; + }; + E47E981C22150F32006E312E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9B53597138D9A690028D27C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C97A6F1E1517AF53005E1998; + remoteInfo = libc_eOS.a; + }; + E47E981E22150F3C006E312E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9B53597138D9A690028D27C /* Project object */; + proxyType = 1; + remoteGlobalIDString = C9D9432E138DB73300FB7ACC; + remoteInfo = libsystem_c.dylib; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -5673,15 +5736,19 @@ 3FD14572171D42B300B7BAF5 /* bcopy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bcopy.c; sourceTree = ""; }; 3FF283231A4764240098AD2C /* sim-compat-symlink.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "sim-compat-symlink.sh"; sourceTree = ""; }; 4B0899B920460FAC001360A4 /* cleanup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cleanup.h; sourceTree = ""; }; + 4B09323321C9C088006063D6 /* mach_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_utils.h; sourceTree = ""; }; 4B151E0B1F8574B400F3F52F /* style.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = style.3; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.man; }; 4B2C50E41F8453FA005DA2B6 /* internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; }; 4B2C64A215519BAF00342BFA /* assumes.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = assumes.c; path = os/assumes.c; sourceTree = ""; }; 4B2C64AB15519C3400342BFA /* assumes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = assumes.h; path = os/assumes.h; sourceTree = ""; }; + 4B450FFA211A56DC0029AF5D /* ctl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ctl.h; sourceTree = ""; }; + 4B450FFC211A56EC0029AF5D /* ctl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ctl.c; sourceTree = ""; }; 4B69E81220800BE9008D13D2 /* libdarwin_init.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libdarwin_init.h; sourceTree = ""; }; 4B6CFC032065B9FF0022DBAD /* mach.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach.c; sourceTree = ""; }; 4B6D181C206DEFBD00C00E37 /* mach_exception.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mach_exception.h; sourceTree = ""; }; 4B6D181E206DF1E200C00E37 /* exception.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = exception.c; sourceTree = ""; }; 4B782978208926A70070E1FF /* api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = api.h; path = os/api.h; sourceTree = ""; }; + 4B8A6F3121C99A0E00D00D67 /* linker_set.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = linker_set.h; path = os/linker_set.h; sourceTree = ""; }; 4BA6E55B202AB1F100F38D3A /* errno.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = errno.h; sourceTree = ""; }; 4BA6E55D202AB31100F38D3A /* string.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = string.h; sourceTree = ""; }; 4BA6E55E202AB35900F38D3A /* string.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = string.c; sourceTree = ""; }; @@ -5693,11 +5760,15 @@ 4BA6E568202ACDAA00F38D3A /* stdio.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = stdio.c; sourceTree = ""; }; 4BA6E56A202ACF7A00F38D3A /* bsd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bsd.h; sourceTree = ""; }; 4BA6E56B202AD02900F38D3A /* bsd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bsd.c; sourceTree = ""; }; - 4BCC350E20659AD500A4CBAA /* mach_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_utils.h; sourceTree = ""; }; + 4BCC350E20659AD500A4CBAA /* linker_set.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = linker_set.h; path = ../../os/linker_set.h; sourceTree = ""; }; 63D4060513DDEDF10094DD56 /* stpcpy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stpcpy.c; sourceTree = ""; }; 63D4060913DDEEA10094DD56 /* stpncpy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stpncpy.c; sourceTree = ""; }; 63D4060C13DDF26A0094DD56 /* strcat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strcat.c; sourceTree = ""; }; 63D4060F13DDF4340094DD56 /* strncat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strncat.c; sourceTree = ""; }; + 7711D82422F37DB600E7296B /* rpmatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = rpmatch.c; sourceTree = ""; }; + 7711D82622F3A52400E7296B /* rpmatch.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = rpmatch.3; sourceTree = ""; }; + 922D0C0821BFA1520072834D /* timespec_get.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = timespec_get.3; sourceTree = ""; }; + 922D0C0921BFA1530072834D /* timespec_get.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timespec_get.c; sourceTree = ""; }; 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 = ""; }; 926F73991E03E8D6001E049D /* variant_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = variant_private.h; path = os/variant_private.h; sourceTree = ""; }; @@ -6865,7 +6936,10 @@ 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 = ""; }; E41BEA97178E72E100E348BB /* Libc.order */ = {isa = PBXFileReference; lastKnownFileType = text; path = Libc.order; sourceTree = ""; }; + E464104B224C5EA2001B23EF /* __wctype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = __wctype.h; sourceTree = ""; }; + E464104C224C5F19001B23EF /* _ctype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _ctype.h; sourceTree = ""; }; E4A877A6174D82FB000DBB55 /* alias.list */ = {isa = PBXFileReference; lastKnownFileType = text; path = alias.list; sourceTree = ""; }; + E4EDB7262227DF25006A8322 /* Makefile.inc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.pascal; path = Makefile.inc; sourceTree = ""; }; FC2ED60E157D4BE70098EC69 /* inet_ntop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inet_ntop.c; sourceTree = ""; }; FC2ED60F157D4BE70098EC69 /* inet_pton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inet_pton.c; sourceTree = ""; }; FC2ED623157D4DA90098EC69 /* inet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inet.h; sourceTree = ""; }; @@ -7026,10 +7100,12 @@ children = ( 4BA6E56A202ACF7A00F38D3A /* bsd.h */, 4B0899B920460FAC001360A4 /* cleanup.h */, + 4B450FFA211A56DC0029AF5D /* ctl.h */, 4BA6E563202AC0C200F38D3A /* err.h */, 4BA6E55B202AB1F100F38D3A /* errno.h */, 4B6D181C206DEFBD00C00E37 /* mach_exception.h */, - 4BCC350E20659AD500A4CBAA /* mach_utils.h */, + 4B09323321C9C088006063D6 /* mach_utils.h */, + 4BCC350E20659AD500A4CBAA /* linker_set.h */, 4BA6E567202ACAFA00F38D3A /* stdio.h */, 4BA6E564202AC43700F38D3A /* stdlib.h */, 4BA6E55D202AB31100F38D3A /* string.h */, @@ -7044,6 +7120,7 @@ isa = PBXGroup; children = ( 4B782978208926A70070E1FF /* api.h */, + 4B8A6F3121C99A0E00D00D67 /* linker_set.h */, 926F73991E03E8D6001E049D /* variant_private.h */, 2DF67CE7184F9CD000B83A3D /* debug_private.h */, 2DF67CDD184F9CBE00B83A3D /* debug_private.c */, @@ -7060,6 +7137,7 @@ 9280EA171E59BC8A007A6F58 /* AppleInternalVariant.plist */, 4B2C50E41F8453FA005DA2B6 /* internal.h */, 4BA6E56B202AD02900F38D3A /* bsd.c */, + 4B450FFC211A56EC0029AF5D /* ctl.c */, 4B6D181E206DF1E200C00E37 /* exception.c */, 4BA6E561202AC06300F38D3A /* err.c */, 4B6CFC032065B9FF0022DBAD /* mach.c */, @@ -7690,6 +7768,8 @@ C9B5379E138D9E990028D27C /* time.c */, C9B537A0138D9E990028D27C /* times.3 */, C9B537A2138D9E990028D27C /* times.c */, + 922D0C0821BFA1520072834D /* timespec_get.3 */, + 922D0C0921BFA1530072834D /* timespec_get.c */, C9B537A3138D9E990028D27C /* timezone.3 */, C9B537A4138D9E990028D27C /* timezone.c */, C9B537A5138D9E990028D27C /* ttyname.3 */, @@ -7757,6 +7837,8 @@ C9B5384F138D9E990028D27C /* include */ = { isa = PBXGroup; children = ( + E464104B224C5EA2001B23EF /* __wctype.h */, + E464104C224C5F19001B23EF /* _ctype.h */, 3006CB0E20BF7482003C5C79 /* _stdio.h */, C9B53850138D9E990028D27C /* _locale.h */, FC60BAD016555A4A00033196 /* _types */, @@ -8197,6 +8279,7 @@ isa = PBXGroup; children = ( C975E22B1A12ECA00093B345 /* appletv */, + E4EDB7252227DF25006A8322 /* driverkit */, C9B53A46138D9E990028D27C /* iphoneos */, C9B53A48138D9E990028D27C /* macosx */, C9A288A61ACDBA95004A33A7 /* watchos */, @@ -8690,6 +8773,8 @@ C9B53D0B138D9E9A0028D27C /* memset.3 */, C9B53D0E138D9E9A0028D27C /* rindex.3 */, C9B53D10138D9E9A0028D27C /* rindex.c */, + 7711D82622F3A52400E7296B /* rpmatch.3 */, + 7711D82422F37DB600E7296B /* rpmatch.c */, C9B53D13138D9E9A0028D27C /* strcasecmp.3 */, C9B53D15138D9E9A0028D27C /* strcasecmp.c */, C9B53D17138D9E9A0028D27C /* strcasestr.c */, @@ -8899,6 +8984,14 @@ path = xcodescripts; sourceTree = ""; }; + E4EDB7252227DF25006A8322 /* driverkit */ = { + isa = PBXGroup; + children = ( + E4EDB7262227DF25006A8322 /* Makefile.inc */, + ); + path = driverkit; + sourceTree = ""; + }; FC60BAD016555A4A00033196 /* _types */ = { isa = PBXGroup; children = ( @@ -8922,16 +9015,19 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4B450FFB211A56DD0029AF5D /* ctl.h in Headers */, + 4B782979208926A80070E1FF /* api.h in Headers */, 4B6D181D206DEFBD00C00E37 /* mach_exception.h in Headers */, 4B20DB4D202B81A4005C2327 /* bsd.h in Headers */, 4B20DB50202B81A4005C2327 /* err.h in Headers */, 4B20DB51202B81A4005C2327 /* errno.h in Headers */, 4B20DB52202B81A4005C2327 /* stdio.h in Headers */, 4B0899BC2046258F001360A4 /* cleanup.h in Headers */, - 4BCC350F20659AD500A4CBAA /* mach_utils.h in Headers */, + 4BCC350F20659AD500A4CBAA /* linker_set.h in Headers */, 4B20DB53202B81A4005C2327 /* stdlib.h in Headers */, + 4B8A6F3221C99ACC00D00D67 /* linker_set.h in Headers */, + 4B09323421C9C08F006063D6 /* mach_utils.h in Headers */, 4B69E81320800D47008D13D2 /* libdarwin_init.h in Headers */, - 4B782979208926A80070E1FF /* api.h in Headers */, 4B20DB54202B81A4005C2327 /* string.h in Headers */, 4B075C8E208BE9F200FD4F23 /* variant_private.h in Headers */, 4B4E643F2069E94A00C4D8D5 /* internal.h in Headers */, @@ -9230,9 +9326,6 @@ C9EB326D138F74D20075BB52 /* PBXTargetDependency */, C9EB3515138F771F0075BB52 /* PBXTargetDependency */, 3F51211716C318EB00AFB431 /* PBXTargetDependency */, - C942130913901709004BA536 /* PBXTargetDependency */, - C0E345E61C58323000E749C2 /* PBXTargetDependency */, - C925D2031518FEBE003D315B /* PBXTargetDependency */, ); name = libsystem_c.dylib; productName = Libc; @@ -9315,6 +9408,12 @@ 928F25D01BEACED7007B13C7 = { CreatedOnToolsVersion = 7.1; }; + E47E980E22150EAD006E312E = { + CreatedOnToolsVersion = 11.0; + }; + E47E981222150EBB006E312E = { + CreatedOnToolsVersion = 11.0; + }; }; }; buildConfigurationList = C9B5359A138D9A690028D27C /* Build configuration list for PBXProject "Libc" */; @@ -9322,6 +9421,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = C9B53595138D9A690028D27C; @@ -9329,6 +9429,10 @@ projectDirPath = ""; projectRoot = ""; targets = ( + E47E980E22150EAD006E312E /* Libc */, + 926F739D1E046E55001E049D /* Libc_darwin */, + E47E981222150EBB006E312E /* Libc_driverkit */, + 925E7FE619E8945900AC7889 /* Libc_tests */, C9D9432E138DB73300FB7ACC /* libsystem_c.dylib */, C942102D13900C8A004BA536 /* libc_dyld */, C0E343831C582ECB00E749C2 /* libc_static */, @@ -9345,10 +9449,8 @@ C9EB2FC9138F6D880075BB52 /* Variant_Legacy */, C9EB326F138F75580075BB52 /* Variant_Inode32 */, 3F51206A16C3174300AFB431 /* FortifySource */, - 925E7FE619E8945900AC7889 /* Libc_tests */, - 928F25D01BEACED7007B13C7 /* darwintests */, - 926F739D1E046E55001E049D /* Libc_darwin */, 926F73911E03E2A3001E049D /* libsystem_darwin.dylib */, + 928F25D01BEACED7007B13C7 /* darwintests */, ); }; /* End PBXProject section */ @@ -9367,7 +9469,8 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = "/bin/bash -e -x"; - shellScript = ". \"${SCRIPT_INPUT_FILE_0}\"\n"; + shellScript = ". \"${SCRIPT_INPUT_FILE_0}\""; + showEnvVarsInLog = 0; }; 3F51206B16C3174300AFB431 /* Generate libc-features.h */ = { isa = PBXShellScriptBuildPhase; @@ -9397,6 +9500,7 @@ runOnlyForDeploymentPostprocessing = 0; shellPath = "/bin/bash -e -x"; shellScript = "mkdir -p ${TAPI_PUBLIC_HEADER_PATH}"; + showEnvVarsInLog = 0; }; 3FF283291A4764370098AD2C /* Simulator Build Compat Symlink */ = { isa = PBXShellScriptBuildPhase; @@ -9412,6 +9516,7 @@ runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/bash; shellScript = ". \"${SCRIPT_INPUT_FILE_0}\""; + showEnvVarsInLog = 0; }; 9280EA241E5A5D6F007A6F58 /* Copy AppleFooVariant.plists */ = { isa = PBXShellScriptBuildPhase; @@ -9457,6 +9562,7 @@ runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; shellScript = ". \"${SCRIPT_INPUT_FILE_0}\" /bin/ln -sf libc_dyld.a ${DSTROOT}${INSTALL_PATH}/libc.a"; + showEnvVarsInLog = 0; }; C0E3438E1C582ECB00E749C2 /* Build Link List */ = { isa = PBXShellScriptBuildPhase; @@ -9472,6 +9578,7 @@ runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = ". \"${SCRIPT_INPUT_FILE_0}\""; + showEnvVarsInLog = 0; }; C0E3438F1C582ECB00E749C2 /* Generate libc-features.h */ = { isa = PBXShellScriptBuildPhase; @@ -9500,7 +9607,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C0E345E41C5830C200E749C2 /* Symlink libc.a to a loaderd path */ = { @@ -9518,6 +9625,7 @@ runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; shellScript = ". \"${SCRIPT_INPUT_FILE_0}\" /bin/ln -sf ../../../../${INSTALL_PATH}/libc.a ${DSTROOT}/usr/local/lib/loaderd/libc.a"; + showEnvVarsInLog = 0; }; C9194B4B140E3A7100BE0C3A /* Build Link Lists */ = { isa = PBXShellScriptBuildPhase; @@ -9533,6 +9641,7 @@ runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = ". \"${SCRIPT_INPUT_FILE_0}\""; + showEnvVarsInLog = 0; }; C93D6152143D321000EB9023 /* Sanitise Headers (rdar://problem/10241868) */ = { isa = PBXShellScriptBuildPhase; @@ -9577,7 +9686,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C942135B13905EB9004BA536 /* Install Manpages */ = { @@ -9624,7 +9733,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C95B8185138F52B0004311DA /* Generate libc-features.h */ = { @@ -9654,7 +9763,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C95B842B138F53DB004311DA /* Generate libc-features.h */ = { @@ -9684,7 +9793,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C965CBF3143BBFF7003912CE /* Remove deps.c */ = { @@ -9701,6 +9810,7 @@ runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = ". \"${SCRIPT_INPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; C9766152138ECA3800741512 /* Patch Headers */ = { isa = PBXShellScriptBuildPhase; @@ -9714,7 +9824,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C976616D138EF15900741512 /* Generate libc-features.h */ = { @@ -9759,7 +9869,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C9950E6B1390D2DC009863B6 /* Install Headers */ = { @@ -9792,6 +9902,7 @@ runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = ". \"${SCRIPT_INPUT_FILE_0}\""; + showEnvVarsInLog = 0; }; C9BD3C3C138F189200B389FD /* Generate libc-features.h */ = { isa = PBXShellScriptBuildPhase; @@ -9880,7 +9991,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; C9EB3270138F75580075BB52 /* Generate libc-features.h */ = { @@ -9910,7 +10021,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDKROOT}/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\""; + shellScript = "perl \"${SRCROOT}/xcodescripts/patch_headers_variants.pl\" \\\n \"${SDK_SYSTEM_FRAMEWORK_HEADERS}\" \\\n \"${DERIVED_FILES_DIR}/System.framework/Versions/B\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -9948,6 +10059,7 @@ 926F73981E03E8C4001E049D /* variant.c in Sources */, 4BA6E566202AC94800F38D3A /* stdlib.c in Sources */, 92D763E01EA6DA3A001467FC /* dirstat.c in Sources */, + 4B450FFD211A56EC0029AF5D /* ctl.c in Sources */, 4BA6E569202ACDAA00F38D3A /* stdio.c in Sources */, 4B6D181F206DF1E200C00E37 /* exception.c in Sources */, 92767C841E0A7E2700AB9C76 /* init.c in Sources */, @@ -10302,6 +10414,7 @@ C0E344DF1C582ECB00E749C2 /* ftell.c in Sources */, C0E344E01C582ECB00E749C2 /* funopen.c in Sources */, C0E344E11C582ECB00E749C2 /* fvwrite.c in Sources */, + 922D0C0C21BFA19A0072834D /* timespec_get.c in Sources */, C0E344E21C582ECB00E749C2 /* fwalk.c in Sources */, C0E344E31C582ECB00E749C2 /* fwide.c in Sources */, C0E344E41C582ECB00E749C2 /* fwprintf.c in Sources */, @@ -10364,6 +10477,7 @@ C0E3451D1C582ECB00E749C2 /* wprintf.c in Sources */, C0E3451E1C582ECB00E749C2 /* wscanf.c in Sources */, C0E3451F1C582ECB00E749C2 /* wsetup.c in Sources */, + 7756338922F3B53A002F1707 /* rpmatch.c in Sources */, C0E345201C582ECB00E749C2 /* a64l.c in Sources */, C0E345211C582ECB00E749C2 /* _Exit_.c in Sources */, C0E345221C582ECB00E749C2 /* abort.c in Sources */, @@ -10797,6 +10911,7 @@ C9257FD4138E1CC000B3107C /* makebuf.c in Sources */, C9257FD5138E1CC000B3107C /* mktemp.c in Sources */, C9257FD6138E1CC000B3107C /* perror.c in Sources */, + 7756338B22F3B546002F1707 /* rpmatch.c in Sources */, C9257FD7138E1CC000B3107C /* printf-pos.c in Sources */, C9257FD8138E1CC000B3107C /* printf.c in Sources */, C9257FD9138E1CC000B3107C /* putc.c in Sources */, @@ -10968,6 +11083,7 @@ C9421022138F2661004BA536 /* machdep_ldisd.c in Sources */, C9421023138F2661004BA536 /* machdep_ldisdd.c in Sources */, C9421024138F2661004BA536 /* machdep_ldisQ.c in Sources */, + 922D0C0A21BFA1530072834D /* timespec_get.c in Sources */, C9421025138F2661004BA536 /* machdep_ldisx.c in Sources */, C95B7ED7138F3BEA004311DA /* rune.c in Sources */, C9EB2FC1138F6BB00075BB52 /* merge_b.c in Sources */, @@ -11149,6 +11265,7 @@ C94210D213900C8A004BA536 /* sleep.c in Sources */, C94210D313900C8A004BA536 /* srand48.c in Sources */, C94210D413900C8A004BA536 /* stringlist.c in Sources */, + 922D0C0B21BFA19A0072834D /* timespec_get.c in Sources */, C94210D513900C8A004BA536 /* sysconf.c in Sources */, C94210D613900C8A004BA536 /* sysctl.c in Sources */, C94210D713900C8A004BA536 /* sysctlbyname.c in Sources */, @@ -11529,6 +11646,7 @@ C94212B813900C8A004BA536 /* pack.c in Sources */, C94212B913900C8A004BA536 /* parse.c in Sources */, C94212BA13900C8A004BA536 /* unpack.c in Sources */, + 7756338822F3B539002F1707 /* rpmatch.c in Sources */, C94212BB13900C8A004BA536 /* unparse.c in Sources */, C94212C613900C8A004BA536 /* scandir_b.c in Sources */, 63D4060813DDEDFF0094DD56 /* stpcpy.c in Sources */, @@ -11564,6 +11682,7 @@ C95B7EF6138F3C55004311DA /* bt_close.c in Sources */, C95B7EF7138F3C55004311DA /* bt_conv.c in Sources */, C95B7EF8138F3C55004311DA /* bt_debug.c in Sources */, + 7756338D22F3B54A002F1707 /* rpmatch.c in Sources */, C95B7EF9138F3C55004311DA /* bt_delete.c in Sources */, C95B7EFA138F3C55004311DA /* bt_get.c in Sources */, C95B7EFB138F3C55004311DA /* bt_open.c in Sources */, @@ -11955,6 +12074,7 @@ C95B80D3138F3C55004311DA /* setenv.c in Sources */, C95B80D4138F3C55004311DA /* strhash.c in Sources */, C95B80D5138F3C55004311DA /* strtoimax.c in Sources */, + 922D0C1021BFA1A30072834D /* timespec_get.c in Sources */, C95B80D6138F3C55004311DA /* strtol.c in Sources */, C95B80D7138F3C55004311DA /* strtoll.c in Sources */, C95B80D8138F3C55004311DA /* strtoq.c in Sources */, @@ -12098,6 +12218,7 @@ C95B81A1138F52B0004311DA /* bt_close.c in Sources */, C95B81A2138F52B0004311DA /* bt_conv.c in Sources */, C95B81A3138F52B0004311DA /* bt_debug.c in Sources */, + 7756338E22F3B54A002F1707 /* rpmatch.c in Sources */, C95B81A4138F52B0004311DA /* bt_delete.c in Sources */, C95B81A5138F52B0004311DA /* bt_get.c in Sources */, C95B81A6138F52B0004311DA /* bt_open.c in Sources */, @@ -12489,6 +12610,7 @@ C95B837E138F52B0004311DA /* setenv.c in Sources */, C95B837F138F52B0004311DA /* strhash.c in Sources */, C95B8380138F52B0004311DA /* strtoimax.c in Sources */, + 922D0C1121BFA1A30072834D /* timespec_get.c in Sources */, C95B8381138F52B0004311DA /* strtol.c in Sources */, C95B8382138F52B0004311DA /* strtoll.c in Sources */, C95B8383138F52B0004311DA /* strtoq.c in Sources */, @@ -12632,6 +12754,7 @@ C95B8447138F53DB004311DA /* bt_close.c in Sources */, C95B8448138F53DB004311DA /* bt_conv.c in Sources */, C95B8449138F53DB004311DA /* bt_debug.c in Sources */, + 7756338F22F3B54B002F1707 /* rpmatch.c in Sources */, C95B844A138F53DB004311DA /* bt_delete.c in Sources */, C95B844B138F53DB004311DA /* bt_get.c in Sources */, C95B844C138F53DB004311DA /* bt_open.c in Sources */, @@ -13023,6 +13146,7 @@ C95B8624138F53DB004311DA /* setenv.c in Sources */, C95B8625138F53DB004311DA /* strhash.c in Sources */, C95B8626138F53DB004311DA /* strtoimax.c in Sources */, + 922D0C1221BFA1A40072834D /* timespec_get.c in Sources */, C95B8627138F53DB004311DA /* strtol.c in Sources */, C95B8628138F53DB004311DA /* strtoll.c in Sources */, C95B8629138F53DB004311DA /* strtoq.c in Sources */, @@ -13399,6 +13523,7 @@ C97A70AC1517AF53005E1998 /* mbrune.c in Sources */, C97A70AD1517AF53005E1998 /* runedepreciated.c in Sources */, C97A70AE1517AF53005E1998 /* setinvalidrune.c in Sources */, + 7756338A22F3B53B002F1707 /* rpmatch.c in Sources */, C97A70AF1517AF53005E1998 /* xlocale.c in Sources */, C97A70B01517AF53005E1998 /* addr2ascii.c in Sources */, C97A70B11517AF53005E1998 /* ascii2addr.c in Sources */, @@ -13435,6 +13560,7 @@ C97A70D91517AF53005E1998 /* stpncpy_chk.c in Sources */, C97A70DA1517AF53005E1998 /* strcat_chk.c in Sources */, C97A70DB1517AF53005E1998 /* strcpy_chk.c in Sources */, + 922D0C0D21BFA19B0072834D /* timespec_get.c in Sources */, 3FA8F3251643AB8100D37078 /* strlcat_chk.c in Sources */, 3FA8F3261643AB8100D37078 /* strlcpy_chk.c in Sources */, C97A70DC1517AF53005E1998 /* strncat_chk.c in Sources */, @@ -13855,6 +13981,7 @@ C9765ECB138EC61900741512 /* bt_close.c in Sources */, C9765ECC138EC61900741512 /* bt_conv.c in Sources */, C9765ECD138EC61900741512 /* bt_debug.c in Sources */, + 7756338C22F3B549002F1707 /* rpmatch.c in Sources */, C9765ECE138EC61900741512 /* bt_delete.c in Sources */, C9765ECF138EC61900741512 /* bt_get.c in Sources */, C9765ED0138EC61900741512 /* bt_open.c in Sources */, @@ -14246,6 +14373,7 @@ C97660A8138EC61A00741512 /* setenv.c in Sources */, C97660A9138EC61A00741512 /* strhash.c in Sources */, C97660AA138EC61A00741512 /* strtoimax.c in Sources */, + 922D0C1321BFA1A40072834D /* timespec_get.c in Sources */, C97660AB138EC61A00741512 /* strtol.c in Sources */, C97660AC138EC61A00741512 /* strtoll.c in Sources */, C97660AD138EC61A00741512 /* strtoq.c in Sources */, @@ -14747,6 +14875,7 @@ C9EB31A2138F6D880075BB52 /* atof.c in Sources */, C9EB31A3138F6D880075BB52 /* atoi.c in Sources */, C9EB31A4138F6D880075BB52 /* atol.c in Sources */, + 922D0C0F21BFA1A20072834D /* timespec_get.c in Sources */, C9EB31A5138F6D880075BB52 /* atoll.c in Sources */, C9EB31A6138F6D880075BB52 /* bsearch.c in Sources */, C9EB31A7138F6D880075BB52 /* div.c in Sources */, @@ -14806,6 +14935,7 @@ C9EB31DD138F6D880075BB52 /* strptime.c in Sources */, C9EB31DE138F6D880075BB52 /* time32.c in Sources */, C9EB31DF138F6D880075BB52 /* timelocal.c in Sources */, + 7756339022F3B54E002F1707 /* rpmatch.c in Sources */, C9EB31E0138F6D880075BB52 /* getdate.c in Sources */, C9EB31E1138F6D880075BB52 /* timezone_unix03.c in Sources */, C9EB31EA138F6D880075BB52 /* memmem.c in Sources */, @@ -15282,6 +15412,7 @@ C9EB3449138F75580075BB52 /* atof.c in Sources */, C9EB344A138F75580075BB52 /* atoi.c in Sources */, C9EB344B138F75580075BB52 /* atol.c in Sources */, + 922D0C0E21BFA1A10072834D /* timespec_get.c in Sources */, C9EB344C138F75580075BB52 /* atoll.c in Sources */, C9EB344D138F75580075BB52 /* bsearch.c in Sources */, C9EB344E138F75580075BB52 /* div.c in Sources */, @@ -15341,6 +15472,7 @@ C9EB3484138F75580075BB52 /* strptime.c in Sources */, C9EB3485138F75580075BB52 /* time32.c in Sources */, C9EB3486138F75580075BB52 /* timelocal.c in Sources */, + 7756339122F3B550002F1707 /* rpmatch.c in Sources */, C9EB3487138F75580075BB52 /* getdate.c in Sources */, C9EB3488138F75580075BB52 /* timezone_unix03.c in Sources */, C9EB3491138F75580075BB52 /* memmem.c in Sources */, @@ -15486,26 +15618,11 @@ target = C95B7ED9138F3C55004311DA /* Variant_DarwinExtsn */; targetProxy = C0E3438D1C582ECB00E749C2 /* PBXContainerItemProxy */; }; - C0E345E61C58323000E749C2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C0E343831C582ECB00E749C2 /* libc_static */; - targetProxy = C0E345E51C58323000E749C2 /* PBXContainerItemProxy */; - }; C925D2011518FA5D003D315B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C95B7ED9138F3C55004311DA /* Variant_DarwinExtsn */; targetProxy = C925D2001518FA5D003D315B /* PBXContainerItemProxy */; }; - C925D2031518FEBE003D315B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C97A6F1E1517AF53005E1998 /* libc_eOS.a */; - targetProxy = C925D2021518FEBE003D315B /* PBXContainerItemProxy */; - }; - C942130913901709004BA536 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C942102D13900C8A004BA536 /* libc_dyld */; - targetProxy = C942130813901709004BA536 /* PBXContainerItemProxy */; - }; C95B817D138F3F72004311DA /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C95B7ED9138F3C55004311DA /* Variant_DarwinExtsn */; @@ -15576,6 +15693,31 @@ target = C9258093138E2D3100B3107C /* NetBSD */; targetProxy = C9FA32CB138E41800089A94B /* PBXContainerItemProxy */; }; + E47E981722150F0A006E312E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C9D9432E138DB73300FB7ACC /* libsystem_c.dylib */; + targetProxy = E47E981622150F0A006E312E /* PBXContainerItemProxy */; + }; + E47E981922150F2C006E312E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C942102D13900C8A004BA536 /* libc_dyld */; + targetProxy = E47E981822150F2C006E312E /* PBXContainerItemProxy */; + }; + E47E981B22150F2F006E312E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C0E343831C582ECB00E749C2 /* libc_static */; + targetProxy = E47E981A22150F2F006E312E /* PBXContainerItemProxy */; + }; + E47E981D22150F32006E312E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C97A6F1E1517AF53005E1998 /* libc_eOS.a */; + targetProxy = E47E981C22150F32006E312E /* PBXContainerItemProxy */; + }; + E47E981F22150F3C006E312E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C9D9432E138DB73300FB7ACC /* libsystem_c.dylib */; + targetProxy = E47E981E22150F3C006E312E /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -15606,7 +15748,6 @@ 925E7FE719E8945A00AC7889 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -15614,7 +15755,6 @@ 925E7FE819E8945A00AC7889 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -15655,7 +15795,7 @@ "$(PROJECT_DIR)/libdarwin/h", ); LIBRARY_SEARCH_PATHS = /usr/lib/system; - 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) -Wl,-upward-lsystem_trace"; + 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) -lmacho -ldyld -Wl,-upward-lsystem_trace"; OTHER_LDFLAGS = "$(LIBSYSTEM_DARWIN_LDFLAGS)"; OTHER_TAPI_FLAGS = "$(inherited) -extra-public-header $(SRCROOT)/libdarwin/h/dirstat.h -extra-public-header $(SRCROOT)/libdarwin/internal.h -DDARWIN_TAPI=1 -extra-public-header $(SRCROOT)/os/variant_private.h"; PRIVATE_HEADERS_FOLDER_PATH = "$(DARWIN_PRIVATE_HEADERS_FOLDER_PATH)"; @@ -15702,7 +15842,7 @@ "$(PROJECT_DIR)/libdarwin/h", ); LIBRARY_SEARCH_PATHS = /usr/lib/system; - 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) -Wl,-upward-lsystem_trace"; + 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) -lmacho -ldyld -Wl,-upward-lsystem_trace"; OTHER_LDFLAGS = "$(LIBSYSTEM_DARWIN_LDFLAGS)"; OTHER_TAPI_FLAGS = "$(inherited) -extra-public-header $(SRCROOT)/libdarwin/h/dirstat.h -extra-public-header $(SRCROOT)/libdarwin/internal.h -DDARWIN_TAPI=1 -extra-public-header $(SRCROOT)/os/variant_private.h"; PRIVATE_HEADERS_FOLDER_PATH = "$(DARWIN_PRIVATE_HEADERS_FOLDER_PATH)"; @@ -15716,7 +15856,6 @@ 926F739F1E046E56001E049D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -15724,7 +15863,6 @@ 926F73A01E046E56001E049D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -15753,7 +15891,6 @@ "$(BASE_EXCLUDED_SOURCE_FILE_NAMES)", ); EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -15773,7 +15910,6 @@ "$(BASE_EXCLUDED_SOURCE_FILE_NAMES)", ); EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; INCLUDED_SOURCE_FILE_NAMES = "$(FreeBSD_INCLUDED_SOURCE_FILE_NAMES)"; PRODUCT_NAME = TRE; @@ -15808,7 +15944,6 @@ "$(BASE_EXCLUDED_SOURCE_FILE_NAMES)", ); EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -15828,7 +15963,6 @@ "$(BASE_EXCLUDED_SOURCE_FILE_NAMES)", ); EXECUTABLE_PREFIX = lib; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; INCLUDED_SOURCE_FILE_NAMES = "$(FreeBSD_INCLUDED_SOURCE_FILE_NAMES)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -16124,7 +16258,7 @@ DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - /usr/lib/system, + "$(SDK_INSTALL_ROOT)/usr/lib/system", ); "ORDER_FILE[sdk=iphoneos*]" = "$(SDKROOT)/AppleInternal/OrderFiles/libsystem_c.order"; OTHER_LDFLAGS = "$(LIBSYSTEM_C_LDFLAGS)"; @@ -16145,7 +16279,7 @@ DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - /usr/lib/system, + "$(SDK_INSTALL_ROOT)/usr/lib/system", ); "ORDER_FILE[sdk=iphoneos*]" = "$(SDKROOT)/AppleInternal/OrderFiles/libsystem_c.order"; OTHER_LDFLAGS = "$(LIBSYSTEM_C_LDFLAGS)"; @@ -16241,6 +16375,34 @@ }; name = Release; }; + E47E980F22150EAD006E312E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E47E981022150EAD006E312E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + E47E981422150EBB006E312E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E47E981522150EBB006E312E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -16433,6 +16595,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + E47E981122150EAD006E312E /* Build configuration list for PBXAggregateTarget "Libc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E47E980F22150EAD006E312E /* Debug */, + E47E981022150EAD006E312E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E47E981322150EBB006E312E /* Build configuration list for PBXAggregateTarget "Libc_driverkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E47E981422150EBB006E312E /* Debug */, + E47E981522150EBB006E312E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = C9B53597138D9A690028D27C /* Project object */; diff --git a/Platforms/appletvos/Makefile.inc b/Platforms/appletvos/Makefile.inc index aacbe5a..04157fe 100644 --- a/Platforms/appletvos/Makefile.inc +++ b/Platforms/appletvos/Makefile.inc @@ -43,3 +43,6 @@ FEATURE_SMALL_STDIOBUF = 1 # Disable registration of specific signals () FEATURE_SIGNAL_RESTRICTION = 1 + +# Enable 32-bit compilation in unistd.h () +# FEATURE_POSIX_ILP32_ALLOW = 0 diff --git a/Platforms/bridgeos/Makefile.inc b/Platforms/bridgeos/Makefile.inc index ba2fd54..03e0e3c 100644 --- a/Platforms/bridgeos/Makefile.inc +++ b/Platforms/bridgeos/Makefile.inc @@ -43,3 +43,6 @@ FEATURE_SMALL_STDIOBUF = 1 # Disable registration of specific signals () FEATURE_SIGNAL_RESTRICTION = 1 + +# Enable 32-bit compilation in unistd.h () +# FEATURE_POSIX_ILP32_ALLOW = 0 diff --git a/Platforms/driverkit/Makefile.inc b/Platforms/driverkit/Makefile.inc new file mode 100644 index 0000000..8f827c3 --- /dev/null +++ b/Platforms/driverkit/Makefile.inc @@ -0,0 +1,48 @@ +# +# Selectable features for DriverKit +# + +# Legacy *64 APIs +#FEATURE_LEGACY_64_APIS = 1 + +# Legacy crt1.o environ support +#FEATURE_LEGACY_CRT1_ENVIRON = 1 + +# Legacy rune APIs +#FEATURE_LEGACY_RUNE_APIS = 1 + +# Legacy utmp APIs +#FEATURE_LEGACY_UTMP_APIS = 1 + +# OSThermalNotification APIs +#FEATURE_THERM_NOTIFICATION_APIS = 1 + +# No pre-1050 variants (should match sys/cdefs.h) +FEATURE_ONLY_1050_VARIANTS = 1 + +# No legacy variants (should match sys/cdefs.h) +FEATURE_ONLY_UNIX_CONFORMANCE = 1 + +# Only 64-bit ino_t (should match sys/cdefs.h) +FEATURE_ONLY_64_BIT_INO_T = 1 + +# Patch 3333969 +#FEATURE_PATCH_3333969 = 1 + +# Patch 3417676 +#FEATURE_PATCH_3417676 = 1 + +# plockstat dtrace support +#FEATURE_PLOCKSTAT = 1 + +# Timezone change notification +#FEATURE_TIMEZONE_CHANGE_NOTIFICATION = 1 + +# Extensible printf performance enhancement (uses more memory) +#FEATURE_XPRINTF_PERF = 1 + +# Disable registration of specific signals () +# FEATURE_SIGNAL_RESTRICTION = 0 + +# Enable 32-bit compilation in unistd.h () +# FEATURE_POSIX_ILP32_ALLOW = 0 diff --git a/Platforms/iphoneos/Makefile.inc b/Platforms/iphoneos/Makefile.inc index 3ea7c19..16cfa88 100644 --- a/Platforms/iphoneos/Makefile.inc +++ b/Platforms/iphoneos/Makefile.inc @@ -43,3 +43,6 @@ FEATURE_SMALL_STDIOBUF = 1 # Disable registration of specific signals () # FEATURE_SIGNAL_RESTRICTION = 0 + +# Enable 32-bit compilation in unistd.h () +# FEATURE_POSIX_ILP32_ALLOW = 0 diff --git a/Platforms/macosx/Makefile.inc b/Platforms/macosx/Makefile.inc index 9952af8..b73ae87 100644 --- a/Platforms/macosx/Makefile.inc +++ b/Platforms/macosx/Makefile.inc @@ -45,3 +45,6 @@ FEATURE_XPRINTF_PERF = 1 # Disable registration of specific signals () # FEATURE_SIGNAL_RESTRICTION = 0 + +# Enable 32-bit compilation in unistd.h () +# FEATURE_POSIX_ILP32_ALLOW = 0 diff --git a/Platforms/watchos/Makefile.inc b/Platforms/watchos/Makefile.inc index b8c3680..13a81ca 100644 --- a/Platforms/watchos/Makefile.inc +++ b/Platforms/watchos/Makefile.inc @@ -43,3 +43,6 @@ FEATURE_SMALL_STDIOBUF = 1 # Disable registration of specific signals () FEATURE_SIGNAL_RESTRICTION = 1 + +# Enable 32-bit compilation in unistd.h () +FEATURE_POSIX_ILP32_ALLOW = 1 diff --git a/darwin/compatibility_hacks.c b/darwin/compatibility_hacks.c index b6419ab..805aa2e 100644 --- a/darwin/compatibility_hacks.c +++ b/darwin/compatibility_hacks.c @@ -26,7 +26,9 @@ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ -#if !TARGET_OS_IPHONE +#include + +#if !TARGET_OS_IPHONE && !TARGET_OS_DRIVERKIT #define WEAK_SYMBOL_LD_CMD(sym, version) \ __asm__(".section __TEXT,__const\n\t" \ diff --git a/darwin/libc_private.h b/darwin/libc_private.h index 3dc00ae..6214528 100644 --- a/darwin/libc_private.h +++ b/darwin/libc_private.h @@ -63,7 +63,7 @@ _atexit_receipt(void); __IOS_AVAILABLE(9.0) __OSX_AVAILABLE(10.11) extern void -abort_report_np(const char *, ...) __dead2 __printflike(1, 2); +abort_report_np(const char *, ...) __dead2 __cold __printflike(1, 2); __END_DECLS diff --git a/gen/FreeBSD/arc4random.c b/gen/FreeBSD/arc4random.c index d2368d7..7c6ec08 100644 --- a/gen/FreeBSD/arc4random.c +++ b/gen/FreeBSD/arc4random.c @@ -42,22 +42,86 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/arc4random.c,v 1.25 2008/09/09 09:46:36 ach #include #include #include + +#include +#if !TARGET_OS_DRIVERKIT +#define OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE 1 +#endif #include #include #include "string.h" #include "libc_private.h" -#define CACHE_LENGTH 64 -#define BUFFERSIZE 32 +#if defined(__APPLE__) && !defined(VARIANT_STATIC) +#include -#define INITIAL_COUNT 1600000 -#define MAX_BUF_COUNT 4096 +static struct ccrng_state *rng; -static os_unfair_lock arc4_lock = OS_UNFAIR_LOCK_INIT; -static int arc4_count; +static void +arc4_init(void) +{ + int err; + + if (rng != NULL) return; + + rng = ccrng(&err); + if (rng == NULL) { +#if OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE + os_crash("arc4random: unable to get ccrng() handle (%d)", err); +#else + os_crash("arc4random: unable to get ccrng() handle"); +#endif + } +} + +void +arc4random_addrandom(__unused u_char *dat, __unused int datlen) +{ + /* NOP - deprecated */ +} + +uint32_t +arc4random(void) +{ + uint32_t rand; -uint64_t arc4random64(void); + arc4random_buf(&rand, sizeof(rand)); + + return rand; +} + +void +arc4random_buf(void *buf, size_t buf_size) +{ + arc4_init(); + ccrng_generate(rng, buf_size, buf); +} + +void +arc4random_stir(void) +{ + /* NOP */ +} + +uint32_t +arc4random_uniform(uint32_t upper_bound) +{ + uint64_t rand; + + arc4_init(); + ccrng_uniform(rng, upper_bound, &rand); + + return (uint32_t)rand; +} + +__private_extern__ void +_arc4_fork_child(void) +{ + /* NOP */ +} + +#else /* __APPLE__ && !VARIANT_STATIC */ #define RANDOMDEV "/dev/random" @@ -94,136 +158,6 @@ shortread: (void)close(fd); } -#if defined(__APPLE__) && !defined(VARIANT_STATIC) -#include -#include - -static struct ccdrbg_info rng_info; -static struct ccdrbg_nistctr_custom rng_custom; -static struct ccdrbg_state *rng_state; - -static int cache_pos = CACHE_LENGTH; -static uint32_t rand_buffer[CACHE_LENGTH]; - -static void -arc4_init(void) -{ - if (rng_state != NULL) return; - - uint8_t entropy[BUFFERSIZE]; - int ret; - rng_custom.ctr_info = ccaes_ctr_crypt_mode(); - rng_custom.keylen = 16; - rng_custom.strictFIPS = 0; - rng_custom.use_df = 1; - ccdrbg_factory_nistctr(&rng_info, &rng_custom); - rng_state = malloc(rng_info.size); - os_assert(rng_state != NULL); - - _my_getentropy(entropy, BUFFERSIZE); - - ret = ccdrbg_init(&rng_info, rng_state, - sizeof(entropy), entropy, - 0, NULL, 0, NULL); - os_assert_zero(ret); - - memset_s(entropy, sizeof(entropy), 0, sizeof(entropy)); - - arc4_count = INITIAL_COUNT; -} - -static void -arc4_stir(void) -{ - uint8_t entropy[BUFFERSIZE]; - int ret; - - arc4_init(); - - _my_getentropy(entropy, BUFFERSIZE); - - ret = ccdrbg_reseed(&rng_info, rng_state, - sizeof(entropy), entropy, - 0, NULL); - os_assert_zero(ret); - - memset_s(entropy, sizeof(entropy), 0, sizeof(entropy)); - - arc4_count = INITIAL_COUNT; -} - -void -arc4random_addrandom(__unused u_char *dat, __unused int datlen) -{ - /* NOP - deprecated */ -} - -uint32_t -arc4random(void) -{ - int ret; - os_unfair_lock_lock(&arc4_lock); - arc4_init(); - if (arc4_count <= 0) { - arc4_stir(); - } - if (cache_pos >= CACHE_LENGTH) { - ret = ccdrbg_generate(&rng_info, rng_state, sizeof(rand_buffer), rand_buffer, 0, NULL); - os_assert_zero(ret); - cache_pos = 0; - } - uint32_t rand = rand_buffer[cache_pos]; - // Delete the current random number from buffer - memset_s(rand_buffer+cache_pos, sizeof(rand_buffer[cache_pos]), 0, sizeof(rand_buffer[cache_pos])); - arc4_count--; - cache_pos++; - os_unfair_lock_unlock(&arc4_lock); - return rand; -} - -void -arc4random_buf(void *_buf, size_t buf_size) -{ - uint8_t *buf = _buf; - os_unfair_lock_lock(&arc4_lock); - arc4_init(); - while (buf_size > 0) { - if (arc4_count <= 0 ) { - arc4_stir(); - } - size_t n = MIN(buf_size, (size_t)MIN(MAX_BUF_COUNT, arc4_count) * sizeof(uint32_t)); - int ret = ccdrbg_generate(&rng_info, rng_state, n, buf, 0, NULL); - os_assert_zero(ret); - buf_size -= n; - buf += n; - arc4_count -= n/sizeof(uint32_t); - - if (buf_size > 0) { - os_unfair_lock_unlock(&arc4_lock); - // Give others a chance to get the lock - os_unfair_lock_lock(&arc4_lock); - } - } - os_unfair_lock_unlock(&arc4_lock); -} - -__private_extern__ void -_arc4_fork_child(void) -{ - arc4_lock = OS_UNFAIR_LOCK_INIT; - cache_pos = CACHE_LENGTH; - if (rng_state != NULL) { - arc4_count = 0; - memset_s(rand_buffer, sizeof(rand_buffer), 0, sizeof(rand_buffer)); - memset_s(rng_state, rng_info.size, 0, rng_info.size); - free(rng_state); rng_state = NULL; - bzero(&rng_info, sizeof(rng_info)); - bzero(&rng_custom, sizeof(rng_custom)); - } -} - -#else /* __APPLE__ && !VARIANT_STATIC */ - struct arc4_stream { u_int8_t i; u_int8_t j; @@ -289,6 +223,9 @@ arc4_fetch(void) _my_getentropy((uint8_t*)&rdat, KEYSIZE); } +static os_unfair_lock arc4_lock = OS_UNFAIR_LOCK_INIT; +static int arc4_count; + static void arc4_stir(void) { @@ -425,8 +362,6 @@ arc4random_buf(void *_buf, size_t n) } } -#endif /* __APPLE__ */ - void arc4random_stir(void) { @@ -475,3 +410,5 @@ arc4random_uniform(uint32_t upper_bound) } } while (1); } + +#endif /* __APPLE__ */ diff --git a/gen/FreeBSD/assert.c b/gen/FreeBSD/assert.c index bf0de53..0d4c06e 100644 --- a/gen/FreeBSD/assert.c +++ b/gen/FreeBSD/assert.c @@ -36,7 +36,12 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/assert.c,v 1.8 2007/01/09 00:27:53 imp Exp #include #include #include +#if __has_include() #include +#else +#define CRGetCrashLogMessage() NULL +#define CRSetCrashLogMessage(...) +#endif #include "_simple.h" void @@ -48,12 +53,12 @@ __assert_rtn(func, file, line, failedexpr) if (func == (const char *)-1L) { /* 8462256: special case to replace __eprintf */ _simple_dprintf(STDERR_FILENO, - "%s:%u: failed assertion `%s'\n", file, line, failedexpr); + "%s:%d: failed assertion `%s'\n", file, line, failedexpr); if (!CRGetCrashLogMessage()) { _SIMPLE_STRING s = _simple_salloc(); if (s) { _simple_sprintf(s, - "%s:%u: failed assertion `%s'\n", + "%s:%d: failed assertion `%s'\n", file, line, failedexpr); CRSetCrashLogMessage(_simple_string(s)); } else diff --git a/gen/FreeBSD/dirname.c b/gen/FreeBSD/dirname.c index c291a06..7def49a 100644 --- a/gen/FreeBSD/dirname.c +++ b/gen/FreeBSD/dirname.c @@ -64,7 +64,7 @@ dirname_r(const char *path, char *dname) errno = ENAMETOOLONG; return (NULL); } - memcpy(dname, path, len); + memmove(dname, path, len); dname[len] = '\0'; return (dname); } diff --git a/gen/FreeBSD/glob.3 b/gen/FreeBSD/glob.3 index 192c70c..75bebc4 100644 --- a/gen/FreeBSD/glob.3 +++ b/gen/FreeBSD/glob.3 @@ -43,7 +43,7 @@ .Ft int .Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *epath, int errno)" "glob_t * restrict pglob" .Ft int -.Fn glob "const char * restrict pattern" "int flags" "int (^errblk)(const char *epath, int errno)" "glob_t * restrict pglob" +.Fn glob_b "const char * restrict pattern" "int flags" "int (^errblk)(const char *epath, int errno)" "glob_t * restrict pglob" .Ft void .Fn globfree "glob_t *pglob" .Sh DESCRIPTION diff --git a/gen/FreeBSD/opendir.c b/gen/FreeBSD/opendir.c index 4242906..844a7e8 100644 --- a/gen/FreeBSD/opendir.c +++ b/gen/FreeBSD/opendir.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -49,6 +50,32 @@ __FBSDID("$FreeBSD$"); #include "telldir.h" +static bool +__kernel_supports_unionfs(void) +{ + static int8_t kernel_supports_unionfs = -1; + if (kernel_supports_unionfs == -1) { + int value = 0; + size_t len = sizeof(value); + sysctlbyname("kern.secure_kernel", &value, &len, NULL, 0); + kernel_supports_unionfs = !value; + } + return kernel_supports_unionfs; +} + +static int +__fd_is_on_union_mount(int fd) +{ + struct statfs stbuf; + int rc; + + rc = fstatfs(fd, &stbuf); + if (rc < 0) { + return rc; + } + return (stbuf.f_flags & MNT_UNION) != 0; +} + static DIR * __opendir_common(int, int, bool); /* @@ -294,7 +321,6 @@ static DIR * __opendir_common(int fd, int flags, bool use_current_pos) { DIR *dirp; - int incr; int saved_errno; int unionstack; @@ -310,25 +336,13 @@ __opendir_common(int fd, int flags, bool use_current_pos) LIST_INIT(&dirp->dd_td->td_locq); dirp->dd_td->td_loccnt = 0; - /* - * 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; - /* * Determine whether this directory is the top of a union stack. */ - if (flags & DTF_NODUP) { - struct statfs sfb; - - if (_fstatfs(fd, &sfb) < 0) + if ((flags & DTF_NODUP) && __kernel_supports_unionfs()) { + unionstack = __fd_is_on_union_mount(fd); + if (unionstack < 0) goto fail; - unionstack = !strcmp(sfb.f_fstypename, "unionfs") - || (sfb.f_flags & MNT_UNION); } else { unionstack = 0; } @@ -338,7 +352,14 @@ __opendir_common(int fd, int flags, bool use_current_pos) goto fail; dirp->dd_flags |= __DTF_READALL; } else { - dirp->dd_len = incr; + /* + * Start with a small-ish size to avoid allocating full pages. + * readdir() will allocate a larger buffer if it didn't fit + * to stay fast for large directories. + */ + _Static_assert(GETDIRENTRIES64_EXTENDED_BUFSIZE <= READDIR_INITIAL_SIZE, + "Make sure we'll get extended metadata"); + dirp->dd_len = READDIR_INITIAL_SIZE; dirp->dd_buf = malloc(dirp->dd_len); if (dirp->dd_buf == NULL) goto fail; @@ -349,8 +370,26 @@ __opendir_common(int fd, int flags, bool use_current_pos) * fd passed to fdopendir() is a directory. */ #if __DARWIN_64_BIT_INO_T + /* + * sufficiently recent kernels when the buffer is large enough, + * will use the last bytes of the buffer to return status. + * + * To support older kernels: + * - make sure it's 0 initialized + * - make sure it's past `dd_size` before reading it + */ + getdirentries64_flags_t *gdeflags = + (getdirentries64_flags_t *)(dirp->dd_buf + dirp->dd_len - + sizeof(getdirentries64_flags_t)); + *gdeflags = 0; dirp->dd_size = (long)__getdirentries64(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_td->seekoff); + if (dirp->dd_size >= 0 && + dirp->dd_size <= dirp->dd_len - sizeof(getdirentries64_flags_t)) { + if (*gdeflags & GETDIRENTRIES64_EOF) { + dirp->dd_flags |= __DTF_ATEND; + } + } #else /* !__DARWIN_64_BIT_INO_T */ dirp->dd_size = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); diff --git a/gen/FreeBSD/pause.3 b/gen/FreeBSD/pause.3 index b7ddcae..815995a 100644 --- a/gen/FreeBSD/pause.3 +++ b/gen/FreeBSD/pause.3 @@ -46,9 +46,8 @@ .Pp The .Fn pause -function -forces a process to pause until -a signal is received from either the +function causes the calling thread to pause until a signal is received from +either the .Xr kill 2 function or an interval timer. diff --git a/gen/FreeBSD/readdir.c b/gen/FreeBSD/readdir.c index aa8443b..c78c6bf 100644 --- a/gen/FreeBSD/readdir.c +++ b/gen/FreeBSD/readdir.c @@ -37,7 +37,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include "un-namespace.h" @@ -56,18 +58,50 @@ _readdir_unlocked(DIR *dirp, int skip) for (;;) { if (dirp->dd_loc >= dirp->dd_size) { - if (dirp->dd_flags & __DTF_READALL) + if (dirp->dd_flags & (__DTF_READALL | __DTF_ATEND)) 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 | __DTF_SKIPREAD))) { + !(dirp->dd_flags & (__DTF_READALL | __DTF_ATEND | __DTF_SKIPREAD))) { + if (dirp->dd_len == READDIR_INITIAL_SIZE) { + /* + * If we need to read more, and we still have the original size, + * then grow the internal buffer to a large size to amortize + * the cost of __getdirentries64 calls. + */ + int len = READDIR_LARGE_SIZE; + char *buf = malloc(len); + if (buf) { + free(dirp->dd_buf); + dirp->dd_buf = buf; + dirp->dd_len = len; + } + } #if __DARWIN_64_BIT_INO_T + /* + * sufficiently recent kernels when the buffer is large enough, + * will use the last bytes of the buffer to return status. + * + * To support older kernels: + * - make sure it's 0 initialized + * - make sure it's past `dd_size` before reading it + */ + getdirentries64_flags_t *gdeflags = + (getdirentries64_flags_t *)(dirp->dd_buf + dirp->dd_len - + sizeof(getdirentries64_flags_t)); + *gdeflags = 0; initial_seek = dirp->dd_td->seekoff; dirp->dd_size = (long)__getdirentries64(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_td->seekoff); + if (dirp->dd_size >= 0 && + dirp->dd_size <= dirp->dd_len - sizeof(getdirentries64_flags_t)) { + if (*gdeflags & GETDIRENTRIES64_EOF) { + dirp->dd_flags |= __DTF_ATEND; + } + } #else /* !__DARWIN_64_BIT_INO_T */ initial_seek = dirp->dd_seek; dirp->dd_size = _getdirentries(dirp->dd_fd, diff --git a/gen/FreeBSD/rewinddir.c b/gen/FreeBSD/rewinddir.c index 97067d3..66deadc 100644 --- a/gen/FreeBSD/rewinddir.c +++ b/gen/FreeBSD/rewinddir.c @@ -49,7 +49,7 @@ rewinddir(DIR *dirp) if (__isthreaded) _pthread_mutex_lock(&dirp->dd_lock); - dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */ + dirp->dd_flags &= ~(__DTF_SKIPREAD | __DTF_ATEND); /* current contents are invalid */ if (dirp->dd_flags & __DTF_READALL) _filldir(dirp, false); else { diff --git a/gen/FreeBSD/telldir.c b/gen/FreeBSD/telldir.c index c447a37..8351dc1 100644 --- a/gen/FreeBSD/telldir.c +++ b/gen/FreeBSD/telldir.c @@ -132,7 +132,7 @@ _seekdir(DIR *dirp, long loc) 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 */ + dirp->dd_flags &= ~(__DTF_SKIPREAD | __DTF_ATEND); /* current contents are invalid */ while (dirp->dd_loc < lp->loc_loc) { dp = _readdir_unlocked(dirp, 0); if (dp == NULL) diff --git a/gen/FreeBSD/telldir.h b/gen/FreeBSD/telldir.h index 271981e..6b7902d 100644 --- a/gen/FreeBSD/telldir.h +++ b/gen/FreeBSD/telldir.h @@ -67,14 +67,21 @@ struct _telldir { #endif /* __DARWIN_64_BIT_INO_T */ }; +/* + * This lets paths like `/` or top-level bundles to return in a single + * __getdirentries64 while keeping pressure on malloc small. + */ +#define READDIR_INITIAL_SIZE 2048 +#define READDIR_LARGE_SIZE (8 << 10) + #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); +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); diff --git a/gen/FreeBSD/timespec_get.3 b/gen/FreeBSD/timespec_get.3 new file mode 100644 index 0000000..3406300 --- /dev/null +++ b/gen/FreeBSD/timespec_get.3 @@ -0,0 +1,81 @@ +.\" $NetBSD: timespec_get.3,v 1.2 2016/10/04 10:46:40 wiz Exp $ +.\" +.\" Copyright (c) 2016 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Kamil Rytarowski. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd August 26, 2018 +.Dt TIMESPEC_GET 3 +.Os +.Sh NAME +.Nm timespec_get +.Nd get current calendar time +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In time.h +.Ft int +.Fn timespec_get "struct timespec *ts" "int base" +.Sh DESCRIPTION +The +.Nm +function sets the interval pointed to by +.Fa ts +to hold the current calendar time based on the specified time base in +.Fa base . +.Pp +The base +.Dv TIME_UTC +returns the time since the epoch. +This time is expressed in seconds and nanoseconds since midnight (0 hour), January 1, 1970. +This corresponds to +.Dv CLOCK_REALTIME . +.Sh RETURN VALUES +The +.Nm +function returns the passed value of +.Fa base +if successful, otherwise +.Dv 0 +on failure. +.Sh SEE ALSO +.Xr gettimeofday 2 , +.Xr clock_gettime 2 , +.Xr time 3 +.Sh STANDARDS +The +.Nm +function with a +.Fa base +of +.Dv TIME_UTC +conforms to +.St -isoC-2011 . +.Sh AUTHORS +.An Kamil Rytarowski Aq Mt kamil@NetBSD.org +.An Warner Losh Aq Mt imp@FreeBSD.org diff --git a/gen/FreeBSD/timespec_get.c b/gen/FreeBSD/timespec_get.c new file mode 100644 index 0000000..1dd0147 --- /dev/null +++ b/gen/FreeBSD/timespec_get.c @@ -0,0 +1,54 @@ +/* $NetBSD: timespec_get.c,v 1.2 2016/10/04 12:48:15 christos Exp $ */ + +/*- + * Copyright (c) 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Kamil Rytarowski. + * + * 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 +__RCSID("$NetBSD: timespec_get.c,v 1.2 2016/10/04 12:48:15 christos Exp $"); +__FBSDID("$FreeBSD$"); + +#include + +/* ISO/IEC 9899:201x 7.27.2.5 The timespec_get function */ + +int +timespec_get(struct timespec *ts, int base) +{ + + switch (base) { + case TIME_UTC: + if (clock_gettime(CLOCK_REALTIME, ts) == -1) + return 0; + break; + default: + return 0; + } + + return base; +} diff --git a/gen/NetBSD/rbtree.3 b/gen/NetBSD/rbtree.3 index 399eeca..56e52ed 100644 --- a/gen/NetBSD/rbtree.3 +++ b/gen/NetBSD/rbtree.3 @@ -45,7 +45,9 @@ .Nm RB_TREE_MIN , .Nm RB_TREE_MAX , .Nm RB_TREE_FOREACH , -.Nm RB_TREE_FOREACH_REVERSE +.Nm RB_TREE_FOREACH_SAFE , +.Nm RB_TREE_FOREACH_REVERSE , +.Nm RB_TREE_FOREACH_REVERSE_SAFE .Nd red-black tree .Sh LIBRARY .Lb libc @@ -72,7 +74,9 @@ .Ft void * .Fn RB_TREE_MAX "rb_tree_t *rbt" .Fn RB_TREE_FOREACH "void *rb" "rb_tree_t *rbt" +.Fn RB_TREE_FOREACH_SAFE "void *rb" "rb_tree_t *rbt" "void *tmp" .Fn RB_TREE_FOREACH_REVERSE "void *rb" "rb_tree_t *rbt" +.Fn RB_TREE_FOREACH_REVERSE_SAFE "void *rb" "rb_tree_t *rbt" "void *tmp" .Sh DESCRIPTION .Nm provides red-black trees. @@ -275,6 +279,13 @@ header preceding a statement to traverse the nodes in from least to greatest, assigning .Fa rb to each node in turn and executing the statement. +.It Fn RB_TREE_FOREACH_SAFE "rb" "rbt" "tmp" +.Nm RB_TREE_FOREACH_SAFE +is a macro to be used like +.Nm RB_TREE_FOREACH +but which uses a temporary variable to permit safe modification or deletion of +.Fa rb +in the body of the loop. .It Fn RB_TREE_FOREACH_REVERSE "rb" "rbt" .Nm RB_TREE_FOREACH_REVERSE is a macro to be used in the place of a @@ -284,6 +295,13 @@ header preceding a statement to traverse the nodes in from greatest to least, assigning .Fa rb to each node in turn and executing the statement. +.It Fn RB_TREE_FOREACH_REVERSE_SAFE "rb" "rbt" "tmp" +.Nm RB_TREE_FOREACH_REVERSE_SAFE +is a macro to be used like +.Nm RB_TREE_FOREACH_REVERSE +but which uses a temporary variable to permit safe modification or deletion of +.Fa rb +in the body of the loop. .El .Sh SEE ALSO .Xr queue 3 , diff --git a/gen/backtrace.c b/gen/backtrace.c index 7719283..f3b7424 100644 --- a/gen/backtrace.c +++ b/gen/backtrace.c @@ -21,19 +21,14 @@ * @APPLE_LICENSE_HEADER_END@ */ +#include #include #include - -#include #include #include #include #include -#include -#include #include - -#include "stack_logging.h" #include "execinfo.h" extern void _thread_stack_pcs(vm_address_t *buffer, unsigned max, @@ -55,6 +50,13 @@ backtrace_from_fp(void *startfp, void **buffer, int size) return num_frames; } +#if !TARGET_OS_DRIVERKIT + +#include +#include +#include +#include "stack_logging.h" + #if __LP64__ #define _BACKTRACE_FORMAT "%-4d%-35s 0x%016lx %s + %lu" #define _BACKTRACE_FORMAT_SIZE 83 /* %lu can take up to 20, does not include %s, includes NUL */ @@ -64,41 +66,76 @@ backtrace_from_fp(void *startfp, void **buffer, int size) #define _BACKTRACE_FORMAT_SIZE 65 /* %lu can take up to 10, does not include %s, includes NUL */ #define _BACKTRACE_ADDRESS_LEN 10 /* 0x + 8 (no NUL) */ #endif +#define _BACKTRACE_IMAGE_LEN 35 +#define _BACKTRACE_UUID_LEN 36 static int _backtrace_snprintf(char* buf, size_t size, int frame, const void* addr, const Dl_info* info) { - char symbuf[_BACKTRACE_ADDRESS_LEN + 1]; + char addrbuf[_BACKTRACE_ADDRESS_LEN + 1]; + char imagebuf[_BACKTRACE_IMAGE_LEN + 1]; + uuid_string_t uuidbuf; const char* image = "???"; const char* symbol = "0x0"; uintptr_t symbol_offset = 0; if (info->dli_fname) { const char *tmp = strrchr(info->dli_fname, '/'); - if(tmp == NULL) - image = info->dli_fname; - else - image = tmp + 1; + if (tmp == NULL) { + strlcpy(imagebuf, info->dli_fname, sizeof(imagebuf)); + } else { + strlcpy(imagebuf, tmp + 1, sizeof(imagebuf)); + } + image = imagebuf; } - + if (info->dli_sname) { - symbol = info->dli_sname; - symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_saddr; - } else if(info->dli_fname) { + uuid_t uuid; + if (strcmp(info->dli_sname, "") == 0 && + _dyld_get_image_uuid(info->dli_fbase, uuid)) { + /* + * dyld returns when the symbol name has been elided in + * the shared cache. To enable symbolication later, we provide the + * UUID and UUID-offset instead. + */ + uuid_unparse(uuid, uuidbuf); + symbol = uuidbuf; + symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_fbase; + } else { + symbol = info->dli_sname; + symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_saddr; + } + } else if (info->dli_fname) { symbol = image; symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_fbase; - } else if(0 < snprintf(symbuf, sizeof(symbuf), "0x%lx", (uintptr_t)info->dli_saddr)) { - symbol = symbuf; + } else if (0 < snprintf(addrbuf, sizeof(addrbuf), "0x%lx", + (uintptr_t)info->dli_saddr)) { + symbol = addrbuf; symbol_offset = (uintptr_t)addr - (uintptr_t)info->dli_saddr; } else { symbol_offset = (uintptr_t)addr; } - return snprintf(buf, size, - _BACKTRACE_FORMAT, - frame, - image, - (uintptr_t)addr, - symbol, - symbol_offset); + return snprintf(buf, size, _BACKTRACE_FORMAT, frame, image, + (uintptr_t)addr, symbol, symbol_offset); +} + +static size_t symbol_length(Dl_info *info) +{ + if (info->dli_sname) { + if (strcmp(info->dli_sname, "") == 0) { + return _BACKTRACE_UUID_LEN; + } else { + return strlen(info->dli_sname); + } + } else if (info->dli_fname) { + const char *tmp = strrchr(info->dli_fname, '/'); + if (tmp == NULL) { + return strlen(info->dli_fname); + } else { + return strlen(tmp + 1); + } + } else { + return _BACKTRACE_ADDRESS_LEN; + } } char** backtrace_symbols(void* const* buffer, int size) { @@ -108,60 +145,51 @@ char** backtrace_symbols(void* const* buffer, int size) { char** ptrs; intptr_t strs, end; Dl_info* info = calloc(size, sizeof (Dl_info)); - + if (info == NULL) return NULL; - + // Compute the total size for the block that is returned. // The block will contain size number of pointers to the // symbol descriptions. total_bytes = sizeof(char*) * size; - + // Plus each symbol description for (i = 0 ; i < size; ++i) { dladdr(buffer[i], &info[i]); total_bytes += _BACKTRACE_FORMAT_SIZE; - if (info[i].dli_sname) { - total_bytes += strlen(info[i].dli_sname); - } else if(info[i].dli_fname) { - const char *tmp = strrchr(info[i].dli_fname, '/'); - if(tmp == NULL) - total_bytes += strlen(info[i].dli_fname); - else - total_bytes += strlen(tmp + 1); - } else { - total_bytes += _BACKTRACE_ADDRESS_LEN; - } + total_bytes += symbol_length(&info[i]); } - + result = (char**)malloc(total_bytes); if (result == NULL) { - free(info); - return NULL; + goto error; } end = (intptr_t)result + total_bytes; - + // Fill in the array of pointers and append the strings for // each symbol description. - + ptrs = result; strs = ((intptr_t)result) + sizeof(char*) * size; for (i = 0; i < size; ++i) { int chk = _backtrace_snprintf((char*)strs, end - (intptr_t)strs, i, buffer[i], &info[i]); - - if(chk < 0) { - free(info); - return NULL; + if (chk < 0) { + goto error; } ptrs[i] = (char*)strs; strs += chk + 1; // Step over the '\0' } - + free(info); - return result; + +error: + free(info); + free(result); + return NULL; } void backtrace_symbols_fd(void* const* buffer, int size, int fd) { @@ -185,6 +213,8 @@ void backtrace_symbols_fd(void* const* buffer, int size, int fd) { } } +#endif // !TARGET_OS_DRIVERKIT + void backtrace_image_offsets(void* const* buffer, struct image_offset *imgoffs, int size) { diff --git a/gen/confstr.3 b/gen/confstr.3 index 224e7d1..4ea7c12 100644 --- a/gen/confstr.3 +++ b/gen/confstr.3 @@ -159,7 +159,7 @@ argument is invalid. Insufficient storage space is available. .It Bq Er EIO I/O error communicating with -.Xr opendirectoryd 8 . +.Xr dirhelper 8 . .El .Sh LEGACY ERRORS If the call to diff --git a/gen/directory.3 b/gen/directory.3 index 712617d..4e52375 100644 --- a/gen/directory.3 +++ b/gen/directory.3 @@ -9,7 +9,7 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" @@ -28,7 +28,7 @@ .\" @(#)directory.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd April 16, 2008 +.Dd May 22, 2017 .Dt DIRECTORY 3 .Os .Sh NAME @@ -65,6 +65,15 @@ .Ft int .Fn dirfd "DIR *dirp" .Sh DESCRIPTION +.Bf -symbolic +The +.Fn readdir_r +interface is deprecated +because it cannot be used correctly unless +.Brq Va NAME_MAX +is a fixed value. +.Ef +.Pp The .Fn opendir function @@ -83,10 +92,7 @@ is returned if .Fa filename cannot be accessed, or if it cannot .Xr malloc 3 -enough memory to hold the whole thing, -and sets the global variable -.Va errno -to indicate the error. +enough memory to hold the whole thing. .Pp The .Fn fdopendir @@ -122,16 +128,27 @@ The .Fn readdir function returns a pointer to the next directory entry. -It returns +The directory entry remains valid until the next call to +.Fn readdir +or +.Fn closedir +on the same +.Em directory stream . +The function returns .Dv NULL upon reaching the end of the directory or on error. In the event of an error, .Va errno may be set to any of the values documented for the .Xr getdirentries 2 -system call. Note that the order of the directory entries vended by +system call. Note that the order of the directory entries vended by .Fn readdir -is not specified. Some filesystems may return entries in lexicographic sort order and others may not. +is not specified. +Some filesystems may return entries in lexicographic sort order and others may not. +Also note that not all filesystems will provide a value for +.Va d_type +and may instead set the field to +.Dv DT_UNKNOWN . .Pp The .Fn readdir_r @@ -141,6 +158,13 @@ provides the same functionality as but the caller must provide a directory .Fa entry buffer to store the results in. +The buffer must be large enough for a +.Vt struct dirent +with a +.Va d_name +array with +.Brq Va NAME_MAX ++ 1 elements. If the read succeeds, .Fa result is pointed at the @@ -157,7 +181,7 @@ returns 0 on success or an error number to indicate failure. The .Fn telldir function -returns the current location associated with the named +returns a token representing the current location associated with the named .Em directory stream . Values returned by .Fn telldir @@ -170,6 +194,10 @@ If the directory is closed and then reopened, prior values returned by .Fn telldir will no longer be valid. +Values returned by +.Fn telldir +are also invalidated by a call to +.Fn rewinddir . .Pp The .Fn seekdir @@ -211,9 +239,6 @@ returns the integer file descriptor associated with the named .Em directory stream , see .Xr open 2 . -On failure, \-1 is returned and the global variable -.Va errno -is set to indicate the error. .Pp Sample code which searches a directory for entry ``name'' is: .Bd -literal -offset indent diff --git a/gen/nftw.c b/gen/nftw.c index a1a485a..7227030 100644 --- a/gen/nftw.c +++ b/gen/nftw.c @@ -150,6 +150,7 @@ both_ftw(const char *path, break; case FTS_F: case FTS_DEFAULT: + SKIP_MOUNT; fnflag = FTW_F; break; case FTS_NS: diff --git a/gen/strtofflags.c b/gen/strtofflags.c index 0df9996..1e45bda 100644 --- a/gen/strtofflags.c +++ b/gen/strtofflags.c @@ -95,6 +95,7 @@ static struct { { "nohidden", UF_HIDDEN, 0 }, { "nocompressed", UF_COMPRESSED, 0 }, { "nodatavault", UF_DATAVAULT, 0 }, + { "nodataless", SF_DATALESS, 0 }, }; #define longestflaglen 12 #define nmappings (sizeof(mapping) / sizeof(mapping[0])) diff --git a/gen/thread_stack_pcs.c b/gen/thread_stack_pcs.c index 18bbf21..5066a52 100644 --- a/gen/thread_stack_pcs.c +++ b/gen/thread_stack_pcs.c @@ -27,16 +27,9 @@ #include #include #include +#include #include "stack_logging.h" - -#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__) -#define FP_LINK_OFFSET 1 -#else -#error ********** Unimplemented architecture -#endif - - #define INSTACK(a) ((a) >= stackbot && (a) <= stacktop) #if defined(__x86_64__) #define ISALIGNED(a) ((((uintptr_t)(a)) & 0xf) == 0) @@ -46,9 +39,9 @@ #define ISALIGNED(a) ((((uintptr_t)(a)) & 0x1) == 0) #endif -__private_extern__ __attribute__((noinline)) -void -_thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb, +__attribute__((noinline)) +static void +__thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb, unsigned skip, void *startfp) { void *frame, *next; @@ -58,42 +51,57 @@ _thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb, *nb = 0; + // Rely on the fact that our caller has an empty stackframe (no local vars) + // to determine the minimum size of a stackframe (frame ptr & return addr) + frame = __builtin_frame_address(0); + next = (void*)pthread_stack_frame_decode_np((uintptr_t)frame, NULL); + /* make sure return address is never out of bounds */ - stacktop -= (FP_LINK_OFFSET + 1) * sizeof(void *); + stacktop -= (next - frame); - frame = __builtin_frame_address(0); if(!INSTACK(frame) || !ISALIGNED(frame)) return; - while ((startfp && startfp >= *(void **)frame) || skip--) { - next = *(void **)frame; + while (startfp || skip--) { + if (startfp && startfp < next) break; if(!INSTACK(next) || !ISALIGNED(next) || next <= frame) return; frame = next; + next = (void*)pthread_stack_frame_decode_np((uintptr_t)frame, NULL); } while (max--) { - void *retaddr = (void *)*(vm_address_t *) - (((void **)frame) + FP_LINK_OFFSET); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wint-conversion" + uintptr_t retaddr; + next = (void*)pthread_stack_frame_decode_np((uintptr_t)frame, &retaddr); buffer[*nb] = retaddr; -#pragma clang diagnostic pop (*nb)++; - next = *(void **)frame; if(!INSTACK(next) || !ISALIGNED(next) || next <= frame) return; frame = next; } } +// Note that callee relies on this function having a minimal stackframe +// to introspect (i.e. no tailcall and no local variables) +__private_extern__ __attribute__((disable_tail_calls)) +void +_thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb, + unsigned skip, void *startfp) +{ + // skip this frame + __thread_stack_pcs(buffer, max, nb, skip + 1, startfp); +} + // Prevent thread_stack_pcs() from getting tail-call-optimized into -// _thread_stack_pcs() on 64-bit environments, thus making the "number of hot +// __thread_stack_pcs() on 64-bit environments, thus making the "number of hot // frames to skip" be more predictable, giving more consistent backtraces. // // See "stack logging: frames keep getting truncated" // for why this is necessary. +// +// Note that callee relies on this function having a minimal stackframe +// to introspect (i.e. no tailcall and no local variables) __attribute__((disable_tail_calls)) void thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *nb) { - _thread_stack_pcs(buffer, max, nb, 0, NULL); + __thread_stack_pcs(buffer, max, nb, 0, NULL); } diff --git a/include/_ctermid.h b/include/_ctermid.h new file mode 100644 index 0000000..540b117 --- /dev/null +++ b/include/_ctermid.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2000, 2002-2006, 2008-2010, 2012 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 _CTERMID_H_ +#define _CTERMID_H_ +char *ctermid(char *); +#endif diff --git a/include/_stdio.h b/include/_stdio.h index 0f3ae7a..af0664c 100644 --- a/include/_stdio.h +++ b/include/_stdio.h @@ -76,6 +76,7 @@ #include #include +#ifndef UNIFDEF_DRIVERKIT #include typedef __darwin_off_t fpos_t; @@ -155,5 +156,6 @@ typedef struct __sFILE { int _blksize; /* stat.st_blksize (may be != _bf._size) */ fpos_t _offset; /* current lseek offset (see WARNING) */ } FILE; +#endif /* UNIFDEF_DRIVERKIT */ #endif /* __STDIO_H_ */ diff --git a/include/_types.h b/include/_types.h index 83cd510..12db190 100644 --- a/include/_types.h +++ b/include/_types.h @@ -37,7 +37,9 @@ #define __strftimelike(fmtarg) #endif +#ifndef UNIFDEF_DRIVERKIT typedef int __darwin_nl_item; +#endif /* UNIFDEF_DRIVERKIT */ typedef int __darwin_wctrans_t; #ifdef __LP64__ typedef __uint32_t __darwin_wctype_t; diff --git a/include/alloca.h b/include/alloca.h index 0264ae6..6f41a4d 100644 --- a/include/alloca.h +++ b/include/alloca.h @@ -28,9 +28,11 @@ #include <_types.h> #include +#ifndef UNIFDEF_DRIVERKIT __BEGIN_DECLS void *alloca(size_t); /* built-in for gcc */ __END_DECLS +#endif /* UNIFDEF_DRIVERKIT */ #if defined(__GNUC__) && __GNUC__ >= 3 /* built-in for gcc 3 */ diff --git a/include/assert.h b/include/assert.h index 7c81e75..1697026 100644 --- a/include/assert.h +++ b/include/assert.h @@ -56,11 +56,12 @@ #define assert(e) ((void)0) #else +#ifndef UNIFDEF_DRIVERKIT #ifndef __GNUC__ __BEGIN_DECLS #ifndef __cplusplus -void abort(void) __dead2; +void abort(void) __dead2 __cold; #endif /* !__cplusplus */ int printf(const char * __restrict, ...); __END_DECLS @@ -68,20 +69,20 @@ __END_DECLS #define assert(e) \ ((void) ((e) ? ((void)0) : __assert (#e, __FILE__, __LINE__))) #define __assert(e, file, line) \ - ((void)printf ("%s:%u: failed assertion `%s'\n", file, line, e), abort()) + ((void)printf ("%s:%d: failed assertion `%s'\n", file, line, e), abort()) #else /* __GNUC__ */ __BEGIN_DECLS -void __assert_rtn(const char *, const char *, int, const char *) __dead2 __disable_tail_calls; +void __assert_rtn(const char *, const char *, int, const char *) __dead2 __cold __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; +void __eprintf(const char *, const char *, unsigned, const char *) __dead2 __cold; #endif __END_DECLS #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1070) #define __assert(e, file, line) \ - __eprintf ("%s:%u: failed assertion `%s'\n", file, line, e) + __eprintf ("%s:%d: failed assertion `%s'\n", file, line, e) #else /* 8462256: modified __assert_rtn() replaces deprecated __eprintf() */ #define __assert(e, file, line) \ @@ -97,6 +98,13 @@ __END_DECLS #endif /* __DARWIN_UNIX03 */ #endif /* __GNUC__ */ +#else /* UNIFDEF_DRIVERKIT */ +__BEGIN_DECLS +void __assert_rtn(const char *, const char *, int, const char *) __dead2 __cold __disable_tail_calls; +__END_DECLS +#define assert(e) \ + (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0) +#endif /* UNIFDEF_DRIVERKIT */ #endif /* NDEBUG */ #ifndef _ASSERT_H_ diff --git a/include/dirent.h b/include/dirent.h index c105526..c8e0e0c 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -93,7 +93,8 @@ typedef struct { #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 */ +#define __DTF_SKIPREAD 0x0010 /* assume internal buffer is populated */ +#define __DTF_ATEND 0x0020 /* there's nothing more to read in the kernel */ #endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */ @@ -196,8 +197,16 @@ int dirfd(DIR *dirp) __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0); int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)) __DARWIN_INODE64(scandir); #ifdef __BLOCKS__ +#if __has_attribute(noescape) +#define __scandir_noescape __attribute__((__noescape__)) +#else +#define __scandir_noescape +#endif + int scandir_b(const char *, struct dirent ***, - int (^)(const struct dirent *), int (^)(const struct dirent **, const struct dirent **)) __DARWIN_INODE64(scandir_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (^)(const struct dirent *) __scandir_noescape, + int (^)(const struct dirent **, const struct dirent **) __scandir_noescape) + __DARWIN_INODE64(scandir_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); #endif /* __BLOCKS__ */ __END_DECLS diff --git a/include/err.h b/include/err.h index 6a53176..0d005d0 100644 --- a/include/err.h +++ b/include/err.h @@ -70,18 +70,18 @@ #include __BEGIN_DECLS -void err(int, const char *, ...) __dead2 __printflike(2, 3); -void verr(int, const char *, __darwin_va_list) __dead2 __printflike(2, 0); -void errc(int, int, const char *, ...) __dead2 __printflike(3, 4); -void verrc(int, int, const char *, __darwin_va_list) __dead2 __printflike(3, 0); -void errx(int, const char *, ...) __dead2 __printflike(2, 3); -void verrx(int, const char *, __darwin_va_list) __dead2 __printflike(2, 0); -void warn(const char *, ...) __printflike(1, 2); -void vwarn(const char *, __darwin_va_list) __printflike(1, 0); -void warnc(int, const char *, ...) __printflike(2, 3); -void vwarnc(int, const char *, __darwin_va_list) __printflike(2, 0); -void warnx(const char *, ...) __printflike(1, 2); -void vwarnx(const char *, __darwin_va_list) __printflike(1, 0); +void err(int, const char *, ...) __cold __dead2 __printflike(2, 3); +void verr(int, const char *, __darwin_va_list) __cold __dead2 __printflike(2, 0); +void errc(int, int, const char *, ...) __cold __dead2 __printflike(3, 4); +void verrc(int, int, const char *, __darwin_va_list) __cold __dead2 __printflike(3, 0); +void errx(int, const char *, ...) __cold __dead2 __printflike(2, 3); +void verrx(int, const char *, __darwin_va_list) __cold __dead2 __printflike(2, 0); +void warn(const char *, ...) __cold __printflike(1, 2); +void vwarn(const char *, __darwin_va_list) __cold __printflike(1, 0); +void warnc(int, const char *, ...) __cold __printflike(2, 3); +void vwarnc(int, const char *, __darwin_va_list) __cold __printflike(2, 0); +void warnx(const char *, ...) __cold __printflike(1, 2); +void vwarnx(const char *, __darwin_va_list) __cold __printflike(1, 0); void err_set_file(void *); void err_set_exit(void (* _Nullable)(int)); #ifdef __BLOCKS__ diff --git a/include/fts.h b/include/fts.h index 0263b5e..3256137 100644 --- a/include/fts.h +++ b/include/fts.h @@ -197,15 +197,22 @@ FTS *fts_open(char * const *, int, #endif /* !LIBC_ALIAS_FTS_OPEN */ //End-Libc #ifdef __BLOCKS__ +#if __has_attribute(noescape) +#define __fts_noescape __attribute__((__noescape__)) +#else +#define __fts_noescape +#endif //Begin-Libc #ifndef LIBC_ALIAS_FTS_OPEN_B //End-Libc FTS *fts_open_b(char * const *, int, - int (^)(const FTSENT **, const FTSENT **)) __DARWIN_INODE64(fts_open_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (^)(const FTSENT **, const FTSENT **) __fts_noescape) + __DARWIN_INODE64(fts_open_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); //Begin-Libc #else /* LIBC_ALIAS_FTS_OPEN */ FTS *fts_open_b(char * const *, int, - int (^)(const FTSENT **, const FTSENT **)) LIBC_INODE64(fts_open_b); + int (^)(const FTSENT **, const FTSENT **) __fts_noescape) + LIBC_INODE64(fts_open_b); #endif /* !LIBC_ALIAS_FTS_OPEN */ //End-Libc #endif /* __BLOCKS__ */ diff --git a/include/glob.h b/include/glob.h index 4f2b684..c602c8e 100644 --- a/include/glob.h +++ b/include/glob.h @@ -125,14 +125,19 @@ int glob(const char * __restrict, int, int (*)(const char *, int), #endif /* !LIBC_ALIAS_GLOB */ //End-Libc #ifdef __BLOCKS__ +#if __has_attribute(noescape) +#define __glob_noescape __attribute__((__noescape__)) +#else +#define __glob_noescape +#endif //Begin-Libc #ifndef LIBC_ALIAS_GLOB_B //End-Libc -int glob_b(const char * __restrict, int, int (^)(const char *, int), +int glob_b(const char * __restrict, int, int (^)(const char *, int) __glob_noescape, glob_t * __restrict) __DARWIN_INODE64(glob_b) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); //Begin-Libc #else /* LIBC_ALIAS_GLOB_B */ -int glob_b(const char * __restrict, int, int (^)(const char *, int), +int glob_b(const char * __restrict, int, int (^)(const char *, int) __glob_noescape, glob_t * __restrict) LIBC_INODE64(glob_b); #endif /* !LIBC_ALIAS_GLOB_B */ //End-Libc diff --git a/include/limits.h b/include/limits.h index 2ed444e..5917cca 100644 --- a/include/limits.h +++ b/include/limits.h @@ -62,6 +62,7 @@ #include #include +#ifndef UNIFDEF_DRIVERKIT #include #if __DARWIN_C_LEVEL > __DARWIN_C_ANSI @@ -163,5 +164,6 @@ #endif /* __DARWIN_C_LEVEL > __DARWIN_C_ANSI */ /* NZERO to be defined here. TBD. See also sys/param.h */ +#endif /* UNIFDEF_DRIVERKIT */ #endif /* !_LIMITS_H_ */ diff --git a/include/regex.h b/include/regex.h index 83e801a..7ef9b35 100644 --- a/include/regex.h +++ b/include/regex.h @@ -107,14 +107,16 @@ #define REG_NOSPEC 0020 /* Compile turning off all special characters */ #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8 \ - || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 + || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 \ + || defined(__DRIVERKIT_VERSION_MIN_REQUIRED) #define REG_LITERAL REG_NOSPEC #endif #define REG_PEND 0040 /* Use re_endp as end pointer */ #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8 \ - || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 + || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 \ + || defined(__DRIVERKIT_VERSION_MIN_REQUIRED) #define REG_MINIMAL 0100 /* Compile using minimal repetition */ #define REG_UNGREEDY REG_MINIMAL #endif @@ -122,7 +124,8 @@ #define REG_DUMP 0200 /* Unused */ #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8 \ - || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 + || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 \ + || defined(__DRIVERKIT_VERSION_MIN_REQUIRED) #define REG_ENHANCED 0400 /* Additional (non-POSIX) features */ #endif #endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */ @@ -168,7 +171,8 @@ #define REG_BACKR 02000 /* force use of backref code */ #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8 \ - || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 + || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 \ + || defined(__DRIVERKIT_VERSION_MIN_REQUIRED) #define REG_BACKTRACKING_MATCHER REG_BACKR #endif #endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */ @@ -183,7 +187,7 @@ int regcomp(regex_t * __restrict, const char * __restrict, int) __DARWIN_ALIAS(r int regcomp(regex_t * __restrict, const char * __restrict, int) LIBC_ALIAS(regcomp); #endif /* !LIBC_ALIAS_REGCOMP */ //End-Libc -size_t regerror(int, const regex_t * __restrict, char * __restrict, size_t); +size_t regerror(int, const regex_t * __restrict, char * __restrict, size_t) __cold; /* * gcc under c99 mode won't compile "[ __restrict]" by itself. As a workaround, * a dummy argument name is added. diff --git a/include/secure/_stdio.h b/include/secure/_stdio.h index c4dc7b2..76bdaaa 100644 --- a/include/secure/_stdio.h +++ b/include/secure/_stdio.h @@ -37,6 +37,7 @@ #define __has_builtin(x) 0 #endif +#ifndef UNIFDEF_DRIVERKIT /* sprintf, vsprintf, snprintf, vsnprintf */ #if __has_builtin(__builtin___sprintf_chk) || defined(__GNUC__) extern int __sprintf_chk (char * __restrict, int, size_t, @@ -46,6 +47,7 @@ extern int __sprintf_chk (char * __restrict, int, size_t, #define sprintf(str, ...) \ __builtin___sprintf_chk (str, 0, __darwin_obsz(str), __VA_ARGS__) #endif +#endif /* UNIFDEF_DRIVERKIT */ #if __DARWIN_C_LEVEL >= 200112L #if __has_builtin(__builtin___snprintf_chk) || defined(__GNUC__) @@ -57,6 +59,7 @@ extern int __snprintf_chk (char * __restrict, size_t, int, size_t, __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__) #endif +#ifndef UNIFDEF_DRIVERKIT #if __has_builtin(__builtin___vsprintf_chk) || defined(__GNUC__) extern int __vsprintf_chk (char * __restrict, int, size_t, const char * __restrict, va_list); @@ -65,6 +68,7 @@ extern int __vsprintf_chk (char * __restrict, int, size_t, #define vsprintf(str, format, ap) \ __builtin___vsprintf_chk (str, 0, __darwin_obsz(str), format, ap) #endif +#endif /* UNIFDEF_DRIVERKIT */ #if __has_builtin(__builtin___vsnprintf_chk) || defined(__GNUC__) extern int __vsnprintf_chk (char * __restrict, size_t, int, size_t, diff --git a/include/secure/_string.h b/include/secure/_string.h index 08e228d..595b85d 100644 --- a/include/secure/_string.h +++ b/include/secure/_string.h @@ -46,7 +46,8 @@ /* memccpy, memcpy, mempcpy, memmove, memset, strcpy, strlcpy, stpcpy, strncpy, stpncpy, strcat, strlcat, and strncat */ -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 || \ + defined(__DRIVERKIT_VERSION_MIN_REQUIRED) #if __has_builtin(__builtin___memccpy_chk) && __HAS_FIXED_CHK_PROTOTYPES #undef memccpy /* void *memccpy(void *dst, const void *src, int c, size_t n) */ @@ -76,6 +77,7 @@ __builtin___memset_chk (dest, __VA_ARGS__, __darwin_obsz0 (dest)) #endif +#ifndef UNIFDEF_DRIVERKIT #if __has_builtin(__builtin___strcpy_chk) || defined(__GNUC__) #undef strcpy /* char *strcpy(char *dst, const char *src) */ @@ -90,7 +92,10 @@ #define stpcpy(dest, ...) \ __builtin___stpcpy_chk (dest, __VA_ARGS__, __darwin_obsz (dest)) #endif +#endif /* __DARWIN_C_LEVEL >= 200809L */ +#endif /* UNIFDEF_DRIVERKIT */ +#if __DARWIN_C_LEVEL >= 200809L #if __has_builtin(__builtin___stpncpy_chk) || __APPLE_CC__ >= 5666 || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) #undef stpncpy /* char *stpncpy(char *dst, const char *src, size_t n) */ @@ -100,7 +105,8 @@ #endif /* _DARWIN_C_LEVEL >= 200809L */ #if __DARWIN_C_LEVEL >= __DARWIN_C_FULL -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 || \ + defined(__DRIVERKIT_VERSION_MIN_REQUIRED) #if __has_builtin(__builtin___strlcpy_chk) && __HAS_FIXED_CHK_PROTOTYPES #undef strlcpy /* size_t strlcpy(char *dst, const char *source, size_t size) */ @@ -124,12 +130,14 @@ __builtin___strncpy_chk (dest, __VA_ARGS__, __darwin_obsz (dest)) #endif +#ifndef UNIFDEF_DRIVERKIT #if __has_builtin(__builtin___strcat_chk) || defined(__GNUC__) #undef strcat /* char *strcat(char *s1, const char *s2) */ #define strcat(dest, ...) \ __builtin___strcat_chk (dest, __VA_ARGS__, __darwin_obsz (dest)) #endif +#endif /* UNIFDEF_DRIVERKIT */ #if ! (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 32000) #if __has_builtin(__builtin___strncat_chk) || defined(__GNUC__) diff --git a/include/stdint.h b/include/stdint.h index b4f027e..f4bb4cd 100644 --- a/include/stdint.h +++ b/include/stdint.h @@ -58,6 +58,25 @@ typedef uint64_t uint_fast64_t; #include <_types/_intmax_t.h> #include <_types/_uintmax_t.h> +/* 7.18.4 Macros for integer constants */ +#define INT8_C(v) (v) +#define INT16_C(v) (v) +#define INT32_C(v) (v) +#define INT64_C(v) (v ## LL) + +#define UINT8_C(v) (v) +#define UINT16_C(v) (v) +#define UINT32_C(v) (v ## U) +#define UINT64_C(v) (v ## ULL) + +#ifdef __LP64__ +#define INTMAX_C(v) (v ## L) +#define UINTMAX_C(v) (v ## UL) +#else +#define INTMAX_C(v) (v ## LL) +#define UINTMAX_C(v) (v ## ULL) +#endif + /* 7.18.2 Limits of specified-width integer types: * These #defines specify the minimum and maximum limits * of each of the types declared above. @@ -138,15 +157,14 @@ typedef uint64_t uint_fast64_t; #endif /* 7.18.2.5 Limits of greatest-width integer types */ -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX - -#define UINTMAX_MAX UINT64_MAX +#define INTMAX_MAX INTMAX_C(9223372036854775807) +#define UINTMAX_MAX UINTMAX_C(18446744073709551615) +#define INTMAX_MIN (-INTMAX_MAX-1) /* 7.18.3 "Other" */ #if __WORDSIZE == 64 -#define PTRDIFF_MIN INT64_MIN -#define PTRDIFF_MAX INT64_MAX +#define PTRDIFF_MIN INTMAX_MIN +#define PTRDIFF_MAX INTMAX_MAX #else #define PTRDIFF_MIN INT32_MIN #define PTRDIFF_MAX INT32_MAX @@ -184,23 +202,4 @@ typedef uint64_t uint_fast64_t; #define SIG_ATOMIC_MIN INT32_MIN #define SIG_ATOMIC_MAX INT32_MAX -/* 7.18.4 Macros for integer constants */ -#define INT8_C(v) (v) -#define INT16_C(v) (v) -#define INT32_C(v) (v) -#define INT64_C(v) (v ## LL) - -#define UINT8_C(v) (v) -#define UINT16_C(v) (v) -#define UINT32_C(v) (v ## U) -#define UINT64_C(v) (v ## ULL) - -#ifdef __LP64__ -#define INTMAX_C(v) (v ## L) -#define UINTMAX_C(v) (v ## UL) -#else -#define INTMAX_C(v) (v ## LL) -#define UINTMAX_C(v) (v ## ULL) -#endif - #endif /* _STDINT_H_ */ diff --git a/include/stdio.h b/include/stdio.h index 4535751..07730d4 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -63,6 +63,7 @@ #include <_stdio.h> +#ifndef UNIFDEF_DRIVERKIT __BEGIN_DECLS extern FILE *__stdinp; extern FILE *__stdoutp; @@ -199,7 +200,7 @@ size_t fwrite(const void * __restrict __ptr, size_t __size, size_t __nitems, FI int getc(FILE *); int getchar(void); char *gets(char *); -void perror(const char *); +void perror(const char *) __cold; int printf(const char * __restrict, ...) __printflike(1, 2); int putc(int, FILE *); int putchar(int); @@ -235,11 +236,7 @@ __END_DECLS #define L_ctermid 1024 /* size for ctermid(); PATH_MAX */ __BEGIN_DECLS -#ifndef __CTERMID_DEFINED -/* Multiply defined in stdio.h and unistd.h by SUS */ -#define __CTERMID_DEFINED 1 -char *ctermid(char *); -#endif +#include <_ctermid.h> #if defined(_DARWIN_UNLIMITED_STREAMS) || defined(_DARWIN_C_SOURCE) FILE *fdopen(int, const char *) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_3_2, __DARWIN_EXTSN(fdopen)); @@ -458,6 +455,22 @@ __END_DECLS #endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */ +#else /* UNIFDEF_DRIVERKIT */ +#define EOF (-1) + +__BEGIN_DECLS +int sscanf(const char * __restrict, const char * __restrict, ...) __scanflike(2, 3); +#if __DARWIN_C_LEVEL >= 200112L || defined(_C99_SOURCE) || defined(__cplusplus) +int snprintf(char * __restrict __str, size_t __size, const char * __restrict __format, ...) __printflike(3, 4); +int vsnprintf(char * __restrict __str, size_t __size, const char * __restrict __format, va_list) __printflike(3, 0); +int vsscanf(const char * __restrict __str, const char * __restrict __format, va_list) __scanflike(2, 0); +#endif /* __DARWIN_C_LEVEL >= 200112L || defined(_C99_SOURCE) || defined(__cplusplus) */ +#if __DARWIN_C_LEVEL >= __DARWIN_C_FULL +int asprintf(char ** __restrict, const char * __restrict, ...) __printflike(2, 3); +int vasprintf(char ** __restrict, const char * __restrict, va_list) __printflike(2, 0); +#endif /* __DARWIN_C_LEVEL >= __DARWIN_C_FULL */ +__END_DECLS +#endif /* UNIFDEF_DRIVERKIT */ #ifdef _USE_EXTENDED_LOCALES_ #include diff --git a/include/stdlib.h b/include/stdlib.h index 5be3e04..7979ffa 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -63,7 +63,9 @@ #include <_types.h> #if !defined(_ANSI_SOURCE) +#ifndef UNIFDEF_DRIVERKIT #include +#endif /* UNIFDEF_DRIVERKIT */ #if (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) #include #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ @@ -99,8 +101,10 @@ typedef struct { #include +#ifndef UNIFDEF_DRIVERKIT #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 +#endif /* UNIFDEF_DRIVERKIT */ #define RAND_MAX 0x7fffffff @@ -130,12 +134,16 @@ extern int __mb_cur_max; #define LIBC_ABORT(f,...) abort_report_np("%s:%s:%u: " f, __FILE__, __func__, __LINE__, ## __VA_ARGS__) //End-Libc +#ifndef UNIFDEF_DRIVERKIT #include +#endif /* UNIFDEF_DRIVERKIT */ __BEGIN_DECLS -void abort(void) __dead2; +void abort(void) __cold __dead2; int abs(int) __pure2; +#ifndef UNIFDEF_DRIVERKIT int atexit(void (* _Nonnull)(void)); +#endif /* UNIFDEF_DRIVERKIT */ double atof(const char *); int atoi(const char *); long atol(const char *); @@ -145,11 +153,15 @@ long long #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 *)); +#ifndef UNIFDEF_DRIVERKIT /* calloc is now declared in _malloc.h */ +#endif /* UNIFDEF_DRIVERKIT */ div_t div(int, int) __pure2; +#ifndef UNIFDEF_DRIVERKIT void exit(int) __dead2; /* free is now declared in _malloc.h */ char *getenv(const char *); +#endif /* UNIFDEF_DRIVERKIT */ long labs(long) __pure2; ldiv_t ldiv(long, long) __pure2; #if !__DARWIN_NO_LONG_LONG @@ -157,16 +169,22 @@ long long llabs(long long); lldiv_t lldiv(long long, long long); #endif /* !__DARWIN_NO_LONG_LONG */ +#ifndef UNIFDEF_DRIVERKIT /* malloc is now declared in _malloc.h */ +#endif /* UNIFDEF_DRIVERKIT */ 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); +#ifndef UNIFDEF_DRIVERKIT /* posix_memalign is now declared in _malloc.h */ +#endif /* UNIFDEF_DRIVERKIT */ void qsort(void *__base, size_t __nel, size_t __width, int (* _Nonnull __compar)(const void *, const void *)); +#ifndef UNIFDEF_DRIVERKIT int rand(void) __swift_unavailable("Use arc4random instead."); /* realloc is now declared in _malloc.h */ void srand(unsigned) __swift_unavailable("Use arc4random instead."); +#endif /* UNIFDEF_DRIVERKIT */ double strtod(const char *, char **) __DARWIN_ALIAS(strtod); float strtof(const char *, char **) __DARWIN_ALIAS(strtof); long strtol(const char *__str, char **__endptr, int __base); @@ -182,6 +200,7 @@ unsigned long unsigned long long strtoull(const char *__str, char **__endptr, int __base); #endif /* !__DARWIN_NO_LONG_LONG */ +#ifndef UNIFDEF_DRIVERKIT //Begin-Libc #ifndef LIBC_ALIAS_SYSTEM //End-Libc @@ -203,10 +222,12 @@ int system(const char *) LIBC_ALIAS_C(system); //End-Libc #undef __swift_unavailable_on +#endif /* UNIFDEF_DRIVERKIT */ size_t wcstombs(char * __restrict, const wchar_t * __restrict, size_t); int wctomb(char *, wchar_t); +#ifndef UNIFDEF_DRIVERKIT #ifndef _ANSI_SOURCE void _Exit(int) __dead2; long a64l(const char *); @@ -315,30 +336,37 @@ int unsetenv(const char *) LIBC_ALIAS(unsetenv); void unsetenv(const char *); #endif /* __DARWIN_UNIX03 */ #endif /* !_ANSI_SOURCE */ +#endif /* UNIFDEF_DRIVERKIT */ #if !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) #include - +#ifndef UNIFDEF_DRIVERKIT #include #include +#endif /* UNIFDEF_DRIVERKIT */ #include <_types/_uint32_t.h> uint32_t arc4random(void); +#ifndef UNIFDEF_DRIVERKIT void arc4random_addrandom(unsigned char * /*dat*/, int /*datlen*/) __OSX_DEPRECATED(10.0, 10.12, "use arc4random_stir") __IOS_DEPRECATED(2.0, 10.0, "use arc4random_stir") __TVOS_DEPRECATED(2.0, 10.0, "use arc4random_stir") __WATCHOS_DEPRECATED(1.0, 3.0, "use arc4random_stir"); +#endif /* UNIFDEF_DRIVERKIT */ void arc4random_buf(void * __buf, size_t __nbytes) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); void arc4random_stir(void); uint32_t arc4random_uniform(uint32_t __upper_bound) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); #ifdef __BLOCKS__ +#ifndef UNIFDEF_DRIVERKIT int atexit_b(void (^ _Nonnull)(void)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); +#endif /* UNIFDEF_DRIVERKIT */ void *bsearch_b(const void *__key, const void *__base, size_t __nel, size_t __width, int (^ _Nonnull __compar)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); #endif /* __BLOCKS__ */ +#ifndef UNIFDEF_DRIVERKIT /* getcap(3) functions */ char *cgetcap(char *, const char *, int); int cgetclose(void); @@ -358,49 +386,72 @@ char *getbsize(int *, long *); int getloadavg(double [], int); const char *getprogname(void); +void setprogname(const char *); +#endif /* UNIFDEF_DRIVERKIT */ + +#ifdef __BLOCKS__ +#if __has_attribute(noescape) +#define __sort_noescape __attribute__((__noescape__)) +#else +#define __sort_noescape +#endif +#endif /* __BLOCKS__ */ int heapsort(void *__base, size_t __nel, size_t __width, int (* _Nonnull __compar)(const void *, const void *)); #ifdef __BLOCKS__ int heapsort_b(void *__base, size_t __nel, size_t __width, - int (^ _Nonnull __compar)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (^ _Nonnull __compar)(const void *, const void *) __sort_noescape) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); #endif /* __BLOCKS__ */ int mergesort(void *__base, size_t __nel, size_t __width, int (* _Nonnull __compar)(const void *, const void *)); #ifdef __BLOCKS__ int mergesort_b(void *__base, size_t __nel, size_t __width, - int (^ _Nonnull __compar)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (^ _Nonnull __compar)(const void *, const void *) __sort_noescape) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); #endif /* __BLOCKS__ */ +#ifndef UNIFDEF_DRIVERKIT void psort(void *__base, size_t __nel, size_t __width, - int (* _Nonnull __compar)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (* _Nonnull __compar)(const void *, const void *)) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); #ifdef __BLOCKS__ void psort_b(void *__base, size_t __nel, size_t __width, - int (^ _Nonnull __compar)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (^ _Nonnull __compar)(const void *, const void *) __sort_noescape) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); #endif /* __BLOCKS__ */ void psort_r(void *__base, size_t __nel, size_t __width, void *, - int (* _Nonnull __compar)(void *, const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (* _Nonnull __compar)(void *, const void *, const void *)) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); +#endif /* UNIFDEF_DRIVERKIT */ #ifdef __BLOCKS__ void qsort_b(void *__base, size_t __nel, size_t __width, - int (^ _Nonnull __compar)(const void *, const void *)) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); + int (^ _Nonnull __compar)(const void *, const void *) __sort_noescape) + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); #endif /* __BLOCKS__ */ void qsort_r(void *__base, size_t __nel, size_t __width, void *, int (* _Nonnull __compar)(void *, const void *, const void *)); int radixsort(const unsigned char **__base, int __nel, const unsigned char *__table, unsigned __endbyte); -void setprogname(const char *); +int rpmatch(const char *) + __API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0)); int sradixsort(const unsigned char **__base, int __nel, const unsigned char *__table, unsigned __endbyte); +#ifndef UNIFDEF_DRIVERKIT void sranddev(void); void srandomdev(void); void *reallocf(void *__ptr, size_t __size) __alloc_size(2); +#endif /* UNIFDEF_DRIVERKIT */ #if !__DARWIN_NO_LONG_LONG long long strtoq(const char *__str, char **__endptr, int __base); unsigned long long strtouq(const char *__str, char **__endptr, int __base); #endif /* !__DARWIN_NO_LONG_LONG */ +#ifndef UNIFDEF_DRIVERKIT extern char *suboptarg; /* getsubopt(3) external variable */ /* valloc is now declared in _malloc.h */ +#endif /* UNIFDEF_DRIVERKIT */ #endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */ /* Poison the following routines if -fshort-wchar is set */ diff --git a/include/string.h b/include/string.h index 6fe4b8d..a166d36 100644 --- a/include/string.h +++ b/include/string.h @@ -72,11 +72,15 @@ int memcmp(const void *__s1, const void *__s2, size_t __n); void *memcpy(void *__dst, const void *__src, size_t __n); void *memmove(void *__dst, const void *__src, size_t __len); void *memset(void *__b, int __c, size_t __len); +#ifndef UNIFDEF_DRIVERKIT char *strcat(char *__s1, const char *__s2); +#endif /* UNIFDEF_DRIVERKIT */ char *strchr(const char *__s, int __c); int strcmp(const char *__s1, const char *__s2); int strcoll(const char *__s1, const char *__s2); +#ifndef UNIFDEF_DRIVERKIT char *strcpy(char *__dst, const char *__src); +#endif /* UNIFDEF_DRIVERKIT */ size_t strcspn(const char *__s, const char *__charset); //Begin-Libc #ifndef LIBC_ALIAS_STRERROR @@ -135,7 +139,9 @@ __END_DECLS #if __DARWIN_C_LEVEL >= 200809L __BEGIN_DECLS +#ifndef UNIFDEF_DRIVERKIT char *stpcpy(char *__dst, const char *__src); +#endif /* UNIFDEF_DRIVERKIT */ char *stpncpy(char *__dst, const char *__src, size_t __n) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); char *strndup(const char *__s1, size_t __n) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); size_t strnlen(const char *__s1, size_t __n) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); diff --git a/include/struct.h b/include/struct.h index e8dab2c..4dff678 100644 --- a/include/struct.h +++ b/include/struct.h @@ -61,6 +61,13 @@ (sizeof(arr) / sizeof(arr[0])) #endif +/* + * countof() cannot be safely used in a _Static_assert statement, so we provide + * an unsafe variant that does not verify the input array is statically-defined. + */ +#define countof_unsafe(arr) \ + (sizeof(arr) / sizeof(arr[0])) + /* Length of a statically-defined string (does not include null terminator) */ #define lenof(str) \ (sizeof(str) - 1) diff --git a/include/time.h b/include/time.h index 51442ef..3024c87 100644 --- a/include/time.h +++ b/include/time.h @@ -64,7 +64,9 @@ #define _TIME_H_ #include <_types.h> +#include #include +#ifndef UNIFDEF_DRIVERKIT #include #include #include @@ -110,8 +112,10 @@ extern long timezone LIBC_ALIAS(timezone); //End-Libc #endif /* __DARWIN_UNIX03 */ extern int daylight; +#endif /* UNIFDEF_DRIVERKIT */ __BEGIN_DECLS +#ifndef UNIFDEF_DRIVERKIT char *asctime(const struct tm *); //Begin-Libc #ifndef LIBC_ALIAS_CLOCK @@ -188,6 +192,7 @@ int nanosleep(const struct timespec *__rqtp, struct timespec *__rmtp) LIBC_ALIAS #endif /* !LIBC_ALIAS_NANOSLEEP */ //End-Libc #endif +#endif /* UNIFDEF_DRIVERKIT */ #if !defined(_DARWIN_FEATURE_CLOCK_GETTIME) || _DARWIN_FEATURE_CLOCK_GETTIME != 0 #if __DARWIN_C_LEVEL >= 199309L @@ -218,25 +223,40 @@ _CLOCK_THREAD_CPUTIME_ID __CLOCK_AVAILABILITY = 16 #define CLOCK_THREAD_CPUTIME_ID _CLOCK_THREAD_CPUTIME_ID } clockid_t; +#ifndef UNIFDEF_DRIVERKIT __CLOCK_AVAILABILITY int clock_getres(clockid_t __clock_id, struct timespec *__res); __CLOCK_AVAILABILITY int clock_gettime(clockid_t __clock_id, struct timespec *__tp); +#endif /* UNIFDEF_DRIVERKIT */ #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) __CLOCK_AVAILABILITY __uint64_t clock_gettime_nsec_np(clockid_t __clock_id); #endif +#ifndef UNIFDEF_DRIVERKIT __OSX_AVAILABLE(10.12) __IOS_PROHIBITED __TVOS_PROHIBITED __WATCHOS_PROHIBITED int clock_settime(clockid_t __clock_id, const struct timespec *__tp); +#endif /* UNIFDEF_DRIVERKIT */ #undef __CLOCK_AVAILABILITY #endif /* __DARWIN_C_LEVEL */ #endif /* _DARWIN_FEATURE_CLOCK_GETTIME */ +#ifndef UNIFDEF_DRIVERKIT +#if (__DARWIN_C_LEVEL >= __DARWIN_C_FULL) && \ + ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ + (defined(__cplusplus) && __cplusplus >= 201703L)) +/* ISO/IEC 9899:201x 7.27.2.5 The timespec_get function */ +#define TIME_UTC 1 /* time elapsed since epoch */ +__API_AVAILABLE(macosx(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +int timespec_get(struct timespec *ts, int base); +#endif + +#endif /* UNIFDEF_DRIVERKIT */ __END_DECLS #ifdef _USE_EXTENDED_LOCALES_ diff --git a/include/unistd.h b/include/unistd.h index 7896f8d..01b7166 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -164,7 +164,12 @@ #endif /* __DARWIN_C_LEVEL */ #define __ILP32_OFF32 (-1) +#ifdef UNIFDEF_POSIX_ILP32_ALLOW #define __ILP32_OFFBIG (1) +#else // UNIFDEF_POSIX_ILP32_ALLOW +#define __ILP32_OFFBIG (-1) +#endif // UNIFDEF_POSIX_ILP32_ALLOW + #define __LP64_OFF64 (1) #define __LPBIG_OFFBIG (1) @@ -586,6 +591,7 @@ __END_DECLS */ #if __DARWIN_C_LEVEL >= 199506L +#include <_ctermid.h> /* These F_* are really XSI or Issue 6 */ #define F_ULOCK 0 /* unlock locked section */ #define F_LOCK 1 /* lock a section for exclusive use */ @@ -605,11 +611,6 @@ int chroot(const char *) __POSIX_C_DEPRECATED(199506L); #endif char *crypt(const char *, const char *); -#ifndef __CTERMID_DEFINED -/* Multiply defined in stdio.h and unistd.h by SUS */ -#define __CTERMID_DEFINED 1 -char *ctermid(char *); -#endif #if __DARWIN_UNIX03 //Begin-Libc #ifndef LIBC_ALIAS_ENCRYPT diff --git a/include/wchar.h b/include/wchar.h index 1e514ae..f68ce8f 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -88,13 +88,16 @@ #include #include +#ifndef UNIFDEF_DRIVERKIT #include +#endif /* UNIFDEF_DRIVERKIT */ #include <_wctype.h> /* Initially added in Issue 4 */ __BEGIN_DECLS wint_t btowc(int); +#ifndef UNIFDEF_DRIVERKIT wint_t fgetwc(FILE *); wchar_t *fgetws(wchar_t * __restrict, int, FILE * __restrict); wint_t fputwc(wchar_t, FILE *); @@ -104,22 +107,29 @@ int fwprintf(FILE * __restrict, const wchar_t * __restrict, ...); int fwscanf(FILE * __restrict, const wchar_t * __restrict, ...); wint_t getwc(FILE *); wint_t getwchar(void); +#endif /* UNIFDEF_DRIVERKIT */ size_t mbrlen(const char * __restrict, size_t, mbstate_t * __restrict); size_t mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); int mbsinit(const mbstate_t *); size_t mbsrtowcs(wchar_t * __restrict, const char ** __restrict, size_t, mbstate_t * __restrict); +#ifndef UNIFDEF_DRIVERKIT wint_t putwc(wchar_t, FILE *); wint_t putwchar(wchar_t); +#endif /* UNIFDEF_DRIVERKIT */ int swprintf(wchar_t * __restrict, size_t, const wchar_t * __restrict, ...); int swscanf(const wchar_t * __restrict, const wchar_t * __restrict, ...); +#ifndef UNIFDEF_DRIVERKIT wint_t ungetwc(wint_t, FILE *); int vfwprintf(FILE * __restrict, const wchar_t * __restrict, __darwin_va_list); +#endif /* UNIFDEF_DRIVERKIT */ int vswprintf(wchar_t * __restrict, size_t, const wchar_t * __restrict, __darwin_va_list); +#ifndef UNIFDEF_DRIVERKIT int vwprintf(const wchar_t * __restrict, __darwin_va_list); +#endif /* UNIFDEF_DRIVERKIT */ size_t wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); wchar_t *wcscat(wchar_t * __restrict, const wchar_t * __restrict); wchar_t *wcschr(const wchar_t *, wchar_t); @@ -127,6 +137,7 @@ int wcscmp(const wchar_t *, const wchar_t *); int wcscoll(const wchar_t *, const wchar_t *); wchar_t *wcscpy(wchar_t * __restrict, const wchar_t * __restrict); size_t wcscspn(const wchar_t *, const wchar_t *); +#ifndef UNIFDEF_DRIVERKIT //Begin-Libc #ifndef LIBC_ALIAS_WCSFTIME //End-Libc @@ -138,6 +149,7 @@ size_t wcsftime(wchar_t * __restrict, size_t, const wchar_t * __restrict, const struct tm * __restrict) LIBC_ALIAS(wcsftime); #endif /* !LIBC_ALIAS_WCSFTIME */ //End-Libc +#endif /* UNIFDEF_DRIVERKIT */ size_t wcslen(const wchar_t *); wchar_t *wcsncat(wchar_t * __restrict, const wchar_t * __restrict, size_t); int wcsncmp(const wchar_t *, const wchar_t *, size_t); @@ -161,8 +173,10 @@ int wmemcmp(const wchar_t *, const wchar_t *, size_t); wchar_t *wmemcpy(wchar_t * __restrict, const wchar_t * __restrict, size_t); wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t); wchar_t *wmemset(wchar_t *, wchar_t, size_t); +#ifndef UNIFDEF_DRIVERKIT int wprintf(const wchar_t * __restrict, ...); int wscanf(const wchar_t * __restrict, ...); +#endif /* UNIFDEF_DRIVERKIT */ int wcswidth(const wchar_t *, size_t); int wcwidth(wchar_t); __END_DECLS @@ -176,11 +190,15 @@ __END_DECLS #if __DARWIN_C_LEVEL >= 200112L || defined(_C99_SOURCE) || defined(__cplusplus) __BEGIN_DECLS +#ifndef UNIFDEF_DRIVERKIT int vfwscanf(FILE * __restrict, const wchar_t * __restrict, __darwin_va_list); +#endif /* UNIFDEF_DRIVERKIT */ int vswscanf(const wchar_t * __restrict, const wchar_t * __restrict, __darwin_va_list); +#ifndef UNIFDEF_DRIVERKIT int vwscanf(const wchar_t * __restrict, __darwin_va_list); +#endif /* UNIFDEF_DRIVERKIT */ float wcstof(const wchar_t * __restrict, wchar_t ** __restrict); long double wcstold(const wchar_t * __restrict, wchar_t ** __restrict); @@ -211,7 +229,9 @@ int wcsncasecmp(const wchar_t *, const wchar_t *, size_t n) __OSX_AVAILABLE_ 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); +#ifndef UNIFDEF_DRIVERKIT FILE *open_wmemstream(wchar_t ** __bufp, size_t * __sizep) __API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0)); +#endif /* UNIFDEF_DRIVERKIT */ __END_DECLS #endif /* __DARWIN_C_LEVEL >= 200809L */ @@ -221,7 +241,9 @@ __END_DECLS #if __DARWIN_C_LEVEL >= __DARWIN_C_FULL __BEGIN_DECLS +#ifndef UNIFDEF_DRIVERKIT wchar_t *fgetwln(FILE * __restrict, size_t *) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); +#endif /* UNIFDEF_DRIVERKIT */ size_t wcslcat(wchar_t *, const wchar_t *, size_t); size_t wcslcpy(wchar_t *, const wchar_t *, size_t); __END_DECLS diff --git a/include/xlocale.h b/include/xlocale.h index 8569540..5375138 100644 --- a/include/xlocale.h +++ b/include/xlocale.h @@ -50,6 +50,7 @@ #define _LC_LAST_MASK (1 << (_LC_NUM_MASK - 1)) #define LC_GLOBAL_LOCALE ((locale_t)-1) +#define LC_C_LOCALE ((locale_t)NULL) #ifdef MB_CUR_MAX #undef MB_CUR_MAX diff --git a/libdarwin/bsd.c b/libdarwin/bsd.c index 30d915f..35cbafd 100644 --- a/libdarwin/bsd.c +++ b/libdarwin/bsd.c @@ -23,137 +23,76 @@ #include "internal.h" #pragma mark Utilities -static int -_sysctl_12809455(int mib[4], size_t mib_cnt, void *old, size_t *old_len, - void *new, size_t new_len) -{ - int error = -1; - int ret = -1; - size_t mylen = 0; - size_t *mylenp = NULL; -#if RDAR_12809455 - bool workaround_12809455 = false; -#endif - - if (old_len) { - mylen = *old_len; - mylenp = &mylen; - } - - // sysctl(3) doesn't behave anything like its documentation leads you to - // believe. If the given buffer is too small to hold the requested data, - // what's supposed to happen is: - // - // - as much data as possible is copied into the buffer - // - the number of bytes copied is written to the len parameter - // - errno is set to ENOMEM - // - -1 is returned (to indicate that you should check errno) - // - // What actually happens: - // - // - no data is copied - // - len is set to zero - // - errno is undefined - // - zero is returned - // - // So... swing and a miss. - // - // Since it returns success in this case our only indication that something - // went wrong is if mylen is set to zero. - // - // So we do our best to sniff out the misbehavior and emulate sysctl(3)'s - // API contract until it's fixed. - // - // -#if RDAR_12809455 - if (old_len && *old_len > 0) { - // We can only work around the bug if the passed-in length was non-zero. - workaround_12809455 = true; - } -#endif - - ret = sysctl(mib, (u_int)mib_cnt, old, mylenp, new, new_len); -#if RDAR_12809455 - if (workaround_12809455 && old && ret == 0 && mylen == 0) { - ret = -1; - errno = ENOMEM; - } -#endif // RDAR_12809455 - - if (ret == 0) { - error = 0; - } else { - error = errno; - } - - if (old_len) { - *old_len = mylen; - } - - return error; -} -static char * -_strblk(const char *str) +/* + * Factored out from _get_parse_boot_arg_value for unit testing purposes + */ +static bool +_parse_boot_arg_value(char *argsbuff, const char *which, char *where, size_t max) { - const char *cur = str; + bool found = false; - while (*cur && !isblank(*cur)) { - cur++; + char *token = NULL; + char *argsstr = argsbuff; + static const char seps[] = { ' ', '\t', }; + while ((token = strsep(&argsstr, seps)) != NULL) { + bool is_boolean = false; + + char *value = NULL; + char *equals = strchr(token, '='); + if (token[0] == '-') { + /* + * Arguments whose names begins with "-" are booleans, so don't get + * key=value splitting. Though I'd still discourage you from + * naming your option "-edge=case". + */ + is_boolean = true; + } else if (equals) { + equals[0] = '\0'; + value = &equals[1]; + } else { + is_boolean = true; + } + + if (strcmp(which, token) == 0) { + /* + * Found it! Copy out the value as required. + */ + found = true; + + if (!where) { + // Caller just wants to know whether the boot-arg exists. + } else if (is_boolean || value == NULL) { + strlcpy(where, "", max); + } else { + strlcpy(where, value, max); + } + + break; + } } - return (char *)cur; + return found; } +/* + * This is (very) loosely based on the implementation of + * PE_parse_boot_argn() (or at least the parts where I was able to easily + * decipher the policy). + */ static bool _get_boot_arg_value(const char *which, char *where, size_t max) { - // This is (very) loosely based on the implementation of - // PE_parse_boot_argn() (or at least the parts where I was able to easily - // decipher the policy). bool found = false; - errno_t error = -1; - char *buff = NULL; - size_t buff_len = 0; - char *theone = NULL; - char *equals = NULL; - - error = sysctlbyname_get_data_np("kern.bootargs", (void **)&buff, - &buff_len); - if (error) { - goto __out; - } + __os_free char *argsbuff = NULL; + size_t argsbuff_len = 0; + errno_t error = sysctlbyname_get_data_np("kern.bootargs", + (void **)&argsbuff, &argsbuff_len); - theone = strstr(buff, which); - if (!theone) { - goto __out; + if (!error) { + found = _parse_boot_arg_value(argsbuff, which, where, max); } - found = true; - if (!where) { - // Caller just wants to know whether the boot-arg exists. - goto __out; - } - - equals = strchr(theone, '='); - if (!equals || isblank(equals[1])) { - strlcpy(where, "", max); - } else { - char *nextsep = NULL; - char nextsep_old = 0; - - // Find the next separator and nerf it temporarily for the benefit of - // the underlying strcpy(3). - nextsep = _strblk(theone); - nextsep_old = *nextsep; - *nextsep = 0; - strlcpy(where, &equals[1], max); - - *nextsep = nextsep_old; - } - -__out: - free(buff); return found; } @@ -161,14 +100,16 @@ __out: errno_t sysctl_get_data_np(int mib[4], size_t mib_cnt, void **buff, size_t *buff_len) { - errno_t error = -1; + errno_t error = 0; + int ret = 0; size_t needed = 0; void *mybuff = NULL; // We need to get the length of the parameter so we can allocate a buffer // that's large enough. - error = _sysctl_12809455(mib, mib_cnt, NULL, &needed, NULL, 0); - if (error) { + ret = sysctl(mib, (unsigned int)mib_cnt, NULL, &needed, NULL, 0); + if (ret) { + error = errno; goto __out; } @@ -178,11 +119,12 @@ sysctl_get_data_np(int mib[4], size_t mib_cnt, void **buff, size_t *buff_len) goto __out; } - error = _sysctl_12809455(mib, mib_cnt, mybuff, &needed, NULL, 0); - if (error) { + ret = sysctl(mib, (unsigned int)mib_cnt, mybuff, &needed, NULL, 0); + if (ret) { // It's conceivable that some other process came along within this // window and modified the variable to be even larger than we'd // previously been told, but if that's the case, just give up. + error = errno; goto __out; } diff --git a/libdarwin/ctl.c b/libdarwin/ctl.c new file mode 100755 index 0000000..8015ba3 --- /dev/null +++ b/libdarwin/ctl.c @@ -0,0 +1,289 @@ +#include "internal.h" + +#pragma mark Definitions +#define CTL_OUTPUT_WIDTH (80) +#define CTL_OUTPUT_OPTARG_PAD (28) +#define CTL_OUTPUT_LIST_PAD (4) +#define SUBCOMMAND_LINKER_SET "__subcommands" + +#pragma mark Module Globals +static const os_subcommand_t _help_cmd; + +#pragma mark Module Routines +static char * +_os_subcommand_copy_optarg_usage(const os_subcommand_t *osc, + const struct option *opt, os_subcommand_optarg_format_t format, + os_subcommand_option_t *scopt) +{ + char optbuff[64] = ""; + char argbuff[64] = ""; + char *final = NULL; + int ret = -1; + + snprintf(optbuff, sizeof(optbuff), "--%s", opt->name); + + if (osc->osc_info) { + osc->osc_info(osc, format, opt, scopt); + } + + switch (opt->has_arg) { + case no_argument: + break; + case optional_argument: + snprintf(argbuff, sizeof(argbuff), "[=%s]", scopt->osco_argdesc); + break; + case required_argument: + snprintf(argbuff, sizeof(argbuff), "=<%s>", scopt->osco_argdesc); + break; + default: + __builtin_unreachable(); + } + + ret = asprintf(&final, "%s%s", optbuff, argbuff); + if (ret < 0) { + os_assert_zero(ret); + } + + return final; +} + +static void +_os_subcommand_print_optarg_usage(const os_subcommand_t *osc, + const struct option *opt, FILE *f) +{ + os_subcommand_option_t scopt = { + .osco_flags = 0, + .osco_argdesc = opt->name, + }; + char *__os_free usage = NULL; + char *braces[2] = { + "", + "", + }; + + usage = _os_subcommand_copy_optarg_usage(osc, opt, + OS_SUBCOMMAND_OPTARG_USAGE, &scopt); + if (scopt.osco_flags & OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL) { + braces[0] = "["; + braces[1] = "]"; + } + + fprintf(f, " %s%s%s", braces[0], usage, braces[1]); +} + +static void +_os_subcommand_print_usage(const os_subcommand_t *osc, FILE *f) +{ + const struct option *opts = osc->osc_options; + const struct option *curopt = NULL; + size_t i = 0; + + fprintf(f, "usage: %s %s", getprogname(), osc->osc_name); + + while ((curopt = &opts[i]) && curopt->name) { + _os_subcommand_print_optarg_usage(osc, curopt, f); + i++; + } + + fprintf(f, "\n"); +} + +static void +_os_subcommand_print_optarg_human(const os_subcommand_t *osc, + const struct option *opt, FILE *f) +{ + os_subcommand_option_t scopt = { + .osco_flags = 0, + .osco_argdesc = opt->name, + }; + char *__os_free usage = NULL; + char *__os_free human = NULL; + + usage = _os_subcommand_copy_optarg_usage(osc, opt, + OS_SUBCOMMAND_OPTARG_USAGE, &scopt); + fprintf(f, " %-24s", usage); + + human = _os_subcommand_copy_optarg_usage(osc, opt, + OS_SUBCOMMAND_OPTARG_HUMAN, &scopt); + wfprintf_np(f, -CTL_OUTPUT_OPTARG_PAD, CTL_OUTPUT_OPTARG_PAD, + CTL_OUTPUT_WIDTH, "%s", scopt.osco_argdesc); +} + +static void +_os_subcommand_print_human(const os_subcommand_t *osc, FILE *f) +{ + const struct option *opts = osc->osc_options; + const struct option *curopt = NULL; + size_t i = 0; + + _os_subcommand_print_usage(osc, f); + + while ((curopt = &opts[i]) && curopt->name) { + _os_subcommand_print_optarg_human(osc, curopt, f); + i++; + } +} + +static void +_os_subcommand_print_list(const os_subcommand_t *osc, FILE *f) +{ + wfprintf_np(f, CTL_OUTPUT_LIST_PAD, 0, 0, "%-24s %s", + osc->osc_name, osc->osc_desc); +} + +static const os_subcommand_t * +_os_subcommand_find(const char *name) +{ + const os_subcommand_t **oscip = NULL; + + if (strcmp(_help_cmd.osc_name, name) == 0) { + return &_help_cmd; + } + + LINKER_SET_FOREACH(oscip, const os_subcommand_t **, SUBCOMMAND_LINKER_SET) { + const os_subcommand_t *osci = *oscip; + + if (strcmp(osci->osc_name, name) == 0) { + return osci; + } + } + + return NULL; +} + +#pragma mark Default Usage +static void +_usage_default(FILE *f) +{ + const os_subcommand_t **oscip = NULL; + + crfprintf_np(f, "usage: %s [...] | help [subcommand]", + getprogname()); + crfprintf_np(f, ""); + + crfprintf_np(f, "subcommands:"); + LINKER_SET_FOREACH(oscip, const os_subcommand_t **, SUBCOMMAND_LINKER_SET) { + const os_subcommand_t *osci = *oscip; + _os_subcommand_print_list(osci, f); + } + + _os_subcommand_print_list(&_help_cmd, f); +} + +static int +_usage(FILE *f) +{ + _usage_default(f); + return EX_USAGE; +} + +#pragma mark Help Subcommand +static int _help_invoke(const os_subcommand_t *osc, + int argc, + const char *argv[] +); + +static const os_subcommand_t _help_cmd = { + .osc_version = OS_SUBCOMMAND_VERSION, + .osc_flags = 0, + .osc_name = "help", + .osc_desc = "prints helpful information", + .osc_optstring = NULL, + .osc_options = NULL, + .osc_info = NULL, + .osc_invoke = &_help_invoke, +}; + +static void +_help_print_subcommand(const os_subcommand_t *osc, FILE *f) +{ + wfprintf_np(f, 4, 4, 76, "%-16s%s", osc->osc_name, osc->osc_desc); +} + +static void +_help_print_all(FILE *f) +{ + const os_subcommand_t **oscip = NULL; + + _usage_default(f); + crfprintf_np(f, ""); + + crfprintf_np(f, "subcommands:"); + LINKER_SET_FOREACH(oscip, const os_subcommand_t **, SUBCOMMAND_LINKER_SET) { + const os_subcommand_t *osci = *oscip; + if (osci->osc_flags & OS_SUBCOMMAND_FLAG_HIDDEN) { + continue; + } + _help_print_subcommand(osci, f); + } +} + +static int +_help_invoke(const os_subcommand_t *osc, int argc, const char *argv[]) +{ + const os_subcommand_t *target = NULL; + + if (argc == 1) { + _help_print_all(stdout); + } else { + target = _os_subcommand_find(argv[1]); + if (!target) { + crfprintf_np(stderr, "unrecognized subcommand: %s", argv[1]); + _usage_default(stderr); + return EX_USAGE; + } + + _os_subcommand_print_human(target, stdout); + } + + return 0; +} + +#pragma mark API +int +os_subcommand_main(int argc, const char *argv[]) +{ + int exitcode = -1; + const char *cmdname = NULL; + const os_subcommand_t *osci = NULL; + + if (argc < 2) { + exitcode = _usage(stderr); + goto __out; + } + + // Advance argument pointer and make the subcommand argv[0]. + argc -= 1; + argv += 1; + cmdname = argv[0]; + + osci = _os_subcommand_find(cmdname); + if (osci) { + if (osci->osc_flags & OS_SUBCOMMAND_FLAG_REQUIRE_ROOT) { + if (geteuid()) { + crfprintf_np(stderr, "subcommand requires root: %s", cmdname); + exitcode = EX_NOPERM; + goto __out; + } + } + + if (osci->osc_flags & OS_SUBCOMMAND_FLAG_TTYONLY) { + if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO)) { + crfprintf_np(stderr, "subcommand requires a tty: %s", cmdname); + exitcode = EX_UNAVAILABLE; + goto __out; + } + } + + exitcode = osci->osc_invoke(osci, argc, argv); + if (exitcode == EX_USAGE) { + _os_subcommand_print_usage(osci, stderr); + } + } else { + crfprintf_np(stderr, "unrecognized subcommand: %s", cmdname); + exitcode = _usage(stderr); + } + +__out: + return exitcode; +} diff --git a/libdarwin/h/cleanup.h b/libdarwin/h/cleanup.h index c74c8f1..0b82c05 100644 --- a/libdarwin/h/cleanup.h +++ b/libdarwin/h/cleanup.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include __BEGIN_DECLS; @@ -121,11 +123,11 @@ __os_cleanup_fclose(FILE **__fp) /*! * @define __os_close_mach_recv * An attribute that may be applied to a variable's type. This attribute causes - * the variable to be passed to {@link darwin_mach_port_close_recv} when it goes - * out of scope. Applying this attribute to variables that do not reference a - * valid Mach port receive right will result in undefined behavior. If the - * variable's value is MACH_PORT_NULL or MACH_PORT_DEAD upon going out-of-scope, - * no cleanup is performed. + * the variable to be wrapped in a mach receive right object and passed to + * {@link mach_right_recv_destruct} when it goes out of scope. Applying this + * attribute to variables that do not reference a valid Mach port receive right + * will result in undefined behavior. If the variable's value is MACH_PORT_NULL + * or MACH_PORT_DEAD upon going out-of-scope, no cleanup is performed. */ #define __os_close_mach_recv \ __attribute__((cleanup(__os_cleanup_close_mach_recv))) @@ -133,24 +135,24 @@ static inline void __os_cleanup_close_mach_recv(mach_port_t *__p) { mach_port_t p = *__p; - kern_return_t kr = KERN_FAILURE; + mach_right_recv_t mr = mach_right_recv(p); if (!MACH_PORT_VALID(p)) { return; } - kr = mach_port_destruct(mach_task_self(), p, 0, 0); - os_assert_zero(kr); + mach_right_recv_destruct(mr, NULL, 0); } /*! * @define __os_release_mach_send * An attribute that may be applied to a variable's type. This attribute causes - * the variable to be passed to {@link darwin_mach_port_release} when it goes - * out of scope. Applying this attribute to variables that do not reference a - * valid Mach port send right or MACH_PORT_NULL or MACH_PORT_DEAD will result - * in undefined behavior. If the variable's value is MACH_PORT_NULL or - * MACH_PORT_DEAD upon going out-of-scope, no cleanup is performed. + * the variable to be wrapped in a mach send right object and passed to + * {@link mach_right_send_release} when it goes out of scope. Applying this + * attribute to variables that do not reference a valid Mach port send right or + * MACH_PORT_NULL or MACH_PORT_DEAD will result in undefined behavior. If the + * variable's value is MACH_PORT_NULL or MACH_PORT_DEAD upon going out-of-scope, + * no cleanup is performed. */ #define __os_release_mach_send \ __attribute__((cleanup(__os_cleanup_release_mach_send))) @@ -158,14 +160,13 @@ static inline void __os_cleanup_release_mach_send(mach_port_t *__p) { mach_port_t p = *__p; - kern_return_t kr = KERN_FAILURE; + mach_right_send_t ms = mach_right_send(p); if (!MACH_PORT_VALID(p)) { return; } - kr = mach_port_deallocate(mach_task_self(), p); - os_assert_zero(kr); + mach_right_send_release(ms); } /*! @@ -192,7 +193,12 @@ __os_cleanup_errno(int *__e) * upon going out-of-scope, no cleanup is performed. * * This attribute may be applied to dispatch and XPC objects. + * + * When compiling with ARC, this attribute does nothing. */ +#if __has_feature(objc_arc) +#define __os_release +#else #define __os_release __attribute__((cleanup(__os_cleanup_os_release))) static inline void __os_cleanup_os_release(void *__p) @@ -204,6 +210,7 @@ __os_cleanup_os_release(void *__p) } os_release(o); } +#endif #if __COREFOUNDATION__ /*! @@ -227,15 +234,53 @@ __os_cleanup_cfrelease(void *__p) } #endif // __COREFOUNDATION__ +/*! + * @define __os_unfair_unlock + * An attribute that may be applied to a variable's type. This attribute causes + * the variable to be passed to os_unfair_lock_unlock() when it goes out of + * scope. Applying this attribute to a variable which does not reference a valid + * os_unfair_lock_t object will result in undefined behavior. If the variable's + * value is NULL upon going out-of-scope, no cleanup is performed. + * + * This attribute is useful even when the target lock is taken conditionally via + * the following pattern: + * + * os_unfair_lock lock = OS_UNFAIR_LOCK_INIT; + * os_unfair_lock_t __os_unfair_unlock l2un = NULL; + * + * if (take_the_lock) { + * os_unfair_lock_lock(&lock); + * + * // Guarantee that 'lock' will be unconditionally released when the + * // scope containing 'l2un' ends. + * l2un = &lock; + * } + */ +#define __os_unfair_unlock __attribute__((cleanup(__os_cleanup_unfair_unlock))) +static inline void +__os_cleanup_unfair_unlock(void *__p) +{ + os_unfair_lock_t *tp = (os_unfair_lock_t *)__p; + os_unfair_lock_t ufl = *tp; + if (!ufl) { + return; + } + os_unfair_lock_assert_owner(ufl); + os_unfair_lock_unlock(ufl); +} + #else // __has_attribute(cleanup) -#define __os_free __attribute__((__os_not_supported)) -#define __os_close __attribute__((__os_not_supported)) -#define __os_fclose __attribute__((__os_not_supported)) -#define __os_close_mach_recv __attribute__((__os_not_supported)) -#define __os_release_mach_send __attribute__((__os_not_supported)) -#define __os_preserve_errno __attribute__((__os_not_supported)) -#define __os_release __attribute__((__os_not_supported)) -#define __os_cfrelease __attribute__((__os_not_supported)) +#define __os_cleanup_unsupported \ + _Pragma("GCC error \"automatic cleanup not supported\"") +#define __os_free __os_cleanup_unsupported +#define __os_close __os_cleanup_unsupported +#define __os_fclose __os_cleanup_unsupported +#define __os_close_mach_recv __os_cleanup_unsupported +#define __os_release_mach_send __os_cleanup_unsupported +#define __os_preserve_errno __os_cleanup_unsupported +#define __os_release __os_cleanup_unsupported +#define __os_cfrelease __os_cleanup_unsupported +#define __os_unfair_unlock __os_cleanup_unsupported #endif // __has_attribute(cleanup) __END_DECLS; diff --git a/libdarwin/h/ctl.h b/libdarwin/h/ctl.h new file mode 100644 index 0000000..450f097 --- /dev/null +++ b/libdarwin/h/ctl.h @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2018 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@ + */ + +/*! + * @header + * Interfaces to implement subcommand-style command line utilities (e.g. + * launchctl(1)) and automatically generate usage output. The usage generated by + * these interfaces assumes a long option convention (cf. getopt_long(3)) and is + * loosely based on the docopt convention described at + * + * http://docopt.org + * + * The user may define each subcommand taken by the utility as: + * + * static const os_subcommand_t _foo_cmd = { + * .osc_version = OS_SUBCOMMAND_VERSION, + * .osc_flags = 0, + * .osc_name = "foo", + * .osc_desc = "does a foo", + * .osc_optstring = NULL, + * .osc_options = NULL, + * .osc_info = NULL, + * .osc_invoke = &_foo_invoke, + * }; + * OS_SUBCOMMAND_REGISTER(_foo_cmd); + * + * static const os_subcommand_t _bar_cmd = { + * .osc_version = OS_SUBCOMMAND_VERSION, + * .osc_flags = 0, + * .osc_name = "bar", + * .osc_desc = "bars a foo", + * .osc_optstring = "x:q", + * .osc_options = _bar_opts, + * .osc_info = &_bar_optinfo, + * .osc_invoke = &_bar_invoke, + * }; + * OS_SUBCOMMAND_REGISTER(_bar_cmd); + * }; + * + * Where the "bar" subcommand's option information is returned by the routine: + * + * static void + * _bar_optinfo(const os_subcommand_t *osc, + * os_subcommand_optarg_format_t format, const struct option *opt, + * os_subcommand_option_t *scopt) + * { + * switch (format) { + * case OS_SUBCOMMAND_OPTARG_USAGE: + * switch (opt->val) { + * case 'x': + * scopt->osco_flags |= OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL; + * scopt->osco_argdesc = "x-argument"; + * break; + * case 'q': + * scopt->osco_argdesc = "q-argument"; + * break; + * default: + * __builtin_unreachable(); + * } + * break; + * case OS_SUBCOMMAND_OPTARG_HUMAN: + * switch (opt->val) { + * case 'x': + * scopt->osco_flags |= OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL; + * scopt->osco_argdesc = "argument describing x"; + * break; + * case 'q': + * scopt->osco_argdesc = "Lorem ipsum dolor sit amet, consectetur " + * "adipiscing elit. Nullam a maximus lectus. Curabitur ornare " + * "convallis turpis, in porttitor augue tempus laoreet. Maecenas " + * "auctor mauris tortor, et tempor libero maximus id. Donec ac " + * "nunc et elit sagittis commodo. Donec tincidunt libero vehicula " + * "ex eleifend sagittis. Suspendisse consectetur cursus elit. " + * "Proin neque metus, commodo id rhoncus eu, cursus hendrerit ex. " + * "Etiam in fringilla nulla, vitae mollis eros."; + * break; + * default: + * __builtin_unreachable(); + * } + * break; + * } + * } + * + * When {@link os_subcommand_main} is called, the tool's "help" subcommand will + * display approximately the following: + * + * $ tool help + * usage: playground [...] | help [subcommand] + * + * subcommands: + * foo does a foo + * bar bars a foo + * + * $ tool help foo + * usage: tool foo + * + * $ tool help bar + * usage: tool bar [--xarg] --qarg[=q-argument] + * --xarg argument describing x + * --qarg[=q-argument] Lorem ipsum dolor sit amet, consectetur + * adipiscing elit. Nullam a maximus lectus. + * Curabitur ornare convallis turpis, in porttitor + * augue tempus laoreet. Maecenas auctor mauris + * tortor, et tempor libero maximus id. Donec ac + * nunc et elit sagittis commodo. Donec tincidunt + * libero vehicula ex eleifend sagittis. Suspendisse + * consectetur cursus elit. Proin neque metus, + * commodo id rhoncus eu, cursus hendrerit ex. Etiam + * in fringilla nulla, vitae mollis eros. + */ +#ifndef __DARWIN_CTL_H +#define __DARWIN_CTL_H + +#include +#include + +#if DARWIN_TAPI +#define LINKER_SET_ENTRY(_x, _y) +#else +#include +#endif + +#include +#include +#include + +__BEGIN_DECLS; + +/*! + * @define OS_SUBCOMMAND_REGISTER + * Registers a {@link os_subcommand_t} with the runtime. Subcommands may only be + * declared as part of the main executable image -- subcommands declared in + * dynamic libraries or bundles will not be recognized. + */ +#define OS_SUBCOMMAND_REGISTER(_subcommand) \ + LINKER_SET_ENTRY(__subcommands, _subcommand) + +/*! + * @typedef os_subcommand_t + * The formal type name for the _os_subcommand structure. + */ +DARWIN_API_AVAILABLE_20181020 +typedef struct _os_subcommand os_subcommand_t; + +/*! + * @const OS_SUBCOMMAND_OPTION_VERSION + * The maximum version of the {@link os_subcommand_option_t} structure supported + * by the implementation. + */ +#define OS_SUBCOMMAND_OPTION_VERSION ((os_struct_version_t)0) + +/*! + * @typedef os_subcommand_optarg_format_t + * A type describing a usage format for the argument taken by an option. + * + * @const OS_SUBCOMMAND_OPTION_USAGE + * The short-form name of the argument given to the option. For example, if the + * subcommand takes a "--file" option with a required argument, this might be + * "file-path" and will be displayed as + * + * --file= + * + * @const OS_SUBCOMMAND_OPTION_HUMAN + * The long-form description of the argument given to the option. Extending the + * above example, this might be "The path to a file to take as input. This path + * must be absolute; relative paths are not supported." and will be displayed as + * + * --file The path to a file to take as input. This path must be + * absolute; relative paths are not supported. + */ +DARWIN_API_AVAILABLE_20181020 +OS_CLOSED_ENUM(os_subcommand_optarg_format, uint64_t, + OS_SUBCOMMAND_OPTARG_USAGE, + OS_SUBCOMMAND_OPTARG_HUMAN, +); + +/*! + * @typedef os_subcommand_option_flags_t + * Flags describing an option for a subcommand. + * + * @const OS_SUBCOMMAND_OPTION_FLAG_INIT + * No flags set. This value is suitable for initialization purposes. + * + * @const OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL + * The option does not need to be present in the subcommand invocation. By + * default, options are considered required. + */ +DARWIN_API_AVAILABLE_20181020 +OS_CLOSED_ENUM(os_subcommand_option_flags, uint64_t, + OS_SUBCOMMAND_OPTION_FLAG_INIT = 0, + OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL = (1 << 0), +); + +/*! + * @typedef os_subcommand_option_t + * A structure describing human-readable information about a particular option + * taken by a subcommand. This structure is to be returned when the + * implementation queries about a command's options individually. This is done + * when the implementation is synthesizing a usage string. + * + * @field osco_version + * The version of the structure. Initialize to + * {@link OS_SUBCOMMAND_OPTION_VERSION}. + * + * @field osco_flags + * On return from a {@link os_subcommand_option_info_t} function, a set of flags + * describing information about the option. + * + * @field osco_argdesc + * On return from a {@link os_subcommand_option_info_t} function, this should + * point to a constant string describing the argument to the option. + */ +DARWIN_API_AVAILABLE_20181020 +typedef struct _os_subcommand_option { + const os_struct_version_t osco_version; + os_subcommand_option_flags_t osco_flags; + const char *osco_argdesc; +} os_subcommand_option_t; + +/*! + * @typedef os_subcommand_option_info_t + * A type describing a function which returns option information. + * + * @param osc + * The subcommand to which the option belongs. + * + * @param format + * The format of usage information required. + * + * @param opt + * A pointer to the option structure for which to retrieve information. + * + * @param scopt + * A pointer to a subcommand option structure to be populated with information + * pertaining to the option. When passed to the callee, this structure is zero- + * filled. + */ +DARWIN_API_AVAILABLE_20181020 +typedef void (*os_subcommand_option_info_t)( + const os_subcommand_t *osc, + os_subcommand_optarg_format_t format, + const struct option *opt, + os_subcommand_option_t *scopt); + +/*! + * @const OS_SUBCOMMAND_VERSION + * The maximum version of the {@link os_subcommand_t} structure supported by the + * implementation. + */ +#define OS_SUBCOMMAND_VERSION ((os_struct_version_t)0) + +/*! + * @enum os_subcommand_flags_t + * A type describing flags associated with a subcommand for a command line + * utility. + * + * @const OS_SUBCOMMAND_FLAG_INIT + * No flags set. This value is suitable for initialization purposes. + * + * @const OS_SUBCOMMAND_FLAG_REQUIRE_ROOT + * This subcommand requires the user to be root. If the user is not root, the + * {@link os_subcommand_dispatch} routine will return {@EX_PERM}. + * + * @const OS_SUBCOMMAND_FLAG_TTYONLY + * This subcommand may only be invoked via a terminal interface, i.e. it should + * not be invoked by scripts. Use this option to emphasize that a command's + * output is human-readably only and should not be parsed. + * + * @const OS_SUBCOMMAND_FLAG_HIDDEN + * This subcommand should not be displayed in the list of subcommands. + */ +DARWIN_API_AVAILABLE_20181020 +OS_CLOSED_OPTIONS(os_subcommand_flags, uint64_t, + OS_SUBCOMMAND_FLAG_INIT, + OS_SUBCOMMAND_FLAG_REQUIRE_ROOT = (1 << 0), + OS_SUBCOMMAND_FLAG_TTYONLY = (1 << 1), + OS_SUBCOMMAND_FLAG_HIDDEN = (1 << 2), +); + +/*! + * @typedef os_subcommand_invoke_t + * An type describing the invocation function for a subcommand. + * + * @param osc + * The descriptor for the command being invoked. + * + * @param argc + * The argument vector count. + * + * @param argv + * The argument vector. The first element of this array is the name of the + * subcommand. + * + * @result + * An exit code, preferably from sysexits(3). Note that exit codes should not + * intersect with POSIX error codes from errno.h (cf. intro(2)). + * + * @discussion + * You may exit directly from within the routine if you wish. + */ +DARWIN_API_AVAILABLE_20181020 +typedef int (*os_subcommand_invoke_t)( + const os_subcommand_t *osc, + int argc, + const char *argv[]); + +/*! + * @struct os_subcommand_t + * A type describing a subcommand for a command line tool. + * + * @field osc_version + * The version of the structure. Initialize to {@link OS_SUBCOMMAND_VERSION}. + * + * @field osc_flags + * The flags for the subcommand. + * + * @field osc_name + * The name of the subcommand. The second argument of user input will be matched + * against this name. + * + * @field osc_desc + * A brief description of the subcommand. This description will be displayed + * next to the subcommand when the user lists all subcommands. + * + * @field osc_optstring + * The option string associated with the subcommand. The implementation does not + * recognize this string directly; the intent of storing it here is to provide a + * convenient place to access the string for the implementation function. + * Combined with the {@link osc_options} field, this enables the following + * pattern: + * + * int ch = 0; + * while ((ch = getopt_long(argc, argv, cmd->osc_optstring, + * cmd->osc_options, NULL)) != -1) { + * switch (ch) { + * // process option + * } + * } + * + * This pattern keeps the option string and option structs co-located in code. + * + * @field osc_options + * A pointer to an array of option structures describing the long options + * recognized by the subcommand (cf. getopt_long(3)). + * + * @field osc_info + * A pointer to a function which returns information about the subcommand's + * individual options. + * + * @field osc_invoke + * The implementation for the subcommand. + */ +DARWIN_API_AVAILABLE_20181020 +struct _os_subcommand { + const os_struct_version_t osc_version; + const os_subcommand_flags_t osc_flags; + const char *const osc_name; + const char *const osc_desc; + const char *osc_optstring; + const struct option *osc_options; + const os_subcommand_option_info_t osc_info; + const os_subcommand_invoke_t osc_invoke; +}; + +/*! + * @function os_subcommand_main + * Dispatches the subcommand appropriate for the given arguments. All + * subcommands will be implicitly discovered by virtue of their delcarations + * with the OS_SUBCOMMAND_REGISTER attribute. + * + * @param argc + * The argument count supplied to main(). + * + * @param argv + * The argument vector supplied to main(). + * + * @result + * The exit status from the subcommand's invocation function or an exit status + * from the implementation indicating that the subcommand could not be + * dispatched. Exit codes that can be returned by the implementation are: + * + * [EX_USAGE] The subcommand was invoked with improper syntax. Usage + * has been printed to stderr. + * [EX_USAGE] The subcommand specified is not recognized. + * [EX_PERM] The command required root privileges, and the caller is + * not running as root. + * [EX_UNAVAILABLE] The command specified that it may only run within + * the context of a tty(3), and either stdin or stdout are + * not a tty(3). + * + * @discussion + * In general, the code returned by this routine should immediately be passed to + * exit(3). The reason this routine does not implicitly exit is to allow for the + * caller to process multiple subcommand invocations as a batch. + * + * The caller should not print anything after this routine has returned -- the + * expectation is that all relevant information has already been conveyed to the + * user either by the implementation or from one of the subcommand invocation + * routines. + * + * This routine implicitly implements a "help" subcommand. + */ +DARWIN_API_AVAILABLE_20181020 +OS_EXPORT OS_WARN_RESULT OS_NONNULL2 +int +os_subcommand_main(int argc, const char *argv[]); + +__END_DECLS; + +#endif // __DARWIN_CTL_H diff --git a/libdarwin/h/err.h b/libdarwin/h/err.h index f33730a..c5cd955 100644 --- a/libdarwin/h/err.h +++ b/libdarwin/h/err.h @@ -75,7 +75,7 @@ __BEGIN_DECLS; * error code using {@link darwin_sysexit} and pass it to exit(3). */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_NORETURN OS_NONNULL2 OS_FORMAT_PRINTF(2, 3) +OS_EXPORT OS_NORETURN OS_COLD OS_NONNULL2 OS_FORMAT_PRINTF(2, 3) void err_np(errno_t code, const char *fmt, ...); @@ -96,7 +96,7 @@ err_np(errno_t code, const char *fmt, ...); * The arguments corresponding to the format string. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_NORETURN OS_NONNULL3 OS_FORMAT_PRINTF(3, 4) +OS_EXPORT OS_NORETURN OS_COLD OS_NONNULL3 OS_FORMAT_PRINTF(3, 4) void errc_np(int eval, errno_t code, const char *fmt, ...); @@ -114,7 +114,7 @@ errc_np(int eval, errno_t code, const char *fmt, ...); * The arguments corresponding to the format string. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_NONNULL2 OS_FORMAT_PRINTF(2, 3) +OS_EXPORT OS_COLD OS_NONNULL2 OS_FORMAT_PRINTF(2, 3) void warn_np(errno_t code, const char *fmt, ...); @@ -136,7 +136,7 @@ warn_np(errno_t code, const char *fmt, ...); * error code using {@link darwin_sysexit} and pass it to exit(3). */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_NORETURN OS_NONNULL2 OS_NONNULL3 +OS_EXPORT OS_NORETURN OS_COLD OS_NONNULL2 OS_NONNULL3 void verr_np(errno_t code, const char *fmt, va_list ap); @@ -157,7 +157,7 @@ verr_np(errno_t code, const char *fmt, va_list ap); * The argument pointer corresponding to the format string. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_NORETURN OS_NONNULL3 OS_NONNULL4 +OS_EXPORT OS_NORETURN OS_COLD OS_NONNULL3 OS_NONNULL4 void verrc_np(int eval, errno_t code, const char *fmt, va_list ap); @@ -175,7 +175,7 @@ verrc_np(int eval, errno_t code, const char *fmt, va_list ap); * The arguments corresponding to the format string. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_NONNULL2 OS_NONNULL3 +OS_EXPORT OS_COLD OS_NONNULL2 OS_NONNULL3 void vwarn_np(errno_t code, const char *fmt, va_list ap); diff --git a/libdarwin/h/mach_utils.h b/libdarwin/h/mach_utils.h index 13ad410..45ea439 100644 --- a/libdarwin/h/mach_utils.h +++ b/libdarwin/h/mach_utils.h @@ -155,7 +155,7 @@ os_mach_msg_get_context_trailer(const mach_msg_header_t *hdr); * required. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 +OS_EXPORT OS_COLD OS_WARN_RESULT OS_MALLOC OS_NONNULL1 char * os_mach_msg_copy_description(const mach_msg_header_t *msg); @@ -176,7 +176,7 @@ os_mach_msg_copy_description(const mach_msg_header_t *msg); * required. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 +OS_EXPORT OS_COLD OS_WARN_RESULT OS_MALLOC OS_NONNULL1 char * os_mach_msg_trailer_copy_description(const mach_msg_trailer_t *tlr); @@ -196,7 +196,7 @@ os_mach_msg_trailer_copy_description(const mach_msg_trailer_t *tlr); * required. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_WARN_RESULT OS_MALLOC +OS_EXPORT OS_COLD OS_WARN_RESULT OS_MALLOC char * os_mach_port_copy_description(mach_port_t port); diff --git a/libdarwin/h/stdio.h b/libdarwin/h/stdio.h index 3042ce2..11e1c11 100644 --- a/libdarwin/h/stdio.h +++ b/libdarwin/h/stdio.h @@ -31,9 +31,91 @@ #include #include #include +#include +#include +#include + +// TAPI and the compiler don't agree about header search paths, so if TAPI found +// our header in the SDK, help it out. +#if DARWIN_TAPI && DARWIN_API_VERSION < 20180727 +#define DARWIN_API_AVAILABLE_20180727 +#endif __BEGIN_DECLS; +/*! + * @typedef os_fd_t + * A type alias for a file descriptor. + */ +typedef int os_fd_t; + +/*! + * @function os_fd_valid + * Returns whether the given integer is a valid file descriptor number. + * + * @param fd + * The integer to check. + * + * @result + * A Boolean indicating whether the integer is a valid file descriptor number, + * that is, greater than or equal to zero. + */ +DARWIN_API_AVAILABLE_20180727 +OS_ALWAYS_INLINE OS_WARN_RESULT +static inline bool +os_fd_valid(os_fd_t fd) +{ + return (fd >= STDIN_FILENO); +} + +/*! + * @function fcheck_np + * Checks the status of an fread(3) or fwrite(3) operation to a FILE. + * + * @param f + * The file on which the operation was performed. + * + * @param n + * The return value of the operation. + * + * @param expected + * The expected return value of the operation. + * + * @result + * One of the following integers: + * + * 0 The operation succeeded + * EOF The operation encountered the end of the FILE stream before it + * could complete + * 1 There was an error + */ +DARWIN_API_AVAILABLE_20180727 +OS_EXPORT OS_WARN_RESULT OS_NONNULL1 +int +fcheck_np(FILE *f, size_t n, size_t expected); + +/*! + * @function dup_np + * Variant of dup(2) that guarantees the dup(2) operation will either succeed or + * not return. + * + * @param fd + * The descriptor to dup(2). + * + * @result + * A new file descriptor number that is functionally equivalent to what the + * caller passed. + * + * @discussion + * The implementation will retry if the operation was interrupted by a signal. + * If the operation failed for any other reason, the implementation will + * terminate the caller. + */ +DARWIN_API_AVAILABLE_20180727 +OS_EXPORT OS_WARN_RESULT +os_fd_t +dup_np(os_fd_t fd); + /*! * @function zsnprintf_np * snprintf(3) variant which returns the numnber of bytes written less the null @@ -74,6 +156,124 @@ OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3 OS_FORMAT_PRINTF(3, 4) size_t zsnprintf_np(char *buff, size_t len, const char *fmt, ...); +/*! + * @function crfprintf_np + * fprintf(3) variant that appends a new line character to the output. + * + * @param f + * The file to which the output should be written. + * + * @param fmt + * The printf(3)-like format string. + * + * @param ... + * The arguments corresponding to the format string. + */ +DARWIN_API_AVAILABLE_20181020 +OS_EXPORT OS_NONNULL1 OS_NONNULL2 OS_FORMAT_PRINTF(2, 3) +void +crfprintf_np(FILE *f, const char *fmt, ...); + +/*! + * @function vcrfprintf_np + * vfprintf(3) variant that appends a new line character to the output. + * + * @param f + * The file to which the output should be written. + * + * @param fmt + * The printf(3)-like format string. + * + * @param ap + * The argument list corresponding to the format string. + */ +DARWIN_API_AVAILABLE_20181020 +OS_EXPORT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 +void +vcrfprintf_np(FILE *f, const char *fmt, va_list ap); + +/*! + * @function wfprintf_np + * fprintf(3) variant which wraps the output to the specified column width, + * inserting new lines as necessary. Output will be word-wrapped with a trivial + * algorithm. + * + * @param f + * The file to which the output should be written. + * + * @param initpad + * The number of spaces that should be inserted prior to the first line of + * output. If a negative value is given, the implementation will assume that an + * amount of spaces equal to the absolute value of the parameter has already + * been written, and therefore it will only use the parameter to compute line- + * wrapping information and not insert any additional spaces on the first line + * of output. + * + * @param pad + * The number of spaces that should be inserted prior to every line of output + * except the first line. + * + * @param width + * The maximum number of columns of each line of output. Pass zero to indicate + * that there is no maximum. + * + * @param fmt + * The printf(3)-like format string. + * + * @param ... + * The arguments corresponding to the format string. + * + * @discussion + * This routine will silently fail to print to the desired output stream if + * there was a failure to allocate heap memory. + */ +DARWIN_API_AVAILABLE_20181020 +OS_EXPORT OS_NONNULL1 OS_NONNULL5 OS_NONNULL6 +void +wfprintf_np(FILE *f, ssize_t initpad, size_t pad, size_t width, + const char *fmt, ...); + +/*! + * @function vwfprintf_np + * vfprintf(3) variant which wraps the output to the specified column width, + * inserting new lines as necessary. Output will be word-wrapped with a trivial + * algorithm. + * + * @param f + * The file to which the output should be written. + * + * @param initpad + * The number of spaces that should be inserted prior to the first line of + * output. If a negative value is given, the implementation will assume that an + * amount of spaces equal to the absolute value of the parameter has already + * been written, and therefore it will only use the parameter to compute line- + * wrapping information and not insert any additional spaces on the first line + * of output. + * + * @param pad + * The number of spaces that should be inserted prior to every line of output + * except the first line. + * + * @param width + * The maximum number of columns of each line of output. Pass zero to indicate + * that there is no maximum. + * + * @param fmt + * The printf(3)-like format string. + * + * @param ap + * The argument list corresponding to the format string. + * + * @discussion + * This routine will silently fail to print to the desired output stream if + * there was a failure to allocate heap memory. + */ +DARWIN_API_AVAILABLE_20181020 +OS_EXPORT OS_NONNULL1 OS_NONNULL5 OS_NONNULL6 +void +vwfprintf_np(FILE *f, ssize_t initpad, size_t pad, size_t width, + const char *fmt, va_list ap); + __END_DECLS; #endif // __DARWIN_STDIO_H diff --git a/libdarwin/h/stdlib.h b/libdarwin/h/stdlib.h index ed4d3ef..25d524e 100644 --- a/libdarwin/h/stdlib.h +++ b/libdarwin/h/stdlib.h @@ -47,11 +47,13 @@ #include #include #include +#include #include #include #include #include +#include __BEGIN_DECLS; @@ -129,6 +131,9 @@ _os_strdup_known(const char *str) return strdup(str); } +#define __os_requires_experimental_libtrace \ + _Pragma("GCC error \"requires OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE\"") + /*! * @function os_malloc * Wrapper around malloc(3) which guarantees that the allocation succeeds. @@ -144,6 +149,7 @@ _os_strdup_known(const char *str) * the size is not known at compile-time, the routine will retry until it is * successful. */ +#if defined(OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE) #define os_malloc(__size) ({ \ void *ptr = NULL; \ size_t _size = (__size); \ @@ -155,6 +161,9 @@ _os_strdup_known(const char *str) } \ (ptr); \ }) +#else +#define os_malloc(__size) __os_requires_experimental_libtrace +#endif /*! * @function os_calloc @@ -174,6 +183,7 @@ _os_strdup_known(const char *str) * the size is not known at compile-time, the routine will retry until it is * successful. */ +#if defined(OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE) #define os_calloc(__cnt, __size) ({ \ void *ptr = NULL; \ size_t _size = (__size); \ @@ -187,6 +197,9 @@ _os_strdup_known(const char *str) } \ (ptr); \ }) +#else +#define os_calloc(__size) __os_requires_experimental_libtrace +#endif /*! * @function os_strdup @@ -208,6 +221,7 @@ _os_strdup_known(const char *str) * stdlib.h header because its semantic changes are solely related to the manner * in which memory is allocated. */ +#if defined(OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE) #define os_strdup(__str) ({ \ char *ptr = NULL; \ const char *_str = (__str); \ @@ -219,6 +233,9 @@ _os_strdup_known(const char *str) } \ (ptr); \ }) +#else +#define os_strdup(__size) __os_requires_experimental_libtrace +#endif /*! * @function os_localtime_file @@ -241,7 +258,7 @@ _os_strdup_known(const char *str) DARWIN_API_AVAILABLE_20170407 OS_EXPORT void -os_localtime_file(char buff[32]); +os_localtime_file(char buff[static 32]); /*! * @function os_simple_hash @@ -259,7 +276,7 @@ os_localtime_file(char buff[32]); * @discussion * This routine is meant to be used as a simple way to obtain a value that can * be used to choose a bucket in a simple hash table. Do not attach security - * assumptions to the output of this routine. Do not assume thst the computed + * assumptions to the output of this routine. Do not assume that the computed * hash is stable between hosts, OS versions, or boot sessions. */ DARWIN_API_AVAILABLE_20170407 @@ -267,6 +284,32 @@ OS_EXPORT OS_NONNULL1 uint64_t os_simple_hash(const void *buff, size_t len); +/*! + * @function os_simple_hash_with_seed + * A seeded variant of os_simple_hash. + * + * @param buff + * A pointer to the buffer to hash. + * + * @param len + * The length of the buffer. + * + * @param seed + * The seed value for the hash. + * + * @result + * The hashed value of the input. + * + * @discussion + * Usually, hashing the same buffer with different seeds will produce + * different hash values. + * All the same considerations of {@link os_simple_hash} apply. + */ +DARWIN_API_AVAILABLE_20181020 +OS_EXPORT OS_NONNULL1 +uint64_t +os_simple_hash_with_seed(const void *buff, size_t len, uint64_t seed); + /*! * @function os_simple_hash_string * An implementation of a simple non-cryptographic hashing algorithm. @@ -280,7 +323,7 @@ os_simple_hash(const void *buff, size_t len); * @discussion * This routine is the moral equivalent of a call to * - * os_simple_hash(buff, strlen(buff)); + * os_simple_hash(buff, strlen(buff)); * * All the same considerations of {@link os_simple_hash} apply. */ @@ -289,6 +332,46 @@ OS_EXPORT OS_NONNULL1 uint64_t os_simple_hash_string(const char *string); +/*! + * @function os_simple_hash_string_with_seed + * A seeded variant of os_simple_hash_string. + * + * @param string + * A pointer to the null-terminated string to hash. + * + * @result + * The hashed value of the input. + * + * @discussion + * Usually, hashing the same string with different seeds will produce + * different hash values. + * All the same considerations of {@link os_simple_hash_string} apply. + */ +DARWIN_API_AVAILABLE_20181020 +OS_EXPORT OS_NONNULL1 +uint64_t +os_simple_hash_string_with_seed(const char *string, uint64_t seed); + +/*! + * @function realpath_np + * Obtains a fully-resolved representation of the path to the file represented + * by the given descriptor. + * + * @param fd + * The file descriptor whose path is to be obtained. + * + * @param buff + * The buffer in which to write the path. + * + * @result + * On success, zero is returned. Otherwise, the implementation may return any + * error that can be returned by fcntl(2). + */ +DARWIN_API_AVAILABLE_20180727 +OS_EXPORT OS_WARN_RESULT +errno_t +realpath_np(os_fd_t fd, char buff[static PATH_MAX]); + __END_DECLS; #endif // __DARWIN_STDLIB_H diff --git a/libdarwin/h/string.h b/libdarwin/h/string.h index 8d16ac1..23c0098 100644 --- a/libdarwin/h/string.h +++ b/libdarwin/h/string.h @@ -89,7 +89,7 @@ typedef os_flag_t os_flagset_t[OS_FLAGSET_COUNT]; * is given, this is equivalent to a call to strerror(3). */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_WARN_RESULT OS_PURE +OS_EXPORT OS_COLD OS_WARN_RESULT OS_PURE const char * strerror_np(int code); @@ -106,7 +106,7 @@ strerror_np(int code); * string "EPERM" is returned. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_WARN_RESULT OS_PURE +OS_EXPORT OS_COLD OS_WARN_RESULT OS_PURE const char * symerror_np(int code); @@ -124,7 +124,7 @@ symerror_np(int code); * exit code. */ DARWIN_API_AVAILABLE_20170407 -OS_EXPORT OS_WARN_RESULT OS_PURE +OS_EXPORT OS_COLD OS_WARN_RESULT OS_PURE const char * symexit_np(int code); diff --git a/libdarwin/internal.h b/libdarwin/internal.h index 12e64c7..a16d866 100644 --- a/libdarwin/internal.h +++ b/libdarwin/internal.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,7 @@ #include #include #include +#include #define OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE 1 #include @@ -77,10 +79,9 @@ #include #include -#define RDAR_12809455 1 - #include "h/bsd.h" #include "h/cleanup.h" +#include "h/ctl.h" #include "h/err.h" #include "h/errno.h" #include "h/mach_exception.h" @@ -90,12 +91,15 @@ #include "h/string.h" #if DARWIN_TAPI +#undef os_assert_mach +#undef os_assert_mach_port_status + // Duplicate declarations to make TAPI happy. This header is included in the // TAPI build as an extra public header. API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) OS_EXPORT OS_NONNULL1 void -os_assert_mach(const char *op, kern_return_t kr); +(os_assert_mach)(const char *op, kern_return_t kr); API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) OS_EXPORT diff --git a/libdarwin/mach.c b/libdarwin/mach.c index 08bf794..8a07d04 100644 --- a/libdarwin/mach.c +++ b/libdarwin/mach.c @@ -361,7 +361,7 @@ os_mach_port_copy_description(mach_port_t p) // libsystem_darwin. The long-term plan is to move assumes() and assert() // functionality into libdarwin anyway. void -os_assert_mach(const char *op, kern_return_t kr) +(os_assert_mach)(const char *op, kern_return_t kr) { kern_return_t real_kr = (kern_return_t)(kr & (~MACH_MSG_MASK)); kern_return_t extra = (kern_return_t)(kr & MACH_MSG_MASK); diff --git a/libdarwin/stdio.c b/libdarwin/stdio.c index 49bfd85..c1d1585 100644 --- a/libdarwin/stdio.c +++ b/libdarwin/stdio.c @@ -23,6 +23,49 @@ #include "internal.h" #pragma mark API +int +fcheck_np(FILE *f, size_t n, size_t expected) +{ + if (n == expected) { + return 0; + } + if (feof(f)) { + return EOF; + } + if (ferror(f)) { + return 1; + } + __builtin_unreachable(); +} + +os_fd_t +dup_np(os_fd_t fd) +{ + os_fd_t dfd = -1; + + while (true) { + dfd = dup(fd); + + if (os_fd_valid(dfd)) { + break; + } + + switch (errno) { + case EINTR: + break; + case EBADF: + os_crash("bad fd"); + case EMFILE: + case ENFILE: + os_crash("failed to dup fd"); + default: + os_crash("unhandled error: %s", symerror_np(errno)); + } + } + + return dfd; +} + size_t zsnprintf_np(char *buff, size_t len, const char *fmt, ...) { @@ -41,3 +84,136 @@ zsnprintf_np(char *buff, size_t len, const char *fmt, ...) return (size_t)np; } + +void +crfprintf_np(FILE *f, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vcrfprintf_np(f, fmt, ap); + va_end(ap); +} + +void +vcrfprintf_np(FILE *f, const char *fmt, va_list ap) +{ + vfprintf(f, fmt, ap); + fprintf(f, "\n"); +} + +void +wfprintf_np(FILE *f, ssize_t initpad, size_t pad, size_t width, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwfprintf_np(f, initpad, pad, width, fmt, ap); + va_end(ap); +} + +void +vwfprintf_np(FILE *f, ssize_t initpad, size_t pad, size_t width, + const char *fmt, va_list ap) +{ + char *__os_free string = NULL; + char *__os_free working = NULL; + char *__os_free init_padding = NULL; + char *__os_free padding = NULL; + const char *curline = NULL;; + size_t left = 0; + size_t initpad_labs = (size_t)labs(initpad); + int ret = -1; + + if (width && width <= pad) { + os_crash("width cannot be smaller than pad"); + } + if (width && (initpad > 0) && width <= initpad_labs) { + os_crash("width cannot be smaller than initpad"); + } + if (width && (initpad < 0) && width <= initpad_labs) { + os_crash("width cannot be smaller than negative initpad"); + } + + ret = vasprintf(&string, fmt, ap); + if (ret < 0 || !string) { + return; + } + + left = (size_t)ret; + curline = string; + + // The working buffer will always be large enough to handle any individual + // line. vasprintf(3) returns the number of characters printed not including + // the null terminator, so add space for that. + working = malloc(left + 1); + if (!working) { + return; + } + + init_padding = malloc(initpad_labs + 1); + if (!init_padding) { + return; + } + + if (initpad >= 0) { + memset(init_padding, ' ', initpad); + init_padding[initpad] = 0; + } else { + init_padding[0] = 0; + } + + padding = malloc(pad + 1); + if (!padding) { + return; + } + + memset(padding, ' ', pad); + padding[pad] = 0; + + do { + size_t which_pad = pad; + char *which_padding = padding; + bool findspace = true; + size_t n2consume = 0; + char *breakchar = NULL; + + if (curline == string) { + which_padding = init_padding; + which_pad = initpad_labs; + } + + if (width == 0) { + // Width is unconstrained so just consume the entire string and + // indent any new lines within. + n2consume = left; + findspace = false; + } else { + n2consume = width - which_pad; + if (n2consume >= left) { + n2consume = left; + findspace = false; + } + } + + strlcpy(working, curline, n2consume + 1); + breakchar = strchr(working, '\n'); + if (!breakchar && findspace) { + // No new line within our maximally-constrained width of characters, + // so search for a space instead. + breakchar = strrchr(working, ' '); + } + + if (breakchar) { + // Found something to break on, so nerf it and only consume the + // characters up until that break character. + *breakchar = 0; + n2consume = (size_t)(breakchar - working); + curline += n2consume + 1; + } + + fprintf(f, "%s%s\n", which_padding, working); + left -= n2consume; + } while (left); +} diff --git a/libdarwin/stdlib.c b/libdarwin/stdlib.c index d718a94..d5ba786 100644 --- a/libdarwin/stdlib.c +++ b/libdarwin/stdlib.c @@ -24,7 +24,7 @@ #pragma mark API void -os_localtime_file(char buff[32]) +os_localtime_file(char buff[static 32]) { struct timeval tv; struct tm curtime; @@ -42,9 +42,8 @@ os_localtime_file(char buff[32]) // MurmurHash2 was written by Austin Appleby, and is placed in the public // domain. The author hereby disclaims copyright to this source code. uint64_t -os_simple_hash(const void *buff, size_t len) +os_simple_hash_with_seed(const void *buff, size_t len, uint64_t seed) { - const uint64_t seed = 0; #ifdef __LP64__ // MurmurHash64A const uint64_t m = 0xc6a4a7935bd1e995; @@ -126,8 +125,36 @@ os_simple_hash(const void *buff, size_t len) } uint64_t -os_simple_hash_string(const char *string) +os_simple_hash(const void *buff, size_t len) +{ + return os_simple_hash_with_seed(buff, len, 0); +} + +uint64_t +os_simple_hash_string_with_seed(const char *string, uint64_t seed) { size_t len = strlen(string); - return os_simple_hash(string, len); + return os_simple_hash_with_seed(string, len, seed); +} + +uint64_t +os_simple_hash_string(const char *string) +{ + return os_simple_hash_string_with_seed(string, 0); +} + +errno_t +realpath_np(os_fd_t fd, char buff[static PATH_MAX]) +{ + errno_t error = -1; + int ret = -1; + + ret = fcntl(fd, F_GETPATH, buff); + if (ret) { + error = errno; + } else { + error = 0; + } + + return error; } diff --git a/libdarwin/variant.c b/libdarwin/variant.c index 745a0ce..6e02d63 100644 --- a/libdarwin/variant.c +++ b/libdarwin/variant.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -55,6 +56,11 @@ enum check_status { S_YES = 3 }; +typedef struct { + const char *variant; + bool (*function)(const char*); +} variant_check_mapping; + static bool status2bool(enum check_status status) { switch (status) { @@ -62,6 +68,7 @@ status2bool(enum check_status status) { return false; case S_YES: return true; + case S_UNKNOWN: default: os_crash("os_variant had unexpected status"); } @@ -89,6 +96,7 @@ status2bool(enum check_status status) { #else #define INTERNAL_DIAGS_PROFILE_PATH "/var/db/ConfigurationProfiles/Settings/com.apple.InternalDiagnostics.plist" #define FACTORY_CONTENT_PATH "/System/Library/CoreServices/AppleFactoryVariant.plist" +#define BASE_SYSTEM_CONTENT_PATH "/System/Library/BaseSystem" #endif #if !TARGET_OS_SIMULATOR @@ -163,11 +171,16 @@ static enum check_status can_has_debugger = S_UNKNOWN; #if TARGET_OS_IPHONE static enum check_status internal_release_type = S_UNKNOWN; static enum check_status factory_release_type = S_UNKNOWN; +static enum check_status darwin_release_type = S_UNKNOWN; +static enum check_status recovery_release_type = S_UNKNOWN; +static enum check_status development_kernel = S_UNKNOWN; #else // TARGET_OS_IPHONE static enum check_status internal_diags_profile = S_UNKNOWN; static enum check_status factory_content = S_UNKNOWN; +static enum check_status base_system_content = S_UNKNOWN; #endif // TARGET_OS_IPHONE #endif // !TARGET_OS_SIMULATOR +static enum check_status is_ephemeral = S_UNKNOWN; static bool disabled_status[VP_MAX] = {}; @@ -321,16 +334,18 @@ static bool _parse_system_version_plist(void) */ internal_release_type = S_NO; factory_release_type = S_NO; - } else if (strcmp(release_type, "Internal") == 0 || - strcmp(release_type, "Lite Internal") == 0) { - internal_release_type = S_YES; - factory_release_type = S_NO; + darwin_release_type = S_NO; + recovery_release_type = S_NO; } else if (strcmp(release_type, "NonUI") == 0) { - internal_release_type = S_YES; factory_release_type = S_YES; + internal_release_type = S_YES; + darwin_release_type = S_NO; + recovery_release_type = S_NO; } else { - internal_release_type = S_NO; factory_release_type = S_NO; + internal_release_type = (strstr(release_type, "Internal") != NULL) ? S_YES : S_NO; + darwin_release_type = (strstr(release_type, "Darwin") != NULL) ? S_YES : S_NO; + recovery_release_type = (strstr(release_type, "Recovery") != NULL) ? S_YES : S_NO; } xpc_release(system_version_plist); @@ -372,7 +387,37 @@ static bool _check_factory_release_type(void) #endif // TARGET_OS_SIMULATOR } -#else +static bool _check_darwin_release_type(void) +{ +#if TARGET_OS_SIMULATOR + return false; +#else // TARGET_OS_SIMULATOR + if (darwin_release_type == S_UNKNOWN) { + if (!_parse_system_version_plist()) { + darwin_release_type = S_NO; + } + } + + return status2bool(darwin_release_type); +#endif // TARGET_OS_SIMULATOR +} + +static bool _check_recovery_release_type(void) +{ +#if TARGET_OS_SIMULATOR + return false; +#else // TARGET_OS_SIMULATOR + if (recovery_release_type == S_UNKNOWN) { + if (!_parse_system_version_plist()) { + recovery_release_type = S_NO; + } + } + + return status2bool(recovery_release_type); +#endif // TARGET_OS_SIMULATOR +} + +#else // TARGET_OS_IPHONE static bool _check_internal_diags_profile(void) { @@ -389,13 +434,20 @@ static bool _check_internal_diags_profile(void) return status2bool(internal_diags_profile); } +static bool _check_base_system_content(void) +{ + if (base_system_content == S_UNKNOWN) { + const char * path = BASE_SYSTEM_CONTENT_PATH; + base_system_content = (access(path, F_OK) == 0) ? S_YES : S_NO; + } + return status2bool(base_system_content); +} + #endif +#if !TARGET_OS_SIMULATOR 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; @@ -409,8 +461,36 @@ static bool _check_can_has_debugger(void) #endif } return status2bool(can_has_debugger); -#endif // TARGET_OS_SIMULATOR } +#endif // !TARGET_OS_SIMULATOR + +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +static bool _check_development_kernel(void) +{ + if (development_kernel == S_UNKNOWN) { + /* + * Whitelist values from SUPPORTED_KERNEL_CONFIGS. + */ + char *osbuildconfig = NULL; + size_t osbuildconfig_sz = 0; + errno_t err = sysctlbyname_get_data_np("kern.osbuildconfig", (void **)&osbuildconfig, &osbuildconfig_sz); + if (err == 0) { + if (strcmp(osbuildconfig, "development") == 0 || + strcmp(osbuildconfig, "debug") == 0 || + strcmp(osbuildconfig, "profile") == 0 || + strcmp(osbuildconfig, "kasan") == 0) { + development_kernel = S_YES; + } + } + free(osbuildconfig); + + if (development_kernel == S_UNKNOWN) { + development_kernel = S_NO; + } + } + return status2bool(development_kernel); +} +#endif // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR // For unit tests #ifndef VARIANT_SKIP_EXPORTED @@ -465,7 +545,13 @@ os_variant_allows_internal_security_policies(const char * __unused subsystem) return false; } +#if TARGET_OS_SIMULATOR + return _check_internal_content(); +#elif TARGET_OS_IPHONE + return _check_can_has_debugger() || _check_development_kernel(); +#else return _check_can_has_debugger(); +#endif } bool @@ -478,6 +564,68 @@ os_variant_has_factory_content(const char * __unused subsystem) #endif } +bool +os_variant_is_darwinos(const char * __unused subsystem) +{ + +#if TARGET_OS_IPHONE + return _check_darwin_release_type(); +#else + return false; +#endif +} + +bool +os_variant_is_recovery(const char * __unused subsystem) +{ +#if TARGET_OS_IPHONE + return _check_recovery_release_type(); +#else + return _check_base_system_content(); +#endif +} + +bool +os_variant_uses_ephemeral_storage(const char * __unused subsystem) +{ + if (is_ephemeral == S_UNKNOWN) { + uint32_t buffer = 0; + size_t buffer_size = sizeof(buffer); + + sysctlbyname("hw.ephemeral_storage", (void *)&buffer, &buffer_size, NULL, 0); + + is_ephemeral = (buffer != 0) ? S_YES : S_NO; + } + + return status2bool(is_ephemeral); +} + +bool +os_variant_check(const char * __unused subsystem, const char *variant) +{ + static const variant_check_mapping map[] = { + {.variant = "HasInternalContent", .function = os_variant_has_internal_content}, + {.variant = "HasInternalDiagnostics", .function = os_variant_has_internal_diagnostics}, + {.variant = "HasInternalUI", .function = os_variant_has_internal_ui}, + {.variant = "AllowsInternalSecurityPolicies", .function = os_variant_allows_internal_security_policies}, + {.variant = "HasFactoryContent", .function = os_variant_has_factory_content}, + {.variant = "IsDarwinOS", .function = os_variant_is_darwinos}, + {.variant = "UsesEphemeralStorage", .function = os_variant_uses_ephemeral_storage}, + {.variant = "IsRecovery", .function = os_variant_is_recovery}, + {.variant = NULL, .function = NULL} + }; + variant_check_mapping *current = (variant_check_mapping *)map; + + while (current->variant) { + if (0 == strncasecmp(current->variant, variant, strlen(current->variant))) { + return current->function(""); + } + current ++; + } + + return false; +} + #endif // VARIANT_SKIP_EXPORTED #define STATUS_INITIAL_BITS 0x70000000F0000000ULL @@ -492,6 +640,11 @@ enum status_flags_positions { SFP_INTERNAL_DIAGS_PROFILE = 3, SFP_FACTORY_CONTENT = 4, SFP_FACTORY_RELEASE_TYPE = 5, + SFP_DARWINOS_RELEASE_TYPE = 6, + SFP_EPHEMERAL_VOLUME = 7, + SFP_RECOVERY_RELEASE_TYPE = 8, + SFP_BASE_SYSTEM_CONTENT = 9, + SFP_DEVELOPMENT_KERNEL = 10, }; #if !TARGET_OS_SIMULATOR @@ -509,6 +662,10 @@ static uint64_t _get_cached_check_status(void) if (can_has_debugger != S_UNKNOWN) res |= can_has_debugger << SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH; + (void)os_variant_uses_ephemeral_storage(""); + if (is_ephemeral != S_UNKNOWN) + res |= is_ephemeral << SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH; + #if TARGET_OS_IPHONE _check_internal_release_type(); if (internal_release_type != S_UNKNOWN) @@ -517,6 +674,18 @@ static uint64_t _get_cached_check_status(void) _check_factory_release_type(); if (factory_release_type != S_UNKNOWN) res |= factory_release_type << SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH; + + _check_darwin_release_type(); + if (darwin_release_type != S_UNKNOWN) + res |= darwin_release_type << SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH; + + _check_recovery_release_type(); + if (recovery_release_type != S_UNKNOWN) + res |= recovery_release_type << SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH; + + _check_development_kernel(); + if (development_kernel != S_UNKNOWN) + res |= development_kernel << SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH; #else _check_internal_diags_profile(); if (internal_diags_profile != S_UNKNOWN) @@ -525,6 +694,10 @@ static uint64_t _get_cached_check_status(void) _check_factory_content(); if (factory_content != S_UNKNOWN) res |= factory_content << SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH; + + _check_base_system_content(); + if (base_system_content != S_UNKNOWN) + res |= base_system_content << SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH; #endif _parse_disabled_status(NULL); @@ -547,18 +720,33 @@ static void _restore_cached_check_status(uint64_t status) 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 ((status >> (SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH)) & STATUS_SET) + is_ephemeral = (status >> (SFP_EPHEMERAL_VOLUME * 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; if ((status >> (SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET) factory_release_type = (status >> (SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK; + + if ((status >> (SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET) + darwin_release_type = (status >> (SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK; + + if ((status >> (SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET) + recovery_release_type = (status >> (SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK; + + if ((status >> (SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH)) & STATUS_SET) + development_kernel = (status >> (SFP_DEVELOPMENT_KERNEL * 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; if ((status >> (SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET) factory_content = (status >> (SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK; + + if ((status >> (SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET) + base_system_content = (status >> (SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK; #endif for (int i = 0; i < VP_MAX; i++) { diff --git a/locale/xlocale.3 b/locale/xlocale.3 index b83609d..f1a2640 100644 --- a/locale/xlocale.3 +++ b/locale/xlocale.3 @@ -35,6 +35,10 @@ LC_GLOBAL_LOCALE - A special .Vt locale_t value that corresponds to the global, process-wide locale. .It +LC_C_LOCALE - A special +.Vt locale_t +value that corresponds to the C, system locale. +.It MB_CUR_MAX - This macro is traditionally defined as an integer containing the value of the longest multi-byte string that a single-wide character in the global locale can translate into. diff --git a/locale/xlocale_private.h b/locale/xlocale_private.h index 94f8ecc..99bf7c3 100644 --- a/locale/xlocale_private.h +++ b/locale/xlocale_private.h @@ -170,7 +170,7 @@ struct _xlocale { (x) = &__global_locale; \ } -#define NORMALIZE_LOCALE(x) if ((x) == NULL) { \ +#define NORMALIZE_LOCALE(x) if ((x) == LC_C_LOCALE) { \ (x) = _c_locale; \ } else if ((x) == LC_GLOBAL_LOCALE) { \ (x) = &__global_locale; \ diff --git a/man/manpages.lst b/man/manpages.lst index 56b88c6..65ecdeb 100644 --- a/man/manpages.lst +++ b/man/manpages.lst @@ -304,6 +304,7 @@ time2posix.3 time2posix.3 posix2time.3 times.3 times.3 timezone.3 timezone.3 timingsafe_bcmp.3 timingsafe_bcmp.3 +timespec_get.3 timespec_get.3 tmpnam.3 tmpnam.3 tempnam.3 tmpfile.3 toascii.3 toascii.3 tolower.3 tolower.3 tolower_l.3 diff --git a/net/inet_ntop.c b/net/inet_ntop.c index 600ecfd..aa6ffe4 100644 --- a/net/inet_ntop.c +++ b/net/inet_ntop.c @@ -20,24 +20,34 @@ * * @APPLE_LICENSE_HEADER_END@ */ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 -#include #include -#include +#include +#include +#include #include +#include #include -#include #include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wcomma" -#pragma clang diagnostic ignored "-Wint-conversion" +#include #define MAX_V4_ADDR_LEN 16 -#define MAX_V6_ADDR_LEN 64 - -static const char *hexchars = "0123456789abcdef"; const char * inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size); const char * inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size); @@ -45,158 +55,115 @@ const char * inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size); const char * inet_ntop(int af, const void *addr, char *buf, socklen_t len) { - if (af == AF_INET6) return inet_ntop6(addr, buf, len); - if (af == AF_INET) return inet_ntop4(addr, buf, len); + if (addr && af == AF_INET6) return inet_ntop6(addr, buf, len); + if (addr && af == AF_INET) return inet_ntop4(addr, buf, len); errno = EAFNOSUPPORT; return NULL; } +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ const char * inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size) { - char hexa[8][5], tmp[MAX_V6_ADDR_LEN]; - int zr[8]; - socklen_t len; - int32_t i, j, k, skip; - uint8_t x8, hx8; - uint16_t x16; - struct in_addr a4; - - if (addr == NULL) - { - errno = EAFNOSUPPORT; - return NULL; - } - - if (dst == NULL) - { - errno = ENOSPC; - return NULL; - } - - memset(tmp, 0, MAX_V6_ADDR_LEN); - - /* check for mapped or compat addresses */ - i = IN6_IS_ADDR_V4MAPPED(addr); - j = IN6_IS_ADDR_V4COMPAT(addr); - if ((i != 0) || (j != 0)) - { - const char *prefix; - socklen_t prefix_len; - if (i != 0) { - prefix = "::ffff:"; - prefix_len = 7; + const u_char *src = addr->__u6_addr.__u6_addr8; + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) { + cur.base = i; + cur.len = 1; + } else { + cur.len++; + } } else { - prefix = "::"; - prefix_len = 2; - } - a4.s_addr = addr->__u6_addr.__u6_addr32[3]; - inet_ntop4(&a4, tmp, sizeof(tmp)); - len = strlen(tmp) + 1; - if (prefix_len + len > size) - { - errno = ENOSPC; - return NULL; - } - - memcpy(dst, prefix, prefix_len); - memcpy(dst + prefix_len, tmp, len); - return dst; - } - - k = 0; - for (i = 0; i < 16; i += 2) - { - j = 0; - skip = 1; - - memset(hexa[k], 0, 5); - - x8 = addr->__u6_addr.__u6_addr8[i]; - - hx8 = x8 >> 4; - if (hx8 != 0) - { - skip = 0; - hexa[k][j++] = hexchars[hx8]; - } - - hx8 = x8 & 0x0f; - if ((skip == 0) || ((skip == 1) && (hx8 != 0))) - { - skip = 0; - hexa[k][j++] = hexchars[hx8]; - } - - x8 = addr->__u6_addr.__u6_addr8[i + 1]; - - hx8 = x8 >> 4; - if ((skip == 0) || ((skip == 1) && (hx8 != 0))) - { - hexa[k][j++] = hexchars[hx8]; - } - - hx8 = x8 & 0x0f; - hexa[k][j++] = hexchars[hx8]; - - k++; - } - - /* find runs of zeros for :: convention */ - j = 0; - for (i = 7; i >= 0; i--) - { - zr[i] = j; - x16 = addr->__u6_addr.__u6_addr16[i]; - if (x16 == 0) j++; - else j = 0; - zr[i] = j; - } - - /* find longest run of zeros */ - k = -1; - j = 0; - for(i = 0; i < 8; i++) - { - if (zr[i] > j) - { - k = i; - j = zr[i]; + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } } } - - for(i = 0; i < 8; i++) - { - if (i != k) zr[i] = 0; + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; } - - len = 0; - for (i = 0; i < 8; i++) - { - if (zr[i] != 0) - { - /* check for leading zero */ - if (i == 0) tmp[len++] = ':'; - tmp[len++] = ':'; - i += (zr[i] - 1); + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; continue; } - for (j = 0; hexa[i][j] != '\0'; j++) tmp[len++] = hexa[i][j]; - if (i != 7) tmp[len++] = ':'; + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { + struct in_addr ipv4_addr; + memcpy(&ipv4_addr, src+12, sizeof(ipv4_addr)); + if (!inet_ntop4(&ipv4_addr, tp, (socklen_t)sizeof(tmp) - (socklen_t)(tp - tmp))) { + errno = ENOSPC; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += sprintf(tp, "%x", words[i]); } - - /* trailing NULL */ - len++; - - if (len > size) - { + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((socklen_t)(tp - tmp) > size) { errno = ENOSPC; - return NULL; + return (NULL); } - - memcpy(dst, tmp, len); - return dst; + strcpy(dst, tmp); + return (dst); } const char * @@ -204,16 +171,15 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) { char tmp[MAX_V4_ADDR_LEN], *p; const u_int8_t *ap = (u_int8_t *)&addr->s_addr; - int i, ql, len; + int i; + size_t ql, len; - if (addr == NULL) - { + if (addr == NULL) { errno = EAFNOSUPPORT; return NULL; } - if (dst == NULL) - { + if (dst == NULL) { errno = ENOSPC; return NULL; } @@ -225,8 +191,7 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) p = tmp; - for (i = 0; i < 4; i++, ap++) - { + for (i = 0; i < 4; i++, ap++) { snprintf(p, 4, "%d", *ap); ql = strlen(p); len += ql; @@ -234,8 +199,7 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) if (i < 3) *p++ = '.'; } - if (len > size) - { + if (len > size) { errno = ENOSPC; return NULL; } @@ -243,4 +207,3 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) memcpy(dst, tmp, len); return dst; } -#pragma clang diagnostic pop diff --git a/os/api.h b/os/api.h index 59b870e..d68f175 100644 --- a/os/api.h +++ b/os/api.h @@ -50,6 +50,7 @@ #define __DARWIN_API_H #include +#include /*! * @const DARWIN_API_VERSION @@ -70,9 +71,31 @@ * individual preprocessor macros in this header that declare new behavior as * required. */ -#define DARWIN_API_VERSION 20170407lu +#define DARWIN_API_VERSION 20181020u +#if !DARWIN_BUILDING_LIBSYSTEM_DARWIN #define DARWIN_API_AVAILABLE_20170407 \ API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) +#define DARWIN_API_AVAILABLE_20180727 \ + API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +#define DARWIN_API_AVAILABLE_20181020 \ + API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +#else +#define DARWIN_API_AVAILABLE_20170407 +#define DARWIN_API_AVAILABLE_20180727 +#define DARWIN_API_AVAILABLE_20181020 +#endif + +/*! + * @typedef os_struct_magic_t + * A type representing the magic number of a transparent structure. + */ +typedef uint32_t os_struct_magic_t; + +/*! + * @typedef os_struct_version_t + * A type representing the version of a transparent structure. + */ +typedef uint32_t os_struct_version_t; #endif // __DARWIN_API_H diff --git a/os/assumes.c b/os/assumes.c index 30fe420..3f711f7 100644 --- a/os/assumes.c +++ b/os/assumes.c @@ -22,43 +22,56 @@ */ #include -#include #include #include #include #include #include -#include #include #include #include #include +#include #include #include -#include #include <_simple.h> #include #include #include #include "os/assumes.h" + +#if !TARGET_OS_DRIVERKIT +#include #include #include #include #include - +#else +#define _os_debug_log_error_str(...) +// placeholder to disable usage of dlfcn.h +typedef struct dl_info { + void *dli_fbase; +} Dl_info; +#endif +#if __has_include() #include #define os_set_crash_message(arg) CRSetCrashLogMessage(arg) +#else +#define os_set_crash_message(arg) +#endif #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)) static bool _os_should_abort_on_assumes = false; +#if !TARGET_OS_DRIVERKIT static const char * _os_basename(const char *p) { return ((strrchr(p, '/') ? : p - 1) + 1); } +#endif static void _os_get_build(char *build, size_t sz) @@ -84,6 +97,7 @@ _os_get_build(char *build, size_t sz) #endif } +#if !TARGET_OS_DRIVERKIT static void _os_get_image_uuid(void *hdr, uuid_t uuid) { @@ -111,6 +125,7 @@ _os_get_image_uuid(void *hdr, uuid_t uuid) uuid_clear(uuid); } } +#endif static void _os_abort_on_assumes_once(void) @@ -161,6 +176,7 @@ _os_find_log_redirect_func(os_mach_header *hdr) { os_redirect_t result = NULL; +#if !TARGET_OS_DRIVERKIT char name[128]; unsigned long size = 0; uint8_t *data = getsectiondata(hdr, OS_ASSUMES_REDIRECT_SEG, OS_ASSUMES_REDIRECT_SECT, &size); @@ -175,6 +191,7 @@ _os_find_log_redirect_func(os_mach_header *hdr) struct _os_redirect_assumes_s *redirect = (struct _os_redirect_assumes_s *)data; result = redirect->redirect; } +#endif return result; } @@ -200,6 +217,7 @@ _os_construct_message(uint64_t code, _SIMPLE_STRING asl_message, Dl_info *info, uintptr_t offset = 0; uuid_string_t uuid_str; +#if !TARGET_OS_DRIVERKIT void *ret = __builtin_return_address(0); if (dladdr(ret, info)) { uuid_t uuid; @@ -210,6 +228,9 @@ _os_construct_message(uint64_t code, _SIMPLE_STRING asl_message, Dl_info *info, offset = ret - info->dli_fbase; } +#else + info->dli_fbase = NULL; +#endif char sig[64]; (void)snprintf(sig, sizeof(sig), "%s:%lu", uuid_str, offset); @@ -238,14 +259,17 @@ __attribute__((always_inline)) static inline void _os_crash_impl(const char *message) { os_set_crash_message(message); +#if !TARGET_OS_DRIVERKIT if (!_os_crash_callback) { _os_crash_callback = dlsym(RTLD_MAIN_ONLY, "os_crash_function"); } if (_os_crash_callback) { _os_crash_callback(message); } +#endif } +#if !TARGET_OS_DRIVERKIT __attribute__((always_inline)) static inline bool _os_crash_fmt_impl(os_log_pack_t pack, size_t pack_size) @@ -271,6 +295,7 @@ _os_crash_fmt_impl(os_log_pack_t pack, size_t pack_size) abort_with_payload(OS_REASON_LIBSYSTEM, OS_REASON_LIBSYSTEM_CODE_FAULT, pack, pack_size, composed, 0); } +#endif __attribute__((always_inline)) static inline void @@ -367,10 +392,12 @@ void _os_crash(const char *message) _os_crash_impl(message); } +#if !TARGET_OS_DRIVERKIT void _os_crash_fmt(os_log_pack_t pack, size_t pack_size) { _os_crash_fmt_impl(pack, pack_size); } +#endif void _os_assumes_log(uint64_t code) diff --git a/os/assumes.h b/os/assumes.h index c68e87e..ac76db5 100644 --- a/os/assumes.h +++ b/os/assumes.h @@ -96,6 +96,7 @@ __BEGIN_DECLS #define os_crash(...) \ __os_crash_invoke(__has_more_than_one_argument(__VA_ARGS__), __VA_ARGS__) +OS_COLD extern void _os_crash_fmt(os_log_pack_t, size_t); @@ -118,22 +119,15 @@ _os_crash_fmt(os_log_pack_t, size_t); * statically-sized buffer. */ API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) -OS_ALWAYS_INLINE +OS_ALWAYS_INLINE OS_COLD static inline void os_assert_sprintf(int ret, size_t buff_size) { - union { - size_t size; - int ret; - } myret = { - .ret = ret, - }; - if (ret < 0) { os_crash("error printing buffer: %s", strerror(errno)); } - if (myret.size > buff_size) { + if ((size_t)ret > buff_size) { os_crash("buffer too small: needed = %d, actual = %lu", ret, buff_size); } @@ -184,10 +178,15 @@ os_assert_malloc(const char *desc, const void *const p, size_t alloc_size) * section of the resulting crash log. */ API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) -OS_EXPORT OS_NONNULL1 +OS_EXPORT OS_NONNULL1 OS_COLD void os_assert_mach(const char *op, kern_return_t kr); +#define os_assert_mach(op, kr) ({ \ + kern_return_t __kr = (kr); \ + if (os_unlikely(__kr != KERN_SUCCESS)) os_assert_mach(op, kr); \ +}) + /*! * @function os_assert_mach_port_status * A routine to assert the status of a Mach port. @@ -371,7 +370,6 @@ os_set_crash_callback(os_crash_callback_t callback) { __OS_COMPILETIME_ASSERT__(e); \ } \ _os_assumes_log((uint64_t)(uintptr_t)_e); \ - _os_avoid_tail_call(); \ } \ _e; \ }) @@ -383,7 +381,6 @@ os_set_crash_callback(os_crash_callback_t callback) { __OS_COMPILETIME_ASSERT__(!(e)); \ } \ _os_assumes_log((uint64_t)(uintptr_t)_e); \ - _os_avoid_tail_call(); \ } \ _e; \ }) @@ -392,7 +389,6 @@ os_set_crash_callback(os_crash_callback_t callback) { __typeof__(e) _e = os_slowpath(e); \ if (_e == (__typeof__(e))-1) { \ _os_assumes_log((uint64_t)(uintptr_t)errno); \ - _os_avoid_tail_call(); \ } \ _e; \ }) @@ -443,7 +439,6 @@ typedef bool (*os_log_callout_t)(_SIMPLE_STRING asl_message, void *ctx, const ch __OS_COMPILETIME_ASSERT__(e); \ } \ _os_assumes_log_ctx(f, ctx, (uintptr_t)_e); \ - _os_avoid_tail_call(); \ } \ _e; \ }) @@ -455,7 +450,6 @@ typedef bool (*os_log_callout_t)(_SIMPLE_STRING asl_message, void *ctx, const ch __OS_COMPILETIME_ASSERT__(!(e)); \ } \ _os_assumes_log_ctx((f), (ctx), (uintptr_t)_e); \ - _os_avoid_tail_call(); \ } \ _e; \ }) @@ -464,7 +458,6 @@ typedef bool (*os_log_callout_t)(_SIMPLE_STRING asl_message, void *ctx, const ch __typeof__(e) _e = os_slowpath(e); \ if (_e == (__typeof__(e))-1) { \ _os_assumes_log_ctx((f), (ctx), (uintptr_t)errno); \ - _os_avoid_tail_call(); \ } \ _e; \ }) @@ -507,22 +500,27 @@ typedef bool (*os_log_callout_t)(_SIMPLE_STRING asl_message, void *ctx, const ch #pragma mark internal symbols __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0) +OS_COLD OS_NOT_TAIL_CALLED extern void _os_crash(const char *); __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0) +OS_COLD OS_NOT_TAIL_CALLED extern void _os_assumes_log(uint64_t code); __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0) +OS_COLD OS_NOT_TAIL_CALLED extern char * _os_assert_log(uint64_t code); __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0) +OS_COLD OS_NOT_TAIL_CALLED extern void _os_assumes_log_ctx(os_log_callout_t callout, void *ctx, uint64_t code); __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0) +OS_COLD OS_NOT_TAIL_CALLED extern char * _os_assert_log_ctx(os_log_callout_t callout, void *ctx, uint64_t code); diff --git a/os/debug_private.h b/os/debug_private.h index daedf82..c4b1ced 100644 --- a/os/debug_private.h +++ b/os/debug_private.h @@ -30,7 +30,7 @@ #include __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0) -OS_FORMAT_PRINTF(1, 2) +OS_FORMAT_PRINTF(1, 2) OS_COLD extern void _os_debug_log(const char *msg, ...); @@ -61,6 +61,7 @@ _os_debug_log(const char *msg, ...); */ #define os_debug_log_redirect(func) \ __attribute__((__used__)) \ + __attribute__((__cold__)) \ __attribute__((__visibility__("default"))) \ bool _os_debug_log_redirect_func(const char *msg) { \ return func(msg); \ @@ -71,6 +72,7 @@ _os_debug_log(const char *msg, ...); // str must be modifiable (non-const)! __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_6_0) +OS_COLD extern void _os_debug_log_error_str(char *str); diff --git a/os/linker_set.h b/os/linker_set.h new file mode 100644 index 0000000..2bf02a2 --- /dev/null +++ b/os/linker_set.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + * + * + * Copyright (c) 1999 John D. Polstra + * 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. + * + */ + +#ifndef _SYS_LINKER_SET_H_ +#define _SYS_LINKER_SET_H_ + +#include +#if !defined(KERNEL) || defined(__APPLE_API_PRIVATE) + +/* + * The following macros are used to declare global sets of objects, which + * are collected by the linker into a `linker set' as defined below. + * For Mach-O, this is done by constructing a separate segment inside the + * __DATA section for each set. The contents of this segment are an array + * of pointers to the objects in the set. + * + * Note that due to limitations of the Mach-O format, there cannot + * be more than 255 sections in a segment, so linker set usage should be + * conserved. Set names may not exceed 16 characters. + */ + +#ifdef KERNEL +# include +# include + +# define MACH_HEADER_TYPE kernel_mach_header_t +# define GETSECTIONDATA_VARIANT getsectdatafromheader +# define SECTDATA_SIZE_TYPE unsigned long +# define MH_EXECUTE_HEADER &_mh_execute_header +# define IMAGE_SLIDE_CORRECT 0 +#else +# include +# include +# include +# include + +# if __LP64__ +# define MACH_HEADER_TYPE struct mach_header_64 +# define GETSECTIONDATA_VARIANT getsectdatafromheader_64 +# define SECTDATA_SIZE_TYPE uint64_t +# define MH_EXECUTE_HEADER _NSGetMachExecuteHeader() +# else +# define MACH_HEADER_TYPE struct mach_header +# define GETSECTIONDATA_VARIANT getsectdatafromheader +# define SECTDATA_SIZE_TYPE uint32_t +# define MH_EXECUTE_HEADER _NSGetMachExecuteHeader() +# endif +#endif + + +/* + * Private macros, not to be used outside this header file. + * + * The objective of this macro stack is to produce the following output, + * given SET and SYM as arguments: + * + * void const * __set_SET_sym_SYM __attribute__((section("__DATA,SET"))) = & SYM + */ + +/* Wrap entries in a type that can be blacklisted from KASAN */ +struct linker_set_entry { + void *ptr; +} __attribute__((packed)); + +#ifdef __LS_VA_STRINGIFY__ +# undef __LS_VA_STRINGIFY__ +#endif +#ifdef __LS_VA_STRCONCAT__ +# undef __LS_VA_STRCONCAT__ +#endif +#define __LS_VA_STRINGIFY(_x ...) #_x +#define __LS_VA_STRCONCAT(_x, _y) __LS_VA_STRINGIFY(_x,_y) +#define __LINKER_MAKE_SET(_set, _sym) \ + /*__unused*/ /*static*/ const struct linker_set_entry /*const*/ __set_##_set##_sym_##_sym \ + __attribute__ ((section(__LS_VA_STRCONCAT(__DATA,_set)),used)) = { (void *)&_sym } +/* the line above is very fragile - if your compiler breaks linker sets, + * just play around with "static", "const", "used" etc. :-) */ + +/* + * Public macros. + */ +#define LINKER_SET_ENTRY(_set, _sym) __LINKER_MAKE_SET(_set, _sym) + +/* + * FreeBSD compatibility. + */ +#ifdef __APPLE_API_OBSOLETE +# define TEXT_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) +# define DATA_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) +# define BSS_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) +# define ABS_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) +# define SET_ENTRY(_set, _sym) __LINKER_MAKE_SET(_set, _sym) +#endif /* __APPLE_API_OBSOLETE */ + +/* + * Extended linker set API. + * + * Since linker sets are per-object-file, and we may have multiple + * object files, we need to be able to specify which object's set + * to scan. + * + * The set itself is a contiguous array of pointers to the objects + * within the set. + */ + +/* + * Public interface. + * + * void **LINKER_SET_OBJECT_BEGIN(_object, _set) + * Preferred interface to linker_set_object_begin(), takes set name unquoted. + * void **LINKER_SET_OBJECT_LIMIT(_object, _set) + * Preferred interface to linker_set_object_begin(), takes set name unquoted. + * LINKER_SET_OBJECT_FOREACH(_object, (set_member_type **)_pvar, _cast, _set) + * Iterates over the members of _set within _object. Since the set contains + * pointers to its elements, for a set of elements of type etyp, _pvar must + * be (etyp **). + * LINKER_SET_FOREACH((set_member_type **)_pvar, _cast, _set) + * + * Example of _cast: For the _pvar "struct sysctl_oid **oidpp", _cast would be + * "struct sysctl_oid **" + * + */ + +#define LINKER_SET_OBJECT_BEGIN(_object, _set) __linker_set_object_begin(_object, _set) +#define LINKER_SET_OBJECT_LIMIT(_object, _set) __linker_set_object_limit(_object, _set) + +#define LINKER_SET_OBJECT_FOREACH(_object, _pvar, _cast, _set) \ + for (_pvar = (_cast) LINKER_SET_OBJECT_BEGIN(_object, _set); \ + _pvar < (_cast) LINKER_SET_OBJECT_LIMIT(_object, _set); \ + _pvar++) + +#define LINKER_SET_OBJECT_ITEM(_object, _cast, _set, _i) \ + (((_cast)(LINKER_SET_OBJECT_BEGIN(_object, _set)))[_i]) + +#define LINKER_SET_FOREACH(_pvar, _cast, _set) \ + LINKER_SET_OBJECT_FOREACH((MACH_HEADER_TYPE *)MH_EXECUTE_HEADER, _pvar, _cast, _set) + +/* + * Implementation. + * + * void **__linker_set_object_begin(_header, _set) + * Returns a pointer to the first pointer in the linker set. + * void **__linker_set_object_limi(_header, _set) + * Returns an upper bound to the linker set (base + size). + */ + +static __inline intptr_t +__linker_get_slide(struct mach_header *_header) +{ +#ifndef KERNEL + /* + * Gross. + * + * We cannot get the image slide directly from the header, so we need to + * determine the image's index and ask for the slide of that index. + */ + uint32_t i = 0; + for (i = 0; i < _dyld_image_count(); i++) { + const struct mach_header *hdr = _dyld_get_image_header(i); + if (_header == hdr) { + return _dyld_get_image_vmaddr_slide(i); + } + } + return 0; +#else + return 0; +#endif +} + +static __inline void ** +__linker_set_object_begin(MACH_HEADER_TYPE *_header, const char *_set) +__attribute__((__const__)); +static __inline void ** +__linker_set_object_begin(MACH_HEADER_TYPE *_header, const char *_set) +{ + void *_set_begin; + SECTDATA_SIZE_TYPE _size; + + _set_begin = GETSECTIONDATA_VARIANT(_header, "__DATA", _set, &_size); + _set_begin += __linker_get_slide((struct mach_header *)_header); + return (void **) _set_begin; +} + +static __inline void ** +__linker_set_object_limit(MACH_HEADER_TYPE *_header, const char *_set) +__attribute__((__const__)); +static __inline void ** +__linker_set_object_limit(MACH_HEADER_TYPE *_header, const char *_set) +{ + void *_set_begin; + SECTDATA_SIZE_TYPE _size; + + _set_begin = GETSECTIONDATA_VARIANT(_header, "__DATA", _set, &_size); + _set_begin += __linker_get_slide((struct mach_header *)_header); + + return (void **) ((uintptr_t) _set_begin + _size); +} + +#endif /* !KERNEL || __APPLE_API_PRIVATE */ + +#endif /* _SYS_LINKER_SET_H_ */ diff --git a/os/variant_private.h b/os/variant_private.h index bcbcefc..5d6113e 100644 --- a/os/variant_private.h +++ b/os/variant_private.h @@ -32,16 +32,30 @@ * 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: + * device by creating on override file. On macOS, the path of this file + * is: * /var/db/os_variant_override - * On embedded platforms, this file is placed at: + * On embedded platforms, the path of the override file is: * /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. + * behaviors to disable. To disable all internal behaviors, empty the file. + * + * There is currently no support for configuring per-subsystem overrides. + * + * Examples: + * This will disable internal diagnostics and UI on macOS: + * sudo sh -c 'echo "diagnostics,ui" > /var/db/os_variant_override' + * This will disable internal UI on iOS (assuming logged in as root): + * echo "ui" > /usr/share/misc/os_variant_override + * This will disable all internal behaviors on macOS: + * sudo sh -c '/bin/echo -n > /var/db/os_variant_override' + * + * Note that the values returned by these APIs are cached in the kernel at + * system boot. A reboot will be required after changing the overrides + * before the new settings will take effect. * * Each of these functions takes a constant string argument for the requesting * subsystem. This should be a reverse-DNS string describing the subsystem @@ -102,7 +116,7 @@ os_variant_has_internal_diagnostics(const char *subsystem); * * 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. + * a manner similar to the MobileGestalt check for InternalBuild. * * @result * Returns true if this build has this property. False otherwise or upon error. @@ -155,11 +169,82 @@ os_variant_allows_internal_security_policies(const char *subsystem); * @result * Returns true if this build has this property. False otherwise or upon error. */ -API_AVAILABLE(macosx(10.14), ios(12.0), tvos(12.0), watchos(5.0)) +API_AVAILABLE(macosx(10.14.4), ios(12.2), tvos(12.2), watchos(5.2)) OS_EXPORT OS_WARN_RESULT bool os_variant_has_factory_content(const char *subsystem); +/*! + * @function os_variant_is_darwinos + * + * @abstract returns whether this system variant is a darwinOS variant + * + * @result + * Returns true if this variant is a darwinOS variant. + */ +API_AVAILABLE(macosx(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +OS_EXPORT OS_WARN_RESULT +bool +os_variant_is_darwinos(const char *subsystem); + +/*! + * @function os_variant_uses_ephemeral_storage + * + * @abstract returns whether the system is booted from an ephermeral volume + * + * @result + * Returns true if the system is booted with ephemeral storage for the data volume. + */ +API_AVAILABLE(macosx(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +OS_EXPORT OS_WARN_RESULT +bool +os_variant_uses_ephemeral_storage(const char *subsystem); + +/*! + * @function os_variant_is_recovery + * + * @abstract returns whether this system variant is the recovery OS. + * + * @description + * On macOS, this returns whether the running environment is the BaseSystem. + * This will be true in the installer and recovery environments. On embedded + * platforms, this returns whether this is the NeRD (Network Recovery on + * Device) OS. + * + * @result + * Returns true if this variant is a recoveryOS + */ +API_AVAILABLE(macosx(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +OS_EXPORT OS_WARN_RESULT +bool +os_variant_is_recovery(const char *subsystem); + +/*! + * @function os_variant_check + * + * @abstract returns whether the system is of the specified variant + * + * @description + * This check checks against below known variants. False is returned if the + * variant passed in is not in the list. + * + * HasInternalContent + * HasInternalDiagnostics + * HasInternalUI + * AllowsInternalSecurityPolicies + * HasFactoryContent + * IsDarwinOS + * UsesEphemeralStorage + * IsRecovery + * + * @result + * Returns true if the system is of the specified variant. + */ +API_AVAILABLE(macosx(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +OS_EXPORT OS_WARN_RESULT +bool +os_variant_check(const char *subsystem, const char *variant); + __END_DECLS #endif // __os_variant_H__ diff --git a/posix1e/acl_translate.c b/posix1e/acl_translate.c index 2d400f6..57cb01f 100644 --- a/posix1e/acl_translate.c +++ b/posix1e/acl_translate.c @@ -349,7 +349,7 @@ acl_from_text(const char *buf_p) */ field = strsep(&entry, " "); errno = 0; - if (!*field || strtol(field, NULL, 0) != 1) + if (field == NULL || !*field || strtol(field, NULL, 0) != 1) { error = EINVAL; goto exit; diff --git a/secure/chk_fail.c b/secure/chk_fail.c index db859a6..596ce44 100644 --- a/secure/chk_fail.c +++ b/secure/chk_fail.c @@ -21,104 +21,27 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include -#include -#include -#include +#include +#include #include - -#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 -#include -#include -#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); -} +uint32_t __chk_assert_no_overlap = 1; __attribute__ ((visibility ("hidden"))) __attribute__ ((noreturn)) void __chk_fail_overflow (void) { - __chk_fail("detected buffer overflow"); + os_crash("detected buffer overflow"); } __attribute__ ((visibility ("hidden"))) __attribute__ ((noreturn)) void __chk_fail_overlap (void) { - __chk_fail("detected source and destination buffer overlap"); + os_crash("detected source and destination buffer overlap"); } - __attribute__ ((visibility ("hidden"))) void __chk_overlap (const void *_a, size_t an, const void *_b, size_t bn) { diff --git a/secure/snprintf_chk.c b/secure/snprintf_chk.c index 3b982b1..a30a473 100644 --- a/secure/snprintf_chk.c +++ b/secure/snprintf_chk.c @@ -45,3 +45,22 @@ __snprintf_chk (char *dest, size_t len, int flags, size_t dstlen, return done; } + +int +__snprintf_object_size_chk (char *dest, size_t dstlen, size_t len, +const char *format, ...) +{ + va_list arg; + int done; + + if (__builtin_expect (dstlen < len, 0)) + __chk_fail_overflow (); + + va_start (arg, format); + + done = vsnprintf (dest, len, format, arg); + + va_end (arg); + + return done; +} diff --git a/secure/sprintf_chk.c b/secure/sprintf_chk.c index f16c83a..6163ce1 100644 --- a/secure/sprintf_chk.c +++ b/secure/sprintf_chk.c @@ -48,3 +48,25 @@ __sprintf_chk (char *dest, int flags, size_t dstlen, const char *format, ...) return done; } + +int +__sprintf_object_size_chk (char *dest, size_t dstlen, const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + + if (__builtin_expect (dstlen > (size_t) INT_MAX, 0)) + done = vsprintf (dest, format, arg); + else + { + done = vsnprintf (dest, dstlen, format, arg); + if (__builtin_expect(done >= 0 && (size_t) done >= dstlen, 0)) + __chk_fail_overflow (); + } + + va_end (arg); + + return done; +} diff --git a/stdio/FreeBSD/fclose.c b/stdio/FreeBSD/fclose.c index e38bbbf..5a6183c 100644 --- a/stdio/FreeBSD/fclose.c +++ b/stdio/FreeBSD/fclose.c @@ -60,7 +60,7 @@ fclose(FILE *fp) return (EOF); } FLOCKFILE(fp); - r = fp->_flags & __SWR ? __sflush(fp) : 0; + r = __sflush(fp); if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) r = EOF; if (fp->_flags & __SMBF) diff --git a/stdio/FreeBSD/fflush.3 b/stdio/FreeBSD/fflush.3 index e05b2ff..b4e9530 100644 --- a/stdio/FreeBSD/fflush.3 +++ b/stdio/FreeBSD/fflush.3 @@ -32,7 +32,7 @@ .\" @(#)fflush.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD: src/lib/libc/stdio/fflush.3,v 1.11 2007/01/09 00:28:06 imp Exp $ .\" -.Dd June 4, 1993 +.Dd August 1, 2019 .Dt FFLUSH 3 .Os .Sh NAME @@ -50,9 +50,13 @@ .Sh DESCRIPTION The function .Fn fflush -forces a write of all buffered data for the given output or update +synchronizes the state of the given .Fa stream -via the stream's underlying write function. +in light of buffered I/O. +For output or update streams it writes all buffered data via the stream's +underlying write function. +For input streams it seeks to the current file position indicator via the +stream's underlying seek function. The open status of the stream is unaffected. .Pp If the @@ -62,7 +66,7 @@ argument is .Fn fflush flushes .Em all -open output streams. +open streams. .Pp The function .Fn fpurge @@ -87,25 +91,28 @@ is set to indicate the error. The .Fa stream argument -is not an open stream, or, in the case of -.Fn fflush , -not a stream open for writing. +is not an open stream. .El .Pp The function .Fn fflush may also fail and set .Va errno -for any of the errors specified for the routine -.Xr write 2 . +for any of the errors specified for the routines +.Xr write 2 +and +.Xr lseek 2 . .Sh SEE ALSO .Xr write 2 , .Xr fclose 3 , .Xr fopen 3 , +.Xr lseek 2 , .Xr setbuf 3 .Sh STANDARDS The .Fn fflush function conforms to -.St -isoC . +.St -isoC +and +.St -susv3 . diff --git a/stdio/FreeBSD/fflush.c b/stdio/FreeBSD/fflush.c index 9866826..db6761d 100644 --- a/stdio/FreeBSD/fflush.c +++ b/stdio/FreeBSD/fflush.c @@ -53,34 +53,14 @@ static int sflush_locked(FILE *); int fflush(FILE *fp) { - int retval; + int retval = 0; - if (fp == NULL) + if (fp == NULL) { return (_fwalk(sflush_locked)); - FLOCKFILE(fp); + } - /* - * 11103146: Conformance change: - * --- Begin History --- - * There is disagreement about the correct behaviour of fflush() - * when passed a file which is not open for writing. According to - * the ISO C standard, the behaviour is undefined. - * Under linux, such an fflush returns success and has no effect; - * under Windows, such an fflush is documented as behaving instead - * as fpurge(). - * Given that applications may be written with the expectation of - * either of these two behaviours, the only safe (non-astonishing) - * option is to return EBADF and ask that applications be fixed. - * --- End History --- - * SUSv3 now requires that fflush() returns success on a read-only - * stream. In addition, the conformance tests will warn if a fflush - * on a read-only stream does not set the file descriptor's file offset - * to the real position. We won't be fixing the warning at this time. - */ - if ((fp->_flags & (__SWR | __SRW)) == 0) { - retval = 0; - } else - retval = __sflush(fp); + FLOCKFILE(fp); + retval = __sflush(fp); FUNLOCKFILE(fp); return (retval); } @@ -110,36 +90,77 @@ __sflush(FILE *fp) int n, t; t = fp->_flags; - if ((t & __SWR) == 0) - return (0); if ((p = fp->_bf._base) == NULL) return (0); - n = fp->_p - p; /* write this much */ - /* - * Set these immediately to avoid problems with longjmp and to allow - * exchange buffering (via setvbuf) in user write function. + * SUSv3 requires that fflush() on a seekable input stream updates the file + * position indicator with the underlying seek function. Use a dumb fseek + * for this (don't attempt to preserve the buffers). */ - fp->_p = p; - fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; - - for (; n > 0; n -= t, p += t) { - t = _swrite(fp, (char *)p, n); - if (t <= 0) { - /* 5340694: reset _p and _w on EAGAIN */ - if (t < 0 && errno == EAGAIN) { - if (p > fp->_p) { - /* some was written */ - memmove(fp->_p, p, n); - fp->_p += n; - if (!(fp->_flags & (__SLBF|__SNBF))) - fp->_w -= n; + if ((t & __SRD) != 0) { + if (fp->_seek == NULL) { + /* + * No way to seek this file -- just return "success." + */ + return (0); + } + + n = fp->_r; + + if (n > 0) { + /* + * See _fseeko's dumb path. + */ + if (_sseek(fp, (fpos_t)-n, SEEK_CUR) == -1) { + if (errno == ESPIPE) { + /* + * Ignore ESPIPE errors, since there's no way to put the bytes + * back into the pipe. + */ + return (0); + } + return (EOF); + } + + if (HASUB(fp)) { + FREEUB(fp); + } + fp->_p = fp->_bf._base; + fp->_r = 0; + fp->_flags &= ~__SEOF; + memset(&fp->_mbstate, 0, sizeof(mbstate_t)); + } + return (0); + } + + if ((t & __SWR) != 0) { + n = fp->_p - p; /* write this much */ + + /* + * Set these immediately to avoid problems with longjmp and to allow + * exchange buffering (via setvbuf) in user write function. + */ + fp->_p = p; + fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; + + for (; n > 0; n -= t, p += t) { + t = _swrite(fp, (char *)p, n); + if (t <= 0) { + /* 5340694: reset _p and _w on EAGAIN */ + if (t < 0 && errno == EAGAIN) { + if (p > fp->_p) { + /* some was written */ + memmove(fp->_p, p, n); + fp->_p += n; + if (!(fp->_flags & (__SLBF|__SNBF))) + fp->_w -= n; + } } + fp->_flags |= __SERR; + return (EOF); } - fp->_flags |= __SERR; - return (EOF); } } return (0); diff --git a/stdio/FreeBSD/makebuf.c b/stdio/FreeBSD/makebuf.c index e5ec5bd..a472776 100644 --- a/stdio/FreeBSD/makebuf.c +++ b/stdio/FreeBSD/makebuf.c @@ -144,7 +144,7 @@ __senvbuf(FILE *fp, size_t *bufsize, int *couldbetty) return flags; // No number found, this protects us from negative size values } - size = strtol_l(evp, &end, 10, NULL); // No locale + size = strtol_l(evp, &end, 10, LC_C_LOCALE); if (*end != '\0') { return flags; } diff --git a/stdio/FreeBSD/vfprintf.c b/stdio/FreeBSD/vfprintf.c index dd2bcfe..cf51045 100644 --- a/stdio/FreeBSD/vfprintf.c +++ b/stdio/FreeBSD/vfprintf.c @@ -33,7 +33,10 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wint-conversion" +#include +#if !TARGET_OS_DRIVERKIT #define OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE 1 +#endif #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; @@ -873,7 +876,11 @@ fp_common: static_format_checked = __printf_is_memory_read_only((void*)fmt0, strlen(fmt0)); } if (!static_format_checked) { +#if OS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE os_crash("%%n used in a non-immutable format string: %s", fmt0); +#else + os_crash("%%n used in a non-immutable format string"); +#endif } #endif // ALLOW_DYNAMIC_PERCENT_N diff --git a/stdlib/FreeBSD/abort.c b/stdlib/FreeBSD/abort.c index 8758cf8..bac55ad 100644 --- a/stdlib/FreeBSD/abort.c +++ b/stdlib/FreeBSD/abort.c @@ -48,11 +48,16 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/abort.c,v 1.11 2007/01/09 00:28:09 imp E #include "libc_private.h" +#if __has_include() #include +#else +#define CRGetCrashLogMessage() NULL +#define CRSetCrashLogMessage(...) +#endif #include "_simple.h" extern void (*__cleanup)(); -extern void __abort(void) __dead2; +extern void __abort(void) __cold __dead2; #define TIMEOUT 10000 /* 10 milliseconds */ @@ -78,6 +83,17 @@ abort() */ sigdelset(&act.sa_mask, SIGABRT); + /* + * Don't block SIGSEGV since we might trigger a segfault if the pthread + * struct is corrupt. The end user behavior is that the program will + * terminate with a SIGSEGV instead of a SIGABRT which is acceptable. If + * the user registers a SIGSEGV handler, then they are responsible for + * dealing with any corruption themselves and abort may not work. + * rdar://48853131 + */ + sigdelset(&act.sa_mask, SIGSEGV); + sigdelset(&act.sa_mask, SIGBUS); + /* abort() should call pthread_kill to deliver a signal to the aborting thread * This helps gdb focus on the thread calling abort() */ diff --git a/stdlib/FreeBSD/atexit.c b/stdlib/FreeBSD/atexit.c index 45b62eb..48ada4c 100644 --- a/stdlib/FreeBSD/atexit.c +++ b/stdlib/FreeBSD/atexit.c @@ -41,6 +41,7 @@ static char sccsid[] = "@(#)atexit.c 8.2 (Berkeley) 7/3/94"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.8 2007/01/09 00:28:09 imp Exp $"); +#include #include "namespace.h" #include @@ -49,7 +50,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.8 2007/01/09 00:28:09 imp E #include #include #include -#if defined(__DYNAMIC__) || defined (__BLOCKS__) +#if (defined(__DYNAMIC__) || defined (__BLOCKS__)) && !TARGET_OS_DRIVERKIT #include #endif /* defined(__DYNAMIC__) */ #include "atexit.h" @@ -62,8 +63,6 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/atexit.c,v 1.8 2007/01/09 00:28:09 imp E #include "libc_private.h" #include -#include - #define ATEXIT_FN_EMPTY 0 #define ATEXIT_FN_STD 1 #define ATEXIT_FN_CXA 2 @@ -154,7 +153,7 @@ atexit(void (*func)(void)) fn.fn_arg = NULL; fn.fn_dso = NULL; -#if defined(__DYNAMIC__) && !TARGET_OS_IPHONE +#if defined(__DYNAMIC__) && !TARGET_OS_IPHONE && !TARGET_OS_DRIVERKIT // struct dl_info info; if (dladdr(func, &info)) { diff --git a/stdlib/FreeBSD/realpath.c b/stdlib/FreeBSD/realpath.c index 3ce9d8b..15cf79e 100644 --- a/stdlib/FreeBSD/realpath.c +++ b/stdlib/FreeBSD/realpath.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/realpath.c,v 1.20 2003/05/28 08:23:01 fj #include #include "un-namespace.h" + struct attrs { u_int32_t len; attrreference_t name; @@ -105,6 +106,7 @@ realpath(const char *path, char inresolved[PATH_MAX]) return (NULL); } #endif /* __DARWIN_UNIX03 */ + /* * Extension to the standard; if inresolved == NULL, allocate memory */ diff --git a/stdtime/FreeBSD/asctime.c b/stdtime/FreeBSD/asctime.c index 89804ab..c96c408 100644 --- a/stdtime/FreeBSD/asctime.c +++ b/stdtime/FreeBSD/asctime.c @@ -10,6 +10,7 @@ */ #include +#include #ifndef lint #ifndef NOID static char elsieid[] __unused = "@(#)asctime.c 8.2"; @@ -105,7 +106,7 @@ asctime_r(const struct tm * __restrict timeptr, char * __restrict buf) ** Assume that strftime is unaffected by other out-of-range members ** (e.g., timeptr->tm_mday) when processing "%Y". */ - (void) strftime(year, sizeof year, "%Y", timeptr); + (void) strftime_l(year, sizeof(year), "%Y", timeptr, NULL); /* ** We avoid using snprintf since it's not available on all systems. */ diff --git a/stdtime/FreeBSD/strptime.c b/stdtime/FreeBSD/strptime.c index d237bdd..ab0731d 100644 --- a/stdtime/FreeBSD/strptime.c +++ b/stdtime/FreeBSD/strptime.c @@ -93,6 +93,18 @@ first_wday_of(int year) ((year % 100) / 4) + (isleap(year) ? 6 : 0) + 1) % 7); } +static inline bool is_plus(char c) { + return c == '+'; +} + +static inline bool is_minus(char c) { + return c == '-'; +} + +static inline bool is_zero(char c) { + return c == '0'; +} + static char * _strptime0(const char *buf, const char *fmt, struct tm *tm, int *convp, locale_t locale, int flags, int week_number, enum week_kind week_kind) { @@ -100,6 +112,7 @@ _strptime0(const char *buf, const char *fmt, struct tm *tm, int *convp, locale_t const char *ptr; int wday_offset; int i, len; + bool negative; int Ealternative, Oalternative; const struct lc_time_T *tptr = __get_current_time_locale(locale); static int start_of_month[2][13] = { @@ -109,6 +122,7 @@ _strptime0(const char *buf, const char *fmt, struct tm *tm, int *convp, locale_t ptr = fmt; while (*ptr != 0) { + int field_width = 0; c = *ptr++; if (c != '%') { @@ -125,6 +139,29 @@ _strptime0(const char *buf, const char *fmt, struct tm *tm, int *convp, locale_t Oalternative = 0; label: c = *ptr++; + if (is_zero(c)) { + // Leading '0' is to be ignored. + c = *ptr++; + } else if (is_plus(c)) { + // POSIX sats leading '+' should be ignored, but FreeBSD interprets + // "%+" to mean locale-specific date format. Try to handle both by + // checking the next character. + char next = *ptr; + if (next != '\0' && next != '%' && !isspace_l(next, locale)) { + // Use POSIX interpretation. + c = *ptr++; + } + } + + if (isdigit_l(c, locale)) { + // Field width + field_width = c - '0'; + while (*ptr != '\0' && isdigit_l(*ptr, locale)) { + field_width *= 10; + field_width += *ptr++ - '0'; + } + c = *ptr++; + } switch (c) { case '%': if (*buf++ != '%') @@ -139,19 +176,30 @@ label: break; case 'C': - if (!isdigit_l((unsigned char)*buf, locale)) + if (!isdigit_l((unsigned char)*buf, locale) && !is_plus(*buf) && !is_minus(*buf)) return (NULL); /* XXX This will break for 3-digit centuries. */ - len = 2; + negative = false; + len = field_width ? field_width : 2; + if (is_plus(*buf)) { + len--; + buf++; + } else if (is_minus(*buf)) { + len--; + negative = true; + buf++; + } for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } - if (i < 19) - return (NULL); + + if (negative) { + i = -i; + } if (flags & FLAG_YEAR_IN_CENTURY) { tm->tm_year = i * 100 + (tm->tm_year % 100) - TM_YEAR_BASE; @@ -238,7 +286,7 @@ label: if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); - len = 3; + len = field_width ? field_width : 3; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++){ i *= 10; @@ -262,7 +310,7 @@ label: if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); - len = 2; + len = field_width ? field_width : 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++){ i *= 10; @@ -297,7 +345,7 @@ label: if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); - len = 2; + len = field_width ? field_width : 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; @@ -322,7 +370,7 @@ label: if (tm->tm_hour > 12) return (NULL); - len = strlen(tptr->am); + len = (int)strlen(tptr->am); if (strncasecmp_l(buf, tptr->am, len, locale) == 0) { if (tm->tm_hour == 12) tm->tm_hour = 0; @@ -330,7 +378,7 @@ label: break; } - len = strlen(tptr->pm); + len = (int)strlen(tptr->pm); if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) { if (tm->tm_hour != 12) tm->tm_hour += 12; @@ -343,11 +391,11 @@ label: case 'A': case 'a': for (i = 0; i < asizeof(tptr->weekday); i++) { - len = strlen(tptr->weekday[i]); + len = (int)strlen(tptr->weekday[i]); if (strncasecmp_l(buf, tptr->weekday[i], len, locale) == 0) break; - len = strlen(tptr->wday[i]); + len = (int)strlen(tptr->wday[i]); if (strncasecmp_l(buf, tptr->wday[i], len, locale) == 0) break; @@ -366,7 +414,7 @@ label: if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); - len = 2; + len = field_width ? field_width : 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; @@ -420,7 +468,7 @@ label: * digits if used incorrectly. */ /* Leading space is ok if date is single digit */ - len = 2; + len = field_width ? field_width : 2; if (isspace_l((unsigned char)buf[0], locale) && isdigit_l((unsigned char)buf[1], locale) && !isdigit_l((unsigned char)buf[2], locale)) { @@ -450,14 +498,14 @@ label: for (i = 0; i < asizeof(tptr->month); i++) { if (Oalternative) { if (c == 'B') { - len = strlen(tptr->alt_month[i]); + len = (int)strlen(tptr->alt_month[i]); if (strncasecmp_l(buf, tptr->alt_month[i], len, locale) == 0) break; } } else { - len = strlen(tptr->month[i]); + len = (int)strlen(tptr->month[i]); if (strncasecmp_l(buf, tptr->month[i], len, locale) == 0) break; @@ -469,7 +517,7 @@ label: */ if (i == asizeof(tptr->month) && !Oalternative) { for (i = 0; i < asizeof(tptr->month); i++) { - len = strlen(tptr->mon[i]); + len = (int)strlen(tptr->mon[i]); if (strncasecmp_l(buf, tptr->mon[i], len, locale) == 0) break; @@ -488,7 +536,7 @@ label: if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); - len = 2; + len = field_width ? field_width : 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; @@ -534,79 +582,34 @@ label: isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit_l((unsigned char)*buf, locale)) + if (!isdigit_l((unsigned char)*buf, locale) && !is_plus(*buf) + && !is_minus(*buf)) return (NULL); -#if __DARWIN_UNIX03 - if (c == 'Y') { - int savei = 0; - const char *savebuf = buf; - int64_t i64 = 0; - int overflow = 0; - - for (len = 0; *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { - i64 *= 10; - i64 += *buf - '0'; - if (++len <= 4) { - savei = i64; - savebuf = buf + 1; - } - if (i64 > INT_MAX) { - overflow++; - break; - } - } - /* - * Conformance requires %Y to be more then 4 - * digits. However, there are several cases - * where %Y is immediately followed by other - * digits values. So we do the conformance - * case first (as many digits as possible), - * and if we fail, we backup and try just 4 - * digits for %Y. - */ - if (len > 4 && !overflow) { - struct tm savetm = *tm; - int saveconv = *convp; - const char *saveptr = ptr; - char *ret; - - if (i64 < 1900) - return 0; - - tm->tm_year = i64 - 1900; - - if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) - while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale) && *ptr != '%') - ptr++; - ret = _strptime0(buf, ptr, tm, convp, locale, flags, week_number, week_kind); - if (ret) return ret; - /* Failed, so try 4-digit year */ - *tm = savetm; - *convp = saveconv; - ptr = saveptr; - } - buf = savebuf; - i = savei; - } else { - len = 2; -#else /* !__DARWIN_UNIX03 */ - len = (c == 'Y') ? 4 : 2; -#endif /* __DARWIN_UNIX03 */ - - for (i = 0; len && *buf != 0 && - isdigit_l((unsigned char)*buf, locale); buf++) { - i *= 10; - i += *buf - '0'; - len--; - } -#if __DARWIN_UNIX03 + len = field_width ? field_width : ((c == 'Y') ? 4 : 2); + negative = false; + if (is_plus(*buf)) { + len--; + buf++; + } else if (is_minus(*buf)) { + len--; + buf++; + negative = true; + } + for (i = 0; len && *buf != 0 && + isdigit_l((unsigned char)*buf, locale); buf++) { + i *= 10; + i += *buf - '0'; + len--; } -#endif /* __DARWIN_UNIX03 */ if (i < 0) return (NULL); + if (negative) { + i = -i; + } + if (c == 'Y'){ i -= TM_YEAR_BASE; } else if (c == 'y' && flags & FLAG_CENTURY) { @@ -634,7 +637,7 @@ label: isupper_l((unsigned char)*cp, locale); ++cp) { /*empty*/ } - len = cp - buf; + len = field_width ? field_width : cp - buf; if (len == 3 && strncmp(buf, "GMT", 3) == 0) { *convp = CONVERT_GMT; buf += len; diff --git a/string/FreeBSD/rpmatch.3 b/string/FreeBSD/rpmatch.3 new file mode 100644 index 0000000..8c77530 --- /dev/null +++ b/string/FreeBSD/rpmatch.3 @@ -0,0 +1,65 @@ +.\" +.\" Copyright (c) 2005 Tim J. Robbins +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd July 21, 2005 +.Dt RPMATCH 3 +.Os +.Sh NAME +.Nm rpmatch +.Nd "determine whether the response to a question is affirmative or negative" +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In stdlib.h +.Ft int +.Fn rpmatch "const char *response" +.Sh DESCRIPTION +The +.Fn rpmatch +function determines whether the +.Fa response +argument is an affirmative or negative response to a question +according to the current locale. +.Sh RETURN VALUES +The +.Fn rpmatch +functions returns: +.Bl -tag -width indent +.It 1 +The response is affirmative. +.It 0 +The response is negative. +.It \&-1 +The response is not recognized. +.El +.Sh SEE ALSO +.Xr nl_langinfo 3 , +.Xr setlocale 3 +.Sh HISTORY +The +.Fn rpmatch +function appeared in macOS 10.15. diff --git a/string/FreeBSD/rpmatch.c b/string/FreeBSD/rpmatch.c new file mode 100644 index 0000000..e4c366a --- /dev/null +++ b/string/FreeBSD/rpmatch.c @@ -0,0 +1,57 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2004-2005 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +int +rpmatch(const char *response) +{ + regex_t yes, no; + int ret; + + if (regcomp(&yes, nl_langinfo(YESEXPR), REG_EXTENDED|REG_NOSUB) != 0) + return (-1); + if (regcomp(&no, nl_langinfo(NOEXPR), REG_EXTENDED|REG_NOSUB) != 0) { + regfree(&yes); + return (-1); + } + if (regexec(&yes, response, 0, NULL, 0) == 0) + ret = 1; + else if (regexec(&no, response, 0, NULL, 0) == 0) + ret = 0; + else + ret = -1; + regfree(&yes); + regfree(&no); + return (ret); +} diff --git a/string/FreeBSD/timingsafe_bcmp.c b/string/FreeBSD/timingsafe_bcmp.c index 838c3c6..f47cf44 100644 --- a/string/FreeBSD/timingsafe_bcmp.c +++ b/string/FreeBSD/timingsafe_bcmp.c @@ -24,9 +24,12 @@ int timingsafe_bcmp(const void *b1, const void *b2, size_t n) { const unsigned char *p1 = b1, *p2 = b2; - int ret = 0; + unsigned char ret = 0; - for (; n > 0; n--) + for (; n > 0; n--) { ret |= *p1++ ^ *p2++; - return ret; + } + + /* map zero to zero and nonzero to one */ + return (ret + 0xff) >> 8; } diff --git a/sys/OSThermalNotification.c b/sys/OSThermalNotification.c index ef884f6..36b0042 100644 --- a/sys/OSThermalNotification.c +++ b/sys/OSThermalNotification.c @@ -21,9 +21,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include #include -#include #include @@ -31,6 +29,10 @@ const char * const kOSThermalNotificationPressureLevelName = OSThermalPressureLevelName; #if TARGET_OS_IPHONE + +#include +#include + #define OSThermalAlert "com.apple.system.thermalalert" #define OSThermalDecision "com.apple.system.thermaldecision" #define OSThermalStatusName "com.apple.system.thermalstatus" diff --git a/sys/OpenBSD/stack_protector.c b/sys/OpenBSD/stack_protector.c index 988d8ed..7ac7c7b 100644 --- a/sys/OpenBSD/stack_protector.c +++ b/sys/OpenBSD/stack_protector.c @@ -31,17 +31,20 @@ #include #include #include -#include #include #include #include +#if __has_include() #include +#else +#define CRSetCrashLogMessage(...) +#endif #include "libproc.h" #include "_simple.h" #define GUARD_MAX 8 long __stack_chk_guard[GUARD_MAX] = {0, 0, 0, 0, 0, 0, 0, 0}; -void __abort(void) __dead2; +void __abort(void) __cold __dead2; void __guard_setup(const char *apple[]) __attribute__ ((visibility ("hidden"))); void __stack_chk_fail(void); @@ -112,30 +115,18 @@ __guard_setup(const char *apple[]) ((unsigned char *)__stack_chk_guard)[3] = 255; } -#define STACKOVERFLOW "] stack overflow" +static const char *stackoverflow_msg = "stack buffer overflow"; void __stack_chk_fail() { - char n[16]; // bigger than will hold the digits in a pid_t - char *np; - int pid = getpid(); - char message[sizeof(n) + sizeof(STACKOVERFLOW)] = "["; - char prog[2*MAXCOMLEN+1] = {0}; + CRSetCrashLogMessage(stackoverflow_msg); - proc_name(pid, prog, 2*MAXCOMLEN); - prog[2*MAXCOMLEN] = 0; - np = n + sizeof(n); - *--np = 0; - while(pid > 0) { - *--np = (pid % 10) + '0'; - pid /= 10; - } - strlcat(message, np, sizeof(message)); - strlcat(message, STACKOVERFLOW, sizeof(message)); /* This may fail on a chroot jail... */ - _simple_asl_log_prog(ASL_LEVEL_CRIT, "user", message, prog); + char prog[2*MAXCOMLEN+1] = {0}; + proc_name(getpid(), prog, 2*MAXCOMLEN); + prog[2*MAXCOMLEN] = 0; + _simple_asl_log_prog(ASL_LEVEL_CRIT, "user", stackoverflow_msg, prog); - CRSetCrashLogMessage(message); __abort(); } diff --git a/sys/_libc_fork_child.c b/sys/_libc_fork_child.c index 596fab3..e6c2b57 100644 --- a/sys/_libc_fork_child.c +++ b/sys/_libc_fork_child.c @@ -24,7 +24,11 @@ * _libc_fork_child() is called from Libsystem's libSystem_atfork_child() */ #include +#if __has_include() #include +#else +#define CRSetCrashLogMessage(...) +#endif #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wstrict-prototypes" diff --git a/sys/_libc_init.c b/sys/_libc_init.c index 3f95640..54790ce 100644 --- a/sys/_libc_init.c +++ b/sys/_libc_init.c @@ -41,7 +41,6 @@ extern void _arc4_init(void); extern void __atexit_init(void); extern void __confstr_init(const struct _libc_functions *funcs); extern void _init_clock_port(void); -extern void __chk_init(void); extern void __xlocale_init(void); extern void __guard_setup(const char *apple[]); @@ -56,7 +55,6 @@ _libc_initializer(const struct _libc_functions *funcs, __confstr_init(funcs); __atexit_init(); _init_clock_port(); - __chk_init(); __xlocale_init(); __guard_setup(apple); } diff --git a/sys/settimeofday.c b/sys/settimeofday.c index 5dea59c..50cddb6 100644 --- a/sys/settimeofday.c +++ b/sys/settimeofday.c @@ -21,9 +21,14 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include +#include +#if !TARGET_OS_DRIVERKIT #include #include +#else +#define notify_post(...) +#endif +#include #include #include #include "_simple.h" diff --git a/sys/sigaction.c b/sys/sigaction.c index a81d20c..7b497d8 100644 --- a/sys/sigaction.c +++ b/sys/sigaction.c @@ -21,7 +21,11 @@ * @APPLE_LICENSE_HEADER_END@ */ +#if __has_include() #include +#else +#define CRSetCrashLogMessage(...) +#endif #include #include #include diff --git a/tests/Makefile b/tests/Makefile index 4938274..e6cbbed 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,8 @@ PROJECT := Libc TEST_DIR := tests/ +CUSTOM_TARGETS += osvariantutil + ifeq ($(DEVELOPER_DIR),) DEVELOPER_DIR := $(shell xcode-select -p) endif @@ -11,14 +13,15 @@ ifeq ($(PLATFORM),BridgeOS) EXCLUDED_SOURCES += locale.c endif +FRAMEWORK_CFLAGS := $(patsubst %,-iframework %,$(SYSTEM_FRAMEWORK_SEARCH_PATHS)) 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 + -Wno-c++98-compat -Wno-extra-semi -Wno-language-extension-token +OTHER_CFLAGS := -DDARWINTEST --std=gnu11 $(FRAMEWORK_CFLAGS) $(WARNING_CFLAGS) +DT_LDFLAGS += -ldarwintest_utils ASAN_DYLIB_PATH := /usr/local/lib/sanitizers/ nxheap: OTHER_CFLAGS += -Wno-cast-align @@ -37,5 +40,15 @@ EXCLUDED_SOURCES += qsort_perf.c endif os_variant: OTHER_CFLAGS += -DOS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE +osvariantutil: OTHER_CFLAGS += -Wno-gnu-statement-expression -Wno-covered-switch-default -DOS_CRASH_ENABLE_EXPERIMENTAL_LIBTRACE + include $(DEVELOPER_DIR)/AppleInternal/Makefiles/darwintest/Makefile.targets +OSVARIANTUTIL_INSTALLDIR = $(DSTROOT)/usr/local/bin + +install-osvariantutil: osvariantutil + mkdir -p $(OSVARIANTUTIL_INSTALLDIR) + cp $(SYMROOT)/osvariantutil $(OSVARIANTUTIL_INSTALLDIR)/ +ifeq ($(DWARF_DSYM_FILE_SHOULD_ACCOMPANY_PRODUCT),YES) + cp $(SYMROOT)/osvariantutil.dSYM $(OSVARIANTUTIL_INSTALLDIR)/ +endif diff --git a/tests/abort_tests.c b/tests/abort_tests.c new file mode 100644 index 0000000..f4306fa --- /dev/null +++ b/tests/abort_tests.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include + +static void * +body(void *corrupt) +{ + T_LOG("Helper thread running: %d", (bool)corrupt); + if (corrupt) { + // The pthread_t is stored at the top of the stack and could be + // corrupted because of a stack overflow. To make the test more + // reliable, we will manually smash the pthread struct directly. + pthread_t self = pthread_self(); + memset(self, 0x41, 4096); + } + // Expected behavior is that if a thread calls abort, the process should + // abort promptly. + abort(); + T_FAIL("Abort didn't?"); +} + +typedef enum { PTHREAD, WORKQUEUE } thread_type_t; + +static void +abort_test(thread_type_t type, int expected_signal) +{ + pid_t child = fork(); + bool corrupt = expected_signal == SIGSEGV; + + if (child == 0) { + T_LOG("Child running"); + switch (type) { + case PTHREAD: { + pthread_t tid; + T_QUIET; + T_ASSERT_POSIX_ZERO( + pthread_create(&tid, NULL, body, (void *)corrupt), NULL); + break; + } + case WORKQUEUE: { + dispatch_async_f(dispatch_get_global_queue( + DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), + (void *)corrupt, &body); + break; + } + } + sleep(5); + T_FAIL("Child didn't abort"); + exit(-1); + } else { + // Wait and check the exit status of the child + int status = 0; + pid_t pid = wait(&status); + T_QUIET; + T_ASSERT_EQ(pid, child, NULL); + T_QUIET; + T_EXPECT_FALSE(WIFEXITED(status), "WIFEXITED Status: %x", status); + T_QUIET; + T_EXPECT_TRUE(WIFSIGNALED(status), "WIFSIGNALED Status: %x", status); + T_QUIET; + T_EXPECT_FALSE(WIFSTOPPED(status), "WIFSTOPPED Status: %x", status); + // This test is successful if we trigger a SIGSEGV|SIGBUS or SIGABRT + // since both will promptly terminate the program + int signal = WTERMSIG(status); + if (signal == SIGBUS) { + // rdar://53269061 + T_LOG("Converting %d to SIGSEGV", signal); + signal = SIGSEGV; + } + T_EXPECT_EQ(signal, expected_signal, NULL); + } +} + +static void +signal_handler(int signo) +{ + // The user's signal handler should not be called during abort + T_FAIL("Unexpected signal: %d\n", signo); +} + +T_DECL(abort_pthread_corrupt_test, "Tests abort") +{ + abort_test(PTHREAD, SIGSEGV); +} + +T_DECL(abort_workqueue_corrupt_test, "Tests abort") +{ + abort_test(WORKQUEUE, SIGSEGV); +} + +T_DECL(abort_pthread_handler_test, "Tests abort") +{ + // rdar://52892057 + T_SKIP("Abort hangs if the user registers their own SIGSEGV handler"); + signal(SIGSEGV, signal_handler); + abort_test(PTHREAD, SIGSEGV); +} + +T_DECL(abort_workqueue_handler_test, "Tests abort") +{ + // rdar://52892057 + T_SKIP("Abort hangs if the user registers their own SIGSEGV handler"); + signal(SIGSEGV, signal_handler); + abort_test(WORKQUEUE, SIGSEGV); +} + +T_DECL(abort_pthread_test, "Tests abort") +{ + abort_test(PTHREAD, SIGABRT); +} + +T_DECL(abort_workqueue_test, "Tests abort") +{ + abort_test(WORKQUEUE, SIGABRT); +} diff --git a/tests/acl_tests.c b/tests/acl_tests.c new file mode 100644 index 0000000..f468730 --- /dev/null +++ b/tests/acl_tests.c @@ -0,0 +1,9 @@ +#include +#include +#include + +T_DECL(acl_bad_test, "Tests invalid acl") { + + acl_t acl = acl_from_text("!#acl"); + T_EXPECT_NULL(acl, "Invalid acl detected"); +} diff --git a/tests/backtrace.c b/tests/backtrace.c index da91023..87595fe 100644 --- a/tests/backtrace.c +++ b/tests/backtrace.c @@ -9,6 +9,7 @@ #define MAX_FRAMES 32 static const int expected_nframes = 20; +static const int skip_nframes = 5; static void *observed_bt[MAX_FRAMES] = {}; static int observed_nframes = 0; @@ -23,7 +24,7 @@ recurse_b(unsigned int frames); static int __attribute__((noinline,not_tail_called,disable_tail_calls)) recurse_a(unsigned int frames) { - if (frames == 1) { + if (frames == 0) { if (save_fp_at_nframes > 0) { observed_nframes = backtrace_from_fp(save_fp, observed_bt, MAX_FRAMES); @@ -41,7 +42,7 @@ recurse_a(unsigned int frames) static int __attribute__((noinline,not_tail_called,disable_tail_calls)) recurse_b(unsigned int frames) { - if (frames == 1) { + if (frames == 0) { if (save_fp_at_nframes > 0) { observed_nframes = backtrace_from_fp(save_fp, observed_bt, MAX_FRAMES); @@ -57,9 +58,9 @@ recurse_b(unsigned int frames) } static void __attribute__((noinline,not_tail_called,disable_tail_calls)) -setup_and_backtrace(unsigned int nframes, unsigned int skip_nframes) +setup_and_backtrace(unsigned int nframes, unsigned int skip) { - save_fp_at_nframes = skip_nframes ? skip_nframes - 1 : 0; + save_fp_at_nframes = skip ? skip - 1 : 0; recurse_a(nframes - 1); } @@ -72,7 +73,7 @@ check_for_setup(int i, struct dl_info *info) return info->dli_saddr == setup_fp; } -static void __attribute__((noinline)) +static void __attribute__((noinline,not_tail_called)) expect_backtrace(void) { void *recurse_a_fp = (void *)&recurse_a; @@ -83,8 +84,8 @@ expect_backtrace(void) T_EXPECT_EQ(expected_nframes, observed_nframes - observed_existing_nframes, - "number of frames traced matches"); - bool expect_a = true; + "number of frames traced matches %d", expected_nframes); + bool expect_a = !(skip_nframes % 2); bool found_setup = false; for (int i = 0; i < observed_nframes; i++) { @@ -96,8 +97,8 @@ expect_backtrace(void) void *expected_saddr = expect_a ? recurse_a_fp : recurse_b_fp; void *observed_saddr = info.dli_saddr; - T_EXPECT_GE(observed_saddr, expected_saddr, - "frame %d (%p) matches", i, observed_bt[i]); + T_EXPECT_EQ(observed_saddr, expected_saddr, + "frame %d (%p: %s) matches", i, observed_bt[i], info.dli_sname); expect_a = !expect_a; } @@ -113,7 +114,6 @@ T_DECL(backtrace, "ensure backtrace(3) gives the correct backtrace") T_DECL(backtrace_from_fp, "ensure backtrace_from_fp(3) starts from the correct frame") { - const int skip_nframes = 5; setup_and_backtrace(expected_nframes + skip_nframes, skip_nframes); expect_backtrace(); } @@ -149,3 +149,23 @@ T_DECL(backtrace_image_offsets, T_EXPECT_TRUE(found_setup, "should have found the setup frame"); } + +T_DECL(backtrace_symbols, "tests backtrace_symbols") +{ + setup_and_backtrace(expected_nframes, 0); + + char **symbols = backtrace_symbols(observed_bt, observed_nframes); + + bool found_setup = false; + + for (int i = 0; i < observed_nframes; i++) { + T_LOG("frame[%d]: %s", i, symbols[i]); + if (strstr(symbols[i], "setup_and_backtrace") != NULL) { + found_setup = true; + } + } + + T_EXPECT_TRUE(found_setup, "should have found the setup frame"); + + free(symbols); +} diff --git a/tests/darwin_bsd.c b/tests/darwin_bsd.c new file mode 100644 index 0000000..56efa8e --- /dev/null +++ b/tests/darwin_bsd.c @@ -0,0 +1,61 @@ +#include + +#include "../libdarwin/bsd.c" + +static struct test_case { + const char *args; + const char *argname; + const char *argvalue; +} test_cases[] = { + {"-x -a b=3 y=42", "-a", ""}, + {"-x -a b=3 y=42", "b", "3"}, + {"-x -a b=2 ba=3 y=42", "b", "2"}, + {"-x -a ba=3 b=2 y=42", "b", "2"}, + {"-x -a b=2 ba=3 y=42", "ba", "3"}, + {"-x -a ba=3 b=2 y=42", "ba", "3"}, + {"-x -ab -aa y=42", "-a", NULL}, + {"-x b=96 y=42", "bx", NULL}, + {"-x ab=96 y=42", "a", NULL}, +}; + +T_DECL(parse_boot_arg_value, "Parsing boot args") +{ + for (int i = 0; i < (int)(sizeof(test_cases)/sizeof(test_cases[0])); i++) { + struct test_case *test_case = &test_cases[i]; + T_LOG("\"%s\": Looking for \"%s\", expecting \"%s\"", + test_case->args, test_case->argname, test_case->argvalue); + + char *argbuff = strdup(test_case->args); + + char result[256] = "NOT_FOUND"; + bool found = _parse_boot_arg_value(argbuff, test_case->argname, + result,sizeof(result)); + + if (test_case->argvalue) { + T_EXPECT_EQ(found, true, "Should find argument"); + T_EXPECT_EQ_STR(result, test_case->argvalue, "Should find correct result"); + } else { + T_EXPECT_EQ(found, false, "Should not find argument"); + } + + free(argbuff); + } +} + +T_DECL(os_parse_boot_arg, "Getting boot args") +{ + int64_t value = 0; + T_EXPECT_EQ(os_parse_boot_arg_int("notarealthing", &value), false, NULL); + + T_MAYFAIL; + T_EXPECT_EQ(os_parse_boot_arg_int("debug", &value), true, NULL); + T_EXPECT_GT(value, 0LL, "non-zero debug= value"); + + char buf[64] = {}; + + T_EXPECT_EQ(os_parse_boot_arg_string("notarealthing", buf, sizeof(buf)), false, NULL); + + T_MAYFAIL; + T_EXPECT_EQ(os_parse_boot_arg_string("debug", buf, sizeof(buf)), true, NULL); + T_EXPECT_GT(strlen(buf), 0UL, "non-empty debug= value"); +} diff --git a/tests/fflush.c b/tests/fflush.c new file mode 100644 index 0000000..bd38edb --- /dev/null +++ b/tests/fflush.c @@ -0,0 +1,437 @@ +#include +#include +#include +#include +#include +#include + +static char tmpfile_template[] = "/tmp/libc_test_fflushXXXXX"; +#define BUFSZ 128 +static char wrbuf[BUFSZ] = ""; +static const size_t filesz = BUFSZ * 120; + +static void +cleanup_tmp_file(void) +{ + (void)unlink(tmpfile_template); +} + +static const char * +assert_empty_tmp_file(void) +{ + T_SETUPBEGIN; + + int tmpfd = mkstemp(tmpfile_template); + T_ASSERT_POSIX_SUCCESS(tmpfd, "created tmp file at %s", tmpfile_template); + T_ATEND(cleanup_tmp_file); + close(tmpfd); + + T_SETUPEND; + + return tmpfile_template; +} + +static const char * +assert_full_tmp_file(void) +{ + T_SETUPBEGIN; + + int tmpfd = mkstemp(tmpfile_template); + T_ASSERT_POSIX_SUCCESS(tmpfd, "created tmp file at %s", tmpfile_template); + T_ATEND(cleanup_tmp_file); + + /* + * Write a pattern of bytes into the file -- the lowercase alphabet, + * separated by newlines. + */ + for (size_t i = 0; i < BUFSZ; i++) { + wrbuf[i] = 'a' + (i % 27); + if (i % 27 == 26) { + wrbuf[i] = '\n'; + } + } + for (size_t i = 0; i < filesz; i++) { + ssize_t byteswr = 0; + do { + byteswr = write(tmpfd, wrbuf, BUFSZ); + } while (byteswr == -1 && errno == EAGAIN); + + T_QUIET; T_ASSERT_POSIX_SUCCESS(byteswr, "wrote %d bytes to tmp file", + BUFSZ); + T_QUIET; T_ASSERT_EQ(byteswr, (ssize_t)BUFSZ, + "wrote correct amount of bytes to tmp file"); + } + + close(tmpfd); + + T_SETUPEND; + + return tmpfile_template; +} + +/* + * Ensure that fflush on an input stream conforms to the SUSv3 definition, which + * requires synchronizing the FILE position with the underlying file descriptor. + */ +T_DECL(fflush_input, "fflush on a read-only FILE resets fd offset") +{ + const char *tmpfile = assert_full_tmp_file(); + + T_SETUPBEGIN; + + FILE *tmpf = fopen(tmpfile, "r"); + T_QUIET; T_WITH_ERRNO; + T_ASSERT_NOTNULL(tmpf, "opened tmp file for reading"); + + /* + * Move some way into the file. + */ + char buf[100] = ""; + size_t nread = fread(buf, sizeof(buf), 1, tmpf); + T_ASSERT_EQ(nread, (size_t)1, "read correct number of items from FILE"); + char last_read_char = buf[sizeof(buf) - 1]; + + off_t curoff = lseek(fileno(tmpf), 0, SEEK_CUR); + T_ASSERT_GT(curoff, (off_t)0, "file offset should be non-zero"); + + T_SETUPEND; + + /* + * fflush(3) to reset the fd back to the FILE offset. + */ + int ret = fflush(tmpf); + T_ASSERT_POSIX_SUCCESS(ret, "fflush on read-only FILE"); + + off_t flushoff = lseek(fileno(tmpf), 0, SEEK_CUR); + T_ASSERT_EQ(flushoff, (off_t)sizeof(buf), + "offset of file should be bytes read on FILE after fflush"); + + /* + * Make sure the FILE is reading the right thing -- the next character + * should be one letter after the last byte read, from the last call to + * fread(3). + */ + char c = '\0'; + nread = fread(&c, sizeof(c), 1, tmpf); + T_QUIET; + T_ASSERT_EQ(nread, (size_t)1, "read correct number of items from FILE"); + + /* + * The pattern in the file is the alphabet -- and this doesn't land on + * a newline. + */ + T_QUIET; + T_ASSERT_NE((flushoff) % 27, (off_t)0, + "previous offset shouldn't land on newline"); + T_QUIET; + T_ASSERT_NE((flushoff + 1) % 27, (off_t)0, + "current offset shouldn't land on newline"); + + T_ASSERT_EQ(c, last_read_char + 1, "read correct byte after fflush"); + + ret = fflush(tmpf); + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "fflush on read-only FILE"); + + flushoff = lseek(fileno(tmpf), 0, SEEK_CUR); + T_ASSERT_EQ(flushoff, (off_t)(sizeof(buf) + sizeof(c)), + "offset of file should be incremented after subsequent read"); + + /* + * Use ungetc(3) to induce the optimized ungetc behavior in the FILE. + */ + int ugret = ungetc(c, tmpf); + T_QUIET; T_ASSERT_NE(ugret, EOF, "ungetc after fflush"); + T_QUIET; T_ASSERT_EQ((char)ugret, c, "ungetc un-got the correct char"); + + ret = fflush(tmpf); + T_ASSERT_POSIX_SUCCESS(ret, "fflush after ungetc"); + flushoff = lseek(fileno(tmpf), 0, SEEK_CUR); + T_ASSERT_EQ(flushoff, (off_t)sizeof(buf), + "offset of file should be correct after ungetc and fflush"); + + nread = fread(&c, sizeof(c), 1, tmpf); + T_QUIET; + T_ASSERT_EQ(nread, (size_t)1, "read correct number of items from FILE"); + T_ASSERT_EQ(c, last_read_char + 1, + "read correct byte after ungetc and fflush"); +} + +/* + * Try to trick fclose into not reporting an ENOSPC error from the underlying + * descriptor in update mode. Previous versions of Libc only flushed the FILE + * if it was write-only. + */ + +#if TARGET_OS_OSX +/* + * Only macOS contains a version of hdiutil that can create disk images. + */ + +#define DMGFILE "/tmp/test_fclose_enospc.dmg" +#define VOLNAME "test_fclose_enospc" +static const char *small_file = "/Volumes/" VOLNAME "/test.txt"; + +static void +cleanup_dmg(void) +{ + char *hdiutil_detach_argv[] = { + "/usr/bin/hdiutil", "detach", "/Volumes/" VOLNAME, NULL, + }; + pid_t hdiutil_detach = -1; + int ret = dt_launch_tool(&hdiutil_detach, hdiutil_detach_argv, false, NULL, + NULL); + if (ret != -1) { + int status = 0; + (void)waitpid(hdiutil_detach, &status, 0); + } + (void)unlink(DMGFILE); +} + +T_DECL(fclose_enospc, "ensure ENOSPC is preserved on fclose") +{ + T_SETUPBEGIN; + + /* + * Ensure a disk is available that will fill up and start returning ENOSPC. + * + * system(3) would be easier... + */ + char *hdiutil_argv[] = { + "/usr/bin/hdiutil", "create", "-size", "5m", "-type", "UDIF", + "-volname", VOLNAME, "-nospotlight", "-fs", "HFS+", DMGFILE, "-attach", + NULL, + }; + pid_t hdiutil_create = -1; + int ret = dt_launch_tool(&hdiutil_create, hdiutil_argv, false, NULL, NULL); + T_ASSERT_POSIX_SUCCESS(ret, "created and attached 5MB DMG"); + int status = 0; + pid_t waited = waitpid(hdiutil_create, &status, 0); + T_QUIET; T_ASSERT_EQ(waited, hdiutil_create, + "should have waited for the process that was launched"); + T_QUIET; + T_ASSERT_TRUE(WIFEXITED(status), "hdiutil should have exited"); + T_QUIET; + T_ASSERT_EQ(WEXITSTATUS(status), 0, + "hdiutil should have exited successfully"); + + T_ATEND(cleanup_dmg); + + /* + * Open for updating, as previously only write-only files would be flushed + * on fclose. + */ + FILE *fp = fopen(small_file, "a+"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened file at %s for append-updating", small_file); + + char *buf = malloc(BUFSIZ); + T_QUIET; T_WITH_ERRNO; + T_ASSERT_NOTNULL(buf, "should allocate BUFSIZ bytes"); + + for (int i = 0; i < BUFSIZ; i++) { + buf[i] = (char)(i % 256); + } + + /* + * Fill up the disk -- induce ENOSPC. + */ + size_t wrsize = BUFSIZ; + for (int i = 0; i < 2; i++) { + for (;;) { + errno = 0; + if (write(fileno(fp), buf, wrsize) < 0) { + if (errno == ENOSPC) { + break; + } + T_WITH_ERRNO; T_ASSERT_FAIL("write(2) failed"); + } + } + wrsize = 1; + } + T_PASS("filled up the file until ENOSPC"); + free(buf); + + /* + * Make sure the FILE is at the end, so any writes it does hit ENOSPC. + */ + ret = fseek(fp, 0, SEEK_END); + T_ASSERT_POSIX_SUCCESS(ret, "fseek to the end of a complete file"); + + /* + * Try to push a character into the file; since this is buffered, it should + * succeed. + */ + ret = fputc('a', fp); + T_ASSERT_POSIX_SUCCESS(ret, + "fputc to put an additional character in the FILE"); + + T_SETUPEND; + + /* + * fclose should catch the ENOSPC error when it flushes the file, before it + * closes the underlying descriptor. + */ + errno = 0; + ret = fclose(fp); + if (ret != EOF) { + T_ASSERT_FAIL("fclose should fail when the FILE is full"); + } + if (errno != ENOSPC) { + T_WITH_ERRNO; T_ASSERT_FAIL("fclose should fail with ENOSPC"); + } + + T_PASS("fclose returned ENOSPC"); +} + +#endif // TARGET_OS_OSX + +/* + * Ensure no errors are returned when flushing a read-only, unseekable input + * stream. + */ +T_DECL(fflush_unseekable_input, + "ensure sanity when an unseekable input stream is flushed") +{ + T_SETUPBEGIN; + + /* + * Use a pipe for the unseekable streams. + */ + int pipes[2]; + int ret = pipe(pipes); + T_ASSERT_POSIX_SUCCESS(ret, "create a pipe"); + FILE *in = fdopen(pipes[0], "r"); + T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(in, + "open input stream to read end of pipe"); + FILE *out = fdopen(pipes[1], "w"); + T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(out, + "open output stream to write end of pipe"); + + /* + * Fill the pipe with some text (but not too much that the write would + * block!). + */ + fprintf(out, "this is a test and has some more text"); + ret = fflush(out); + T_ASSERT_POSIX_SUCCESS(ret, "flushed the output stream"); + + /* + * Protect stdio from delving too deep into the pipe. + */ + char inbuf[8] = {}; + setbuffer(in, inbuf, sizeof(inbuf)); + + /* + * Just read a teensy bit to get the FILE offset different from the + * descriptor "offset." + */ + char rdbuf[2] = {}; + size_t nitems = fread(rdbuf, sizeof(rdbuf), 1, in); + T_QUIET; T_ASSERT_GT(nitems, (size_t)0, + "read from the read end of the pipe"); + + T_SETUPEND; + + ret = fflush(in); + T_ASSERT_POSIX_SUCCESS(ret, + "should successfully flush unseekable input stream after reading"); +} + +/* + * Ensure that reading to the end of a file and then calling ftell() still + * causes EOF. + */ +T_DECL(ftell_feof, + "ensure ftell does not reset feof when actually at end of file") { + T_SETUPBEGIN; + FILE *fp = fopen("/System/Library/CoreServices/SystemVersion.plist", "rb"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened SystemVersion.plist"); + struct stat sb; + T_ASSERT_POSIX_SUCCESS(fstat(fileno(fp), &sb), "fstat SystemVersion.plist"); + void *buf = malloc(sb.st_size * 2); + T_ASSERT_NOTNULL(buf, "allocating buffer for size of SystemVersion.plist"); + T_SETUPEND; + + T_ASSERT_POSIX_SUCCESS(fseek(fp, 0, SEEK_SET), "seek to beginning"); + // fread can return short *or* zero, according to manpage + fread(buf, sb.st_size * 2, 1, fp); + T_ASSERT_EQ(ftell(fp), sb.st_size, "tfell() == file size"); + T_ASSERT_TRUE(feof(fp), "feof() reports end-of-file"); + free(buf); +} + +T_DECL(putc_flush, "ensure putc flushes to file on close") { + const char *fname = assert_empty_tmp_file(); + FILE *fp = fopen(fname, "w"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened temporary file read/write"); + T_WITH_ERRNO; + T_ASSERT_EQ(fwrite("testing", 1, 7, fp), 7, "write temp contents"); + (void)fclose(fp); + + fp = fopen(fname, "r+"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened temporary file read/write"); + + T_ASSERT_POSIX_SUCCESS(fseek(fp, -1, SEEK_END), "seek to end - 1"); + T_ASSERT_EQ(fgetc(fp), 'g', "fgetc should read 'g'"); + T_ASSERT_EQ(fgetc(fp), EOF, "fgetc should read EOF"); + T_ASSERT_EQ(ftell(fp), 7, "tfell should report position 7"); + + int ret = fputc('!', fp); + T_ASSERT_POSIX_SUCCESS(ret, + "fputc to put an additional character in the FILE"); + T_ASSERT_EQ(ftell(fp), 8, "tfell should report position 8"); + + T_QUIET; + T_ASSERT_POSIX_SUCCESS(fclose(fp), "close temp file"); + + fp = fopen(fname, "r"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened temporary file read/write"); + + char buf[9]; + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fgets(buf, sizeof(buf), fp), "read file data"); + T_ASSERT_EQ_STR(buf, "testing!", "read all the new data"); + + (void)fclose(fp); +} + +T_DECL(putc_writedrop, "ensure writes are flushed with a pending read buffer") { + const char *fname = assert_empty_tmp_file(); + FILE *fp = fopen(fname, "w"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened temporary file read/write"); + T_WITH_ERRNO; + T_ASSERT_EQ(fwrite("testing", 1, 7, fp), 7, "write temp contents"); + (void)fclose(fp); + + fp = fopen(fname, "r+"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened temporary file read/write"); + + T_ASSERT_POSIX_SUCCESS(fseek(fp, -1, SEEK_END), "seek to end - 1"); + + int ret = fputc('!', fp); + T_ASSERT_POSIX_SUCCESS(ret, + "fputc to put an additional character in the FILE"); + // flush the write buffer by reading a byte from the stream to put the + // FILE* into read mode + T_ASSERT_EQ(fgetc(fp), EOF, "fgetc should read EOF"); + + T_QUIET; + T_ASSERT_POSIX_SUCCESS(fclose(fp), "close temp file"); + + fp = fopen(fname, "r"); + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fp, "opened temporary file read/write"); + + char buf[9]; + T_WITH_ERRNO; + T_ASSERT_NOTNULL(fgets(buf, sizeof(buf), fp), "read file data"); + T_ASSERT_EQ_STR(buf, "testin!", "read all the new data"); + + (void)fclose(fp); +} diff --git a/tests/net.c b/tests/net.c index 758ee48..a8bcd5b 100644 --- a/tests/net.c +++ b/tests/net.c @@ -147,11 +147,6 @@ T_DECL(inet_ntop_resolve_zeroes, "Check for proper behavior when shortening zero 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); - // Single-zero tests will fail until change - // implemented. - if (i < 2) { - T_EXPECTFAIL; - } T_EXPECT_EQ_STR(str, expected_out_addr, NULL); } @@ -168,13 +163,42 @@ T_DECL(inet_ntop_resolve_zeroes, "Check for proper behavior when shortening zero T_QUIET; T_EXPECT_NOTNULL(str, "inet_ntop(AF_INET6) of %s", in_addr); T_QUIET; - // - 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"); } + +static void +conv(const char *addr) +{ + int ret; + void *retp; + + struct in6_addr addr6; + memset(&addr6, 0, sizeof addr6); + ret = inet_pton(AF_INET6, addr, &addr6); + T_ASSERT_EQ(ret, 1, "inet_pton"); + + T_LOG("%s: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", addr, + ((unsigned char *) &addr6)[0], ((unsigned char *) &addr6)[1], ((unsigned char *) &addr6)[2], ((unsigned char *) &addr6)[3], + ((unsigned char *) &addr6)[4], ((unsigned char *) &addr6)[5], ((unsigned char *) &addr6)[6], ((unsigned char *) &addr6)[7], + ((unsigned char *) &addr6)[8], ((unsigned char *) &addr6)[9], ((unsigned char *) &addr6)[10], ((unsigned char *) &addr6)[11], + ((unsigned char *) &addr6)[12], ((unsigned char *) &addr6)[13], ((unsigned char *) &addr6)[14], ((unsigned char *) &addr6)[15]); + + char buf6[INET6_ADDRSTRLEN]; + memset(buf6, 0, sizeof buf6); + retp = inet_ntop(AF_INET6, &addr6, buf6, (socklen_t) sizeof buf6); + T_ASSERT_NOTNULL(retp, "inet_ntop"); + + T_LOG("%s: %s\n", addr, buf6); + + T_EXPECT_EQ_STR(addr, buf6, NULL); +} + +T_DECL(inet_ntop_PR46867324, "Regression test for PR46867324") +{ + conv("2001:db8::1"); + conv("::192.168.1.2"); + conv("::ffff:10.11.12.13"); +} diff --git a/tests/netbsd_getcwd.c b/tests/netbsd_getcwd.c index 4c9580a..5c625b6 100644 --- a/tests/netbsd_getcwd.c +++ b/tests/netbsd_getcwd.c @@ -91,7 +91,9 @@ T_DECL(getcwd_fts, "A basic test of getcwd(3)") case FTS_DP: (void)memset(buf, 0, sizeof(buf)); + T_WITH_ERRNO; T_ASSERT_NOTNULL(getcwd(buf, sizeof(buf)), NULL); + T_LOG("ftse->fts_path: %s", ftse->fts_path); T_ASSERT_NOTNULL(strstr(ftse->fts_path, buf), NULL); break; diff --git a/tests/os_simple_hash.c b/tests/os_simple_hash.c index ae1bc40..946ba96 100644 --- a/tests/os_simple_hash.c +++ b/tests/os_simple_hash.c @@ -15,3 +15,26 @@ T_DECL(os_simple_hash, "sanity check of os_simple_hash", hashval = os_simple_hash(buf, sizeof(buf)); T_EXPECT_NE(hashval, 0ULL, "usually should get a non-0 hash value"); } + +T_DECL(os_simple_hash_seeds, "os_simple_hash different seeds give different hashes", + T_META_ALL_VALID_ARCHS(true)) +{ + const char * string = + "We made the buttons on the screen look so good you'll want to lick them."; + + uint64_t hashval0 = os_simple_hash_string_with_seed(string, 0x0); + T_EXPECT_NE(hashval0, 0ULL, "usually should get a non-0 hash value"); + uint64_t hashval1 = os_simple_hash_string_with_seed(string, 0x1); + T_EXPECT_NE(hashval1, 0ULL, "usually should get a non-0 hash value"); + uint64_t hashvalF = os_simple_hash_string_with_seed(string, 0xF); + T_EXPECT_NE(hashvalF, 0ULL, "usually should get a non-0 hash value"); + uint64_t hashvalFoo = os_simple_hash_string_with_seed(string, 0xF0000000); + T_EXPECT_NE(hashvalFoo, 0ULL, "usually should get a non-0 hash value"); + + T_EXPECT_NE(hashval0, hashval1, NULL); + T_EXPECT_NE(hashval0, hashvalF, NULL); + T_EXPECT_NE(hashval0, hashvalFoo, NULL); + T_EXPECT_NE(hashval1, hashvalF, NULL); + T_EXPECT_NE(hashval1, hashvalFoo, NULL); + T_EXPECT_NE(hashvalF, hashvalFoo, NULL); +} diff --git a/tests/os_variant.c b/tests/os_variant.c index 4890c51..70e820b 100644 --- a/tests/os_variant.c +++ b/tests/os_variant.c @@ -22,6 +22,12 @@ T_DECL(os_variant_basic, "Just calls all the APIs") T_MAYFAIL; T_EXPECT_FALSE(os_variant_has_factory_content("com.apple.Libc.tests"), NULL); + + T_MAYFAIL; + T_EXPECT_FALSE(os_variant_is_darwinos("com.apple.Libc.tests"), NULL); + + T_MAYFAIL; + T_EXPECT_FALSE(os_variant_uses_ephemeral_storage("com.apple.Libc.tests"), NULL); } #define VARIANT_SKIP_EXPORTED @@ -143,8 +149,9 @@ T_DECL(os_status_cache, "Checks saving and restoring of state") 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); + (S_NO << (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH)) | + (S_NO << (SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH)); + T_LOG("Restoring status without can_has_debugger and development_kernel: %llx", status); _restore_cached_check_status(status); T_EXPECT_FALSE(_check_can_has_debugger(), NULL); diff --git a/tests/osvariantutil.c b/tests/osvariantutil.c new file mode 100644 index 0000000..3d55240 --- /dev/null +++ b/tests/osvariantutil.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +#include "../libdarwin/variant.c" + +#define bool2str(b) (b ? "true" : "false") + +static void __dead2 +usage(void) +{ + printf("osvariantutil status\n"); + printf("osvariantutil parse \n"); + exit(1); +} + +int +main(int argc, char *argv[]) { + // Warm up the dispatch_once + _check_disabled(VP_CONTENT); + + if (argc == 2 && strcmp(argv[1], "status") == 0) { + uint64_t status = _get_cached_check_status(); + printf("Cached status: %llx\n", status); + } else if (argc == 3 && strcmp(argv[1], "parse") == 0) { + uint64_t status = strtoull(argv[2], NULL, 0); + if ((status & STATUS_INITIAL_BITS) != STATUS_INITIAL_BITS) { + printf("Invalid status: 0x%llx\n", status); + exit(1); + } + _restore_cached_check_status(status); + printf("Using status: %llx\n", status); + } else { + usage(); + } + + printf("\nOS Variants:\n"); + printf("\tos_variant_has_internal_content: %s\n", + bool2str(os_variant_has_internal_content("com.apple.osvariantutil"))); + printf("\tos_variant_has_internal_diagnostics: %s\n", + bool2str(os_variant_has_internal_diagnostics("com.apple.osvariantutil"))); + printf("\tos_variant_has_internal_ui: %s\n", + bool2str(os_variant_has_internal_ui("com.apple.osvariantutil"))); + printf("\tos_variant_allows_internal_security_properties: %s\n", + bool2str(os_variant_allows_internal_security_policies("com.apple.osvariantutil"))); + printf("\tos_variant_has_factory_content: %s\n", + bool2str(os_variant_has_factory_content("com.apple.osvariantutil"))); + printf("\tos_variant_is_darwinos: %s\n", + bool2str(os_variant_is_darwinos("com.apple.osvariantutil"))); + printf("\tos_variant_uses_ephemeral_storage: %s\n", + bool2str(os_variant_uses_ephemeral_storage("com.apple.osvariantutil"))); + printf("\tos_variant_is_recovery: %s\n", + bool2str(os_variant_is_recovery("com.apple.osvariantutil"))); + + printf("\nOS Variant Overrides:\n"); + printf("\tCONTENT: %s\n", bool2str(_check_disabled(VP_CONTENT))); + printf("\tDIAGNOSTICS: %s\n", bool2str(_check_disabled(VP_DIAGNOSTICS))); + printf("\tUI: %s\n", bool2str(_check_disabled(VP_UI))); + printf("\tSECURITY: %s\n", bool2str(_check_disabled(VP_SECURITY))); + + printf("\nOS Variant Inputs:\n"); +#if !TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + printf("\tInternal Content: %s\n", bool2str(_check_internal_content())); +#endif +#if TARGET_OS_IPHONE + printf("\tInternal Release Type: %s\n", bool2str(_check_internal_release_type())); + printf("\tFactory Release Type: %s\n", bool2str(_check_factory_release_type())); + printf("\tDarwin Release Type: %s\n", bool2str(_check_darwin_release_type())); + printf("\tRecovery Release Type: %s\n", bool2str(_check_recovery_release_type())); + printf("\tDevelopment Kernel: %s\n", bool2str(_check_development_kernel())); +#else + printf("\tInternal Diags Profile: %s\n", bool2str(_check_internal_diags_profile())); + printf("\tFactory Content: %s\n", bool2str(_check_factory_content())); + printf("\tBaseSystem Content: %s\n", bool2str(_check_base_system_content())); +#endif + printf("\tCan Has Debugger: %s\n", bool2str(_check_can_has_debugger())); + + return 0; +} diff --git a/tests/rpmatch.c b/tests/rpmatch.c new file mode 100644 index 0000000..1af1a68 --- /dev/null +++ b/tests/rpmatch.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include + +#include + +static char *expectations[] = { + "inclonclusive", /* -1 */ + "negative", /* 0 */ + "affirmative" /* 1 */ +}; + +static size_t +dumb_strescape(char * dst, const char * in, size_t len) { + size_t count = 0; + + while (*in && count + 3 < len) { + switch (*in) { + case '\"': + *dst++ = '\\'; + *dst++ = '\"'; + count += 2; + break; + case '\'': + *dst++ = '\\'; + *dst++ = '\"'; + count += 2; + break; + case '\\': + *dst++ = '\\'; + *dst++ = '\\'; + count += 2; + break; + case '\a': + *dst++ = '\\'; + *dst++ = 'a'; + count += 2; + break; + case '\b': + *dst++ = '\\'; + *dst++ = 'b'; + count += 2; + break; + case '\n': + *dst++ = '\\'; + *dst++ = 'n'; + count += 2; + break; + case '\t': + *dst++ = '\\'; + *dst++ = 't'; + count += 2; + break; + /* There are many more special cases */ + default: + if (iscntrl(*in)) { + count += (size_t)snprintf(dst, len - count, "\\%03o", *in); + } + else { + *dst++ = *in; + count++; + } + } + in++; + } + *dst++ = '\0'; + return count; +} + +static void +rpmatch_testcase(const char * response, int expectation) { + const char * expect_msg = expectations[expectation+1]; + + char escaped_response[16]; + dumb_strescape(escaped_response, response, sizeof(escaped_response)/sizeof(char)); + + /* darwintest should escape special characters in message strings */ + T_EXPECT_EQ(rpmatch(response), expectation, "'%s' is %s in the %s locale", escaped_response, expect_msg, setlocale(LC_ALL, NULL)); +} + +T_DECL(rpmatch, "Ensure rpmatch responds to locales") +{ + setlocale(LC_ALL, "C"); + + /* Check several single character variants */ + rpmatch_testcase("y", 1); + rpmatch_testcase("Y", 1); + rpmatch_testcase("j", -1); /* becomes afirmative in german */ + rpmatch_testcase("J", -1); + rpmatch_testcase("x", -1); + rpmatch_testcase(" ", -1); + rpmatch_testcase("", -1); + rpmatch_testcase("n", 0); + rpmatch_testcase("N", 0); + + /* A few full words */ + rpmatch_testcase("yes", 1); + rpmatch_testcase("ja", -1); + rpmatch_testcase("no", 0); + + /* Check each variant with a newline */ + rpmatch_testcase("y\n", 1); + rpmatch_testcase("Y\n", 1); + rpmatch_testcase("j\n", -1); + rpmatch_testcase("J\n", -1); + rpmatch_testcase("x\n", -1); + rpmatch_testcase(" \n", -1); + rpmatch_testcase("\n", -1); + rpmatch_testcase("n\n", 0); + rpmatch_testcase("N\n", 0); + + rpmatch_testcase("yes\n", 1); + rpmatch_testcase("ja\n", -1); + rpmatch_testcase("no\n", 0); + + /* Do it all again in a german locale */ + setlocale(LC_ALL, "de_DE.ISO8859-1"); + + if (strcmp(setlocale(LC_ALL, NULL), "de_DE.ISO8859-1") != 0) { + T_LOG("This system does not have a de_DE.ISO8859-1 locale"); + return; + } + + /* Check several single character variants */ + rpmatch_testcase("y", 1); + rpmatch_testcase("Y", 1); + rpmatch_testcase("j", 1); /* now afirmative */ + rpmatch_testcase("J", 1); + rpmatch_testcase("x", -1); + rpmatch_testcase(" ", -1); + rpmatch_testcase("", -1); + rpmatch_testcase("n", 0); + rpmatch_testcase("N", 0); + + /* A few full words */ + rpmatch_testcase("yes", 1); + rpmatch_testcase("ja", 1); + rpmatch_testcase("xx", -1); + rpmatch_testcase("no", 0); + + /* Check each variant with a newline */ + rpmatch_testcase("y\n", 1); + rpmatch_testcase("Y\n", 1); + rpmatch_testcase("j\n", 1); + rpmatch_testcase("J\n", 1); + rpmatch_testcase("x\n", -1); + rpmatch_testcase(" \n", -1); + rpmatch_testcase("\n", -1); + rpmatch_testcase("n\n", 0); + rpmatch_testcase("N\n", 0); + + rpmatch_testcase("yes\n", 1); + rpmatch_testcase("ja\n", 1); + rpmatch_testcase("xx\n", -1); + rpmatch_testcase("no\n", 0); +} diff --git a/tests/stdtime.c b/tests/stdtime.c index 80f2380..c847359 100644 --- a/tests/stdtime.c +++ b/tests/stdtime.c @@ -73,10 +73,12 @@ T_DECL(strptime_lukemftp, "year parsing"){ T_DECL(strptime_five_digit_year, "strptime(%Y) with a 5 digit year") { + // POSIX conformance requires that %Y only use 4 characters, so use the + // field width to change that for this test. char *timestr = "20080922T020000"; struct tm tm; bzero(&tm, sizeof(tm)); - T_ASSERT_NOTNULL(strptime("10001", "%Y", &tm), NULL); + T_ASSERT_NOTNULL(strptime("10001", "%5Y", &tm), NULL); T_EXPECT_EQ(tm.tm_year, 10001 - 1900, NULL); T_ASSERT_NOTNULL(strptime(timestr, "%Y%m%dT%H%M%S", &tm), NULL); } diff --git a/tests/strlcpy.c b/tests/strlcpy.c index c90945a..aba7c2b 100644 --- a/tests/strlcpy.c +++ b/tests/strlcpy.c @@ -2,7 +2,7 @@ #include -T_DECL(strlcpy_PR_30745460, "Test return value of strlcpy(2)", +T_DECL(strlcpy_PR_30745460, "Test return value of strlcpy(3)", T_META_CHECK_LEAKS(NO)) { char buf[1]; diff --git a/tests/strptime.c b/tests/strptime.c index 7cbca30..b34fa1a 100644 --- a/tests/strptime.c +++ b/tests/strptime.c @@ -34,3 +34,73 @@ T_DECL(strptime_PR_29381762, "strptime() sets the tm_wday field incorrectly") (void)strptime("1993-03-02 12:00:00", "%F %T", &t); T_EXPECT_EQ(t.tm_wday, 2, NULL); } + + +T_DECL(strptime_PR_42669744_1, "strptime() with %%C, %%y and %%Y") +{ + struct tm tm; + char *result; + + // %C%y combinations + T_LOG("201, %%C%%y"); + result = strptime("201", "%C%y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "201, %%C%%y"); + T_EXPECT_EQ(tm.tm_year, 2001 - 1900, NULL); + + T_LOG("2010, %%C%%y"); + result = strptime("2010", "%C%y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "2010, %%C%%y"); + T_EXPECT_EQ(tm.tm_year, 2010 - 1900, NULL); + + T_LOG("20010, %%C%%y"); + result = strptime("20010", "%C%y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "20010, %%C%%y"); + T_EXPECT_EQ(tm.tm_year, 2001 - 1900, NULL); + + T_LOG("+2010, %%C%%y"); + result = strptime("+2010", "%C%y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "2010, %%C%%y"); + T_EXPECT_EQ(tm.tm_year, 201 - 1900, NULL); + + T_LOG("-20100, %%C%%y"); + result = strptime("-20100", "%C%y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "-20100, %%C%%y"); + T_EXPECT_EQ(tm.tm_year, -200 + 1 - 1900, NULL); + + T_LOG("-2-1, %%C%%y"); + result = strptime("-2-1", "%C%y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "-2-1, %%C%%y"); + T_EXPECT_EQ(tm.tm_year, -200 - 1 - 1900, NULL); + + T_LOG("-2+1, %%C%%y"); + result = strptime("-2+1", "%C%y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "-2+1, %%C%%y"); + T_EXPECT_EQ(tm.tm_year, -200 + 1 - 1900, NULL); + + // %Y combinations + T_LOG("201, %%Y"); + result = strptime("201", "%Y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "201, %%Y"); + T_EXPECT_EQ(tm.tm_year, 201 - 1900, NULL); + + T_LOG("2001, %%Y"); + result = strptime("2001", "%Y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "2001, %%Y"); + T_EXPECT_EQ(tm.tm_year, 2001 - 1900, NULL); + + T_LOG("20010, %%Y"); + result = strptime("20010", "%Y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "20010, %%Y"); + T_EXPECT_EQ(tm.tm_year, 2001 - 1900, NULL); + + T_LOG("+2010, %%Y"); + result = strptime("+2010", "%Y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "+2010, %%Y"); + T_EXPECT_EQ(tm.tm_year, 201 - 1900, NULL); + + T_LOG("-2010, %%Y"); + result = strptime("-2010", "%Y", &tm); + T_QUIET; T_EXPECT_NOTNULL(result, "-2010, %%Y"); + T_EXPECT_EQ(tm.tm_year, -201 - 1900, NULL); +} + diff --git a/tests/timespec_get.c b/tests/timespec_get.c new file mode 100644 index 0000000..b387342 --- /dev/null +++ b/tests/timespec_get.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +#include + +T_DECL(timespec_get, "timespec_get") +{ + struct timespec ts; + T_ASSERT_EQ(timespec_get(&ts, TIME_UTC), TIME_UTC, NULL); + + struct timeval tv; + T_ASSERT_POSIX_ZERO(gettimeofday(&tv, NULL), NULL); + + T_EXPECT_LE((unsigned long)tv.tv_sec - (unsigned long)ts.tv_sec, (unsigned long)1, + "gettimeofday() should return same as timespec_get(TIME_UTC)"); +} + diff --git a/tests/timingsafe_bcmp.c b/tests/timingsafe_bcmp.c index dace1b0..391066e 100644 --- a/tests/timingsafe_bcmp.c +++ b/tests/timingsafe_bcmp.c @@ -14,17 +14,26 @@ T_DECL(timingsafe_bcmp, "tests for timingsafe_bcmp(3)") T_ASSERT_EQ(0, timingsafe_bcmp("foo", "foo", strlen("foo")), NULL); // unequal - T_ASSERT_NE(0, timingsafe_bcmp("foo", "bar", strlen("foo")), NULL); - T_ASSERT_NE(0, timingsafe_bcmp("foo", "goo", strlen("foo")), NULL); - T_ASSERT_NE(0, timingsafe_bcmp("foo", "fpo", strlen("foo")), NULL); - T_ASSERT_NE(0, timingsafe_bcmp("foo", "fop", strlen("foo")), NULL); + T_ASSERT_EQ(1, timingsafe_bcmp("foo", "bar", strlen("foo")), NULL); + T_ASSERT_EQ(1, timingsafe_bcmp("foo", "goo", strlen("foo")), NULL); + T_ASSERT_EQ(1, timingsafe_bcmp("foo", "fpo", strlen("foo")), NULL); + T_ASSERT_EQ(1, timingsafe_bcmp("foo", "fop", strlen("foo")), NULL); + + // all possible bitwise differences + int i; + for (i = 1; i < 256; i += 1) { + unsigned char a = 0; + unsigned char b = (unsigned char)i; + + T_ASSERT_EQ(1, timingsafe_bcmp(&a, &b, sizeof(a)), NULL); + } // large char buf[1024 * 16]; arc4random_buf(buf, sizeof(buf)); T_ASSERT_EQ(0, timingsafe_bcmp(buf, buf, sizeof(buf)), NULL); - T_ASSERT_NE(0, timingsafe_bcmp(buf, buf + 1, sizeof(buf) - 1), NULL); - T_ASSERT_NE(0, timingsafe_bcmp(buf, buf + 128, 128), NULL); + T_ASSERT_EQ(1, timingsafe_bcmp(buf, buf + 1, sizeof(buf) - 1), NULL); + T_ASSERT_EQ(1, timingsafe_bcmp(buf, buf + 128, 128), NULL); memcpy(buf+128, buf, 128); T_ASSERT_EQ(0, timingsafe_bcmp(buf, buf + 128, 128), NULL); diff --git a/xcodescripts/generate_features.pl b/xcodescripts/generate_features.pl index f275d28..e2da8f9 100755 --- a/xcodescripts/generate_features.pl +++ b/xcodescripts/generate_features.pl @@ -76,9 +76,11 @@ for my $arch (split(/ /, $ENV{"ARCHS"})) elsif ($unifdef == 1) { # assume FEATURE_BLOCKS was on by default $unifdefs{"UNIFDEF_BLOCKS"} = 1; + $unifdefs{"UNIFDEF_DRIVERKIT"} = defined($ENV{"DRIVERKITSDK"}); $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_POSIX_ILP32_ALLOW"} = defined($features{"FEATURE_POSIX_ILP32_ALLOW"}); my $output = ""; for my $d (keys %unifdefs) { diff --git a/xcodescripts/headers.sh b/xcodescripts/headers.sh index 5b9b9ed..2c53924 100755 --- a/xcodescripts/headers.sh +++ b/xcodescripts/headers.sh @@ -3,6 +3,13 @@ set -x # Installs Libc header files +if [ -n "${DRIVERKIT}" -a -z "${DRIVERKITSDK}" ]; then + # Run script in the mode that installs public DriverKit SDK headers first: + # required to get the correct header unifdef ordering, that mode strips out more + # and rewrites all headers under the parent directory (/System/DriverKit) + DRIVERKITSDK=1 SDK_INSTALL_HEADERS_ROOT="${SDK_INSTALL_ROOT}" "${BASH}" -e "$0" +fi + MKDIR="mkdir -p" INSTALL=install MV=mv @@ -26,15 +33,17 @@ else HDRROOT=${DSTROOT} fi -INCDIR=${HDRROOT}/${PUBLIC_HEADERS_FOLDER_PATH} -LOCINCDIR=${HDRROOT}/${PRIVATE_HEADERS_FOLDER_PATH} -SYSTEMFRAMEWORK=${HDRROOT}/System/Library/Frameworks/System.framework -KERNELFRAMEWORK=${HDRROOT}/System/Library/Frameworks/Kernel.framework +INCDIR=${HDRROOT}/${SDK_INSTALL_HEADERS_ROOT}/usr/include +LOCINCDIR=${HDRROOT}/${SDK_INSTALL_HEADERS_ROOT}/usr/local/include +SYSTEMFRAMEWORK=${HDRROOT}/${SDK_INSTALL_HEADERS_ROOT}/System/Library/Frameworks/System.framework +KERNELFRAMEWORK=${HDRROOT}/${SDK_INSTALL_HEADERS_ROOT}/System/Library/Frameworks/Kernel.framework PRIVHDRS=${SYSTEMFRAMEWORK}/Versions/B/PrivateHeaders PRIVKERNELHDRS=${KERNELFRAMEWORK}/Versions/A/PrivateHeaders INSTALLMODE=$([[ `id -u` -eq 0 ]] && echo 444 || echo 644) +if [ -z "${DRIVERKITSDK}" ]; then + INSTHDRS=( ${SRCROOT}/gen/get_compat.h ${SRCROOT}/gen/execinfo.h @@ -49,6 +58,7 @@ INC_INSTHDRS=( _types.h _wctype.h _xlocale.h + _ctermid.h aio.h alloca.h ar.h @@ -209,50 +219,128 @@ SYS_INSTHDRS=( ) PRIVUUID_INSTHDRS=( ${SRCROOT}/uuid/namespace.h ) -${MKDIR} ${INCDIR}/arpa -${MKDIR} ${INCDIR}/libkern -${MKDIR} ${INCDIR}/malloc -${MKDIR} ${INCDIR}/protocols -${MKDIR} ${INCDIR}/secure -${MKDIR} ${INCDIR}/sys -${MKDIR} ${INCDIR}/xlocale -${MKDIR} ${INCDIR}/_types +else # DRIVERKITSDK + +# Public DriverKit SDK headers + +UNIFDEFARGS="${UNIFDEFARGS} -U_USE_EXTENDED_LOCALES_" + +INC_INSTHDRS=( + __wctype.h + _ctype.h + _locale.h + _stdio.h + _types.h + _wctype.h + alloca.h + assert.h + ctype.h + inttypes.h + limits.h + locale.h + runetype.h + stddef.h + stdio.h + stdint.h + stdlib.h + string.h + strings.h + time.h + wchar.h + wctype.h +) + +TYPES_INSTHDRS=( + ${SRCROOT}/include/_types/_intmax_t.h + ${SRCROOT}/include/_types/_uint16_t.h + ${SRCROOT}/include/_types/_uint32_t.h + ${SRCROOT}/include/_types/_uint64_t.h + ${SRCROOT}/include/_types/_uint8_t.h + ${SRCROOT}/include/_types/_uintmax_t.h + ${SRCROOT}/include/_types/_wctrans_t.h + ${SRCROOT}/include/_types/_wctype_t.h +) + +INC_INSTHDRS=( + "${INC_INSTHDRS[@]/#/${SRCROOT}/include/}" +) +INSTHDRS=( "${INSTHDRS[@]}" "${INC_INSTHDRS[@]}" ) + +INC_SECURE_INSTHDRS=( _common.h _string.h _strings.h _stdio.h ) +SECURE_INSTHDRS=( "${INC_SECURE_INSTHDRS[@]/#/${SRCROOT}/include/secure/}" ) + +fi # DRIVERKITSDK + +if [ -n "${INSTHDRS}" ]; then +${MKDIR} ${INCDIR} ${INSTALL} -m ${INSTALLMODE} ${INSTHDRS[@]} ${INCDIR} +fi +if [ -n "${ARPA_INSTHDRS}" ]; then +${MKDIR} ${INCDIR}/arpa ${INSTALL} -m ${INSTALLMODE} ${ARPA_INSTHDRS[@]} ${INCDIR}/arpa -if [ "x${FEATURE_MEM_NOTIFICATION_APIS}" == "x1" ]; then -${INSTALL} -m ${INSTALLMODE} ${MEM_INSTHDRS[@]} ${INCDIR}/libkern fi -if [ "x${FEATURE_THERM_NOTIFICATION_APIS}" == "x1" ]; then +if [ -n "${THERM_INSTHDRS}" ]; then +${MKDIR} ${INCDIR}/libkern ${INSTALL} -m ${INSTALLMODE} ${THERM_INSTHDRS[@]} ${INCDIR}/libkern fi +if [ -n "${PROTO_INSTHDRS}" ]; then +${MKDIR} ${INCDIR}/protocols ${INSTALL} -m ${INSTALLMODE} ${PROTO_INSTHDRS[@]} ${INCDIR}/protocols +fi +if [ -n "${SECURE_INSTHDRS}" ]; then +${MKDIR} ${INCDIR}/secure ${INSTALL} -m ${INSTALLMODE} ${SECURE_INSTHDRS[@]} ${INCDIR}/secure +fi +if [ -n "${SYS_INSTHDRS}" ]; then +${MKDIR} ${INCDIR}/sys ${INSTALL} -m ${INSTALLMODE} ${SYS_INSTHDRS[@]} ${INCDIR}/sys +fi +if [ -n "${XLOCALE_INSTHDRS}" ]; then +${MKDIR} ${INCDIR}/xlocale ${INSTALL} -m ${INSTALLMODE} ${XLOCALE_INSTHDRS[@]} ${INCDIR}/xlocale +fi +if [ -n "${TYPES_INSTHDRS}" ]; then +${MKDIR} ${INCDIR}/_types ${INSTALL} -m ${INSTALLMODE} ${TYPES_INSTHDRS[@]} ${INCDIR}/_types +fi +if [ -n "${LOCALHDRS}" ]; then ${MKDIR} ${LOCINCDIR} -${MKDIR} ${LOCINCDIR}/os ${INSTALL} -m ${INSTALLMODE} ${LOCALHDRS[@]} ${LOCINCDIR} +fi +if [ -n "${OS_LOCALHDRS}" ]; then +${MKDIR} ${LOCINCDIR}/os ${INSTALL} -m ${INSTALLMODE} ${OS_LOCALHDRS[@]} ${LOCINCDIR}/os -${MKDIR} ${PRIVHDRS}/btree -${MKDIR} ${PRIVHDRS}/machine -${MKDIR} ${PRIVHDRS}/uuid -${MKDIR} ${PRIVHDRS}/sys -${MKDIR} ${PRIVKERNELHDRS}/uuid +fi +if [ -n "${PRIV_INSTHDRS}" ]; then +${MKDIR} ${PRIVHDRS} ${INSTALL} -m ${INSTALLMODE} ${PRIV_INSTHDRS[@]} ${PRIVHDRS} +fi +if [ -n "${PRIV_BTREEHDRS}" ]; then +${MKDIR} ${PRIVHDRS}/btree ${INSTALL} -m ${INSTALLMODE} ${PRIV_BTREEHDRS[@]} ${PRIVHDRS}/btree -${MV} ${INCDIR}/asm.h ${PRIVHDRS}/machine +fi +if [ -n "${SYS_INSTHDRS}" ]; then +${MKDIR} ${PRIVHDRS}/sys ${INSTALL} -m ${INSTALLMODE} ${SYS_INSTHDRS[@]} ${PRIVHDRS}/sys +fi +if [ -n "${PRIVUUID_INSTHDRS}" ]; then +${MKDIR} ${PRIVHDRS}/uuid ${INSTALL} -m ${INSTALLMODE} ${PRIVUUID_INSTHDRS[@]} ${PRIVHDRS}/uuid +${MKDIR} ${PRIVKERNELHDRS}/uuid ${INSTALL} -m ${INSTALLMODE} ${PRIVUUID_INSTHDRS[@]} ${PRIVKERNELHDRS}/uuid +fi +if [ -f "${INCDIR}/asm.h" ]; then +${MKDIR} ${PRIVHDRS}/machine +${MV} ${INCDIR}/asm.h ${PRIVHDRS}/machine +fi -for i in `${FIND} "${HDRROOT}" -name \*.h -print0 | ${XARGS} -0 ${GREP} -l '^//Begin-Libc'`; do +for i in `${FIND} "${HDRROOT}/${SDK_INSTALL_HEADERS_ROOT}" -name \*.h -print0 | ${XARGS} -0 ${GREP} -l '^//Begin-Libc'`; do ${CHMOD} u+w $i && ${ECHO} ${ED} - $i \< ${SRCROOT}/xcodescripts/strip-header.ed && ${ED} - $i < ${SRCROOT}/xcodescripts/strip-header.ed && ${CHMOD} u-w $i || exit 1; done -for i in `${FIND} "${HDRROOT}" -name \*.h -print0 | ${XARGS} -0 ${FGREP} -l -e UNIFDEF -e OPEN_SOURCE`; do +for i in `${FIND} "${HDRROOT}/${SDK_INSTALL_HEADERS_ROOT}" -name \*.h -print0 | ${XARGS} -0 ${FGREP} -l -e UNIFDEF -e OPEN_SOURCE -e _USE_EXTENDED_LOCALES_`; do ${CHMOD} u+w $i && ${CP} $i $i.orig && ${ECHO} ${UNIFDEF} ${UNIFDEFARGS} $i.orig \> $i && diff --git a/xcodescripts/libc.xcconfig b/xcodescripts/libc.xcconfig index f243d73..a7437ae 100644 --- a/xcodescripts/libc.xcconfig +++ b/xcodescripts/libc.xcconfig @@ -2,14 +2,27 @@ // Standard settings SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator iphoneosnano iphonesimulatornano bridgeos + +SDK_INSTALL_VARIANT = $(SDK_INSTALL_VARIANT_$(DRIVERKIT)) +SDK_INSTALL_VARIANT_1 = driverkit +SDK_INSTALL_VARIANT_ = default +SDK_INSTALL_ROOT = $(SDK_INSTALL_ROOT_$(SDK_INSTALL_VARIANT)) +SDK_INSTALL_ROOT_driverkit = $(DRIVERKITROOT) +SDK_INSTALL_HEADERS_ROOT = $(SDK_INSTALL_HEADERS_ROOT_$(SDK_INSTALL_VARIANT)) +SDK_INSTALL_HEADERS_ROOT_driverkit = $(SDK_INSTALL_ROOT)/$(SDK_RUNTIME_HEADERS_PREFIX) +SDK_RUNTIME_HEADERS_PREFIX = Runtime + 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) +SYSTEM_FRAMEWORK_HEADERS = $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders +SDK_SYSTEM_FRAMEWORK_HEADERS = $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders +HEADER_SEARCH_PATHS = $($(TARGET_NAME)_SEARCH_PATHS) $(DERIVED_FILES_DIR)/dtrace $(SRCROOT_SEARCH_PATHS) $(inherited) +SYSTEM_HEADER_SEARCH_PATHS = $(SYSTEM_FRAMEWORK_HEADERS) $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/usr/local/include $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/usr/include +SYSTEM_FRAMEWORK_SEARCH_PATHS = $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/System/Library/Frameworks ALWAYS_SEARCH_USER_PATHS = YES USE_HEADERMAP = NO BUILD_VARIANTS = normal GCC_OPTIMIZATION_LEVEL = s -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu11 GCC_ENABLE_OBJC_EXCEPTIONS = YES GCC_SYMBOLS_PRIVATE_EXTERN = NO GCC_DYNAMIC_NO_PIC = NO @@ -34,7 +47,7 @@ VERSIONING_SYSTEM = VERSION_INFO_PREFIX = __attribute__((visibility("hidden"))) COPY_PHASE_STRIP = NO STRIP_INSTALLED_PRODUCT = NO -LD_DYLIB_INSTALL_NAME = /usr/lib/system/$(EXECUTABLE_NAME) +LD_DYLIB_INSTALL_NAME = $(SDK_INSTALL_ROOT)/usr/lib/system/$(EXECUTABLE_NAME) IS_ZIPPERED = YES BUILD_VARIANTS = normal debug @@ -45,12 +58,12 @@ GCC_VERSION = com.apple.compilers.llvm.clang.1_0 GCC_VERSION[arch=armv6] = com.apple.compilers.llvmgcc42 EXECUTABLE_PREFIX = libsystem_ -INSTALL_PATH = /usr/lib/system -PUBLIC_HEADERS_FOLDER_PATH = /usr/include -PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include +INSTALL_PATH = $(SDK_INSTALL_ROOT)/usr/lib/system +PUBLIC_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/usr/include +PRIVATE_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/usr/local/include -DARWIN_PUBLIC_HEADERS_FOLDER_PATH = /usr/include/os -DARWIN_PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/os +DARWIN_PUBLIC_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/usr/include/os +DARWIN_PRIVATE_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/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 @@ -62,6 +75,7 @@ GCC_PREPROCESSOR_DEFINITIONS = $(BASE_PREPROCESSOR_MACROS) // libsystem_c.dylib linking CR_LDFLAGS = -lCrashReporterClient +CR_LDFLAGS[sdk=driverkit*] = LIBCOMPILER_RT_LDFLAGS = -lcompiler_rt LIBMALLOC_LDFLAGS = -lsystem_malloc LIBC_LDFLAGS = -lsystem_c @@ -72,13 +86,14 @@ LIBPTHREAD_LDFLAGS = -lsystem$(SIM_SUFFIX)_pthread LIBSYSCALL_LDFLAGS = -lsystem$(SIM_SUFFIX)_kernel LIBM_LDFLAGS = -lsystem_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) $(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_LDFLAGS = -all_load -nostdlib -L$(SDK_INSTALL_ROOT)/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 @$(BUILT_PRODUCTS_DIR)/$(CURRENT_VARIANT).linklist LIBSYSTEM_C_EXTRA_LDFLAGS_i386 = -Wl,-alias_list,$(SRCROOT)/xcodescripts/legacy_alias.list // TODO: Remove upward links - mostly , macho is for assumes.c UPWARD_LDFLAGS = -Wl,-upward-ldispatch -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 -Wl,-upward-lsystem_trace +UPWARD_LDFLAGS[sdk=driverkit*] = -Wl,-upward-lmacho -Wl,-upward-lsystem_blocks -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) +LIBSYSTEM_DARWIN_LDFLAGS = -all_load -nostdlib -L$(SDK_INSTALL_ROOT)/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)) @@ -129,6 +144,7 @@ BASE_EXCLUDED_SOURCE_FILE_NAMES_appletvsimulator = $(BASE_EXCLUDED_SOURCE_FILE_N 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) +BASE_EXCLUDED_SOURCE_FILE_NAMES_driverkit = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_macosx) $(BASE_EXCLUDED_SOURCE_FILE_NAMES_iphoneos) getlogin.c setlogin.c logwtmp.c utmpx.c utmpx-darwin.c daemon.c authentication.c pty.c opendev.c fparseln.c psort*.c crypt.c glob.c readpassphrase.c atexit_receipt.c debug_private.c sourcefilter.c inet*.c nsap_addr.c ascii2addr.c addr2ascii.c acl*.c filesec.c chmodx_np.c openx_np.c umaskx_np.c statx_np.c // TODO: Remove these legacy platform names: BASE_EXCLUDED_SOURCE_FILE_NAMES_iphoneosnano = $(BASE_EXCLUDED_SOURCE_FILE_NAMES_watchos) @@ -148,5 +164,7 @@ TAPI_HEADER_SEARCH_PATHS = // TODO: Remove this hack once Marzipan bringup is done VARIANT_PLATFORM_NAME = $(VARIANT_PLATFORM_NAME_$(RC_MARZIPAN)) -VARIANT_PLATFORM_NAME_ = $(PLATFORM_NAME) VARIANT_PLATFORM_NAME_YES = macosx +VARIANT_PLATFORM_NAME_ = $(VARIANT_PLATFORM_NAME_$(SDK_INSTALL_VARIANT)) +VARIANT_PLATFORM_NAME_default = $(PLATFORM_NAME) +VARIANT_PLATFORM_NAME_driverkit = driverkit diff --git a/xcodescripts/manpages.sh b/xcodescripts/manpages.sh index 32054df..3141add 100755 --- a/xcodescripts/manpages.sh +++ b/xcodescripts/manpages.sh @@ -3,6 +3,7 @@ if [ "$ACTION" = installhdrs ]; then exit 0; fi if [ "${PLATFORM_NAME}" != "macosx" ]; then exit 0; fi if [ "${SKIP_MANPAGES}" = "YES" ]; then exit 0; fi +if [ "${DRIVERKIT}" = 1 ]; then exit 0; fi UNIFDEF_FLAGS=`${SRCROOT}/xcodescripts/generate_features.pl --unifdef` MANPAGES_LIST="${SRCROOT}/man/manpages.lst" diff --git a/xcodescripts/variants.xcconfig b/xcodescripts/variants.xcconfig index f8118ea..68fd071 100644 --- a/xcodescripts/variants.xcconfig +++ b/xcodescripts/variants.xcconfig @@ -21,12 +21,12 @@ VARIANT_CANCELABLE_INCLUDE_sys = system.c VARIANT_DARWINEXTSN_MACROS = -DVARIANT_DARWINEXTSN -VARIANT_DARWINEXTSN_INCLUDE = $(VARIANT_DARWINEXTSN_INCLUDE_gen) $(VARIANT_DARWINEXTSN_INCLUDE_stdio) $(VARIANT_DARWINEXTSN_INCLUDE_stdlib) $(VARIANT_DARWINEXTSN_INCLUDE_sys) +VARIANT_DARWINEXTSN_INCLUDE = $(VARIANT_DARWINEXTSN_INCLUDE_gen) $(VARIANT_DARWINEXTSN_INCLUDE_stdio) $(VARIANT_DARWINEXTSN_INCLUDE_stdlib) $(VARIANT_DARWINEXTSN_INCLUDE_sys_$(SDK_INSTALL_VARIANT)) VARIANT_DARWINEXTSN_INCLUDE_gen = popen.c VARIANT_DARWINEXTSN_INCLUDE_stdio = fdopen.c fopen.c VARIANT_DARWINEXTSN_INCLUDE_stdlib = realpath.c -VARIANT_DARWINEXTSN_INCLUDE_sys = getgroups.c +VARIANT_DARWINEXTSN_INCLUDE_sys_default = getgroups.c // $DARWINEXTSN + no cancel (everyone else is cancelable anyway) -- 2.45.2