Skip to content

Fall back to QFile when QSaveFile fails on CIFS/SMB - #50

Open
rva79 wants to merge 1 commit into
omacom:masterfrom
rva79:save-cifs-qsavefile-fallback
Open

Fall back to QFile when QSaveFile fails on CIFS/SMB#50
rva79 wants to merge 1 commit into
omacom:masterfrom
rva79:save-cifs-qsavefile-fallback

Conversation

@rva79

@rva79 rva79 commented Sep 2, 2026

Copy link
Copy Markdown

Problem

Saving to a CIFS/SMB mount fails in Omawrite with Could not save …, even when the share is mounted read-write and a normal file write succeeds.

Backend::saveTo uses QSaveFile. On Linux that creates an unnamed temp file with O_TMPFILE, then materializes it with linkat. CIFS does not support O_TMPFILE and returns ENOENT rather than EOPNOTSUPP. Qt only treats EOPNOTSUPP and EISDIR as “not supported”, so it never falls back to a named temp file and QSaveFile::open() fails.

QSaveFile::setDirectWriteFallback(true) does not help: that path only retries on EACCES.

Reproduced with Qt 6.11:

  • open(dir, O_TMPFILE | O_RDWR) on CIFS → ENOENT
  • mkstemp / QFile on the same directory → success
  • QSaveFile::open on the same directory → "No such file or directory"

Change

Keep QSaveFile as the default (atomic replace on local filesystems). If that fails, write the destination with QFile so saves still work on CIFS/SMB.

Recovery snapshots stay on QSaveFile; those go to AppDataLocation on a local disk.

Test plan

  • ./bin/test (12 passed)
  • Save a new Markdown file to a CIFS/SMB mount from Omawrite (Ctrl+Shift+S)
  • Save again to the same path (Ctrl+S)
  • Save to a local directory still works

QSaveFile uses Linux O_TMPFILE. CIFS returns ENOENT instead of
EOPNOTSUPP, so Qt never falls back to a named temp file and save
fails even though the share is writable. Write the destination
directly in that case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant