cmsv_open.pro
8.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
;+
; NAME:
; CMSV_OPEN
;
; AUTHOR:
; Craig B. Markwardt, NASA/GSFC Code 662, Greenbelt, MD 20770
; craigm@lheamail.gsfc.nasa.gov
;
; PURPOSE:
; Open IDL SAVE file for reading or writing
;
; CALLING SEQUENCE:
; CMSV_OPEN, UNIT, FILENAME, OFFSET, $
; ACCESS=ACCESS, /FORCE, /GET_LUN, /REOPEN, $
; COMPATIBILITY=COMPATIBILITY, $
; STATUS=STATUS, ERRMSG=ERRMSG
;
; DESCRIPTION:
;
; CMSV_OPEN opens an IDL SAVE-formatted file for reading or writing.
; The mode of operation is controlled by the ACCESS keyword, which
; may be either 'R' for reading, 'W' for writing, or 'RW' for
; read/write access.
;
; 'R': In the case of reading, the specified file is opened with
; read-only access, and the first bytes are examined to verify that
; it is indeed a valid IDL SAVE file.
;
; 'W': In the case of writing, the specified file is opened with
; write access, and the initial file signature is written.
;
; 'RW': In the case of read-write access, the file must already
; exist as a valid SAVE file. Users are advised that every time
; they switch between reading and writing operations, they must use
; POINT_LUN to flush the file buffers.
;
; The CMSVLIB routines do not support file sizes greater than 2 GB,
; nor SAVE files created with the COMPRESS option.
;
; Upon return, the file pointer is positioned at the start of the
; first valid SAVE record. The file offset is returned in OFFSET.
; The user is responsible for reading or writing the remainder of
; the file with other library routines.
;
; The file unit is determined based on the following criteria. This
; behavior is similar to the OPEN family of procedures, except for
; the REOPEN keyword.
;
; * If REOPEN is set then it is assumed that UNIT is an
; already-open file, and FILENAME is ignored.
;
; * If GET_LUN is set then a file unit is allocated with GET_LUN,
; and upon success this unit is returned in UNIT.
;
; * Otherwise it is asssumed that UNIT is a valid but unopened
; file unit. Upon successful return, UNIT is opened.
;
; This procedure is part of the CMSVLIB SAVE library for IDL by
; Craig Markwardt. You must have the full CMSVLIB core package
; installed in order for this procedure to function properly.
;
; ==================================================================
; Research Systems, Inc. has issued a separate license intended
; to resolve any potential conflict between this software and the
; IDL End User License Agreement. The text of that license
; can be found in the file LICENSE.RSI, included with this
; software library.
; ==================================================================
;
;
; INPUTS:
;
; UNIT - a logical unit number (a scalar). In the case of GET_LUN,
; a file unit will be allocated and returned in UNIT. In the
; default case, or REOPEN, UNIT must be a valid file unit
; upon input. For REOPEN the corresponding file must be
; seekable.
;
; FILENAME - a scalar string specifying the filename path (ignored
; for REOPEN).
;
; OFFSET - upon return, the file offset of the next available SAVE
; record.
;
;
; KEYWORDS:
;
; ACCESS - a scalar string, case insensitive:
; 'R' - read-only access
; 'W' - write access (new file)
; 'RW' - read-write access (existing file)
; Default: 'R' - read-only
;
; GET_LUN - if set, the file unit is allocated using GET_LUN
;
; FORCE - if set, then the file is opened despite a detected file
; format inconsistency.
;
; REOPEN - if set, then an already-opened file is manipulated. The
; valid file unit must be specified by UNIT, and FILENAME
; is ignored.
;
; COMPATIBILITY - a string, which describes the format to be used in
; the output file. Possible values are:
;
; 'IDL4' - format of IDL version 4;
; 'IDL5' - format of IDL versions 5.0-5.3;
; 'IDL6' - not supported yet, for versions 5.4-above;
; 'RIVAL1' - same as 'IDL5', plus a directory entry is
; written to the file.
; Note that files written in IDL5 format may still be
; readable by IDL v.4.
; Default: 'IDL5'
;
;
; STATUS - upon return, this keyword will contain 1 for success and
; 0 for failure.
;
; ERRMSG - upon return with a failure, this keyword will contain the
; error condition as a string.
;
; EXAMPLE:
;
;
; SEE ALSO:
;
; CMRESTORE, SAVE, RESTORE, CMSVLIB
;
; MODIFICATION HISTORY:
; Written, 2000
; Documented, 24 Jan 2001
; Change BLOCK to STREAM to support VMS properly, 14 Feb 2001, CM
; Added notification about RSI License, 13 May 2002, CM
; NOTE: remember to modify CMSVLIB.PRO when changing library!
;
; $Id: cmsv_open.pro,v 1.13 2009/11/22 22:50:49 craigm Exp $
;
;-
; Copyright (C) 2000-2001, Craig Markwardt
; This software is provided as is without any warranty whatsoever.
; Permission to use, copy, modify, and distribute modified or
; unmodified copies is granted, provided this copyright and disclaimer
; are included unchanged.
;-
pro cmsv_open, unit, filename, offset, access=access0, force=force, $
get_lun=get_lun, status=status, errmsg=errmsg, $
reopen=reopen, compatibility=compat, query=query, $
compressed=compressed
status = 0
offset = 0L
errmsg = ''
error = 0
if keyword_set(query) then return
if keyword_set(get_lun) then get_lun, unit
if n_elements(access0) EQ 0 then access0 = 'R'
access = strupcase(strtrim(access0(0),2))
if access NE 'R' AND access NE 'W' AND access NE 'RW' then begin
errmsg = 'ERROR: CMSV_OPEN: ACCESS must be one of "R", "RW" or "W"'
status = 0
return
endif
;; RE-OPEN
if keyword_set(reopen) then begin
;; Re-open an existing unit, but first make sure it's open
unit = floor(unit(0))
stat = fstat(unit)
errmsg = 'ERROR: CMSV_OPEN: Unit '+strtrim(unit,2)+' is not open'
if stat.open EQ 0 then begin
REOPEN_ERROR:
return
endif
if access EQ 'R' then begin
if stat.read EQ 0 then begin
errmsg = errmsg + ' for reading'
goto, REOPEN_ERROR
endif
endif else if access EQ 'RW' then begin
if stat.read EQ 0 OR stat.write EQ 0 then begin
errmsg = errmsg + ' for reading and writing'
goto, REOPEN_ERROR
endif
endif else begin
if stat.read EQ 0 OR stat.write EQ 0 then begin
errmsg = errmsg + ' for writing'
goto, REOPEN_ERROR
endif
endelse
point_lun, unit, 0L
errmsg = ''
endif
;; READ or READ-WRITE ACCESS
if access EQ 'R' OR access EQ 'RW' then begin
compressed = 0L
if NOT keyword_set(reopen) then begin
if access EQ 'R' then cmd = 'openr' else cmd = 'openu'
call_procedure, cmd, unit(0), filename, error=error, /STREAM
if error NE 0 then begin
READ_ERROR:
close, unit(0)
if keyword_set(get_lun) then free_lun, unit(0)
status = 0
errmsg = !err_string
return
endif
endif
;; Read 4-byte signature at start of file
on_ioerror, READ_ERROR
signature = bytarr(4)
readu, unit, signature
if string(signature(0:1)) NE 'SR' then begin
close, unit(0)
if keyword_set(get_lun) then free_lun, unit(0)
errmsg = 'ERROR: CMSV_OPEN: '+strtrim(filename(0),2)+ $
' is not a valid SAVE file'
return
endif
;; Check for compressed files, which are not supported
if signature(3) EQ 6 then begin
compressed = 1
if NOT keyword_set(force) then begin
errmsg = 'ERROR: CMSVLIB library cannot read '+ $
'compressed files'
status = 0
return
endif
endif
endif else if access EQ 'W' then begin
;; WRITE-ONLY (CREATE) ACCESS
if NOT keyword_set(reopen) then begin
openw, unit, filename, error=error, /STREAM
if error NE 0 then begin
WRITE_ERROR:
close, unit(0)
if keyword_set(get_lun) then free_lun, unit(0)
status = 0
errmsg = !err_string
return
endif
endif
;; Write a valid signature
vbyte = '04'xb
;; '06'xb would indicate a compressed SAVE file, which we don't
;; support.
on_ioerror, WRITE_ERROR
; S R
signature = ['53'xb, '52'xb, '00'xb, vbyte]
writeu, unit, signature
endif
status = 1
point_lun, -unit, offset
return
end