Transferring Save Files
by Bruce Guetzkow
The code for this article is available for download.
In addition to transferring physical file data to and from the Integrated File System (IFS), which I covered a year ago in this newsletter (see "Better Data Transfers"), it is sometimes desirable to transfer data that has been placed into a save file. Copying a save file to the IFS makes it possible to attach data to an email. You can then easily share objects with a colleague or with IBM for aid in problem resolution. I have developed two commands that simplify this task: SAVSAVFIFS (Save Save File to IFS) and RSTSAVFIFS (Restore Save File from IFS).
Saving Save Files
To create a save file, use the CRTSAVF (Create Save File) command. To populate the save file, use any of the standard IBM commands, such as SAVOBJ (Save Object), SAVLIB (Save Library), or SAV (Save Object). Now that you have a save file containing data, you can copy it to the IFS.
The SAVSAVFIFS command has just two parameters:
- Qualified name of a save file to be copied to the IFS
- Complete path name of the IFS stream file to create or replace
Let's take a look at the command processing program (CPP) for this command to see how the data is copied. Source member SAVSAVFIFS in yourlib/QCLLESRC begins by parsing the qualified name of the save file passed from the command into separate fields for library and file names. Next, the CHKOBJ (Check Object) command is used to confirm that the save file exists. If the file does not exist, the CL program issues escape message CPF9897. You can monitor for this message in your own programs.
The program continues by using the RTVOBJD (Retrieve Object Description) command to determine the actual library name if either *LIBL or *CURLIB was specified on the SAVSAVFIFS command. The actual library name is required for the next step.
Now it is time to copy the save file to the IFS. The copy is accomplished using the CPYTOSTMF (Copy to Stream File) command. Before this command is executed it is necessary to first convert the name of the save file from the "library/object" naming convention common to most iSeries developers into its equivalent IFS path name: /QSYS.LIB/library.LIB/object.FILE.
The last step in the process is to call C's stat function to confirm that the IFS file has been created. As with most C functions, parms are passed as null-terminated strings. If the return value from the stat function is anything other than zeros, the file was not created and escape message CPF9897 is again issued.
Restoring Save Files
- Complete path name of the IFS stream file to restore
- Qualified name of the save file to be restored from the IFS
Source member RSTSAVFIFS in yourlib/QCLLESRC is the CPP for this command. Processing begins by confirming that the IFS object exists, again using the stat function. The save file name is then parsed for library and file name and CHKOBJ is used to confirm that the save file exists.
RTVOBJD is once again used to retrieve the actual save file library name. This time the CPYFRMSTMF command is used to copy the save file from the IFS back to the library and file name specified.
Creating the Objects
To create the programs and commands described above execute the following commands:
If you wanted to get fancy, you could add the ENDPGM label so the user doesn't wonder what happened:
CHGVAR VAR(&ERRMSG) +
VALUE('SAVSAVFIFS command ended abnormally. See job log')
SNDPGMMSG MSGID(CPF9897) +
You could also add the following immediately before ENDPGM:
SNDPGMMSG MSG('SAVSAVFIFS completed normally.') +
Points to Consider
I've kept the CPPs for both commands very simple, but there are a few things to keep in mind.
When validating the existence of the save file, I am only using the CHKOBJ command to determine if there is a *FILE object. The iSeries has many different flavors of file: physical, logical, display, and so forth. If you want to be certain that only save files can be used with this command, you can easily modify the RTVOBJD command to return the OBJATR (Object Attribute) parameter and confirm that it contains the value SAVF. You can then issue escape message CPF9897 with an appropriate error message so a calling program can trap the error condition.
With the CPYTOSTMF command, I specified a value of *REPLACE for the STMFOPT (Stream File Option). In the event that the file already exists on the IFS, the file will be replaced upon execution of the SAVSAVFIFS command. Likewise, I used *REPLACE for the MBROPT (Member Option) parameter of the CPYFRMSTMF command in the RSTSAVFIFS command. When restoring a save file from the IFS, data in an existing save file will be replaced by the contents found in the IFS file. You could add parameters to each command to allow a user to specify whether replacing an existing object is acceptable.
If you have configured your iSeries as part of a network, these commands can also be used to transfer a save file to or from a network server. The path to a network drive is /qntc/server-name/share-name/folders/file.ext.
As I indicated at the start of this article, transferring data to a file in the IFS simplifies attaching data to an email. This is certainly a potential security risk, so you should consider securing these commands accordingly.
Putting It to Work
With these two new commands, you can simplify sending data between two iSeries systems or consolidating backups into a folder in the IFS. I also like the fact that these commands successfully hide the CPYTOSTMF and CPYFRMSTMF commands with their confusing array of parameters. Feel free to use them as they are or with some of the modifications suggested, as long as they simplify your data transfers.
Bruce Guetzkow has programmed on the AS/400 and iSeries since 1990, in manufacturing, distribution, and other industries. He is currently the IS director at United Credit Service in Elkhorn, Wisconsin. Click here to contact Bruce by e-mail.