SAVF の中身を正確に調べたいときに、DSPSAVF
コマンドによって
SAVF にどのようなオブジェクトが保管されているかは知ることはできるのだが
直接、SAVF をダンプすることはできない。
SAVF のダンプを調査するような高度な解析を行なうときに便利な解析ツールとなるのが
ここで紹介する CPYSAVF
コマンドである。
CPYSAVF コマンドは SAVF を物理ファイルにコピーするだけでなく、逆のパターンとして
物理ファイルから SAVF へコピーすることもできる。
もちろん SAVF 同士をコピーし合うこともできる。
SAVF とは実は 528 バイト長の単なる物理ファイルである。
しかし CPYF コマンドを始めとする ユーティリティーを使って SAVF を操作することはできない。
DSPPFM コマンドを使って SAVF をダンプすることもできない。
そこでここで紹介する CPYSAVF コマンドを使って 528 バイトの物理ファイルにコピーしてしまえば
DSPPFM コマンド等を使って自由に SAVF の内容を解析することができるようになる。
001.00 CMD PROMPT('*SAVF コピー ') 002.00 PARM KWD(FRMFILE) TYPE(FRMFILE) + 003.00 PROMPT(' 取出しファイル ') 004.00 FRMFILE: QUAL TYPE(*NAME) LEN(10) MIN(1) 005.00 QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + 006.00 SPCVAL((*LIBL) (*CURLIB)) + 007.00 PROMPT(' ライブラリー ') 008.00 PARM KWD(TOFILE) TYPE(TOFILE) + 009.00 PROMPT(' 受入れファイル ') 010.00 TOFILE: QUAL TYPE(*NAME) LEN(10) MIN(1) 011.00 QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + 012.00 SPCVAL((*LIBL) (*CURLIB)) + 013.00 PROMPT(' ライブラリー ')
CRTCMD CMD(MYLIB/CPYSAVF) PGM(MYLIB/CPYSAVFCL) SRCFILE(MYSRCLIB/QCMDSRC) AUT(*ALL)
0001.00 PGM PARM(&FRMFILLIB &TOFILLIB) 0002.00 /*---------------------------------------------------------*/ 0003.00 /* CPYSAVF : *SAVF コピー */ 0004.00 /*---------------------------------------------------------*/ 0005.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(80) 0006.00 DCL VAR(&FRMFILLIB) TYPE(*CHAR) LEN(20) 0007.00 DCL VAR(&FRMFIL) TYPE(*CHAR) LEN(10) 0008.00 DCL VAR(&FRMLIB) TYPE(*CHAR) LEN(10) 0009.00 DCL VAR(&TOFILLIB) TYPE(*CHAR) LEN(20) 0010.00 DCL VAR(&TOFIL) TYPE(*CHAR) LEN(10) 0011.00 DCL VAR(&TOLIB) TYPE(*CHAR) LEN(10) 0012.00 DCL VAR(&OBJATR) TYPE(*CHAR) LEN(10) 0013.00 DCL VAR(&STSMSG) TYPE(*CHAR) LEN(128) 0014.00 MONMSG MSGID(CPF0000 RNX9000 CEE9900) EXEC(GOTO + 0015.00 CMDLBL(ERROR)) 0016.00 0017.00 CHGVAR VAR(&FRMFIL) VALUE(%SST(&FRMFILLIB 1 10)) 0018.00 CHGVAR VAR(&FRMLIB) VALUE(%SST(&FRMFILLIB 11 10)) 0019.00 CHGVAR VAR(&TOFIL) VALUE(%SST(&TOFILLIB 1 10)) 0020.00 CHGVAR VAR(&TOLIB) VALUE(%SST(&TOFILLIB 11 10)) 0021.00 RTVOBJD OBJ(&TOLIB/&TOFIL) OBJTYPE(*FILE) + 0022.00 OBJATR(&OBJATR) 0023.00 IF COND(&OBJATR *EQ 'SAVF ') THEN(DO) 0024.00 CLRSAVF FILE(&TOLIB/&TOFIL) 0025.00 ENDDO 0026.00 IF COND(&OBJATR *EQ 'PF ') THEN(DO) 0027.00 CLRPFM FILE(&TOLIB/&TOFIL) 0028.00 ENDDO 0029.00 CHGVAR VAR(&STSMSG) VALUE(&FRMLIB *TCAT '/' *CAT + 0030.00 &FRMFIL *TCAT ' をコピー中です。 ') 0031.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&STSMSG) + 0032.00 TOPGMQ(*EXT) MSGTYPE(*STATUS) 0033.00 OVRDBF FILE(FRMSAVF) TOFILE(&FRMLIB/&FRMFIL) + 0034.00 OVRSCOPE(*JOB) 0035.00 OVRDBF FILE(TOSAVF) TOFILE(&TOLIB/&TOFIL) + 0036.00 OVRSCOPE(*JOB) 0037.00 CALL PGM(CPYSAVF) 0038.00 DLTOVR FILE(FRMSAVF) LVL(*JOB) 0039.00 DLTOVR FILE(TOSAVF) LVL(*JOB) 0040.00 SNDPGMMSG MSG(&FRMLIB *TCAT '/' *CAT &FRMFIL *TCAT + 0041.00 ' から ' *CAT &TOLIB *TCAT '/' *CAT + 0042.00 &TOFIL *TCAT + 0043.00 ' へのコピーが完了しました。 ') + 0044.00 MSGTYPE(*DIAG) 0045.00 RETURN 0046.00 0047.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) 0048.00 SNDMSG: SNDPGMMSG MSG(&MSG) MSGTYPE(*DIAG) 0049.00 ENDPGM
CRTCLPGM PGM(MYLIB/CPYSAVFCL) SRCFILE(MYSRCLIB/QCLSRC) AUT(*ALL)
0001.00 H DFTNAME(CPYSAVF) DATEDIT(*YMD/) 0002.00 F********** *SAVF コピー **************************************** 0003.00 FFRMSAVF IP F 528 DISK 0004.00 F INFDS(INFDSF) 0005.00 FTOSAVF O F 528 DISK 0006.00 F INFSR(*PSSR) 0007.00 F***************************************************************** 0008.00 D INFDSF DS 0009.00 D* RECRRN: 入出力レコードの RRN 0010.00 D RECRRN 397 400B 0 0011.00 D MSGE C CONST(' でエラーがあった。 ') 0012.00 D DSP40 S 40 0013.00 IFRMSAVF AA 01 0014.00 I 1 528 DATA 0015.00 0016.00 C****************************************************** 0017.00 C *PSSR BEGSR 0018.00 C****************************************************** 0019.00 C Z-ADD RECRRN DSPRRN 4 0 0020.00 C MOVE DSPRRN DSPRRN_C 4 0021.00 C EVAL DSP40 = 'RRN=' + DSPRRN_C + MSGE 0022.00 C DSP40 DSPLY ANS 1 0023.00 C ENDSR '*CANCL' 0024.00 OTOSAVF D 01 0025.00 O DATA 528
RPG : CPYSAVF
は 528 バイトのファイルを 528 バイトのファイルへデータを
コピーしているだけに過ぎない。
ただし簡単なプログラムの割には *PSSR
サブルーチンによってエラーを厳しく監視しているのは
物理ファイルから SAVF にコピーする場合、SAVF としての論理的な整合性に問題があった場合は
レコードが書き込まれると同時に OS/400 によってエラーと扱われるからである。
CPYSAVF は、エラーが発生したときの RRN を報告することができるように記述されている。