diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2021-04-18 21:23:14 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2021-05-11 21:06:29 +0200 |
commit | 269576eea2c20033dc3a704847810a0b1bc55440 (patch) | |
tree | 1ad1dfa82a6dceb9065f76ec1c7cdf09a5ca7e4f | |
parent | 9eecad496db62159376bda0cf2789690039872ce (diff) | |
download | weechat-269576eea2c20033dc3a704847810a0b1bc55440.zip |
core: move directory/file functions from wee-util.c to wee-dir.c (issue #1285)
-rw-r--r-- | po/POTFILES.in | 2 | ||||
-rw-r--r-- | po/srcfiles.cmake | 2 | ||||
-rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/core/Makefile.am | 2 | ||||
-rw-r--r-- | src/core/wee-command.c | 3 | ||||
-rw-r--r-- | src/core/wee-completion.c | 20 | ||||
-rw-r--r-- | src/core/wee-dir.c | 514 | ||||
-rw-r--r-- | src/core/wee-dir.h | 37 | ||||
-rw-r--r-- | src/core/wee-signal.c | 1 | ||||
-rw-r--r-- | src/core/wee-upgrade.c | 7 | ||||
-rw-r--r-- | src/core/wee-util.c | 479 | ||||
-rw-r--r-- | src/core/wee-util.h | 15 | ||||
-rw-r--r-- | src/core/weechat.c | 7 | ||||
-rw-r--r-- | src/plugins/plugin.c | 23 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/tests.cpp | 5 | ||||
-rw-r--r-- | tests/unit/core/test-core-dir.cpp | 119 | ||||
-rw-r--r-- | tests/unit/core/test-core-util.cpp | 83 |
19 files changed, 715 insertions, 607 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in index 9be72f0fc..393f196b1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -55,6 +55,8 @@ ./src/core/wee-crypto.h ./src/core/wee-debug.c ./src/core/wee-debug.h +./src/core/wee-dir.c +./src/core/wee-dir.h ./src/core/wee-eval.c ./src/core/wee-eval.h ./src/core/wee-hook.c diff --git a/po/srcfiles.cmake b/po/srcfiles.cmake index 8313afe3b..33e675694 100644 --- a/po/srcfiles.cmake +++ b/po/srcfiles.cmake @@ -56,6 +56,8 @@ SET(WEECHAT_SOURCES ./src/core/wee-crypto.h ./src/core/wee-debug.c ./src/core/wee-debug.h +./src/core/wee-dir.c +./src/core/wee-dir.h ./src/core/wee-eval.c ./src/core/wee-eval.h ./src/core/wee-hook.c diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index bbeaa9ce4..6b02d9404 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -30,6 +30,7 @@ set(LIB_CORE_SRC wee-config-file.c wee-config-file.h wee-crypto.c wee-crypto.h wee-debug.c wee-debug.h + wee-dir.c wee-dir.h wee-eval.c wee-eval.h wee-hashtable.c wee-hashtable.h wee-hdata.c wee-hdata.h diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 29f7b2c61..0dcdc2812 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -41,6 +41,8 @@ lib_weechat_core_a_SOURCES = weechat.c \ wee-crypto.h \ wee-debug.c \ wee-debug.h \ + wee-dir.c \ + wee-dir.h \ wee-eval.c \ wee-eval.h \ wee-hashtable.c \ diff --git a/src/core/wee-command.c b/src/core/wee-command.c index cd85e8173..fba0743fb 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -46,6 +46,7 @@ #include "wee-config.h" #include "wee-config-file.h" #include "wee-debug.h" +#include "wee-dir.h" #include "wee-eval.h" #include "wee-hashtable.h" #include "wee-hdata.h" @@ -4755,7 +4756,7 @@ COMMAND_CALLBACK(plugin) | WEECHAT_STRING_SPLIT_COLLAPSE_SEPS, 0, &plugin_argc); } - full_name = util_search_full_lib_name (argv[2], "plugins"); + full_name = dir_search_full_lib_name (argv[2], "plugins"); plugin_load (full_name, 1, plugin_argc, plugin_argv); if (full_name) free (full_name); diff --git a/src/core/wee-completion.c b/src/core/wee-completion.c index a13c2c3f3..7f210dbd4 100644 --- a/src/core/wee-completion.c +++ b/src/core/wee-completion.c @@ -36,6 +36,7 @@ #include "weechat.h" #include "wee-arraylist.h" #include "wee-config.h" +#include "wee-dir.h" #include "wee-eval.h" #include "wee-hashtable.h" #include "wee-hook.h" @@ -43,7 +44,6 @@ #include "wee-proxy.h" #include "wee-secure.h" #include "wee-string.h" -#include "wee-util.h" #include "../gui/gui-completion.h" #include "../gui/gui-bar.h" #include "../gui/gui-bar-window.h" @@ -1000,9 +1000,9 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, if (dir_name) { snprintf (dir_name, length, "%s/plugins", extra_libdir); - util_exec_on_files (dir_name, 1, 0, - &completion_list_add_plugins_installed_exec_cb, - completion); + dir_exec_on_files (dir_name, 1, 0, + &completion_list_add_plugins_installed_exec_cb, + completion); free (dir_name); } } @@ -1015,9 +1015,9 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, NULL, NULL, NULL); if (plugin_path) { - util_exec_on_files (plugin_path, 1, 0, - &completion_list_add_plugins_installed_exec_cb, - completion); + dir_exec_on_files (plugin_path, 1, 0, + &completion_list_add_plugins_installed_exec_cb, + completion); free (plugin_path); } } @@ -1028,9 +1028,9 @@ completion_list_add_plugins_installed_cb (const void *pointer, void *data, if (dir_name) { snprintf (dir_name, length, "%s/plugins", WEECHAT_LIBDIR); - util_exec_on_files (dir_name, 1, 0, - &completion_list_add_plugins_installed_exec_cb, - completion); + dir_exec_on_files (dir_name, 1, 0, + &completion_list_add_plugins_installed_exec_cb, + completion); free (dir_name); } diff --git a/src/core/wee-dir.c b/src/core/wee-dir.c new file mode 100644 index 000000000..2eb3bd7d7 --- /dev/null +++ b/src/core/wee-dir.c @@ -0,0 +1,514 @@ +/* + * wee-dir.c - directory/file functions + * + * Copyright (C) 2003-2021 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +/* for P_tmpdir in stdio.h */ +#ifndef __USE_XOPEN +#define __USE_XOPEN +#endif + +/* for nftw() */ +#define _XOPEN_SOURCE 700 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> +#include <ftw.h> + +#include "weechat.h" +#include "wee-config.h" +#include "wee-string.h" + + +/* + * Returns the path to a temporary directory, the first valid directory in + * this list: + * - content of environment variable "TMPDIR" + * - P_tmpdir (from stdio.h) + * - content of environment variable "HOME" (user home directory) + * - "." (current directory) + */ + +char * +dir_get_temp_dir() +{ + char *tmpdir; + struct stat buf; + int rc; + + /* get directory from $TMPDIR */ + tmpdir = getenv ("TMPDIR"); + if (tmpdir && tmpdir[0]) + { + rc = stat (tmpdir, &buf); + if ((rc == 0) && S_ISDIR(buf.st_mode)) + return strdup (tmpdir); + } + + /* get directory from P_tmpdir */ + rc = stat (P_tmpdir, &buf); + if ((rc == 0) && S_ISDIR(buf.st_mode)) + return strdup (P_tmpdir); + + /* get directory from $HOME */ + tmpdir = getenv ("HOME"); + if (tmpdir && tmpdir[0]) + { + rc = stat (tmpdir, &buf); + if ((rc == 0) && S_ISDIR(buf.st_mode)) + return strdup (tmpdir); + } + + /* fallback on current directory */ + return strdup ("."); +} + +/* + * Creates a directory in WeeChat home. + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_mkdir_home (const char *directory, int mode) +{ + char *dir_name; + int dir_length; + + if (!directory) + return 0; + + /* build directory, adding WeeChat home */ + dir_length = strlen (weechat_home) + strlen (directory) + 2; + dir_name = malloc (dir_length); + if (!dir_name) + return 0; + + snprintf (dir_name, dir_length, "%s/%s", weechat_home, directory); + + if (mkdir (dir_name, mode) < 0) + { + if (errno != EEXIST) + { + free (dir_name); + return 0; + } + } + + free (dir_name); + return 1; +} + +/* + * Creates a directory. + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_mkdir (const char *directory, int mode) +{ + if (!directory) + return 0; + + if (mkdir (directory, mode) < 0) + { + if (errno != EEXIST) + return 0; + } + + return 1; +} + +/* + * Creates a directory and makes parent directories as needed. + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_mkdir_parents (const char *directory, int mode) +{ + char *string, *ptr_string, *pos_sep; + struct stat buf; + int rc; + + if (!directory) + return 0; + + string = strdup (directory); + if (!string) + return 0; + + ptr_string = string; + while (ptr_string[0] == DIR_SEPARATOR_CHAR) + { + ptr_string++; + } + + while (ptr_string && ptr_string[0]) + { + pos_sep = strchr (ptr_string, DIR_SEPARATOR_CHAR); + if (pos_sep) + pos_sep[0] = '\0'; + + rc = stat (string, &buf); + if ((rc < 0) || !S_ISDIR(buf.st_mode)) + { + /* try to create directory */ + if (!dir_mkdir (string, mode)) + { + free (string); + return 0; + } + } + + if (pos_sep) + { + pos_sep[0] = DIR_SEPARATOR_CHAR; + ptr_string = pos_sep + 1; + } + else + ptr_string = NULL; + } + + free (string); + + return 1; +} + +/* + * Unlinks a file or directory; callback called by function dir_rmtree(). + * + * Returns the return code of remove(): + * 0: OK + * -1: error + */ + +int +dir_unlink_cb (const char *fpath, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) +{ + /* make C compiler happy */ + (void) sb; + (void) typeflag; + (void) ftwbuf; + + return remove (fpath); +} + +/* + * Removes a directory and all files inside recursively. + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_rmtree (const char *directory) +{ + int rc; + + if (!directory) + return 0; + + rc = nftw (directory, dir_unlink_cb, 64, FTW_DEPTH | FTW_PHYS); + + return (rc == 0) ? 1 : 0; +} + +/* + * Finds files in a directory and executes a function on each file. + */ + +void +dir_exec_on_files (const char *directory, int recurse_subdirs, + int hidden_files, + void (*callback)(void *data, const char *filename), + void *callback_data) +{ + char complete_filename[PATH_MAX]; + DIR *dir; + struct dirent *entry; + struct stat statbuf; + + if (!directory || !callback) + return; + + dir = opendir (directory); + if (dir) + { + while ((entry = readdir (dir))) + { + if (hidden_files || (entry->d_name[0] != '.')) + { + snprintf (complete_filename, sizeof (complete_filename), + "%s/%s", directory, entry->d_name); + lstat (complete_filename, &statbuf); + if (S_ISDIR(statbuf.st_mode)) + { + if (recurse_subdirs + && (strcmp (entry->d_name, ".") != 0) + && (strcmp (entry->d_name, "..") != 0)) + { + dir_exec_on_files (complete_filename, 1, hidden_files, + callback, callback_data); + } + } + else + { + (*callback) (callback_data, complete_filename); + } + } + } + closedir (dir); + } +} + +/* + * Searches for the full name of a WeeChat library with name and extension + * (searches first in WeeChat user's dir, then WeeChat global lib directory). + * + * Returns name of library found, NULL if not found. + * + * Note: result must be freed after use (if not NULL). + */ + +char * +dir_search_full_lib_name_ext (const char *filename, const char *extension, + const char *plugins_dir) +{ + char *name_with_ext, *final_name, *extra_libdir; + int length; + struct stat st; + + length = strlen (filename) + strlen (extension) + 1; + name_with_ext = malloc (length); + if (!name_with_ext) + return NULL; + snprintf (name_with_ext, length, + "%s%s", + filename, + (strchr (filename, '.')) ? "" : extension); + + /* try libdir from environment variable WEECHAT_EXTRA_LIBDIR */ + extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR); + if (extra_libdir && extra_libdir[0]) + { + length = strlen (extra_libdir) + strlen (name_with_ext) + + strlen (plugins_dir) + 16; + final_name = malloc (length); + if (!final_name) + { + free (name_with_ext); + return NULL; + } + snprintf (final_name, length, + "%s%s%s%s%s", + extra_libdir, + DIR_SEPARATOR, + plugins_dir, + DIR_SEPARATOR, + name_with_ext); + if ((stat (final_name, &st) == 0) && (st.st_size > 0)) + { + free (name_with_ext); + return final_name; + } + free (final_name); + } + + /* try WeeChat user's dir */ + length = strlen (weechat_home) + strlen (name_with_ext) + + strlen (plugins_dir) + 16; + final_name = malloc (length); + if (!final_name) + { + free (name_with_ext); + return NULL; + } + snprintf (final_name, length, + "%s%s%s%s%s", + weechat_home, + DIR_SEPARATOR, + plugins_dir, + DIR_SEPARATOR, + name_with_ext); + if ((stat (final_name, &st) == 0) && (st.st_size > 0)) + { + free (name_with_ext); + return final_name; + } + free (final_name); + + /* try WeeChat global lib dir */ + length = strlen (WEECHAT_LIBDIR) + strlen (name_with_ext) + + strlen (plugins_dir) + 16; + final_name = malloc (length); + if (!final_name) + { + free (name_with_ext); + return NULL; + } + snprintf (final_name, length, + "%s%s%s%s%s", + WEECHAT_LIBDIR, + DIR_SEPARATOR, + plugins_dir, + DIR_SEPARATOR, + name_with_ext); + if ((stat (final_name, &st) == 0) && (st.st_size > 0)) + { + free (name_with_ext); + return final_name; + } + free (final_name); + + free (name_with_ext); + + return NULL; +} + +/* + * Searches for the full name of a WeeChat library with name. + * + * All extensions listed in option "weechat.plugin.extension" are tested. + * + * Note: result must be freed after use (if not NULL). + */ + +char * +dir_search_full_lib_name (const char *filename, const char *plugins_dir) +{ + char *filename2, *full_name; + int i; + + /* expand home in filename */ + filename2 = string_expand_home (filename); + if (!filename2) + return NULL; + + /* if full path, return it */ + if (strchr (filename2, '/') || strchr (filename2, '\\')) + return filename2; + + if (config_plugin_extensions) + { + for (i = 0; i < config_num_plugin_extensions; i++) + { + full_name = dir_search_full_lib_name_ext ( + filename2, + config_plugin_extensions[i], + plugins_dir); + if (full_name) + { + free (filename2); + return full_name; + } + } + } + else + { + full_name = dir_search_full_lib_name_ext (filename2, "", plugins_dir); + if (full_name) + { + free (filename2); + return full_name; + } + } + + free (filename2); + + return strdup (filename); +} + +/* + * Reads content of a file. + * + * Returns an allocated buffer with the content of file, NULL if error. + * + * Note: result must be freed after use. + */ + +char * +dir_file_get_content (const char *filename) +{ + char *buffer, *buffer2; + FILE *f; + size_t count, fp; + + if (!filename) + return NULL; + + buffer = NULL; + fp = 0; + + f = fopen (filename, "r"); + if (!f) + goto error; + + while (!feof (f)) + { + if (fp > SIZE_MAX - (1024 * sizeof (char))) + goto error; + buffer2 = (char *) realloc (buffer, (fp + (1024 * sizeof (char)))); + if (!buffer2) + goto error; + buffer = buffer2; + count = fread (&buffer[fp], sizeof (char), 1024, f); + if (count <= 0) + goto error; + fp += count; + } + if (fp > SIZE_MAX - sizeof (char)) + goto error; + buffer2 = (char *) realloc (buffer, fp + sizeof (char)); + if (!buffer2) + goto error; + buffer = buffer2; + buffer[fp] = '\0'; + fclose (f); + + return buffer; + +error: + if (buffer) + free (buffer); + if (f) + fclose (f); + return NULL; +} diff --git a/src/core/wee-dir.h b/src/core/wee-dir.h new file mode 100644 index 000000000..fbbdf96a7 --- /dev/null +++ b/src/core/wee-dir.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2003-2021 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef WEECHAT_DIR_H +#define WEECHAT_DIR_H + +extern char *dir_get_temp_dir(); +extern int dir_mkdir_home (const char *directory, int mode); +extern int dir_mkdir (const char *directory, int mode); +extern int dir_mkdir_parents (const char *directory, int mode); +extern int dir_rmtree (const char *directory); +extern void dir_exec_on_files (const char *directory, int recurse_subdirs, + int hidden_files, + void (*callback)(void *data, + const char *filename), + void *callback_data); +extern char *dir_search_full_lib_name (const char *filename, + const char *sys_directory); +extern char *dir_file_get_content (const char *filename); + +#endif /* WEECHAT_DIR_H */ diff --git a/src/core/wee-signal.c b/src/core/wee-signal.c index 0765decf0..c53fc5e31 100644 --- a/src/core/wee-signal.c +++ b/src/core/wee-signal.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> +#include <signal.h> #include "weechat.h" #include "wee-signal.h" diff --git a/src/core/wee-upgrade.c b/src/core/wee-upgrade.c index 26a6037ff..3d5967e1b 100644 --- a/src/core/wee-upgrade.c +++ b/src/core/wee-upgrade.c @@ -30,6 +30,7 @@ #include "weechat.h" #include "wee-upgrade.h" +#include "wee-dir.h" #include "wee-hook.h" #include "wee-infolist.h" #include "wee-secure-buffer.h" @@ -924,9 +925,9 @@ upgrade_weechat_end () long long time_diff; /* remove .upgrade files */ - util_exec_on_files (weechat_home, - 0, 0, - &upgrade_weechat_remove_file_cb, NULL); + dir_exec_on_files (weechat_home, + 0, 0, + &upgrade_weechat_remove_file_cb, NULL); /* display message for end of /upgrade with duration */ gettimeofday (&tv_now, NULL); diff --git a/src/core/wee-util.c b/src/core/wee-util.c index 61a095645..293bca097 100644 --- a/src/core/wee-util.c +++ b/src/core/wee-util.c @@ -19,35 +19,21 @@ * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. */ -/* for P_tmpdir in stdio.h */ -#ifndef __USE_XOPEN -#define __USE_XOPEN -#endif - -/* for nftw() */ -#define _XOPEN_SOURCE 700 - #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <stdlib.h> #include <stdio.h> -#include <stdint.h> #include <errno.h> #include <string.h> #include <sys/types.h> -#include <sys/stat.h> #include <sys/time.h> #ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> #endif -#include <unistd.h> -#include <dirent.h> -#include <signal.h> #include <ctype.h> #include <time.h> -#include <ftw.h> #include "weechat.h" #include "wee-util.h" @@ -430,471 +416,6 @@ util_parse_delay (const char *string_delay, long default_factor) } /* - * Returns the path to a temporary directory, the first valid directory in - * this list: - * - content of environment variable "TMPDIR" - * - P_tmpdir (from stdio.h) - * - content of environment variable "HOME" (user home directory) - * - "." (current directory) - */ - -char * -util_get_temp_dir() -{ - char *tmpdir; - struct stat buf; - int rc; - - /* get directory from $TMPDIR */ - tmpdir = getenv ("TMPDIR"); - if (tmpdir && tmpdir[0]) - { - rc = stat (tmpdir, &buf); - if ((rc == 0) && S_ISDIR(buf.st_mode)) - return strdup (tmpdir); - } - - /* get directory from P_tmpdir */ - rc = stat (P_tmpdir, &buf); - if ((rc == 0) && S_ISDIR(buf.st_mode)) - return strdup (P_tmpdir); - - /* get directory from $HOME */ - tmpdir = getenv ("HOME"); - if (tmpdir && tmpdir[0]) - { - rc = stat (tmpdir, &buf); - if ((rc == 0) && S_ISDIR(buf.st_mode)) - return strdup (tmpdir); - } - - /* fallback on current directory */ - return strdup ("."); -} - -/* - * Creates a directory in WeeChat home. - * - * Returns: - * 1: OK - * 0: error - */ - -int -util_mkdir_home (const char *directory, int mode) -{ - char *dir_name; - int dir_length; - - if (!directory) - return 0; - - /* build directory, adding WeeChat home */ - dir_length = strlen (weechat_home) + strlen (directory) + 2; - dir_name = malloc (dir_length); - if (!dir_name) - return 0; - - snprintf (dir_name, dir_length, "%s/%s", weechat_home, directory); - - if (mkdir (dir_name, mode) < 0) - { - if (errno != EEXIST) - { - free (dir_name); - return 0; - } - } - - free (dir_name); - return 1; -} - -/* - * Creates a directory. - * - * Returns: - * 1: OK - * 0: error - */ - -int -util_mkdir (const char *directory, int mode) -{ - if (!directory) - return 0; - - if (mkdir (directory, mode) < 0) - { - if (errno != EEXIST) - return 0; - } - - return 1; -} - -/* - * Creates a directory and makes parent directories as needed. - * - * Returns: - * 1: OK - * 0: error - */ - -int -util_mkdir_parents (const char *directory, int mode) -{ - char *string, *ptr_string, *pos_sep; - struct stat buf; - int rc; - - if (!directory) - return 0; - - string = strdup (directory); - if (!string) - return 0; - - ptr_string = string; - while (ptr_string[0] == DIR_SEPARATOR_CHAR) - { - ptr_string++; - } - - while (ptr_string && ptr_string[0]) - { - pos_sep = strchr (ptr_string, DIR_SEPARATOR_CHAR); - if (pos_sep) - pos_sep[0] = '\0'; - - rc = stat (string, &buf); - if ((rc < 0) || !S_ISDIR(buf.st_mode)) - { - /* try to create directory */ - if (!util_mkdir (string, mode)) - { - free (string); - return 0; - } - } - - if (pos_sep) - { - pos_sep[0] = DIR_SEPARATOR_CHAR; - ptr_string = pos_sep + 1; - } - else - ptr_string = NULL; - } - - free (string); - - return 1; -} - -/* - * Unlinks a file or directory; callback called by function util_rmtree(). - * - * Returns the return code of remove(): - * 0: OK - * -1: error - */ - -int -util_unlink_cb (const char *fpath, const struct stat *sb, int typeflag, - struct FTW *ftwbuf) -{ - /* make C compiler happy */ - (void) sb; - (void) typeflag; - (void) ftwbuf; - - return remove (fpath); -} - -/* - * Removes a directory and all files inside recursively. - * - * Returns: - * 1: OK - * 0: error - */ - -int -util_rmtree (const char *directory) -{ - int rc; - - if (!directory) - return 0; - - rc = nftw (directory, util_unlink_cb, 64, FTW_DEPTH | FTW_PHYS); - - return (rc == 0) ? 1 : 0; -} - -/* - * Finds files in a directory and executes a function on each file. - */ - -void -util_exec_on_files (const char *directory, int recurse_subdirs, - int hidden_files, - void (*callback)(void *data, const char *filename), - void *callback_data) -{ - char complete_filename[PATH_MAX]; - DIR *dir; - struct dirent *entry; - struct stat statbuf; - - if (!directory || !callback) - return; - - dir = opendir (directory); - if (dir) - { - while ((entry = readdir (dir))) - { - if (hidden_files || (entry->d_name[0] != '.')) - { - snprintf (complete_filename, sizeof (complete_filename), - "%s/%s", directory, entry->d_name); - lstat (complete_filename, &statbuf); - if (S_ISDIR(statbuf.st_mode)) - { - if (recurse_subdirs - && (strcmp (entry->d_name, ".") != 0) - && (strcmp (entry->d_name, "..") != 0)) - { - util_exec_on_files (complete_filename, 1, hidden_files, - callback, callback_data); - } - } - else - { - (*callback) (callback_data, complete_filename); - } - } - } - closedir (dir); - } -} - -/* - * Searches for the full name of a WeeChat library with name and extension - * (searches first in WeeChat user's dir, then WeeChat global lib directory). - * - * Returns name of library found, NULL if not found. - * - * Note: result must be freed after use (if not NULL). - */ - -char * -util_search_full_lib_name_ext (const char *filename, const char *extension, - const char *plugins_dir) -{ - char *name_with_ext, *final_name, *extra_libdir; - int length; - struct stat st; - - length = strlen (filename) + strlen (extension) + 1; - name_with_ext = malloc (length); - if (!name_with_ext) - return NULL; - snprintf (name_with_ext, length, - "%s%s", - filename, - (strchr (filename, '.')) ? "" : extension); - - /* try libdir from environment variable WEECHAT_EXTRA_LIBDIR */ - extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR); - if (extra_libdir && extra_libdir[0]) - { - length = strlen (extra_libdir) + strlen (name_with_ext) + - strlen (plugins_dir) + 16; - final_name = malloc (length); - if (!final_name) - { - free (name_with_ext); - return NULL; - } - snprintf (final_name, length, - "%s%s%s%s%s", - extra_libdir, - DIR_SEPARATOR, - plugins_dir, - DIR_SEPARATOR, - name_with_ext); - if ((stat (final_name, &st) == 0) && (st.st_size > 0)) - { - free (name_with_ext); - return final_name; - } - free (final_name); - } - - /* try WeeChat user's dir */ - length = strlen (weechat_home) + strlen (name_with_ext) + - strlen (plugins_dir) + 16; - final_name = malloc (length); - if (!final_name) - { - free (name_with_ext); - return NULL; - } - snprintf (final_name, length, - "%s%s%s%s%s", - weechat_home, - DIR_SEPARATOR, - plugins_dir, - DIR_SEPARATOR, - name_with_ext); - if ((stat (final_name, &st) == 0) && (st.st_size > 0)) - { - free (name_with_ext); - return final_name; - } - free (final_name); - - /* try WeeChat global lib dir */ - length = strlen (WEECHAT_LIBDIR) + strlen (name_with_ext) + - strlen (plugins_dir) + 16; - final_name = malloc (length); - if (!final_name) - { - free (name_with_ext); - return NULL; - } - snprintf (final_name, length, - "%s%s%s%s%s", - WEECHAT_LIBDIR, - DIR_SEPARATOR, - plugins_dir, - DIR_SEPARATOR, - name_with_ext); - if ((stat (final_name, &st) == 0) && (st.st_size > 0)) - { - free (name_with_ext); - return final_name; - } - free (final_name); - - free (name_with_ext); - - return NULL; -} - -/* - * Searches for the full name of a WeeChat library with name. - * - * All extensions listed in option "weechat.plugin.extension" are tested. - * - * Note: result must be freed after use (if not NULL). - */ - -char * -util_search_full_lib_name (const char *filename, const char *plugins_dir) -{ - char *filename2, *full_name; - int i; - - /* expand home in filename */ - filename2 = string_expand_home (filename); - if (!filename2) - return NULL; - - /* if full path, return it */ - if (strchr (filename2, '/') || strchr (filename2, '\\')) - return filename2; - - if (config_plugin_extensions) - { - for (i = 0; i < config_num_plugin_extensions; i++) - { - full_name = util_search_full_lib_name_ext (filename2, - config_plugin_extensions[i], - plugins_dir); - if (full_name) - { - free (filename2); - return full_name; - } - } - } - else - { - full_name = util_search_full_lib_name_ext (filename2, "", plugins_dir); - if (full_name) - { - free (filename2); - return full_name; - } - } - - free (filename2); - - return strdup (filename); -} - -/* - * Reads content of a file. - * - * Returns an allocated buffer with the content of file, NULL if error. - * - * Note: result must be freed after use. - */ - -char * -util_file_get_content (const char *filename) -{ - char *buffer, *buffer2; - FILE *f; - size_t count, fp; - - if (!filename) - return NULL; - - buffer = NULL; - fp = 0; - - f = fopen (filename, "r"); - if (!f) - goto error; - - while (!feof (f)) - { - if (fp > SIZE_MAX - (1024 * sizeof (char))) - goto error; - buffer2 = (char *) realloc (buffer, (fp + (1024 * sizeof (char)))); - if (!buffer2) - goto error; - buffer = buffer2; - count = fread (&buffer[fp], sizeof (char), 1024, f); - if (count <= 0) - goto error; - fp += count; - } - if (fp > SIZE_MAX - sizeof (char)) - goto error; - buffer2 = (char *) realloc (buffer, fp + sizeof (char)); - if (!buffer2) - goto error; - buffer = buffer2; - buffer[fp] = '\0'; - fclose (f); - - return buffer; - -error: - if (buffer) - free (buffer); - if (f) - fclose (f); - return NULL; -} - -/* * Gets version number (integer) with a version as string. * * Non-digit chars like "-dev" are ignored. diff --git a/src/core/wee-util.h b/src/core/wee-util.h index e7cf2a5cd..a2175a97d 100644 --- a/src/core/wee-util.h +++ b/src/core/wee-util.h @@ -50,21 +50,6 @@ extern void util_get_time_diff (time_t time1, time_t time2, extern long util_parse_delay (const char *string_delay, long default_factor); -/* files/directories */ -extern char *util_get_temp_dir(); -extern int util_mkdir_home (const char *directory, int mode); -extern int util_mkdir (const char *directory, int mode); -extern int util_mkdir_parents (const char *directory, int mode); -extern int util_rmtree (const char *directory); -extern void util_exec_on_files (const char *directory, int recurse_subdirs, - int hidden_files, - void (*callback)(void *data, - const char *filename), - void *callback_data); -extern char *util_search_full_lib_name (const char *filename, - const char *sys_directory); -extern char *util_file_get_content (const char *filename); - /* version */ extern int util_version_number (const char *version); diff --git a/src/core/weechat.c b/src/core/weechat.c index 32456bdde..d29a4eac0 100644 --- a/src/core/weechat.c +++ b/src/core/weechat.c @@ -59,6 +59,7 @@ #include "wee-completion.h" #include "wee-config.h" #include "wee-debug.h" +#include "wee-dir.h" #include "wee-eval.h" #include "wee-hdata.h" #include "wee-hook.h" @@ -435,7 +436,7 @@ weechat_create_home_dir () /* temporary WeeChat home */ if (weechat_home_temp) { - temp_dir = util_get_temp_dir (); + temp_dir = dir_get_temp_dir (); if (!temp_dir || !temp_dir[0]) { string_fprintf (stderr, @@ -515,7 +516,7 @@ weechat_create_home_dir () } /* create home directory; error is fatal */ - if (!util_mkdir (weechat_home, 0755)) + if (!dir_mkdir (weechat_home, 0755)) { string_fprintf (stderr, _("Error: cannot create directory \"%s\"\n"), @@ -697,7 +698,7 @@ weechat_shutdown (int return_code, int crash) if (!crash && weechat_home_delete_on_exit) { /* remove temporary home (only if not crashing) */ - util_rmtree (weechat_home); + dir_rmtree (weechat_home); } if (weechat_argv0) diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 58dd23ad6..3982e04c5 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -38,6 +38,7 @@ #include "../core/weechat.h" #include "../core/wee-arraylist.h" #include "../core/wee-config.h" +#include "../core/wee-dir.h" #include "../core/wee-eval.h" #include "../core/wee-hashtable.h" #include "../core/wee-hdata.h" @@ -665,11 +666,11 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) new_plugin->crypto_hash = &plugin_api_crypto_hash; new_plugin->crypto_hash_pbkdf2 = &plugin_api_crypto_hash_pbkdf2; - new_plugin->mkdir_home = &util_mkdir_home; - new_plugin->mkdir = &util_mkdir; - new_plugin->mkdir_parents = &util_mkdir_parents; - new_plugin->exec_on_files = &util_exec_on_files; - new_plugin->file_get_content = &util_file_get_content; + new_plugin->mkdir_home = &dir_mkdir_home; + new_plugin->mkdir = &dir_mkdir; + new_plugin->mkdir_parents = &dir_mkdir_parents; + new_plugin->exec_on_files = &dir_exec_on_files; + new_plugin->file_get_content = &dir_file_get_content; new_plugin->util_timeval_cmp = &util_timeval_cmp; new_plugin->util_timeval_diff = &util_timeval_diff; @@ -1049,8 +1050,8 @@ plugin_auto_load (char *force_plugin_autoload, NULL, NULL, NULL); if (plugin_path) { - util_exec_on_files (plugin_path, 1, 0, - &plugin_auto_load_file, &plugin_args); + dir_exec_on_files (plugin_path, 1, 0, + &plugin_auto_load_file, &plugin_args); free (plugin_path); } } @@ -1064,8 +1065,8 @@ plugin_auto_load (char *force_plugin_autoload, length = strlen (extra_libdir) + 16 + 1; dir_name = malloc (length); snprintf (dir_name, length, "%s/plugins", extra_libdir); - util_exec_on_files (dir_name, 1, 0, - &plugin_auto_load_file, &plugin_args); + dir_exec_on_files (dir_name, 1, 0, + &plugin_auto_load_file, &plugin_args); free (dir_name); } } @@ -1078,8 +1079,8 @@ plugin_auto_load (char *force_plugin_autoload, if (dir_name) { snprintf (dir_name, length, "%s/plugins", WEECHAT_LIBDIR); - util_exec_on_files (dir_name, 1, 0, - &plugin_auto_load_file, &plugin_args); + dir_exec_on_files (dir_name, 1, 0, + &plugin_auto_load_file, &plugin_args); free (dir_name); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a9b536095..01bade1f2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,6 +27,7 @@ set(LIB_WEECHAT_UNIT_TESTS_CORE_SRC unit/core/test-core-arraylist.cpp unit/core/test-core-calc.cpp unit/core/test-core-crypto.cpp + unit/core/test-core-dir.cpp unit/core/test-core-eval.cpp unit/core/test-core-hashtable.cpp unit/core/test-core-hdata.cpp diff --git a/tests/Makefile.am b/tests/Makefile.am index c1b243fbc..95a8f9139 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,6 +24,7 @@ noinst_LIBRARIES = lib_weechat_unit_tests_core.a lib_weechat_unit_tests_core_a_SOURCES = unit/core/test-core-arraylist.cpp \ unit/core/test-core-calc.cpp \ unit/core/test-core-crypto.cpp \ + unit/core/test-core-dir.cpp \ unit/core/test-core-eval.cpp \ unit/core/test-core-hashtable.cpp \ unit/core/test-core-hdata.cpp \ diff --git a/tests/tests.cpp b/tests/tests.cpp index 052f48096..12ae8fdf0 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -34,10 +34,10 @@ extern "C" #define HAVE_CONFIG_H #endif #include "src/core/weechat.h" +#include "src/core/wee-dir.h" #include "src/core/wee-hook.h" #include "src/core/wee-input.h" #include "src/core/wee-string.h" -#include "src/core/wee-util.h" #include "src/plugins/plugin.h" #include "src/gui/gui-main.h" #include "src/gui/gui-buffer.h" @@ -62,6 +62,7 @@ extern "C" IMPORT_TEST_GROUP(CoreArraylist); IMPORT_TEST_GROUP(CoreCalc); IMPORT_TEST_GROUP(CoreCrypto); +IMPORT_TEST_GROUP(CoreDir); IMPORT_TEST_GROUP(CoreEval); IMPORT_TEST_GROUP(CoreHashtable); IMPORT_TEST_GROUP(CoreHdata); @@ -197,7 +198,7 @@ main (int argc, char *argv[]) } /* clean WeeChat home */ - util_exec_on_files (WEECHAT_TESTS_HOME, 1, 1, &exec_on_files_cb, NULL); + dir_exec_on_files (WEECHAT_TESTS_HOME, 1, 1, &exec_on_files_cb, NULL); /* build arguments for WeeChat */ weechat_tests_args = getenv ("WEECHAT_TESTS_ARGS"); diff --git a/tests/unit/core/test-core-dir.cpp b/tests/unit/core/test-core-dir.cpp new file mode 100644 index 000000000..2be7bcd39 --- /dev/null +++ b/tests/unit/core/test-core-dir.cpp @@ -0,0 +1,119 @@ +/* + * test-core-dir.cpp - test directory/file functions + * + * Copyright (C) 2014-2021 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <sys/time.h> +#include "src/core/wee-dir.h" +#include "src/core/wee-string.h" +} + +TEST_GROUP(CoreDir) +{ +}; + +/* + * Tests functions: + * dir_mkdir_home + * dir_mkdir + * dir_mkdir_parents + */ + +TEST(CoreDir, Mkdir) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_exec_on_files + */ + +TEST(CoreDir, ExecOnFiles) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_search_full_lib_name + */ + +TEST(CoreDir, LibName) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * dir_file_get_content + */ + +TEST(CoreDir, FileGetContent) +{ + char *path, *content, *content_read; + const char *content_small = "line 1\nline 2\nend"; + int length, i; + FILE *f; + + /* file not found */ + POINTERS_EQUAL(NULL, dir_file_get_content (NULL)); + POINTERS_EQUAL(NULL, dir_file_get_content ("")); + POINTERS_EQUAL(NULL, dir_file_get_content ("/tmp/does/not/exist.xyz")); + + path = string_eval_path_home ("%h/test_file.txt", NULL, NULL, NULL); + + /* small file */ + length = strlen (content_small); + f = fopen (path, "wb"); + CHECK(f); + LONGS_EQUAL(length, fwrite (content_small, 1, length, f)); + fclose (f); + content_read = dir_file_get_content (path); + STRCMP_EQUAL(content_small, content_read); + free (content_read); + unlink (path); + + /* bigger file: 26 lines of 5000 bytes */ + length = 26 * 5001; + content = (char *)malloc (length + 1); + CHECK(content); + for (i = 0; i < 26; i++) + { + memset (content + (i * 5001), 'a' + i, 5000); + content[(i * 5001) + 5000] = '\n'; + } + content[26 * 5001] = '\0'; + f = fopen (path, "wb"); + CHECK(f); + LONGS_EQUAL(length, fwrite (content, 1, length, f)); + fclose (f); + content_read = dir_file_get_content (path); + STRCMP_EQUAL(content, content_read); + free (content_read); + unlink (path); + free (content); +} diff --git a/tests/unit/core/test-core-util.cpp b/tests/unit/core/test-core-util.cpp index e78d2ba77..315a88a1d 100644 --- a/tests/unit/core/test-core-util.cpp +++ b/tests/unit/core/test-core-util.cpp @@ -224,89 +224,6 @@ TEST(CoreUtil, ParseDelay) /* * Tests functions: - * util_mkdir_home - * util_mkdir - * util_mkdir_parents - */ - -TEST(CoreUtil, Mkdir) -{ - /* TODO: write tests */ -} - -/* - * Tests functions: - * util_exec_on_files - */ - -TEST(CoreUtil, ExecOnFiles) -{ - /* TODO: write tests */ -} - -/* - * Tests functions: - * util_search_full_lib_name - */ - -TEST(CoreUtil, LibName) -{ - /* TODO: write tests */ -} - -/* - * Tests functions: - * util_file_get_content - */ - -TEST(CoreUtil, FileGetContent) -{ - char *path, *content, *content_read; - const char *content_small = "line 1\nline 2\nend"; - int length, i; - FILE *f; - - /* file not found */ - POINTERS_EQUAL(NULL, util_file_get_content (NULL)); - POINTERS_EQUAL(NULL, util_file_get_content ("")); - POINTERS_EQUAL(NULL, util_file_get_content ("/tmp/does/not/exist.xyz")); - - path = string_eval_path_home ("%h/test_file.txt", NULL, NULL, NULL); - - /* small file */ - length = strlen (content_small); - f = fopen (path, "wb"); - CHECK(f); - LONGS_EQUAL(length, fwrite (content_small, 1, length, f)); - fclose (f); - content_read = util_file_get_content (path); - STRCMP_EQUAL(content_small, content_read); - free (content_read); - unlink (path); - - /* bigger file: 26 lines of 5000 bytes */ - length = 26 * 5001; - content = (char *)malloc (length + 1); - CHECK(content); - for (i = 0; i < 26; i++) - { - memset (content + (i * 5001), 'a' + i, 5000); - content[(i * 5001) + 5000] = '\n'; - } - content[26 * 5001] = '\0'; - f = fopen (path, "wb"); - CHECK(f); - LONGS_EQUAL(length, fwrite (content, 1, length, f)); - fclose (f); - content_read = util_file_get_content (path); - STRCMP_EQUAL(content, content_read); - free (content_read); - unlink (path); - free (content); -} - -/* - * Tests functions: * util_version_number */ |