1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-12 14:14:48 +02:00

api: add function file_compare (issue #2250)

This commit is contained in:
Sébastien Helleu
2025-05-07 20:42:46 +02:00
parent 9a661aecd0
commit 51d24fd2da
11 changed files with 391 additions and 7 deletions
+1
View File
@@ -10,6 +10,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
### Added
- api: add function file_compare
- irc: add support of strikethrough text in IRC messages ([#2248](https://github.com/weechat/weechat/issues/2248))
- buflist: add variables `${number_zero}` and `${number_zero2}` (zero-padded buffer number)
- tests: add fuzz testing ([#1462](https://github.com/weechat/weechat/issues/1462))
+37
View File
@@ -4624,6 +4624,43 @@ if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
[NOTE]
This function is not available in scripting API.
==== file_compare
_WeeChat ≥ 4.7.0._
Compare the content of two files.
Prototype:
[source,c]
----
int weechat_file_compare (const char *filename1, const char *filename2);
----
Arguments:
* _filename1_: first file to compare
* _filename2_: second file to compare
Return value:
* 0: both files have same content
* 1: content is different
* 2: error (file not found or read error)
C example:
[source,c]
----
if (weechat_file_compare ("/tmp/test.txt", "/tmp/test2.txt") == 0)
{
/* same content */
}
----
[NOTE]
This function is not available in scripting API.
[[util]]
=== Util
+37
View File
@@ -4703,6 +4703,43 @@ if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
[NOTE]
Cette fonction n'est pas disponible dans l'API script.
==== file_compare
_WeeChat ≥ 4.7.0._
Compare the content of two files.
Prototype:
[source,c]
----
int weechat_file_compare (const char *filename1, const char *filename2);
----
Arguments:
* _filename1_: first file to compare
* _filename2_: second file to compare
Return value:
* 0: both files have same content
* 1: content is different
* 2: error (file not found or read error)
C example:
[source,c]
----
if (weechat_file_compare ("/tmp/test.txt", "/tmp/test2.txt") == 0)
{
/* same content */
}
----
[NOTE]
This function is not available in scripting API.
[[util]]
=== Util
+38
View File
@@ -4831,6 +4831,44 @@ if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
[NOTE]
Questa funzione non è disponibile nelle API per lo scripting.
// TRANSLATION MISSING
==== file_compare
_WeeChat ≥ 4.7.0._
Compare the content of two files.
Prototipo:
[source,c]
----
int weechat_file_compare (const char *filename1, const char *filename2);
----
Argomenti:
* _filename1_: first file to compare
* _filename2_: second file to compare
Valore restituito:
* 0: both files have same content
* 1: content is different
* 2: error (file not found or read error)
Esempio in C:
[source,c]
----
if (weechat_file_compare ("/tmp/test.txt", "/tmp/test2.txt") == 0)
{
/* same content */
}
----
[NOTE]
Questa funzione non è disponibile nelle API per lo scripting.
[[util]]
=== Utilità
+38
View File
@@ -4756,6 +4756,44 @@ if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
[NOTE]
スクリプト API ではこの関数を利用できません。
// TRANSLATION MISSING
==== file_compare
_WeeChat ≥ 4.7.0._
Compare the content of two files.
プロトタイプ:
[source,c]
----
int weechat_file_compare (const char *filename1, const char *filename2);
----
引数:
* _filename1_: first file to compare
* _filename2_: second file to compare
戻り値:
* 0: both files have same content
* 1: content is different
* 2: error (file not found or read error)
C 言語での使用例:
[source,c]
----
if (weechat_file_compare ("/tmp/test.txt", "/tmp/test2.txt") == 0)
{
/* same content */
}
----
[NOTE]
スクリプト API ではこの関数を利用できません。
[[util]]
=== ユーティリティ
+38
View File
@@ -4484,6 +4484,44 @@ if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
[NOTE]
Ова функција није доступна у API скриптовања.
// TRANSLATION MISSING
==== file_compare
_WeeChat ≥ 4.7.0._
Compare the content of two files.
Прототип:
[source,c]
----
int weechat_file_compare (const char *filename1, const char *filename2);
----
Аргументи:
* _filename1_: first file to compare
* _filename2_: second file to compare
Повратна вредност:
* 0: both files have same content
* 1: content is different
* 2: error (file not found or read error)
C пример:
[source,c]
----
if (weechat_file_compare ("/tmp/test.txt", "/tmp/test2.txt") == 0)
{
/* same content */
}
----
[NOTE]
Ова функција није доступна у API скриптовања.
[[util]]
=== Алати
+124
View File
@@ -1431,3 +1431,127 @@ dir_file_compress (const char *filename_input,
return 0;
}
}
/*
* Compares the content of two files (the attributes of the files like the
* permissions or timestamp are ignored).
*
* Comparison is done like this:
* 1. if sizes are different, return 1 (different content)
* 2. if sizes are the same, read both files until a difference is found
*
* Returns:
* 0: both files exist and their content is exactly the same
* 1: content is different
* 2: other error (file not found, read error)
*/
int
dir_file_compare (const char *filename1, const char *filename2)
{
char buffer1[4096], buffer2[4096];
FILE *f1, *f2;
struct stat st;
off_t size1, size2;
size_t count1, count2;
int rc, eof1, eof2;
if (!filename1 || !filename1[0] || !filename2 || !filename2[0])
return 2;
rc = 1;
f1 = NULL;
f2 = NULL;
/* get size of first file */
if (access (filename1, R_OK) != 0)
{
rc = 2;
goto end;
}
if (stat (filename1, &st) != 0)
{
rc = 2;
goto end;
}
size1 = st.st_size;
/* get size of second file */
if (access (filename2, R_OK) != 0)
{
rc = 2;
goto end;
}
if (stat (filename2, &st) != 0)
{
rc = 2;
goto end;
}
size2 = st.st_size;
if (size1 != size2)
{
/* different size, so different content */
rc = 1;
goto end;
}
f1 = fopen (filename1, "r");
if (!f1)
{
rc = 2;
goto end;
}
f2 = fopen (filename2, "r");
if (!f2)
{
rc = 2;
goto end;
}
while (1)
{
eof1 = feof (f1);
eof2 = feof (f2);
if ((eof1 && !eof2) || (!eof1 && eof2))
{
/* different content */
rc = 1;
goto end;
}
if (eof1 && eof2)
{
/* same content */
rc = 0;
goto end;
}
count1 = fread (buffer1, sizeof (char), sizeof (buffer1), f1);
count2 = fread (buffer2, sizeof (char), sizeof (buffer2), f2);
if (count1 != count2)
{
/* different content */
rc = 1;
goto end;
}
if ((count1 == 0) || (count2 == 0))
{
/* read error */
rc = 2;
goto end;
}
if (memcmp (buffer1, buffer2, count1) != 0)
{
/* different content */
rc = 1;
goto end;
}
}
end:
if (f1)
fclose (f1);
if (f2)
fclose (f2);
return rc;
}
+1
View File
@@ -41,5 +41,6 @@ extern char *dir_file_get_content (const char *filename);
extern int dir_file_copy (const char *from, const char *to);
extern int dir_file_compress (const char *from, const char *to,
const char *compressor, int compression_level);
extern int dir_file_compare (const char *filename1, const char *filename2);
#endif /* WEECHAT_DIR_H */
+1
View File
@@ -693,6 +693,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv)
new_plugin->file_get_content = &dir_file_get_content;
new_plugin->file_copy = &dir_file_copy;
new_plugin->file_compress = &dir_file_compress;
new_plugin->file_compare = &dir_file_compare;
new_plugin->util_timeval_cmp = &util_timeval_cmp;
new_plugin->util_timeval_diff = &util_timeval_diff;
+4 -1
View File
@@ -76,7 +76,7 @@ struct t_weelist_item;
* 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 "20250215-01"
#define WEECHAT_PLUGIN_API_VERSION "20250507-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -457,6 +457,7 @@ struct t_weechat_plugin
int (*file_copy) (const char *from, const char *to);
int (*file_compress) (const char *from, const char *to,
const char *compressor, int compression_level);
int (*file_compare) (const char *filename1, const char *filename2);
/* util */
int (*util_timeval_cmp) (struct timeval *tv1, struct timeval *tv2);
@@ -1528,6 +1529,8 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
__compression_level) \
(weechat_plugin->file_compress)(__from, __to, __compressor, \
__compression_level)
#define weechat_file_compare(__filename1, __filename2) \
(weechat_plugin->file_compress)(__filename1, __filename2)
/* util */
#define weechat_util_timeval_cmp(__time1, __time2) \
+72 -6
View File
@@ -227,16 +227,15 @@ TEST(CoreDir, FileGetContentCopy)
LONGS_EQUAL(0, dir_file_copy ("", ""));
LONGS_EQUAL(0, dir_file_copy ("/tmp/does/not/exist.xyz", "/tmp/test.txt"));
path1 = string_eval_path_home ("${weechat_data_dir}/test_file.txt",
path1 = string_eval_path_home ("${weechat_data_dir}/test_content_file1.txt",
NULL, NULL, NULL);
path2 = string_eval_path_home ("${weechat_data_dir}/test_file2.txt",
path2 = string_eval_path_home ("${weechat_data_dir}/test_content_file2.txt",
NULL, NULL, NULL);
/* small file */
length = strlen (content_small);
f = fopen (path1, "wb");
CHECK(f);
LONGS_EQUAL(length, fwrite (content_small, 1, length, f));
fwrite (content_small, 1, length, f);
fclose (f);
LONGS_EQUAL(1, dir_file_copy (path1, path2));
content_read1 = dir_file_get_content (path1);
@@ -259,8 +258,7 @@ TEST(CoreDir, FileGetContentCopy)
}
content[26 * 5001] = '\0';
f = fopen (path1, "wb");
CHECK(f);
LONGS_EQUAL(length, fwrite (content, 1, length, f));
fwrite (content, 1, length, f);
fclose (f);
LONGS_EQUAL(1, dir_file_copy (path1, path2));
content_read1 = dir_file_get_content (path1);
@@ -303,3 +301,71 @@ TEST(CoreDir, FileCompress)
{
/* TODO: write tests */
}
/*
* Tests functions:
* dir_file_compare
*/
TEST(CoreDir, FileCompare)
{
char *path1, *path2, *content;
const char *content_small = "line 1\nline 2\nend";
int length, i;
FILE *f;
/* file not found */
LONGS_EQUAL(2, dir_file_compare (NULL, NULL));
LONGS_EQUAL(2, dir_file_compare ("", ""));
LONGS_EQUAL(2, dir_file_compare ("/tmp/does/not/exist1.xyz", "/tmp/does/not/exist2.xyz"));
path1 = string_eval_path_home ("${weechat_data_dir}/test_compare_file1.txt",
NULL, NULL, NULL);
path2 = string_eval_path_home ("${weechat_data_dir}/test_compare_file2.txt",
NULL, NULL, NULL);
/* small file */
length = strlen (content_small);
f = fopen (path1, "wb");
fwrite (content_small, 1, length, f);
fclose (f);
f = fopen (path2, "wb");
fwrite (content_small, 1, length, f);
fclose (f);
LONGS_EQUAL(0, dir_file_compare (path1, path2));
f = fopen (path1, "ab");
fwrite ("A", 1, 1, f);
fclose (f);
f = fopen (path2, "ab");
fwrite ("B", 1, 1, f);
fclose (f);
LONGS_EQUAL(1, dir_file_compare (path1, path2));
/* bigger file: 26 lines of 5000 bytes + 1 byte */
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 (path1, "wb");
fwrite (content, 1, length, f);
fclose (f);
f = fopen (path2, "wb");
fwrite (content, 1, length, f);
fclose (f);
LONGS_EQUAL(0, dir_file_compare (path1, path2));
f = fopen (path1, "ab");
fwrite ("A", 1, 1, f);
fclose (f);
f = fopen (path2, "ab");
fwrite ("B", 1, 1, f);
fclose (f);
LONGS_EQUAL(1, dir_file_compare (path1, path2));
unlink (path1);
unlink (path2);
}