Index: head/include/stdlib.h =================================================================== --- head/include/stdlib.h (revision 350419) +++ head/include/stdlib.h (revision 350420) @@ -1,347 +1,348 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)stdlib.h 8.5 (Berkeley) 5/19/95 * $FreeBSD$ */ #ifndef _STDLIB_H_ #define _STDLIB_H_ #include #include #include __NULLABILITY_PRAGMA_PUSH #if __BSD_VISIBLE #ifndef _RUNE_T_DECLARED typedef __rune_t rune_t; #define _RUNE_T_DECLARED #endif #endif #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef __cplusplus #ifndef _WCHAR_T_DECLARED typedef ___wchar_t wchar_t; #define _WCHAR_T_DECLARED #endif #endif typedef struct { int quot; /* quotient */ int rem; /* remainder */ } div_t; typedef struct { long quot; long rem; } ldiv_t; #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 #define RAND_MAX 0x7ffffffd __BEGIN_DECLS #ifdef _XLOCALE_H_ #include #endif extern int __mb_cur_max; extern int ___mb_cur_max(void); #define MB_CUR_MAX ((size_t)___mb_cur_max()) _Noreturn void abort(void); int abs(int) __pure2; int atexit(void (* _Nonnull)(void)); double atof(const char *); int atoi(const char *); long atol(const char *); void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void * _Nonnull, const void *)); void *calloc(size_t, size_t) __malloc_like __result_use_check __alloc_size2(1, 2); div_t div(int, int) __pure2; _Noreturn void exit(int); void free(void *); char *getenv(const char *); long labs(long) __pure2; ldiv_t ldiv(long, long) __pure2; void *malloc(size_t) __malloc_like __result_use_check __alloc_size(1); int mblen(const char *, size_t); size_t mbstowcs(wchar_t * __restrict , const char * __restrict, size_t); int mbtowc(wchar_t * __restrict, const char * __restrict, size_t); void qsort(void *, size_t, size_t, int (* _Nonnull)(const void *, const void *)); int rand(void); void *realloc(void *, size_t) __result_use_check __alloc_size(2); void srand(unsigned); double strtod(const char * __restrict, char ** __restrict); float strtof(const char * __restrict, char ** __restrict); long strtol(const char * __restrict, char ** __restrict, int); long double strtold(const char * __restrict, char ** __restrict); unsigned long strtoul(const char * __restrict, char ** __restrict, int); int system(const char *); int wctomb(char *, wchar_t); size_t wcstombs(char * __restrict, const wchar_t * __restrict, size_t); /* * Functions added in C99 which we make conditionally available in the * BSD^C89 namespace if the compiler supports `long long'. * The #if test is more complicated than it ought to be because * __BSD_VISIBLE implies __ISO_C_VISIBLE == 1999 *even if* `long long' * is not supported in the compilation environment (which therefore means * that it can't really be ISO C99). * * (The only other extension made by C99 in thie header is _Exit().) */ #if __ISO_C_VISIBLE >= 1999 || defined(__cplusplus) #ifdef __LONG_LONG_SUPPORTED /* LONGLONG */ typedef struct { long long quot; long long rem; } lldiv_t; /* LONGLONG */ long long atoll(const char *); /* LONGLONG */ long long llabs(long long) __pure2; /* LONGLONG */ lldiv_t lldiv(long long, long long) __pure2; /* LONGLONG */ long long strtoll(const char * __restrict, char ** __restrict, int); /* LONGLONG */ unsigned long long strtoull(const char * __restrict, char ** __restrict, int); #endif /* __LONG_LONG_SUPPORTED */ _Noreturn void _Exit(int); #endif /* __ISO_C_VISIBLE >= 1999 */ /* * If we're in a mode greater than C99, expose C11 functions. */ #if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) __alloc_size(2); int at_quick_exit(void (*)(void)); _Noreturn void quick_exit(int); #endif /* __ISO_C_VISIBLE >= 2011 */ /* * Extensions made by POSIX relative to C. */ #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE char *realpath(const char * __restrict, char * __restrict); #endif #if __POSIX_VISIBLE >= 199506 int rand_r(unsigned *); /* (TSF) */ #endif #if __POSIX_VISIBLE >= 200112 int posix_memalign(void **, size_t, size_t); /* (ADV) */ int setenv(const char *, const char *, int); int unsetenv(const char *); #endif #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE int getsubopt(char **, char *const *, char **); #ifndef _MKDTEMP_DECLARED char *mkdtemp(char *); #define _MKDTEMP_DECLARED #endif #ifndef _MKSTEMP_DECLARED int mkstemp(char *); #define _MKSTEMP_DECLARED #endif #endif /* __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE */ /* * The only changes to the XSI namespace in revision 6 were the deletion * of the ttyslot() and valloc() functions, which FreeBSD never declared * in this header. For revision 7, ecvt(), fcvt(), and gcvt(), which * FreeBSD also does not have, and mktemp(), are to be deleted. */ #if __XSI_VISIBLE /* XXX XSI requires pollution from here. We'd rather not. */ long a64l(const char *); double drand48(void); /* char *ecvt(double, int, int * __restrict, int * __restrict); */ double erand48(unsigned short[3]); /* char *fcvt(double, int, int * __restrict, int * __restrict); */ /* char *gcvt(double, int, int * __restrict, int * __restrict); */ int grantpt(int); char *initstate(unsigned int, char *, size_t); long jrand48(unsigned short[3]); char *l64a(long); void lcong48(unsigned short[7]); long lrand48(void); #if !defined(_MKTEMP_DECLARED) && (__BSD_VISIBLE || __XSI_VISIBLE <= 600) char *mktemp(char *); #define _MKTEMP_DECLARED #endif long mrand48(void); long nrand48(unsigned short[3]); int posix_openpt(int); char *ptsname(int); int putenv(char *); long random(void); unsigned short *seed48(unsigned short[3]); char *setstate(/* const */ char *); void srand48(long); void srandom(unsigned int); int unlockpt(int); #endif /* __XSI_VISIBLE */ #if __BSD_VISIBLE extern const char *malloc_conf; extern void (*malloc_message)(void *, const char *); /* * The alloca() function can't be implemented in C, and on some * platforms it can't be implemented at all as a callable function. * The GNU C compiler provides a built-in alloca() which we can use. * On platforms where alloca() is not in libc, programs which use it * will fail to link when compiled with non-GNU compilers. */ #if __GNUC__ >= 2 || defined(__INTEL_COMPILER) #undef alloca /* some GNU bits try to get cute and define this on their own */ #define alloca(sz) __builtin_alloca(sz) #endif void abort2(const char *, int, void **) __dead2; __uint32_t arc4random(void); void arc4random_buf(void *, size_t); __uint32_t arc4random_uniform(__uint32_t); #ifdef __BLOCKS__ int atexit_b(void (^ _Nonnull)(void)); void *bsearch_b(const void *, const void *, size_t, size_t, int (^ _Nonnull)(const void *, const void *)); #endif char *getbsize(int *, long *); /* getcap(3) functions */ char *cgetcap(char *, const char *, int); int cgetclose(void); int cgetent(char **, char **, const char *); int cgetfirst(char **, char **); int cgetmatch(const char *, const char *); int cgetnext(char **, char **); int cgetnum(char *, const char *, long *); int cgetset(const char *); int cgetstr(char *, const char *, char **); int cgetustr(char *, const char *, char **); int daemon(int, int); int daemonfd(int, int); char *devname(__dev_t, __mode_t); char *devname_r(__dev_t, __mode_t, char *, int); char *fdevname(int); char *fdevname_r(int, char *, int); int getloadavg(double [], int); const char * getprogname(void); int heapsort(void *, size_t, size_t, int (* _Nonnull)(const void *, const void *)); #ifdef __BLOCKS__ int heapsort_b(void *, size_t, size_t, int (^ _Nonnull)(const void *, const void *)); void qsort_b(void *, size_t, size_t, int (^ _Nonnull)(const void *, const void *)); #endif int l64a_r(long, char *, int); int mergesort(void *, size_t, size_t, int (*)(const void *, const void *)); #ifdef __BLOCKS__ int mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *)); #endif int mkostemp(char *, int); int mkostemps(char *, int, int); +int mkostempsat(int, char *, int, int); void qsort_r(void *, size_t, size_t, void *, int (*)(void *, const void *, const void *)); int radixsort(const unsigned char **, int, const unsigned char *, unsigned); void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size2(2, 3); void *reallocf(void *, size_t) __result_use_check __alloc_size(2); int rpmatch(const char *); void setprogname(const char *); int sradixsort(const unsigned char **, int, const unsigned char *, unsigned); void sranddev(void); void srandomdev(void); long long strtonum(const char *, long long, long long, const char **); /* Deprecated interfaces, to be removed. */ __int64_t strtoq(const char *, char **, int); __uint64_t strtouq(const char *, char **, int); extern char *suboptarg; /* getsubopt(3) external variable */ #endif /* __BSD_VISIBLE */ #if __EXT1_VISIBLE #ifndef _ERRNO_T_DEFINED #define _ERRNO_T_DEFINED typedef int errno_t; #endif /* K.3.6 */ typedef void (*constraint_handler_t)(const char * __restrict, void * __restrict, errno_t); /* K.3.6.1.1 */ constraint_handler_t set_constraint_handler_s(constraint_handler_t handler); /* K.3.6.1.2 */ _Noreturn void abort_handler_s(const char * __restrict, void * __restrict, errno_t); /* K3.6.1.3 */ void ignore_handler_s(const char * __restrict, void * __restrict, errno_t); #endif /* __EXT1_VISIBLE */ __END_DECLS __NULLABILITY_PRAGMA_POP #endif /* !_STDLIB_H_ */ Index: head/lib/libc/stdio/Makefile.inc =================================================================== --- head/lib/libc/stdio/Makefile.inc (revision 350419) +++ head/lib/libc/stdio/Makefile.inc (revision 350420) @@ -1,88 +1,88 @@ # @(#)Makefile.inc 8.3 (Berkeley) 4/17/94 # $FreeBSD$ # stdio sources .PATH: ${LIBC_SRCTOP}/stdio SRCS+= _flock_stub.c asprintf.c clrerr.c dprintf.c \ fclose.c fcloseall.c fdopen.c \ feof.c ferror.c fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetwc.c \ fgetwln.c fgetws.c \ fileno.c findfp.c flags.c fmemopen.c fopen.c \ fopencookie.c fprintf.c fpurge.c \ fputc.c fputs.c \ fputwc.c fputws.c fread.c freopen.c fscanf.c fseek.c fsetpos.c \ ftell.c funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwscanf.c \ fwrite.c getc.c getchar.c getdelim.c getline.c \ gets.c gets_s.c getw.c getwc.c getwchar.c makebuf.c mktemp.c \ open_memstream.c open_wmemstream.c \ perror.c printf.c printf-pos.c putc.c putchar.c \ puts.c putw.c putwc.c putwchar.c \ refill.c remove.c rewind.c rget.c scanf.c setbuf.c setbuffer.c \ setvbuf.c snprintf.c sprintf.c sscanf.c stdio.c swprintf.c swscanf.c \ tempnam.c tmpfile.c \ tmpnam.c ungetc.c ungetwc.c vasprintf.c vdprintf.c vfprintf.c \ vfscanf.c \ vfwprintf.c vfwscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c \ vsscanf.c \ vswprintf.c vswscanf.c vwprintf.c vwscanf.c wbuf.c wprintf.c wscanf.c \ wsetup.c SRCS+= xprintf.c xprintf_float.c xprintf_int.c xprintf_str.c SRCS+= xprintf_errno.c xprintf_hexdump.c xprintf_quote.c SRCS+= xprintf_time.c xprintf_vis.c SYM_MAPS+= ${LIBC_SRCTOP}/stdio/Symbol.map MAN+= fclose.3 ferror.3 fflush.3 fgetln.3 fgets.3 fgetwln.3 fgetws.3 \ flockfile.3 \ fopen.3 fopencookie.3 fputs.3 \ fputws.3 fread.3 fseek.3 funopen.3 fwide.3 getc.3 \ getline.3 getwc.3 mktemp.3 open_memstream.3 \ printf.3 printf_l.3 putc.3 putwc.3 remove.3 scanf.3 scanf_l.3 setbuf.3 \ stdio.3 tmpnam.3 \ ungetc.3 ungetwc.3 wprintf.3 wscanf.3 MLINKS+=fclose.3 fcloseall.3 fclose.3 fdclose.3 MLINKS+=ferror.3 ferror_unlocked.3 \ ferror.3 clearerr.3 ferror.3 clearerr_unlocked.3 \ ferror.3 feof.3 ferror.3 feof_unlocked.3 \ ferror.3 fileno.3 ferror.3 fileno_unlocked.3 MLINKS+=fflush.3 fpurge.3 MLINKS+=fgets.3 gets.3 MLINKS+=fgets.3 gets_s.3 MLINKS+=flockfile.3 ftrylockfile.3 flockfile.3 funlockfile.3 MLINKS+=fopen.3 fdopen.3 fopen.3 freopen.3 fopen.3 fmemopen.3 MLINKS+=fputs.3 puts.3 MLINKS+=fread.3 fwrite.3 MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \ fseek.3 ftello.3 fseek.3 rewind.3 MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3 MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \ getc.3 getchar_unlocked.3 getc.3 getw.3 MLINKS+=getline.3 getdelim.3 MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3 MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3 \ - mktemp.3 mkostemp.3 mktemp.3 mkostemps.3 + mktemp.3 mkostemp.3 mktemp.3 mkostemps.3 mktemp.3 mkostempsat.3 MLINKS+=open_memstream.3 open_wmemstream.3 MLINKS+=printf.3 asprintf.3 printf.3 dprintf.3 printf.3 fprintf.3 \ printf.3 snprintf.3 printf.3 sprintf.3 \ printf.3 vasprintf.3 printf.3 vdprintf.3 \ printf.3 vfprintf.3 printf.3 vprintf.3 printf.3 vsnprintf.3 \ printf.3 vsprintf.3 MLINKS+=printf_l.3 asprintf_l.3 printf_l.3 fprintf_l.3 printf_l.3 snprintf_l.3 \ printf_l.3 sprintf_l.3 printf_l.3 vasprintf_l.3 printf_l.3 vfprintf_l.3 \ printf_l.3 vprintf_l.3 printf_l.3 vsnprintf_l.3 printf_l.3 vsprintf_l.3 MLINKS+=putc.3 fputc.3 putc.3 putc_unlocked.3 putc.3 putchar.3 \ putc.3 putchar_unlocked.3 putc.3 putw.3 MLINKS+=putwc.3 fputwc.3 putwc.3 putwchar.3 MLINKS+=scanf.3 fscanf.3 scanf.3 sscanf.3 scanf.3 vfscanf.3 scanf.3 vscanf.3 \ scanf.3 vsscanf.3 MLINKS+=scanf_l.3 fscanf_l.3 scanf_l.3 sscanf_l.3 scanf_l.3 vfscanf_l.3 \ scanf_l.3 vscanf_l.3 scanf_l.3 vsscanf_l.3 MLINKS+=setbuf.3 setbuffer.3 setbuf.3 setlinebuf.3 setbuf.3 setvbuf.3 MLINKS+=tmpnam.3 tempnam.3 tmpnam.3 tmpfile.3 MLINKS+=wprintf.3 fwprintf.3 wprintf.3 swprintf.3 \ wprintf.3 vwprintf.3 wprintf.3 vfwprintf.3 wprintf.3 vswprintf.3 MLINKS+=wscanf.3 fwscanf.3 wscanf.3 swscanf.3 wscanf.3 vwscanf.3 \ wscanf.3 vswscanf.3 wscanf.3 vfwscanf.3 Index: head/lib/libc/stdio/Symbol.map =================================================================== --- head/lib/libc/stdio/Symbol.map (revision 350419) +++ head/lib/libc/stdio/Symbol.map (revision 350420) @@ -1,212 +1,216 @@ /* * $FreeBSD$ */ FBSD_1.0 { flockfile; ftrylockfile; funlockfile; asprintf; clearerr; fclose; fcloseall; fdopen; feof; ferror; fflush; fgetc; fgetln; fgetpos; fgets; fgetwc; fgetwln; fgetws; fileno; __sF; __stdinp; __stdoutp; __stderrp; f_prealloc; /* deprecated??? */ fopen; fprintf; fpurge; fputc; fputs; fputwc; fputws; fread; freopen; fscanf; fseek; fseeko; fsetpos; ftell; ftello; funopen; fwide; fwprintf; fwrite; fwscanf; getc; getchar; gets; getw; getwc; getwchar; mkstemps; mkstemp; mkdtemp; mktemp; perror; printf; putc; putchar; puts; putw; putwc; putwchar; remove; rewind; __srget; scanf; setbuf; setbuffer; setlinebuf; setvbuf; snprintf; sprintf; sscanf; swprintf; swscanf; tempnam; tmpfile; tmpnam; ungetc; ungetwc; getchar_unlocked; getc_unlocked; putchar_unlocked; putc_unlocked; feof_unlocked; ferror_unlocked; clearerr_unlocked; fileno_unlocked; vasprintf; vfprintf; vfscanf; vfwprintf; vfwscanf; vprintf; vscanf; vsnprintf; vsprintf; vsscanf; vswprintf; vswscanf; vwprintf; vwscanf; __swbuf; wprintf; wscanf; }; FBSD_1.1 { dprintf; getdelim; getline; vdprintf; }; FBSD_1.3 { asprintf_l; fprintf_l; fwprintf_l; printf_l; snprintf_l; sprintf_l; swprintf_l; vasprintf_l; vfprintf_l; vfwprintf_l; vprintf_l; vsnprintf_l; vsprintf_l; vswprintf_l; vwprintf_l; wprintf_l; fgetwc_l; fputwc_l; ungetwc_l; vfwscanf_l; vswscanf_l; fscanf_l; fwscanf_l; scanf_l; sscanf_l; swscanf_l; vfscanf_l; vscanf_l; vsscanf_l; vwscanf_l; wscanf_l; fgetws_l; fputws_l; getwc_l; getwchar_l; putwc_l; putwchar_l; fmemopen; open_memstream; open_wmemstream; mkostemp; mkostemps; }; FBSD_1.4 { fdclose; fopencookie; }; FBSD_1.5 { gets_s; }; +FBSD_1.6 { + mkostempsat; +}; + FBSDprivate_1.0 { _flockfile; _flockfile_debug_stub; _flockfile_debug; _ftrylockfile; _funlockfile; __vfscanf; /* * xprintf support */ __use_xprintf; __lowercase_hex; __uppercase_hex; __printf_flush; __printf_puts; __printf_pad; __printf_out; __xvprintf; register_printf_function; register_printf_render; register_printf_render_std; __printf_arginfo_float; __printf_render_float; __printf_arginfo_hexdump; __printf_render_hexdump; __printf_arginfo_int; __printf_render_int; __printf_arginfo_ptr; __printf_render_ptr; __printf_arginfo_str; __printf_render_str; __printf_arginfo_chr; __printf_render_chr; __printf_arginfo_time; __printf_render_time; __printf_arginfo_vis; __printf_render_vis; }; Index: head/lib/libc/stdio/mktemp.3 =================================================================== --- head/lib/libc/stdio/mktemp.3 (revision 350419) +++ head/lib/libc/stdio/mktemp.3 (revision 350420) @@ -1,326 +1,349 @@ .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)mktemp.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd August 8, 2013 +.Dd July 29, 2019 .Dt MKTEMP 3 .Os .Sh NAME .Nm mktemp .Nd make temporary file name (unique) .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In stdlib.h .Ft char * .Fn mktemp "char *template" .Ft int .Fn mkstemp "char *template" .Ft int .Fn mkostemp "char *template" "int oflags" .Ft int .Fn mkostemps "char *template" "int suffixlen" "int oflags" +.Ft int +.Fn mkostempsat "int dfd" "char *template" "int suffixlen" "int oflags" .Ft char * .Fn mkdtemp "char *template" .In unistd.h .Ft int .Fn mkstemps "char *template" "int suffixlen" .Sh DESCRIPTION The .Fn mktemp function takes the given file name template and overwrites a portion of it to create a file name. This file name is guaranteed not to exist at the time of function invocation and is suitable for use by the application. The template may be any file name with some number of .Ql X Ns s appended to it, for example .Pa /tmp/temp.XXXXXX . The trailing .Ql X Ns s are replaced with a unique alphanumeric combination. The number of unique file names .Fn mktemp can return depends on the number of .Ql X Ns s provided; six .Ql X Ns s will result in .Fn mktemp selecting one of 56800235584 (62 ** 6) possible temporary file names. .Pp The .Fn mkstemp function makes the same replacement to the template and creates the template file, mode 0600, returning a file descriptor opened for reading and writing. This avoids the race between testing for a file's existence and opening it for use. .Pp The .Fn mkostemp function is like .Fn mkstemp but allows specifying additional .Xr open 2 flags (defined in .In fcntl.h ) . The permitted flags are .Dv O_APPEND , .Dv O_DIRECT , .Dv O_SHLOCK , .Dv O_EXLOCK , .Dv O_SYNC and .Dv O_CLOEXEC . .Pp The .Fn mkstemps and .Fn mkostemps functions act the same as .Fn mkstemp and .Fn mkostemp respectively, except they permit a suffix to exist in the template. The template should be of the form .Pa /tmp/tmpXXXXXXsuffix . The .Fn mkstemps and .Fn mkostemps function are told the length of the suffix string. .Pp The +.Fn mkostempsat +function acts the same as +.Fn mkostemps +but takes an additional directory descriptor as a parameter. +The temporary file is created relative to the corresponding +directory, or to the current working directory if the special +value +.Dv AT_FDCWD +is specified. +If the template path is an absolute path, the +.Fa dfd +parameter is ignored and the behavior is identical to +.Fn mkostemps . +.Pp +The .Fn mkdtemp function makes the same replacement to the template as in .Fn mktemp and creates the template directory, mode 0700. .Sh RETURN VALUES The .Fn mktemp and .Fn mkdtemp functions return a pointer to the template on success and .Dv NULL on failure. The .Fn mkstemp , .Fn mkostemp .Fn mkstemps and .Fn mkostemps functions return \-1 if no suitable file could be created. If either call fails an error code is placed in the global variable .Va errno . .Sh ERRORS The .Fn mkstemp , .Fn mkostemp , .Fn mkstemps , .Fn mkostemps and .Fn mkdtemp functions may set .Va errno to one of the following values: .Bl -tag -width Er .It Bq Er ENOTDIR The pathname portion of the template is not an existing directory. .El .Pp The .Fn mkostemp and .Fn mkostemps functions may also set .Va errno to the following value: .Bl -tag -width Er .It Bq Er EINVAL The .Fa oflags argument is invalid. .El .Pp The .Fn mkstemp , .Fn mkostemp , .Fn mkstemps , .Fn mkostemps and .Fn mkdtemp functions may also set .Va errno to any value specified by the .Xr stat 2 function. .Pp The .Fn mkstemp , .Fn mkostemp , .Fn mkstemps and .Fn mkostemps functions may also set .Va errno to any value specified by the .Xr open 2 function. .Pp The .Fn mkdtemp function may also set .Va errno to any value specified by the .Xr mkdir 2 function. .Sh NOTES A common problem that results in a core dump is that the programmer passes in a read-only string to .Fn mktemp , .Fn mkstemp , .Fn mkstemps or .Fn mkdtemp . This is common with programs that were developed before .St -isoC compilers were common. For example, calling .Fn mkstemp with an argument of .Qq /tmp/tempfile.XXXXXX will result in a core dump due to .Fn mkstemp attempting to modify the string constant that was given. .Pp The .Fn mkdtemp , .Fn mkstemp and .Fn mktemp function prototypes are also available from .In unistd.h . .Sh SEE ALSO .Xr chmod 2 , .Xr getpid 2 , .Xr mkdir 2 , .Xr open 2 , .Xr stat 2 .Sh STANDARDS The .Fn mkstemp and .Fn mkdtemp functions are expected to conform to .St -p1003.1-2008 . The .Fn mktemp function is expected to conform to .St -p1003.1-2001 and is not specified by .St -p1003.1-2008 . The .Fn mkostemp , -.Fn mkstemps -and +.Fn mkstemps , .Fn mkostemps +and +.Fn mkostempsat functions do not conform to any standard. .Sh HISTORY A .Fn mktemp function appeared in .At v7 . The .Fn mkstemp function appeared in .Bx 4.4 . The .Fn mkdtemp function first appeared in .Ox 2.2 , and later in .Fx 3.2 . The .Fn mkstemps function first appeared in .Ox 2.4 , and later in .Fx 3.4 . The .Fn mkostemp and .Fn mkostemps functions appeared in .Fx 10.0 . +The +.Fn mkostempsat +function appeared in +.Fx 13.0 . .Sh BUGS This family of functions produces filenames which can be guessed, though the risk is minimized when large numbers of .Ql X Ns s are used to increase the number of possible temporary filenames. This makes the race in .Fn mktemp , between testing for a file's existence (in the .Fn mktemp function call) and opening it for use (later in the user application) particularly dangerous from a security perspective. Whenever it is possible, -.Fn mkstemp -or +.Fn mkstemp , .Fn mkostemp -should be used instead, since it does not have the race condition. +or +.Fn mkostempsat +should be used instead, since they do not have the race condition. If .Fn mkstemp cannot be used, the filename created by .Fn mktemp should be created using the .Dv O_EXCL flag to .Xr open 2 and the return status of the call should be tested for failure. This will ensure that the program does not continue blindly in the event that an attacker has already created the file with the intention of manipulating or reading its contents. Index: head/lib/libc/stdio/mktemp.c =================================================================== --- head/lib/libc/stdio/mktemp.c (revision 350419) +++ head/lib/libc/stdio/mktemp.c (revision 350420) @@ -1,212 +1,220 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include #include #include "un-namespace.h" char *_mktemp(char *); -static int _gettemp(char *, int *, int, int, int); +static int _gettemp(int, char *, int *, int, int, int); static const unsigned char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; int +mkostempsat(int dfd, char *path, int slen, int oflags) +{ + int fd; + + return (_gettemp(dfd, path, &fd, 0, slen, oflags) ? fd : -1); +} + +int mkostemps(char *path, int slen, int oflags) { int fd; - return (_gettemp(path, &fd, 0, slen, oflags) ? fd : -1); + return (_gettemp(AT_FDCWD, path, &fd, 0, slen, oflags) ? fd : -1); } int mkstemps(char *path, int slen) { int fd; - return (_gettemp(path, &fd, 0, slen, 0) ? fd : -1); + return (_gettemp(AT_FDCWD, path, &fd, 0, slen, 0) ? fd : -1); } int mkostemp(char *path, int oflags) { int fd; - return (_gettemp(path, &fd, 0, 0, oflags) ? fd : -1); + return (_gettemp(AT_FDCWD, path, &fd, 0, 0, oflags) ? fd : -1); } int mkstemp(char *path) { int fd; - return (_gettemp(path, &fd, 0, 0, 0) ? fd : -1); + return (_gettemp(AT_FDCWD, path, &fd, 0, 0, 0) ? fd : -1); } char * mkdtemp(char *path) { - return (_gettemp(path, (int *)NULL, 1, 0, 0) ? path : (char *)NULL); + return (_gettemp(AT_FDCWD, path, (int *)NULL, 1, 0, 0) ? path : (char *)NULL); } char * _mktemp(char *path) { - return (_gettemp(path, (int *)NULL, 0, 0, 0) ? path : (char *)NULL); + return (_gettemp(AT_FDCWD, path, (int *)NULL, 0, 0, 0) ? path : (char *)NULL); } __warn_references(mktemp, "warning: mktemp() possibly used unsafely; consider using mkstemp()"); char * mktemp(char *path) { return (_mktemp(path)); } static int -_gettemp(char *path, int *doopen, int domkdir, int slen, int oflags) +_gettemp(int dfd, char *path, int *doopen, int domkdir, int slen, int oflags) { char *start, *trv, *suffp, *carryp; char *pad; struct stat sbuf; int rval; uint32_t rand; char carrybuf[MAXPATHLEN]; if ((doopen != NULL && domkdir) || slen < 0 || (oflags & ~(O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC | O_CLOEXEC)) != 0) { errno = EINVAL; return (0); } for (trv = path; *trv != '\0'; ++trv) ; if (trv - path >= MAXPATHLEN) { errno = ENAMETOOLONG; return (0); } trv -= slen; suffp = trv; --trv; if (trv < path || NULL != strchr(suffp, '/')) { errno = EINVAL; return (0); } /* Fill space with random characters */ while (trv >= path && *trv == 'X') { rand = arc4random_uniform(sizeof(padchar) - 1); *trv-- = padchar[rand]; } start = trv + 1; /* save first combination of random characters */ memcpy(carrybuf, start, suffp - start); /* * check the target directory. */ if (doopen != NULL || domkdir) { for (; trv > path; --trv) { if (*trv == '/') { *trv = '\0'; - rval = stat(path, &sbuf); + rval = fstatat(dfd, path, &sbuf, 0); *trv = '/'; if (rval != 0) return (0); if (!S_ISDIR(sbuf.st_mode)) { errno = ENOTDIR; return (0); } break; } } } + oflags |= O_CREAT | O_EXCL | O_RDWR; for (;;) { if (doopen) { - if ((*doopen = - _open(path, O_CREAT|O_EXCL|O_RDWR|oflags, 0600)) >= - 0) + *doopen = _openat(dfd, path, oflags, 0600); + if (*doopen >= 0) return (1); if (errno != EEXIST) return (0); } else if (domkdir) { if (mkdir(path, 0700) == 0) return (1); if (errno != EEXIST) return (0); } else if (lstat(path, &sbuf)) return (errno == ENOENT); /* If we have a collision, cycle through the space of filenames */ for (trv = start, carryp = carrybuf;;) { /* have we tried all possible permutations? */ if (trv == suffp) return (0); /* yes - exit with EEXIST */ pad = strchr(padchar, *trv); if (pad == NULL) { /* this should never happen */ errno = EIO; return (0); } /* increment character */ *trv = (*++pad == '\0') ? padchar[0] : *pad; /* carry to next position? */ if (*trv == *carryp) { /* increment position and loop */ ++trv; ++carryp; } else { /* try with new name */ break; } } } /*NOTREACHED*/ }