Page MenuHome GnuPG

temp-output-then-rename-20251117.patch

Authored By
gniibe
Mon, Nov 17, 8:17 AM
Size
6 KB
Subscribers

temp-output-then-rename-20251117.patch

diff --git a/common/iobuf.h b/common/iobuf.h
index 5fa064c20..4d04421e0 100644
--- a/common/iobuf.h
+++ b/common/iobuf.h
@@ -253,6 +253,10 @@ struct iobuf_struct
(iobuf_cancel). */
char *real_fname;
+ /* When REAL_FNAME above is active, remember if it's temporary output
+ file name (with .tmp suffix). */
+ int with_temp_output;
+
/* The next filter in the pipeline. */
iobuf_t chain;
diff --git a/g10/decrypt.c b/g10/decrypt.c
index fb606cb0f..e06bcf34c 100644
--- a/g10/decrypt.c
+++ b/g10/decrypt.c
@@ -39,6 +39,71 @@
+static gpg_error_t
+finish_temp_output (iobuf_t fp, gpg_error_t err)
+{
+ if (fp->with_temp_output)
+ {
+ char *fname_old = NULL;
+ char *fname_new = NULL;
+
+ fname_old = strdup (fp->real_fname);
+ if (!err)
+ {
+ if (!fname_old)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ size_t n = strlen (fname_old);
+
+ fname_new = strdup (fp->real_fname);
+ if (!fname_new)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ if (n <= 4)
+ err = gpg_error (GPG_ERR_INV_NAME);
+ else
+ {
+ fname_old [n-3] = 't';
+ fname_old [n-2] = 'm';
+ fname_old [n-1] = 'p';
+ fname_new [n-4] = 0;
+ err = gnupg_rename_file (fname_old, fname_new, NULL);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!fname_old)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ size_t n = strlen (fname_old);
+
+ if (n <= 4)
+ err = gpg_error (GPG_ERR_INV_NAME);
+ else
+ {
+ fname_old [n-3] = 't';
+ fname_old [n-2] = 'm';
+ fname_old [n-1] = 'p';
+ if (gnupg_remove (fname_old))
+ log_error ("removing temporary file failed: %s\n",
+ strerror (errno));
+ }
+ }
+ }
+
+ xfree (fname_old);
+ xfree (fname_new);
+ }
+
+ return err;
+}
+
+
/* Assume that the input is an encrypted message and decrypt
* (and if signed, verify the signature on) it.
* This command differs from the default operation, as it never
@@ -119,6 +184,7 @@ decrypt_message (ctrl_t ctrl, const char *filename, strlist_t remusr)
remusr, dek, sesenc_list);
}
+ err = finish_temp_output (fp, err);
xfree (dek);
free_seskey_enc_list (sesenc_list);
iobuf_close (fp);
@@ -269,9 +335,6 @@ decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
break;
print_file_status(STATUS_FILE_START, filename, 3);
- output = make_outfile_name(filename);
- if (!output)
- goto next_file;
fp = iobuf_open(filename);
if (fp)
iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
@@ -287,6 +350,18 @@ decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
goto next_file;
}
+ /* Check the suffix of input filename in advance, if it is
+ relevant for the output filname. */
+ output = make_outfile_name (fp);
+ if (!output)
+ {
+ /* If not, skip the file. */
+ iobuf_close(fp);
+ fp = NULL;
+ goto next_file;
+ }
+ xfree(output);
+
handle_progress (pfx, fp, filename);
if (!opt.no_armor)
@@ -301,6 +376,7 @@ decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
}
}
rc = proc_packets (ctrl,NULL, fp);
+ rc = finish_temp_output (fp, rc);
iobuf_close(fp);
if (rc)
log_error("%s: decryption failed: %s\n", print_fname_stdin(filename),
@@ -312,7 +388,6 @@ decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
next_file:
/* Note that we emit file_done even after an error. */
write_status( STATUS_FILE_DONE );
- xfree(output);
reset_literals_seen();
}
diff --git a/g10/main.h b/g10/main.h
index a926581c7..e390cb61c 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -347,7 +347,7 @@ gpg_error_t generate_card_subkeypair (ctrl_t ctrl, kbnode_t pub_keyblock,
/*-- openfile.c --*/
int overwrite_filep( const char *fname );
-char *make_outfile_name( const char *iname );
+char *make_outfile_name( iobuf_t input );
char *ask_outfile_name( const char *name, size_t namelen );
int open_outfile (gnupg_fd_t out_fd, const char *iname, int mode,
int restrictedperm, iobuf_t *a);
diff --git a/g10/openfile.c b/g10/openfile.c
index 04545ea75..f38ab67a3 100644
--- a/g10/openfile.c
+++ b/g10/openfile.c
@@ -86,13 +86,19 @@ overwrite_filep( const char *fname )
/*
- * Strip known extensions from iname and return a newly allocated
- * filename. Return NULL if we can't do that.
+ * Strip/modify known extensions from the input filename of INPUT and
+ * return a newly allocated filename. Return NULL if we can't do
+ * that.
*/
char *
-make_outfile_name (const char *iname)
+make_outfile_name (iobuf_t input)
{
size_t n;
+ const char *iname;
+
+ iname = iobuf_get_real_fname (input);
+ if (!iname || !*iname)
+ return NULL;
if (iobuf_is_pipe_filename (iname))
return xstrdup ("-");
@@ -104,7 +110,15 @@ make_outfile_name (const char *iname)
|| !CMP_FILENAME(iname+n-4, EXTSEP_S "asc")))
{
char *buf = xstrdup (iname);
- buf[n-4] = 0;
+ if (!CMP_FILENAME(iname+n-4, EXTSEP_S "sig"))
+ buf[n-4] = 0;
+ else
+ {
+ buf[n-3] = 't';
+ buf[n-2] = 'm';
+ buf[n-1] = 'p';
+ input->with_temp_output = 1;
+ }
return buf;
}
else if (n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign"))
diff --git a/g10/plaintext.c b/g10/plaintext.c
index a96214994..2a311ce09 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
@@ -88,7 +88,7 @@ get_output_file (const byte *embedded_name, int embedded_namelen,
else if (!opt.flags.use_embedded_filename)
{
if (data)
- fname = make_outfile_name (iobuf_get_real_fname (data));
+ fname = make_outfile_name (data);
if (!fname)
fname = ask_outfile_name (embedded_name, embedded_namelen);
if (!fname)

File Metadata

Mime Type
text/x-diff
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
23/aa/7df297b3f2860b546225c2db411f

Event Timeline

At line 133 shouldn't we have used iobuf_cancel there? Would it be possible to call finish_temp_output from iobuf_close or iobuf_cancel instead?

At line 133 shouldn't we have used iobuf_cancel there?

I don't think so. Here, iobuf is used for input (with fp). Inside proc_packets, it opens output file determining its filename using the input filename. Note that output is not done by iobuf.

After processing of fp has done, the file is renamed (or removed), depending the error-code of proc_packets.

Would it be possible to call finish_temp_output from iobuf_close

We could introduce new function iobuf_close_with (fp, err) to provide the error-code of the process. Or else, we need to change all the occurence of iobuf_close call.