• pack_qwk() ignores write errors and delivers QWK packets with 0-byte M

    From Rob Swindell@1:103/705 to GitLab issue in main/sbbs on Fri Sep 18 19:16:40 2026
    open https://gitlab.synchro.net/main/sbbs/-/issues/1244

    ## Summary

    `sbbs_t::pack_qwk()` does not check for write errors on `MESSAGES.DAT` / `HEADERS.DAT`. When writes to the temp directory fail, it archives the resulting 0-byte files and returns success, so QWK network hubs receive a packet with no usable content. The receiving system then fails to unpack it and renames it to `*.bad`:

    ```
    evnt QNET !ERROR[x2] 2 (No such file or directory) in un_qwk.cpp line 105 (unpack_qwk) checking length ".../temp/event/MESSAGES.DAT" access=0
    evnt QNET .../data/VERT.qwk renamed to .../data/VERT.qwk.6aadc6da.bad
    ```

    Reported on IRC by Accession (hub PHARCYDE): 10 such packets (292 bytes zipped, containing a 0-byte `MESSAGES.DAT` and a 0-byte `HEADERS.DAT`) downloaded from VERT on Aug 13-14, 2026.

    ## What the VERT logs show

    **All hubs were affected, not just PHARCYDE.** VERT's FTP server logs show 292- or 294-byte QWK packets downloaded only between about 22:00 Aug 12 and 12:00 Aug 14 (VERT local time):

    | Day | 292/294-byte packets / total QWK downloads |
    |---|---|
    | Aug 12 | 3 / 1988 |
    | Aug 13 | 40 / 1623 |
    | Aug 14 | 19 / 1791 |

    No other day in August or September has any. Affected hubs include FREESIDE, ARCADIA, ANDUIN, CITBBS, LRDBBS, CAVEBBS, UNDREDUX, BOOBTUBE, BITSLAIR, SUBCBBS, EMERALD and PHARCYDE.

    **The failure was intermittent.** PHARCYDE got empty packets at 00:37 and 11:37 on Aug 13 and at 02:37, 04:37 and 06:37 on Aug 14, with normal packets (1-4 KB) in between.

    **No code change was involved.** VERT ran the same build (`master/~2701a79802`, compiled Aug 9) before, during and after the window, per the Terminal Server's Aug 14 15:35 recycle banner and `error.log` build stamps from Aug 11-16.

    **Nothing was logged on VERT.** `error.log` has no packQWK/disk/memory errors in the window. The event-thread log (`events.log`) for those dates has since rotated away.

    ## Analysis

    A packet with no messages would still have a 128-byte `MESSAGES.DAT`: `pack_qwk()` always writes the "Produced by ..." header block first (`pack_qwk.cpp` around line 314). A **0-byte** `MESSAGES.DAT` therefore means the writes failed.

    On VERT the packet is assembled in the temp dir on the local C: drive (`c:\sbbstemp\event\`), while the archive is written to `s:\sbbs\data\file\NNNN.qwk` on a different volume. Writes to the temp volume failing while the archive destination was fine would produce this. The likeliest cause is a full or nearly-full C: drive during the window, but that is **unconfirmed** (VERT's Windows System event log would show it).

    Whatever the environmental cause, the defect is that it goes unnoticed:

    - `fprintf()`/`fwrite()` calls writing to `MESSAGES.DAT` and `HEADERS.DAT` are not checked.
    - The `fclose()` return values for those files (around line 613) are ignored, so a failed flush of buffered data is also missed.
    - The message counters still increase, so the "nothing to pack" early return doesn't trigger, and the empty files are archived and delivered as a successful packet.

    ## Proposed fix

    In `pack_qwk()`:

    1. Check `ferror()` and the `fclose()` results for `MESSAGES.DAT` and `HEADERS.DAT` (and ideally `VOTING.DAT` and the `*.NDX` files). On failure, log an error (`errormsg()`, so it reaches `error.log`) and return false without creating a packet.
    2. Before creating the archive, verify that `MESSAGES.DAT` is at least `QWK_BLOCK_LEN` (128) bytes. If it isn't, log an error and return false.

    The hub then gets "no packet" (FTP 550) instead of a corrupt one, and the hub's sysop gets a clear `error.log` entry.

    Hubs holding `.bad` packets from this window can delete them; they contain nothing to recover.

    - *Authored by Claude (Claude Code), on behalf of @rswindell*
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell@1:103/705 to GitLab note in main/sbbs on Fri Sep 18 23:11:44 2026
    https://gitlab.synchro.net/main/sbbs/-/issues/1244#note_10375

    Follow-up: the messages in those empty packets were skipped, not just delayed.

    When the event thread's pre-pack returns success, it saves the hub's message pointers (`putmsgptrs()`). Because `pack_qwk()` reported success for these empty packets, the pointers of every affected hub advanced past the messages the packet should have carried. Those hubs never received them. Deleting the `.bad` files is still correct (they contain nothing), but getting the messages back would mean resetting the affected hubs' scan pointers on VERT to before Aug 12 about 22:00.

    A fix is committed (not yet pushed). `pack_qwk()` now checks `ferror()` and `fclose()` for MESSAGES.DAT, HEADERS.DAT, VOTING.DAT and the `.NDX` files, and requires MESSAGES.DAT to be at least one QWK block (128 bytes) before archiving. On any failure it logs to error.log and creates no packet. The pack then counts as failed, so the pointers aren't saved and the messages go out in the next successful packet.

    - *Authored by Claude (Claude Code), on behalf of @rswindell*
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell@1:103/705 to GitLab issue in main/sbbs on Fri Sep 18 23:15:29 2026
    close https://gitlab.synchro.net/main/sbbs/-/issues/1244
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)