diff --git a/AUTHORS b/AUTHORS index cc47ce3d62..58b03ce2de 100644 --- a/AUTHORS +++ b/AUTHORS @@ -47,6 +47,7 @@ Jérôme Pinot Mike Blumenkrantz Patryk Kaczmarek Igor Murzov +Vladislav Brovko Eet --- diff --git a/src/lib/eina/eina_file.h b/src/lib/eina/eina_file.h index d0accf338c..959f089fda 100644 --- a/src/lib/eina/eina_file.h +++ b/src/lib/eina/eina_file.h @@ -323,7 +323,40 @@ 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_mkstemp(const char *filename, Eina_Tmpstr **path); +/** + * @brief Generate and create a uniquely named temporary file from template. + * Generated file is opened with the open(2) O_EXCL flag. + * + * @param [in] templatename is a string. The last six characters of templatename must be XXXXXX. + * @param [out] path Where to put the name of the created file. If not NULL + * should 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 errno is set appropriately. + * + * This function calls mkstemp, generates a unique temporary filename + * from template, creates and opens the file, and returns an open file + * descriptor for the file. + * + * @see eina_file_mkdtemp() + * @since 1.8 + */ +EAPI int eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path); + +/** + * @brief Generate and create a uniquely named temporary directory from template. + * + * @param [in] templatename is a string. The last six characters of templatename must be XXXXXX. + * @param [out] path Where to put the name of the created directory. If not NULL + * should be released by eina_tmpstr_del. + * @return On success @c EINA_TRUE is returned, On error @c EINA_FALSE is returned, + * in which case errno is set appropriately. + * + * This function calls mkdtemp. The directory is then created with permissions 0700. + * + * @see eina_file_mkstemp() + * @since 1.8 + */ +EAPI Eina_Bool eina_file_mkdtemp(const char *templatename, Eina_Tmpstr **path); /** * @brief Get 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 e17b185725..475f89da5a 100644 --- a/src/lib/eina/eina_file_common.c +++ b/src/lib/eina/eina_file_common.c @@ -571,7 +571,7 @@ eina_file_copy(const char *src, const char *dst, Eina_File_Copy_Flags flags, Ein } EAPI int -eina_file_mkstemp(const char *filename, Eina_Tmpstr **path) +eina_file_mkstemp(const char *templatename, Eina_Tmpstr **path) { char buffer[PATH_MAX]; const char *tmpdir; @@ -584,7 +584,7 @@ eina_file_mkstemp(const char *filename, Eina_Tmpstr **path) tmpdir = (char *)evil_tmpdir_get(); #endif /* ! HAVE_EVIL */ - snprintf(buffer, PATH_MAX, "%s/%s", tmpdir, filename); + snprintf(buffer, PATH_MAX, "%s/%s", tmpdir, templatename); fd = mkstemp(buffer); if (path) *path = eina_tmpstr_add(buffer); @@ -593,3 +593,27 @@ eina_file_mkstemp(const char *filename, Eina_Tmpstr **path) return fd; } + +EAPI Eina_Bool +eina_file_mkdtemp(const char *templatename, Eina_Tmpstr **path) +{ + char buffer[PATH_MAX]; + const char *tmpdir; + char *tmpdirname; + +#ifndef HAVE_EVIL + tmpdir = getenv("TMPDIR"); + if (!tmpdir) tmpdir = "/tmp"; +#else + tmpdir = (char *)evil_tmpdir_get(); +#endif /* ! HAVE_EVIL */ + + snprintf(buffer, PATH_MAX, "%s/%s", tmpdir, templatename); + + tmpdirname = mkdtemp(buffer); + if (path) *path = eina_tmpstr_add(buffer); + if (tmpdirname == NULL) + return EINA_FALSE; + + return EINA_TRUE; +} diff --git a/src/tests/eina/eina_test_file.c b/src/tests/eina/eina_test_file.c index 60b3a3c361..a8bde8351b 100644 --- a/src/tests/eina/eina_test_file.c +++ b/src/tests/eina/eina_test_file.c @@ -23,11 +23,14 @@ #include #include #include +#include #include "eina_suite.h" #include "Eina.h" #include "eina_safety_checks.h" +static int default_dir_rights = 0777; + #ifdef EINA_SAFETY_CHECKS struct log_ctx { const char *msg; @@ -134,9 +137,128 @@ START_TEST(eina_file_split_simple) } END_TEST +Eina_Tmpstr* +get_full_path(const char* tmpdirname, const char* filename) +{ + char full_path[PATH_MAX] = ""; + eina_str_join(full_path, sizeof(full_path), '/', tmpdirname, filename); + return eina_tmpstr_add(full_path); +} + +Eina_Tmpstr* +get_eina_test_file_tmp_dir() +{ + Eina_Tmpstr *tmp_dir; + + Eina_Bool created = eina_file_mkdtemp("EinaFileTestXXXXXX", &tmp_dir); + + if (!created) + { + return NULL; + } + + return tmp_dir; +} + +START_TEST(eina_file_direct_ls_simple) +{ + eina_init(); + + const char *good_dirs[] = + { + "eina_file_direct_ls_simple_dir", + "a.", + "$a$b", + "~$a@:-*$b!{}" + }; + const int good_dirs_count = sizeof(good_dirs) / sizeof(const char *); + Eina_Tmpstr *test_dirname = get_eina_test_file_tmp_dir(); + fail_if(test_dirname == NULL); + + for (int i = 0; i != good_dirs_count; ++i) + { + Eina_Tmpstr *dirname = get_full_path(test_dirname, good_dirs[i]); + // clean old test directories + rmdir(dirname); + fail_if(mkdir(dirname, default_dir_rights) != 0); + + Eina_File_Direct_Info *dir_info; + Eina_Iterator *it = eina_file_direct_ls(test_dirname); + Eina_Bool found_dir = EINA_FALSE; + + while (eina_iterator_next(it, (void **)&dir_info)) + { + if (!strcmp(dir_info->path, dirname)) + { + found_dir = EINA_TRUE; + } + } + + eina_iterator_free(it); + + fail_if(!found_dir); + fail_if(rmdir(dirname) != 0); + + eina_tmpstr_del(dirname); + } + fail_if(rmdir(test_dirname) != 0); + eina_tmpstr_del(test_dirname); + eina_shutdown(); +} +END_TEST + +START_TEST(eina_file_ls_simple) +{ + eina_init(); + + const char *good_dirs[] = + { + "eina_file_ls_simple_dir", + "b.", + "$b$a", + "~$b@:-*$a!{}" + }; + const int good_dirs_count = sizeof(good_dirs) / sizeof(const char *); + Eina_Tmpstr *test_dirname = get_eina_test_file_tmp_dir(); + fail_if(test_dirname == NULL); + + for (int i = 0; i != good_dirs_count; ++i) + { + Eina_Tmpstr *dirname = get_full_path(test_dirname, good_dirs[i]); + // clean old test directories + rmdir(dirname); + fail_if(mkdir(dirname, default_dir_rights) != 0); + + char *filename; + Eina_Iterator *it = eina_file_ls(test_dirname); + Eina_Bool found_dir = EINA_FALSE; + + while (eina_iterator_next(it, (void **)&filename)) + { + if (!strcmp(filename, dirname)) + { + found_dir = EINA_TRUE; + } + } + + eina_iterator_free(it); + + fail_if(!found_dir); + fail_if(rmdir(dirname) != 0); + + eina_tmpstr_del(dirname); + } + fail_if(rmdir(test_dirname) != 0); + eina_tmpstr_del(test_dirname); + eina_shutdown(); +} +END_TEST + void eina_test_file(TCase *tc) { tcase_add_test(tc, eina_file_split_simple); + tcase_add_test(tc, eina_file_direct_ls_simple); + tcase_add_test(tc, eina_file_ls_simple); }