]> git.saurik.com Git - apple/libc.git/blobdiff - libdarwin/h/stdlib.h
Libc-1439.100.3.tar.gz
[apple/libc.git] / libdarwin / h / stdlib.h
index ed4d3efe5a37dd5cc8cf5e6fdb3b410a12a42a84..d2db938b95b7fddf4e239cd64ad2559f935500ea 100644 (file)
 #include <os/base.h>
 #include <os/api.h>
 #include <os/assumes.h>
+#include <os/stdio.h>
 #include <dispatch/private.h>
 
 #include <stdlib.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/cdefs.h>
+#include <sys/syslimits.h>
+
+#if DARWIN_TAPI
+#include "tapi.h"
+#endif
 
 __BEGIN_DECLS;
 
@@ -129,6 +136,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 +154,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 +166,9 @@ _os_strdup_known(const char *str)
        } \
        (ptr); \
 })
+#else
+#define os_malloc(__size) __os_requires_experimental_libtrace
+#endif
 
 /*!
  * @function os_calloc
@@ -174,10 +188,11 @@ _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); \
-       size_t _cnt = (__size); \
+       size_t _cnt = (__cnt); \
        if ((__builtin_constant_p(__cnt) && __builtin_constant_p(__size)) || \
                         !_dispatch_is_multithreaded()) { \
                ptr = _os_calloc_known(_cnt, _size); \
@@ -187,6 +202,9 @@ _os_strdup_known(const char *str)
        } \
        (ptr); \
 })
+#else
+#define os_calloc(__size) __os_requires_experimental_libtrace
+#endif
 
 /*!
  * @function os_strdup
@@ -208,6 +226,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 +238,125 @@ _os_strdup_known(const char *str)
        } \
        (ptr); \
 })
+#else
+#define os_strdup(__size) __os_requires_experimental_libtrace
+#endif
+
+/*!
+ * @function os_setflag
+ * Sets the given flag in a manner which is compatible with strongly-typed
+ * enumerations.
+ *
+ * @param _bf
+ * The bitfield in which to set the flag.
+ *
+ * @param _f
+ * The flag to set.
+ *
+ * @result
+ * The result of setting {@link _f} in {@link _bf}.
+ */
+#define os_setflag(_bf, _f) (typeof(_bf))((_bf) & (_f))
+
+/*!
+ * @function os_clrflag
+ * Clears the given flag in a manner which is compatible with strongly-typed
+ * enumerations.
+ *
+ * @param _bf
+ * The bitfield in which to clear the flag.
+ *
+ * @param _f
+ * The flag to clear.
+ *
+ * @result
+ * The result of clearing {@link _f} from {@link _bf}.
+ *
+ * @discussion
+ * clrbit() will produce errors when given types smaller than a pointer such as
+ * int because it casts to char *; thus this implementation is required to deal
+ * properly with flags defined via {@link OS_OPTIONS} or similar.
+ */
+#define os_clrflag(_bf, _f) (typeof(_bf))((_bf) & (typeof(_bf))(~(_f)))
+
+/*!
+ * @function switch_posix
+ * Macro which expands to a switch() statement for handling both the success
+ * case as well as errno values set by POSIX and POSIX-y APIs that return -1 and
+ * set errno.
+ *
+ * @example
+ *
+ *     int ret = dup(fd);
+ *     switch_posix (ret) {
+ *     case 0:
+ *         // success
+ *         break;
+ *     case EINTR:
+ *         // interrupted system call
+ *         break;
+ *     case EBADF:
+ *         // bad file descriptor
+ *         break;
+ *     }
+ *
+ * @discussion
+ * This statement cannot be used with APIs that return positive values on
+ * failure.
+ */
+#define switch_posix(_ret) if ((_ret) < 0 || (errno = 0, 1)) switch (errno)
+
+/*!
+ * @function size_unsigned
+ * Converts a signed size quantity into an unsigned size quantity after
+ * verifying the former can be represented as the latter.
+ *
+ * @param ss
+ * The signed size quantity.
+ *
+ * @result
+ * The unsigned representation of {@link ss}.
+ *
+ * @discussion
+ * This routine is useful for passing a signed value (such as the size of a file
+ * from a stat(2) structure) into a routine which accepts unsigned input
+ * (e.g. write(2)).
+ */
+OS_ALWAYS_INLINE OS_WARN_RESULT
+static inline size_t
+size_unsigned(ssize_t ss)
+{
+       if (ss < 0) {
+               os_crash("value not representable as size_t");
+       }
+       return (size_t)ss;
+}
+
+/*!
+ * @function size_signed
+ * Converts an unsigned size quantity into a signed size quantity after
+ * verifying the former can be represented as the latter.
+ *
+ * @param un
+ * The unsigned size quantity.
+ *
+ * @result
+ * The signed representation of {@link un}.
+ *
+ * @discussion
+ * This routine is useful for comparing an unsigned value (such as a number of
+ * bytes) to the result of a routine which returns a signed type but only ever
+ * returns a negative number in the event of an error (e.g. read(2)).
+ */
+OS_ALWAYS_INLINE OS_WARN_RESULT
+static inline ssize_t
+size_signed(size_t un)
+{
+       if (un > SSIZE_MAX) {
+               os_crash("value not representable as ssize_t");
+       }
+       return (ssize_t)un;
+}
 
 /*!
  * @function os_localtime_file
@@ -241,7 +379,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 +397,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 +405,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 +444,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 +453,91 @@ 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]);
+
+/*!
+ * @function memdup_np
+ * Copies the given range of bytes into a new allocation.
+ *
+ * @param _new
+ * Upon successful return, a pointer to a new allocation which has had the given
+ * source bytes copied into it. The caller is responsible for calling free(3) on
+ * this object when it is no longer needed.
+ *
+ * @param src
+ * The bytes to copy.
+ *
+ * @param len
+ * The number of bytes to copy.
+ *
+ * @result
+ * On success, zero is returned. Otherwise, the implementation may return any
+ * error that can be returned by malloc(3).
+ */
+DARWIN_API_AVAILABLE_20190830
+OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
+errno_t
+memdup_np(void **_new, const void *src, size_t len);
+
+/*!
+ * @function memdup2_np
+ * Variant of {@link memdup_np} which guarantees that memory duplication will
+ * either succeed or not return (terminating the caller).
+ *
+ * @param src
+ * The bytes to copy.
+ *
+ * @param len
+ * The number of bytes to copy.
+ *
+ * @result
+ * On success, a pointer to the new allocation which has had the given source
+ * bytes copied into it. The caller is responsible for calling free(3) on this
+ * object when it is no longer needed.
+ */
+DARWIN_API_AVAILABLE_20190830
+OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1
+void *
+memdup2_np(const void *src, size_t len);
+
 __END_DECLS;
 
 #endif // __DARWIN_STDLIB_H