1 /* SR.H         (c)Copyright Greg Smith, 2004-2009                   */
2 /*              Suspend/Resume a Hercules session                    */
3 
4 /*
5  * The suspend/resume functions allow a hercules instance to be
6  * captured to a file and later resumed.  Note that the suspend
7  * function also terminates the hercules instance.
8  *
9  * In order for an instance to be resumed, hercules must be started
10  * with a config file describing the configuration at suspend time.
11  * For example, mainsize and xpndsize must match.  Also, all devices
12  * present at suspend time must be present at resume time.
13  *
14  * Disk devices must be at the same state as they were at suspend
15  * time.  They can, however, be a different file type.  That is,
16  * a disk could be a cckd disk at suspend time.  Then a ckd disk
17  * could be created using dasdcopy and hercules resumed using the
18  * ckd disk instead.
19  *
20  * Also, hercules must be configured similarly as at suspend time.
21  * For example, if 4 emulated CPUs were active at suspend time
22  * then the session can not be resumed on a hercules with a
23  * maximum of two CPUs.  Another example, you will not be able
24  * to resume a session in z900 architecture mode for a hercules
25  * that was built without z900 architecture.
26  *
27  * Device state
28  *
29  * Currently, device state is only fully saved for CKD disks.
30  * Each device class (eg TAPE, RDR, PUN, CTC) will need code
31  * to save and restore their state.  Some states may not be
32  * possible to restore (eg active tcp/ip connections at the
33  * time of suspend).
34  *
35  * Further limitations
36  *
37  * Currently the vector facility state is not saved.
38  * Also, the ecpsvm state is not currently saved.
39  *
40  * File Structure
41  *
42  * The suspend/resume file (.srf) contains some number of `text
43  * units'.  A text unit has an 8 byte header followed by zero or
44  * more bytes of data.
45  *
46  * The file is designed to be hercules release independent and
47  * to be host architecture independent.  For example, I should be
48  * able to take an srf file created on hercules 3.02 on an intel
49  * machine and resume on a Sun machine running hercules 3.04.
50  *
51  * The header contains a 4 byte key and a 4 byte length.  Both
52  * the key and the length are stored in big-endian byte order.
53  *
54  * There are 3 types of data: STRING, BUF and VALUE.
55  *
56  * A string is a null terminated sequence of bytes.  The string
57  * includes the null terminator byte.  The total length of a
58  * string cannot exceed SR_MAX_STRING_LENGTH (4096).  The
59  * length is checked by SR_READ_STRING.
60  *
61  * A buf is a sequence of bytes whose length must be provided.
62  * The length should be checked before issuing SR_READ_BUF.
63  *
64  * A value is an arithmetic number.  It's length can be
65  * 0, 1, 2, 4 or 8 bytes.  Values are stored in big-endian
66  * byte order.  A zero length indicates the value is 0.
67  *
68  * Text Units
69  *
70  * There are 4 categories (so far) of text units:
71  *   HDR     ...    fields that describe the file
72  *   SYS     ...    fields from SYSBLK
73  *   CPU     ...    fields from REGS
74  *   DEV     ...    fields from DEVBLK
75  *
76  * The format of a text unit key value is
77  *   ace c t xxx
78  *
79  *   ace  -- all keys start with 0xace
80  *   c    -- category (0 - HDR, 1 - SYS, 2 - CPU, 3 - DEV)
81  *   t    -- for DEV keys, identifies the subtype for the
82  *           device type (0 - general, 1 - CKD, ...)
83  *   xxx  -- field identifier
84  *
85  * Note that there is no array data type.  When an array
86  * needs to be used, the elements should have ascending
87  * text unit key values.  For example:
88  *
89  *   #define SR_CPU_GR               0xace20020
90  *   #define SR_CPU_GR_0             0xace20020
91  *   #define SR_CPU_GR_1             0xace20021
92  *   #define SR_CPU_GR_2             0xace20022
93  *   #define SR_CPU_GR_3             0xace20023
94  *   .  .  .  .  .  .
95  *
96  * The array can be written during suspend as follows:
97  *
98  *   for (i = 0; i < 16; i++)
99  *     SR_WRITE_VALUE(fd, SR_CPU_GR+i, regs->gr[i], sizeof(regs->gr[0]));
100  *
101  * The array can be processed during resume as follows
102  *
103  *   case SR_CPU_GR_0:
104  *   case SR_CPU_GR_1:
105  *   case SR_CPU_GR_2:
106  *   case SR_CPU_GR_3:
107  *   .  .  .  .  .  .
108  *     i = key - SR_CPU_GR;
109  *     SR_READ_VALUE(fd, len, &regs->gr[i], sizeof(regs->gr[0]));
110  *     break;
111  *
112  * The format of the .srf file is deliberately unstructured to
113  * allow for flexibility in future enhancements.  However there
114  * are a few restrictions.
115  *
116  * o Key SR_SYS_ARCHNAME shoud be specified before any
117  *   SR_CPU keys.  The corresponding CPU is configured
118  *   when the SR_CPU key is read, so sysblk.arch_mode must
119  *   already be correctly set.
120  * o SR_CPU_ keys must follow the corresponding SR_CPU key.
121  * o Likewise SR_DEV_ keys must follow the corresponding SR_DEV key
122  *
123  * There may be other instances where the processing of one
124  * key requires that another key has been previously processed.
125  *
126  */
127 
128 // $Log$
129 // Revision 1.15  2007/06/23 00:04:16  ivan
130 // Update copyright notices to include current year (2007)
131 //
132 // Revision 1.14  2006/12/08 09:43:30  jj
133 // Add CVS message log
134 //
135 
136 #ifndef _HERCULES_SR_H
137 #define _HERCULES_SR_H
138 
139 #include "opcode.h"
140 
141 #define SR_ID "Hercules suspend/resume file"
142 #define SR_MAX_STRING_LENGTH 4096
143 
144 #define SR_KEY_ID_MASK          0xfff00000
145 #define SR_KEY_ID               0xace00000
146 
147 #define SR_HDR_ID               0xace00000
148 #define SR_HDR_VERSION          0xace00001
149 #define SR_HDR_DATE             0xace00002
150 
151 #define SR_SYS_MASK             0xfffff000
152 #define SR_SYS_STARTED_MASK     0xace10000
153 #define SR_SYS_INTS_STATE       0xace10001
154 #define SR_SYS_ARCH_NAME        0xace10002
155 #define SR_SYS_MAINSIZE         0xace10007
156 #define SR_SYS_MAINSTOR         0xace10008
157 #define SR_SYS_SKEYSIZE         0xace10009
158 #define SR_SYS_STORKEYS         0xace1000a
159 #define SR_SYS_XPNDSIZE         0xace1000b
160 #define SR_SYS_XPNDSTOR         0xace1000c
161 #define SR_SYS_CPUID            0xace1000d
162 #define SR_SYS_IPLDEV           0xace1000e
163 #define SR_SYS_IPLCPU           0xace1000f
164 #define SR_SYS_MBO              0xace10010
165 #define SR_SYS_MBK              0xace10011
166 #define SR_SYS_MBM              0xace10012
167 #define SR_SYS_MBD              0xace10013
168 #define SR_SYS_IOINTQ           0xace10020
169 #define SR_SYS_IOPENDING        0xace10021
170 #define SR_SYS_PCIPENDING       0xace10022
171 #define SR_SYS_ATTNPENDING      0xace10023
172 #define SR_SYS_CHP_RESET        0xace10030
173 #define SR_SYS_CHP_RESET_0      0xace10030
174 #define SR_SYS_CHP_RESET_1      0xace10031
175 #define SR_SYS_CHP_RESET_2      0xace10032
176 #define SR_SYS_CHP_RESET_3      0xace10033
177 #define SR_SYS_CHP_RESET_4      0xace10034
178 #define SR_SYS_CHP_RESET_5      0xace10035
179 #define SR_SYS_CHP_RESET_6      0xace10036
180 #define SR_SYS_CHP_RESET_7      0xace10037
181 #define SR_SYS_SERVPARM         0xace10040
182 #define SR_SYS_SIGINTREQ        0xace10041
183 #define SR_SYS_VMACTIVE         0xace10042
184 #define SR_SYS_MSCHDELAY        0xace10043
185 #define SR_SYS_LOADPARM         0xace10044
186  /*
187   * Following 3 tags added for Multiple
188   * Logical Channel Subsystem support
189   */
190 #define SR_SYS_IOPENDING_LCSS   0xace10045
191 #define SR_SYS_PCIPENDING_LCSS  0xace10046
192 #define SR_SYS_ATTNPENDING_LCSS 0xace10047
193 
194 #define SR_SYS_SERVC            0xace11000
195 
196 #define SR_SYS_CLOCK            0xace12000
197 
198 #define SR_CPU                  0xace20000
199 #define SR_CPU_ARCHMODE         0xace20001
200 #define SR_CPU_PX               0xace20002
201 #define SR_CPU_PSW              0xace20003
202 #define SR_CPU_GR               0xace20020
203 #define SR_CPU_GR_0             0xace20020
204 #define SR_CPU_GR_1             0xace20021
205 #define SR_CPU_GR_2             0xace20022
206 #define SR_CPU_GR_3             0xace20023
207 #define SR_CPU_GR_4             0xace20024
208 #define SR_CPU_GR_5             0xace20025
209 #define SR_CPU_GR_6             0xace20026
210 #define SR_CPU_GR_7             0xace20027
211 #define SR_CPU_GR_8             0xace20028
212 #define SR_CPU_GR_9             0xace20029
213 #define SR_CPU_GR_10            0xace2002a
214 #define SR_CPU_GR_11            0xace2002b
215 #define SR_CPU_GR_12            0xace2002c
216 #define SR_CPU_GR_13            0xace2002d
217 #define SR_CPU_GR_14            0xace2002e
218 #define SR_CPU_GR_15            0xace2002f
219 #define SR_CPU_CR               0xace20040
220 #define SR_CPU_CR_0             0xace20040
221 #define SR_CPU_CR_1             0xace20041
222 #define SR_CPU_CR_2             0xace20042
223 #define SR_CPU_CR_3             0xace20043
224 #define SR_CPU_CR_4             0xace20044
225 #define SR_CPU_CR_5             0xace20045
226 #define SR_CPU_CR_6             0xace20046
227 #define SR_CPU_CR_7             0xace20047
228 #define SR_CPU_CR_8             0xace20048
229 #define SR_CPU_CR_9             0xace20049
230 #define SR_CPU_CR_10            0xace2004a
231 #define SR_CPU_CR_11            0xace2004b
232 #define SR_CPU_CR_12            0xace2004c
233 #define SR_CPU_CR_13            0xace2004d
234 #define SR_CPU_CR_14            0xace2004e
235 #define SR_CPU_CR_15            0xace2004f
236 #define SR_CPU_AR               0xace20060
237 #define SR_CPU_AR_0             0xace20060
238 #define SR_CPU_AR_1             0xace20061
239 #define SR_CPU_AR_2             0xace20062
240 #define SR_CPU_AR_3             0xace20063
241 #define SR_CPU_AR_4             0xace20064
242 #define SR_CPU_AR_5             0xace20065
243 #define SR_CPU_AR_6             0xace20066
244 #define SR_CPU_AR_7             0xace20067
245 #define SR_CPU_AR_8             0xace20068
246 #define SR_CPU_AR_9             0xace20069
247 #define SR_CPU_AR_10            0xace2006a
248 #define SR_CPU_AR_11            0xace2006b
249 #define SR_CPU_AR_12            0xace2006c
250 #define SR_CPU_AR_13            0xace2006d
251 #define SR_CPU_AR_14            0xace2006e
252 #define SR_CPU_AR_15            0xace2006f
253 #define SR_CPU_FPR              0xace20080
254 #define SR_CPU_FPR_0            0xace20080
255 #define SR_CPU_FPR_1            0xace20081
256 #define SR_CPU_FPR_2            0xace20082
257 #define SR_CPU_FPR_3            0xace20083
258 #define SR_CPU_FPR_4            0xace20084
259 #define SR_CPU_FPR_5            0xace20085
260 #define SR_CPU_FPR_6            0xace20086
261 #define SR_CPU_FPR_7            0xace20087
262 #define SR_CPU_FPR_8            0xace20088
263 #define SR_CPU_FPR_9            0xace20089
264 #define SR_CPU_FPR_10           0xace2008a
265 #define SR_CPU_FPR_11           0xace2008b
266 #define SR_CPU_FPR_12           0xace2008c
267 #define SR_CPU_FPR_13           0xace2008d
268 #define SR_CPU_FPR_14           0xace2008e
269 #define SR_CPU_FPR_15           0xace2008f
270 #define SR_CPU_FPR_16           0xace20090
271 #define SR_CPU_FPR_17           0xace20091
272 #define SR_CPU_FPR_18           0xace20092
273 #define SR_CPU_FPR_19           0xace20093
274 #define SR_CPU_FPR_20           0xace20094
275 #define SR_CPU_FPR_21           0xace20095
276 #define SR_CPU_FPR_22           0xace20096
277 #define SR_CPU_FPR_23           0xace20097
278 #define SR_CPU_FPR_24           0xace20098
279 #define SR_CPU_FPR_25           0xace20099
280 #define SR_CPU_FPR_26           0xace2009a
281 #define SR_CPU_FPR_27           0xace2009b
282 #define SR_CPU_FPR_28           0xace2009c
283 #define SR_CPU_FPR_29           0xace2009d
284 #define SR_CPU_FPR_30           0xace2009e
285 #define SR_CPU_FPR_31           0xace2009f
286 #define SR_CPU_FPC              0xace20100
287 #define SR_CPU_DXC              0xace20101
288 #define SR_CPU_MC               0xace20102
289 #define SR_CPU_EA               0xace20103
290 #define SR_CPU_PTIMER           0xace20104
291 #define SR_CPU_CLKC             0xace20105
292 #define SR_CPU_CHANSET          0xace20106
293 #define SR_CPU_TODPR            0xace20107
294 #define SR_CPU_MONCLASS         0xace20108
295 #define SR_CPU_EXCARID          0xace20109
296 #define SR_CPU_INTS_STATE       0xace2010a
297 #define SR_CPU_INTS_MASK        0xace2010b
298 #define SR_CPU_EXTCCPU          0xace2010c
299 #define SR_CPU_BEAR             0xace2010d
300 #define SR_CPU_OPNDRID          0xace20110
301 #define SR_CPU_CHECKSTOP        0xace20111
302 #define SR_CPU_HOSTINT          0xace20112
303 #define SR_CPU_EXECFLAG         0xace20113
304 #define SR_CPU_INSTVALID        0xace20114
305 #define SR_CPU_PERMODE          0xace20115
306 #define SR_CPU_LOADSTATE        0xace20116
307 #define SR_CPU_INVALIDATE       0xace20117
308 #define SR_CPU_RESET_OPCTAB     0xace20118
309 #define SR_CPU_SIGPRESET        0xace20119
310 #define SR_CPU_SIGPIRESET       0xace2011a
311 #define SR_CPU_VTIMERINT        0xace2011b
312 #define SR_CPU_RTIMERINT        0xace2011c
313 #define SR_CPU_MALFCPU          0xace20120
314 #define SR_CPU_MALFCPU_0        0xace20120
315 #define SR_CPU_MALFCPU_1        0xace20121
316 #define SR_CPU_MALFCPU_2        0xace20122
317 #define SR_CPU_MALFCPU_3        0xace20123
318 #define SR_CPU_MALFCPU_4        0xace20124
319 #define SR_CPU_MALFCPU_5        0xace20125
320 #define SR_CPU_MALFCPU_6        0xace20126
321 #define SR_CPU_MALFCPU_7        0xace20127
322 #define SR_CPU_MALFCPU_8        0xace20128
323 #define SR_CPU_MALFCPU_9        0xace20129
324 #define SR_CPU_MALFCPU_10       0xace2012a
325 #define SR_CPU_MALFCPU_11       0xace2012b
326 #define SR_CPU_MALFCPU_12       0xace2012c
327 #define SR_CPU_MALFCPU_13       0xace2012d
328 #define SR_CPU_MALFCPU_14       0xace2012e
329 #define SR_CPU_MALFCPU_15       0xace2012f
330 #define SR_CPU_MALFCPU_16       0xace20130
331 #define SR_CPU_MALFCPU_17       0xace20131
332 #define SR_CPU_MALFCPU_18       0xace20132
333 #define SR_CPU_MALFCPU_19       0xace20133
334 #define SR_CPU_MALFCPU_20       0xace20134
335 #define SR_CPU_MALFCPU_21       0xace20135
336 #define SR_CPU_MALFCPU_22       0xace20136
337 #define SR_CPU_MALFCPU_23       0xace20137
338 #define SR_CPU_MALFCPU_24       0xace20138
339 #define SR_CPU_MALFCPU_25       0xace20139
340 #define SR_CPU_MALFCPU_26       0xace2013a
341 #define SR_CPU_MALFCPU_27       0xace2013b
342 #define SR_CPU_MALFCPU_28       0xace2013c
343 #define SR_CPU_MALFCPU_29       0xace2013d
344 #define SR_CPU_MALFCPU_30       0xace2013e
345 #define SR_CPU_MALFCPU_31       0xace2013f
346 #define SR_CPU_EMERCPU          0xace20140
347 #define SR_CPU_EMERCPU_0        0xace20140
348 #define SR_CPU_EMERCPU_1        0xace20141
349 #define SR_CPU_EMERCPU_2        0xace20142
350 #define SR_CPU_EMERCPU_3        0xace20143
351 #define SR_CPU_EMERCPU_4        0xace20144
352 #define SR_CPU_EMERCPU_5        0xace20145
353 #define SR_CPU_EMERCPU_6        0xace20146
354 #define SR_CPU_EMERCPU_7        0xace20147
355 #define SR_CPU_EMERCPU_8        0xace20148
356 #define SR_CPU_EMERCPU_9        0xace20149
357 #define SR_CPU_EMERCPU_10       0xace2014a
358 #define SR_CPU_EMERCPU_11       0xace2014b
359 #define SR_CPU_EMERCPU_12       0xace2014c
360 #define SR_CPU_EMERCPU_13       0xace2014d
361 #define SR_CPU_EMERCPU_14       0xace2014e
362 #define SR_CPU_EMERCPU_15       0xace2014f
363 #define SR_CPU_EMERCPU_16       0xace20150
364 #define SR_CPU_EMERCPU_17       0xace20151
365 #define SR_CPU_EMERCPU_18       0xace20152
366 #define SR_CPU_EMERCPU_19       0xace20153
367 #define SR_CPU_EMERCPU_20       0xace20154
368 #define SR_CPU_EMERCPU_21       0xace20155
369 #define SR_CPU_EMERCPU_22       0xace20156
370 #define SR_CPU_EMERCPU_23       0xace20157
371 #define SR_CPU_EMERCPU_24       0xace20158
372 #define SR_CPU_EMERCPU_25       0xace20159
373 #define SR_CPU_EMERCPU_26       0xace2015a
374 #define SR_CPU_EMERCPU_27       0xace2015b
375 #define SR_CPU_EMERCPU_28       0xace2015c
376 #define SR_CPU_EMERCPU_29       0xace2015d
377 #define SR_CPU_EMERCPU_30       0xace2015e
378 #define SR_CPU_EMERCPU_31       0xace2015f
379 
380 #define SR_DEV                  0xace30000
381 #define SR_DEV_DEVTYPE          0xace30001
382 #define SR_DEV_ARGC             0xace30002
383 #define SR_DEV_ARGV             0xace30003
384 #define SR_DEV_TYPNAME          0xace30004
385  /*
386   * Following tag added for multiple Logical
387   * Channel subsystem support
388   */
389 #define SR_DEV_LCSS             0xace30005
390 #define SR_DEV_ORB              0xace30010
391 #define SR_DEV_PMCW             0xace30011
392 #define SR_DEV_SCSW             0xace30012
393 #define SR_DEV_PCISCSW          0xace30013
394 #define SR_DEV_ATTNSCSW         0xace30014
395 #define SR_DEV_CSW              0xace30015
396 #define SR_DEV_PCICSW           0xace30016
397 #define SR_DEV_ATTNCSW          0xace30017
398 #define SR_DEV_ESW              0xace30018
399 #define SR_DEV_ECW              0xace30019
400 #define SR_DEV_SENSE            0xace3001a
401 #define SR_DEV_PGSTAT           0xace3001b
402 #define SR_DEV_PGID             0xace3001c
403  /* By Adrian - SR_DEV_DRVPWD              */
404 #define SR_DEV_DRVPWD           0xace3001d
405 
406 #define SR_DEV_BUSY             0xace30020
407 #define SR_DEV_RESERVED         0xace30021
408 #define SR_DEV_SUSPENDED        0xace30022
409 #define SR_DEV_PENDING          0xace30023
410 #define SR_DEV_PCIPENDING       0xace30024
411 #define SR_DEV_ATTNPENDING      0xace30025
412 #define SR_DEV_STARTPENDING     0xace30026
413 #define SR_DEV_CRWPENDING       0xace30027
414 #define SR_DEV_CCWADDR          0xace30028
415 #define SR_DEV_IDAPMASK         0xace30029
416 #define SR_DEV_IDAWFMT          0xace3002a
417 #define SR_DEV_CCWFMT           0xace3002b
418 #define SR_DEV_CCWKEY           0xace3002c
419 
420 #define SR_DEV_MASK             0xfffff000
421 #define SR_DEV_CKD              0xace31000
422 #define SR_DEV_FBA              0xace32000
423 #define SR_DEV_TTY              0xace33000
424 #define SR_DEV_3270             0xace34000
425 #define SR_DEV_RDR              0xace35000
426 #define SR_DEV_PUN              0xace36000
427 #define SR_DEV_PRT              0xace37000
428 #define SR_DEV_TAPE             0xace38000
429 #define SR_DEV_COMM             0xace39000
430 #define SR_DEV_CTC              0xace3a000
431 #define SR_DEV_CTCI             0xace3b000
432 #define SR_DEV_CTCT             0xace3c000
433 #define SR_DEV_VMNET            0xace3d000
434 #define SR_DEV_LCS              0xace3e000
435 #define SR_DEV_CTCE             0xace3f000
436 
437 #define SR_DELIMITER            0xaceffffe
438 #define SR_EOF                  0xacefffff
439 
440 #if defined (_HERCULES_SR_C)
441 #define SR_WRITE_ERROR       goto sr_write_error
442 #define SR_READ_ERROR        goto sr_read_error
443 #define SR_SEEK_ERROR        goto sr_seek_error
444 #define SR_VALUE_ERROR       goto sr_value_error
445 #define SR_STRING_ERROR      goto sr_string_error
446 #else
447 #define SR_WRITE_ERROR \
448  do { \
449    logmsg(_("HHCSR010E write error: %s\n"), strerror(errno)); \
450    return -1; \
451  } while (0)
452 #define SR_READ_ERROR \
453  do { \
454    logmsg(_("HHCSR011E read error: %s\n"), strerror(errno)); \
455    return -1; \
456  } while (0)
457 #define SR_SEEK_ERROR \
458  do { \
459    logmsg(_("HHCSR012E seek error: %s\n"), strerror(errno)); \
460    return -1; \
461  } while (0)
462 #define SR_VALUE_ERROR \
463  do { \
464    logmsg(_("HHCSR013E value error, incorrect length\n")); \
465    return -1; \
466  } while (0)
467 #define SR_STRING_ERROR \
468  do { \
469    logmsg(_("HHCSR014E string error, incorrect length\n")); \
470    return -1; \
471  } while (0)
472 #endif
473 
474 #ifdef HAVE_LIBZ
475 #define SR_DEFAULT_FILENAME "hercules.srf.gz"
476 #define SR_FILE gzFile
477 #define SR_OPEN(_path, _mode) \
478  gzopen((_path), (_mode))
479 #define SR_READ(_ptr, _size, _nmemb, _stream) \
480  gzread((_stream), (_ptr), (unsigned int)((_size) * (_nmemb)))
481 #define SR_WRITE(_ptr, _size, _nmemb, _stream) \
482  gzwrite((_stream), (_ptr), (unsigned int)((_size) * (_nmemb)))
483 #define SR_SEEK(_stream, _offset, _whence) \
484  gzseek((_stream), (_offset), (_whence))
485 #define SR_CLOSE(_stream) \
486  gzclose((_stream))
487 #else
488 #define SR_DEFAULT_FILENAME "hercules.srf"
489 #define SR_FILE FILE*
490 #define SR_OPEN(_path, _mode) \
491  fopen((_path), (_mode))
492 #define SR_READ(_ptr, _size, _nmemb, _stream) \
493  fread((_ptr), (_size), (_nmemb), (_stream))
494 #define SR_WRITE(_ptr, _size, _nmemb, _stream) \
495  fwrite((_ptr), (_size), (_nmemb), (_stream))
496 #define SR_SEEK(_stream, _offset, _whence) \
497  fseek((_stream), (_offset), (_whence))
498 #define SR_CLOSE(_stream) \
499  fclose((_stream))
500 #endif
501 
502 #define SR_WRITE_HDR(_file, _key, _len) \
503  do { \
504    size_t _rc; \
505    BYTE _buf[8]; \
506    store_fw (_buf, (_key)); \
507    store_fw (_buf+4, (_len)); \
508    _rc = SR_WRITE(_buf, 1, 8, (_file)); \
509    if (_rc != 8) SR_WRITE_ERROR; \
510  } while (0)
511 
512 #define SR_WRITE_STRING(_file, _key, _s) \
513 do { \
514   size_t _rc; \
515   if (strlen((_s)) + 1 > SR_MAX_STRING_LENGTH) SR_STRING_ERROR; \
516   SR_WRITE_HDR((_file), (_key), strlen((_s)) + 1); \
517   _rc = SR_WRITE((_s), 1, strlen((_s)) + 1, (_file)); \
518   if (_rc != strlen((_s)) + 1) SR_WRITE_ERROR; \
519 } while (0);
520 
521 #define SR_WRITE_BUF(_file, _key, _buf, _len) \
522 do { \
523   size_t _rc; \
524   if ((_len)) { \
525     SR_WRITE_HDR((_file), (_key), (_len)); \
526     _rc = SR_WRITE((_buf), 1, (_len), (_file)); \
527     if (_rc != (_len)) SR_WRITE_ERROR; \
528   } else \
529     SR_WRITE_HDR((_file), (_key), 0); \
530 } while (0)
531 
532 #define SR_WRITE_VALUE(_file, _key, _val, _len) \
533 do { \
534   size_t _rc; \
535   BYTE _buf[8]; \
536   if ((_len) != 1 && (_len) != 2 && (_len) != 4 && (_len) != 8) \
537     SR_VALUE_ERROR; \
538   SR_WRITE_HDR((_file), (_key), (_len)); \
539   switch ((_len)) { \
540     case 1: _buf[0] = (_val); break; \
541     case 2: store_hw(_buf, (_val)); break; \
542     case 4: store_fw(_buf, (_val)); break; \
543     case 8: store_dw(_buf, (_val)); break; \
544   } \
545   _rc = SR_WRITE(_buf, 1, (_len), (_file)); \
546   if (_rc != (_len)) SR_WRITE_ERROR; \
547 } while (0)
548 
549 #define SR_READ_HDR(_file, _key, _len) \
550 do { \
551   size_t _rc; \
552   BYTE _buf[8]; \
553   _rc = SR_READ(_buf, 1, 8, (_file)); \
554   if (_rc != 8) SR_READ_ERROR; \
555   (_key) = fetch_fw(_buf); \
556   (_len) = fetch_fw(_buf+4); \
557 } while (0)
558 
559 //FIXME: Workaround for problem involving gzseek
560 //       and large files.  Just read the data.
561 #define SR_READ_SKIP(_file, _len) \
562 do { \
563   size_t _rc; \
564   size_t _l; \
565   BYTE _buf[256]; \
566   _l = (_len); \
567   while (_l) { \
568     _rc = SR_READ(_buf, 1, _l < 256 ? _l : 256, (_file)); \
569     if (_rc == (size_t)-1) SR_READ_ERROR; \
570     _l -= _l < 256 ? _l : 256; \
571   } \
572 } while (0)
573 
574 #define SR_READ_STRING(_file, _p, _len) \
575 do { \
576   size_t _rc; \
577   if ((_len) > SR_MAX_STRING_LENGTH) SR_STRING_ERROR; \
578   _rc = SR_READ((_p), 1, (_len), (_file)); \
579   if (_rc != (_len)) SR_READ_ERROR; \
580 } while (0)
581 
582 #define SR_READ_BUF(_file, _p, _len) \
583 do { \
584   size_t _rc; \
585   _rc = SR_READ((_p), 1, (_len), (_file)); \
586   if (_rc != (_len)) SR_READ_ERROR; \
587 } while (0)
588 
589 #define SR_READ_VALUE(_file, _len1, _p, _len2) \
590 do { \
591   size_t _rc; \
592   BYTE _buf[8]; \
593   U64 _value; \
594   if ((_len1) != 1 && (_len1) != 2 && (_len1) != 4 && (_len1) != 8) \
595     SR_VALUE_ERROR; \
596   _rc = SR_READ(_buf, 1, (_len1), (_file)); \
597   if (_rc != (_len1)) SR_READ_ERROR; \
598   switch ((_len1)) { \
599     case 1: _value = _buf[0]; break; \
600     case 2: _value = fetch_hw(_buf); break; \
601     case 4: _value = fetch_fw(_buf); break; \
602     case 8: _value = fetch_dw(_buf); break; \
603     default: _value=0; break; /* To ward off gcc -Wall */ \
604   } \
605   switch ((_len2)) { \
606   case 1: \
607     { \
608       BYTE *_ptr = (void *)(_p); \
609       *_ptr = _value & 0xff; \
610       break; \
611     } \
612   case 2: \
613     { \
614       U16 *_ptr = (void *)(_p); \
615       *_ptr = _value & 0xffff; \
616       break; \
617     } \
618   case 4: \
619     { \
620       U32 *_ptr = (void *)(_p); \
621       *_ptr = _value & 0xffffffff; \
622       break; \
623     } \
624   case 8: \
625     { \
626       U64 *_ptr = (void *)(_p); \
627       *_ptr = _value; \
628       break; \
629     } \
630   } \
631 } while (0)
632 
633 #define SR_SKIP_NULL_DEV(_dev, _file, _len) \
634   if ((_dev) == NULL) { \
635     SR_READ_SKIP((_file),(_len)); \
636     break; \
637   }
638 
639 #endif /* !defined(_HERCULES_SR_H) */
640