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
This commit is contained in:
Jean-Philippe Andre 2016-01-19 11:50:54 +09:00
parent 210b3e6c62
commit e472f97d96
2 changed files with 67 additions and 20 deletions

View File

@ -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); 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. * @brief Generates and creates a uniquely named temporary file from a template name.
* Generated file is opened with the open(2) O_EXCL flag. * 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' * @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 * at the end or directly followed by an extension as in
* 'prefixXXXXXX.ext'. * 'prefixXXXXXX.ext'.
* @param[out] path Where to put the name of the created file. If not @c NULL * @param[out] path The path to the created temporary file, or @c NULL in case of failure.
* should be released by eina_tmpstr_del(). * It must be released by eina_tmpstr_del().
* @return On success @c file descriptor of the temporary file is returned, * @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. * 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 * @note If a filename extension was specified in @p templatename, then the new @p path
* will also contain this extension (since 1.10). * 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() * @see eina_file_mkdtemp()
* @since 1.8 * @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 * @param[in] templatename This is a string. The last six characters of @p templatename
* must be XXXXXX. * must be XXXXXX.
* @param[out] path Where to put the name of the created directory. If not @c NULL * @param[out] path The path to the created temporary directory, or @c NULL in case of failure.
* should be released by eina_tmpstr_del(). * It must be released by eina_tmpstr_del().
* @return On success @c EINA_TRUE is returned, On error @c EINA_FALSE is returned, * @return On success @c EINA_TRUE is returned, On error @c EINA_FALSE is returned,
* in which case @c errno is set appropriately. * in which case @c errno is set appropriately.
* *
* @details This function calls mkdtemp(). The directory is then created with * @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() * @see eina_file_mkstemp()
* @since 1.8 * @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 * @brief Gets an iterator to list the content of a directory, with direct

View File

@ -913,14 +913,27 @@ EAPI int
eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path) eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path)
{ {
char buffer[PATH_MAX]; char buffer[PATH_MAX];
const char *XXXXXX = NULL; const char *XXXXXX = NULL, *sep;
int fd, len; int fd, len;
#ifndef _WIN32 #ifndef _WIN32
mode_t old_umask; mode_t old_umask;
#endif #endif
len = eina_file_path_join(buffer, sizeof(buffer), EINA_SAFETY_ON_NULL_RETURN_VAL(templatename, -1);
eina_environment_tmp_get(), templatename);
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: * Unix:
@ -945,10 +958,13 @@ eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path)
umask(old_umask); umask(old_umask);
#endif #endif
if (path) *path = eina_tmpstr_add(buffer);
if (fd < 0) if (fd < 0)
return -1; {
if (path) *path = NULL;
return -1;
}
if (path) *path = eina_tmpstr_add(buffer);
return fd; return fd;
} }
@ -956,16 +972,32 @@ EAPI Eina_Bool
eina_file_mkdtemp(const char *templatename, Eina_Tmpstr **path) eina_file_mkdtemp(const char *templatename, Eina_Tmpstr **path)
{ {
char buffer[PATH_MAX]; char buffer[PATH_MAX];
char *tmpdirname; char *tmpdirname, *sep;
eina_file_path_join(buffer, sizeof(buffer), EINA_SAFETY_ON_NULL_RETURN_VAL(templatename, EINA_FALSE);
eina_environment_tmp_get(), templatename);
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); tmpdirname = mkdtemp(buffer);
if (path) *path = eina_tmpstr_add(buffer);
if (tmpdirname == NULL) if (tmpdirname == NULL)
return EINA_FALSE; {
if (path) *path = NULL;
return EINA_FALSE;
}
if (path) *path = eina_tmpstr_add(tmpdirname);
return EINA_TRUE; return EINA_TRUE;
} }