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

xfer: add option xfer.file.download_temporary_suffix with default value ".part" (closes #1237)

This commit is contained in:
Sébastien Helleu
2019-10-05 18:11:39 +02:00
parent 6c23f632b1
commit 3c0bdc18f3
28 changed files with 317 additions and 65 deletions
+9
View File
@@ -64,6 +64,7 @@ struct t_config_option *xfer_config_file_auto_rename;
struct t_config_option *xfer_config_file_auto_resume;
struct t_config_option *xfer_config_file_convert_spaces;
struct t_config_option *xfer_config_file_download_path;
struct t_config_option *xfer_config_file_download_temporary_suffix;
struct t_config_option *xfer_config_file_upload_path;
struct t_config_option *xfer_config_file_use_nick_in_filename;
@@ -385,6 +386,14 @@ xfer_config_init ()
"(note: content is evaluated, see /help eval)"),
NULL, 0, 0, "%h/xfer", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
xfer_config_file_download_temporary_suffix = weechat_config_new_option (
xfer_config_file, ptr_section,
"download_temporary_suffix", "string",
N_("temporary filename suffix used during the transfer for a file "
"received, it is removed after successful transfer; "
"if empty string, no filename suffix is used during the transfer"),
NULL, 0, 0, ".part", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
xfer_config_file_upload_path = weechat_config_new_option (
xfer_config_file, ptr_section,
"upload_path", "string",
+1
View File
@@ -52,6 +52,7 @@ extern struct t_config_option *xfer_config_file_auto_resume;
extern struct t_config_option *xfer_config_file_auto_check_crc32;
extern struct t_config_option *xfer_config_file_convert_spaces;
extern struct t_config_option *xfer_config_file_download_path;
extern struct t_config_option *xfer_config_file_download_temporary_suffix;
extern struct t_config_option *xfer_config_file_upload_path;
extern struct t_config_option *xfer_config_file_use_nick_in_filename;
+1 -1
View File
@@ -255,7 +255,7 @@ xfer_dcc_resume_hash (struct t_xfer *xfer)
while (fd <= 0)
{
fd = open (xfer->local_filename, O_RDONLY);
fd = open (xfer->temp_local_filename, O_RDONLY);
if (fd < 0)
{
if (errno == EINTR)
+131 -45
View File
@@ -70,6 +70,135 @@ xfer_file_resume (struct t_xfer *xfer, const char *filename)
return 0;
}
/*
* Checks if file can be downloaded with a given suffix index (if 0 the
* filename is unchanged, otherwise .1, .2, etc. are added to the filename).
*
* Returns 1 if the file can be downloaded with this suffix, 0 if it can not.
*/
int
xfer_file_check_suffix (struct t_xfer *xfer, int suffix)
{
char *new_filename, *new_temp_filename;
const char *ptr_suffix;
int rc, length_suffix, length, filename_exists, temp_filename_exists;
int same_files;
rc = 0;
new_filename = NULL;
new_temp_filename = NULL;
ptr_suffix = weechat_config_string (
xfer_config_file_download_temporary_suffix);
length_suffix = (ptr_suffix) ? strlen (ptr_suffix) : 0;
/* build filename with suffix */
if (suffix == 0)
{
new_filename = strdup (xfer->local_filename);
}
else
{
length = strlen (xfer->local_filename) + 16 + 1;
new_filename = malloc (length);
if (new_filename)
{
snprintf (new_filename, length, "%s.%d",
xfer->local_filename,
suffix);
}
}
if (!new_filename)
goto error;
/* build temp filename with suffix */
length = strlen (new_filename) + length_suffix + 1;
new_temp_filename = malloc (length);
if (!new_temp_filename)
goto error;
snprintf (new_temp_filename, length,
"%s%s",
new_filename,
(ptr_suffix) ? ptr_suffix : "");
filename_exists = (access (new_filename, F_OK) == 0);
temp_filename_exists = (access (new_temp_filename, F_OK) == 0);
same_files = (length_suffix == 0);
/* if both filenames don't exist, we can use this prefix */
if (!filename_exists && !temp_filename_exists)
goto use_prefix;
/*
* we try to resume if one of this condition is true:
* - filename == temp filename and it exists
* - filename != temp filename and only the temp filename exists
* in any other case, we skip this suffix index
*/
if ((same_files && filename_exists)
|| (!same_files && !filename_exists && temp_filename_exists))
{
if (xfer_file_resume (xfer, new_temp_filename))
goto use_prefix;
}
/* we skip this suffix index */
goto end;
use_prefix:
free (xfer->local_filename);
xfer->local_filename = new_filename;
xfer->temp_local_filename = new_temp_filename;
return 1;
error:
/*
* in case of error, we remove the local filename and return 1 to stop the
* infinite loop used to find a suffix index
*/
free (xfer->local_filename);
xfer->local_filename = NULL;
rc = 1;
end:
if (new_filename)
free (new_filename);
if (new_temp_filename)
free (new_temp_filename);
return rc;
}
/*
* Finds the suffix needed for a file, if the file already exists.
*
* If no suffix is needed, nothing is changed in the xfer.
* If a suffix is needed, temp_local_filename and local_filename are changed
* and filename_suffix is set with the suffix number (starts to 1).
*/
void
xfer_file_find_suffix (struct t_xfer *xfer)
{
if (xfer_file_check_suffix (xfer, 0))
return;
/* if auto rename is not set, then abort xfer */
if (!xfer_config_file_auto_rename)
{
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return;
}
/* loop until we find a suffix we can use, starting with suffix == 1 */
xfer->filename_suffix = 0;
while (!xfer_file_check_suffix (xfer, ++xfer->filename_suffix))
{
}
}
/*
* Searches for local filename for a xfer.
*
@@ -80,8 +209,7 @@ xfer_file_resume (struct t_xfer *xfer, const char *filename)
void
xfer_file_find_filename (struct t_xfer *xfer)
{
char *dir_separator, *path, *filename2;
int length;
char *dir_separator, *path;
if (!XFER_IS_FILE(xfer->type))
return;
@@ -119,49 +247,7 @@ xfer_file_find_filename (struct t_xfer *xfer)
free (path);
/* file already exists? */
if (access (xfer->local_filename, F_OK) == 0)
{
if (xfer_file_resume (xfer, xfer->local_filename))
return;
/* if auto rename is not set, then abort xfer */
if (!xfer_config_file_auto_rename)
{
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return;
}
length = strlen (xfer->local_filename) + 16;
filename2 = malloc (length);
if (!filename2)
{
xfer_close (xfer, XFER_STATUS_FAILED);
xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
return;
}
xfer->filename_suffix = 0;
do
{
xfer->filename_suffix++;
snprintf (filename2, length, "%s.%d",
xfer->local_filename,
xfer->filename_suffix);
if (access (filename2, F_OK) == 0)
{
if (xfer_file_resume (xfer, filename2))
break;
}
else
break;
}
while (1);
free (xfer->local_filename);
xfer->local_filename = strdup (filename2);
free (filename2);
}
xfer_file_find_suffix (xfer);
}
/*
+6 -2
View File
@@ -290,12 +290,16 @@ xfer_network_recv_file_fork (struct t_xfer *xfer)
return;
if (xfer->start_resume > 0)
xfer->file = open (xfer->local_filename,
{
xfer->file = open (xfer->temp_local_filename,
O_APPEND | O_WRONLY | O_NONBLOCK);
}
else
xfer->file = open (xfer->local_filename,
{
xfer->file = open (xfer->temp_local_filename,
O_CREAT | O_TRUNC | O_WRONLY | O_NONBLOCK,
0644);
}
switch (pid = fork ())
{
+18 -3
View File
@@ -346,17 +346,26 @@ xfer_close (struct t_xfer *xfer, enum t_xfer_status status)
|| (xfer->status == XFER_STATUS_ABORTED))
&& XFER_IS_FILE(xfer->type)
&& XFER_IS_RECV(xfer->type)
&& xfer->local_filename
&& xfer->temp_local_filename
&& xfer->pos == 0)
{
/* erase file only if really empty on disk */
if (stat (xfer->local_filename, &st) != -1)
if (stat (xfer->temp_local_filename, &st) != -1)
{
if ((unsigned long long) st.st_size == 0)
unlink (xfer->local_filename);
unlink (xfer->temp_local_filename);
}
}
/* rename received file if it has a suffix */
if ((xfer->status == XFER_STATUS_DONE)
&& XFER_IS_FILE(xfer->type)
&& XFER_IS_RECV(xfer->type)
&& (strcmp (xfer->local_filename, xfer->temp_local_filename) != 0))
{
rename (xfer->temp_local_filename, xfer->local_filename);
}
if (XFER_IS_FILE(xfer->type))
xfer_file_calculate_speed (xfer, 1);
@@ -500,6 +509,7 @@ xfer_alloc ()
new_xfer->unterminated_message = NULL;
new_xfer->file = -1;
new_xfer->local_filename = NULL;
new_xfer->temp_local_filename = NULL;
new_xfer->filename_suffix = -1;
new_xfer->pos = 0;
new_xfer->ack = 0;
@@ -955,6 +965,8 @@ xfer_free (struct t_xfer *xfer)
free (xfer->unterminated_message);
if (xfer->local_filename)
free (xfer->local_filename);
if (xfer->temp_local_filename)
free (xfer->temp_local_filename);
if (xfer->hash_handle)
{
gcry_md_close (*xfer->hash_handle);
@@ -1688,6 +1700,8 @@ xfer_add_to_infolist (struct t_infolist *infolist, struct t_xfer *xfer)
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "local_filename", xfer->local_filename))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "temp_local_filename", xfer->temp_local_filename))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "filename_suffix", xfer->filename_suffix))
return 0;
snprintf (value, sizeof (value), "%llu", xfer->pos);
@@ -1776,6 +1790,7 @@ xfer_print_log ()
weechat_log_printf (" unterminated_message. . : '%s'", ptr_xfer->unterminated_message);
weechat_log_printf (" file. . . . . . . . . . : %d", ptr_xfer->file);
weechat_log_printf (" local_filename. . . . . : '%s'", ptr_xfer->local_filename);
weechat_log_printf (" temp_local_filename . . : '%s'", ptr_xfer->temp_local_filename);
weechat_log_printf (" filename_suffix . . . . : %d", ptr_xfer->filename_suffix);
weechat_log_printf (" pos . . . . . . . . . . : %llu", ptr_xfer->pos);
weechat_log_printf (" ack . . . . . . . . . . : %llu", ptr_xfer->ack);
+3
View File
@@ -170,6 +170,9 @@ struct t_xfer
char *unterminated_message; /* beginning of a message */
int file; /* local file (read or write) */
char *local_filename; /* local filename (with path) */
char *temp_local_filename; /* local filename filename with */
/* temp. suffix (during transfer, */
/* for receive file only) */
int filename_suffix; /* suffix (like .1) if renaming file */
unsigned long long pos; /* number of bytes received/sent */
unsigned long long ack; /* number of bytes received OK */