Page MenuHome GnuPG

Kleopatra / Gpgtar: Windows write error ERROR_FILE_INVALID
Closed, InvalidPublic

Description

Not yet really finished my analysis when this can occur. But it happened to me, neither the gpgtar output showed a useful error nor Kleopatra.

Might have been because the disk was full. I'm just changing my test setup to have some more options regarding such tests. I'm updating this when I know more but this is a release blocker.

Event Timeline

aheinecke triaged this task as Unbreak Now! priority.Jun 9 2023, 1:23 PM
aheinecke created this task.

We have seen this problem in the QA this week and could identify that this was a ERROR_FILE_INVALID (ec=1006,"The volume for a file has been externally altered so that the opened file is no longer valid"). We also noticed disk errors in the event logger but did not recorded them. The USB stick was not unplugged but merely used with VirtualBox.

I don't see any problem in gpgtar here, thus no gnupg24 tag jut the gpgtar marker.

werner renamed this task from Kleopatra / Gpgtar: System error w/o error code to Kleopatra / Gpgtar: Windows write error ERROR_FILE_INVALID.Jun 9 2023, 1:39 PM
werner lowered the priority of this task from Unbreak Now! to High.Jun 9 2023, 1:51 PM
werner added a project: gpg4win.

I don't think this is a regression or something we can do anything about. Note that we see the same thing also on the command line. Actually I have seen the very same thing pretty often with USB devices. Thus lowering priority.

Please note that my test was not on an USB Device. I will keep this issue with your analysis and reopen a different one with my error and details on how to reproduce that one. Pretty sure it was disk full.

As what I see is similar as what Andre saw, I'll describe it here. Please check if this is relevant.
After the above mentioned Ticket was resolved, I tried the exact same encryption in Kleopatra on the same Test-VM.

In more than half a dozen tries I got only once "no space left on device", all the other tries are "Signieren Fehlgeschlagen, Systemfehler ohne gesetzten Systemfehlercode" if did sign+encrypt and "Verschlüsseln fehlgeschlagen, Systemfehler ohne gesetzten Systemfehlercode" if I did choose encrypt only.

Debugview shows:

[5888] org.kde.pim.kleopatra: Task:  "5G.txt"  has no total progress set. 
[5888] org.kde.pim.kleopatra: Kleo::Crypto::SignEncryptTask(0x11613ed0) slotResult job: QGpgME::QGpgMESignEncryptJob(0x6c00650) signing result: "GpgME::SigningResult(\n error:              GpgME::Error(117456893 (Systemfehler ohne gesetzten Systemfehlercode))\n createdSignatures:\n invalidSigningKeys:\n)" encryption result: "GpgME::EncryptionResult(\n error:        GpgME::Error(117456893 (Systemfehler ohne gesetzten Systemfehlercode))\n invalid recipients:\n)"
[5888] org.kde.pim.kleopatra: 0x114e0528
[5888] org.kde.pim.kleopatra: 0x114e0528
[5888] org.kde.pim.kleopatra: 
[5888] inputError : "Unbekannter Fehler" 
[5888] outputError: "Es steht nicht genug Speicherplatz auf dem Datenträger zur Verfügung."
[5888] org.kde.pim.kleopatra: Collection Progress:  1000  total:  1000

gpgme debug:

4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_data_inbound_handler: enter: dh=0x069b9f38 fd=4
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:           gpgme_data_write: enter: dh=0x069b9f38 buffer=0x0e32ea20, size=4095
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:           gpgme_data_write:422: error: No error (0)\n
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_data_inbound_handler:664: error: Systemfehler ohne gesetzten Systemfehlercode <GPGME>\n
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_cancel_with_err: enter: ctx=0x03edc190 ctx_err=117456893, op_err=0
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c277b8 setting fd 0x0 (item=0x06c27620) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c27878 setting fd 0x2 (item=0x06c282b0) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c28730 setting fd 0x4 (item=0x06c28598) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c28820 setting fd 0x7 (item=0x06c28958) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:           gpgme:gpg_io_event: call: gpg=0x03ed0460 event 0x6f489437, type 1, type_data 0x0e32faa4
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_cancel_with_err: leave: 
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:       gpgme_op_encrypt_sign:175: error: Systemfehler ohne gesetzten Systemfehlercode <GPGME>\n

I've debugged Eva's problem and I think it's unrelated to the original problem, as it's specific to qt.

What seems to be happening here is that gpgme reads the errror from errno during write (specifically, this is read from the last gpg_error_from_syserror() in _gpgme_data_inbound_handler() in src/data.c), but this isn't set anywhere. The write operation here is done through the qt parts of gpgme, which ultimately is a WriteFile() in qfsfileengine_win.cpp in qtbase that always leaves errno as 0, apparently.

Adding a patch like below to qtbase makes Kleopatra report the error correctly, but is of course not a solution since it would report every error as ENOSPC.

diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index dd4882a..2ea027b 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -392,6 +392,7 @@ qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
             if (totalWritten == 0) {
                 // Note: Only return error if the first WriteFile failed.
                 q->setError(QFile::WriteError, qt_error_string());
+                errno = ENOSPC;
                 return -1;
             }
             break;

This doesn't quite explain why it worked once for Eva, though. There's a second code path for file writing on windows in qt that does use the normal fwrite, but I don't know why it would randomly use that one time when it used the other code path the rest of the time.

The original issue was about creating an encrypted archive. This code doesn't use Qt anymore for writing the result file, but delegates this to gpgtar.

That sounds like a solid conclusion. I mean if errno is not set explicitly it is basically undefined which value it is, so maybe some other function set errno to no space left on device in that one case where it "worked".

I think we should do the error check in gpgme/lang/qt/src/dataprovider.cpp if the write failed and set an errno there. This is also the place where we set multiple other errnos.

The original issue was about creating an encrypted archive. This code doesn't use Qt anymore for writing the result file, but delegates this to gpgtar.

Indeed, but Evas test was then for a single file. I wonder if we should just rename the issue instead of copying all the comments over to a new one.

I mean this would also be solved if we did not use qiodevicedataprovider but pass the filenames directly to gpg for single files, too. (can't remember the ticket number) but I don't want to do that right now.

ebo moved this task from Restricted Project Column to Restricted Project Column on the Restricted Project board.

The original issue was to unclear to analyse and it was likely meanwhile fixed. For the other issue see the follow up ticket.