From e472f97d9670207896635985cebd3119fcb21b89 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 19 Jan 2016 11:50:54 +0900 Subject: [PATCH] Eina: Fix eina_file_mk[ds]temp when a path is passed If the template is a path, mkstemp and mkdtemp would fail miserably as they would try to create a file inside /run/user/1000//path/to/file.XXXXXX even if the path did not exist. This patch fixes that by creating temp files inside the sys temp dir iif the templatename is just a basic name without path separator. @fix --- src/lib/eina/eina_file.h | 35 +++++++++++++++------- src/lib/eina/eina_file_common.c | 52 ++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/lib/eina/eina_file.h b/src/lib/eina/eina_file.h index 4235f1c849..3e20bd040e 100644 --- a/src/lib/eina/eina_file.h +++ b/src/lib/eina/eina_file.h @@ -353,14 +353,14 @@ EAPI Eina_Iterator *eina_file_stat_ls(const char *dir) EINA_WARN_UNUSED_RESULT E EAPI int eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2, 3); /** - * @brief Generates and creates a uniquely named temporary file from template. - * Generated file is opened with the open(2) O_EXCL flag. + * @brief Generates and creates a uniquely named temporary file from a template name. + * The generated file is opened with the open(2) @c O_EXCL flag. * * @param[in] templatename This is a string. It must contain the six characters 'XXXXXX' * at the end or directly followed by an extension as in * 'prefixXXXXXX.ext'. - * @param[out] path Where to put the name of the created file. If not @c NULL - * should be released by eina_tmpstr_del(). + * @param[out] path The path to the created temporary file, or @c NULL in case of failure. + * It must be released by eina_tmpstr_del(). * @return On success @c file descriptor of the temporary file is returned, * On error @c -1 is returned, in which case @c errno is set appropriately. * @@ -371,28 +371,43 @@ EAPI int eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Sta * @note If a filename extension was specified in @p templatename, then the new @p path * will also contain this extension (since 1.10). * + * @note If the @p templatename is a simple file name (no relative or absolute + * path to another directory), then a temporary file will be created inside + * the system temporary directory (@see eina_environment_tmp_get()). If the + * @p templatename contains a directory separator ('/', or '\\' on Windows) + * then the file will be created inside this directory, which must exist and + * be writable. Use ./filename.XXXXXX to create files in the current + * working directory. (since 1.17) + * * @see eina_file_mkdtemp() * @since 1.8 */ -EAPI int eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path); +EAPI int eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path) EINA_ARG_NONNULL(1); /** - * @brief Generates and creates a uniquely named temporary directory from template. + * @brief Generates and creates a uniquely named temporary directory from a template name. * * @param[in] templatename This is a string. The last six characters of @p templatename * must be XXXXXX. - * @param[out] path Where to put the name of the created directory. If not @c NULL - * should be released by eina_tmpstr_del(). + * @param[out] path The path to the created temporary directory, or @c NULL in case of failure. + * It must be released by eina_tmpstr_del(). * @return On success @c EINA_TRUE is returned, On error @c EINA_FALSE is returned, * in which case @c errno is set appropriately. * * @details This function calls mkdtemp(). The directory is then created with - * permissions 0700. + * permissions 0700. + * + * @note If the @p templatename is a simple directory name (no relative or absolute + * path to another directory), then a temporary directory will be created inside + * the system temporary directory (@see eina_environment_tmp_get()). If the + * @p templatename contains a directory separator ('/', or '\\' on Windows) + * then the temporary directory will be created inside that other directory, + * which must exist and be writable. (since 1.17) * * @see eina_file_mkstemp() * @since 1.8 */ -EAPI Eina_Bool eina_file_mkdtemp(const char *templatename, Eina_Tmpstr **path); +EAPI Eina_Bool eina_file_mkdtemp(const char *templatename, Eina_Tmpstr **path) EINA_ARG_NONNULL(1,2); /** * @brief Gets an iterator to list the content of a directory, with direct diff --git a/src/lib/eina/eina_file_common.c b/src/lib/eina/eina_file_common.c index 57d9b99d41..8314f009a4 100644 --- a/src/lib/eina/eina_file_common.c +++ b/src/lib/eina/eina_file_common.c @@ -913,14 +913,27 @@ EAPI int eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path) { char buffer[PATH_MAX]; - const char *XXXXXX = NULL; + const char *XXXXXX = NULL, *sep; int fd, len; #ifndef _WIN32 mode_t old_umask; #endif - len = eina_file_path_join(buffer, sizeof(buffer), - eina_environment_tmp_get(), templatename); + EINA_SAFETY_ON_NULL_RETURN_VAL(templatename, -1); + + sep = strchr(templatename, '/'); +#ifdef _WIN32 + if (!sep) sep = strchr(templatename, '\\'); +#endif + if (sep) + { + len = eina_strlcpy(buffer, templatename, sizeof(buffer)); + } + else + { + len = eina_file_path_join(buffer, sizeof(buffer), + eina_environment_tmp_get(), templatename); + } /* * Unix: @@ -945,10 +958,13 @@ eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path) umask(old_umask); #endif - if (path) *path = eina_tmpstr_add(buffer); if (fd < 0) - return -1; + { + if (path) *path = NULL; + return -1; + } + if (path) *path = eina_tmpstr_add(buffer); return fd; } @@ -956,16 +972,32 @@ EAPI Eina_Bool eina_file_mkdtemp(const char *templatename, Eina_Tmpstr **path) { char buffer[PATH_MAX]; - char *tmpdirname; + char *tmpdirname, *sep; - eina_file_path_join(buffer, sizeof(buffer), - eina_environment_tmp_get(), templatename); + EINA_SAFETY_ON_NULL_RETURN_VAL(templatename, EINA_FALSE); + + sep = strchr(templatename, '/'); +#ifdef _WIN32 + if (!sep) sep = strchr(templatename, '\\'); +#endif + if (sep) + { + eina_strlcpy(buffer, templatename, sizeof(buffer)); + } + else + { + eina_file_path_join(buffer, sizeof(buffer), + eina_environment_tmp_get(), templatename); + } tmpdirname = mkdtemp(buffer); - if (path) *path = eina_tmpstr_add(buffer); if (tmpdirname == NULL) - return EINA_FALSE; + { + if (path) *path = NULL; + return EINA_FALSE; + } + if (path) *path = eina_tmpstr_add(tmpdirname); return EINA_TRUE; }