From 8a11a18dc56d1f77661e84fe470e34f9b3bcdb11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Sat, 3 Jul 2021 16:04:50 +0200 Subject: [PATCH] api: add function file_copy (issue #1667) --- ChangeLog.adoc | 1 + doc/en/weechat_plugin_api.en.adoc | 35 +++++++++++++++++++ doc/fr/weechat_plugin_api.fr.adoc | 35 +++++++++++++++++++ doc/it/weechat_plugin_api.it.adoc | 36 ++++++++++++++++++++ doc/ja/weechat_plugin_api.ja.adoc | 36 ++++++++++++++++++++ doc/sr/weechat_plugin_api.sr.adoc | 36 ++++++++++++++++++++ src/core/wee-dir.c | 56 +++++++++++++++++++++++++++++++ src/core/wee-dir.h | 1 + src/plugins/plugin.c | 1 + src/plugins/weechat-plugin.h | 5 ++- tests/unit/core/test-core-dir.cpp | 47 ++++++++++++++++---------- 11 files changed, 271 insertions(+), 18 deletions(-) diff --git a/ChangeLog.adoc b/ChangeLog.adoc index ecd93dbe9..a4d5081b2 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -21,6 +21,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] New features:: * core: add option "certs" in command /debug + * api: add function file_copy (issue #1667) * api: remember insertion order in hashtables * api: add keys/values with tags in output of irc_message_parse_to_hashtable (issue #1654) * irc: allow signals "irc_raw_in" and "irc_in" to eat messages (issue #1657) diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index cc3c678d4..f4e558e27 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -3887,6 +3887,41 @@ free (content); [NOTE] This function is not available in scripting API. +==== file_copy + +_WeeChat ≥ 3.3._ + +Copy a file to another location. + +Prototype: + +[source,C] +---- +int weechat_file_copy (const char *from, const char *to); +---- + +Arguments: + +* _from_: source file +* _to_: destination file + +Return value: + +* 1 if OK, 0 if error + +C example: + +[source,C] +---- +if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt")) +{ + /* OK */ +} +---- + +[NOTE] +This function is not available in scripting API. + [[util]] === Util diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc index 22a6164c2..715373835 100644 --- a/doc/fr/weechat_plugin_api.fr.adoc +++ b/doc/fr/weechat_plugin_api.fr.adoc @@ -3953,6 +3953,41 @@ free (contenu); [NOTE] Cette fonction n'est pas disponible dans l'API script. +==== file_copy + +_WeeChat ≥ 3.3._ + +Copier un fichier vers une autre destination. + +Prototype : + +[source,C] +---- +int weechat_file_copy (const char *from, const char *to); +---- + +Paramètres : + +* _from_ : fichier source +* _to_ : fichier cible + +Valeur de retour : + +* 1 si OK, 0 si erreur + +Exemple en C : + +[source,C] +---- +if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt")) +{ + /* OK */ +} +---- + +[NOTE] +Cette fonction n'est pas disponible dans l'API script. + [[util]] === Util diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index c47c579af..2c60fe1de 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -4026,6 +4026,42 @@ free (content); [NOTE] Questa funzione non è disponibile nelle API per lo scripting. +// TRANSLATION MISSING +==== file_copy + +_WeeChat ≥ 3.3._ + +Copy a file to another location. + +Prototipo: + +[source,C] +---- +int weechat_file_copy (const char *from, const char *to); +---- + +Argomenti: + +* _from_: source file +* _to_: destination file + +Valore restituito: + +* 1 if OK, 0 if error + +Esempio in C: + +[source,C] +---- +if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt")) +{ + /* OK */ +} +---- + +[NOTE] +Questa funzione non è disponibile nelle API per lo scripting. + [[util]] === Utilità diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc index bf72f8a72..28bb49229 100644 --- a/doc/ja/weechat_plugin_api.ja.adoc +++ b/doc/ja/weechat_plugin_api.ja.adoc @@ -3933,6 +3933,42 @@ free (content); [NOTE] スクリプト API ではこの関数を利用できません。 +// TRANSLATION MISSING +==== file_copy + +_WeeChat ≥ 3.3._ + +Copy a file to another location. + +プロトタイプ: + +[source,C] +---- +int weechat_file_copy (const char *from, const char *to); +---- + +引数: + +* _from_: source file +* _to_: destination file + +戻り値: + +* 1 if OK, 0 if error + +C 言語での使用例: + +[source,C] +---- +if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt")) +{ + /* OK */ +} +---- + +[NOTE] +スクリプト API ではこの関数を利用できません。 + [[util]] === ユーティリティ diff --git a/doc/sr/weechat_plugin_api.sr.adoc b/doc/sr/weechat_plugin_api.sr.adoc index 3e5eab170..6fea2cc26 100644 --- a/doc/sr/weechat_plugin_api.sr.adoc +++ b/doc/sr/weechat_plugin_api.sr.adoc @@ -3745,6 +3745,42 @@ free (content); [NOTE] Ова функција није доступна у API скриптовања. +// TRANSLATION MISSING +==== file_copy + +_WeeChat ≥ 3.3._ + +Copy a file to another location. + +Прототип: + +[source,C] +---- +int weechat_file_copy (const char *from, const char *to); +---- + +Аргументи: + +* _from_: source file +* _to_: destination file + +Повратна вредност: + +* 1 if OK, 0 if error + +C пример: + +[source,C] +---- +if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt")) +{ + /* OK */ +} +---- + +[NOTE] +Ова функција није доступна у API скриптовања. + [[util]] === Алати diff --git a/src/core/wee-dir.c b/src/core/wee-dir.c index aae69b267..bb5ac16f6 100644 --- a/src/core/wee-dir.c +++ b/src/core/wee-dir.c @@ -555,6 +555,62 @@ error: return NULL; } +/* + * Copies a file to another location. + * + * Returns: + * 1: OK + * 0: error + */ + +int +dir_file_copy (const char *from, const char *to) +{ + FILE *src, *dst; + char *buffer; + int rc; + size_t count; + + rc = 0; + buffer = NULL; + src = NULL; + dst = NULL; + + if (!from || !from[0] || !to || !to[0]) + goto end; + + buffer = malloc (65536); + if (!buffer) + goto end; + + src = fopen (from, "rb"); + if (!src) + goto end; + dst = fopen (to, "wb"); + if (!dst) + goto end; + + while (!feof (src)) + { + count = fread (buffer, 1, 65535, src); + if (count <= 0) + goto end; + if (fwrite (buffer, 1, count, dst) <= 0) + goto end; + } + + rc = 1; + +end: + if (buffer) + free (buffer); + if (src) + fclose (src); + if (dst) + fclose (dst); + return rc; +} + /* * Uses one or four different paths for WeeChat home directories. * diff --git a/src/core/wee-dir.h b/src/core/wee-dir.h index 489ca2a64..9e368c596 100644 --- a/src/core/wee-dir.h +++ b/src/core/wee-dir.h @@ -33,6 +33,7 @@ extern void dir_exec_on_files (const char *directory, int recurse_subdirs, extern char *dir_search_full_lib_name (const char *filename, const char *sys_directory); extern char *dir_file_get_content (const char *filename); +extern int dir_file_copy (const char *from, const char *to); extern void dir_create_home_dirs (); extern void dir_remove_home_dirs (); extern char *dir_get_string_home_dirs (); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 6254b613b..7deb32cc6 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -672,6 +672,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) 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->file_copy = &dir_file_copy; new_plugin->util_timeval_cmp = &util_timeval_cmp; new_plugin->util_timeval_diff = &util_timeval_diff; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 9eb42f7e9..b509e952e 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -68,7 +68,7 @@ struct timeval; * please change the date with current one; for a second change at same * date, increment the 01, otherwise please keep 01. */ -#define WEECHAT_PLUGIN_API_VERSION "20210601-01" +#define WEECHAT_PLUGIN_API_VERSION "20210703-01" /* macros for defining plugin infos */ #define WEECHAT_PLUGIN_NAME(__name) \ @@ -395,6 +395,7 @@ struct t_weechat_plugin void (*callback)(void *data, const char *filename), void *callback_data); char *(*file_get_content) (const char *filename); + int (*file_copy) (const char *from, const char *to); /* util */ int (*util_timeval_cmp) (struct timeval *tv1, struct timeval *tv2); @@ -1374,6 +1375,8 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); __callback, __callback_data) #define weechat_file_get_content(__filename) \ (weechat_plugin->file_get_content)(__filename) +#define weechat_file_copy(__from, __to) \ + (weechat_plugin->file_copy)(__from, __to) /* util */ #define weechat_util_timeval_cmp(__time1, __time2) \ diff --git a/tests/unit/core/test-core-dir.cpp b/tests/unit/core/test-core-dir.cpp index 361630693..3ecb4018e 100644 --- a/tests/unit/core/test-core-dir.cpp +++ b/tests/unit/core/test-core-dir.cpp @@ -90,33 +90,41 @@ TEST(CoreDir, SearchFullLibName) /* * Tests functions: * dir_file_get_content + * dir_file_copy */ -TEST(CoreDir, FileGetContent) +TEST(CoreDir, FileGetContentCopy) { - char *path, *content, *content_read; + char *path1, *path2, *content, *content_read1, *content_read2; 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")); + LONGS_EQUAL(0, dir_file_copy (NULL, NULL)); + LONGS_EQUAL(0, dir_file_copy ("", "")); + LONGS_EQUAL(0, dir_file_copy ("/tmp/does/not/exist.xyz", "/tmp/test.txt")); - path = string_eval_path_home ("${weechat_data_dir}/test_file.txt", - NULL, NULL, NULL); + path1 = string_eval_path_home ("${weechat_data_dir}/test_file.txt", + NULL, NULL, NULL); + path2 = string_eval_path_home ("${weechat_data_dir}/test_file2.txt", + NULL, NULL, NULL); /* small file */ length = strlen (content_small); - f = fopen (path, "wb"); + f = fopen (path1, "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); + LONGS_EQUAL(1, dir_file_copy (path1, path2)); + content_read1 = dir_file_get_content (path1); + content_read2 = dir_file_get_content (path2); + STRCMP_EQUAL(content_small, content_read1); + MEMCMP_EQUAL(content_read1, content_read2, length); + free (content_read1); + free (content_read2); + unlink (path1); + unlink (path2); /* bigger file: 26 lines of 5000 bytes */ length = 26 * 5001; @@ -128,14 +136,19 @@ TEST(CoreDir, FileGetContent) content[(i * 5001) + 5000] = '\n'; } content[26 * 5001] = '\0'; - f = fopen (path, "wb"); + f = fopen (path1, "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); + LONGS_EQUAL(1, dir_file_copy (path1, path2)); + content_read1 = dir_file_get_content (path1); + content_read2 = dir_file_get_content (path2); + STRCMP_EQUAL(content, content_read1); + MEMCMP_EQUAL(content_read1, content_read2, length); + free (content_read1); + free (content_read2); + unlink (path1); + unlink (path2); free (content); }