Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 51 additions & 13 deletions src/Modules/MainMenu.bb
Original file line number Diff line number Diff line change
Expand Up @@ -853,11 +853,19 @@ Function LogIn()
Wend
; If successful, download Actor/Attributes lists and go to character selection
If Result = 1
; Save username/password
F = WriteFile("Data\Last Username.dat")
; Save username/password. Atomic via SafeWriteOpen/
; SafeWriteCommit -- a WriteFile failure mid-write would
; leave the cache file empty, locking the user out of
; pre-fill on next login. The previous cache (if any)
; is retained as .bak.
Local LUFinal$ = "Data\Last Username.dat"
Local LUTemp$ = SafeWriteOpen$(LUFinal$)
F = WriteFile(LUTemp$)
If F <> 0
WriteLine F, GY_TextFieldText$(TName)
WriteLine F, Encrypt$(GY_TextFieldText$(TPass), -1)
CloseFile F
SafeWriteCommit%(LUTemp$, LUFinal$, F)
EndIf
UName$ = GY_TextFieldText$(TName) : PWord$ = MD5$(GY_TextFieldText$(TPass))

; Request actors list
Expand Down Expand Up @@ -1496,12 +1504,20 @@ Function LogIn()
; Music update
If GY_CheckBoxDown(BUpdateMusic) <> 1 - UpdateMusic
UpdateMusic = 1 - GY_CheckBoxDown(BUpdateMusic)
; Update file
F = WriteFile("Data\Game Data\Misc.dat")
; Update file atomically. A crash mid-write would
; leave Misc.dat empty, which the next launch would
; interpret as "no game name, no version" -- locking
; the user out of the project. SafeWriteCommit demotes
; the previous Misc.dat to .bak for recovery.
Local MMFinal$ = "Data\Game Data\Misc.dat"
Local MMTemp$ = SafeWriteOpen$(MMFinal$)
F = WriteFile(MMTemp$)
If F <> 0
WriteLine F, GameName$
WriteLine F, UpdateGame$
WriteLine F, UpdateMusic
CloseFile F
SafeWriteCommit%(MMTemp$, MMFinal$, F)
EndIf
EndIf
EndIf

Expand Down Expand Up @@ -3690,12 +3706,20 @@ Function GameOptionsMenu()
; Music update
If GY_CheckBoxDown(BUpdateMusic) <> 1 - UpdateMusic
UpdateMusic = 1 - GY_CheckBoxDown(BUpdateMusic)
; Update file
F = WriteFile("Data\Game Data\Misc.dat")
; Update file atomically. A crash mid-write would
; leave Misc.dat empty, which the next launch would
; interpret as "no game name, no version" -- locking
; the user out of the project. SafeWriteCommit demotes
; the previous Misc.dat to .bak for recovery.
Local MMFinal$ = "Data\Game Data\Misc.dat"
Local MMTemp$ = SafeWriteOpen$(MMFinal$)
F = WriteFile(MMTemp$)
If F <> 0
WriteLine F, GameName$
WriteLine F, UpdateGame$
WriteLine F, UpdateMusic
CloseFile F
SafeWriteCommit%(MMTemp$, MMFinal$, F)
EndIf
EndIf
EndIf

Expand Down Expand Up @@ -3843,8 +3867,14 @@ Function DownloadFile(URL$, SaveTo$ = "", GYProgress = 0)

If BytesToRead = 0 Then CloseTCPStream WWW : Return 0

; Create new file to write downloaded bytes into
Save = WriteFile(SaveTo$)
; Create new file to write downloaded bytes into.
; Atomic: write to .tmp, only promote to final on completion
; (BytesIn = BytesToRead). Mid-download cancellation, EOF
; before content-length, or any error path abort the temp
; without touching the prior on-disk file (if any). The prior
; download is retained as .bak.
Local DLTemp$ = SafeWriteOpen$(SaveTo$)
Save = WriteFile(DLTemp$)
If Save = 0 Then CloseTCPStream(WWW) : Return 0

; Incredibly complex download-to-file routine...
Expand All @@ -3869,8 +3899,16 @@ Function DownloadFile(URL$, SaveTo$ = "", GYProgress = 0)
If BytesIn = BytesToRead Then Exit
Forever

; Done
CloseFile(Save)
; Done. Promote to production only if the full content-length
; arrived; partial downloads abort the temp and leave the
; previous file (if any) intact. SafeWriteCommit closes Save
; internally on success; we close + abort on the partial path.
If BytesIn = BytesToRead
SafeWriteCommit%(DLTemp$, SaveTo$, Save)
Comment on lines +3906 to +3907
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Propagate SafeWriteCommit failure in DownloadFile

DownloadFile ignores the return value of SafeWriteCommit%, so a full network read is reported as success even when the local promote step fails (e.g., destination not writable or copy failure). In that case this function still returns BytesIn > 0, and its callers treat non-zero as a successful download, which can make them continue with stale/missing on-disk data. Capture the commit result and convert failure to a 0 return (and/or abort path) so call sites can handle it as a failed download.

Useful? React with 👍 / 👎.

Else
CloseFile(Save)
SafeWriteAbort(DLTemp$)
EndIf
CloseTCPStream(WWW)
EndIf

Expand Down
Loading