McIDAS Programmer's Manual
McIDAS disk files
Reading and writing data to and from disk is fundamental to many applications programs. A McIDAS-X disk file stores information that applications can randomly access by byte address using standard system library calls.
This section describes:
- the special attributes of McIDAS-X disk files that distinguish them from other system files
- the API functions you will use to read, write, delete, and copy
disk files
Basic concepts
McIDAS-X disk file utilities have several characteristics that distinguish them from other file system utilities.
- Disk files are always open. From an application's perspective, a McIDAS-X disk file is always available for use. Since the application doesn't need to open, close or otherwise position the file to perform input or output, it can treat disk files as virtual arrays of bytes.
- Disk files are byte-oriented. This attribute applies to both the location of data on disk and the amount of data moved to or from disk. You can use higher-level APIs to transfer words, which are 4-byte groups. Four bytes is the common length of Fortran INTEGER and REAL variables.
- Disk files use zero-based addressing. The first byte in every disk file is byte number 0, not byte 1.
- Disk files contain a unique, missing-data value. When reading bytes in a disk file that have never been written, a unique value (hexadecimal 0x80) is returned.
- Zero-length disk files are automatically deleted. When a McIDAS-X command ends, all writable, zero-length files accessed while the program was running are deleted.
- Disk file name length. The McIDAS-X disk file I/O subsystem has no inherent name length limitation.
- Disk files may exist in a variety of directories , depending on the settings that the user enters for the session's MCPATH environment variable, as well as the entries in the REDIRECT table. When accessing files, do not impose a complete pathname. Rather, assign only a file name that can then be converted into a fully qualified pathname/filename by the McIDAS-X file system.
If the file name passed from the application to the McIDAS-X disk file API functions does not contain a slash character, the McIDAS-X file system will perform the following three steps to determine a file's location on disk.
-
-
Check the REDIRECT table entries and try to match the file name.
-
If that fails, search for the file name in all directories named in the MCPATH environment variable.
-
If that fails, choose the pathname of the first writable directory named in the MCPATH environment variable.
Disk file APIs
The table below describes the McIDAS-X library functions that you will use when programming with disk files. In McIDAS-X, a disk file is called an LW (Large Word) array file. You will notice that many of the Fortran APIs below begin with the letters lw .
|
|
|
Mcpathname
|
volnam
|
converts a disk file name to a fully qualified pathname/filename
|
Mcread
|
lbi
|
reads bytes from a disk file into memory
|
not available
|
lwi
|
reads words (4-byte groups) from a disk file
|
Mcwrite
|
lbo
|
creates a disk file by writing bytes into it from memory
|
not available
|
lwo
|
creates a disk file by writing words (4-byte groups) into it
|
Mcremove
|
lwd
|
deletes a disk file
|
Mctruncate
|
lwtrunc
|
deletes the contents of a disk file without deleting the file itself
|
not available
|
lwfile
|
determines if a file exists
|
not available
|
lock
|
acquires an exclusive lock on a file
|
not available
|
unlock
|
frees the lock on a file
|
Each function is described in the sections below, along with sample code illustrating its use.
Reading and writing disk files
The McIDAS-X library provides the Mcread and Mcwrite functions for reading and writing disk files in C. The comparable functions in Fortran are lbi and lbo , which are shown in the code fragment below. The lwi and lwo functions read and write words (4-byte groups) from a disk file.
c --- an example of writing data
integer array_out(3)
integer array_in(3)
integer nwords, status, lwo, lwi, first
...
c --- initialize
first = 0
nwords = 3
do 200 i = 1, nwords
200 array_out(i) = i * 100
c --- write the data to disk -- note that there are four bytes
c --- in each array element
status = lbo('testdata', first*4, nwords*4, array_out)
if (status .lt. 0) then
call edest('Failed to write testdata', status)
call mccodeset(1)
return
endif
c --- at this point, the file 'testdata' will consist of:
c --- word 0 = integer value 100
c --- word 1 = integer value 200
c --- word 2 = integer value 300
c --- words 3 and beyond are unwritten
c --- now, read the data in, skipping the first word:
first = 1
status = lbi('testdata', first*4, nwords*4, array_in)
c --- at this point, the array array_in will consist of:
c --- word 1 = integer value 200
c --- word 2 = integer value 300
c --- word 3 = 0x80808080 (the missing value indicating
c --- this word was never written)
|
Assigning a system pathname to a disk file
If your application uses Fortran or C library functions for disk I/O, you must use the volnam or Mcpathname function to convert the name of the disk file into a fully qualified, system pathname/filename . This pathname is essential for locating and working on a file.
The code fragment below illustrates the use of volnam with a Fortran OPEN statement. The maximum number of characters allowed for the fully-qualified pathname is stored in the constant MAXPATHLENGTH in the Fortran INCLUDE file, fileparm.inc . The limit for C is in the file /usr/include/sys/limits.h .
c --- For illustration, assume the user has done a REDIRECT
c --- command that looks like this:
c --- REDIRECT ADD MYDATA "/home/me/mcidas/data
c ---
include 'fileparm.inc'
character*(MAXPATHLENGTH) fullname
character*12 filename
integer rc, volnam
...
filename = 'MYDATA'
...
rc = volnam(filename, fullname)
if (rc.lt.0) then
call edest('Problem resolving path for '//
filename,0)
call mccodeset(1)
return
endif
c --- At this point, fullname will contain the fully-qualified
c --- name ('/home/me/mcidas/data/MYDATA')
open(unit=12, file=fullname, mode='share', status='old')
...
|
Determining if a disk file exists
Use the function lwfile to determine if a file with a given name already exists. If the file does not exist, lwfile returns a zero; it does not create the file for you. The following code fragment illustrates how to use lwfile .
c --- find out if file 'mystuff' exists
status = lwfile('mystuff')
if (status .ne. 0) then
call sdest('The file is there!',0)
else
call edest('The file is NOT there!!!',0)
endif
...
|
Deleting the contents of a disk file
To delete the contents of a disk file but not the file itself, use the lwtrunc or Mctruncate function. These functions remove the contents of the file, leaving one word (4 bytes) of 0x80808080 at the beginning of the file.
Deleting only the contents of a file and not the file itself is important if the file name appears in more than one location in the MCPATH tree. For example, if you delete the file ABC from a directory where you have write permissions but the file also exists further down your MCPATH in a directory where you have only read permissions, you won't be able to create a writable file by that name. If you use lwtrunc or Mctruncate to delete only the file's contents, you can write into it again in the future, since it resides in the original, writable directory.
The code fragment below uses the lwtrunc function to delete the contents of a file.
c --- assume the user's MCPATH contains the directories
c --- /home/my/data and /home/your/data, with a file named
c --- DATAFILE residing in both directories; further assume
c --- that I only have write permissions to /home/my/data
status = lwtrunc('DATAFILE')
if (status .lt. 0) then
call edest('Error occurred trying to truncate file',0)
endif
c --- now write the contents of buffer to DATAFILE
status = lbo('DATAFILE', 0, bufsiz, buffer)
c --- at this point, the contents of buffer were written to
c --- /home/my/data/DATAFILE; if lwd had been called instead of
c --- lwtrunc, the lbo call would have returned an error because
c --- I don't have write permissions to /home/your/data/DATAFILE
|
Deleting a disk file
Use the lwd or Mcremove functions to delete a disk file, as shown in the code fragment below.
...
character filename*20
integer status, lwd
c --- try to remove the file
status = lwd(filename)
if (status .lt. 0) then
call edest('Error trying to remove file '//
filename,0)
call mccodeset(2)
goto 999
else
...
c --- do some other processing
|
Locking and unlocking a disk file
As long as a user has read and write permissions, the McIDAS-X disk file I/O subsystem will open all files and permit simultaneous access to these files for both reading and writing. If you write applications that update information in disk files, you must synchronize access to the file to avoid potential file collisions.
McIDAS-X has a locking mechanism called lock for coordinating file updates between applications or between copies of the same application. The lock function acquires exclusive use of a unique lock. If your application is using the lock, another application trying to lock the file must wait until you free the lock with the unlock function before using it.
The lock and unlock functions do not prevent other applications from reading a file or writing to it. They simply ensure an orderly means of updating a file without losing or overwriting information.
The code fragment below shows how to lock and unlock a file to protect its integrity during updating.
...
c --- protect against simultaneous attempts to use this lock
call lock( 'myfile ')
c --- when control is returned, this application has exclusive use
rc = lbi('myfile', 0,100,array)
...
c --- update the values in array
...
c --- now save the updated info back into 'myfile'
rc = lbo('myfile',0,100,array)
c --- now free the lock
call unlock('myfile')
...
|
Copying a disk file
Use the lwcopy function to copy one disk file into another, as shown in the code fragment below.
c --- set up some variables
integer status, lwcopy, lwo
integer source(3)
integer destination(3)
c --- fill up source array
do 200 i=1,3
source(i) = I*100
200 continue
c --- write out array to file "first"
status = lwo('first', 0,3,source)
if (status.lt.0) then
call edest('Error writing to "first" file',0)
call mccodeset(2)
goto 999
endif
c --- now copy file 'first' into 'backup'
status = lwcopy('first', 'backup')
if (status.lt.0) then
call edest('Error during copy...',status)
call mccodeset(2)
goto 999
endif
...
|