Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Disk Full handling

jaeger0
Beginner
914 Views
I thought, that is simple, however I do not get any error message writing a file to a full USB-Stick.
The disk is completely full and no Error appears. Files are then generated but 0Bytes large.

here the simple code:

OPEN(UNIT=file_id, FILE=filename, status='REPLACE',form='binary', iostat=iErr)
write(file_id, iostat=iErr, err= 20) Large_Data
if (.NOT. COMMITQQ(file_id)) then ! Flushing a file to disk
iErr = ERR_FILE_IO_ACCESS ! maybe disk is full
endif
close (file_id)

no Error appears. Did I something wrong ? I just want to get a warning, when not all data could be written
0 Kudos
6 Replies
Paul_Curtis
Valued Contributor I
914 Views
The OPEN statement will always succeed for an existing file. Any WRITE error directs your code to line 20, not shown, so the code immediately following the WRITE would not be visited.

You might consider finding the available space on the disk before opening the file, using the WinAPI function GetDiskFreeSpaceEx. IVF provides a declaration in kernel32.f90:

[bash]FUNCTION GetDiskFreeSpaceEx( &
        lpDirectoryName, &
        lpFreeBytesAvailableToCaller, &
        lpTotalNumberOfBytes, &
        lpTotalNumberOfFreeBytes)
import
  integer(BOOL) :: GetDiskFreeSpaceEx ! BOOL
    !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'GetDiskFreeSpaceExA' :: GetDiskFreeSpaceEx
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: lpDirectoryName
  character*(*) lpDirectoryName ! LPCSTR lpDirectoryName
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: lpFreeBytesAvailableToCaller
  TYPE(T_LARGE_INTEGER)  lpFreeBytesAvailableToCaller
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: lpTotalNumberOfBytes
  TYPE(T_LARGE_INTEGER)  lpTotalNumberOfBytes 
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: lpTotalNumberOfFreeBytes
  TYPE(T_LARGE_INTEGER) lpTotalNumberOfFreeBytes
 END FUNCTION[/bash]
0 Kudos
mecej4
Honored Contributor III
914 Views
Paul's advice is right-on, but also note that in a multitasking OS other processes can consume and free up disk space during the course of running the program in question. If, for example, the USB drive is used by "ReadyBoost" or contains the TMP/TEMP directories, the amount of free space could change in a way that is impossible to predict.
0 Kudos
jaeger0
Beginner
914 Views
here the completer code: I never get an error, the line 20 is never passed. Of course one could check available disk space, however I do not have any guess, how large my files will become. If write does not provide an error, is there a possibility to proof for example if data_array have completely written, or to proof, how many bytes where written ?


OPEN(UNIT=file_id, FILE=filename, status='REPLACE',form='binary', iostat=iErr)
write(file_id, iostat=iErr, err= 20) data_array
close (file_id)
goto 10

20 iErr = ERR_FILE_IO_ACCESS ! maybe disk is full
10 continue
0 Kudos
Paul_Curtis
Valued Contributor I
914 Views
You can get feedback on bytes actually written, but you will have to use the WinAPI functions directly:

[bash]IF (.NOT.WriteFile(ihandl,			&  ! file handle
				  loc_pointer,		&  ! address of data
				  nbytes,			&  ! byte count to write
				  LOC(nact),		&  ! actual bytes written
				  NULL_OVERLAPPED))	THEN
  	! deal with write error
END IF

IF (nact .LT. nbytes) THEN
! disk might be full
END IF


[/bash]
0 Kudos
rwg
Beginner
914 Views
I never had problems with IOSTAT= or ERR=. But I also never used them together. So remove ERR=20 from your write-statement an check the value of iErr after the write statement (and after the open statement!).

To check if an error can be recognized, remove IOSTAT= and IERR=. If your program does not crash thers's perhaps a problem with your USB-Port or an USB-driver.
0 Kudos
IanH
Honored Contributor II
914 Views
Quoting Paul Curtis
You can get feedback on bytes actually written, but you will have to use the WinAPI functions directly:

[bash]IF (.NOT.WriteFile(ihandl,			&  ! file handle
				  loc_pointer,		&  ! address of data
				  nbytes,			&  ! byte count to write
				  LOC(nact),		&  ! actual bytes written
				  NULL_OVERLAPPED))	THEN
  	! deal with write error
END IF

IF (nact .LT. nbytes) THEN
! disk might be full
END IF
[/bash]

Note the return value from WriteFile (if that's just the raw Win32 API without any wrapper) is not a Fortran logical - to be safe the returned value should be explictly compared with zero.

You also need the right flags to the CreateFile call in order to avoid the OS doing lazy writes, etc. Even with the right flags I'm not sure if you can still guarantee that the device driver that ultimately does the write won't do some caching.

0 Kudos
Reply