1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-07 02:03:13 +02:00

api: add function file_compress

This commit is contained in:
Sébastien Helleu
2022-09-27 20:49:12 +02:00
parent e7b6e8c60f
commit 26e6fdc645
17 changed files with 824 additions and 323 deletions
+1
View File
@@ -29,6 +29,7 @@ New features::
* api: add function crypto_hash_file
* api: add support of priority in function hook_line (issue #1821)
* api: add function string_parse_size
* api: add function file_compress
* buflist: add variable `${hotlist_priority_number}` (integer version of `${hotlist_priority}`)
* irc: display SETNAME command in channels and private buffers, add options irc.color.message_setname and irc.look.smart_filter_setname (issue #1805)
* irc: add option irc.look.display_pv_nick_change
+41
View File
@@ -4189,6 +4189,47 @@ if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt"))
[NOTE]
This function is not available in scripting API.
==== file_compress
_WeeChat ≥ 3.7._
Compress a file with gzip or zstd.
Prototype:
[source,c]
----
int weechat_file_compress (const char *from, const char *to,
const char *compressor, int compression_level);
----
Arguments:
* _from_: source file
* _to_: destination file
* _compressor_: the compressor to use, one of:
** _gzip_: gzip compression
** _zstd_: zstandard compression
* _compression_level_: compression level, between 1 (fast, low compression) to
100 (slow, best compression)
Return value:
* 1 if OK, 0 if error
C example:
[source,c]
----
if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
{
/* OK */
}
----
[NOTE]
This function is not available in scripting API.
[[util]]
=== Util
+41
View File
@@ -4258,6 +4258,47 @@ if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt"))
[NOTE]
Cette fonction n'est pas disponible dans l'API script.
==== file_compress
_WeeChat ≥ 3.7._
Compresser un fichier avec gzip ou zstd.
Prototype :
[source,c]
----
int weechat_file_compress (const char *from, const char *to,
const char *compressor, int compression_level);
----
Paramètres :
* _from_ : fichier source
* _to_ : fichier cible
* _compressor_ : le compresseur à utiliser, un parmi :
** _gzip_ : compression gzip
** _zstd_ : compression zstandard
* _compression_level_ : niveau de compression, entre 1 (rapide, peu de
compression) à 100 (lent, meilleure compression)
Valeur de retour :
* 1 si OK, 0 si erreur
Exemple en C :
[source,c]
----
if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
{
/* OK */
}
----
[NOTE]
Cette fonction n'est pas disponible dans l'API script.
[[util]]
=== Util
+42
View File
@@ -4342,6 +4342,48 @@ if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt"))
[NOTE]
Questa funzione non è disponibile nelle API per lo scripting.
// TRANSLATION MISSING
==== file_compress
_WeeChat ≥ 3.7._
Compress a file with gzip or zstd.
Prototipo:
[source,c]
----
int weechat_file_compress (const char *from, const char *to,
const char *compressor, int compression_level);
----
Argomenti:
* _from_: source file
* _to_: destination file
* _compressor_: the compressor to use, one of:
** _gzip_: gzip compression
** _zstd_: zstandard compression
* _compression_level_: compression level, between 1 (fast, low compression) to
100 (slow, best compression)
Valore restituito:
* 1 if OK, 0 if error
Esempio in C:
[source,c]
----
if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
{
/* OK */
}
----
[NOTE]
Questa funzione non è disponibile nelle API per lo scripting.
[[util]]
=== Utilità
+42
View File
@@ -4258,6 +4258,48 @@ if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt"))
[NOTE]
スクリプト API ではこの関数を利用できません。
// TRANSLATION MISSING
==== file_compress
_WeeChat ≥ 3.7._
Compress a file with gzip or zstd.
プロトタイプ:
[source,c]
----
int weechat_file_compress (const char *from, const char *to,
const char *compressor, int compression_level);
----
引数:
* _from_: source file
* _to_: destination file
* _compressor_: the compressor to use, one of:
** _gzip_: gzip compression
** _zstd_: zstandard compression
* _compression_level_: compression level, between 1 (fast, low compression) to
100 (slow, best compression)
戻り値:
* 1 if OK, 0 if error
C 言語での使用例:
[source,c]
----
if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
{
/* OK */
}
----
[NOTE]
スクリプト API ではこの関数を利用できません。
[[util]]
=== ユーティリティ
+42
View File
@@ -4053,6 +4053,48 @@ if (weechat_file_copy ("/tmp/test.txt", "/path/to/test2.txt"))
Неке корисне функције.
// TRANSLATION MISSING
==== file_compress
_WeeChat ≥ 3.7._
Compress a file with gzip or zstd.
Прототип:
[source,c]
----
int weechat_file_compress (const char *from, const char *to,
const char *compressor, int compression_level);
----
Аргументи:
* _from_: изворишни фајл
* _to_: одредишни фајл
* _compressor_: the compressor to use, one of:
** _gzip_: gzip compression
** _zstd_: zstandard compression
* _compression_level_: compression level, between 1 (fast, low compression) to
100 (slow, best compression)
Повратна вредност:
* 1 ако је копирање OK, 0 у случају грешке
C пример:
[source,c]
----
if (weechat_file_compress ("/tmp/test.txt", "/tmp/test.txt.zst", "zstd", 50))
{
/* OK */
}
----
[NOTE]
Ова функција није доступна у API скриптовања.
==== util_timeval_cmp
Пореди две „timeval” структуре.
+2
View File
@@ -88,6 +88,8 @@ include_directories(${GNUTLS_INCLUDE_PATH})
include_directories(${CURL_INCLUDE_DIRS})
include_directories(${ZSTD_INCLUDE_DIRS})
include_directories(${CMAKE_BINARY_DIR})
add_library(weechat_core STATIC ${LIB_CORE_SRC})
target_link_libraries(weechat_core coverage_config)
+1 -1
View File
@@ -17,7 +17,7 @@
# along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
#
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(GCRYPT_CFLAGS) $(GNUTLS_CFLAGS) $(CURL_CFLAGS)
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(GCRYPT_CFLAGS) $(GNUTLS_CFLAGS) $(CURL_CFLAGS) $(ZLIB_CFLAGS) $(ZSTD_CFLAGS)
noinst_LIBRARIES = lib_weechat_core.a
+588 -318
View File
@@ -44,6 +44,8 @@
#include <unistd.h>
#include <dirent.h>
#include <ftw.h>
#include <zlib.h>
#include <zstd.h>
#include "weechat.h"
#include "wee-config.h"
@@ -293,324 +295,6 @@ dir_rmtree (const char *directory)
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_data_dir) + 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_data_dir,
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;
}
/*
* 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, 65536, 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.
*
@@ -1038,3 +722,589 @@ dir_get_string_home_dirs ()
return string_rebuild_split_string ((const char **)dirs, ":", 0, -1);
}
/*
* 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_data_dir) + 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_data_dir,
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;
}
/*
* 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, 65536, 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;
}
/*
* Compresses a file with gzip.
*
* The output file must not exist.
*
* Returns:
* 1: OK
* 0: error
*/
int
dir_file_compress_gzip (const char *from, const char *to,
int compression_level)
{
FILE *source, *dest;
z_stream strm;
unsigned char *buffer_in, *buffer_out;
int rc, ret, flush;
size_t buffer_size, have;
source = NULL;
dest = NULL;
buffer_size = 256 * 1024;
buffer_in = NULL;
buffer_out = NULL;
rc = 0;
if (!from || !to || (compression_level < 1) || (compression_level > 9))
goto end;
if (access (to, F_OK) == 0)
goto end;
buffer_in = malloc (buffer_size);
if (!buffer_in)
goto end;
buffer_out = malloc (buffer_size);
if (!buffer_out)
goto end;
source = fopen (from, "rb");
if (!source)
goto end;
dest = fopen (to, "wb");
if (!dest)
goto end;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit2 (
&strm,
compression_level,
Z_DEFLATED, /* method */
15 + 16, /* + 16 = gzip instead of zlib */
8, /* memLevel */
Z_DEFAULT_STRATEGY); /* strategy */
if (ret != Z_OK)
goto end;
do
{
strm.avail_in = fread (buffer_in, 1, buffer_size, source);
if (ferror (source))
goto error;
flush = feof (source) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = buffer_in;
do
{
strm.avail_out = buffer_size;
strm.next_out = buffer_out;
ret = deflate (&strm, flush);
if (ret == Z_STREAM_ERROR)
goto error;
have = buffer_size - strm.avail_out;
if (fwrite (buffer_out, 1, have, dest) != have || ferror (dest))
goto error;
} while (strm.avail_out == 0);
if (strm.avail_in != 0)
goto error;
} while (flush != Z_FINISH);
if (ret != Z_STREAM_END)
goto error;
(void) deflateEnd (&strm);
rc = 1;
goto end;
error:
(void) deflateEnd (&strm);
unlink (to);
end:
if (buffer_in)
free (buffer_in);
if (buffer_out)
free (buffer_out);
if (source)
fclose (source);
if (dest)
fclose (dest);
return rc;
}
/*
* Compresses a file with zstandard.
*
* The output file must not exist.
*
* Returns:
* 1: OK
* 0: error
*/
int
dir_file_compress_zstd (const char *from, const char *to,
int compression_level)
{
FILE *source, *dest;
void *buffer_in, *buffer_out;
size_t buffer_in_size, buffer_out_size, num_read, remaining;
int rc, finished, last_chunk;
ZSTD_CCtx *cctx;
ZSTD_EndDirective mode;
ZSTD_inBuffer input;
ZSTD_outBuffer output;
source = NULL;
dest = NULL;
buffer_in = NULL;
buffer_out = NULL;
cctx = NULL;
rc = 0;
if (!from || !to || (compression_level < 1) || (compression_level > 19))
goto end;
if (access (to, F_OK) == 0)
goto end;
buffer_in_size = ZSTD_CStreamInSize ();
buffer_in = malloc (buffer_in_size);
if (!buffer_in)
goto end;
buffer_out_size = ZSTD_CStreamOutSize ();
buffer_out = malloc (buffer_out_size);
if (!buffer_out)
goto end;
source = fopen (from, "rb");
if (!source)
goto end;
dest = fopen (to, "wb");
if (!dest)
goto end;
cctx = ZSTD_createCCtx ();
if (!cctx)
goto end;
ZSTD_CCtx_setParameter (cctx, ZSTD_c_compressionLevel, compression_level);
while (1)
{
num_read = fread (buffer_in, 1, buffer_in_size, source);
if (ferror (source))
goto error;
last_chunk = (num_read < buffer_in_size);
mode = (last_chunk) ? ZSTD_e_end : ZSTD_e_continue;
input.src = buffer_in;
input.size = num_read;
input.pos = 0;
finished = 0;
while (!finished)
{
output.dst = buffer_out;
output.size = buffer_out_size;
output.pos = 0;
remaining = ZSTD_compressStream2(cctx, &output , &input, mode);
if (ZSTD_isError (remaining))
goto error;
fwrite (buffer_out, 1, output.pos, dest);
finished = (last_chunk) ? (remaining == 0) : (input.pos == input.size);
};
if (input.pos != input.size)
goto error;
if (last_chunk)
break;
}
rc = 1;
goto end;
error:
if (cctx)
{
ZSTD_freeCCtx (cctx);
cctx = NULL;
}
unlink (to);
end:
if (cctx)
ZSTD_freeCCtx (cctx);
if (buffer_in)
free (buffer_in);
if (buffer_out)
free (buffer_out);
if (source)
fclose (source);
if (dest)
fclose (dest);
return rc;
}
/*
* Compresses a file with gzip or zstandard.
*
* The output file must not exist.
*
* Supported values for parameter "compressor":
* - "gzip": gzip compression (via zlib)
* - "zstd": zstandard compression
*
* Parameter "compression_level" is the compression level as percentage:
* from 1 (fast, low compression) to 100 (slow, best compression).
*
* Returns:
* 1: OK
* 0: error
*/
int
dir_file_compress (const char *filename_input,
const char *filename_output,
const char *compressor,
int compression_level)
{
int level;
if (!compressor || (compression_level < 1) || (compression_level > 100))
return 0;
if (strcmp (compressor, "gzip") == 0)
{
/* convert percent to zlib compression level (1-9) */
level = (((compression_level - 1) * 9) / 100) + 1;
return dir_file_compress_gzip (filename_input, filename_output, level);
}
else if (strcmp (compressor, "zstd") == 0)
{
/* convert percent to zstd compression level (1-19) */
level = (((compression_level - 1) * 19) / 100) + 1;
return dir_file_compress_zstd (filename_input, filename_output, level);
}
else
{
return 0;
}
}
+5 -3
View File
@@ -25,6 +25,9 @@ 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_create_home_dirs ();
extern void dir_remove_home_dirs ();
extern char *dir_get_string_home_dirs ();
extern void dir_exec_on_files (const char *directory, int recurse_subdirs,
int hidden_files,
void (*callback)(void *data,
@@ -34,8 +37,7 @@ 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 ();
extern int dir_file_compress (const char *from, const char *to,
const char *compressor, int compression_level);
#endif /* WEECHAT_DIR_H */
+3
View File
@@ -47,6 +47,9 @@ list(APPEND EXTRA_LIBS "m")
list(APPEND EXTRA_LIBS ${CURL_LIBRARIES})
list(APPEND EXTRA_LIBS ${ZLIB_LIBRARY})
list(APPEND EXTRA_LIBS ${LIBZSTD_LDFLAGS})
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# link with resolv lib on macOS
list(APPEND EXTRA_LIBS "resolv")
+2
View File
@@ -48,6 +48,8 @@ weechat_headless_LDADD = ./../../../core/lib_weechat_core.a \
$(GCRYPT_LFLAGS) \
$(GNUTLS_LFLAGS) \
$(CURL_LFLAGS) \
$(ZLIB_LFLAGS) \
$(ZSTD_LFLAGS) \
-lm
weechat_headless_SOURCES = main.c
+2
View File
@@ -45,6 +45,8 @@ weechat_LDADD = ./../../../core/lib_weechat_core.a \
$(GCRYPT_LFLAGS) \
$(GNUTLS_LFLAGS) \
$(CURL_LFLAGS) \
$(ZLIB_LFLAGS) \
$(ZSTD_LFLAGS) \
-lm
weechat_SOURCES = main.c
+1
View File
@@ -676,6 +676,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv)
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->file_compress = &dir_file_compress;
new_plugin->util_timeval_cmp = &util_timeval_cmp;
new_plugin->util_timeval_diff = &util_timeval_diff;
+7 -1
View File
@@ -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 "20220925-01"
#define WEECHAT_PLUGIN_API_VERSION "20220926-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -402,6 +402,8 @@ struct t_weechat_plugin
void *callback_data);
char *(*file_get_content) (const char *filename);
int (*file_copy) (const char *from, const char *to);
int (*file_compress) (const char *from, const char *to,
const char *compressor, int compression_level);
/* util */
int (*util_timeval_cmp) (struct timeval *tv1, struct timeval *tv2);
@@ -1415,6 +1417,10 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
(weechat_plugin->file_get_content)(__filename)
#define weechat_file_copy(__from, __to) \
(weechat_plugin->file_copy)(__from, __to)
#define weechat_file_compress(__from, __to, __compressor, \
__compression_level) \
(weechat_plugin->file_compress)(__from, __to, __compressor, \
__compression_level)
/* util */
#define weechat_util_timeval_cmp(__time1, __time2) \
+2
View File
@@ -137,6 +137,8 @@ target_link_libraries(tests
weechat_core
${EXTRA_LIBS}
${CURL_LIBRARIES}
${ZLIB_LIBRARY}
${LIBZSTD_LDFLAGS}
${CPPUTEST_LIBRARIES}
-rdynamic
)
+2
View File
@@ -66,6 +66,8 @@ tests_LDADD = ./../src/core/lib_weechat_core.a \
$(GCRYPT_LFLAGS) \
$(GNUTLS_LFLAGS) \
$(CURL_LFLAGS) \
$(ZLIB_LFLAGS) \
$(ZSTD_LFLAGS) \
$(CPPUTEST_LFLAGS) \
-lm
tests_LDFLAGS = -rdynamic