XL C-C++ Programming Guide PDF
XL C-C++ Programming Guide PDF
XL C/C++
Programming Guide
SC09-4765-13
Note
Before using this information and the product it supports, read the information under Notices on page 1019.
This edition applies to z/OS XL C/C++ compiler in version 1, release 13, modification 0 of z/OS (5694-A01) and to all
subsequent releases and modifications until otherwise indicated in new editions.
This edition replaces SC09-4765-12.
Copyright IBM Corporation 1996, 2012.
US Government Users Restricted Rights Use, duplication or disclosure restricted by GSA ADP Schedule Contract
with IBM Corp.
Contents
Figures . . . . . . . . . . . . . . . . . . . . . . . . . . . xv
Tables. . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi
Part 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Chapter 11. Performing z/OS UNIX file system I/O operations . . . . . . 123
Creating files . . . . . . . . . . . . . . . . . . . . . . . . . 123
Opening files . . . . . . . . . . . . . . . . . . . . . . . . . 124
Reading from z/OS UNIX file system files . . . . . . . . . . . . . . 128
Opening and reading from z/OS UNIX file system directory files . . . . . . 129
Writing to z/OS UNIX file system files . . . . . . . . . . . . . . . . 129
Flushing records . . . . . . . . . . . . . . . . . . . . . . . . 130
Setting positions within files . . . . . . . . . . . . . . . . . . . . 130
Closing files . . . . . . . . . . . . . . . . . . . . . . . . . 131
Deleting files . . . . . . . . . . . . . . . . . . . . . . . . . 131
Pipe I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Low-level z/OS UNIX I/O . . . . . . . . . . . . . . . . . . . . . 137
Example of z/OS UNIX file system I/O functions . . . . . . . . . . . . 137
fldata() behavior . . . . . . . . . . . . . . . . . . . . . . . . 142
File tagging and conversion . . . . . . . . . . . . . . . . . . . . 144
Access control lists (ACLs) . . . . . . . . . . . . . . . . . . . . 144
Chapter 14. Performing memory file and hiperspace I/O operations . . . 199
Using hiperspace operations . . . . . . . . . . . . . . . . . . . 199
Opening files . . . . . . . . . . . . . . . . . . . . . . . . . 200
Reading from files . . . . . . . . . . . . . . . . . . . . . . . 206
Writing to files . . . . . . . . . . . . . . . . . . . . . . . . . 207
Flushing records . . . . . . . . . . . . . . . . . . . . . . . . 208
Repositioning within files . . . . . . . . . . . . . . . . . . . . . 208
Closing files . . . . . . . . . . . . . . . . . . . . . . . . . 209
Removing memory files . . . . . . . . . . . . . . . . . . . . . 209
fldata() behavior . . . . . . . . . . . . . . . . . . . . . . . . 209
Example program . . . . . . . . . . . . . . . . . . . . . . . 210
Contents v
File I/O trace . . . . . . . . . . . . . . . . . . . . . . . . . 232
Locating the file I/O trace . . . . . . . . . . . . . . . . . . . . 233
Chapter 21. Building and using Dynamic Link Libraries (DLLs) . . . . . 279
Support for DLLs. . . . . . . . . . . . . . . . . . . . . . . . 279
DLL concepts and terms . . . . . . . . . . . . . . . . . . . . . 280
Loading a DLL . . . . . . . . . . . . . . . . . . . . . . . . 281
Managing the use of DLLs when running DLL applications . . . . . . . . 286
Creating a DLL or a DLL application . . . . . . . . . . . . . . . . 288
Building a simple DLL . . . . . . . . . . . . . . . . . . . . . . 288
Building a simple DLL application . . . . . . . . . . . . . . . . . 292
Creating and using DLLs . . . . . . . . . . . . . . . . . . . . . 293
DLL restrictions . . . . . . . . . . . . . . . . . . . . . . . . 294
Contents vii
Chapter 32. Using environment variables . . . . . . . . . . . . . . 467
Working with environment variables . . . . . . . . . . . . . . . . . 475
Environment variables specific to the z/OS XL C/C++ library. . . . . . . . 477
Propagating environment variables . . . . . . . . . . . . . . . . . 501
Chapter 35. Writing applications for Single UNIX Specification, Version 3 549
Announcing your intentions . . . . . . . . . . . . . . . . . . . . 549
Testing the environment . . . . . . . . . . . . . . . . . . . . . 550
What is different in SUSv3 . . . . . . . . . . . . . . . . . . . . 551
Symbols withdrawn in SUSv3 . . . . . . . . . . . . . . . . . . . 552
Candidates for removal in a future version . . . . . . . . . . . . . . 552
Implementation compliance . . . . . . . . . . . . . . . . . . . . 552
Chapter 43. Stepping through optimized code using the dbx debugger
utility . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
Steps for setting up a stopping point for dbx in optimized code . . . . . . . 615
Steps for using dbx to step through optimized code . . . . . . . . . . . 615
Contents ix
Part 7. Programming with Other Products . . . . . . . . . . . . . . . . . . 709
Chapter 48. Using the CICS Transaction Server (CICS TS) . . . . . . . 711
Developing XL C/C++ programs for the CICS environment . . . . . . . . 711
Preparing CICS for use with z/OS Language Environment . . . . . . . . 711
Designing and coding for CICS . . . . . . . . . . . . . . . . . . 712
Translating and compiling for reentrancy . . . . . . . . . . . . . . . 725
Prelinking and linking all object modules . . . . . . . . . . . . . . . 732
Defining and running the CICS program . . . . . . . . . . . . . . . 733
Chapter 61. Coded character set considerations with locale functions 885
Variant character detail . . . . . . . . . . . . . . . . . . . . . 885
Alternate code points . . . . . . . . . . . . . . . . . . . . . . 887
Coding without locale support by using a hybrid coded character set . . . . 887
Coded character set independence in developing applications . . . . . . . 889
Writing source code in coded character set IBM-1047 . . . . . . . . . . 900
Exporting source code to other sites . . . . . . . . . . . . . . . . 900
Converting existing work . . . . . . . . . . . . . . . . . . . . . 901
Considerations with other products and tools . . . . . . . . . . . . . 902
Contents xi
Support for the Curses library . . . . . . . . . . . . . . . . . . 1005
Notices . . . . . . . . . . . . . . . . . . . . . . . . . . 1019
Policy for unsupported hardware . . . . . . . . . . . . . . . . . 1021
Permission Notice . . . . . . . . . . . . . . . . . . . . . . . 1021
Programming Interface Information . . . . . . . . . . . . . . . . 1021
Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . 1022
Standards . . . . . . . . . . . . . . . . . . . . . . . . . . 1022
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . 1025
z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1025
z/OS XL C/C++ . . . . . . . . . . . . . . . . . . . . . . . . 1025
z/OS Metal C Runtime Library . . . . . . . . . . . . . . . . . . 1025
z/OS Run-Time Library Extensions. . . . . . . . . . . . . . . . . 1025
Debug Tool . . . . . . . . . . . . . . . . . . . . . . . . . 1025
z/OS Language Environment . . . . . . . . . . . . . . . . . . . 1026
Assembler. . . . . . . . . . . . . . . . . . . . . . . . . . 1026
COBOL. . . . . . . . . . . . . . . . . . . . . . . . . . . 1026
PL/I . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1026
VS FORTRAN . . . . . . . . . . . . . . . . . . . . . . . . 1026
CICS Transaction Server for z/OS . . . . . . . . . . . . . . . . . 1026
DB2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1026
IMS/ESA . . . . . . . . . . . . . . . . . . . . . . . . . . 1026
MVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1026
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . 1029
Contents xiii
xiv z/OS V1R13.0 XL C/C++ Programming Guide
Figures
1. Blocking fixed-length records . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2. Variable-length records on z/OS . . . . . . . . . . . . . . . . . . . . . . . . . 15
3. Memory file example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4. ASA Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5. ungetwc() Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6. Interleaving I/O with sync_with_stdio() . . . . . . . . . . . . . . . . . . . . . . . 63
7. Interleaving I/O without sync_with_stdio() . . . . . . . . . . . . . . . . . . . . . . 65
8. MVS example of redirecting three standard streams by ddnames . . . . . . . . . . . . . 71
9. Example of using stdout and stderr to share the same file. . . . . . . . . . . . . . . . 72
10. Example of passing text streams . . . . . . . . . . . . . . . . . . . . . . . . . 74
11. Example of passing record I/O streams . . . . . . . . . . . . . . . . . . . . . . 76
12. Example of command line redirection . . . . . . . . . . . . . . . . . . . . . . . 79
13. Generation data group example for C . . . . . . . . . . . . . . . . . . . . . . . 86
14. Generation data group example for C++ . . . . . . . . . . . . . . . . . . . . . . 87
15. How the operating system completes the DCB . . . . . . . . . . . . . . . . . . . 102
16. Example of reading updated records . . . . . . . . . . . . . . . . . . . . . . . 110
17. Example of signal handler . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
18. fldata() Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
19. Unnamed pipes example . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
20. Named pipes example . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
21. Example of z/OS UNIX stream input and output functions . . . . . . . . . . . . . . . 137
22. Example of HFS stream input and output functions . . . . . . . . . . . . . . . . . . 141
23. fldata() structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
24. Types and advantages of VSAM data sets . . . . . . . . . . . . . . . . . . . . . 149
25. VSAM example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
26. KSDS example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
27. KSDS example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
28. RRDS example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
29. fldata() structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
30. fldata() structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
31. Removing members of a PDS . . . . . . . . . . . . . . . . . . . . . . . . . 204
32. Renaming members of a PDS . . . . . . . . . . . . . . . . . . . . . . . . . 205
33. fldata() structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
34. Memory file example, part 1 . . . . . . . . . . . . . . . . . . . . . . . . . . 211
35. Memory file example, part 2 . . . . . . . . . . . . . . . . . . . . . . . . . . 212
36. fldata() structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
37. fldata() example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
38. CELQPIPI MSGRTN example . . . . . . . . . . . . . . . . . . . . . . . . . 219
39. __amrc structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
40. Example of printing the __amrc structure . . . . . . . . . . . . . . . . . . . . . 224
41. __amrc2 structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
42. Example of using SIGIOERR . . . . . . . . . . . . . . . . . . . . . . . . . . 230
43. Sample File I/O Trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
44. Example of parameter lists For OS linkages . . . . . . . . . . . . . . . . . . . . 245
45. EDCXPRLG macro with an ALIAS statement . . . . . . . . . . . . . . . . . . . . 250
46. Call to an XPLINK routine with no parameters . . . . . . . . . . . . . . . . . . . 251
47. Call to an XPLINK routine with 5 parameters . . . . . . . . . . . . . . . . . . . . 252
48. Establishing the C run-time environment . . . . . . . . . . . . . . . . . . . . . . 253
49. Calling an intermediate C function from Assembler OS linkage . . . . . . . . . . . . . 254
50. Intermediate C routine calling a run-time library function . . . . . . . . . . . . . . . . 254
51. Establishing the XL C/C++ run-time environment. . . . . . . . . . . . . . . . . . . 255
52. Calling an intermediate XL C/C++ function from Assembler using OS linkage . . . . . . . . 255
53. Intermediate XL C/C++ routine calling a run-time library function . . . . . . . . . . . . . 256
Copyright IBM Corp. 1996, 2012 xv
54. Interface for preinitializable programs . . . . . . . . . . . . . . . . . . . . . . . 258
55. Preinitializing a C program (CCNGCA6) . . . . . . . . . . . . . . . . . . . . . . 262
56. Using the preinitializable program (CCNGCA7) . . . . . . . . . . . . . . . . . . . 264
57. Using the preinitializable program (CCNGCA8) . . . . . . . . . . . . . . . . . . . 265
58. JCL for running a preinitializable C program . . . . . . . . . . . . . . . . . . . . 267
59. Explicit use of a DLL in an application using the dllload() family of functions . . . . . . . . 283
60. Explicit use of a DLL in an application using the dlopen() family of functions . . . . . . . . 285
61. Using #pragma export to create a DLL executable module named BASICIO . . . . . . . . 289
62. Using #pragma export to create the triangle DLL executable module . . . . . . . . . . . 290
63. Using _Export to create the triangle DLL executable module . . . . . . . . . . . . . . 290
64. Summary of DLL and DLL application preparation and usage . . . . . . . . . . . . . . 294
65. Referencing functions and external variables in DLL code . . . . . . . . . . . . . . . 304
66. Pointer Assignment in DLL code. . . . . . . . . . . . . . . . . . . . . . . . . 305
67. Pointer assignment in non-DLL code . . . . . . . . . . . . . . . . . . . . . . . 306
68. File 1. Application A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
69. File 2. Application A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
70. File 3. Application B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
71. File 4. DLL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
72. DLL function pointer call in non-DLL code . . . . . . . . . . . . . . . . . . . . . 309
73. DLL function pointer call in non-DLL code . . . . . . . . . . . . . . . . . . . . . 310
74. C non-DLL code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
75. C DLL code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
76. C++ DLL code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
77. C++ DLL code calling an Assembler function . . . . . . . . . . . . . . . . . . . . 312
78. Comparison of function pointers in non-DLL code . . . . . . . . . . . . . . . . . . 313
79. C DLL code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
80. C non-DLL code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
81. File 1 C DLL code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
82. File 2 C DLL code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
83. File 3 C non-DLL code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
84. Comparison of two DLL function pointers in non-DLL code . . . . . . . . . . . . . . . 315
85. Undefined comparison in DLL code (C or C++) . . . . . . . . . . . . . . . . . . . 316
86. Comparison of function pointers in DLL code (C or C++) . . . . . . . . . . . . . . . . 316
87. Valid comparisons in DLL code (C or C++) . . . . . . . . . . . . . . . . . . . . . 317
88. Application CCNGA2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
89. Application CCNGA2D1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
90. Application CCNGA2D2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
91. Application CCNGA2D3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
92. CCNGA2M1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
93. CCNGA2M2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
94. Comparison of struct li, alignments under ILP32 and LP64 . . . . . . . . . . . . . . . 335
95. Comparison of struct lii alignments under ILP32 and LP64 . . . . . . . . . . . . . . . 336
96. Comparison of struct ili alignments under ILP32 and LP64 . . . . . . . . . . . . . . . 337
97. Example of potential alignment problems when a struct is shared or exchanged among 32-bit
and 64-bit processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
98. Example of user-defined data padding for a structure that is shared or exchanged among 32-bit
and 64-bit processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
99. Referring to thread-specific data . . . . . . . . . . . . . . . . . . . . . . . . . 360
100. Controlling external static . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
101. Making strings constant . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
102. Example of controllong the memory area . . . . . . . . . . . . . . . . . . . . . 372
103. How to Make String Literals Modifiable . . . . . . . . . . . . . . . . . . . . . . 373
104. Referencing objects in the writable static area, Part 1 . . . . . . . . . . . . . . . . . 374
105. Referencing objects in the writable static area, Part 2 . . . . . . . . . . . . . . . . . 375
106. Arithmetic operators example . . . . . . . . . . . . . . . . . . . . . . . . . . 380
107. Relational operators example . . . . . . . . . . . . . . . . . . . . . . . . . . 381
Figures xvii
164. Sample Freestanding z/OS Routine . . . . . . . . . . . . . . . . . . . . . . . 625
165. Link edit control statements used to build a freestanding z/OS routine . . . . . . . . . . . 626
166. Compile and link using EDCCL . . . . . . . . . . . . . . . . . . . . . . . . . 626
167. Sample reentrant freestanding z/OS routine . . . . . . . . . . . . . . . . . . . . 626
168. Building and running a reentrant freestanding z/OS routine . . . . . . . . . . . . . . . 627
169. System exit example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
170. Example of function used in a persistent C environment . . . . . . . . . . . . . . . . 634
171. Using a persistent C environment . . . . . . . . . . . . . . . . . . . . . . . . 635
172. Example of user routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
173. Example of application service routine . . . . . . . . . . . . . . . . . . . . . . 640
174. Example of server initialization stub . . . . . . . . . . . . . . . . . . . . . . . 644
175. Example of server message stub-LIFO . . . . . . . . . . . . . . . . . . . . . . 646
176. Example of server message stub-FIFO . . . . . . . . . . . . . . . . . . . . . . 647
177. Example of server message stub-GET . . . . . . . . . . . . . . . . . . . . . . 649
178. Example of server message stub-TERM . . . . . . . . . . . . . . . . . . . . . . 650
179. Example of routine to generate abend . . . . . . . . . . . . . . . . . . . . . . 654
180. Example of routine to get storage . . . . . . . . . . . . . . . . . . . . . . . . 655
181. Example of routine to free storage . . . . . . . . . . . . . . . . . . . . . . . . 656
182. Location of user exits. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 668
183. Interface for Assembler user exits . . . . . . . . . . . . . . . . . . . . . . . . 673
184. CEEAUE_FLAGS format . . . . . . . . . . . . . . . . . . . . . . . . . . . 674
185. Exit_list and hook_exit control blocks . . . . . . . . . . . . . . . . . . . . . . . 683
186. Computational independence . . . . . . . . . . . . . . . . . . . . . . . . . . 686
187. Example of a C program running without MTF . . . . . . . . . . . . . . . . . . . 687
188. Processor usage with one parallel function . . . . . . . . . . . . . . . . . . . . . 689
189. Sample program using one parallel function . . . . . . . . . . . . . . . . . . . . 690
190. Processor usage with two parallel function . . . . . . . . . . . . . . . . . . . . . 690
191. Sample program using two parallel functions . . . . . . . . . . . . . . . . . . . . 691
192. Processor use with multiple instances of the same parallel function . . . . . . . . . . . . 692
193. Sample program using multiple instances of the same parallel function . . . . . . . . . . 693
194. Basic MTF layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 695
195. Identifying Computationally-Independent Code . . . . . . . . . . . . . . . . . . . 698
196. Sample code as a parallel function . . . . . . . . . . . . . . . . . . . . . . . . 698
197. Scheduling instances of a parallel function . . . . . . . . . . . . . . . . . . . . . 699
198. Main task program to call dot product function . . . . . . . . . . . . . . . . . . . 699
199. Sample code to be changed to use MTF . . . . . . . . . . . . . . . . . . . . . 700
200. Sample code (main routine) . . . . . . . . . . . . . . . . . . . . . . . . . . 701
201. Sample code (routine to create parallel functions) . . . . . . . . . . . . . . . . . . 702
202. Sample JCL to compile and link main task program . . . . . . . . . . . . . . . . . 703
203. Sample JCL to compile and link parallel functions . . . . . . . . . . . . . . . . . . 703
204. Source code for EDCMTFS . . . . . . . . . . . . . . . . . . . . . . . . . . 704
205. Example run-time JCL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705
206. Example illustrating how to use EXEC CICS commands . . . . . . . . . . . . . . . . 714
207. Format of data written to a CICS data queue . . . . . . . . . . . . . . . . . . . . 717
208. Example illustrating error handling under CICS . . . . . . . . . . . . . . . . . . . 723
209. Example illustrating how to use EXEC CICS commands . . . . . . . . . . . . . . . . 727
210. Child C program after translation . . . . . . . . . . . . . . . . . . . . . . . . 728
211. JCL to translate and compile a C program . . . . . . . . . . . . . . . . . . . . . 731
212. JCL to translate and compile a C++ program . . . . . . . . . . . . . . . . . . . . 731
213. Prelinking and linking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733
214. JCL to install z/OS XL C/C++ application programs . . . . . . . . . . . . . . . . . . 734
215. C/370 CALLing CSP under TSO. . . . . . . . . . . . . . . . . . . . . . . . . 736
216. z/OS XL Ctransferring control to CSP under TSO using the XFER/DXFR statement . . . . . . 738
217. CSP CALLing z/OS XL C under TSO . . . . . . . . . . . . . . . . . . . . . . . 740
218. CSP transferring control to z/OS XL C under TSO using the XFER statement . . . . . . . . 741
219. CSP CALLing z/OS XL C under CICS . . . . . . . . . . . . . . . . . . . . . . 744
Figures xix
xx z/OS V1R13.0 XL C/C++ Programming Guide
Tables
1. Syntax examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxvi
2. C control to ASA characters . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3. Summary of prototype functions . . . . . . . . . . . . . . . . . . . . . . . . . 25
4. Kinds of I/O supported by z/OS XL C/C++ . . . . . . . . . . . . . . . . . . . . . 27
5. I/O categories and environments that support them . . . . . . . . . . . . . . . . . . 28
6. fopen() defaults for LRECL and BLKSIZE when creating OS files . . . . . . . . . . . . . 33
7. C control to ASA characters translation table . . . . . . . . . . . . . . . . . . . . 47
8. Manipulating wide character arrays . . . . . . . . . . . . . . . . . . . . . . . . 59
9. Standard C and C++ streams . . . . . . . . . . . . . . . . . . . . . . . . . . 61
10. z/OS XL C/C++ Redirection symbols . . . . . . . . . . . . . . . . . . . . . . . 67
11. Output destinations under z/OS XL C/C++ . . . . . . . . . . . . . . . . . . . . . 68
12. z/OS XL C/C++ Interleaved output . . . . . . . . . . . . . . . . . . . . . . . . 69
13. Association of standard streams with ddnames . . . . . . . . . . . . . . . . . . . . 71
14. Standard stream behavior differences . . . . . . . . . . . . . . . . . . . . . . . 77
15. PDSE and PDS differences . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
16. Rules for possible concatenations . . . . . . . . . . . . . . . . . . . . . . . . 90
17. Other devices supported for input and output . . . . . . . . . . . . . . . . . . . . 94
18. Parameters for the fopen() and freopen() functions for z/OS OS I/O . . . . . . . . . . . . 95
19. fopen() defaults for LRECL and BLKSIZE when creating OS files . . . . . . . . . . . . 102
20. C control to ASA characters . . . . . . . . . . . . . . . . . . . . . . . . . . 107
21. Parameters for the fopen() and freopen() functions for z/OS UNIX file system I/O . . . . . . 127
22. Summary of VSAM data set characteristics and allowable I/O operations. . . . . . . . . . 151
23. Keywords for the fopen() and freopen() functions for VSAM data sets . . . . . . . . . . . 155
24. Summary of VSAM record I/O operations . . . . . . . . . . . . . . . . . . . . . 164
25. AMODE31 application XADDR support . . . . . . . . . . . . . . . . . . . . . . 167
26. Summary of fseek() and ftell() parameters in text and binary . . . . . . . . . . . . . . 170
27. Summary of VSAM text I/O operations . . . . . . . . . . . . . . . . . . . . . . 171
28. Summary of VSAM binary I/O operations . . . . . . . . . . . . . . . . . . . . . 171
29. Keywords for the fopen() and freopen() functions for terminal I/O. . . . . . . . . . . . . 190
30. Keywords for the fopen() and freopen() functions for memory file I/O . . . . . . . . . . . 201
31. __last_op codes and diagnosis information . . . . . . . . . . . . . . . . . . . . . 225
32. Linkage used by C or C++ Interlanguage Programs . . . . . . . . . . . . . . . . . 238
33. Comparison of non-XPLINK and XPLINK register conventions. . . . . . . . . . . . . . 246
34. Load service routine parameters. . . . . . . . . . . . . . . . . . . . . . . . . 271
35. Delete service routine parameters . . . . . . . . . . . . . . . . . . . . . . . . 272
36. Get-storage service routine parameters . . . . . . . . . . . . . . . . . . . . . . 272
37. Free-storage service routine parameters . . . . . . . . . . . . . . . . . . . . . . 273
38. Exception router service routine parameters . . . . . . . . . . . . . . . . . . . . 273
39. Attention router service routine parameters . . . . . . . . . . . . . . . . . . . . . 275
40. Attention handler parameters . . . . . . . . . . . . . . . . . . . . . . . . . . 275
41. Message router service routine parameters. . . . . . . . . . . . . . . . . . . . . 276
42. Summary of DLL concepts and terms . . . . . . . . . . . . . . . . . . . . . . . 280
43. Example programs to demonstrate compiling options . . . . . . . . . . . . . . . . . 302
44. Examples of how to compile two source modules and list result . . . . . . . . . . . . . 302
45. Referencing functions and external variables . . . . . . . . . . . . . . . . . . . . 303
46. Comparison of ILP32 and LP64 addressing capabilities . . . . . . . . . . . . . . . . 325
47. Comparison of ILP32 and LP64 data models . . . . . . . . . . . . . . . . . . . . 325
48. ILP32 and LP64 type size comparisons for signed and unsigned data types . . . . . . . . 326
49. Example of diagnostic messages generated from code that is not ready to be migrated from
ILP32 to LP64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
50. Comparison of ILP32 and LP64 processing and run-time options. . . . . . . . . . . . . 332
51. Comparison of data structure member lengths produced from the same code . . . . . . . . 334
52. Example of possible change of result after conversion from signed number to unsigned long 338
Copyright IBM Corp. 1996, 2012 xxi
53. Example of possible change of result after conversion from unsigned int variable to signed long 338
54. Example of possible change of result after conversion from signed long long variable to signed
long . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
55. Example of possible change of result after conversion from unsigned long long variable to
unsigned long . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
56. Example of possible change of result after conversion from signed long long variable to signed
long . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
57. Example of possible change of result after conversion from unsigned long long variable to signed
long . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
58. Examples of pointer declarations that can be made under LP64 . . . . . . . . . . . . . 341
59. Example of source code that explicitly converts an integer to a pointer . . . . . . . . . . 343
60. Example of truncation problem with a pointer cast conversion . . . . . . . . . . . . . . 343
61. Type of an integer constant . . . . . . . . . . . . . . . . . . . . . . . . . . 344
62. An attempt to share pointers between 32-bit and 64-bit processes . . . . . . . . . . . . 345
63. Example of unexpected behavior resulting from use of unsuffixed numbers . . . . . . . . . 346
64. Example of using LONG_MAX macros in a printf subroutine . . . . . . . . . . . . . . 347
65. Example of source code that successfully shares pointers between ILP32 and LP64 programs 349
66. Functions used in creating multi-threaded applications . . . . . . . . . . . . . . . . 353
67. Functions to change default attributes. . . . . . . . . . . . . . . . . . . . . . . 353
68. Functions used to control individual threads in a multi-threaded environment . . . . . . . . 354
69. Functions that allow for synchronization between threads . . . . . . . . . . . . . . . 355
70. Functions used with thread-specific data. . . . . . . . . . . . . . . . . . . . . . 359
71. Cancellation point summary . . . . . . . . . . . . . . . . . . . . . . . . . . 363
72. Functions used to control cancellability . . . . . . . . . . . . . . . . . . . . . . 363
73. Functions used for cleanup purposes . . . . . . . . . . . . . . . . . . . . . . . 364
74. Declarations of fixed-point decimal constants . . . . . . . . . . . . . . . . . . . . 378
75. Examples of Fixed-Point decimal constants and their attributes . . . . . . . . . . . . . 378
76. Intermediate results (without overflow in n or p) . . . . . . . . . . . . . . . . . . . 382
77. Intermediate results (in the general form) . . . . . . . . . . . . . . . . . . . . . 382
78. Operators used with decimal data types . . . . . . . . . . . . . . . . . . . . . . 384
79. C/C++ functions that support floating-point . . . . . . . . . . . . . . . . . . . . . 399
80. Special purpose C/C++ functions that support floating-point. . . . . . . . . . . . . . . 401
81. Functions that establish a signal handler . . . . . . . . . . . . . . . . . . . . . 412
82. Other signal-related functions . . . . . . . . . . . . . . . . . . . . . . . . . . 412
83. Hardware exceptions - Default run-time messages and system actions . . . . . . . . . . 417
84. Software exceptions - Default run-time messages and system actions with POSIX(OFF) 417
85. Default signal processing with POSIX(ON) . . . . . . . . . . . . . . . . . . . . . 419
86. Original versions of fdlibm functions . . . . . . . . . . . . . . . . . . . . . . . 494
87. Standard general-instruction prototypes . . . . . . . . . . . . . . . . . . . . . . 503
88. Built-in general-instruction prototypes . . . . . . . . . . . . . . . . . . . . . . . 505
89. PLO helper macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
90. Compare and load prototypes . . . . . . . . . . . . . . . . . . . . . . . . . 523
91. Compare and swap prototypes . . . . . . . . . . . . . . . . . . . . . . . . . 524
92. Double compare and swap prototypes . . . . . . . . . . . . . . . . . . . . . . 524
93. Compare and swap and store prototypes . . . . . . . . . . . . . . . . . . . . . 525
94. Compare swap and double store prototypes . . . . . . . . . . . . . . . . . . . . 525
95. Compare and swap and triple store prototypes . . . . . . . . . . . . . . . . . . . 526
96. Decimal instruction prototypes . . . . . . . . . . . . . . . . . . . . . . . . . 527
97. Floating-point instruction prototypes . . . . . . . . . . . . . . . . . . . . . . . 528
98. Decimal floating-point instruction prototypes for IEEE operations . . . . . . . . . . . . . 529
99. Decimal floating-point instruction prototypes for IEEE . . . is operations . . . . . . . . . . 531
100. Decimal floating-point instruction prototypes for IBM Instructions . . . . . . . . . . . . . 532
101. Hexadecimal floating-point instruction prototypes . . . . . . . . . . . . . . . . . . 538
102. Binary floating-point instruction prototypes . . . . . . . . . . . . . . . . . . . . . 539
103. Built-in functions for transactional memory . . . . . . . . . . . . . . . . . . . . . 542
104. SUSv3 options and option groups . . . . . . . . . . . . . . . . . . . . . . . . 550
Tables xxiii
xxiv z/OS V1R13.0 XL C/C++ Programming Guide
About this document
This document provides information about implementing programs that are written
in C and C++. It contains advanced guidelines and information for developing C and
C++ programs to run under z/OS.
Note: As of z/OS V1R7, the z/OS C/C++ compiler has been rebranded to z/OS XL
C/C++.
You may notice changes in the style and structure of some of the contents in this
document; for example, headings that use uppercase for the first letter of initial
words only, and procedures that have a different look and format. The changes are
ongoing improvements to the consistency and retrievability of information in our
documents.
Syntax diagrams pictorially display the order and parts (options and arguments) that
comprise a command statement. They are read from left to right and from top to
bottom, following the main path of the horizontal line.
For users accessing the Information Center using a screen reader, syntax diagrams
are provided in dotted decimal format.
Symbols
The following symbols may be displayed in syntax diagrams:
Symbol Definition
Indicates the beginning of the syntax diagram.
Indicates that the syntax diagram is continued to the next line.
Indicates that the syntax is continued from the previous line.
Indicates the end of the syntax diagram.
Syntax items
Syntax diagrams contain many different items. Syntax items include:
v Keywords - a command name or any other literal information.
v Variables - variables are italicized, appear in lowercase, and represent the name
of values you can supply.
v Delimiters - delimiters indicate the start or end of keywords, variables, or
operators. For example, a left parenthesis is a delimiter.
v Operators - operators include add (+), subtract (-), multiply (*), divide (/), equal
(=), and other mathematical operations that may need to be performed.
Note: If a syntax diagram shows a character that is not alphanumeric (for example,
parentheses, periods, commas, equal signs, a blank space), enter the character as
part of the syntax.
Syntax examples
The following table provides syntax examples.
Table 1. Syntax examples
Item Syntax example
Required item.
KEYWORD required_item
Required items appear on the main path of the
horizontal line. You must specify these items.
Required choice.
KEYWORD required_choice1
A required choice (two or more items) appears
in a vertical stack on the main path of the
required_choice2
horizontal line. You must choose one of the
items in the stack.
Optional item.
KEYWORD
Optional items appear below the main path of
the horizontal line.
optional_item
Optional choice.
KEYWORD
An optional choice (two or more items) appears
in a vertical stack below the main path of the
optional_choice1
horizontal line. You may choose one of the optional_choice2
items in the stack.
Default.
default_choice1
Default items appear above the main path of
the horizontal line. The remaining items
KEYWORD
(required or optional) appear on (required) or optional_choice2
below (optional) the main path of the horizontal optional_choice3
line. The following example displays a default
with optional items.
Variable.
KEYWORD variable
Variables appear in lowercase italics. They
represent names or values.
This document is updated weekly and lists documentation changes before they are
incorporated into z/OS publications.
To access the z/OS Basic Skills Information Center, open your Web browser to the
following Web site, which is available to all users (no login required):
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp
IBM or any other organizations will only use the personal information that you
supply to contact you about the issues that you submit.
New information:
v A new environment variable has been added to provide enhanced I/O abend
recovery support; see _EDC_IO_ABEND on page 494 for more information.
v The abend= parameter has been added to the fopen() and freopen() functions;
this parameter controls if the run-time library should attempt to recover from an
abend that is issued during an I/O operation. In addition, the rlse and norlse
keywords have been added to the space= parameter. See Table 18 on page 95
for more information.
v Support for 10 new text locales has been added; see Table 140 on page 937 for
details.
v Support for new standard and built-in general instruction prototypes has been
added; for more information, see Table 88 on page 505.
v New built-in functions have been added to mark the beginning and end of
transactions, and to diagnose the reasons for failure. For detailed information,
see Built-in functions for transaction execution on page 541.
Changed information:
v Information about the preservation of the contents of high registers has been
added to Get-storage service routine on page 272 and Free-storage service
routine on page 273.
v Information about large file support has been clarified in Chapter 10, Performing
OS I/O operations, on page 81.
v Figure 157 on page 556 (saved options information layout) has been updated.
v Reference information about using UCS-2 codeset conversion has been updated
in Codeset conversion using UCS-2 on page 880.
Deleted information:
v Information about using fseek() and ftell() in binary files been removed.
v Information about default signal processing with POSIX(ON) for the SIGDCE
event has been removed.
New information:
v Information has been added for the z/OS XL C/C++ support for accessing an
extended addressable VSAM KSDS data set through an alternate index. For the
details, see Chapter 12, Performing VSAM I/O operations, on page 147.
Changed information:
v Updated getdate_err on page 1008 in Appendix J, External variables, on page
1007.
v An restriction has been added to the _BPXK_AUTOCVT and _BPXK_CCSIDS
environment variables in Chapter 32, Using environment variables, on page
467.
v Updated Chapter 58, Customizing a time zone, on page 847.
v The "Readers' Comments - We'd Like to Hear from You" section at the back of
this publication has been replaced with a new section How to send your
comments to IBM on page xxix. The hardcopy mail-in form has been replaced
with a page that provides information appropriate for submitting readers
comments to IBM.
New information:
v Information has been added for the support of z/OS XL C/C++ compiler direction.
Using built-in library functions and macros on page 577 has been updated to
indicate replacing wcsxxx() functions with their corresponding wmemxxx()
functions, whenever possible.
The C-library built-in functions described in Table 111 on page 583 have been
updated with new information.
Using functions in the system programming C environment on page 620 has
been updated to indicate that 4 new functions are available as built-in.
v A new compiled ASCII locale has been added to Table 140 on page 937.
v File I/O trace on page 232 and Locating the file I/O trace on page 233 has
been added to Chapter 18, Debugging I/O programs, on page 221.
Changed information:
v Updates have been made to fldata() behavior on page 119.
v IEEE binary and decimal floating-point can be supported in a CICS environment.
See Using IEEE floating-point on page 398.
v Table 79 on page 399 has been updated with more C/C++ functions that support
floating point.
v A note in Chapter 10, Performing OS I/O operations, on page 81 has been
updated to indicate z/OS XL C/C++ does not support non-VSAM keyed data sets.
v Updates have been made to Identifying hardware and software signals on page
415 and Default handling of signals on page 418.
v Updates have been made to Overview of the layout functions on page 904 and
Using the layout functions on page 909.
The C run-time functions are available if the corresponding C header files are used.
C I/O can be used by C++ when the C run-time library functions are used.
The z/OS XL C/C++ compiler supports three types of input and output: text streams,
binary streams, and record I/O. Text and binary streams are both ANSI standards;
record I/O is an extension for z/OS XL C. Record I/O is not supported by either the
USL I/O Stream Class Library or the Standard C++ I/O stream classes.
Note: If you have written data in one of these three types and try to read it as
another type (for example, reading a binary file in text mode), you may not get the
behavior that you expect.
Text streams
Text streams contain printable characters and, depending on the type of file, control
characters. Text streams are organized into lines. Each line ends with a control
character, usually a new-line. The last record in a text file may or may not end with
a control character, depending on what kind of file you are using. Text files
recognize the following control characters:
\a Alarm.
\b Backspace.
\f Form feed.
\n New-line.
\r Carriage return.
\t Horizontal tab character.
\v Vertical tab character.
\x0E DBCS shift-out character. Indicates the beginning of a DBCS string, if
MB_CUR_MAX>1 in the definition of the locale that is in effect. For more
information about __MBCURMAX, see Chapter 8, z/OS XL C Support for the
double-byte character set, on page 51.
\x0F DBCS shift-in character. Indicates the end of a DBCS string, if
MB_CUR_MAX>1 in the definition of the locale that is in effect. For more
information about __MBCURMAX, see Chapter 8, z/OS XL C Support for the
double-byte character set, on page 51.
Control characters behave differently in terminal files (see Chapter 13, Performing
terminal I/O operations, on page 189) and ASA files (see Chapter 7, Using ASA
text files, on page 47).
Record I/O
Record I/O is an extension to the ISO standard. For files opened in record format,
z/OS XL C/C++ reads and writes one record at a time. If you try to write more data
to a record than the record can hold, the data is truncated. For record I/O, z/OS XL
C/C++ allows only the use of fread() and fwrite() to read and write to files. Any
other functions (such as fprintf(), fscanf(), getc(), and putc()) will fail. For
record-oriented files, records do not change size when you update them. If the new
record has fewer characters than the original record, the new data fills the first n
characters, where n is the number of characters of the new data. The record will
remain the same size, and the old characters (those after n) are left unchanged. A
subsequent update begins at the next boundary. For example, if you have the string
"abcdefgh":
a b c d e f g h
and you overwrite it with the string "1234", the record will look like this:
1 2 3 4 e f g h
z/OS XL C/C++ record I/O is binary. That is, it does not interpret any of the data in
a record file and therefore does not recognize control characters. The only
exception is for file categories that do not support records, such as the UNIX file
system (also known as POSIX I/O). For these files, z/OS XL C/C++ uses new-line
characters as record boundaries.
The next chapter (Chapter 4, Using the Standard C++ Library I/O Stream Classes,
on page 21) describes a third major model, the object-oriented model.
In the record model of I/O, records and blocks have the following attributes:
RECFM Specifies the format of the data or how the data is organized on the
physical device.
LRECL Specifies the length of logical records (as opposed to physical
ones). Variable length records include a count field that is normally
not available to the programmer.
BLKSIZE Specifies the length of physical records (blocks on the physical
device).
Record formats
Use the RECFM attribute to specify the record format. The records in a file using the
record model have one of the following formats:
v Fixed-length (F)
v Variable-length (V)
v Undefined-length (U)
These formats support the following additional options for RECFM. The record formats
and the options associated with them are discussed in the following sections.
A Specifies that the file contains ASA control characters.
B Specifies that a file is blocked. A blocked file can have more than one
record in each block.
M Specifies that the file contains machine control characters.
S Specifies that a file is either in standard format (if it is fixed) or spanned (if it
is variable). In a standard file, every block must be full before another one
starts. In a spanned file, a record can be longer than a block. If it is, the
record is divided into segments and stored in consecutive blocks.
Fixed-format records
These are the formats you can specify for RECFM if you want to use a fixed-format
file:
F Fixed-length, unblocked
FA Fixed-length, ASA print-control characters
FB Fixed-length, blocked
FM Fixed-length, machine print-control codes
FS Fixed-length, unblocked, standard
FBA Fixed-length, blocked, ASA print-control characters
FBM Fixed-length, blocked, machine print-control codes
FBS Fixed-length, blocked, standard
FSA Fixed-length, unblocked, standard, ASA print-control characters
FSM Fixed-length, unblocked, standard, machine print-control codes
FBSM Fixed-length, blocked, standard, machine print-control codes
FBSA Fixed-length, blocked, standard, ASA print-control characters.
In general, all references to files with record format FB also refer to FBM and FBA.
The specific behavior of ASA files (such as FBA) is explained in Chapter 7, Using
ASA text files, on page 47.
If the records are FB, some blocks may contain fewer records than others, as shown
in Figure 1 on page 11.
Block Block
Mapping C types to fixed format: This section describes the following formats:
v Binary
v Text (non-ASA)
v Text (ASA)
v Record
Binary On binary input and output, data flows over record boundaries.
Because all fixed-format records must be full, z/OS XL C/C++
completes any incomplete output record by padding it with nulls
(\0) when you close the file. Incomplete blocks are not padded.
On input, nulls are visible and are treated as data.
For example, if record length is set to 10 and you are writing 25
characters of data, z/OS XL C/C++ will write two full records, each
containing 10 characters, and then an incomplete record containing
5 characters. If you then close the file, z/OS XL C/C++ will
complete the last record with 5 nulls. If you open the file for
reading, z/OS XL C/C++ will read the records in order. z/OS XL
C/C++ will not strip off the nulls at the end of the last record.
Text (non-ASA)
When writing in a text stream, you indicate the end of the data for a
record by writing a new-line (\n) or carriage return (\r) to the
stream. In a fixed-format file, the new-line or carriage return will not
appear in the external file, and the record will be padded with
blanks from the position of the new-line or carriage return to
LRECL. (A carriage return is considered the same as a new-line
because the \r is not written to the file.)
For example, if you have set LRECL to 10, and you write the string
"ABC\n" to a fixed-format text file, z/OS XL C/C++ will write this to
the physical file:
A B C
file pointer
and you call fgets() to read the line of text, fgets() places the
string "ABC\n" in your input buffer.
1 2 3 4 5 6
file pointer
A B C D E F ...
You can lengthen and shorten records the same way as you can for
non-ASA files. For more information about ASA, refer to Chapter 7,
Using ASA text files, on page 47.
Record As with fixed-format text files, a record can hold LRECL characters.
Every call to fwrite() is considered to be writing a full record. If
you write fewer than LRECL characters, z/OS XL C/C++ completes
the record with enough nulls to make it LRECL characters long. If
you try to write more than that, z/OS XL C/C++ truncates the data.
Variable-format records
In a file with variable-length records, each record may be a different length. The
variable length formats permit both variable-length records and variable-length
blocks. The first 4 bytes of each block are reserved for the Block Descriptor Word
(BDW); the first 4 bytes of each record are reserved for the Record Descriptor Word
(RDW), or, if you are using spanned files, the Segment Descriptor Word (SDW).
Illustrations of variable-length records are shown in Figure 2 on page 15.
The value of LRECL must be greater than 4 to accommodate the RDW or SDW.
The value of BLKSIZE must be greater than or equal to the value of LRECL plus 4.
You should not use a BLKSIZE greater than LRECL plus 4 for an unblocked data
set. Doing so results in buffers that are larger than they need to be. The largest
amount of data that any one record can hold is LRECL bytes minus 4.
For striped data sets, a block is padded out to its full BLKSIZE. This makes
specifying an unnecessarily large BLKSIZE very inefficient.
Record format (RECFM): You can specify the following formats for variable-length
records:
V Variable-length, unblocked
VA Variable-length, ASA print control characters, unblocked
VB Variable-length, blocked
VM Variable-length, machine print-control codes, unblocked
VS Variable-length, unblocked, spanned
VBA Variable-length, blocked, ASA print control characters
VBM Variable-length, blocked, machine print-control codes
VBS Variable-length, blocked, spanned
VSA Variable-length, spanned, ASA print control characters
VSM Variable-length, spanned, machine print-control codes
VBSA Variable-length, blocked, spanned, ASA print control characters
VBSM Variable-length, blocked, spanned, machine print-control codes
Note: In general, all references in this guide to files with record format VB also refer
to VBM and VBA. The specific behavior of ASA files (such as VBA) is explained in
Chapter 7, Using ASA text files, on page 47.
Spanned records: A spanned record is opened using both V and S in the format
specifier. A spanned record is a variable-length record in which the length of the
record can exceed the size of a block. If it does, the record is divided into segments
and accommodated in two or more consecutive blocks. The use of spanned records
allows you to select a block size, independent of record length, that will combine
optimum use of auxiliary storage with the maximum efficiency of transmission.
VS-format specifies that each block contains only one record or segment of a
record. The first 4 bytes of a block describe the block control information. The
VBS-format differs from VS-format in that each block in VBS-format contains as many
complete records or segments as it can accommodate, while each block in
VS-format contains at most one record per block.
V-format:
C1 C2 Record 1 C1 C2 Record 2 C1 C2
VB-format:
Block
VS-format:
Spanned Record
VBS-format:
Spanned Record
Note: If you need to see the BDWs, RDWs, or SDWs, you can
open and read a V-format file as a U-format file. See
Undefined-format records on page 16 for more information.
z/OS XL C/C++ never creates empty binary records for files opened
in V-format. See Writing to binary files on page 106 for more
information. An empty binary record is one that contains only an
RDW, which is 4 bytes long. On input, empty records are ignored.
Text (non-ASA)
Record boundaries are used in the physical file to represent the
Undefined-format records
Everything in an undefined-format file is treated as data, including control
characters and record boundaries. Blocks in undefined-format records are
variable-length; each block is considered a record.
Record format (RECFM): You can specify the following formats for
undefined-length records:
U Undefined-length
UA Undefined-length, ASA print control characters
UM Undefined-length, machine print-control codes
U, UA, and UM formats permit the processing of records that do not conform to F- and
V-formats. The operating system treats each block as a record; your program must
perform any additional blocking or deblocking.
You can read any file in U-format. This is useful if, for example, you want to see the
BDWs and RDWs of a file that you have written in V-format.
If the file is opened in binary mode, any new-line characters previously written to
the file are visible on input. z/OS XL C/C++ memory file I/O and Hiperspace
memory file I/O are based on the byte stream model (see Chapter 14, Performing
memory file and hiperspace I/O operations, on page 199 for more information).
UNIX file system I/O, defined by POSIX, is also based on the byte stream model.
See Chapter 11, Performing z/OS UNIX file system I/O operations, on page 123
for information about I/O with UNIX file system.
A B C \n D E F \n ...
If you are using files with this model, do not use new-line
characters in your output. If you do, they will create extra record
boundaries. If you are unsure about the data being written or are
writing numeric data, use binary instead of text to avoid writing a
byte that has the hex value of a new-line.
There are two base classes, ios and streambuf, from which all other I/O stream
classes are derived. The ios class and its derivative classes are used to implement
formatting of I/O and maintain error state information of stream buffers implemented
with the streambuf class.
The I/O stream classes use OBJECTMODEL(COMPAT). They cannot be used with
other classes that use OBJECTMODEL(IBM), within the same inheritance
hierarchy. For more information, see OBJECTMODEL in z/OS XL C/C++ User's
Guide.
Note: The only exception is that cerr is unit-buffered (that is, ios::unitbuf is set).
A filebuf object is associated with each ifstream, ofstream, and fstream object.
When the filebuf is flushed, it writes to the underlying C stream, which has its own
buffer. The filebuf object follows every fwrite() to the underlying C stream with
an fflush().
Mixing the Standard C++ I/O stream classes, USL I/O stream class
library, and C I/O library functions
It is not recommended to mix the usage of the Standard C++ I/O stream classes,
USL I/O Stream Class Library, and C I/O library functions.
The USL I/O stream class library uses a separate buffer, which means that you
would need to flush the buffer after each call to cout either by setting ios::unitbuf
or by calling sync_with_stdio().
You should avoid switching between the formatted extraction functions of the C++
I/O stream classes and C stdio library functions whenever possible. You should
also avoid switching between versions of these classes.
For more information on mixing the I/O stream classes refer to Interleaving the
standard streams with sync_with_stdio() on page 63 and Interleaving the standard
streams without sync_with_stdio() on page 64.
For z/OS XL C++, overloaded fstream, ifstream, and ofstream constructors, and
open() member functions, with an additional parameter, are provided so you can
specify z/OS XL C fopen() mode values. You can use this additional parameter to
specify any z/OS XL C fopen() mode value except type=record. If you choose to
To open a file stream with a previously opened z/OS UNIX file descriptor, use the
fdopen() function.
To open files with UNIX file system low-level I/O, use the open() function. For more
information about opening files in UNIX file system, see Chapter 11, Performing
z/OS UNIX file system I/O operations, on page 123.
Prototypes of functions
Table 3 summarizes the prototypes of various functions. For more detailed
information about the C I/O stream functions, see z/OS XL C/C++ Run-Time Library
Reference. For more detailed information about the C++ I/O stream classes, see
Standard C++ Library Reference, which discusses the Standard C++ I/O stream
classes.
Table 3. Summary of prototype functions
Type of function Prototype
C Library Functions FILE *fopen(const char *filename, const char *mode);
// ifstream::open()
void open(const char* fname, int mode=ios::in,
int prot=filebuf::openprot);
// ofstream constructor
ofstream(const char* fname, int mode=ios::out,
int prot=filebuf::openprot);
// ofstream::open()
void open(const char* fname, int mode=ios::out,
int prot=filebuf::openprot);
// fstream::open()
void open(const char* fname, int mode,
int prot=filebuf::openprot);
// filebuf::open()
filebuf* open(const char* fname, int mode,
int prot=filebuf::openprot);
Note: CICS Data Queues and z/OS Language Environment Message File do not
apply in AMODE 64 applications. Hiperspace Memory Files are opened as (regular)
Memory Files since the size of a (regular) Memory File can exceed 2GB in AMODE
64 applications.
Table 4. Kinds of I/O supported by z/OS XL C/C++
Type of I/O Suggested Uses and Supported Devices Model Page
OS I/O Used for dealing with the following kinds of files: Record 81
v Generation data group
v MVS sequential DASD files
v Regular and extended partitioned data sets
v Tapes
v Printers
v Punch data sets
v Card reader data sets
v MVS inline JCL data sets
v MVS spool data sets
v Striped data sets
v Optical readers
UNIX file system I/O Used under z/OS UNIX System Services (z/OS UNIX) to support Byte stream 123
data sets in the UNIX file system, and access the byte-oriented
UNIX file system files according to POSIX .1 and XPG 4.2
interfaces. This increases the portability of applications written on
UNIX-based systems to z/OS XL C/C++ systems.
VSAM I/O Used for working with VSAM data sets. Supports direct access to Record 147
records by key, relative record number, or relative byte address.
Supports entry-sequenced, relative record, and key-sequenced
data sets.
Terminal I/O Used to perform interactive input and output operations with a Record 189
terminal.
Memory Files Used for applications requiring temporary I/O files without the Byte stream 199
overhead of system data sets. Fast and efficient.
Hiperspace Memory Used to deal with memory files as large as 2 gigabytes. Byte stream 199
Files
CICS Data Queues Used under the Customer Information Control System (CICS). Record 213
CICS data queues are automatically selected under CICS for the
standard streams stdout and stderr for C, or cout and cerr for
C++. The CICS I/O commands are supported through the
Command Level interface. The standard stream stdin under C (or
cin under C++) is treated as an empty file under CICS.
z/OS Language Used when you are running with z/OS Language Environment. The Record 215
Environment Message message file is automatically selected for stderr under z/OS
File Language Environment. For C++, automatic selection is of cerr.
Table 5 on page 28 lists the environments that z/OS XL C/C++ supports, and which
categories of I/O work in which environment.
OS files
z/OS XL C/C++ treats a file as an OS file, provided that it is not a CICS data
queue, or a UNIX file system, VSAM, memory, terminal, or Hiperspace file.
Terminal files
When you are running with the run-time option POSIX(OFF) under interactive TSO,
z/OS XL C/C++ associates streams to the terminal. You can also call fopen() to
open the terminal directly if you are running under TSO (interactive or batch), and
either the file name you specify begins with an asterisk (*), or the ddname has been
allocated with a DSN of *.
When running with POSIX(ON), z/OS XL C/C++ associates streams to the terminal
under TSO and a shell if the file name you have specified fits one of the following
criteria:
v Under TSO (interactive and batch), the name must begin with the sequence
//*, or the ddname must have been allocated with a DSN of *.
Interactive IMS and CICS behave differently from what is described here. For more
information about terminal files with interactive IMS and CICS see Chapter 9, Using
C and C++ standard streams and redirection, on page 61.
If you are running with POSIX(ON) outside a shell, you must use the regular z/OS XL
C/C++ I/O functions for terminal I/O. If you are running with POSIX(ON) from a shell,
you can use the regular z/OS XL C/C++ I/O functions or the POSIX low-level
functions (such as read()) for terminal I/O.
While a memory file exists, you can just use another fopen() or freopen() that
specifies the memory file's name. As sample program CCNGOF1 shows in Figure 3,
you do not have to specify type=memory.
/* this example shows how fopen() may be used with memory files */
#include <stdio.h>
char text[3], *result;
FILE * fp;
int main(void)
{
fp = fopen("a.b", "w, type=memory"); /* Opens a memory file */
fprintf(fp, "%d\n",10); /* Writes to the file */
fclose(fp); /* Closes the file */
fp = fopen("a.b", "r"); /* Reopens the same */
/* file (already */
/* a memory file) */
if ((result=fgets(text,3,fp)) !=NULL) /* Retrieves results */
printf("value retrieved is %s\n",result);
fclose(fp); /* Closes the file */
return(0);
}
A valid memory file name will match current file restrictions on a real file. Thus, a
memory file name that is classified as UNIX file system can have more characters
than can one classified as an MVS file name.
If you are not running under CICS, you can open a Hiperspace memory file as
follows:
fp = fopen("a.b", "w, type=memory(hiperspace)");
If you specify hiperspace and you are running in a CICS environment, z/OS XL
C/C++ opens a regular memory file. If you are running with the run-time options
You cannot use fopen() or freopen() to specify this kind of I/O. It is the category
selected automatically when you call any ANSI functions that reference stdout and
stderr under CICS. If you reference either of these in a C or C++ program under
CICS, z/OS XL C/C++ attempts to open the CESO (stdout) or CESE (stderr)
queue. If you want to write to any other queue, you should use the CICS-provided
interface.
See Chapter 16, Language Environment Message file operations, on page 215 for
more information on z/OS Language Environment message files.
When you call fopen() and specify a write mode (w, wb, w+, wb+, w+b) for an
existing file, z/OS XL C/C++ uses the default values for fopen() if:
v the data set is opened by the data set name or
v the data set is opened by ddname and the DD statement does not have any
attributes filled in.
These defaults are listed in Table 6 on page 33. To force z/OS XL C/C++ to use
existing attributes when you are opening a file, specify recfm=* (or recfm=+) on the
fopen() or freopen() call.
Certain categories of I/O may ignore or simulate some attributes such as BLKSIZE
or RECFM that are not physically supported on the device. Table 4 on page 27 lists
all the categories of I/O that z/OS XL C/C++ supports and directs you to where you
can find more information about them.
If you are creating a file and you do not select a record size, z/OS XL C/C++ uses a
default. See fopen() defaults on page 32 for details on how defaults are
calculated.
If you are creating a file and do not select a block size, z/OS XL C/C++ uses a
default. The defaults are listed in Table 6 on page 33.
fopen() defaults
You cannot specify a file attribute more than once on a call to fopen() or freopen().
If you do, the function call fails. If the file attributes specified on the call to fopen()
differ from the actual file attributes, fopen() usually fails. However, fopen() does
not fail if:
v The file is opened for w, w+, wb, or wb+, and the file is neither an existing PDS or
PDSE nor an existing file opened by a ddname that specifies DISP=MOD. In such
instances, fopen() attributes override the actual file attributes. However, if
recfm=* (or recfm=+) is specified on the fopen(), any attributes that are not
specified either on the fopen() or for the ddname will be retrieved from the
existing file. If the final combination of attributes is invalid, the fopen() will fail.
v The file is opened for reading (r or rb) with recfm=U. Any other specified
attributes should be compatible with those of the existing data set.
In calls to fopen(), the LRECL, BLKSIZE, and RECFM parameters are optional. (If
you are opening a file for read or append, any attributes that you specify must
match the existing attributes.)
If you do not specify file attributes for fopen() (or for an I/O stream object), you get
the following defaults.
RECFM defaults
If recfm is not specified in a fopen() call for an output binary file, recfm defaults to:
v recfm=VB for spool (printer) files
v recfm=FB otherwise
If recfm is not specified in a fopen() call for an output text file, recfm defaults to:
v recfm=F if _EDC_ANSI_OPEN_DEFAULT is set to Y and no LRECL or BLKSIZE
specified. In this case, LRECL and BLKSIZE are both defaulted to 254.
v recfm=VBA for spool (printer) files.
v recfm=U for terminal files.
v recfm=VB for MVS files.
v recfm=VB for all other OS files.
If recfm is not specified for a record I/O file, you will get the default of recfm=VB.
In Table 6, the value max represents the maximum block size for the device. These
are the current default maximum block sizes for several devices that z/OS XL
C/C++ supports:
Device Block Size
DASD 6144
3203 Printer 132
3211 Printer 132
4245 Printer 132
2540 Reader 80
2540 Punch 80
2501 Reader 80
3890 Document Processor 80
TAPE 32760
For more information about specific default block sizes, as returned by the DEVTYPE
macro, refer to z/OS DFSMS Using Data Sets.
For DASD files that do not have recfm=U, if you specify blksize=0 on the call to
fopen() or freopen() and you have DFP Release 3.1 or higher, the system
determines the optimal block size for your file. If you do not have the correct level
of DFP or you specify blksize=0 for a ddname instead of specifying it on the
fopen() or freopen() call, z/OS XL C/C++ behaves as if you had not specified the
blksize parameter at all.
For information about block sizes for different categories of I/O, see the chapters
listed in Table 4 on page 27.
To determine the maximum LRECL and BLKSIZE values for the various file types
and devices available on your operating system, refer to the chapters listed in
Table 4 on page 27.
DDnames
DD names are specified by prefixing the DD name with DD:. All the following
forms of the prefix are supported:
v DD:
v dd:
v dD:
v Dd:
The DD statement enables you to write C source programs that are independent of
the files and input/output devices they will use. You can modify the parameters of a
file (such as LRECL, BLKSIZE, and RECFM) or process different files without
recompiling your program.
v How to create a DDname under MVS batch
To create a ddname under MVS batch, you must write a JCL DD statement. For
the C file PARTS.INSTOCK, you would write a JCL DD statement similar to the
following:
//STOCK DD DSN=PARTS.INSTOCK, . . .
UNIX file system files can be allocated with a DD card, as shown in the following
example:
//STOCK DD PATH=/u/parts.instock,
// PATHOPTS=(OWRONLY,OCREAT,OTRUNC),
// PATHMODE=(SIRWXU,SIRWXO,SIRWXG)
When defining DD, do not use DD ... FREE=CLOSE for unallocating DD
statements. The C library may close files to perform some file operations such as
freopen(), and the DD statement will be unallocated.
For more information on writing DD statements, refer to the JCL manuals listed in
z/OS Information Roadmap.
v How to create a DDname under TSO
To create a ddname under TSO, you must write an ALLOCATE command. For the
declaration shown above for the C file STOCK, you should write a TSO ALLOCATE
statement similar to the following:
ALLOCATE FILE(STOCK) DATASET(PARTS.INSTOCK)
You can also allocate UNIX file system files with TSO ALLOCATE commands. For
example:
You do not always need to describe the characteristics of the data in files both
within the program and outside it. There are, in fact, advantages to describing the
characteristics of your data in only one place.
Opening a file by ddname may require the merging of information internal and
external to the program. If any conflict is detected that will prevent the opening of a
file, fopen() returns a NULL pointer to indicate that the file cannot be opened. See
z/OS XL C/C++ Run-Time Library Reference for more information on fopen().
Note: You can open a ddname only with fopen() or freopen(). open() does not
interpret ddnames as such.
Note: Files cannot be opened under CICS when you have specified the POSIX(ON)
run-time option.
MAP 0010: Under TSO, MVS batch, IMS POSIX(ON) on page 36 shows how
z/OS XL C/C++ determines what type of file to open under TSO, MVS batch, and
interactive IMS with POSIX(ON). For information on the types of files shown in the
chart, see the appropriate chapter in the I/O section.
001
Is type=memory specified?
Yes No
002
003
Continue at Step 017 on page 37.
004
Continue at Step 008.
005
Is hiperspace specified?
Yes No
006
z/OS XL C/C++ opens a regular memory file.
007
z/OS XL C/C++ opens a memory file in Hiperspace.
008
009
010
011
z/OS XL C/C++ opens an OS file.
012
z/OS XL C/C++ opens the existing memory file.
013
Continue to Step 032 on page 38.
014
015
z/OS XL C/C++ removes the asterisk from the name unless the asterisk is
the only character, and proceeds to Step 028 on page 38.
016
z/OS XL C/C++ opens a terminal file.
017
018
019
z/OS XL C/C++ opens a UNIX file system file.
020
z/OS XL C/C++ opens the existing memory file.
021
022
023
z/OS XL C/C++ opens a UNIX file system file called either *DD:ddname
or DD:ddname.
024
z/OS XL C/C++ opens the existing memory file.
025
026
z/OS XL C/C++ opens an OS file.
027
z/OS XL C/C++ opens a UNIX file system file.
028
029
030
z/OS XL C/C++ opens an OS file.
031
z/OS XL C/C++ opens the existing memory file.
032
033
034
***ERROR***
035
z/OS XL C/C++ opens the existing memory file.
036
037
z/OS XL C/C++ opens an OS file.
038
z/OS XL C/C++ opens a UNIX file system file.
MAP 0020: Under TSO, MVS batch, IMS POSIX(OFF) on page 40 shows how
z/OS XL C/C++ determines what type of file to open under TSO, MVS batch, and
interactive IMS with POSIX(OFF). For information on the types of files shown in the
chart, see the appropriate chapter in the I/O section.
001
Is type=memory specified?
Yes No
002
003
Continue at Step 017 on page 41.
004
Continue at Step 008.
005
Is hiperspace specified?
Yes No
006
z/OS XL C/C++ opens a regular memory file.
007
z/OS XL C/C++ opens a memory file in Hiperspace.
008
009
010
011
z/OS XL C/C++ opens an OS file.
012
z/OS XL C/C++ opens the existing memory file.
013
Continue at Step 021.
014
015
z/OS XL C/C++ removes the asterisk from the name unless the asterisk is
the only character, and proceeds to Step 017.
016
z/OS XL C/C++ opens a terminal file.
017
018
019
z/OS XL C/C++ opens an OS file.
020
z/OS XL C/C++ opens the existing memory file.
021
022
023
***ERROR***
024
z/OS XL C/C++ opens the existing memory file.
025
026
z/OS XL C/C++ opens an OS file.
027
z/OS XL C/C++ opens a UNIX file system file.
MAP 0030: Under CICS on page 43 shows how z/OS XL C/C++ determines what
type of file to open under CICS. For information on the types of files shown in the
chart, see the appropriate chapter in the I/O section.
001
Is type=memory specified?
Yes No
002
003
The fopen() call fails.
004
z/OS XL C/C++ opens that memory file.
005
Is hiperspace specified?
Yes No
006
z/OS XL C/C++ opens the specified memory file.
007
The fopen() call ignores the hiperspace specification and opens the memory file.
z/OS XL C/C++ uses buffers to map C I/O to system-level I/O. When z/OS XL
C/C++ performs I/O operations, it uses one of the following buffering modes:
v Line buffering - characters are transmitted to the system as a block when a
new-line character is encountered. Line buffering is meaningful only for text
streams and UNIX file system files.
v Full buffering - characters are transmitted to the system as a block when a buffer
is filled.
v No buffering - characters are transmitted to the system as they are written. Only
regular memory files and UNIX file system files support the no buffering mode.
The buffer mode affects the way the buffer is flushed. You can use the setvbuf()
and setbuf() library functions to control buffering, but you cannot change the
buffering mode after an I/O operation has used the buffer, as all read, write, and
reposition operations do. In some circumstances, repositioning alters the contents of
the buffer. It is strongly recommended that you only use setbuf() and setvbuf()
before any I/O, to conform with ANSI, and to avoid any dependency on the current
implementation. If you use setvbuf(), z/OS XL C/C++ may or may not accept your
buffer for its internal use. For a hiperspace memory file, if the size of the buffer
specified to setvbuf() is 8K or more, it will affect the number of hiperspace blocks
read or written on each call to the operating system; the size is rounded down to
the nearest multiple of 4K.
For record I/O files, buffering is meaningful only for blocked files or for record I/O
files in z/OS UNIX file system using full buffering. For unblocked files, the buffer is
full after every write and is therefore written immediately, leaving nothing to flush.
For blocked files or fully-buffered UNIX file system files, however, the buffer can
contain one or more records that have not been flushed and that require a flush
operation for them to go to the system.
You may not see output if a program that is using input and output fails, and the
error handling routines cannot close all the open files.
z/OS XL C/C++ translates control characters in ASA files opened for text processing
(r, w, a, r+, w+, a+ functions). On input, z/OS XL C/C++ translates ASA
characters to sequences of control characters, as shown in Table 7. On output,
z/OS XL C/C++ performs the reverse translation. The following sequences of control
characters are translated, and the resultant ASA character becomes the first
character of the following record.
Table 7. C control to ASA characters translation table
C Control Character ASA Character Description
Sequence
\n '' skip one line
\n\n '0' skip two lines
\n\n\n '-' skip three lines
\f '1' new page
\r '+' overstrike
If you are writing to the first record or byte of the file and the output data does not
start with a translatable sequence of C control characters, the ' ' ASA control
character is written to the file before the specified data.
z/OS XL C/C++ does not translate or verify control characters when you open an
ASA file for binary or record I/O.
#include <stdio.h>
#define MAX_LEN 80
int main(void) {
FILE *fp;
int i;
char s[MAX_LEN+1];
return(0);
}
fp = fopen("asa.file", "r");
for (i = 0; i < 5; i++) {
fscanf(fp, "%s", s[0]);
printf("string = %s\n",s);
}
}
The program writes five records to the file asa.file, as follows. Note that the last
record is 9034. The last single '\n' does not create a record with a single control
character (' '). If this same file is opened for read, and the getc() function is called
to read the file 1 byte at a time, the same characters as those that were written out
by fputs() in the first program are read.
0abcdef
1
+345
-
9034
\n\n\nHELLO WORLD
x = ftell()
If you then update the ASA character to a form feed ('\f'), the logical ASA
position x no longer exists:
\fHELLO WORLD
If you call fseek() with the logical position x, it repositions to the next valid
character, which is the letter 'H':
\fHELLO WORLD
fseek() to pos x
v If you try to shorten a record when you are updating it, z/OS XL C/C++ adds
enough blank padding to fill the record.
v The ASA character can represent up to three new-lines, which can increase the
logical record length by 1 or 2 bytes.
v Extending a fixed logical record on update implies that the logical end of the line
follows the last written non-blank character.
Note: Be careful when you update an ASA file with data containing more than
one consecutive new-line: the result of the update depends on how the original
ASA records were structured.
v If you are writing data to a non-blocked file without intervening flush or reposition
requests, each record is written to the system on completion (that is, when a
'\n', '\r' or '\f' character is written or when the file is closed).
If you are writing data to a blocked file without intervening flush or reposition
requests, and the file is opened in full buffering mode, the block is written to the
system on completion of the record that fills the block. If the blocked file is line
buffered, each record is written to the system on completion.
If you are writing data to a spanned file without intervening flush or reposition
requests, and the record spans multiple blocks, each block is written to the
system once it is full and the user writes an additional byte of data.
v If a flush occurs while an ASA character indicating more than one new-line is
being updated, the remaining new-lines will be discarded and a read will continue
at the first data character. For example, if '\n\n\n' is updated to be '\n\n' and
a flush occurs, then a '0' will be written out in the ASA character position.
Note: The z/OS XL C++ compiler does not have native support for multibyte
characters. The support described here is what z/OS XL C provides; for C++, you
can take advantage of this support by using interlanguage calls to C code. Please
refer to Chapter 19, Using Linkage Specifications in C or C++, on page 237 for
more information.
If the sequence of bytes ends with the shift-in character, the state remains initial,
making this sequence represent a 4-byte multibyte character. Multibyte characters
of various lengths can be normalized by the set of z/OS XL C library functions and
encoded in units of one length. Such normalized characters are called wide
characters; in z/OS XL C they are represented by two bytes. Conversions between
multibyte format and wide character format can be performed by string conversion
functions such as wcstombs(), mbstowcs(), wcsrtombs(), and mbsrtowcs(), as well
by the family of the wide character I/O functions. MB_CUR_MAX is defined in the
stdlib.h header file. Depending on its value, either of the following happens:
v When MB_CUR_MAX is 1, all bytes are considered single-byte characters; shift-out
and shift-in characters are treated as data as well.
v When MB_CUR_MAX is 4:
On input, the wide character I/O functions read the multibyte character from
the streams, and convert them to the wide characters.
On output, they convert wide characters to multibyte characters and write
them to the output streams.
Both binary and text streams have orientation. Streams opened with type=record
do not. There are three possible orientations of a stream:
Non-oriented
A stream that has been associated with an open file before any I/O
operation is performed. The first I/O operation on a non-oriented stream will
set the orientation of the stream. The fwide() function may be used to set
the orientation of a stream before any I/O operation is performed. You can
use the setbuf() and setvbuf() functions only when I/O has not yet been
performed on a stream. When you use these functions, the orientation of
Once you have established a stream's orientation, the only way to change it is to
make a successful call to the freopen() function, which removes a stream's
orientation.
The wchar.h header file declares the WEOF macro and the functions that support
wide character input and output. The macro expands to a constant expression of
type wint_t. Certain functions return WEOF type when the end-of-file is reached on
the stream.
Note: The behavior of the wide character I/O functions is affected by the LC_CTYPE
category of the current locale, and the setting of MB_CUR_MAX. Wide-character input
and output should be performed under the same LC_CTYPE setting. If you change
the setting between when you read from a file and when you write to it, or vice
versa, you may get undefined behavior. If you change it back to the original setting,
however, you will get the behavior that is documented. See the introduction of this
chapter for a discussion of the effects of MB_CUR_MAX.
Opening files
You can use the fopen() or freopen() library functions to open I/O files that contain
multibyte characters. You do not need to specify any special parameters on these
functions for wide character I/O.
For a detailed description of unformatted and formatted I/O functions, see z/OS XL
C/C++ Run-Time Library Reference.
The wide-character input/output functions maintain global shift state for multibyte
character streams they read or write. For each multibyte character they read,
wide-character input functions change global shift state as the mbrtowc() function
would do. Similarly, for each multibyte character they write, wide-character output
functions change global shift state as the wcrtomb() function would do.
When you are using wide-oriented input functions, multibyte characters are
converted to wide characters according to the current shift state. Invalid double-byte
character sequences cause conversion errors on input. As z/OS XL C uses
wide-oriented functions to read a stream, it updates the shift state when it
encounters shift-out and shift-in characters. Wide-oriented functions always read
complete multibyte characters. Byte-oriented functions do not check for complete
multibyte characters, nor do they maintain information about the shift state.
Therefore, they should not be used to read multibyte streams.
For binary streams, no validation is performed to ensure that records start or end in
initial shift state. For text streams, however, all records must start and end in initial
shift state.
All other output functions do not support the wchar_t data type. However, all of the
output functions support multibyte character output for text streams if MB_CUR_MAX is
4.
For a detailed description of unformatted and formatted I/O functions, see z/OS XL
C/C++ Run-Time Library Reference.
Control characters written before the shift-in are treated as multibyte data and are
not interpreted or validated.
When you close the file, z/OS XL C ensures that the file ends in initial shift state.
This may require adding a shift-in and possibly a padding character to complete the
last multibyte character, if it is not already complete. If padding is needed in this
case, z/OS XL C does not raise SIGIOERR.
Multibyte characters are never split across record boundaries. In addition, all
records end and start in initial shift state. When a shift-out is written to the file,
either directly or indirectly by wide-oriented functions, z/OS XL C calculates the
maximum number of complete multibyte characters that can be contained in the
record with the accompanying shift-in. If multibyte output (including any required
shift-out and shift-in characters) does not fit within the current record, the behavior
depends on what type of file it is (a memory file has no record boundaries and so
never has this particular problem). For a standard stream or terminal file, data is
wrapped from one record to the next. Shift characters may be added to ensure that
the first record ends in initial shift state and that the second record starts in the
required shift state.
For files that are not standard streams, terminal files, or memory files, any attempt
to write data that does not fit into the current record results in data truncation. In
such a case, the output function returns an error code, raises SIGIOERR, and sets
errno and the error flag. Truncation continues until initial state is reached and a
new-line is written to the file. An entire multibyte stream may be truncated, including
the shift-out and shift-in, if there are not at least two bytes in the record. For a
wide-oriented stream, truncation stops when a wchar_t new-line character is written
out.
Byte-oriented output functions do not interpret binary data. If you use them for
writing multibyte data, ensure that your data is correct and ends in initial shift state.
If you update a record after you call fgetpos(), the shift state may change. Using
the fpos_t value with the fsetpos() function may cause the shift state to be set
incorrectly.
Flushing buffers
You can use the library function fflush() to flush streams to the system. For more
information about fflush(), see the z/OS XL C/C++ Run-Time Library Reference.
The action taken by the fflush() library function depends on the buffering mode
associated with the stream and the type of stream. If you call one z/OS XL C
program from another z/OS XL C program by using the ANSI system() function, all
open streams are flushed before control is passed to the callee. A call to the POSIX
system() function does not flush any streams to the system. For a POSIX system
call, we recommend that you do a fflush() before the system call.
Calling fflush() has no effect on the current record when you are writing new data
to a wide-oriented or byte-oriented multibyte stream, because the record is
incomplete.
ungetwc() considerations
ungetwc() pushes wide characters back onto the input stream for binary and text
files. You can use it to push one wide character onto the ungetwc() buffer. Never
use ungetc() on a wide-oriented file. After you call ungetwc(), calling fflush()
backs up the file position by one wide character and clears the pushed-back wide
character from the stream. Backing up by one wide character skips over shift
characters and backs up to the start of the previous character (whether single-byte
or double-byte). For text files, z/OS XL C counts the new-lines added to the records
as single-byte characters when it calculates the file position. For example, if you
have the following stream,
A B SO X'FE' X'7F' SI C
fp
You can set the _EDC_COMPAT environment variable before you open the file, so that
fflush() ignores any character pushed back with ungetwc() or ungetc(), and leaves
the file position where it was when ungetwc() or ungetc() was first issued. Any
characters pushed back are still cleared. For more information about _EDC_COMPAT,
see Chapter 32, Using environment variables, on page 467.
Use the fseek() or fsetpos() functions to reposition only to the start of a multibyte
character. If you reposition to the middle of a multibyte character, undefined
behavior can occur.
When you use the fsetpos() function to reposition within a file, the shift state is set
to the state saved by the function. Use this function to reposition to a wide
character that is not in the initial state.
ungetwc() considerations
For text files, the library functions fgetpos() and ftell() take into account the
character you have pushed back onto the input stream with ungetwc(), and move
the file position back by one wide character. The starting position for an fseek() call
with a whence value of SEEK_CUR also takes into account this pushed-back wide
character. Backing up one wide character means backing up either a single-byte
character or a multibyte character, depending on the type of the preceding
character. The implicit new-lines at the end of each record are counted as wide
characters.
For binary files, the library functions fgetpos() and ftell() also take into account
the character you have pushed back onto the input stream with ungetwc(), and
adjust the file position accordingly. However, the ungetwc() must push back the
same type of character just read by fgetwc(), so that ftell() and fgetpos() can
save the state correctly. An fseek() with an offset of SEEK_CUR also accounts for
the pushed-back character. Again, the ungetwc() must unget the same type of
character for this to work properly. If the ungetwc() pushes back a character in the
opposite state, you will get undefined behavior.
You can make only one call to ungetwc(). If the current logical file position is
already at or before the first wchar in the file, a call to ftell() or fgetpos() after
ungetwc() fails.
When you are using fseek() with a whence value of SEEK_CUR, the starting point
for the reposition also accounts for the presence of ungetwc() characters and
compensates as ftell() and fgetpos() do. Specifying a relative offset other than 0
is not supported and results in undefined behavior.
Closing files
z/OS XL C expects files to end in initial shift state. For binary byte-oriented files,
you must ensure that the ending state of the file is initial state. Failure to do so
results in undefined behavior if you reaccess the file again. For wide-oriented
streams and byte-oriented text streams, z/OS XL C tracks new data that you add. If
necessary, z/OS XL C adds a padding byte to complete any incomplete multibyte
character and a shift-in to end the file in initial state.
By default, the standard streams are opened implicitly the first time they are
referenced. You do not have to declare them or call their open() member functions
to open them. For example, with no preceding declaration or open() call, the
following statement writes the decimal number n to the cout stream.
cout << n << endl;
For more detailed information about C++ I/O streaming, see the following:
v z/OS XL C/C++ Run-Time Library Reference discusses the C I/O stream
functions
v Standard C++ Library Reference discusses the Standard C++ I/O stream classes
Table 9. Standard C and C++ streams
Stream Purpose Functions that use it
name
C standard streams and their related functions
stdin The input device from which your C program usually getchar()
retrieves its data. getchar_unlocked()
gets()
gets_unlocked()
scanf()
scanf_unlocked()
vscanf()
vscanf_unlocked()
wscanf()
wscanf_unlocked()
vwscanf()
vwscanf_unlocked()
stdout The output device to which your C program normally printf()
directs its output. printf_unlocked()
puts()
puts_unlocked()
putchar()
putchar_unlocked()
vprintf()
vprintf_unlocked()
wprintf()
wprintf_unlocked()
vwprintf()
vwprintf_unlocked()
stderr The output device to which your C program directs perror()
its diagnostic messages. z/OS XL C/C++ uses perror_unlocked()
stderr to collect error messages about exceptions
that occur.
C++ standard streams and the operators typically used with them
Stream Purpose Common usage
name
On I/O operations requiring a file pointer, you can use stdin, stdout, or stderr in
the same manner as you would any other file pointer.
If you are running with POSIX(ON), standard streams are opened during initialization
of the process, before the application receives control. With POSIX(OFF), the default
behavior is for the C standard streams to open automatically on first reference. You
do not have to call fopen() to open them. For example, if the following statement is
specified without a preceding fopen() statement, it writes the decimal number n to
the stdout stream.
printf("%d\n",n);
By default, stdin interprets the character sequence /* as indicating that the end of
the file has been reached. See Chapter 13, Performing terminal I/O operations, on
page 189 for more information.
Where the streams go depends on what kind of environment you are running under.
These are the defaults:
v Under interactive TSO, all three standard streams go to the terminal.
v Under MVS batch, TSO batch, and IMS (batch and interactive):
stdin goes to dd:sysin. If dd:sysin does not exist, all read operations from
stdin will fail.
stdout goes first to dd:sysprint. If dd:sysprint does not exist, stdout looks
for dd:systerm and then dd:syserr. If neither of these files exists, z/OS XL
C/C++ opens a sysout=* data set and sends the stdout stream to it.
stderr will go to the z/OS Language Environment message file. In AMODE 64
applications, stderr goes to dd:sysout.
Note: When a standard stream is allocated to a large format sequential data set,
the stream will be opened without repositioning (noseek). In this situation, the
open is initially attempted with repositioning (seek), fails with an ABEND 213-14
You can also redirect the standard streams to other files. See Redirecting standard
streams and sections following.
//
// Example of interleaving USL I/O with sync_with_stdio()
//
// tsyncws.cxx
#include <stdio.h>
#include <fstream.h>
int main() {
ios::sync_with_stdio();
cout << "object: to show that sync_with_stdio() allows interleaving\n "
" standard input and output on a per character basis\n" << endl;
int main() {
cout << "object: to illustrate interleaving input and output\n "
" without sync_with_stdio()\n" << endl;
cin.getline(string1, 80);
rc = gets(string2);
cin.getline(string3, 80);
Note that, C++ standard streams are implemented in terms of C standard streams.
Therefore, cin, cout, cerr, and clog are implicitly redirected when the
corresponding C standard streams are redirected. These streams can be redirected
by assignment, as described in Assigning the standard streams on page 68. If
freopen() is applied to a C standard stream, creating a binary stream or one with
"type=record", then behavior of the related stream is undefined.
Note: If you specify a redirection in a system() call, after system() returns, the
streams are redirected back to those at the time of the system() call.
Notes:
1. If you use the NOREDIR option on a #pragma runopts directive, or the
NOREDIR compile-time option, you cannot redirect standard streams on the
command line using the preceding list of symbols.
2. If you want to pass one of the redirection symbols as an argument, you can
enclose it in double quotation marks. For example, the following passes the
string "here are the args including a <" to prog and redirects stdout to
redir1 output a.
prog "here are args including a <" >"redir1 output a"
3. TSO (batch and online) and MVS batch support command line arguments. CICS
and IMS do not.
4. When two options specifying redirection conflict with each other, or when you
redirect a standard stream more than once, the redirection fails. If you do the
latter, you will get an abend. For example, if you specify
2>&1
and then
1>&2
z/OS XL C/C++ uses the first redirection and ignores any subsequent ones. If
you specify
>a.out
and then
1>&2
the redirection fails and the program abends.
5. A failed attempt to redirect a standard stream causes your program to fail in
initialization.
You must ensure that the streams are appropriate; for example, do not assign a
stream opened for w to stdin. Doing so would cause a function such as getchar()
called for the stream to fail, because getchar() expects a stream to be opened for
read access.
Again, you must ensure that the assigned stream is appropriate; for example, do
not assign an fstream opened for ios::out only to cin. This will cause a
subsequent read operation to fail.
You can redirect stderr by specifying a ddname on the MSGFILE run-time option and
not redirecting stderr elsewhere (such as on the command line). The default
ddname for the z/OS Language Environment MSGFILE is SYSOUT. See z/OS
Language Environment Programming Guide for more information on MSGFILE.
MSGFILE considerations
z/OS XL C/C++ makes a distinction between types of error output according to
whether the output is directed to the MSGFILE, to stderr, or to stdout:
Table 11. Output destinations under z/OS XL C/C++
Destination of Type of Message Produced by Default Destination
Output
MSGFILE output z/OS Language z/OS Language MSGFILE ddname
Environment Environment
messages (CEExxxx) conditions
z/OS XL C/C++ z/OS XL C/C++ MSGFILE ddname
language messages unhandled conditions
(EDCxxxx)
Notes:
1. When you are using one of the z/OS UNIX shells, stderr will go to file descriptor 2,
which is typically the terminal. See Chapter 16, Language Environment Message file
operations, on page 215 for more information about z/OS Language Environment
message files.
2. When you are using one of the z/OS UNIX shells, stdout will go to file descriptor 1,
which is typically the terminal.
All stderr output is by default sent to the MSGFILE destination, while stdout output
is sent to its own destination. When stderr is redirected to stdout, both share the
stdout destination. When stdout is redirected to stderr, both share the stderr
destination.
If you specified one of the DDs used in the stdout open search order as the DD for
the MSGFILE option, then that DD will be ignored in the stdout open search.
Table 12 describes the destination of output to stderr and stdout after redirection
has occurred. Whenever stdout and stderr share a common destination, the
output is interleaved. The default case is the one where stdout and stderr have
not been redirected.
Table 12. z/OS XL C/C++ Interleaved output
stderr not stderr redirected to stderr redirected to
redirected destination other stdout
than stdout
stdout not stdout to itself stderr stdout to itself stderr Both to stdout
redirected to MSGFILE to its other destination
stdout redirected to stdout to its other stdout to its other Both to the new
destination other destination stderr to destination stderr to stdout destination
than stderr MSGFILE its other destination
stdout redirected to Both to MSGFILE Both to the new stdout to stderr
stderr stderr destination stderr to stdout
Because the topic of JCL statements goes beyond the scope of this book, only
simple examples will be shown here.
Suppose you have a program called BATCHPGM, with 1 required parameter DEBUG.
The output from BATCHPGM is to be directed to a sequential data set called
MAINT.LOG.LISTING. You can use the following JCL statements:
//JOBname JOB...
. //STEP01 EXEC PGM=BATCHPGM,PARM=DEBUG >MAINT.LOG.LISTING
.
.
The following JCL redirects output to an unqualified data set using the same
program name, parameter and output data set as the example above:
Figure 8 shows excerpt from an MVS example job stream that demonstrates the
redirection of the three standard streams by using ddnames. In the example, your
program name is MONITOR and the input to MONITOR is to be retrieved from a
sequential data set called SAFETY.CHEM.LIST. The output of MONITOR is to be
directed to a partitioned data set member called YEAREND.ACTION(CHEM), and any
errors generated by MONITOR are to be written to a sequential data set called
YEAREND.MONITOR.ERRLIST. To redirect the standard streams using DD statements,
you could use the JCL statements shown in Figure 8.
//JOBname JOB...
. //STEP01 EXEC PGM=MONITOR,PARM=MSGFILE(SYSERR)/
.
.
//SYSIN DD DSN=SAFETY.CHEM.LIST,DISP=OLD
//SYSERR DD DSN=YEAREND.MONITOR.ERRLIST,DISP=MOD
. //SYSPRINT DD DSN=YEAREND.ACTION(CHEM),DISP=OLD
.
.
//JOBname JOB...
//STEP01 EXEC PGM=HOCKEY,PARM=/ 2>&1
//SYSIN DD DSN=HOCKEY.PLAYER.LIST,DISP=SHR
//SYSPRINT DD DSN=HOCKEY.OUTPUT,DISP=(OLD),DCB=...
Figure 9. Example of using stdout and stderr to share the same file
If you want to redirect to a UNIX file system file, you can modify the above
examples to use the PATH and PATHOPT options described in DDnames on page 34.
Under TSO
You can redirect standard streams in the following ways:
v From the freopen() library function call
v From the command line
v Using the parameter list in a CALL command
Under IMS
Under IMS online and batch, you can redirect the C standard streams in any of the
following ways:
v with direct assignment
v with the freopen() function
v with ddnames
Under CICS
There are several ways to redirect C standard streams under CICS:
v You can assign a memory file to the stream (for example, stdout=myfile).
v You can use freopen() to open a standard stream as a memory file.
v You can use CICS facilities to direct where the stream output goes.
If you assign a file pointer to a stream or use freopen() on it, you will not be able
to use C functions to direct the information outside or elsewhere in the CICS
environment. Once access to a CICS transient data queue has been removed,
either by a call to freopen() or fclose(), or by the assignment of another file
pointer to the stream, z/OS XL C/C++ does not provide a way to regain access.
Once C functions have lost access to the transient data queues, you must use the
CICS-provided facilities to regain it.
CICS provides a facility that enables you to direct where a given transient data
queue, the default standard stream implementation, will go, but you must configure
this facility before a CICS cold start.
A system() call occurs when one z/OS XL C/C++ program calls another z/OS XL
C/C++ program by using the ANSI system() function, which z/OS XL C/C++ uses if
you are not running with POSIX(ON). Standard streams are inherited across calls to
the ANSI system() function. With a POSIX system() function, file descriptors 0, 1,
and 2 will be mapped to standard streams stdin, stdout and stderr in the child
process. The behavior of these streams is similar to binary streams called with the
ANSI system() function.
Inheritance includes any redirection of the stream as well as the open mode of the
stream. For example, if program A reopens stdout as "A.B" for "wb" and then calls
program B, program B inherits the definition of stdout. If program B reopens stdout
as "C.D" for "ab" and then uses system() to call program C, program C inherits
stdout opened to "C.D" for append. Once control returns to the calling program, the
definitions of the standard streams from the time of the system() call are restored.
For example, when program B finally returns control to program A, stdout is
restored to "A.B" opened for "wb".
The file position and the amount of data that is visible in the called and calling
programs depend on whether the standard streams are opened for binary, text, or
record I/O.
The behavior of the C standard streams across a system() call indicates the
behavior of all standard streams since they are implemented in terms of the C
standard streams.
Memory files are always opened in binary mode, even if you specify text. Any
standard streams redirected to memory files and passed across system() calls will
be treated as binary files. UNIX file system files are also treated as binary files,
because they do not contain any real record boundaries. Memory files are not
passed across calls to the POSIX system() function.
OUTPUT
------
no ---> from the child
ab01 ---> from root
When you write to a spanned file, the file position moves to the beginning of the
next record, if that record exists. If not, the position moves to the end of the
incomplete record.
For non-spanned standard streams opened for output, if the caller has created a
text record missing an ending control character, the last record is hidden from the
called program. The called program can append new data if the stream is open in
append mode. Any appends made by the called program will be after the last
record that was complete at the time of the system() call.
When the called program terminates, it completes any new unfinished text record
with a new-line; the addition of the new-line does not move the file position. Once
When control returns to the original caller, any incomplete record hidden at the time
of the system() call is restored to the end of the file. If the called program is at EOF
when it is terminated and the caller was within an incomplete record at the time of
the system() call, the position upon return is restored to the original record offset at
the time of the system() call. This position is usually the end of the incomplete
record. Generally, if the caller is writing to a standard stream and does not complete
the last record before it calls system(), writes continue to add to the last record
when control returns to the caller. For example:
printf("test");
printf("abc");
system("hello"); ------> int main(void) { printf("hello world\n");}
printf("def\n");
If stdout had been opened for "w+" in this example, and a reposition had been
made to the character b before the system() call, upon return, the incomplete
record "abc" would have been restored and the position would have been at the
b. The subsequent write of def would have performed an update to give test
hello world adef.
Input with sync_with_stdio(): When cin is open in text mode (the default), and
sync_with_stdio() has been called, the input across a system() call behaves the
same as stdin:
v The child program begins reading at the next record boundary, that is, unread
data in the current record in the parent is hidden.
v When the child program returns, the parent program begins reading at the next
record boundary, that is, unread data in the current record in the child is lost.
In the example shown in Figure 11, stdout is a variable-length record I/O file.
fwrite("test",1,4,stdout);
fwrite("abc",1,3,stdout);
system("hello"); ------> int main(void) {
fwrite("def",1,3,stdout); fwrite("hello world",1,11,stdout)
}
In the default inheritance model, the behavior of C standard streams is such that a
child main() function cannot affect the standard streams of the parent. The child
can use the parent's definition or redirect a standard stream to a new location, but
when control returns to the parent, the standard stream reverts back to the
definition of the parent. In the global model, the C standard streams, stdin, stdout,
and stderr, can be redirected to a different location while running in a child main()
function and have that redirection stay in effect when control returns to the parent.
You can use the _EDC_GLOBAL_STREAMS environment variable to set standard
stream behavior to the global model. For more information, see
_EDC_GLOBAL_STREAMS on page 492.
Notes:
1. The following environments do not allow global standard stream behavior as an
option:
v POSIX(ON)
v CICS
v SPC
v AMODE 64
2. You must identify the behavior of the standard streams to the C run-time library
before initialization of the first C main in the environment. The default behavior
The most important difference is that when redirection is done at system() call time,
the redirection takes effect for the entire C environment. When the child program
terminates, the standard stream definitions do not revert back to what they were
before the system() call.
Redirecting stderr to stdout, or stdout to stderr, does not flush the redirected
stream. Any data in the buffer remains there until the stream is redirected again, to
something other than stdout or stderr. Only then is the buffer flushed.
#include <stdio.h>
#include <stdlib.h>
main() {
int rc;
printf("line 1\n");
printf("line 2");
fprintf(stderr,"line 3\n");
fprintf(stderr,"line 4");
rc=system("PGM=CHILD,PARM=/ >stdout.file 2>&1;")
printf("line 5\n");
fprintf(stderr,"line 6\n");
}
CHILD.C
#include <stdio.h>
main() {
printf("line 7\n");
fprintf(stderr,"line 8\n");
stderr = freopen("stderr.file","w",stderr);
printf("line 9\n");
fprintf(stderr,"line 10\n");
}
Attention: If the stdout or stderr stream has data in its buffer and it is redirected
to stderr or stdout, then the data is lost if stdout or stderr is not redirected again.
Note: If either stdout or stderr is using global behavior, but not both, then any
redirection of stdout or stderr to stderr or stdout is ignored.
Direct assignment
You can directly assign the C standard streams in any main program. This
assignment does not have any effect on the global standard stream. No flush is
done and the new definition is not passed on to a child program nor back to a
parent program. Once you directly assign a standard stream, there is no way to
re-associate it with the global standard stream.
freopen()
When you use freopen() to redirect a standard stream, the stream is closed,
causing a flush, and then redirected. The new definition affects all C mains currently
using the global stream.
fclose()
When a global standard stream is closed, only direct assignment can be used to
begin using the standard stream again. That use would only be for the main
performing the direct assignment. There is no way to get back global behavior for
the standard stream that was closed.
OS I/O supports text, binary, and record I/O, in three record formats: fixed (F),
variable (V), and undefined (U). For information about using wide-character I/O with
z/OS XL C/C++, see Chapter 8, z/OS XL C Support for the double-byte character
set, on page 51.
This topic describes C I/O stream functions as they can be used within C++
programs. If you want to use the C++ I/O stream classes instead, see Chapter 4,
Using the Standard C++ Library I/O Stream Classes, on page 21 for general
information. For more detailed information, see Standard C++ Library Reference,
which discusses the Standard C++ I/O stream classes
Opening files
To open an OS file, you can use the Standard C functions fopen() or freopen().
These are described in general terms in z/OS XL C/C++ Run-Time Library
Reference. Details about them specific to all z/OS XL C/C++ I/O are discussed in
the "Opening Files" section. This section describes considerations for using fopen()
and freopen() with OS files.
qualifier
// ' ( member ) '
+ number
0
& qualifier
&&
Note: The single quotation marks in the filename syntax diagram must be matched;
if you use one, you must use the other.
qualifier1.qualifier2(member)
fp = fopen("//&&myfile","wb+");
fp2 = fopen("//&&myfile","wb+");
The Resource Access Control Facility (RACF) expects the data set name to have
a high-level qualifier that is defined to RACF. RACF uses the entire data set name
when it protects a tape data set.
When you enclose a name in single quotation marks, the name is fully qualified.
The file opened is the one specified by the name inside the quotation marks. If the
name is not fully qualified, z/OS XL C/C++ does one of the following:
v If your system does not use RACF, z/OS XL C/C++ does not add a high-level
qualifier to the name you specified.
v If you are running under TSO (batch or interactive), z/OS XL C/C++ appends the
TSO user prefix to the front of the name. For example, the statement
fopen("a.b","w"); opens a data set tsoid.A.B, where tsoid is the user prefix. If
the name is fully qualified, z/OS XL C/C++ does not append a user prefix. You
can set the user prefix by using the TSO PROFILE command with the PREFIX
parameter.
v If you are running under z/OS batch or IMS (batch or online), z/OS XL C/C++
appends the RACF user ID to the front of the name.
If you want your code to be portable between the VM/CMS and z/OS systems and
between memory files and disk files, use a name of the format name1.name2, where
name1 and name2 are up to 8 characters and are delimited by a period, or use a
ddname. You can also add a member name.
For example, the following piece of code can run under Language Environment for
VM and z/OS Language Environment:
FILE *stream;
stream = fopen("parts.instock", "r");
Using a DDname
The DD statement enables you to write C or C++ source programs that are
independent of the files and input/output devices they use. You can modify the
parameters of a file or process different files without recompiling your program.
To open a file by ddname under z/OS batch, you must define the ddname first. You
can do this in any of the following ways:
v In batch (z/OS, TSO, or IMS), you can write a JCL DD statement. For the
declaration shown above for the C or C++ file PARTS.INSTOCK, you write a JCL
DD statement similar to the following:
//STOCK DD DSN=USERID.PARTS.INSTOCK,DISP=SHR
When defining DD, do not use DD ... FREE=CLOSE for unallocating DD
statements. The C library may close files to perform some file operations such as
freopen(), and the DD statement will be unallocated.
If you use SPACE=RLSE on a DD statement, z/OS XL C/C++ releases space only if
all of the following are true:
The file is open in w, wb, a, or ab mode
It is not simultaneously open for read
No positioning functions (fseek(), ftell(), rewind(), fgetpos(), fsetpos())
have been performed.
For more information on writing DD statements, refer to the job control language
(JCL) manuals listed in z/OS Information Roadmap.
v Under TSO (interactive and batch), you can issue an ALLOCATE command. The
DD definition shown above for the C file STOCK has an equivalent TSO ALLOCATE
command, as follows:
ALLOCATE FILE(STOCK) DATASET(PARTS.INSTOCK) SHR
See z/OS Information Roadmap for manuals containing information on TSO
ALLOCATE.
v In the z/OS environment, you can use the svc99() or dynalloc() library functions
to define ddnames. For information about these functions, refer to z/OS XL
C/C++ Run-Time Library Reference.
DCB parameter: The DCB (data control block) parameter of the DD statement
allows you to describe the characteristics of the data in a file and the way it will be
processed at run time. The other parameters of the DD statement deal chiefly with
the identity, location, and disposition of the file. The DCB parameter specifies
information required for the processing of the records themselves. The
subparameters of the DCB parameter are described in z/OS MVS JCL User's Guide.
You cannot use the DCB parameter to override information already established for
the file in your C or C++ program (by the file attributes declared and the other
attributes that are implied by them). DCB subparameters that attempt to change
information already supplied by fopen() or freopen() are ignored. An example of
the DCB parameter is:
DCB=(RECFM=FB,BLKSIZE=400,LRECL=40)
If you want to open a generation data set by data set name with fopen() or
freopen(), you will require a model. This model specifies parameters for the group,
including the maximum number of generations (the generation index). You can
define such a model by using the Access Method Services DEFINE command. For
more information on the DEFINE command, see z/OS DFSMS Access Method
Services for Catalogs. Note also that fopen() does not support a DCB= parameter. If
you want to change the parameters, alter the JCL that describes the model and
open it in w mode.
z/OS uses an absolute generation and version number to catalog each generation.
The generation and version numbers are in the form GxxxxVyy, where xxxx is an
unsigned 4-digit decimal generation number (0001 through 9999) and yy is an
unsigned 2-digit decimal version number (00 through 99). For example:
v A.B.C.G0001V00 is generation data set 1, version 0, in generation data group
A.B.C.
v A.B.C.G0009V01 is generation data set 9, version 1, in generation data group
A.B.C.
The number of generations kept depends on the size of the generation index.
When you open a GDG by relative number, z/OS XL C/C++ returns the relative
generation in the __dsname field of the structure returned by the fldata() function.
You cannot use the rename() library function to rename GDGs by relative
generation number; rename GDG data sets by using their absolute names.
The example shown in Figure 13 on page 86 is valid only for C. The sample
program (CCNGOS1) defines a GDG. The fopen() fails because it tries to change
the RECFM of the data set.
fp = fopen("MYGDG(+1)", "a,recfm=F");
if (fp == NULL)
{
printf("Error...Unable to open file\n");
printf("errno ... %d\n",errno);
perror("perror ... ");
}
printf("Finished\n");
}
/>
fp = fopen("MYGDG(+1)", "a,recfm=F");
if (fp == NULL)
{
printf("Error...Unable to open file\n");
printf("errno ... %d\n",errno);
perror("perror ... ");
}
printf("Finished\n");
}
A relative number used in the JCL refers to the same generation throughout a job.
The (+1) used in the example above exists for the life of the entire job and not just
the step, so that fopen()'s reference to (+1) did not create another new data set
but accessed the same data set as in previous steps.
Note: You cannot use fopen() to create another generation data set because
fopen() does not fully support the DCB parameter.
You specify a member by enclosing its name in parentheses and placing it after the
data set name. For example, the following JCL refers to member A of the data set
MY.DATA:
//MYDD DD DSN=userid.MY.DATA(A),DISP=SHR
You can specify members on calls to fopen() and freopen(). You can specify
members when you are opening a data set by its data set name or by a ddname.
When you use a ddname and a member name, the definition of the ddname must
not also specify a member. For example, using the DD statement above, the
following will fail:
fp = fopen("dd:MYDD(B)","r");
You cannot open a PDS or PDSE member using the modes a, ab, a+, a+b, w+, w+b,
or wb+. If you want to perform the equivalent of the w+ or wb+ mode, you must first
open the file as w or wb, write to it, and then close it. Then you can perform updates
by reopening the file in r+ or rb+ mode. You can use the C library functions ftell()
or fgetpos() to obtain file positions for later updates to the member. Normally,
opening a file in r+ or rb+ mode enables you to extend a file by writing to the end;
however, with these modes you cannot extend a member. To do so, you must copy
the contents of the old member plus any extensions to a new member. You can
remove the old member by using the remove() function and then rename the new
member to the old name by using rename().
All members have identical attributes for RECFM, LRECL, and BLKSIZE. For PDSs,
you cannot add a member with different attributes or specify a RECFM of FBS, FBSA,
or FBSM. z/OS XL C/C++ verifies any attributes you specify.
For PDSEs, z/OS XL C/C++ checks to make sure that any attributes you specify
are compatible with those of the existing data set. Compatible attributes are those
that specify the same record format (F, V, or U) and the same LRECL. Compatibility
of attributes enables you to choose whether to specify blocked or unblocked format,
because PDSEs reblock all the records. For example, you can create a PDSE as FB
LRECL=40 BLKSIZE=80, and later open it for read as FB LRECL=40 BLKSIZE=1600 or F
At the start of each partitioned data set is its directory, a series of records that
contain the member names and starting locations for each member within the data
set. You can access the directory by specifying the PDS or PDSE name without
specifying a member. You can open the directory only for read; update and write
modes are not allowed. The only RECFM that you can specify for reading the
directory is RECFM=U. However, you do not need to specify the RECFM, because
z/OS XL C/C++ uses U as the default.
z/OS DFSMS Using Data Sets contains more detailed explanations about how to
use PDSs and PDSEs.
the first call to fopen() finds member C from PDS1, even though there is also a
member C in PDS2. The second call finds member D from PDS2, because PDS2 is the
first PDS in the concatenation that contains this member. The member C in PDS2 is
inaccessible.
When you are concatenating partitioned data sets, be aware of the DCB attributes
for them. The concatenation is treated as a single data set with the following
attributes:
v RECFM= the RECFM of the first data set in the concatenation
v LRECL= the LRECL of the first data set in the concatenation
v BLKSIZE= the largest BLKSIZE of any data set in the concatenation
If the first data set is in ASA format, all subsequent data sets must be ASA as well.
The preceding rules apply to ASA files if you add an A to the RECFMs specified.
If you do not follow these rules, undefined behavior occurs. For example, trying to
read a fixed-format member as RECFM=V could cause an exception or abend.
Repositioning is supported as it is for regular PDSs and PDSEs. If you try to read
the directory, you will be able to read only the first one.
//MYDD DD userid.PDS1(A),DISP=SHR
// DD userid.PDS2(E),DISP=SHR
// DD userid.DATA,DISP=SHR
creates a concatenation that contains two members and a regular sequential data
set. You can read or update all of these in order. In partitioned concatenations, you
can read only one member at a time.
z/OS XL C/C++ does not support concatenating data sets that do not have
compatible DCB attributes. The rules for compatibility are the same as those for
partitioned concatenations.
If all the data sets in the concatenation support repositioning, you can reposition
within a concatenation by using the functions fseek(), ftell(), fgetpos(),
fsetpos(), and rewind(). If the first one does not, all of the repositioning functions
except rewind() fail for the entire concatenation. If the first data set supports
repositioning but a subsequent one does not, you must specify the noseek
parameter on the fopen() or freopen() call. If you do not, fopen() or freopen()
opens the file successfully; however, an error occurs when the read position gets to
the data set that does not support repositioning.
Note: Concatenated and multivolume data sets only tolerate single buffering mode.
//MYDD DD *
record 1
record 2
record 3
/*
The // at the beginning of the data set starts in column 1. The statement
fopen("DD:MYDD","rb"); opens a data set with lrecl=80, blksize=80, and
recfm=FB. In this example, the delimiter indicating the end of the data set is /*. In
some cases, your data may contain this string. For example, if you are using C
source code that contains comments, z/OS XL C/C++ treats the beginning of the
first comment as the end of the in-stream data set. To avoid this occurrence, you
can change the delimiter by specifying DLM=nn, where nn is a two-character
delimiter, on the DD statement that identifies the file. For example:
//MYDD DD *,DLM=
#include <stdio.h>
/* Hello, world program */
int main() {printf("Hello, world\n"); }
@@
For more information about in-stream data sets, see z/OS MVS JCL User's Guide.
To open an in-stream data set, call the fopen() or freopen() library function and
specify the ddname of the data set. You can open an in-stream data set only for
reading. Specifying any of the update, write, or append modes fails. Once you have
opened an in-stream data set, you cannot acquire or change the file position except
by rewinding. This means that calls to the fseek(), ftell(), fgetpos(), and
fsetpos() for in-stream data sets fail. Calling rewind() causes z/OS XL C/C++ to
reopen the file, leaving the file position at the beginning.
You can concatenate regular sequential data sets and in-stream data sets. If you do
so, note the following:
v If the first data set is in-stream, you cannot acquire or change the file position for
the entire concatenation.
v If the first data set is not in-stream and supports repositioning, you must specify
the noseek parameter on the fopen() or freopen() call that opens the
concatenation. If you do not, fopen() or freopen() opens the file successfully;
however, an error occurs when the read position gets to the in-stream.
v The in-stream data set is treated as FB 80 and the concatenation rules for
sequential concatenation apply.
On a DD statement, you specify SYSOUT=x, where x is the output class. If the class
matches the JOB statement MSGCLASS, the output appears with the job log. You can
specify a SYSOUT data set and get the job MSGCLASS by specifying SYSOUT=*. If you
want to create a job stream within your program, you can specify INTRDR on the DD
statement. This sends your SYSOUT data set to the internal reader to be read as
an input job stream. For example,
//MYDD DD SYSOUT=(A,INTRDR)
For more details about the SYSOUT parameter, refer to z/OS MVS JCL User's
Guide.
You can specify DCB attributes for a SYSOUT data set on a DD statement or a call
to fopen() or freopen(). If you do not, z/OS XL C/C++ uses the following defaults:
Binary or Record I/O RECFM=VB LRECL=137 BLKSIZE=882
Text I/O RECFM=VBA LRECL=137 BLKSIZE=882
Tapes
z/OS XL C/C++ supports standard label (SL) tapes. If you are creating tape files,
you can only open them by ddname. z/OS XL C/C++ provides support for opening
tapes in read, write, or append mode, but not update. When you open a tape for
read or append, any data set control block (DCB) characteristics you specify must
match those of the existing data set exactly. The repositioning functions are
available only when you have opened a tape for read. For tapes opened for write or
append, calling rewind() has no effect; calls to any of the other repositioning
functions fail. To open a tape file for write, you must open it by ddname.
When you open a tape file for output, the data set name you specify in the JCL
must match the data set name specified in the tape label, even if the existing tape
file is empty. If this is not the case, you must either change the JCL to specify the
correct data set name or write to another tape file, or reinitialize the tape to remove
the tape label and the data. You can use IEBGENER with the following JCL to create
an empty tape file before passing it to the subsequent steps:
Note: For tapes, the value for UNIT= can be TAPE or CART.
The repositioning functions are available when you have opened a multivolume data
set for r,r+,rb,rb+,w+,wb+,a+,ab+. Repositioning multivolume data sets opened for
w,wb,a,ab is not allowed because it would be meaningless. For multivolume data
sets opened for write, calling rewind() has no effect; calls to any of the other
repositioning functions fail.
//MYDD DD DSNAME=TEST.TWO,DISP=(NEW,CATLG),
// VOLUME=(,,,3,SER=(333001,333002,333003)),
// SPACE=(TRK,(9,10)),UNIT=(3390,P)
This creates a data set that may span up to three volumes. For more information
about the VOLUME parameter on DD statements, refer to z/OS MVS JCL User's
Guide.
Notes:
1. Simultaneous readers (files that can support sharing by a writer and one or
more readers) are not supported for multivolume data sets.
2. Concatenated and multivolume data sets only tolerate single buffering mode.
Striped data sets also facilitate repositioning once the relative block number is
known. z/OS XL C/C++ exploits this capability when it uses fseek() to reposition.
This can result in substantial savings for applications that use ftell() and fseek()
with data sets that have RECFMs of V, U, and FB (not FBS). data sets. When a data
set is striped, an fseek() can seek directly to the specified block just as an
fsetpos() or rewind() can. For a normal data set with the aforementioned
RECFMs, z/OS XL C/C++ has to read forward or rewind the data set to get to the
desired position. Depending on how large the data set is, this can be quite
inefficient compared to a direct reposition. Note that for such data sets, striping
pads blocks to their maximum size. Therefore, you may be wasting space if you
have short records.
A large format sequential data set is specified using the DSNTYPE=LARGE keyword on
a JCL DD statement or using the dynamic allocation equivalent. z/OS XL C/C++
does not support the allocation of a large format sequential data set using fopen()
or freopen().
Other devices
z/OS XL C/C++ supports several other devices for input and output. You can open
these devices only by ddname. Table 17 lists a number of these devices and
describes which record formats are valid for them. None of the devices listed can
be opened for update except the DUMMY data set.
Table 17. Other devices supported for input and output
Device Valid open modes Repositioning? fldata()__device
Printer w, wb, a, ab No __PRINTER
Card reader r, rb rewind() only __OTHER
Card punch w, wb, a, ab No __OTHER
Optical reader r, rb rewind() only __OTHER
DUMMY data set r, rb, r+, rb+, r+b, w, rewind() only __DUMMY
wb, w+, wb+ w+b, a,
ab, a+, ab+, a+b
SUBSYS= r, rb No __OTHER
Note: For all devices above that support open modes a or ab, the modes are treated as if
you had specified w or wb.
z/OS XL C/C++ queries each device to find out its maximum BLKSIZE.
The DUMMY data set is not truly a device, although z/OS XL C/C++ treats it as one.
To use the DUMMY data set, specify DD DUMMY in your JCL. On input, the DUMMY data
set always returns EOF; on output, it is always successful. This is the way to specify
a DUMMY data set:
//MYDD DD DUMMY
For more information on DUMMY data sets, see z/OS MVS JCL User's Guide.
The following scenarios exist where QSAM (noseek) is requested, but the z/OS XL
C/C++ Run-Time Library switches to BSAM with NOTE and POINT macros requested
(seek):
v The data set is opened for update (r+, rb+, w+, wb+, a+, ab+)
v The data set is already opened for write (or update) in the same C process
v The data set is RECFM=FBS opened for append (a, ab, a+, ab+)
v The data set is LRECL=X
v The data set is the directory of a partitioned data set (PDS or PDSE)
v The data set is a member of a partitioned data set where the member was not
specified at allocation, but rather specified at fopen() or freopen()
Note: Repositioning is not allowed when noseek is requested, even if there was a
switch to seek.
recfm=
z/OS XL C/C++ allows you to specify any of the 27 possible RECFM types
(listed in Fixed-format records on page 10, Variable-format records on page
13, and Undefined-format records on page 16), as well as the z/OS XL C/C++
RECFMs * and A.
When you are opening an existing file for read or append (or for write, if you
have specified DISP=MOD), any RECFM that you specify must match that of the
existing file, except that you may specify recfm=U to open any file for read, and
you may specify recfm=FBS for a file created as recfm=FB. Specifying recfm=FBS
indicates to z/OS XL C/C++ that there are no short blocks within the file. If there
are, undefined behavior results.
For variable-format OS files, the RDW, SDW, and BDW contain the length of
the record, segment, and block as well as their own lengths. If you open a file
for read with recfm=U, z/OS XL C/C++ treats each physical block as an
undefined-format record. For files created with recfm=V, z/OS XL C/C++ does
not strip off block descriptor words (BDWs) or record descriptor words (RDWs),
and for blocked files, it does not deblock records. Using recfm=U is helpful for
viewing variable-format files or seeing how records are blocked in the file.
When you are opening an existing PDS or PDSE for write and you specify a
RECFM, it must be compatible with the RECFM of the existing data set. FS and
FBS formats are invalid for PDS members. For PDSs, you must use exactly the
same RECFM. For PDSEs, you may choose to change the blocked attribute (B),
because PDSEs perform their own blocking. If you want to read a PDS or
PDSE directory and you specify a RECFM, it must be recfm=U.
Specifying recfm=A indicates that the file contains ASA control characters. If you
are opening an existing file and you specify that ASA characters exist
(>recfm=A) when they do not, the call to fopen() or freopen() fails. If you create
a file by opening it for write or append, the A attribute is added to the default
RECFM. For more information about ASA, see Chapter 7, Using ASA text files,
on page 47.
Specifying recfm=* causes z/OS XL C/C++ to fill in any attributes that you do
not specify, taking the attributes from the existing data set. This is useful if you
want to create a new version of a data set with the same attributes as the
previous version. If you open a data set for write and the data set does not
exist, z/OS XL C/C++ uses the default attributes specified in fopen() defaults
on page 32. This parameter has no effect when you are opening for read or
append, and when you use it for non-DASD files.
recfm=+ is identical to recfm=* with the following exceptions:
v If there is no record format for the existing DASD data set, the defaults are
assigned as if the data set did not exist.
v When append mode is used, the fopen() fails.
96 z/OS V1R13.0 XL C/C++ Programming Guide
lrecl= and blksize=
The LRECL that you specify on the fopen() call defines the maximum record
length that the C library allows. Records longer than the maximum record length
are not written to the file. The first 4 bytes of each block and the first 4 bytes of
each record of variable-format files are used for control information. For more
information, see Variable-format records on page 13.
The maximum LRECL supported for fixed, undefined, or variable-blocked-
spanned format sequential disk files is 32760. For other variable-length format
disk files the maximum LRECL is 32756. Sequential disk files for any format
have a maximum BLKSIZE of 32760. The record length can be any size when
opening a spanned file and specifying lrecl=X. You can now specify lrecl=X on
the fopen() or freopen() call for spanned files. If you are updating an existing
file, the file must have been originally opened with lrecl=X for the open to
succeed. lrecl=X is useful only for text and record I/O.
When you are opening an existing file for read or append (or for write, if you
have specified DISP=MOD), any LRECL or BLKSIZE that you specify must match
that of the existing file, except when you open an F or FB format file on a disk
device without specifying the noseek parameter. In this case, you can specify
the S attribute to indicate to z/OS XL C/C++ that the file has no imbedded short
blocks. Files without short blocks improve z/OS XL C/C++'s performance.
BLKSIZE=0 will be ignored for an existing data set opened for read or append.
When you are opening an existing PDS or PDSE for write and you specify an
LRECL or BLKSIZE, it must be compatible with the LRECL or BLKSIZE of the
existing data set. For PDSs, you must use exactly the same values. For
PDSEs, the LRECL must be the same, but the BLKSIZE may be different if you
have changed the blocking attribute as described under the RECFM parameter
above. You can change the blocking attribute, because PDSEs perform their
own blocking. The BLKSIZE you choose should be compatible with the RECFM
and LRECL. When you open the directory of a PDS or PDSE, do not specify
LRECL or BLKSIZE; z/OS XL C/C++ uses the defaults. See Table 19 on page
102 for more information.
space=(units,(primary,secondary,directory) [rlse | norlse])
This keyword enables you to specify the space parameters for the allocation of
a z/OS data set. It applies only to z/OS data sets that you open by filename
and do not already exist. If you open a data set by ddname, this parameter has
no effect. You cannot specify any whitespace inside the value for the space
keyword. You must specify at least one value with this parameter. Any
parameter that you specify will be validated for syntax. If that validation fails,
then the fopen() or freopen() will fail even if the parameter would have been
ignored.
The supported values for units are as follows:
v Any positive integer indicating BLKSIZE
v CYL (mixed case)
v TRK (mixed case)
The primary quantity, the secondary quantity, and the directory quantity all must
be positive integers. The primary quantity is always required.
If you specify values only for units and primary, you do not have to specify the
inside set of parentheses. You can use a comma to indicate a quantity is to
take the default value. For example:
The last parameter, rlse or norlse , controls the disposition of the unused space.
If you open a new file for write and specify the space keyword, by default, any
unused space will be released when the file is closed. You can preserve the
allocated space by specifying norlse. For example:
You can specify only the values indicated on this parameter. If you specify any
other values, fopen() or freopen() fails. Any values not specified are omitted
on the allocation. These values are filled by the system during SVC 99
processing.
type=
You can omit this parameter. If you specify it, the only valid value for OS I/O is
type=record, which opens a file for record I/O.
acc=
This parameter is not valid for OS I/O. If you specify it, z/OS XL C/C++ ignores
it.
password=
This parameter is not valid for OS I/O. If you specify it, z/OS XL C/C++ ignores
it.
asis
If you use this parameter, z/OS XL C/C++ does not convert your filenames to
upper case. The use of the asis parameter is strongly discouraged, because
most of the I/O services used by z/OS XL C/C++ require uppercase filenames.
byteseek
When you specify this parameter and open a file in binary mode, all
repositioning functions (such as fseek() and ftell()) use relative byte offsets
from the beginning of the file instead of encoded offsets. In previous releases of
z/OS XL C/C++, byteseeking was performed only for fixed format binary files. To
have the byteseek parameter set as the default for all your calls to fopen() or
freopen(), you can set the environment variable _EDC_BYTE_SEEK to Y. See
Chapter 32, Using environment variables, on page 467 for more information.
noseek
Specifying this parameter on the fopen() call disables the repositioning
functions ftell(), fseek(), fgetpos(), and fsetpos() for as long as the file is
open. When you have specified NOSEEK and have opened a disk file for read
only, the only repositioning function allowed on the file is rewind(), if the device
supports rewinding. Otherwise, a call to rewind() sets errno and raises
SIGIOERR, if SIGIOERR is not set to SIG_IGN. Calls to ftell(), fseek(),
fsetpos(), or fgetpos() return EOF, set errno, and set the stream error flag on.
The use of the noseek parameter may improve performance when you are
reading and writing data sets.
Buffering
z/OS XL C/C++ uses buffers to map C I/O to system-level I/O. When z/OS XL
C/C++ performs I/O operations, it uses one of the following buffering modes:
v Line buffering characters are transmitted to the system when a new-line
character is encountered. Line buffering is meaningless for binary and record I/O
files.
v Full buffering characters are transmitted to the system when a buffer is filled.
You can use the setvbuf() and setbuf() library functions to set the buffering mode
before you perform any I/O operation to the file. setvbuf() fails if you specify
unbuffered I/O. It also fails if you try to specify line buffering for an FBS data set
opened in text mode, where the device does not support repositioning. This failure
happens because z/OS XL C/C++ cannot deliver records at line boundaries without
violating FBS format. Do not try to change the buffering mode after you have
performed any I/O operation to the file.
For all files except stderr, full buffering is the default, but you can use setvbuf() to
specify line buffering. For binary files, record I/O files, and unblocked text files, a
block is written out as soon as it is full, regardless of whether you have specified
line buffering or full buffering. Line buffering is different from full buffering only for
blocked text files.
Multiple buffering
Multiple buffering (or asynchronous I/O) is supported for z/OS data sets. Multiple
buffering is not supported for a data set opened for read at the same time that
another file pointer has it opened for write or append. When you open files for
multiple buffering, blocks are read into buffers before they are needed, eliminating
the delay caused by waiting for I/O to complete. Multiple buffering may make I/O
less efficient if you are seeking within or writing to a file, because seeking or writing
may discard blocks that were read into buffers but never used.
If you specify both NCP and BUFNO, z/OS XL C/C++ takes the greater of the two
values, up to the maximum for the applicable value. For example, if you specify a
BUFNO of 120 and you are using BSAM, which uses NCP instead, z/OS XL C/C++ will
use NCP=99.
If you do not specify either, z/OS XL C/C++ defaults to single buffering, except in
the following cases, where z/OS XL C/C++ uses the system's default BUFNO and
performs multiple buffering for both reading and writing:
v If you open a device that does not support repositioning, and specify read-only or
write-only mode (r, rb, w, wb, a, ab).
v If you specify the NOSEEK parameter on the call to fopen() or freopen(), and
specify read-only or write-only mode. When you specify NOSEEK, you get multiple
buffering for both reads and writes.
Note: Multiple buffering is ignored for concatenated and multivolume data sets.
If you do not specify RECFM when you are creating a new file, z/OS XL C/C++
uses the following defaults:
v If recfm is not specified in a fopen() call for an output binary file, recfm defaults
to:
recfm=VB for spool (printer) files,
recfm=FB otherwise.
v If recfm is not specified in a fopen() call for an output text file, recfm defaults to:
recfm=F if _EDC_ANSI_OPEN_DEFAULT is set to Y and no LRECL or BLKSIZE
specified. In this case, LRECL and BLKSIZE are both defaulted to 254.
recfm=VBA for spool (printer) files.
recfm=U for terminal files
recfm=V if the LRECL or BLKSIZE is specified
recfm=VB for all other OS files.
If recfm is not specified for a record I/O file, you will get the default of recfm=VB.
Table 19 on page 102 shows the defaults for LRECL and BLKSIZE when the z/OS
XL C/C++ compiler creates an OS file. Information from the C or C++ program
overrides that from the DD statement and the tape label. Information from the DD
statement overrides that from the data set label.
TAPE LABEL
Record format=FB
Record length=100
Block size=400
Recording density=1600
Table 19. fopen() defaults for LRECL and BLKSIZE when creating OS files
lrecl specified? blksize specified? RECFM LRECL BLKSIZE
no no All F 80 80
All FB 80 maximum integral
multiple of 80 less
than or equal to max
All V, VB, VS, or VBS minimum of 1028 or max
max4
All U 0 max
yes no All F lrecl lrecl
All FB lrecl maximum integral
multiple of lrecl less
than or equal to max
All V lrecl lrecl+4
All U 0 lrecl
no yes All F or FB blksize blksize
All V, VB, VS, or VBS minimum of 1028 or blksize
blksize4
All U 0 blksize
Note: All includes the standard (S) specifier for fixed formats, the ASA (A) specifier, and the machine control character
(M) specifier.
In Table 19, the value max represents the maximum reasonable block size for the
device. These are the current default maximum block sizes for several devices that
z/OS XL C/C++ supports:
Device Default maximum block size
For more information about specific default block sizes as returned by the DEVTYPE
macro, refer to z/OS DFSMS Using Data Sets.
You can perform multiple buffering under z/OS. See Multiple buffering on page
100 for details.
fread() is the only interface allowed for reading record I/O files. A read operation
directly after a write operation without an intervening call to fflush(), fsetpos(),
fseek(), or rewind() fails. z/OS XL C/C++ treats the following as read operations:
v Calls to read functions that request 0 bytes
v Read requests that fail because of a system error
v Calls to the ungetc() function
You can set up a SIGIOERR handler to catch read or write system errors. See the
debugging section in this book for more details.
For ASA variable text files, if a file was created without a control character as its
first byte, the first byte defaults to the ' ' character. When the file is read back, the
first character is read as a new-line.
For undefined format text files, reading a file causes a new-line character to be
inserted at the end of each record. On input, a record containing a single blank
character is considered an empty record and is translated to a new-line character.
Trailing blanks are preserved for each record.
For files opened in fixed text format, rightmost blanks are stripped off a record at
input, and a new-line character is placed in the logical record. This means that a
record consisting of a single new-line character is represented by a fixed-length
record made entirely of blanks.
fread() returns the number of items read successfully, so if you pass a size
argument equal to 1 and a count argument equal to the maximum expected length
A failed read operation may lead to undefined behavior until you reposition
successfully.
Writing to files
You can use the following library functions to write to a file:
v fwrite()
v fwrite_unlocked()
v printf()
v printf_unlocked()
v fprintf()
v fprintf_unlocked()
v vprintf()
v vprintf_unlocked()
v vfprintf()
v vfprintf_unlocked()
v puts()
v puts_unlocked()
v fputc()
v fputc_unlocked()
v fputs()
v fputs_unlocked()
v putc()
v putc_unlocked()
v putchar()
v putchar_unlocked()
fwrite() is the only interface allowed for writing to record I/O files. See z/OS XL
C/C++ Run-Time Library Reference for more information on these library functions.
z/OS XL C/C++ counts a call to a write function writing 0 bytes or a write request
that fails because of a system error as a write operation.
If you are updating a file and a system failure occurs, z/OS XL C/C++ tries to set
the file position to the end of the last record updated successfully. For a
fully-buffered file, this is at the end of the last record in a block. For a line-buffered
file, this may be any record in the current block. If you are writing new data at the
time of a system failure, z/OS XL C/C++ puts the file position at the end of the last
If one user opens a file for writing, and another later opens the same file for
reading, the user who is reading the file can check for records that may have been
written past the end of the file by the other user. If the file is a spanned variable text
file, the reader can read part of a spanned record and reach the end of the file
before reading in the last segment of the spanned record.
The way z/OS XL C/C++ treats text files depends on whether they are in fixed,
variable, or undefined format, and whether they use ASA.
As with ASA files in other environments, the first character of each record is
reserved for the ASA control character that represents a new-line, a carriage return,
or a form feed. See Chapter 7, Using ASA text files, on page 47 for more
information.
Table 20. C control to ASA characters
C Control Character Sequence ASA Character Description
\n ' ' skip one line
\n\n '0' skip two lines
\n\n\n '-' skip three lines
\f '1' new page
\r '+' overstrike
Note: Using ftell() or fgetpos() values for positions that do not exist after you
have shortened records results in undefined behavior.
When you are updating a file, writing new data into an existing record replaces the
old data and, if the new data is longer or shorter than the old data, changes the
size of the logical record by changing the number of blank characters in the
physical record. When you extend a record, thereby writing over the old new-line, a
new-line character is implied after the last character of the update. Calling fflush()
flushes the data out to the file and inserts blank padding between the last data
character and the end of the record. Once you have called fflush(), you can call
any of the read functions, which begin reading at the new-line. Once the new-line is
read, reading continues at the beginning of the next record.
If you have not set _EDC_ZERO_RECLEN, z/OS XL C/C++ writes out a record
containing a single blank character to represent a single new-line. On input, a
record containing a single blank character is considered an empty record and is
translated to a new-line character. Note that a single blank followed by a new-line is
written out as a single blank, and is treated as just a new-line on input. When
_EDC_ZERO_RECLEN is set, writing a record containing only a new-line results in a
zero-length variable record.
For more information about environment variables, refer to Chapter 32, Using
environment variables, on page 467. For more information about how z/OS XL
C/C++ treats empty records in variable format, see Mapping C types to variable
format on page 15.
When you are writing data to a non-blocked file without intervening flush or
reposition requests, each record is written to the system when a new-line or
carriage return character is written or when the file is closed.
When you are writing data to a blocked file without intervening flush or reposition
requests, if the file is opened in full buffering mode, the block is written to the
system on completion of the record that fills the block. If the blocked file is line
buffered, each record is written to the system when it is completed. If you are using
full buffering for a VB format file, a write may not fill a block completely. The data
does not go to the system unless a block is full; you can complete the block with
another write. If the subsequent write contains more data than is needed to fill the
block, it flushes the current block to the system and starts writing your data to a
new block.
When you are writing data to a spanned file without intervening flush or reposition
requests, if the record spans multiple blocks, each block is written to the system
once it is full and the user writes an additional byte of data.
For ASA variable text files, if a file was created without a control character as its
first byte or record (after the RDW and BDW), the first byte defaults to the ' '
character. When the file is read back, the first character is read as a new-line.
Once a record has been written, you cannot change its length. If you try to shorten
a logical record by updating it with a shorter record, z/OS XL C/C++ completes the
record with blank padding. If you try to lengthen a record by updating it with more
data than it can hold, z/OS XL C/C++ truncates the new data. The only instance in
which this does not happen is when you extend an empty record so that it contains
a single byte. Any data beyond the single byte is truncated.
In all truncation cases, the SIGIOERR signal is raised if the action for SIGIOERR is not
SIG_IGN. The user error flag is set so that ferror() will return TRUE. For more
information about SIGIOERR, ferror(), and other I/O-related debugging tools, see
Chapter 18, Debugging I/O programs, on page 221. z/OS XL C/C++ continues to
discard new output until you complete the current record by writing a new-line or
carriage return character, close the file, or change the file position.
If you are writing to one of the standard streams, attempting to write more data than
a record can hold results in the data being split across multiple records.
When you update a record, you can update less than the full record. The remaining
data that you do not update is left untouched in the file.
When you are writing new records to a fixed-record I/O file, if you try to write a
short record, z/OS XL C/C++ pads the record with nulls out to LRECL.
At the completion of an fwrite(), the file position is at the start of the next record.
For new data, the block is flushed out to the system as soon as it is full.
Flushing buffers
You can use the library function fflush() to flush streams to the system. For more
information about fflush(), see z/OS XL C/C++ Run-Time Library Reference.
The action taken by the fflush() library function depends on the buffering mode
associated with the stream and the type of streams. If you call one z/OS XL C/C++
program from another z/OS XL C/C++ program by using the ANSI system()
#include <stdio.h>
int main(void)
{
FILE * fp, * fp2;
int rc, rc2, rc3, rc4;
fp = fopen("a.b","w+");
fprintf(fp,"first record");
rewind(fp);
return(0);
}
Binary streams
z/OS XL C/C++ treats line buffering and full buffering the same way for binary files.
If the file has a variable length or undefined record format, fflush() writes the
current record out. This may result in short records. In blocked files, this means that
the block is written to disk, and subsequent writes are to a new block. For fixed
files, no incomplete records are flushed.
For single-volume disk files in FBS format, fflush() flushes complete records in an
incomplete block out to the file. For all other types of FBS files, fflush() does not
flush an incomplete block out to the file.
For files in FB format, fflush() always flushes out all complete records in the
current block. For sequential DASD files, new completed records are added to the
end of the flushed block if it is short. For non-DASD or non-sequential files, any
new record will start a new block.
Text streams
v Line-Buffered Streams
fflush() has no effect on line-buffered text files, because z/OS XL C/C++ writes
all records to the system as they are completed. All incomplete new records
remain in the buffer.
v Fully Buffered Streams
Calling fflush() flushes all completed records in the buffer, that is, all records
ending with a new-line or carriage return (or form feed character, if you are using
ASA), to the system. z/OS XL C/C++ holds any incomplete record in the buffer
until you complete the record or close the file.
For ASA text files, if a flush occurs while an ASA character that indicates more than
one new-line is being updated, the remaining new-lines will be discarded and a
read will continue at the first data character. For example, if \n\n\n is updated to
be \n\n and a flush occurs, then a 0 will be written out in the ASA character
position.
Record I/O
z/OS XL C/C++ treats line buffering and full buffering the same way for record I/O.
For files in FB format, calling fflush() writes all records in the buffer to the system.
For single-volume disk files in FBS format, fflush() will flush complete records in an
incomplete block out to the file. For all other types of FBS files, fflush() will not
flush an incomplete block out to the file. For all other formats, calling fflush() has
no effect, because fwrite() has already written the records to disk.
ungetc() considerations
ungetc() pushes characters back onto the input stream for binary and text files.
ungetc() handles only single-byte characters. You can use it to push back as many
as four characters onto the ungetc() buffer. For every character pushed back with
ungetc(), fflush() backs up the file position by one character and clears all the
pushed-back characters from the stream. Backing up the file position may end up
A B C D
file pointer
For example, given the stream you can run the following code fragment:
fgetc(fp); /* Returns A and puts the file position at */
/* the beginning of the character B */
ungetc(Z,fp); /* Logically inserts Z ahead of B */
fflush(fp); /* Moves the file position back by one to A, */
/* removes Z from the logical stream */
If you want fflush() to ignore ungetc() characters, you can set the _EDC_COMPAT
environment variable. See Chapter 32, Using environment variables, on page 467
for more information.
With large file support enabled for AMODE 31 C/C++ applications, you can use the
following library functions for 64-bit offsets:
v fseeko()
v fseeko_unlocked()
v ftello()
v ftello_unlocked()
For AMODE 64 C/C++ applications, large files are automatically supported in the
LP64 programming model. All of the above functions (both lists) can be used with
64-bit offsets.
See z/OS XL C/C++ Run-Time Library Reference for more information on these
library functions.
Calling any of these functions flushes all complete and updated records out to the
system. If a repositioning operation fails, z/OS XL C/C++ attempts to restore the
original file position and treats the operation as a call to fflush(), except that it
does not account for the presence of ungetc() or ungetwc() characters, which are
lost. After a successful repositioning operation, feof() always returns 0, even if the
position is just after the last byte of data in the file.
The fsetpos() and fgetpos() library functions are generally more efficient than ftell()
and fseek(). The fgetpos() function can encode the current position into a structure
that provides enough room to hold the system position as well as position data
specific to C or C++. The ftell() function must encode the position into a single
word of storage, which it returns. This compaction forces fseek() to calculate
certain position information specific to C or C++ at the time of repositioning. For
variable-format binary files, you can choose to have ftell() return relative byte
offsets. In previous releases, ftell() returned only encoded offsets, which
contained the relative block number. Since you cannot calculate the block number
from a relative byte offset in a variable-format file, fseek() may have to read
through the file to get to the new position. fsetpos() has system position
information available within the the fpos_t structure and can generally reposition
directly to the desired location.
You can use the ftell() and fseek() functions to set the current position within all
types of files except for the following:
v Files on nonseekable devices (for example, printers)
v Partitioned data sets opened in w or wb mode.
Although repositioning within files opened for write mode is not available, you can
use fgetpos() and ftell() to save the current position, and this position can later
be used to reposition within the same file if opened in one of the modes where
reposition is allowed.
For AMODE 31 C/C++ applications, the repositioning functions can be used with
large format sequential data sets under the following conditions:
v The data set contains 256 TB - 256 bytes or less.
v The data set uses 2 GB blocks or less.
ungetc() considerations
For binary and text files, the library functions fgetpos() and ftell() take into
account the number of characters you have pushed back onto the input stream with
ungetc(), and adjust the file position accordingly. ungetc() backs up the file position
by a single byte each time you call it. For text files, z/OS XL C/C++ counts the
new-lines added to the records as single-byte characters when it calculates the file
position.
If you make so many calls to ungetc() that the logical file position is before the
beginning of the file, the next call to ftell() or fgetpos() fails.
If you want fgetpos() and fseek() to ignore ungetc() characters, you can set the
_EDC_COMPAT environment variable. See Chapter 32, Using environment variables,
on page 467 for details. ftell() is not affected by the setting of _EDC_COMPAT.
You do not need to acquire an offset from ftell() to seek to a relative position; you
may specify a relative offset to fseek() with a whence value of SEEK_SET.
However, you cannot specify a negative offset to fseek() when you have specified
SEEK_SET, because a negative offset would indicate a position before the
beginning of the file. Also, you cannot specify a negative offset with whence values
of SEEK_CUR or SEEK_END such that the resulting file position would be before
the beginning of the file. If you specify such an offset, fseek() fails.
If your file is not opened read-only, you can specify a position that is beyond the
current EOF. In such cases, a new end-of-file position is created; null characters are
automatically added between the old EOF and the new EOF.
fseek() support of byte offsets in variable-format files generally requires reading all
records from the whence value to the new position. The impact on performance is
greatest if you open an existing file for append in BYTESEEK mode and then call
ftell(). In this case, ftell() has to read from the beginning of the file to the
current position to calculate the required byte offset. Support for byteseeking is
intended to ease portability from other platforms. If you need better performance,
consider using ftell()-encoded offsets, see Encoded offsets on page 115.
Encoded offsets are values representing the block number and the relative byte
within that block, all within one long int. Because z/OS XL C/C++ does not
document its encoding scheme, you cannot rely on any encoded offset not returned
by ftell(), except 0, which is the beginning of the file. This includes encoded
offsets that you adjust yourself (for example, with addition or subtraction). When
you call fseek() with the whence value SEEK_SET, you must use either 0 or an
encoded offset returned from ftell(). For whence values of SEEK_CUR and
SEEK_END, however, you specify relative byte offsets. If you want to seek to a
certain relative byte offset, you can use SEEK_SET with an offset of 0 to rewind the
file to the beginning, and then you can use SEEK_CUR to specify the desired
relative byte offset.
In earlier releases, ftell() could determine position only for files with no more than
131,071 blocks. In the new design, this number increases depending on the block
size. From a maximum block size of 32,760, every time this number decreases by
half, the number of blocks that can be represented doubles. Using the large file
version of ftello() for a large format sequential data set increases the maximum
number of blocks that can be represented to 2 GB in AMODE 31 C/C++
applications.
If your file is not opened read-only, you can use SEEK_CUR or SEEK_END to
specify a position that is beyond the current EOF. In such cases, a new end-of-file
position is created; null characters are automatically added between the old EOF and
the new EOF. This does not apply to PDS members, as they cannot be extended.
For SEEK_SET, because you are restricted to using offsets returned by ftell(),
any offset that indicates a position outside the current file is invalid and causes
fseek() to fail.
When you call fseek() with the whence value SEEK_SET, you must use an encoded
offset returned from ftell(). For whence values of SEEK_CUR and SEEK_END,
however, you specify relative byte offsets. If you want to seek to a certain relative
byte offset, you can use SEEK_SET with an offset of 0 to rewind the file to the
beginning, and then you can use SEEK_CUR to specify the desired relative byte
offset. z/OS XL C/C++ counts new-line characters and skips to the next record each
time it reads one.
Unlike binary files you cannot specify offsets for SEEK_CUR and SEEK_END that
set the file position past the end of the file. Any offset that indicates a position
outside the current file is invalid and causes fseek() to fail.
In earlier releases, ftell() could determine position only for files with no more than
131071 blocks. In the new design, this number increases depending on the block
size. From a maximum block size of 32760, every time this number decreases by
seeks to relative record 6. You do not need to get an offset from ftell().
You cannot seek past the end or before the beginning of a file.
For files opened in fixed binary mode, incomplete records will be padded with null
characters when you close the file.
For files opened in variable binary mode, incomplete records are flushed to the
system. In a spanned file, closing a file can cause a zero-length segment to be
written. This segment will still be part of the non-zero-length record. For files
opened in undefined binary mode, any incomplete output is flushed on close.
Closing files opened in text mode causes any incomplete new record to be
completed with a new-line character. All records not yet flushed to the file are
written out when the file is closed.
For files opened for record I/O, closing causes all records not yet flushed to the file
to be written out.
When fclose() is used to close a stream associated with a z/OS data set, some
failures may be unrecoverable, and will result in an ABEND. These ABENDs may
include I/O ABENDs of the form x14 and x37. Control will not be returned to the
caller of fclose() to report the error. To process these types of errors, applications
need to use z/OS Language Environment condition handling to receive control (see
z/OS Language Environment Programming Guide), or register a signal handler for
SIGABND (see Chapter 28, Handling error conditions, exceptions, and signals, on
page 403).
If an application fails during fclose() with a x37 abend, and the application would
like to recover and perform any functions not related to file I/O, the following
technique can be used. Refer to Figure 17 on page 118 for an example.
1. Register a signal handler for SIGABND and SIGIOERR.
2. fopen() the file. The NOSEEK option cannot be specified.
3. Manipulate the file as needed by the application.
4. When the application is done with the file, fflush() the file, before any fclose() is
issued. This will ensure, if an x37 is going to occur during fflush() or fclose()
processing, that the x37 occurs in the fflush(), before the fclose() occurs.
5. An x37 abend occurs during fflush().
6. The signal handler will receive control.
7. Once inside the signal handler, any functions not related to file I/O may be
performed.
#include <stdio.h>
#include <stdlib.h>
#include <dynit.h>
#include <signal.h>
#include <setjmp.h>
void sighandler();
jmp_buf env;
FILE *f;
int main()
{
int rc;
int s=80;
int w;
char buff 80 ="data";
__dyn_t ip;
redo:
dyninit(&ip);
ip.__dsname="MY.DATASET";
ip.__status=__DISP_OLD;
ip.__ddname="NAMEDD";
ip.__conddisp=__DISP_CATLG;
rc=dynalloc(&ip);
f=fopen("DD:NAMEDD","wb");
if (f==0)
{ perror("open error");
return 12;
}
signal(SIGABND,sighandler);
signal(SIGIOERR,sighandler);
while (1)
{
if (setjmp(env))
{
dyninit(&ip);
ip.__ddname="NAMEDD";
ip.__conddisp=__DISP_CATLG;
rc= dynfree(&ip);
goto retry;
}
w=fwrite(buff,1,s,f);
}
fflush(f);
fclose(f);
retry:
goto redo;
}
void sighandler() {
fclose(f);
longjmp(env,1);
}
fldata() behavior
The format of the fldata() function is as follows:
The fldata() function is used to retrieve information about an open stream. The
name of the file is returned in filename and other information is returned in the
fldata_t structure, shown in Figure 18 on page 120. Values specific to this category
of I/O are shown in the comment beside the structure element. Additional notes
follow the figure. For more information on the fldata() function, refer to z/OS XL
C/C++ Run-Time Library Reference.
The Single UNIX Specification defines another type of file called STREAMS. Even
though the system interfaces are provided, it is impossible to have a valid STREAMS
file descriptor. These interfaces will always return a return code of -1 with errno set
to indicate an error such as, EBADF, EINVAL, or ENOTTY.
z/OS UNIX file system streams follow the binary model, regardless of whether they
are opened for text, binary, or record I/O. You can simulate record I/O by using
new-line characters as record boundaries.
For information on the z/OS UNIX file system and access to files within it from other
than the C or C++ language, see z/OS UNIX System Services User's Guide. For an
introduction to and description of the behavior of a POSIX-defined file system, see
Zlotnick, Fred, The POSIX.1 Standard: A Programmer's Guide,,Redwood City, CA:
The Benjamin/Cummings Publishing Company, Inc., 1991.
This topic describes C I/O stream functions as they can be used within C++
programs. If you want to use the C++ I/O stream classes instead, see Chapter 4,
Using the Standard C++ Library I/O Stream Classes, on page 21. For more
detailed information, see Standard C++ Library Reference. For information about
using wide-character I/O with z/OS XL C/C++, see Chapter 8, z/OS XL C Support
for the double-byte character set, on page 51.
Creating files
You can use library functions to create the following types of z/OS UNIX file system
files.
v Regular Files
v Link and Symbolic Link Files
v Directory Files
v Character Special Files
v FIFO Files
Regular files
Use any of the following C functions to create regular files in the z/OS UNIX file
system:
v creat()
v fopen()
v freopen()
v open()
For a description of these and other I/O functions, see z/OS XL C/C++ Run-Time
Library Reference.
Copyright IBM Corp. 1996, 2012 123
Link and symbolic link files
Use either of the following C functions to create z/OS UNIX file system link or
symbolic link files:
v link()
v symlink()
Directory files
Use the mkdir() C function to create a z/OS UNIX file system directory file.
FIFO files
Use the mkfifo() C function to create a FIFO file (named pipe) in the z/OS UNIX
file system.
Opening files
This section discusses the use of the fopen() or freopen() library functions to open
z/OS UNIX file system I/O files. You can also access z/OS UNIX file system files
using low-level I/O open() function. See Low-level z/OS UNIX I/O on page 137 for
information about low-level I/O, and z/OS XL C/C++ Run-Time Library Reference
for information about any of the functions listed above.
The name of a z/OS UNIX file system file can include characters chosen from the
complete set of character values, except for null characters. If you want a portable
filename, then choose characters from the POSIX .1 portable filename character
set.
The complete pathname can begin with a slash and be followed by zero, one, or
more filenames, each separated by a slash. If a directory is included within the
pathname, it may have one or more trailing slashes. Multiple slashes following one
another are interpreted as one slash.
If your program is running under POSIX(ON), all valid POSIX names are passed with
the asis fopen() parameter to the POSIX open() function.
You can access either z/OS UNIX file system files or MVS data sets from programs.
Programs accessing files or data sets can be executed with either the POSIX(OFF)
or POSIX(ON) run-time options. There are basic file naming rules that apply for z/OS
The POSIX run-time option determines the type of z/OS XL C/C++ services and I/O
available to your program. (See z/OS XL C/C++ User's Guide for a discussion of
the z/OS UNIX programming environment and overview of binding z/OS UNIX XL
C/C++ applications.)
Both the basic and special z/OS XL C/C++ file naming rules for z/OS UNIX file
system files are described in the sections that follow. Examples are provided. All
examples must be run with the POSIX(ON) option. For information about MVS data
sets, see Chapter 10, Performing OS I/O operations, on page 81.
z/OS UNIX file system files: The following is the format for the pathname
argument on the fopen() or freopen() function:
pathname
" /
.
dd: ddname
// DD: ( member ) "
The POSIX.1 standard defines pathname as the information that identifies a file. For
the z/OS UNIX implementation of the POSIX.1 standard, a pathname can be up to
1024 charactersincluding the null-terminating character. Optionally, it can begin
with a slash character (/) followed by directory names separated by slash
characters and a filename. For the pathname, each directory name or the filename
can be up to 255 characters long.
If you begin the pathname value with ./, the specified file in the working directory is
opened:
fopen("./parts.order", "w+")
Likewise, if you begin the pathname value with /, the specified file in the root
directory is opened:
fopen("/parts.order", "w+")
Chapter 11. Performing z/OS UNIX file system I/O operations 125
If you specify more than two consecutive slash characters anywhere in a pathname,
all but the first slash character is ignored, as in the following examples:
"//a.b" MVS data set prefix.a.b
"///a.b" z/OS UNIX file system file /a.b
"////a.b" z/OS UNIX file system file /a.b
"a////b.c" z/OS UNIX file system file a/b.c
"/a.b" z/OS UNIX file system file /a.b
"/a///b.c" z/OS UNIX file system file /a/b.c
For z/OS UNIX file system files, leading and trailing white spaces are significant.
For an application program that is to be run under POSIX(ON), you can include in
your program statements similar to the following to open the file parts.instock for
reading in the working directory:
FILE *stream;
To open the MVS data set user-prefix.PARTS.INSTOCK for reading, include statements
similar to the following in your program:
FILE *stream;
To open the file parts.instock in the working directory for reading, include
statements similar to the following in your program:
FILE *stream;
Note: Use of the z/OS XL C/C++ fork() library function from an application
program under z/OS UNIX does not replicate the data definition information of the
parent process in the child process. Use of any of the exec() library functions
deallocates the data definition information for the application process.
For the declaration just shown for the file parts.instock, you should write a JCL
DD statement similar to the following:
//PSTOCK DD PATH=/u/parts.instock,...
For more information on writing DD statements, you should refer to the job control
language (JCL) manual z/OS MVS JCL Reference.
To open the file by DD name under TSO/E, you must write an ALLOCATE command.
For the declaration of a file parts.instock, you should write a TSO/E ALLOCATE
command similar to the following:
ALLOCATE DDNAME(PSTOCK) PATH(/u/parts.instock)...
See z/OS TSO/E Command Reference for more information on TSO ALLOCATE.
recfm=
Ignored for z/OS UNIX file system I/O.
Chapter 11. Performing z/OS UNIX file system I/O operations 127
lrecl= and blksize=
Ignored for z/OS UNIX file system I/O, except that lrecl affects the value
returned in the __maxreclen field of fldata() as described below.
acc= Ignored for z/OS UNIX file system I/O.
password
Ignored for z/OS UNIX file system I/O.
space=
Ignored for z/OS UNIX file system I/O.
type= The only valid value for this parameter under the z/OS UNIX file system is
type=record. If you specify this, your file follows the z/OS UNIX file system
record I/O rules:
1. One record is defined to be the data up to the next new-line character.
2. When an fread() is done the data will be copied into the user buffer as
if an fgets(buf, size_item*num_items, stream) were issued. Data is
read into the user buffer up to the number of bytes specified on the
fread(), or until a new-line character or EOF is found. The new-line
character is not included.
3. When an fwrite() is done the data will be written from the user buffer
with a new-line character added by the RTL code. Data is written up to
the number of bytes specified on the fwrite(); the new-line is added by
the RTL and is not included in the return value from fwrite().
4. If you have specified an lrecl and type=record, fldata() of this stream
will return the lrecl you specified, in the __maxreclen field of the
__fileData return structure of stdio.h. If you specified type=record but
no lrecl, the __maxreclen field will contain 1024.
If type=record is not in effect, a call to fldata() of this stream will return
0 in the __maxreclen field of the __fileData return structure of stdio.h.
asis Ignored for z/OS UNIX file system I/O.
byteseek
Ignored for z/OS UNIX file system I/O.
noseek
Ignored for z/OS UNIX file system I/O.
OS Ignored for z/OS UNIX file system I/O.
abend=
Ignored for z/OS UNIX file system I/O.
fread() is the only interface allowed for reading record I/O files. See z/OS XL
C/C++ Run-Time Library Reference for more information on all of the above library
functions.
For z/OS UNIX low-level I/O, you can use the read() and readv() function. See
Low-level z/OS UNIX I/O on page 137.
Opening and reading from z/OS UNIX file system directory files
To open a z/OS UNIX file system directory, you can use the opendir() function.
You can use the following library functions to read from, and position within, z/OS
UNIX file system directories:
v readdir()
v seekdir()
v telldir()
Chapter 11. Performing z/OS UNIX file system I/O operations 129
v pwrite()
fwrite() is the only interface allowed for writing to record I/O files. See z/OS XL
C/C++ Run-Time Library Reference for more information on all of the above library
functions. For z/OS UNIX low-level I/O, you can use the write() and writev()
function.
Flushing records
You can use the library function fflush() to flush streams to the system. For more
information about fflush(), see z/OS XL C/C++ Run-Time Library Reference.
The action taken by the fflush() library function depends on the buffering mode
associated with the stream and the type of streams. If you call one z/OS XL C/C++
program from another z/OS XL C/C++ program by using the ANSI system()
function, all open streams are flushed before control is passed to the callee, and
again before control is returned to the caller. A call to the POSIX system() function
does not flush any streams.
For z/OS UNIX file system files, the fflush() function copies the data from the
run-time buffer to the file system. The fsync() function copies the data from the file
system buffer to the storage device.
With large file support enabled for AMODE 31 C/C++ applications, you can use the
following library functions for 64-bit offsets:
v fseeko()
v fseeko_unlocked()
v ftello()
v ftello_unlocked()
v lseek()
For AMODE 64 C/C++ applications, large files are automatically supported in the
LP64 programming model. All of the above functions (both lists) can be used with
64-bit offsets.
Closing files
You can use fclose(), freopen(), or close() to close a file. z/OS XL C/C++
automatically closes files on normal program termination, and attempts to do so
under abnormal program termination or abend. See z/OS XL C/C++ Run-Time
Library Reference for more information on these library functions. For z/OS UNIX
low-level I/O, you can use the close() function. When you use any exec() or
fork() function, files defined as marked to be closed are closed before control is
returned.
Deleting files
Use the unlink() or remove() z/OS XL C/C++ function to delete the following types
of z/OS UNIX file system files:
v Regular
v Character special
v FIFO
v Link files
Use the rmdir() z/OS XL C/C++ function to delete a z/OS UNIX file system
directory file. See z/OS XL C/C++ Run-Time Library Reference for more information
about these functions.
Pipe I/O
POSIX.1 pipes represent an I/O channel that processes can use to communicate
with other processes. Pipes are conceptually like z/OS UNIX file system files. One
process can write data into a pipe, and another process can read data from the
pipe.
z/OS UNIX XL C/C++ supports two types of POSIX.1-defined pipes: unnamed pipes
and named pipes (FIFO files).
An unnamed pipe is accessible only by the process that created the pipe and its
child processes. An unnamed pipe does not have to be opened before it can be
used. It is a temporary file that lasts only until the last file descriptor that references
it is closed. You can create an unnamed pipe by calling the pipe() function.
Chapter 11. Performing z/OS UNIX file system I/O operations 131
communicate with other processes that it did not fork, you should use the
POSIX.1-defined named pipe (FIFO special file) support. See Using named pipes
on page 133 for more information.
When you code the pipe() function to create a pipe, you pass a pointer to a
two-element integer array where pipe() puts the file descriptors it creates. One
descriptor is for the input end of the pipe, and the other is for the output end of the
pipe. You can code your application so that one process writes data to the input
end of the pipe and another process reads from the output end on a first-in-first-out
basis. You can also build a stream on the pipe by using fdopen(), and use buffered
I/O functions. The result is that you can communicate data between a parent
process and any of its child processes.
The opened pipe is assigned the two lowest-numbered file descriptors available.
z/OS UNIX provides no security checks for unnamed pipes, because such a pipe is
accessible only by the parent process that creates the pipe and any of the parent
process's descendent processes. When the parent process ends, an unnamed pipe
created by the process can still be used, if needed, by any existing descendant
process that has an open file descriptor for the pipe.
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main() {
int ret_val;
int pfd[2];
char buff[32];
char string1[]="String for pipe I/O";
Within the application program, you create a named pipe by coding a mkfifo() or
mknod() function. You give the FIFO a name and an access mode when you create
it. If the access mode allows all users read and write access to the named pipe,
any process that knows its name can use it to send or receive data.
Chapter 11. Performing z/OS UNIX file system I/O operations 133
Processes can use the open() function to access named pipes and then use the
regular I/O functions for files, such as read(), write(), and close(), when
manipulating named pipes. Buffered I/O functions can also be used to access and
manipulate named pipes. For more information on the mkfifo() and mknod()
functions and the file I/O functions, see z/OS XL C/C++ Run-Time Library
Reference.
The following steps outline how to use a named pipe from z/OS UNIX XL C/C++
application programs:
1. Create a named pipe using the mkfifo() function. Only one of the processes
that use the named pipe needs to do this.
2. Access the named pipe using the appropriate I/O method.
3. Communicate through the pipe with another process using file I/O functions:
a. Write data to the named pipe.
b. Read data from the named pipe.
4. Close the named pipe.
5. If the process created the named pipe and the named pipe is no longer needed,
remove that named pipe using the unlink() function.
A process running the following simple example program creates a new named pipe
with the file pathname pointed to by the path value coded in the mkfifo() function.
The access mode of the new named pipe is initialized from the mode value coded in
the mkfifo() function. The file permission bits of the mode argument are modified
by the process file creation mask.
Note: The two processes are related and have agreed to communicate through the
named pipe. They need not be related, however. Other authorized users can run
the same program and participate in (or interfere with) the process communication.
main()
{ /* start of program */
if ((mkfifo(fifoname,S_IRWXU)) != 0) {
printf("Unable to create a fifo; errno=%d\n",errno);
exit(1); /* Print error message and return */
}
/* perform a write */
n_elements = fwrite(str,1,strlen(str),wr_stream);
if (n_elements != (size_t) strlen(str)) {
printf("Fwrite returned %d, expected %d\n",
(int)n_elements,strlen(str));
exit(101);
}
exit(0); /* return success to parent */
}
Chapter 11. Performing z/OS UNIX file system I/O operations 135
/* get current flag settings of file */
if ((flags = fcntl(fileno(rd_stream),F_GETFL)) == -1) {
printf("fcntl returned -1 for %s\n",fifoname);
exit(3);
}
if (strncmp(char_ptr,str,strlen(str))) {
printf("\ncontents of char_ptr are %s ",
char_ptr);
printf("\ncontents of str are %s ",
str);
printf("\nThese should be equal");
exit(7);
}
ret_value = fclose(rd_stream);
if (ret_value != 0) {
printf("\nFclose failed for %s",fifoname);
printf("\nerrno is %d",errno);
exit(8);
}
ret_value = remove(fifoname);
if (ret_value != 0) {
printf("\nremove failed for %s",fifoname);
printf("\nerrno is %d",errno);
exit(9);
}
pid = wait(c_status);
if ((WIFEXITED(c_status) !=0) &&; (WEXITSTATUS(c_status) !=0)) {
printf("\nchild exited with code %d",WEXITSTATUS(c_status));
exit(10);
}
} /* end of else clause */
printf("About to issue exit(0), \
processing completed successfully\n");
exit(0);
}
Figure 21 is example code (CCNGHF3) that demonstrates the use of z/OS UNIX
stream input/output by writing streams to a file, reading the input lines, and
replacing a line.
#define _OPEN_SYS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#undef _OPEN_SYS
FILE *stream;
Figure 21. Example of z/OS UNIX stream input and output functions (Part 1 of 3)
Chapter 11. Performing z/OS UNIX file system I/O operations 137
int main(void)
{
if ((stream = fopen("./myfile.data","wb"))==NULL) {
perror("Error opening file");
exit(0);
}
for(i=0; i<12;i++) {
int len1 = strlen(string1);
rc = fwrite(string1, 1, len1, stream);
if (rc != len1) {
perror("fwrite failed");
printf("i = %d\n", i);
exit(99);
}
}
rc = fwrite(string2,1,sizeof(string2)-1,stream);
if (rc != sizeof(string2)-1) {
perror("fwrite failed");
exit(99);
}
for(i=0;i<12;i++) {
rc = fwrite(string1,1,sizeof(string1)-1,stream);
if (rc != sizeof(string1)-1) {
perror("fwrite failed");
printf("i = %d\n", i);
exit(99);
}
}
fclose(stream);
/* Read data stream and search for location of string2. */
/* EOF is not set until an attempt is made to read past the */
/* end-of-file, thus the fread is at the end of the while loop */
Figure 21. Example of z/OS UNIX stream input and output functions (Part 2 of 3)
if ((position=ftell(stream)) == -1L)
perror("Error saving file position.");
rc = fread(string4, 1, sizeof(string2)-1, stream);
}
fclose(stream);
/* Replace line containing string2 with string3 */
fd = open("test.data",O_RDWR);
x = write(fd,"a record",8);
if (x < 8){
perror("write failed\n");
}
rc = lseek(fd,0,SEEK_SET);
x = read(fd,buffer,8);
if (x < 8){
perror("read failed\n");
}
printf("data read is %.8s\n",buffer);
close(fd);
}
Figure 21. Example of z/OS UNIX stream input and output functions (Part 3 of 3)
To use 64-bit offset and file sizes, you must make the following changes in your
code:
1. Change any variables used for offsets in fseek() or ftell() that are int
or long to the off_t data type.
2. Define the _LARGE_FILES 1 feature test macro.
3. Replace fseek()/ftell() with fseeko()/ftello(). See z/OS XL C/C++
Run-Time Library Reference for descriptions of these functions.
4. Compile with the LANGLVL(LONGLONG) compiler option.
Notes:
1. These changes are compatible with your older files.
2. Large Files support (64bit offset and file sizes) is automatic in the LP64
programming model that is used in 64bit. The long data type is widened to
64bits. This enables fseek() and ftell() to work with the larger offsets with
no code change. The fseeko() and ftello() functions also work with 64bit
offsets since off_t is typedef'd as a long int.
Chapter 11. Performing z/OS UNIX file system I/O operations 139
The example program (CCNGHF4) in Figure 22 on page 141 provides the same
function as CCNGHF3, but it uses 64-bit offsets. The changed lines are marked in a
bold font.
#define _OPEN_SYS
#define _LARGE_FILES 1
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#undef _OPEN_SYS
FILE *stream;
int main(void)
{
if ((stream = fopen("./myfile.data","wb"))==NULL) {
perror("Error opening file");
exit(0);
}
for(i=0; i<12;i++) {
int len1 = strlen(string1);
rc = fwrite(string1, 1, len1, stream);
if (rc != len1) {
perror("fwrite failed");
printf("i = %d\n", i);
exit(99);
}
}
rc = fwrite(string2,1,sizeof(string2)-1,stream);
if (rc != sizeof(string2)-1) {
perror("fwrite failed");
exit(99);
}
for(i=0;i<12;i++) {
rc = fwrite(string1,1,sizeof(string1)-1,stream);
if (rc != sizeof(string1)-1) {
perror("fwrite failed");
printf("i = %d\n", i);
exit(99);
}
}
Figure 22. Example of HFS stream input and output functions (Part 1 of 2)
Chapter 11. Performing z/OS UNIX file system I/O operations 141
fclose(stream);
/* Read data stream and search for location of string2. */
/* EOF is not set until an attempt is made to read past the */
/* end-of-file, thus the fread is at the end of the while loop */
if ((position=ftello(stream)) == -1LL)
perror("Error saving file position.");
while(!feof(stream)) {
if (rc != sizeof(string2)-1) {
perror("fread failed");
exit(99);
}
if ((position=ftello(stream)) == -1LL)
perror("Error saving file position.");
fclose(stream);
/* Replace line containing string2 with string3 */
fd = open("test.data",O_RDWR);
x = write(fd,"a record",8);
if (x < 8){
perror("write failed\n");
}
strpos = lseek(fd,0LL,SEEK_SET); /* Note off_t is 64bits with _LARGE_FILES */
/* set and the off_t variable */
/* needs a 64bit constant of 0LL */
x = read(fd,buffer,8);
if (x < 8){
perror("read failed\n");
}
printf("data read is %.8s\n",buffer);
close(fd);
}
Figure 22. Example of HFS stream input and output functions (Part 2 of 2)
fldata() behavior
The format of the fldata() function is as follows:
The fldata() function is used to retrieve information about an open stream. The
name of the file is returned in filename and other information is returned in the
fldata_t structure, shown in Figure 23. Values specific to this category of I/O are
shown in the comment beside the structure element. Additional notes pertaining to
this category of I/O follow the figure. For more information on the fldata() function,
refer to z/OS XL C/C++ Run-Time Library Reference.
struct __fileData {
unsigned int __recfmF : 1, /* always off */
__recfmV : 1, /* always off */
__recfmU : 1, /* always on */
__recfmS : 1, /* always off */
__recfmBlk : 1, /* always off */
__recfmASA : 1, /* always off */
__recfmM : 1, /* always off */
__dsorgPO : 1, /* N/A -- always off */
__dsorgPDSmem : 1, /* N/A -- always off */
__dsorgPDSdir : 1, /* N/A -- always off */
__dsorgPS : 1, /* N/A -- always off */
__dsorgConcat : 1, /* N/A -- always off */
__dsorgMem : 1, /* N/A -- always off */
__dsorgHiper : 1, /* N/A -- always off */
__dsorgTemp: 1, /* N/A -- always off */
__dsorgVSAM: 1, /* N/A -- always off */
__dsorgHFS : 1, /* always on */
__openmode : 2, /* one of: */
/* __BINARY */
/* __RECORD */
__modeflag : 4, /* combination of: */
/* __READ */
/* __WRITE */
/* __APPEND */
/* __UPDATE */
__dsorgPDSE: 1, /* N/A -- always off */
__reserve2 : 8; /* */
__device_t __device; /* __HFS */
unsigned long __blksize, /* 0 */
__maxreclen; /* */
unsigned short __vsamtype; /* N/A */
unsigned long __vsamkeylen; /* N/A */
unsigned long __vsamRKP; /* N/A */
char * __dsname; /* */
unsigned int __reserve4; /* */
};
typedef struct __fileData fldata_t;
Notes:
1. The filename is the same as specified on the fopen() or freopen() function call.
2. The __maxreclen value is 0 for regular I/O (binary). For record I/O the value is
lrecl or the default of 1024 when lrecl is not specified.
3. The __dsname value is the real POSIX pathname.
Chapter 11. Performing z/OS UNIX file system I/O operations 143
File tagging and conversion
In general, the file system knows the contents of a file only as a set of bytes.
Applications which create and process bytes in a file know whether these bytes
represent binary data, text (character) data, or a mixture of both. File tags are file
metadata fields which describe the contents of a file. Enhanced ASCII includes the
following file tag fields:
txtflag A flag indicating if a file consists solely of character data encoded
by a single coded character set ID (CCSID).
file ccsid A 16 bit field specifying the CCSID of characters in the file.
Applications can explicitly tag files using new open() or fcntl() options, or
applications can allow the logical file system (LFS) to tag new files on first write,
fopen(). A new environment variable, _BPXK_CCSID, is used to assign a program
CCSID to an application, which LFS will use to tag new files on first write. LFS also
uses the program CCSID derived from _BPXK_CCSID to set up auto-conversion of
pure text datastreams. LFS attempts to set up auto-conversion when:
v Auto-conversion is enabled for an application by the _BPXK_AUTOCVT environment
variable
v The file txtflag flag is set indicating a pure text file
v The file and program CCSIDs do not match.
Automatic file conversion and file tagging include the following facilities:
v _OPEN_SYS_FILE_EXT feature test macro. For more information, see z/OS XL
C/C++ Run-Time Library Reference .
v _BPXK_AUTOCVT and _BPXK_CCSIDS environment variables. For more information,
see Chapter 32, Using environment variables, on page 467.
v z/OS Language Environment FILETAG run-time option. For more information, see
z/OS Language Environment Programming Reference.
v __chattr() and __fchattr() functions; F_SETTAG and F_CONTROL_CVT
arguments for the fcntl() function; options for the fopen(), popen(), stat(),
fstat(), and lstat() functions. For more information, see z/OS XL C/C++
Run-Time Library Reference.
Chapter 11. Performing z/OS UNIX file system I/O operations 145
146 z/OS V1R13.0 XL C/C++ Programming Guide
Chapter 12. Performing VSAM I/O operations
This chapter outlines the use of Virtual Storage Access Method (VSAM) data sets in
z/OS XL C/C++. Three I/O processing modes for VSAM data sets are available in
z/OS XL C/C++:
v Record
v Text Stream
v Binary Stream
For more information about the facilities of VSAM, see the list of DFSMS on page
1027 publications.
See Chapter 8, z/OS XL C Support for the double-byte character set, on page 51
for information about using wide-character I/O with z/OS XL C/C++.
Notes:
1. This chapter describes C I/O as it can be used within C++ programs.
2. The C++ I/O stream libraries cannot be used for VSAM I/O because these do
not support the record processing mode (where type=record is specified).
3. Starting in z/OS V1R10, the C/C++ run-time library provides support for VSAM
data sets in the extended addressing space on extended address volumes
(EAVs).
In addition to the primary VSAM access described above, for KSDS and ESDS,
there is also direct access by one or more additional key fields within each record.
These additional keys can be unique or non-unique; they are called an alternate
index (AIX).
Before a VSAM data set is used for the first time, its structure is defined to the
system by the Access Method Services DEFINE CLUSTER command. This command
defines the type of VSAM data set, its structure, and the space it requires.
Before a VSAM alternate index is used for the first time, its structure is defined to
the system by the Access Method Services DEFINE ALTERNATEINDEX command. To
enable access to the base cluster records through the alternate index, use the
DEFINE PATH command. Finally, to build the alternate index, use the BLDINDEX
command.
When you have built the alternate index, you call fopen() and specify the PATH in
order to access the base cluster through the alternate index. Do not use fopen() to
access the alternate index itself.
Note: You cannot use the BLDINDEX command on an empty base cluster.
FRED 69 M
ANDY
ANDY 70 M FRED
SUZAN 72 F JANE
JANE 75 F SUZAN
By sex (non-unique)
F
M
When choosing the VSAM data set type, you should base your choice on the most
common sequence in which you require data. You should follow a procedure similar
to the one suggested below to help ensure a combination of data sets and indexes
that provide the function you require.
The RBA value is stored in the C structure __amrc, which is defined in the C
<stdio.h> header file. The __amrc->__RBA field is defined as an unsigned int, and
therefore will contain only a 4-byte RBA value. The __amrc->__XRBA field is 8 bytes
(unsigned long long in AMODE 31 applications, and unsigned long in AMODE 64
applications), and therefore can hold the RBA for all locations within an extended
addressable VSAM data set.
You can access the field __amrc->__RBA, as shown in< xref refid="gvs1">. This
example code (CCNGVS1) can be converted to use __amrc->__XRBA with just a few
modifications. For more information about the __amrc structure, refer to Chapter 18,
#include <stdio.h>
#include <stdlib.h>
main() {
FILE *ESDSfile;
unsigned int myRBA;
char recbuff[100]="This is record one.";
int w_retcd;
int l_retcd;
int r_retcd;
printf("calling fopen(\"dd:esdsclus\",\"rb+,type=record\");\n");
ESDSfile = fopen("dd:esdsclus", "rb+,type=record");
printf("fopen() returned 0X%.8x\n",ESDSfile);
if (ESDSfile==NULL) exit;
return(0);
}
This section describes considerations for using fopen() and freopen() with VSAM
files. Remember that a VSAM file must exist and be defined as a VSAM cluster
before you call fopen().
File names for MVS data sets: Using a data set name
The following diagram shows the syntax for the filename argument on your fopen()
or freopen() call:
qualifier
// ' '
qualifier1.qualifier2
' Single quotation marks indicate that you are passing a fully-qualified data set
name, that is, one which includes the high-level qualifier. If you pass a data set
name without single quotation marks, the z/OS XL C/C++ compiler prefixes the
high-level qualifier (usually the user ID) to the name. See Chapter 10,
Performing OS I/O operations, on page 81 for information on fully qualified
data set names.
// Specifying these slashes indicates that the file names refer to MVS data sets.
qualifier
Each qualifier is a 1- to 8-character name. These characters may be
alphanumeric, national ($, #, @), the hyphen, or the character \xC0. The first
character should be either alphabetic or national. Do not use hyphens in names
for RACF-protected data sets.
You can join qualifiers with periods. The maximum length of a data set name is
generally 44 characters, including periods.
To open a data set by its name, you can code something like the following in your
C or C++ program:
infile=fopen("VSAM.CLUSTER1", "ab+, type=record");
If your data set is VSAM.CLUSTER1, your C or C++ program refers to this data set by
the ddname CFILE, and you want exclusive control of the data set for update, you
can write the DD statement:
//CFILE DD DSNAME=VSAM.CLUSTER1,DISP=OLD
FILE *infile;
To share your data set, use DISP=SHR on the DD statement. DISP=SHR is the default
for fopen() calls that use a data set name and specify any of the r,rb, rb+, and
r+b open modes.
Note: z/OS XL C/C++ does not check the value of shareoptions at fopen() time,
and does not provide support for read-integrity and write-integrity, as required to
share files under shareoptions 3 and 4.
Note: If a "key out of sequence" condition is encountered, the data set will
automatically be reopened with a mode string "ab+" and will no longer be in
create mode.
ab Open for writing.
rb+ or r+b
Open for reading, writing, and/or updating.
wb+ or w+b
Open for reading, writing, and/or updating. If the cluster is defined as
reusable, the existing contents of the cluster are destroyed. If the cluster is
defined as not reusable (clusters with paths are, by definition, not reusable),
the fopen() fails. However, if the cluster has been defined but not loaded,
this mode can be used to do the initial load of both reusable and non
reusable clusters.
ab+ or a+b
Open for reading, writing, and/or updating.
For text files, you can specify the following modes: r, w, a, r+, w+, and a+.
Note: For KSDS, KSDS AIX and ESDS AIX in text and binary I/O, the only valid
modes are r and rb, respectively.
Keyword descriptions
recfm=
Any values passed into fopen() are ignored.
lrecl= and blksize=
These keywords are set to the maximum record size of the cluster as
initialized in the cluster definition. Any values passed into fopen() are
ignored.
space=
This keyword is not supported under VSAM.
type=
If you use the type= keyword, the only valid value for VSAM data sets is
type=record. This opens a file for record I/O.
acc= For VSAM files opened with the keyword type=record, you can specify the
direction by using the acc=access_type keyword on the fopen() function
call. For text and binary files, the access direction is always forward.
Attempts to open a VSAM data set with acc=BWD for either binary or text
stream I/O will fail. The access_type can be one of the following:
FWD The acc=FWD keyword specifies that the file be processed in a
forward direction. When the file is opened, it will be positioned at
the beginning of the first physical record, and any subsequent read
operations sets the file position indicator to the beginning of the
next record. The default value for the access keyword is acc=FWD.
Note: When opening paths, records with duplicate alternate index keys are
processed in order of arrival time (oldest to newest) regardless of the
current processing direction.
password=
VSAM facilities provide password protection for your data sets. You access
a data set that has password protection by specifying the password on the
password keyword parameter of the fopen() function call; the password
resides in the VSAM catalog entry for the named file. There can be more
than one password in the VSAM catalog entry; data sets can have different
passwords for different levels of authorization such as reading, writing,
updating, inserting, or deleting. For a complete description of password
protection on VSAM files, see the list of publications given on DFSMS on
page 1027.
The password keyword has the following form, where x is a 1- to
8-character password, and n is the exact number of characters in the
password. The password can contain special characters such as blanks
and commas.
password=nx
If a required password is not supplied, or if an incorrect password is given,
fopen() fails.
asis This keyword is not supported for VSAM.
byteseek
When you specify this keyword and open a file in binary stream mode,
fseek() and ftell() use relative byte offsets from the beginning of the file.
This is the default setting.
noseek
This keyword is ignored for VSAM data sets.
OS This keyword is ignored for VSAM data sets.
rls= Indicates the VSAM RLS/TVS access mode in which a VSAM file is to be
opened. This keyword is ignored for non-VSAM files. The following values
are valid:
v nri No Read Integrity
v cr Consistent Read
v cre Consistent Read Explicit
To find out how to optimize VSAM performance by controlling the number of VSAM
buffers used for your data set, refer to z/OS DFSMS Access Method Services for
Catalogs.
typedef struct {
#ifndef _LP64
unsigned int __fill, /* version: either 0 or 1 */
__recnum; /* the key, starting at 1 */
#else
unsigned long __fill, /* version: either 0 or 1 */
__recnum; /* the key, starting at 1 */
#endif /* not _LP64 */
} __rrds_key_type;
In your source program, you can define an RRDS record structure as either:
or:
struct {
__rrds_key_type rrds_key; /* __fill value always 1 */
char *data;
} rrds_rec_1;
The z/OS XL C/C++ library recognizes which type of record structures you have
used by the value of rrds_key.__fill. Zero indicates that the data is contiguous
with rrds_key and 1 indicates that a pointer to the data follows rrds_key.
fread() reads one record from the system from the current file position. Thus, if
you want to read a certain record, you can call flocate() to position the file pointer
to point to it; the subsequent call to fread() reads in that record.
If you use an fread() call to request more bytes than the record about to be read
contains, fread() reads the entire record and returns the number of bytes read. If
you use fread() to request fewer bytes than the record about to read contains,
fread() reads the number of bytes that you specified and returns your request.
z/OS XL C/C++ VSAM Record I/O does not allow a read operation to immediately
follow a write operation without an intervening reposition. z/OS XL C/C++ treats the
following as read operations:
v Calls to read functions that request 0 bytes
v Read requests that fail because of a system error
v Calls to the ungetc() function
Calling fread() several times in succession, with no other operations on this file in
between, reads several records in sequence (sequential processing), which can be
forward or backward, depending on the access direction, as described in the
following.
v KSDS, KSDS AIX and ESDS AIX
The records are retrieved according to the sequence of the key of reference, or
in reverse key sequence.
Note: Records with duplicate alternate index keys are processed in order of
arrival time (oldest to newest) regardless of the current processing direction
v ESDS
The records are retrieved according to the sequence they were written to the file
(entry sequence), or in reverse entry sequence.
In general, C I/O does not allow a write operation to follow a read operation without
an intervening reposition or fflush(). z/OS XL C/C++ counts a call to a write
function writing 0 bytes or a write request that fails because of a system error as a
write operation. However, z/OS XL C/C++ VSAM record I/O allows a write to directly
follow a read. This feature has been provided for compatibility with earlier releases.
The process of writing to a data set for the first time is known as initial loading.
Using the fwrite() function, you can write to a new VSAM file in initial load mode
just as you would to a file not in initial load mode. Writing to a KSDS PATH or an
ESDS PATH in initial load mode is not supported.
If your fwrite() call does not try to write more bytes than the maximum record
size, fwrite() writes a record of the length you asked for and returns your request.
If your fwrite() call asks for more than the maximum record size, fwrite() writes
the maximum record size, sets errno, and returns the maximum record size. In
either case, the next call to fwrite() writes to the following record.
Note: If an fwrite() fails, you must reposition the file before you try to read or
write again.
v KSDS, KSDS AIX
Records are written to the cluster according to the value stored in the field
designated as the prime key.
You can load a KSDS in any key order but it is most efficient to perform the
fwrite() operations in key sequence.
v ESDS, ESDS AIX
Records are written to the end of the file.
v RRDS
Deleting records
To delete records, use the library function fdelrec(), a z/OS XL C/C++ extension to
the SAA C library. For more information on this function, see z/OS XL C/C++
Run-Time Library Reference.
v KSDS, KSDS PATH, and RRDS
To delete records, you must perform the following operations:
1. Open the VSAM file in update mode (rb+/r+b, ab+/a+b, or wb+/w+b specified
as the required positional parameter of the fopen() function call and
type=record).
2. If the file is not already positioned at the record you want to delete, reposition
to that record.
3. Read the record using the fread() function.
Once the record you want to delete has been read in, you must ensure that
no reading, writing, or repositioning operations are performed before
fdelrec().
4. Delete the record using the fdelrec() function.
Note: If the data set was opened with an access mode of rb+ or r+b, a read
operation can result in the locking of control intervals, depending on
shareoptions specification of the VSAM file. If after reading a record, you decide
not to delete it, you may need to unlock a control interval by performing a
file-positioning operation to the same record, such as an flocate() using the
same key.
v ESDS and ESDS PATH
VSAM does not support deletion of records in ESDS files.
flocate()
The flocate() C library function can be used to locate a specific record within a
VSAM data set given the key, relative byte address, or the relative record number.
The flocate() function also sets the access direction.
VSAM extended addressability support includes an 8 byte RBA for use with
positioning functions such as flocate(). flocate() supports RBA lengths of 4 and
8 bytes. Existing applications that use flocate() with a 4 byte RBA will continue
unaffected, but must use a key length of 8 to locate an RBA beyond 4GB.
The following flocate() parameters all set the access direction to backward and are
only valid for record I/O:
v __KEY_LAST (the key and key_len parameters are ignored)
v __KEY_EQ_BWD
v __RBA_EQ_BWD
Note: The __RBA_EQ and __RBA_EQ_BWD parameters are not valid for paths and are
not recommended for KSDS and RRDS data sets.
You can use the rewind() library function instead of calling flocate() with
__KEY_FIRST.
v KSDS, KSDS AIX, and ESDS AIX
The key parameter of flocate() for the options __KEY_EQ, __KEY_GE, and
__KEY_EQ_BWD is a pointer to the key of reference of the data set. The key_len
parameter is the key length as defined for the data set for a full key search, or
less than the defined key length for a generic key search (a partial key match).
For KSDSs, __RBA_EQ and __RBA_EQ_BWD are supported, but are not
recommended.
For __KEY_EQ_BWD the key_len parameter must be equal to the key length as
defined for the data set for a full key search.
Alternate indexes do not allow positioning by RBA.
v ESDS
The key parameter of flocate() is a pointer to the specified RBA value. The
key_len parameter is either 4 or 8 depending on the size of the RBA.
v RRDS
For __KEY_EQ, __KEY_GE, and __KEY_EQ_BWD, the key parameter of flocate() is a
pointer to an unsigned long integer containing the specified relative record
number. The key_len parameter is sizeof(unsigned long). For __RBA_EQ and
__RBA_EQ_BWD, the key parameter of flocate() is a pointer to the specified RBA.
However, seeking to RBA values is not recommended, because it is not
supported across control intervals. The key_len parameter is either 4 or 8
depending on the size of the RBA.
ftell() and fseek() offsets in record mode I/O are relative record offsets. For
example, the following call moves the file position to the start of the previous
record:
fseek(fp, -1L, SEEK_CUR);
You cannot use fseek() to reposition to a file position before the beginning of the
file or to a position beyond the end of the file.
rewind()
The rewind() function repositions the file position to the beginning of the file, and
clears the error setting for the file. rewind() does not reset the file access direction.
For example, a call to flocate() with __KEY_LAST sets the file pointer to the end of
the file and sets the access direction to backwards. A subsequent call to rewind()
sets the file pointer to the beginning of the file, but the access direction remains
backwards.
Notes:
1. The saved position is based on the relative position of the record within the data set. Subsequent insertions or deletions may
invalidate the saved position.
2. The saved position is based on the RBA of the record. Subsequent insertions, deletions or updates may invalidate the saved
position.
The C/C++ run-time library provides the following support for VSAM RLS/TVS:
v Specification of RLS/TVS-related keywords in the mode string of fopen() and
freopen().
v Specification of RLS/TVS-related text unit key values in the __dyn_t structure,
which is used as input to the dynalloc() function.
v Provides the application with VSAM return and reason codes for VSAM I/O
errors.
v Performs implicit positioning for files opened for RLS/TVS access.
VSAM RLS/TVS has three read integrity file access modes. These modes tell
VSAM the level of locking to perform when records are accessed within a file that
has not been opened in update mode. The access modes are:
nri No Read Integrity indicates that requests performed by the application are
not to be serialized with updates or erases of the records by other calling
programs. VSAM accesses the records without obtaining a lock on the
record.
cr Consistent Read indicates that requests performed by the application are to
be serialized with updates or erases of the records by other calling
programs. VSAM obtains a share lock when accessing the record. This lock
is released once the record has been returned to the caller.
cre Consistent Read Explicit indicates that requests performed by the
application are to be serialized with updates or erases of the records by
other requestors.VSAM obtains a share lock when accessing the record.
This lock is held until the application commits its changes. This ensures that
records read by the application are not changed by other requestors until
the application commits or aborts its changes. Consistent Read Explicit is
for use only by commit protocol applications.
VSAM RLS locks records to support record integrity. An application may wait for an
exclusive record lock if another user has the record locked. The application is also
subject to new locking errors such as deadlock or timeout errors.
If the file has been opened in update mode, and RLS=CR or RLS=CRE is specified,
VSAM also serializes access to the records within the file. However, the type of
serialization differs from non-update mode in the following ways:
v A reposition within the file causes VSAM to obtain a share lock for the record.
v A read of a record causes VSAM to obtain an exclusive lock for the record. The
lock is held until the record is updated in the file, or another record is read. If
RLS=CRE is specified (for commit protocol applications), the lock is held until the
application commits or aborts its changes.
Notes:
1. When a file is opened, it is implicitly positioned to the first record to be
accessed.
Error reporting
Errors are reported through the __amrc structure and the SIGIOERR signal. The
following are additional considerations for error reporting in a VSAM RLS
application:
v VSAM RLS/TVS uses the SMSVSAM server address space. When a file open
fails because the server is not available, the C run-time library places the error
return code and error value in the __amrc structure, and returns a null file
descriptor. Record management requests return specific error return/reason
codes, if the SMSVSAM server is not available. The server address space is
automatically restarted. To recover from this type of error, an application should
first close the file to clean up the file status, and then open the file prior to
attempting record management requests. The close for the file returns a return
code of 4, and an error code of 170(X'AA'). This is the expected result. It is not
an error.
v Opening a recoverable file for output is not supported. If you attempt to do so,
the open will fail with error return code 255 in the __amrc structure.
v Some of the VSAM errors, that are reported in the __amrc structure, are
situations from which an application can recover. These are problems that can
occur unpredictably in a sharing environment. Usually, the application can
recover by simply accessing another record. Examples of such errors are the
following:
RC 8, 21(X'15'): Request cancelled as part of deadlock resolution.
RC 8, 22(X'16'): Request cancelled as part of timeout resolution.
RC 8, 24(X'18'): Request cancelled because transaction backout is pending
on the requested record.
RC 8, 29(X'14'): Intra-luwid contention between threads under a given TCB.
The application can intercept errors by registering a condition handler for the
SIGIOERR condition. Within the condition handler, the application can examine
the information in the __amrc structure and determine how to recover from each
specific situation.
Restriction: z/OS XL C/C++ does not support XADDR for ESDS alternate indexes.
VSAM XADDR support includes an 8 byte relative byte address for use with
positioning functions such as flocate(). flocate() supports key lengths of 4 and 8
bytes. Existing applications that use flocate() to locate with a 4 byte relative byte
address will continue unaffected, but must use a key length of 8 to locate a record
within XADDR addresses.
The RBA field in the __amrc structure is set to -1 when applications access beyond
the addresses that can be represented by the 4 byte value, effectively appearing to
be EOF to any 4 byte RBA positioning (flocate()) calls. The __XRBA field will always
be updated with the address, and must be used in these cases.
For AMODE 31 applications repositioning within a VSAM data set, users of ftell()
and fseek() that need to access XADDR addresses, must use the large file version
of ftello() and fseeko() .
Note: AMODE 64 applications also have the above restrictions on XADDR support.
For complete details on these library functions, see z/OS XL C/C++ Run-Time
Library Reference.
VSAM extended addressability support includes an 8 byte RBA for use with
positioning functions such as flocate(). flocate() supports RBA lengths of 4 and
8 bytes. Existing applications that use flocate() with a 4 byte RBA will continue
unaffected, but must use a key length of 8 to locate an RBA beyond 4GB.
The following flocate() parameters all set the access direction to backward and are
not valid for text and binary I/O, because backwards access is not supported:
v __KEY_LAST (the key and key_len parameters are ignored)
v __KEY_EQ_BWD
v __RBA_EQ_BWD
You can use the rewind() library function instead of calling flocate() with
__KEY_FIRST.
v KSDS, KSDS AIX, and ESDS AIX
The key parameter of flocate() for the options __KEY_EQ and __KEY_GE is a
pointer to the key of reference of the data set. The key_len parameter is the key
length as defined for the data set for a full key search, or less than the defined
key length for a generic key search (a partial key match).
Alternate indexes do not allow positioning by RBA.
Note: The __RBA_EQ parameter is not valid for paths and is not recommended.
v ESDS
The key parameter of flocate() is a pointer to the specified RBA value. The
key_len parameter is either 4 or 8 depending on the size of the RBA.
v RRDS
For __KEY_EQ and __KEY_GE, the key parameter of flocate() is a pointer to an
unsigned long integer containing the specified relative record number. The
key_len parameter is sizeof(unsigned long). For __RBA_EQ, the key parameter of
flocate() is a pointer to the specified RBA. However, seeking to RBA values is
not recommended, because it is not supported across control intervals. The
key_len parameter is either 4 or 8 depending on the size of the RBA.
For AMODE 31 applications repositioning within a VSAM data set, users of ftell()
and fseek() that need to access positions beyond 4GB, must use the large file
version of ftello() and fseeko() .
Table 26 provides a summary of the fseek() and ftell() parameters in binary and
text.
Table 26. Summary of fseek() and ftell() parameters in text and binary
Type Mode ftell() return fseek() SEEK_CUR SEEK_END
values SEEK_SET
KSDS Binary relative byte offset relative byte offset relative byte offset relative byte offset
Text not supported zero only relative byte offset relative byte offset
ESDS Binary relative byte offset relative byte offset relative byte offset relative byte offset
Text not supported zero only relative byte offset relative byte offset
RRDS Binary encoded byte encoded byte relative byte offset relative byte offset
offset offset
Text encoded byte encoded byte relative byte offset relative byte offset
offset offset
PATH Binary not supported not supported not supported not supported
Text not supported not supported not supported not supported
Flushing buffers
You can use the C library function fflush() to flush data.
For text files, calling fflush() to flush an update to a record causes the new data
to be written to the file.
If you call fflush() while you are updating, the updates are flushed out to VSAM.
For ESDS binary files, if fclose() is called and there is a new record in the buffer
that is less than the maximum record size, this record is written to the file at its
current size. A new RRDS binary record that is incomplete when the file is closed is
filled with null characters to the record size.
A new ESDS or RRDS text record that is incomplete when the file is closed is
completed with a new-line.
Note: The __amrc struct is global and can be reset by another I/O operation (such
as printf()).
For definitions of these return codes and feedback codes, refer to the publications
listed in DFSMS on page 1027.
You can set up a SIGIOERR handler to catch read or write system errors. See
Chapter 18, Debugging I/O programs, on page 221 for more information.
VSAM examples
This section provides several examples of using I/O under VSAM.
KSDS example
The example in Figure 26 on page 174 shows a sample program (CCNGVS2) with
two functions from an employee record entry system with a mainline driver to
process selected options (display, display next, update, delete, create). The update
routine is an example of KSDS clusters, and the display routine is an example of
both KSDS clusters and alternate indexes.
For these examples, the clusters and alternate indexes should be defined as
follows:
v The KSDS cluster has a record size of 150 with a key length of 4 with offset 0.
v The unique KSDS AIX has a key length of 20 with an offset of 10.
v The non-unique KSDS AIX has a key length of 40 with an offset of 30.
Chapter 12. Performing VSAM I/O operations 173
The update routine is passed the following:
v data_ptr, which points to the information that is to be updated
v orig_data_ptr, which points to the information that was originally displayed using
the display option
v A file pointer to the KSDS cluster
By definition, the primary key is unique and therefore the employee number was
chosen for this key. The user_id is also a unique key; therefore, it was chosen as
the unique alternate index key. The name field may not be unique; therefore, it was
chosen as the non-unique alternate index key.
#include <stdio.h>
#include <string.h>
/* global definitions */
struct data_struct {
char emp_number[4];
char user_id[8];
char name[20];
char pers_info[37];
};
#define REC_SIZE 69
#define CLUS_KEY_SIZE 4
#define AIX_UNIQUE_KEY_SIZE 8
#define AIX_NONUNIQUE_KEY_SIZE 20
clearerr(fp);
rc = fread(buffer,1,REC_SIZE,fp);
if (rc != REC_SIZE || ferror(fp)) {
print_amrc();
printf("Error: reading old employee record failed\n");
return 40;
}
rc = fdelrec(fp);
if (rc != 0) {
print_amrc();
printf("Error: deleting old employee record failed\n");
return 50;
}
} /* end of checking for change in primary key */
else { /* Locate to current employee record */
rc = flocate(fp,&(data_ptr->emp_number),CLUS_KEY_SIZE,__KEY_EQ);
if (rc == 0) {
/* record exists, so update it */
rc = fread(buffer,1,REC_SIZE,fp);
if (rc != REC_SIZE || ferror(fp)) {
print_amrc();
printf("Error: reading old employee record failed\n");
return 60;
}
Figure 26. KSDS example (Part 3 of 5) Chapter 12. Performing VSAM I/O operations 177
178 z/OS V1R13.0 XL C/C++ Programming Guide
/* Non-unique Alternate Index Search */
else if (data_ptr->name[0] != \0) {
rc = flocate(aix_non_unique_fp,data_ptr->name,
AIX_NONUNIQUE_KEY_SIZE,__KEY_GE);
if (rc != 0) {
printf("Error: flocate with name failed\n");
return 30;
}
int main() {
FILE* clus_fp;
FILE* aix_ufp;
FILE* aix_nufp;
int i;
struct data_struct buf1, buf2;
char data[3][REC_SIZE+1] = {
" 1LARRY LARRY HI, IM LARRY, ",
" 2DARRYL1 DARRYL AND THIS IS MY BROTHER DARRYL, ",
" 3DARRYL2 DARRYL "
};
/* assume base cluster was loaded with at least one dummy record */
/* so aix could be defined */
aix_ufp = fopen("dd:aixuniq", "rb,type=record");
if (aix_ufp == NULL) {
print_amrc();
printf("Error: fopen(\"dd:aixuniq\"...) failed\n");
return 10;
}
/* assume base cluster was loaded with at least one dummy record */
/* so aix could be defined */
aix_nufp = fopen("dd:aixnuniq", "rb,type=record");
return 0;
}
The JCL in the sample code (CCNGVS3) in Figure 27 can be used to test the
example code in Figure 26 on page 174.
RRDS example
The sample program (CCNGVS4) in Figure 28 on page 184 illustrates the use of an
RRDS file. It performs the following operations:
1. Opens an RRDS file in record mode (the cluster must be defined)
2. Writes three records (RRN 2, RRN 10, and RRN 32)
3. Sets the file position to the first record
4. Reads the first record in the file
5. Deletes it
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <env.h>
struct rrds_struct {
__
rrds_key_type rrds_key;
char *rrds_buf;
};
main() {
FILE *fileptr;
RRDS_STRUCT RRDSstruct;
RRDS_STRUCT *rrds_rec = &RRDSstruct;
char buffer1[80] =
"THIS IS THE FIRST RECORD IN THE FILE. I"
"T WILL BE WRITTEN AT RRN POSITION 2. ";
char buffer2[80] =
"THIS IS THE SECOND RECORD IN THE FILE. I"
"T WILL BE WRITTEN AT RRN POSITION 10. ";
char buffer3[80] =
"THIS IS THE THIRD RECORD IN THE FILE. I"
"T WILL BE WRITTEN AT RRN POSITION 32. ";
char outputbuf[80];
unsigned long flocate_key = 0;
/*------------------------------------------------------------------*/
/*| select RRDS record structure 2 by setting __fill to 1 */
/*| */
/*| 1. open an RRDS file record mode (the cluster must be defined) */
/*| 2. write three records (RRN 2, RRN 10, RRN 32) */
/*------------------------------------------------------------------*/
rrds_rec->rrds_key.__fill = 1;
rrds_rec->rrds_key.__recnum = 10;
rrds_rec->rrds_buf = buffer2;
fwrite(rrds_rec,1,88, fileptr);
rrds_rec->rrds_key.__recnum = 32;
rrds_rec->rrds_buf = buffer3;
fwrite(rrds_rec,1,88, fileptr);
memset(outputbuf,0x00,80);
rrds_rec->rrds_buf = outputbuf;
fdelrec(fileptr);
/*------------------------------------------------------------------*/
/*| 6. locate last record in file and set access direction backwards*/
/*| 7. read the record */
/*| 8. update the record */
/*------------------------------------------------------------------*/
flocate(fileptr, &flocate_key,; sizeof(unsigned long), __KEY_LAST);
memset(outputbuf,0x00,80);
rrds_rec->rrds_buf = outputbuf;
memset(outputbuf,0x00,80);
memcpy(outputbuf,"THIS IS THE UPDATED STRING... ",30);
fupdate(rrds_rec,88,fileptr);
/*------------------------------------------------------------------*/
/*| 9. set _EDC_RRDS_HIDE_KEY environment variable */
/*|10. read the next record in sequence (ie. RRN 10) into a */
/*| + character string */
/*------------------------------------------------------------------*/
setenv("_EDC_RRDS_HIDE_KEY","Y",1);
memset(outputbuf,0x00,80);
fread(outputbuf, 1, 80, fileptr);
printf("The middle record in the file (read into char string):\n");
printf("%80s\n\n",outputbuf);
fclose(fileptr);
}
fldata() behavior
The format of the fldata() function is as follows:
The fldata() function is used to retrieve information about an open stream. The
name of the file is returned in filename and other information is returned in the
__device_t __device; /* */
unsigned long __blksize, /* */
__maxreclen; /* */
union { /* */
struct { /* */
unsigned short __vsam_type; /* */
unsigned long __vsam_keylen; /* */
unsigned long __vsam_RKP; /* */
} __vsam; /* */
#if __EDC_TARGET >= 0x41080000 /* */
struct { /* */
unsigned char __disk_access_method; /* */
unsigned char __disk_noseek_to_seek; /* */
long __disk_reserve[2]; /* */
} __disk;
#endif
} __device_specific;
char * __dsname; /* */
unsigned int __reserve4; /* */
};
typedef struct __fileData fldata_t;
Figure 29. fldata() structure Chapter 12. Performing VSAM I/O operations 187
Notes:
1. If you have opened the file by its data set name, the filename is fully qualified,
including quotation marks. If you have opened the file by ddname, filename is
dd:ddname, without any quotation marks. The ddname is uppercase.
2. The __dsname field is filled in with the data set name. The __dsname value is
uppercase unless the asis option was specified on the fopen() or freopen()
function call.
Note: You cannot use the z/OS XL C/C++ I/O functions for terminal I/O under
either IMS or CICS. Terminal I/O under CICS is supported through the CICS
command level interface.
This chapter describes C I/O stream functions as they can be used within C++
programs. If you want to use the C++ I/O stream classes instead, see Chapter 4,
Using the Standard C++ Library I/O Stream Classes, on page 21 for general
information. For more detailed information, see Standard C++ Library Reference,
which discusses the Standard C++ I/O stream classes.
Opening files
You can use the library functions fopen() or freopen() to open a file.
Terminal files opened in append mode are treated as if they were opened in write
mode.
recfm=
z/OS XL C/C++ allows you to specify any of the 27 possible RECFM types
(listed in Fixed-format records on page 10, Variable-format records on
page 13, and Undefined-format records on page 16). The default is
recfm=U. Any specification of ASA for the record format is ignored.
lrecl= and blksize=
The lrecl and blksize parameters allow you to set the record size and
block size, respectively. The maximum limits on lrecl values are as follows:
32771 For input z/OS variable terminals (data length of 32767)
32767 For input z/OS fixed and undefined terminals
32770 For output z/OS variable terminals (data length of 32766)
32766 For output z/OS fixed and undefined terminals
In fixed and undefined terminal files, blksize is always the size of lrecl. In
variable terminal files, blksize is always the size of lrecl plus 4 bytes. It is
not necessary to specify values for lrecl and blksize. If neither is
specified, the default values are used. The default lrecl sizes (not
including the extra 4 bytes in the lrecl of variable length types) are as
follows:
v Screen width for output terminals
v 1000 for input z/OS text terminals
v 254 for all other input terminals
space=
This parameter is accepted as an option for terminal I/O, but it is ignored. It
does not generate an error.
type=
type=record specifies that the file is to be opened for sequential record I/O.
The file must be opened as a binary file.
acc= This parameter is not valid for terminal I/O. If you specify it, your fopen()
call fails.
When you perform input and output in an interactive mode with the terminal, all
standard streams and all files with * as the first character of their names are
associated with the terminal. Output goes to the screen; input comes from the
keyboard.
An input EOF can be generated by a /* if you open a stream in text mode. If you
open the stream in binary or record mode, you can generate an EOF by entering a
null string.
Buffering
z/OS XL C/C++ uses buffers to map byte-level I/O (data stored in records and
blocks) to system-level C I/O.
The setvbuf() and setbuf() functions can be used to control buffering before any
read or write operation to the file. If you want to reset the buffering mode, you must
call setvbuf() or setbuf() before any other operation occurs on a file, because you
cannot change the buffering mode after an I/O operation to the file.
You can set up a SIGIOERR handler to catch read or write system errors. See
Chapter 18, Debugging I/O programs, on page 221 for more information.
A call to the rewind() function clears unread input data in the terminal buffer so that
on the next read request, the system waits for more user input.
Under TSO, the virtual line size of the terminal is used to determine the line length.
When reading from the terminal and the RECFM has been set to be F (for example,
by an ALLOCATE under TSO) in binary or record mode, the input is padded with
blanks to the record length.
On input, all terminal files opened for output flush their output, no matter what type
of file they are and whether a record is complete or not. This includes fixed terminal
files that would normally withhold output until a record is completed, as well as text
records that normally wait until a new-line or carriage return. In all cases, the data
is placed into one line with a blank added to separate output from different terminal
files. Fixed terminal files do not pad the output with blanks when flushing this way.
Note: This flush is not the same as a call to fflush(), because fixed terminal files
do not have incomplete records and text terminal files do not output until the
new-line or carriage return. This flush occurs only when actual input is required
from the terminal. When data is still in the buffer, that data is read without flushing
output terminal files.
Writing to files
You can use the following library functions to write to a terminal file; see z/OS XL
C/C++ Run-Time Library Reference for more information on these library functions.
v fwrite()
v fwrite_unlocked()
v printf()
v printf_unlocked()
v fprintf()
v fprintf_unlocked()
v vprintf()
v vprintf_unlocked()
If no record length is specified for the output terminal file, it defaults to the virtual
line size of the terminal.
On output, records are written one line at a time up to the record length. For all
output terminal files, records are not truncated. If you are printing a long string, it
wraps around to another line.
Flushing records
The action taken by the fflush() library function depends on the file mode. The
fflush() function only flushes buffers in binary files with Variable or Undefined
record format.
If you call one z/OS XL C/C++ program from another z/OS XL C/C++ program by
using the ANSI system() function, all open streams are flushed before control is
passed to the callee, and again before control is returned to the caller. If you are
running with POSIX(ON), a call to the POSIX system() function does not flush any
streams to the system.
Text streams
v Writing a new record:
Because a new-line character has not been encountered to indicate the
end-of-line, fflush() takes no action. The record is written as a new record
when one of the following takes place:
A new-line character is written.
The file is closed.
v Reading a record:
fflush() clears a previous ungetc() character.
Binary streams
v Writing a new record:
Record I/O
v Writing a new record: fflush() takes no action.
v Reading a record: fflush() takes no action.
You can also use rewind() when reading from the terminal to flush out your record
buffer for that stream.
Closing files
Use the fclose() library function to close a file. z/OS XL C/C++ automatically
closes files on normal program termination and attempts to do so under abnormal
program termination or abend. When closing a fixed binary terminal, z/OS XL
C/C++ pads the last record with blanks if it is incomplete.
See z/OS XL C/C++ Run-Time Library Reference for more information on this
library function.
fldata() behavior
The format of the fldata() function is as follows:
The fldata() function is used to retrieve information about an op