📄 idftplistparsemvs.pas
字号:
rickson) writes:
:>
:>MVS directory lines look like this:
:>
:>Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
:>OVH025 3380 12/29/95 1 60 FB 80 23200 PO MICSFILE.CLIST
:>USS018 3380 12/18/95 1 15 VB 259 8000 PS NFS.DOC
:>Migrated OAQPS.INTERIM.CNTYIM.V1.DATA.D052093
:>AIR030 3380 12/13/95 1 18 FB 80 3600 PS OAQPS.INTERIM.PLNTNAME.DATA
:>
:>1) Ext is number of extents? Yes.
:>2) Used is number of tracks? Yes
:>3) Is the volume name important or can I ignore it?
It is important only if it is MIGRAT or migrated. This indicates that the
dataset has not been accessed recently and has been migrated to an HSM
volume (DASD or tape).
:>4) Is there any way to calculate filesizes? I think I would have to know
:> the capacity of the device (i.e. BlkSz * Blks/Trk * Trks)
I'm not sure this would do you any good. Just because you know how many bytes
are in a track doesn't mean that each track is full. In the case of an FB
file you can figure out how many blocks will fit in a track. This may not be
true of V type files.
:>5) Dsorg -- PO seems to equate to partioned data set. Is that always true?
:> Are any values other than PO and PS possible?
Yes - you can also have VS files (VSAM) - however I have no idea why anyone
would try to FTP one.
:>6) What is "Migrated"? Moved to tape? Is the file still available for
:> download, or should I simply ignore these lines?
If you reference the file it will automatically be brought back to a DASD
volume.
:>7) After loggin in, the server reports the current directory as "PA2",
:> but in response to a "PWD" command, it says "PUBLIC.". ??? Not sure about this. Usually, it defaults to "USERID.".
:>8) Is the "CD" command useful for anything other than getting into
:> partitioned data sets?
Sure. If you have a bunch of sequential datasets starting with A.B then
cd'ing to that and then doing MGET * should download all the sequential files.
PDSes should not be downloaded but should be treated as a subdirectory.
:>9) After CD'ing into a PDS, a directory looks like this:
:> Name VV.MM Created Changed Size Init Mod Id
:> $README 01.10 89/04/19 94/12/15 18:55 90 1 0 EWZ
:> What are the Size, Init, Mod and ID fields?
:> Is VV.MM version information?
:>
Size is the number of records in the file. init is the number of lines that
were in the file when statistics were first set and mod is the number of
lines modified since then. VV.MM is a version and modification level. These
SPF statistics can be reset by going into edit on the member and typing STATS
OFF, SAVE, STATS ON, SAVE. They can also be reset via option 3.5 - Member
statistics panel. Some programs also modify them for their own use.
You should count on these statistics even being present. They are created
only by SPF. Other programs use the same area in the directory entry for
their own purposes. When you link a load module, for example, information
about it is stored there. When you FTP files up to MVS FTP will not create
statistics for PDS members.
Hope this is helpful.
Ralph
}
begin
s := TIdStringList.Create;
try
SplitColumns(AItem.Data,s);
if s.Count > 0 then
begin
AItem.FileName := s[0];
//in some particianed data sets, dates are missing.
if (s.Count > 7) and (s[3]<>'') and IsNumeric(s[3][1]) and (IndyPos('/',s[3])>0) then
begin
AItem.ModifiedDate := MVSDate(s[3]);
// Name VV.MM Created Changed Size Init Mod Id
//$README 01.10 89/04/19 94/12/15 18:55 90 1 0 EWZ
if s.Count > 4 then
begin
AItem.ModifiedDate := AItem.ModifiedDate + TimeHHMMSS(s[4]);
end;
end;
end;
finally
FreeAndNil(s);
end;
Result := True;
end;
{ TIdFTPLPMVSJESInterface1 }
class function TIdFTPLPMVSJESInterface1.CheckListing(AListing: TIdStrings;
const ASysDescript: String; const ADetails: Boolean): boolean;
var s : TIdStrings;
begin
if AListing.Count > 0 then
begin
s := TIdStringList.Create;
try
SplitColumns(AListing[0],s);
Result := (s.Count >2) and (PosInStrArray(Trim(s[2]),MVS_JES_Status)>-1);
if Result and (s.Count > 3) then
begin
Result := IsNumeric(s[3]) or (s[3][1]='-');
end;
if Result = False then
begin
Result := IsMVS_JESNoJobsMsg(AListing[0]);
end;
finally
FreeAndNil(s);
end;
end
else
begin
Result := False;
end;
end;
class function TIdFTPLPMVSJESInterface1.GetIdent: String;
begin
Result := 'MVS: JES Queue Interface 1'; {do not localize}
end;
class function TIdFTPLPMVSJESInterface1.IsMVS_JESNoJobsMsg(
const AData: String): Boolean;
begin
Result := (AData = 'No jobs found on JES queue'); {do not localize}
end;
class function TIdFTPLPMVSJESInterface1.MakeNewItem(
AOwner: TIdFTPListItems): TIdFTPListItem;
begin
Result := TIdMVSJESFTPListItem.Create(AOwner);
end;
class function TIdFTPLPMVSJESInterface1.ParseLine(
const AItem: TIdFTPListItem; const APath: String): Boolean;
{
ALFREDCA JOB03192 OUTPUT 3 Spool Files
ALFREDCA JOB03193 OUTPUT 0 Spool Files
ALFREDCA JOB03194 INPUT
12345678901234567890123456789012345678901234567890
1 2 3 4 5
#From: IBM Communications Server for OS/390 V2R10 TCP/IP Implementation Guide Volume 2: UNIX Applications
#Obtained at: http://www.redbooks.ibm.com/pubs/pdfs/redbooks/sg245228.pdf
}
var LBuf : String;
LI : TIdMVSJESFTPListItem;
begin
LI := AItem as TIdMVSJESFTPListItem;
//owner
LBuf := AItem.Data;
LI.OwnerName := Fetch(LBuf);
LBuf := TrimLeft(LBuf);
//filename
LI.FileName := Fetch(LBuf);
LBuf := TrimLeft(LBuf);
case PosInStrArray (Fetch(LBuf),MVS_JES_Status) of
0 : LI.JobStatus := IdJESReceived; // 'INPUT' job received but not run yet
1 : LI.JobStatus := IdJESHold; // 'HELD' job is in hold status
2 : LI.JobStatus := IdJESRunning; // 'ACTIVE' job is running
3 : LI.JobStatus := IdJESOuptutAvailable; // 'OUTPUT' job has finished and has output available
end;
//spool file output if available
LBuf := TrimLeft(LBuf);
LI.JobSpoolFiles := StrToIntDef(Fetch(LBuf),0);
Result := True;
end;
class function TIdFTPLPMVSJESInterface1.ParseListing(AListing: TIdStrings;
ADir: TIdFTPListItems): boolean;
var LItem : TIdFTPListItem;
i : Integer;
begin
Result := False;
if AListing.Count >0 then
begin
if IsMVS_JESNoJobsMsg(Alisting[0])=False then
begin
for i := 0 to AListing.Count -1 do
begin
LItem := MakeNewItem(ADir);
LItem.Data := AListing[i];
ParseLine(LItem);
end;
end
else
begin
Result := True;
end;
end;
end;
{ TIdFTPLPMVSJESInterface2 }
class function TIdFTPLPMVSJESInterface2.CheckListing(AListing: TIdStrings;
const ASysDescript: String; const ADetails: Boolean): boolean;
begin
Result := False;
if AListing.Count > -1 then
begin
Result := IsMVS_JESIntF2Header(AListing[0]);
end;
end;
class function TIdFTPLPMVSJESInterface2.GetIdent: String;
begin
Result := 'MVS: JES Queue Interface 2'; {do not localize}
end;
class function TIdFTPLPMVSJESInterface2.IsMVS_JESIntF2Header(
const AData: String): Boolean;
begin
Result := (AData = 'JOBNAME JOBID OWNER STATUS CLASS'); {do not localize}
end;
class function TIdFTPLPMVSJESInterface2.MakeNewItem(
AOwner: TIdFTPListItems): TIdFTPListItem;
begin
Result := TIdMVSJESIntF2FTPListItem.Create(AOwner);
end;
class function TIdFTPLPMVSJESInterface2.ParseLine(
const AItem: TIdFTPListItem; const APath: String): Boolean;
{
JOBNAME JOBID OWNER STATUS CLASS
BPXAS STC02133 ++++++++ OUTPUT STC RC=000 2 spool
BPXAS STC00916 ++++++++ OUTPUT STC RC=000 2 spool
BPXAS STC02132 ++++++++ ACTIVE STC
BPXAS STC02131 ++++++++ ACTIVE STC
123456789012345678901234567890123456789012345678901234567890
1 2 3 4 5 6
}
var LBuf, LNo : String;
LPos, LPos2 : Integer;
LI : TIdMVSJESIntF2FTPListItem;
begin
LI := AItem as TIdMVSJESIntF2FTPListItem;
LI.FileName := Trim(Copy(AItem.Data,10,8));
LI.OwnerName := Trim(Copy(AItem.Data,19,7));
if IsLineStr(LI.OwnerName) then
begin
LI.OwnerName := '';
end;
case PosInStrArray (Trim(Copy(AItem.Data,28,7)),MVS_JES_Status) of
0 : LI.JobStatus := IdJESReceived; // 'INPUT' job received but not run yet
1 : LI.JobStatus := IdJESHold; // 'HELD' job is in hold status
2 : LI.JobStatus := IdJESRunning; // 'ACTIVE' job is running
3 : LI.JobStatus := IdJESOuptutAvailable; // 'OUTPUT' job has finished and has output available
end;
LBuf := Trim(Copy(AItem.Data,35,Length(AItem.Data)));
LPos := IndyPos(' spool',LBuf); {do not localize}
if LPos = 0 then
begin
Result := False;
Exit;
end;
LNo := '';
for LPos2 := LPos-1 downto 1 do
begin
if (LBuf[LPos2]=' ') then
begin
break;
end
else
begin
LNo := LBuf[LPos2] + LNo;
end;
end;
LI.JobSpoolFiles := StrToIntDef(LNo,0);
Result := True;
end;
class function TIdFTPLPMVSJESInterface2.ParseListing(AListing: TIdStrings;
ADir: TIdFTPListItems): boolean;
var LItem : TIdFTPListItem;
i : Integer;
LStartLine : Integer;
LDetailFlag : Boolean;
LI : TIdMVSJESIntF2FTPListItem;
begin
if AListing.Count >0 then
begin
if IsMVS_JESIntf2Header(AListing[0]) then
begin
LStartLine := 1;
end
else
begin
LStartLine := 0;
end;
LDetailFlag := False;
for i := LStartLine to AListing.Count -1 do
begin
if LDetailFlag then
begin
if ADir.Count > 0 then
begin
LI := ADir.Items[ADir.Count -1] as TIdMVSJESIntF2FTPListItem;
LI.Details.Add(AListing[i]);
end;
end
else
begin
if AListing[i] = '--------' then
begin
LDetailFlag := True;
end
else
begin
LItem := MakeNewItem(ADir);
LItem.Data := AListing[i];
ParseLine(LItem);
end;
end;
end;
Result := True;
end
else
begin
Result := False;
end;
end;
{ TIdMVSFTPListItem }
constructor TIdMVSFTPListItem.Create(AOwner: TCollection);
begin
inherited;
FSizeAvail := False; //we can't get the file size from a MVS system
end;
{ TIdMVSJESIntFFTPListItem }
constructor TIdMVSJESIntF2FTPListItem.Create(AOwner: TCollection);
begin
inherited;
FDetails := TIdStringList.Create;
end;
destructor TIdMVSJESIntF2FTPListItem.Destroy;
begin
FreeAndNil(FDetails);
inherited;
end;
procedure TIdMVSJESIntF2FTPListItem.SetDetails(AValue: TIdStrings);
begin
FDetails.Assign(AValue);
end;
{ TIdMVSJESFTPListItem }
constructor TIdMVSJESFTPListItem.Create(AOwner: TCollection);
begin
inherited;
Self.JobStatus := IdJESNotApplicable;
end;
initialization
RegisterFTPListParser(TIdFTPLPMVS);
RegisterFTPListParser(TIdFTPLPMVSPartitionedDataSet);
RegisterFTPListParser(TIdFTPLPMVSJESInterface1);
RegisterFTPListParser(TIdFTPLPMVSJESInterface2);
finalization
UnRegisterFTPListParser(TIdFTPLPMVS);
UnRegisterFTPListParser(TIdFTPLPMVSPartitionedDataSet);
UnRegisterFTPListParser(TIdFTPLPMVSJESInterface1);
UnRegisterFTPListParser(TIdFTPLPMVSJESInterface2);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -