📄 idftplistparsemvs.pas
字号:
{ $HDR$}
{**********************************************************************}
{ Unit archived using Team Coherence }
{ Team Coherence is Copyright 2002 by Quality Software Components }
{ }
{ For further information / comments, visit our WEB site at }
{ http://www.TeamCoherence.com }
{**********************************************************************}
{}
{ $Log: 16182: IdFTPListParseMVS.pas
{
{ Rev 1.7 10/26/2004 9:46:36 PM JPMugaas
{ Updated refs.
}
{
{ Rev 1.6 6/8/2004 12:42:22 PM JPMugaas
{ Fixed an Invalid Type Cast problem.
}
{
{ Rev 1.5 4/19/2004 5:05:36 PM JPMugaas
{ Class rework Kudzu wanted.
}
{
{ Rev 1.4 2004.02.03 5:45:24 PM czhower
{ Name changes
}
{
Rev 1.3 10/19/2003 3:36:02 PM DSiders
Added localization comments.
}
{
{ Rev 1.2 4/7/2003 04:03:58 PM JPMugaas
{ User can now descover what output a parser may give.
}
{
{ Rev 1.1 2/19/2003 05:53:20 PM JPMugaas
{ Minor restructures to remove duplicate code and save some work with some
{ formats. The Unix parser had a bug that caused it to give a False positive
{ for Xercom MicroRTOS.
}
{
{ Rev 1.0 2/19/2003 06:04:36 AM JPMugaas
{ IBM MVS parser has been ported to new design.
}
unit IdFTPListParseMVS;
interface
uses classes, IdFTPList, IdFTPListParseBase, IdFTPListTypes, IdTStrings;
{
This should work with IBM MVS, OS/390, and z/OS.
Note that in z/OS, there is no need for a parser for the HFS (hierarchical file
system) because the server would present a Unix-like list for that file system.
}
type
TIdJESJobStatus = (IdJESNotApplicable, IdJESReceived, IdJESHold, IdJESRunning, IdJESOuptutAvailable);
TIdMVSFTPListItem = class(TIdRecFTPListItem)
protected
FBlockSize : Integer;
FMigrated : Boolean;
FVolume : String;
FUnit : String;
FOrg : String; //data set organization
FMVSNumberExtents: Integer;
FMVSNumberTracks: Integer;
public
constructor Create(AOwner: TCollection); override;
property Migrated : Boolean read FMigrated write FMigrated;
property BlockSize : Integer read FBlockSize write FBlockSize;
property RecLength;
property RecFormat;
property NumberRecs;
property Volume : String read FVolume write FVolume;
//can't be unit because that's a reserved word
property Units : String read FUnit write FUnit;
property Org : String read FOrg write FOrg; //data set organization
property NumberExtents: Integer read FMVSNumberExtents write FMVSNumberExtents;
property NumberTracks: Integer read FMVSNumberTracks write FMVSNumberTracks;
end;
TIdMVSJESFTPListItem = class(TIdOwnerFTPListItem)
protected
FMVSJobStatus : TIdJESJobStatus;
FMVSJobSpoolFiles : Integer;
public
constructor Create(AOwner: TCollection); override;
property JobStatus : TIdJESJobStatus read FMVSJobStatus write FMVSJobStatus;
property JobSpoolFiles : Integer read FMVSJobSpoolFiles write FMVSJobSpoolFiles;
end;
TIdMVSJESIntF2FTPListItem = class(TIdOwnerFTPListItem)
protected
FJobStatus : TIdJESJobStatus;
FJobSpoolFiles : Integer;
FDetails : TIdStrings;
procedure SetDetails(AValue : TIdStrings);
public
constructor Create(AOwner: TCollection); override;
destructor Destroy; override;
property Details : TIdStrings read FDetails write SetDetails;
property JobStatus : TIdJESJobStatus read FJobStatus write FJobStatus;
property JobSpoolFiles : Integer read FJobSpoolFiles write FJobSpoolFiles;
end;
TIdFTPLPMVS = class(TIdFTPListBaseHeader)
protected
class function MakeNewItem(AOwner : TIdFTPListItems) : TIdFTPListItem; override;
class function IsHeader(const AData: String): Boolean; override;
class function ParseLine(const AItem : TIdFTPListItem; const APath : String=''): Boolean; override;
public
class function GetIdent : String; override;
end;
TIdFTPLPMVSPartitionedDataSet = class(TIdFTPListBaseHeader)
protected
class function IsHeader(const AData: String): Boolean; override;
class function ParseLine(const AItem : TIdFTPListItem; const APath : String=''): Boolean; override;
public
class function GetIdent : String; override;
end;
//Jes queues
TIdFTPLPMVSJESInterface1 = class(TIdFTPListBase)
protected
class function MakeNewItem(AOwner : TIdFTPListItems) : TIdFTPListItem; override;
class function IsMVS_JESNoJobsMsg(const AData: String): Boolean; virtual;
class function ParseLine(const AItem : TIdFTPListItem; const APath : String=''): Boolean; override;
public
class function GetIdent : String; override;
class function CheckListing(AListing : TIdStrings; const ASysDescript : String =''; const ADetails : Boolean = True): boolean; override;
class function ParseListing(AListing : TIdStrings; ADir : TIdFTPListItems) : boolean; override;
end;
TIdFTPLPMVSJESInterface2 = class(TIdFTPListBase)
protected
class function MakeNewItem(AOwner : TIdFTPListItems) : TIdFTPListItem; override;
class function IsMVS_JESIntF2Header(const AData: String): Boolean;
class function ParseLine(const AItem : TIdFTPListItem; const APath : String=''): Boolean; override;
public
class function GetIdent : String; override;
class function CheckListing(AListing : TIdStrings; const ASysDescript : String =''; const ADetails : Boolean = True): boolean; override;
class function ParseListing(AListing : TIdStrings; ADir : TIdFTPListItems) : boolean; override;
end;
implementation
uses
IdGlobal, IdFTPCommon, IdGlobalProtocols, IdStrings, SysUtils;
{ TIdFTPLPMVS }
class function TIdFTPLPMVS.GetIdent: String;
begin
Result := 'MVS'; {do not localize}
end;
class function TIdFTPLPMVS.IsHeader(const AData: String): Boolean;
//Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
//Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
//Volume Unit Date Ext Used Recfm Lrecl BlkSz Dsorg Dsname
var lvolp, lunp, lrefp, lextp, lusedp,
lrecp, lBlkSz, lDsorg, lDsnp : Integer;
{Note that this one is a little more difficult because I could not find
a MVS machine that accepts anonymous FTP. So I have to do the best I can
with some old posts where people had posted dir structures they got from FTP.}
begin
lvolp := IndyPos('Volume',AData); {Do not translate}
lunp := IndyPos('Unit',AData); {Do not translate}
lrefp := IndyPos('Referred',AData); {Do not translate}
if lrefp = 0 then
begin
lrefp := IndyPos('Date',AData); {Do not translate}
end;
lextp := IndyPos('Ext',AData); {Do not translate}
lusedp := IndyPos('Used',AData); {Do not translate}
lrecp := IndyPos('Lrecl',AData); {Do not translate}
lBlkSz := IndyPos('BlkSz',AData); {Do not translate}
lDsorg := IndyPos('Dsorg',AData); {Do not translate}
lDsnp := IndyPos('Dsname',AData); {Do not translate}
Result := (lvolp <> 0) and (lunp > lvolp) and
(lrefp > lunp) and (lextp > lrefp) and
(lusedp > lextp) and (lrecp > lusedp) and
(lBlkSz > lrecp) and (lDsorg > lBlkSz) and
(lDsnp > lDsorg);
end;
class function TIdFTPLPMVS.MakeNewItem(
AOwner: TIdFTPListItems): TIdFTPListItem;
begin
Result := TIdMVSFTPListItem.Create(AOwner);
end;
class function TIdFTPLPMVS.ParseLine(const AItem: TIdFTPListItem;
const APath: String): Boolean;
{Much of this is based on a thread at:
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=utf-8&selm=DLspv2.G2w%40epsilon.com&rnum=2
and
http://www.snee.com/bob/opsys/part6mvs.pdf
Note: Thread concerning MVS Data Set Size
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=utf-8&threadm=jcmorris.767551300%40mwunix&rnum=15&prev=/groups%3Fq%3DMVS%2BRecfm%2BV%26start%3D10%26hl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3Dutf-8%26selm%3Djcmorris.767551300%2540mwunix%26rnum%3D15
http://groups.google.com/groups?q=MVS+Recfm+V&start=10&hl=en&lr=&ie=UTF-8&oe=utf-8&selm=jcmorris.767551300%40mwunix&rnum=15
http://www.isc.ucsb.edu/tsg/ftp-to-mvs.html
http://www.lsu.edu/ocs/tsc/os390doc/mvsftp.html
}
function IsMVSMigrated(const AData : String) : Boolean;
begin
Result := (Copy(AData,1,8) = 'Migrated') or {do not localize}
( Copy(AData,1,6) = 'MIGRAT'); {do not localize}
end;
function IsPseudoDir(const AData : String) : Boolean;
begin
//In newer implementations, a directory mode is available, see if
//item is a Pseudo-directory
Result := (Copy(AData,1,16)='Pseudo Directory'); {do not localize}
end;
function CanGetAttributes(const AData : String) : Boolean;
begin
Result := (IsMVSMigrated(AData)=False) and ( Copy(AData,1,5) <> 'Error') {do not localize}
and (IsPseudoDir(AData)=False);
end;
var i : Integer;
s : TIdStrings;
LI : TIdMVSFTPListItem;
//NOTE: File Size is not supported at all
//because the file size is calculated with something like this:
// BlkSz * Blks/Trk * Trks
//but you can not get MVS DEVINFO macro so you do not have enough information
//to work with.
begin
LI := AItem as TIdMVSFTPListItem;
if IsMVSMigrated(AItem.Data) then
begin
LI.Migrated := True;
end;
if IsPseudoDir(AItem.Data) then
begin
LI.ItemType := ditDirectory;
end;
if CanGetAttributes(AItem.Data) then
begin
s := TIdStringList.Create;
try
SplitColumns(AItem.Data,s);
if s.Count >0 then
begin
LI.Volume := s[0];
end;
if s.Count >1 then
begin
LI.Units := s[1];
end;
if s.Count >2 then
begin
//Sometimes, the Referred Column will contain a date.
//e.g. **NONE**
//Documented in: Communications Server for z/OS V1R2 TCP/IP Implementation Guide Volume 2: UNIX Applications
//URL: http://www.redbooks.ibm.com/pubs/pdfs/redbooks/sg245228.pdf
if IsNumeric(s[2][1]) then
begin
LI.ModifiedDate := MVSDate(s[2]);
end;
end;
if s.Count >3 then
begin
LI.NumberExtents := StrToIntDef(s[3],0);
end;
if s.Count >4 then
begin
LI.NumberTracks := StrToIntDef(s[4],0);
end;
if s.Count >5 then
begin
LI.RecFormat := s[5];
end;
if s.Count >6 then
begin
LI.RecLength := StrToIntDef(s[6],0);
end;
if s.Count >7 then
begin
LI.BlockSize := StrToIntDef(s[7],0);
end;
if s.Count >8 then
begin
LI.Org := s[8];
if (LI.Org = 'PO') then {do not localize}
begin
LI.ItemType := ditDirectory;
end
else
begin
LI.ItemType := ditFile;
end;
end;
finally
FreeAndNil(s);
end;
end;
//Note that spaces are illegal in MVS file names (Data set namess)
//http://www.snee.com/bob/opsys/part6mvs.pdf
//but for filenames enclosed in '', we should tolorate spaces.
if (AItem.Data<>'') and (AItem.Data[Length(AItem.Data)]='''') then
begin
i := IndyPos('''',AItem.Data)+1;
AItem.FileName := Copy(AItem.Data,i,Length(AItem.Data)-i-1);
end
else
begin
i := RPos(' ',AItem.Data) +1;
AItem.FileName := Copy(AItem.Data,i,Length(AItem.Data));
end;
Result := True;
end;
{ TIdFTPLPMVSPartitionedDataSet }
class function TIdFTPLPMVSPartitionedDataSet.GetIdent: String;
begin
Result := 'MVS: Partitioned Data Set'; {do not localize}
end;
class function TIdFTPLPMVSPartitionedDataSet.IsHeader(
const AData: String): Boolean;
//Name VV.MM Created Changed Size Init Mod Id
//
//or
//
//Name Size TTR Alias-of AC --------- Attributes --------- Amode Rmode
//if there are loaded moduals
var LPName,
LPSize : Integer;
begin
LPName := IndyPos('Name', AData); {do not localize}
LPSize := IndyPos('Size', AData); {do not localize}
Result := (LPName>0) and (LPSize > LPName);
end;
class function TIdFTPLPMVSPartitionedDataSet.ParseLine(
const AItem: TIdFTPListItem; const APath: String): Boolean;
//MVS Particianed data sets must be treated differently than
//the regular MVS catalog.
var s : TIdStrings;
//NOTE: File Size is not supported at all. Size is usually size in records, not bytes
// This is based on stuff at:
// http://publibz.boulder.ibm.com:80/cgi-bin/bookmgr_OS390/BOOKS/F1AA2032/1.5.15?SHELF=&DT=20001127174124
// and
// http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=utf-8&selm=DLspv2.G2w%40epsilon.com&rnum=2
//From Google: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=4e7k0p%24t1v%40blackice.winternet.com&rnum=6&prev=/groups%3Fq%3DMVS%2BPartitioned%2Bdata%2Bset%2Bdirectory%26hl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26selm%3D4e7k0p%2524t1v%2540blackice.winternet.com%26rnum%3D6
{
From: Ralph Goers (rgoer@rgoer.candle.com)
Subject: Re: FTP -- VM, MVS, VMS Questions
View this article only
Newsgroups: comp.os.os2.networking.tcp-ip
Date: 1996/01/27
In message <4e7k0p$t1v@blackice.winternet.com> - frickson@gibbon.com (John C. F
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -