mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Make progress work for large files on Windows.
* common/iobuf.c (iobuf_get_filelength): Change return type to uint64_t and remove the overflow args. For Windows always use GetFileSizeEx which is available since the long EOL-ed Windows XP. * g10/sign.c (write_plaintext_packet): Adjust for changed iobuf_get_filelength. * g10/encrypt.c (encrypt_simple, encrypt_crypt): Ditto. * g10/photoid.c (generate_photo_id): Ditto. Also add an upper limit. * g10/filter.h (progress_filter_context_t): Change amount values to use uint64_t. * g10/progress.c (write_status_progress): Change accordingly. -- GnuPG-bug-id: 6534 Backported-from: 808494b48577c2efb894a0877f59d9c4ed664f56
This commit is contained in:
parent
8425cdcc8e
commit
1b60aab2c4
2
NEWS
2
NEWS
@ -15,6 +15,8 @@ Noteworthy changes in version 2.2.42 (unreleased)
|
|||||||
* gpg: Emit status line and proper diagnostics for write errors.
|
* gpg: Emit status line and proper diagnostics for write errors.
|
||||||
[T6528]
|
[T6528]
|
||||||
|
|
||||||
|
* gpg: Make progress work for large files on Windows. [T6534]
|
||||||
|
|
||||||
* gpgsm: Support ECC certificates. [T6253]
|
* gpgsm: Support ECC certificates. [T6253]
|
||||||
|
|
||||||
* gpgsm: Also announce AES256-CBC in signatures. [rGaa397fdcdb21]
|
* gpgsm: Also announce AES256-CBC in signatures. [rGaa397fdcdb21]
|
||||||
|
@ -2365,13 +2365,10 @@ iobuf_set_limit (iobuf_t a, off_t nlimit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the length of the file behind A. If there is no file, return 0. */
|
||||||
off_t
|
uint64_t
|
||||||
iobuf_get_filelength (iobuf_t a, int *overflow)
|
iobuf_get_filelength (iobuf_t a)
|
||||||
{
|
{
|
||||||
if (overflow)
|
|
||||||
*overflow = 0;
|
|
||||||
|
|
||||||
/* Hmmm: file_filter may have already been removed */
|
/* Hmmm: file_filter may have already been removed */
|
||||||
for ( ; a->chain; a = a->chain )
|
for ( ; a->chain; a = a->chain )
|
||||||
;
|
;
|
||||||
@ -2384,56 +2381,18 @@ iobuf_get_filelength (iobuf_t a, int *overflow)
|
|||||||
gnupg_fd_t fp = b->fp;
|
gnupg_fd_t fp = b->fp;
|
||||||
|
|
||||||
#if defined(HAVE_W32_SYSTEM)
|
#if defined(HAVE_W32_SYSTEM)
|
||||||
ulong size;
|
|
||||||
static int (* __stdcall get_file_size_ex) (void *handle,
|
|
||||||
LARGE_INTEGER *r_size);
|
|
||||||
static int get_file_size_ex_initialized;
|
|
||||||
|
|
||||||
if (!get_file_size_ex_initialized)
|
|
||||||
{
|
|
||||||
void *handle;
|
|
||||||
|
|
||||||
handle = dlopen ("kernel32.dll", RTLD_LAZY);
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
get_file_size_ex = dlsym (handle, "GetFileSizeEx");
|
|
||||||
if (!get_file_size_ex)
|
|
||||||
dlclose (handle);
|
|
||||||
}
|
|
||||||
get_file_size_ex_initialized = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_file_size_ex)
|
|
||||||
{
|
|
||||||
/* This is a newer system with GetFileSizeEx; we use this
|
|
||||||
then because it seem that GetFileSize won't return a
|
|
||||||
proper error in case a file is larger than 4GB. */
|
|
||||||
LARGE_INTEGER exsize;
|
LARGE_INTEGER exsize;
|
||||||
|
|
||||||
if (get_file_size_ex (fp, &exsize))
|
if (GetFileSizeEx (fp, &exsize))
|
||||||
{
|
return exsize.QuadPart;
|
||||||
if (!exsize.u.HighPart)
|
|
||||||
return exsize.u.LowPart;
|
|
||||||
if (overflow)
|
|
||||||
*overflow = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((size=GetFileSize (fp, NULL)) != 0xffffffff)
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
log_error ("GetFileSize for handle %p failed: %s\n",
|
log_error ("GetFileSize for handle %p failed: %s\n",
|
||||||
fp, w32_strerror (-1));
|
fp, w32_strerror (-1));
|
||||||
#else /*!HAVE_W32_SYSTEM*/
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
{
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if ( !fstat (FD2INT (fp), &st) )
|
if ( !fstat (fp, &st) )
|
||||||
return st.st_size;
|
return st.st_size;
|
||||||
log_error("fstat() failed: %s\n", strerror(errno) );
|
log_error("fstat() failed: %s\n", strerror(errno) );
|
||||||
}
|
|
||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,12 +556,8 @@ size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen);
|
|||||||
size_t iobuf_copy (iobuf_t dest, iobuf_t source);
|
size_t iobuf_copy (iobuf_t dest, iobuf_t source);
|
||||||
|
|
||||||
/* Return the size of any underlying file. This only works with
|
/* Return the size of any underlying file. This only works with
|
||||||
file_filter based pipelines.
|
file_filter based pipelines. */
|
||||||
|
uint64_t iobuf_get_filelength (iobuf_t a);
|
||||||
On Win32, it is sometimes not possible to determine the size of
|
|
||||||
files larger than 4GB. In this case, *OVERFLOW (if not NULL) is
|
|
||||||
set to 1. Otherwise, *OVERFLOW is set to 0. */
|
|
||||||
off_t iobuf_get_filelength (iobuf_t a, int *overflow);
|
|
||||||
#define IOBUF_FILELENGTH_LIMIT 0xffffffff
|
#define IOBUF_FILELENGTH_LIMIT 0xffffffff
|
||||||
|
|
||||||
/* Return the file descriptor designating the underlying file. This
|
/* Return the file descriptor designating the underlying file. This
|
||||||
|
@ -500,12 +500,12 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
|
|||||||
|
|
||||||
if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
|
if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
|
||||||
{
|
{
|
||||||
off_t tmpsize;
|
uint64_t tmpsize;
|
||||||
int overflow;
|
|
||||||
|
|
||||||
if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
|
tmpsize = iobuf_get_filelength(inp);
|
||||||
&& !overflow && opt.verbose)
|
if (!tmpsize && opt.verbose)
|
||||||
log_info(_("WARNING: '%s' is an empty file\n"), filename );
|
log_info(_("WARNING: '%s' is an empty file\n"), filename );
|
||||||
|
|
||||||
/* We can't encode the length of very large files because
|
/* We can't encode the length of very large files because
|
||||||
OpenPGP uses only 32 bit for file sizes. So if the
|
OpenPGP uses only 32 bit for file sizes. So if the
|
||||||
size of a file is larger than 2^32 minus some bytes for
|
size of a file is larger than 2^32 minus some bytes for
|
||||||
@ -936,11 +936,10 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
|
|||||||
if (filename && *filename
|
if (filename && *filename
|
||||||
&& !iobuf_is_pipe_filename (filename) && !opt.textmode )
|
&& !iobuf_is_pipe_filename (filename) && !opt.textmode )
|
||||||
{
|
{
|
||||||
off_t tmpsize;
|
uint64_t tmpsize;
|
||||||
int overflow;
|
|
||||||
|
|
||||||
if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
|
tmpsize = iobuf_get_filelength (inp);
|
||||||
&& !overflow && opt.verbose)
|
if (!tmpsize && opt.verbose)
|
||||||
log_info(_("WARNING: '%s' is an empty file\n"), filename );
|
log_info(_("WARNING: '%s' is an empty file\n"), filename );
|
||||||
/* We can't encode the length of very large files because
|
/* We can't encode the length of very large files because
|
||||||
OpenPGP uses only 32 bit for file sizes. So if the size
|
OpenPGP uses only 32 bit for file sizes. So if the size
|
||||||
|
@ -155,9 +155,9 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
char *what; /* description */
|
char *what; /* description */
|
||||||
u32 last_time; /* last time reported */
|
u32 last_time; /* last time reported */
|
||||||
unsigned long last; /* last amount reported */
|
uint64_t last; /* last amount reported */
|
||||||
unsigned long offset; /* current amount */
|
uint64_t offset; /* current amount */
|
||||||
unsigned long total; /* total amount */
|
uint64_t total; /* total amount */
|
||||||
int refcount;
|
int refcount;
|
||||||
} progress_filter_context_t;
|
} progress_filter_context_t;
|
||||||
|
|
||||||
|
@ -3399,7 +3399,13 @@ main (int argc, char **argv)
|
|||||||
case oAllowFreeformUID: opt.allow_freeform_uid = 1; break;
|
case oAllowFreeformUID: opt.allow_freeform_uid = 1; break;
|
||||||
case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break;
|
case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break;
|
||||||
case oNoLiteral: opt.no_literal = 1; break;
|
case oNoLiteral: opt.no_literal = 1; break;
|
||||||
case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
|
|
||||||
|
case oSetFilesize:
|
||||||
|
/* There are restricts on the value (e.g. < 2^32); you
|
||||||
|
* need to check the entire code to understand this. */
|
||||||
|
opt.set_filesize = pargs.r.ret_ulong;
|
||||||
|
break;
|
||||||
|
|
||||||
case oFastListMode: opt.fast_list_mode = 1; break;
|
case oFastListMode: opt.fast_list_mode = 1; break;
|
||||||
case oFixedListMode: /* Dummy */ break;
|
case oFixedListMode: /* Dummy */ break;
|
||||||
case oLegacyListMode: opt.legacy_list_mode = 1; break;
|
case oLegacyListMode: opt.legacy_list_mode = 1; break;
|
||||||
|
@ -2869,8 +2869,7 @@ literal (const char *option, int argc, char *argv[], void *cookie)
|
|||||||
if (data->file)
|
if (data->file)
|
||||||
{
|
{
|
||||||
iobuf_t in;
|
iobuf_t in;
|
||||||
int overflow;
|
uint64_t off;
|
||||||
off_t off;
|
|
||||||
|
|
||||||
in = iobuf_open (data->filename);
|
in = iobuf_open (data->filename);
|
||||||
if (! in)
|
if (! in)
|
||||||
@ -2881,10 +2880,10 @@ literal (const char *option, int argc, char *argv[], void *cookie)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
off = iobuf_get_filelength (in, &overflow);
|
off = iobuf_get_filelength (in);
|
||||||
iobuf_close (in);
|
iobuf_close (in);
|
||||||
|
|
||||||
if (overflow || off == 0)
|
if (off == 0)
|
||||||
/* Length is unknown or there was an error
|
/* Length is unknown or there was an error
|
||||||
(unfortunately, iobuf_get_filelength doesn't
|
(unfortunately, iobuf_get_filelength doesn't
|
||||||
distinguish between 0 length files and an error!).
|
distinguish between 0 length files and an error!).
|
||||||
|
@ -52,12 +52,11 @@ generate_photo_id (ctrl_t ctrl, PKT_public_key *pk,const char *photo_name)
|
|||||||
{
|
{
|
||||||
PKT_user_id *uid;
|
PKT_user_id *uid;
|
||||||
int error=1,i;
|
int error=1,i;
|
||||||
unsigned int len;
|
uint64_t len;
|
||||||
char *filename;
|
char *filename;
|
||||||
byte *photo=NULL;
|
byte *photo=NULL;
|
||||||
byte header[16];
|
byte header[16];
|
||||||
IOBUF file;
|
IOBUF file;
|
||||||
int overflow;
|
|
||||||
|
|
||||||
header[0]=0x10; /* little side of photo header length */
|
header[0]=0x10; /* little side of photo header length */
|
||||||
header[1]=0; /* big side of photo header length */
|
header[1]=0; /* big side of photo header length */
|
||||||
@ -125,11 +124,18 @@ generate_photo_id (ctrl_t ctrl, PKT_public_key *pk,const char *photo_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
len=iobuf_get_filelength(file, &overflow);
|
len = iobuf_get_filelength(file);
|
||||||
if(len>6144 || overflow)
|
if(len>6144)
|
||||||
{
|
{
|
||||||
tty_printf( _("This JPEG is really large (%d bytes) !\n"),len);
|
/* We silently skip JPEGs larger than 1MiB because we have a
|
||||||
if(!cpr_get_answer_is_yes("photoid.jpeg.size",
|
* 2MiB limit on the user ID packets and we need some limit
|
||||||
|
* anyway because the returned u64 is larger than the u32 or
|
||||||
|
* OpenPGP. Note that the diagnostic may print a wrong
|
||||||
|
* value if the value is really large; we don't fix this to
|
||||||
|
* avoid a string change. */
|
||||||
|
tty_printf( _("This JPEG is really large (%d bytes) !\n"), (int)len);
|
||||||
|
if(len > 1024*1024
|
||||||
|
|| !cpr_get_answer_is_yes("photoid.jpeg.size",
|
||||||
_("Are you sure you want to use it? (y/N) ")))
|
_("Are you sure you want to use it? (y/N) ")))
|
||||||
{
|
{
|
||||||
iobuf_close(file);
|
iobuf_close(file);
|
||||||
|
@ -72,13 +72,11 @@ release_progress_context (progress_filter_context_t *pfx)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_status_progress (const char *what,
|
write_status_progress (const char *what, uint64_t current, uint64_t total)
|
||||||
unsigned long current, unsigned long total_arg)
|
|
||||||
{
|
{
|
||||||
char buffer[60];
|
char buffer[60];
|
||||||
char units[] = "BKMGTPEZY?";
|
char units[] = "BKMGTPEZY?";
|
||||||
int unitidx = 0;
|
int unitidx = 0;
|
||||||
uint64_t total = total_arg;
|
|
||||||
|
|
||||||
/* Although we use an unsigned long for the values, 32 bit
|
/* Although we use an unsigned long for the values, 32 bit
|
||||||
* applications using GPGME will use an "int" and thus are limited
|
* applications using GPGME will use an "int" and thus are limited
|
||||||
@ -91,7 +89,10 @@ write_status_progress (const char *what,
|
|||||||
* to display how many percent of the operation has been done and
|
* to display how many percent of the operation has been done and
|
||||||
* thus scaling CURRENT and TOTAL down before they get to large,
|
* thus scaling CURRENT and TOTAL down before they get to large,
|
||||||
* should not have a noticeable effect except for rounding
|
* should not have a noticeable effect except for rounding
|
||||||
* imprecision. */
|
* imprecision.
|
||||||
|
* Update 2023-06-13: We now use uint64_t but to keep the API stable
|
||||||
|
* we still do the scaling.
|
||||||
|
*/
|
||||||
|
|
||||||
if (!total && opt.input_size_hint)
|
if (!total && opt.input_size_hint)
|
||||||
total = opt.input_size_hint;
|
total = opt.input_size_hint;
|
||||||
@ -121,7 +122,7 @@ write_status_progress (const char *what,
|
|||||||
unitidx = 9;
|
unitidx = 9;
|
||||||
|
|
||||||
snprintf (buffer, sizeof buffer, "%.20s ? %lu %lu %c%s",
|
snprintf (buffer, sizeof buffer, "%.20s ? %lu %lu %c%s",
|
||||||
what? what : "?", current, (unsigned long)total,
|
what? what : "?", (unsigned long)current, (unsigned long)total,
|
||||||
units[unitidx],
|
units[unitidx],
|
||||||
unitidx? "iB" : "");
|
unitidx? "iB" : "");
|
||||||
write_status_text (STATUS_PROGRESS, buffer);
|
write_status_text (STATUS_PROGRESS, buffer);
|
||||||
@ -181,7 +182,7 @@ progress_filter (void *opaque, int control,
|
|||||||
void
|
void
|
||||||
handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
|
handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
|
||||||
{
|
{
|
||||||
off_t filesize = 0;
|
uint64_t filesize = 0;
|
||||||
|
|
||||||
if (!pfx)
|
if (!pfx)
|
||||||
return;
|
return;
|
||||||
@ -190,7 +191,7 @@ handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name)
|
|||||||
log_assert (is_status_enabled ());
|
log_assert (is_status_enabled ());
|
||||||
|
|
||||||
if ( !iobuf_is_pipe_filename (name) && *name )
|
if ( !iobuf_is_pipe_filename (name) && *name )
|
||||||
filesize = iobuf_get_filelength (inp, NULL);
|
filesize = iobuf_get_filelength (inp);
|
||||||
else if (opt.set_filesize)
|
else if (opt.set_filesize)
|
||||||
filesize = opt.set_filesize;
|
filesize = opt.set_filesize;
|
||||||
|
|
||||||
|
@ -749,14 +749,13 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
|
|||||||
if (!opt.no_literal)
|
if (!opt.no_literal)
|
||||||
pt=setup_plaintext_name(fname,inp);
|
pt=setup_plaintext_name(fname,inp);
|
||||||
|
|
||||||
/* try to calculate the length of the data */
|
/* Try to calculate the length of the data. */
|
||||||
if ( !iobuf_is_pipe_filename (fname) && *fname )
|
if ( !iobuf_is_pipe_filename (fname) && *fname )
|
||||||
{
|
{
|
||||||
off_t tmpsize;
|
uint64_t tmpsize;
|
||||||
int overflow;
|
|
||||||
|
|
||||||
if( !(tmpsize = iobuf_get_filelength(inp, &overflow))
|
tmpsize = iobuf_get_filelength (inp);
|
||||||
&& !overflow && opt.verbose)
|
if (!tmpsize && opt.verbose)
|
||||||
log_info (_("WARNING: '%s' is an empty file\n"), fname);
|
log_info (_("WARNING: '%s' is an empty file\n"), fname);
|
||||||
|
|
||||||
/* We can't encode the length of very large files because
|
/* We can't encode the length of very large files because
|
||||||
|
Loading…
x
Reference in New Issue
Block a user