This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2219ffa1e843b9f813cd4bc34197f93a625fcb8e Author: Marco Casaroli <[email protected]> AuthorDate: Tue Oct 20 19:32:48 2026 +0200 libs/libc/stdlib: Add mkostemp(), mkstemps() and mkostemps(). <stdlib.h> mapped mkostemp64(), mkstemps64() and mkostemps64() to mkostemp(), mkstemps() and mkostemps(), but libc did not have them. mkostemp() is in POSIX.1-2024; mkstemps() and mkostemps() are in the other C libraries. A program that uses them did not link. mkostemps() replaces the X's before a suffix of suffixlen characters, then creates the file with O_EXCL and the extra open() flags. The X's are made with mktemp(), with the suffix cut off while it runs. If the file exists (another process made it in the meantime), it tries the next name. mkostemp(), mkstemps() and mkstemp() call it. So mkstemp() now also tries again when the file exists, instead of failing. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- include/stdlib.h | 3 + libs/libc/libc.csv | 3 + libs/libc/stdlib/lib_mkstemp.c | 123 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 118 insertions(+), 11 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index 60de89e5af4..92ffb7a9161 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -280,6 +280,9 @@ lldiv_t lldiv(long long number, long long denom); FAR char *mktemp(FAR char *path_template); int mkstemp(FAR char *path_template); +int mkostemp(FAR char *path_template, int flags); +int mkstemps(FAR char *path_template, int suffixlen); +int mkostemps(FAR char *path_template, int suffixlen, int flags); FAR char *mkdtemp(FAR char *path_template); /* Sorting */ diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv index ad29135ee64..45c5b7d4e26 100644 --- a/libs/libc/libc.csv +++ b/libs/libc/libc.csv @@ -191,7 +191,10 @@ "memset","string.h","","FAR void *","FAR void *","int","size_t" "mkdtemp","stdlib.h","","FAR char *","FAR char *" "mkfifo","sys/stat.h","defined(CONFIG_PIPES) && CONFIG_DEV_FIFO_SIZE > 0","int","FAR const char *","mode_t" +"mkostemp","stdlib.h","","int","FAR char *","int" +"mkostemps","stdlib.h","","int","FAR char *","int","int" "mkstemp","stdlib.h","","int","FAR char *" +"mkstemps","stdlib.h","","int","FAR char *","int" "mktemp","stdlib.h","","FAR char *","FAR char *" "mktime","time.h","","time_t","FAR struct tm *" "nice","unistd.h","","int","int" diff --git a/libs/libc/stdlib/lib_mkstemp.c b/libs/libc/stdlib/lib_mkstemp.c index 6f65bfed25d..52e05854921 100644 --- a/libs/libc/stdlib/lib_mkstemp.c +++ b/libs/libc/stdlib/lib_mkstemp.c @@ -27,14 +27,123 @@ #include <nuttx/config.h> #include <nuttx/compiler.h> -#include <unistd.h> -#include <stdlib.h> +#include <errno.h> #include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* mktemp() replaces at most six X's */ + +#define MKSTEMP_MAXXS 6 + +/* The number of names that are tried when the file exists */ + +#define MKSTEMP_RETRIES 238328 /* 62**3 */ /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: mkostemps + * + * Description: + * Replace the X's (up to six) before the last suffixlen characters of + * path_template with characters that make the name unique, then create + * and open the file for reading and writing. If another process created + * a file of that name in the meantime, try a new name. + * + * Input Parameters: + * path_template - The name of the file to create, with the X's. + * suffixlen - The number of characters after the X's. + * flags - More flags for open(), such as O_CLOEXEC or O_APPEND. + * + * Returned Value: + * An open file descriptor on success. Otherwise -1 is returned and + * errno is set. + * + ****************************************************************************/ + +int mkostemps(FAR char *path_template, int suffixlen, int flags) +{ + char suffix0; + size_t len = strlen(path_template); + size_t end; + size_t xlen; + int retries; + int fd; + + if (suffixlen < 0 || (size_t)suffixlen > len) + { + set_errno(EINVAL); + return -1; + } + + /* Count the X's before the suffix */ + + end = len - suffixlen; + for (xlen = 0; xlen < MKSTEMP_MAXXS && xlen < end && + path_template[end - xlen - 1] == 'X'; xlen++); + + for (retries = 0; retries < MKSTEMP_RETRIES; retries++) + { + /* mktemp() replaces the X's at the end of the string: cut the suffix + * off while it runs. + */ + + memset(&path_template[end - xlen], 'X', xlen); + suffix0 = path_template[end]; + path_template[end] = '\0'; + if (mktemp(path_template) == NULL) + { + path_template[end] = suffix0; + return -1; + } + + path_template[end] = suffix0; + + fd = open(path_template, O_RDWR | O_CREAT | O_EXCL | + (flags & ~O_ACCMODE), 0600); + if (fd >= 0 || get_errno() != EEXIST || xlen == 0) + { + return fd; + } + } + + return -1; +} + +/**************************************************************************** + * Name: mkostemp + * + * Description: + * As mkstemp(), with more flags for open(). + * + ****************************************************************************/ + +int mkostemp(FAR char *path_template, int flags) +{ + return mkostemps(path_template, 0, flags); +} + +/**************************************************************************** + * Name: mkstemps + * + * Description: + * As mkstemp(), with suffixlen characters after the X's. + * + ****************************************************************************/ + +int mkstemps(FAR char *path_template, int suffixlen) +{ + return mkostemps(path_template, suffixlen, 0); +} + /**************************************************************************** * Name: mkstemp * @@ -63,13 +172,5 @@ int mkstemp(FAR char *path_template) { - FAR char *path = mktemp(path_template); - int ret = ERROR; - - if (path) - { - ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); - } - - return ret; + return mkostemps(path_template, 0, 0); }
