summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2021-04-18 21:23:14 +0200
committerSébastien Helleu <flashcode@flashtux.org>2021-05-11 21:06:29 +0200
commit269576eea2c20033dc3a704847810a0b1bc55440 (patch)
tree1ad1dfa82a6dceb9065f76ec1c7cdf09a5ca7e4f
parent9eecad496db62159376bda0cf2789690039872ce (diff)
downloadweechat-269576eea2c20033dc3a704847810a0b1bc55440.zip
core: move directory/file functions from wee-util.c to wee-dir.c (issue #1285)
-rw-r--r--po/POTFILES.in2
-rw-r--r--po/srcfiles.cmake2
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/Makefile.am2
-rw-r--r--src/core/wee-command.c3
-rw-r--r--src/core/wee-completion.c20
-rw-r--r--src/core/wee-dir.c514
-rw-r--r--src/core/wee-dir.h37
-rw-r--r--src/core/wee-signal.c1
-rw-r--r--src/core/wee-upgrade.c7
-rw-r--r--src/core/wee-util.c479
-rw-r--r--src/core/wee-util.h15
-rw-r--r--src/core/weechat.c7
-rw-r--r--src/plugins/plugin.c23
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/tests.cpp5
-rw-r--r--tests/unit/core/test-core-dir.cpp119
-rw-r--r--tests/unit/core/test-core-util.cpp83
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
*/