stdio.h   [plain text]


/*
 * 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
 * Non-standard, Darwin-specific additions for the stdio(3) family of APIs.
 */
#ifndef __DARWIN_STDIO_H
#define __DARWIN_STDIO_H

#include <os/base.h>
#include <os/api.h>
#include <sys/cdefs.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

#if __has_include(<sys/guarded.h>)
#include <sys/guarded.h>
#else
typedef uint64_t guardid_t;
#endif

#if DARWIN_TAPI
#include "tapi.h"
#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 os_guardid_from_ptr
 * Converts the given pointer to a guardid_t.
 *
 * @param p
 * The pointer to convert.
 *
 * @result
 * The pointer as a guardid_t.
 */
DARWIN_API_AVAILABLE_20190830
OS_ALWAYS_INLINE OS_WARN_RESULT
static inline guardid_t
os_guardid_from_ptr(const void *p)
{
	return (guardid_t)(uintptr_t)p;
}

/*!
 * @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 claimfd_np
 * Claims the given file descriptor for the caller's exclusive use by applying a
 * guard and invalidating the given storage.
 *
 * @param fdp
 * A pointer to the storage for the descriptor to claim. Upon return, a known-
 * invalid value is written into this memory.
 *
 * @param gdid
 * The optional guard value to enforce the caller's claim on the descriptor.
 *
 * @param gdflags
 * The guard flags to enforce the caller's claim on the descriptor.
 *
 * @result
 * The given descriptor with the guard applied.
 */
DARWIN_API_AVAILABLE_20190830
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
os_fd_t
claimfd_np(os_fd_t *fdp, const guardid_t *gdid, u_int gdflags);

/*!
 * @function xferfd_np
 * Transfers ownership from the given file descriptor back to the general public
 * by clearing the guard associated with it.
 *
 * @param fdp
 * A pointer to the storage for the descriptor to claim. Upon return, a known-
 * invalid value is written into this memory.
 *
 * @param gdid
 * The optional guard value to reliquish ownership on the descriptor.
 *
 * @param gdflags
 * The guard flags to relinquish.
 *
 * @result
 * The given descriptor with the guard cleared. This descriptor is suitable for
 * claiming with {@link claimfd_np}.
 */
DARWIN_API_AVAILABLE_20190830
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
os_fd_t
xferfd_np(os_fd_t *fdp, const guardid_t *gdid, u_int gdflags);

/*!
 * @function close_drop_np
 * Variant of close(2) which transfers ownership from the caller and performs
 * the close(2) operation. These semantics are useful for ensuring that a
 * descriptor is not erroneously re-used after it has been closed. To achieve
 * these semantics, this variant will clear the memory in which the descriptor
 * resides and replace it with a known-invalid value before returning.
 *
 * @param fdp
 * A pointer to the storage for the descriptor to close. Upon return, a known-
 * invalid value is written into this memory.
 *
 * @param gdid
 * The optional guard. If the descriptor is not guarded, pass NULL.
 *
 * @discussion
 * If the implementation encounters a failure to close a valid descriptor
 * number, the caller will be terminated.
 */
OS_EXPORT OS_NONNULL1
void
close_drop_np(os_fd_t *fdp, const guardid_t *gdid);

/*!
 * @function close_drop_optional_np
 * Variant of {@link close_drop} which will not attempt to close an invalid
 * descriptor. Otherwise all semantics are the same.
 *
 * @param fdp
 * A pointer to the storage for the descriptor to close. Upon return, a known-
 * invalid value is written into this memory.
 *
 * @param gdid
 * The optional guard. If the descriptor is not guarded, pass NULL.
 *
 * @discussion
 * If the implementation encounters a failure to close a valid descriptor
 * number, the caller will be terminated. The implementation will not attempt to
 * close the descriptor if its value is -1.
 */
OS_EXPORT OS_NONNULL1
void
close_drop_optional_np(os_fd_t *fdp, const guardid_t *gdid);

/*!
 * @function zsnprintf_np
 * snprintf(3) variant which returns the numnber of bytes written less the null
 * terminator.
 *
 * @param buff
 * The buffer in which to write the string.
 *
 * @param len
 * The length of the buffer.
 *
 * @param fmt
 * The printf(3)-like format string.
 *
 * @param ...
 * The arguments corresponding to the format string.
 *
 * @result
 * The number of bytes written into the buffer, less the null terminator. This
 * routine is useful for successive string printing that may be lossy, as it
 * will simply return zero when there is no space left in the destination
 * buffer, i.e. enables the following pattern:
 *
 * char *cur = buff;
 * size_t left = sizeof(buff);
 * for (i = 0; i < n_strings; i++) {
 *     size_t n_written = zsnprintf_np(buff, left, "%s", strings[i]);
 *     cur += n_written;
 *     left -= n_written;
 * }
 *
 * This loop will safely terminate without any special care since, as soon as
 * the buffer's space is exhausted, all further calls to zsnprintf_np() will
 * write nothing and return zero.
 */
DARWIN_API_AVAILABLE_20170407
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