Skip to content

Cannot overwrite a file larger than 1 KB with StorageOperation (nanoff --filedeployment) #1840

Description

@dkovyazin

Describe the bug

After the rework of the StorageOperation command (nanoframework/nf-interpreter#3502), deploying a file that already exists on the device fails with WriteError, deterministically, on every retry. Only files up to a single Wire Protocol packet (WP_PACKET_SIZE, 1024 bytes) can be overwritten; a fresh device or a freshly erased file system still works, which is why this is easy to miss.

Cause

HAL_StorageOperation() in src/HAL/nanoHAL_StorageOperation.cpp opens the target file with volume->Open(relativePath, fileHandle) and relies on it to start from an empty file. Open() has no truncate semantics: a stream driver that opens an existing file for read/write keeps the previous length. The ESP32 littlefs driver does exactly that — targets/ESP32/_littlefs/littlefs_FS_Driver.cpp selects "r+" when stat() finds the file.

A file larger than one packet is sent as one StorageOperation_Write chunk followed by StorageOperation_Append chunks:

  1. Write writes the first ~1 KB at position 0. Because the file was not truncated, its length is still the old one.
  2. The first Append opens the file, seeks to the end and validates position != offsetWriteError.

The per-target implementations that the common one replaced did not have this problem: targets/ESP32/_common/targetHAL_StorageOperation.cpp called remove() on the target path before writing ("Remove the file if already exists").

Steps to reproduce

  1. Take an ESP32 target with accessible storage (reproduced on ESP32-S3 with littlefs, I: drive).
  2. Deploy any file larger than 1 KB, e.g. nanoff --filedeployment with I:\www\app.css (~26 KB). It succeeds — the file did not exist.
  3. Deploy the very same file again, without erasing the file system.
  4. The second deployment fails with WriteError on that file and keeps failing on every retry.

Expected behaviour

A write replaces the existing file, as it did before #3502.

Affected

Every target whose stream driver opens an existing file without truncating it. Confirmed on ESP32/littlefs; targets/ESP32/_FatFs/fatfs_FS_Driver.cpp should be checked too.

Proposed fix

Delete the file before opening it in the StorageOperation_Write branch, restoring the previous behaviour. Both the littlefs and the FatFs driver return CLR_E_FILE_NOT_FOUND for a missing file without touching anything, so the result can be ignored. PR follows.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions