@@ -78,25 +78,40 @@ pwrite(int fd_num, const void *buf, size_t n, off_t off) {
7878 * AmigaOS ChangeFilePosition fails when seeking past EOF.
7979 * POSIX: pwrite past EOF extends the file with zero-fill.
8080 * Use ChangeFileSize to extend, then retry the seek.
81+ *
82+ * IMPORTANT: after a failed ChangeFilePosition the AmigaDOS file
83+ * handle may be left in an undefined state on some filesystems
84+ * Restore the position to saved_pos BEFORE
85+ * calling ChangeFileSize so the handle is in a known good state.
8186 */
8287 file_size = GetFileSize (file );
8388 if (file_size != GETPOSITION_ERROR && off >= file_size ) {
84- if (ChangeFileSize (file , off , OFFSET_BEGINNING ) != -1 ) {
85- new_pos = ChangeFilePosition (file , off , OFFSET_BEGINNING );
86- if (new_pos == CHANGE_FILE_ERROR ) {
87- ChangeFilePosition (file , saved_pos , OFFSET_BEGINNING );
88- fd -> fd_Position = saved_pos ;
89- __fd_unlock (fd );
90- __set_errno (EIO );
91- goto out ;
92- }
93- } else {
94- ChangeFilePosition (file , saved_pos , OFFSET_BEGINNING );
89+ /* Restore position first to stabilise the file handle. */
90+ ChangeFilePosition (file , saved_pos , OFFSET_BEGINNING );
91+
92+ /*
93+ * ChangeFileSize returns the old file size on success, or
94+ * CHANGE_FILE_ERROR (0) on failure. CHANGE_FILE_ERROR == 0,
95+ * so we must also consult IoErr() to distinguish a successful
96+ * call whose old size happened to be 0 from a real error —
97+ * exactly the same pattern used in ftruncate.c.
98+ */
99+ int64_t cfs_result = ChangeFileSize (file , off , OFFSET_BEGINNING );
100+ if (cfs_result == CHANGE_FILE_ERROR && IoErr () != OK ) {
95101 fd -> fd_Position = saved_pos ;
96102 __fd_unlock (fd );
97103 __set_errno (__translate_io_error_to_errno (IoErr ()));
98104 goto out ;
99105 }
106+
107+ new_pos = ChangeFilePosition (file , off , OFFSET_BEGINNING );
108+ if (new_pos == CHANGE_FILE_ERROR && IoErr () != OK ) {
109+ ChangeFilePosition (file , saved_pos , OFFSET_BEGINNING );
110+ fd -> fd_Position = saved_pos ;
111+ __fd_unlock (fd );
112+ __set_errno (EIO );
113+ goto out ;
114+ }
100115 } else {
101116 ChangeFilePosition (file , saved_pos , OFFSET_BEGINNING );
102117 fd -> fd_Position = saved_pos ;
0 commit comments