home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
lan
/
nxcopy
/
nxcopy.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-08-07
|
24KB
|
814 lines
Program Network_XCopy;
Const
{$I UTCONSTS.DEF}
Num_Bind_Files = 2;
Num_OS_Files = 2;
Type
{$I UTTYPES.DEF}
{$I UTFILTYP.DEF}
Reg = RECORD
A : Register;
B : Register;
C : Register;
D : Register;
SI : Word;
DI : Word;
BP : Word;
DS : Word;
ES : Word;
Flags : Word;
End;
Dir2_Req = RECORD { Get a directory's information }
PacketLength : Word;
Func : Byte;
SourceBase : Byte;
SearchStart : Word;
PathSpec : String;
End;
Dir2_Rep = RECORD
ReturnLength : Word;
SubDirName : Packed Array[1..16] of Char;
CreatDate : Array[1..2] of Byte;
CreatTime : Array[1..2] of Byte;
OwnerID : LongInt;
AccessRights : Byte;
PadByte : Byte;
SubDirNumber : Word;
End;
Dir10_Req = RECORD { Create a new directory }
PacketLength : Word;
Func : Byte;
SourceBase : Byte;
AccessMask : Byte;
PathSpec : String;
End;
Dir10_Rep = RECORD
ReturnLength : Word;
End;
Dir12_Req = RECORD { Get a directory's trustees }
PacketLength : Word;
Func : Byte;
SourceBase : Byte;
SetNumber : Byte;
PathSpec : String;
End;
Dir12_Rep = RECORD
ReturnLength : Word;
DirName : Packed Array[1..16] of Char;
CreatTime : Array[1..4] of Byte;
OwnerID : LongInt;
Trustee : Array[1..5] of LongInt;
TrustMask : Array[1..5] of Byte;
End;
Dir13_Req = RECORD { Add a trustee to a directory }
PacketLength : Word;
Func : Byte;
SourceBase : Byte;
Trustee : LongInt;
AccessMask : Byte;
PathSpec : String;
End;
Dir13_Rep = RECORD
ReturnLength : Word;
End;
Dir25_Req = RECORD { Change a directory's information }
PacketLength : Word;
Func : Byte;
BaseNumber : Byte;
CreatDate : Array[1..2] of Byte;
CreatTime : Array[1..2] of Byte;
NewOwnerID : LongInt;
MaxAccessRights : Byte;
PathSpec : String;
End;
Dir25_Rep = RECORD
ReturnLength : Word;
End;
Log15_Req = RECORD { Get a file's environmental info }
PacketLength : Word;
Func : Byte;
LastSlot : Word;
Base : Byte;
SearchAttributes : Byte;
ModPath : String;
End;
Log15_Rep = RECORD
ReturnLength : Word;
SlotNumber : Word;
FileName : Packed Array[1..14] of Char;
FileAttributes : Byte;
ExecuteType : Byte;
FileSize : LongInt;
CreateDate : Word;
LastAccessDate : Word;
LastDateUpdate : Word;
LastTimeUpdate : Word;
UniqueOwnerID : LongInt;
UndefinedInfo : Packed Array[1..60] of Char;
End;
Log16_Req = RECORD { Set a file's environmental info }
PacketLength : Word;
Func : Byte;
FileAttributes : Byte;
ExecuteType : Byte;
Filler : Array[1..4] of Byte;
CreateDate : Word;
LastAccessDate : Word;
LastDateUpdate : Word;
LastTimeUpdate : Word;
UniqueOwnerID : LongInt;
UndefinedInfo : Packed Array[1..60] of Char;
Base : Byte;
SearchAttributes : Byte;
ModPath : String;
End;
Log16_Rep = RECORD
ReturnLength : Word;
End;
Var
Dir2_Rquest : Dir2_Req;
Dir2_Rply : Dir2_Rep;
Dir10_Rquest : Dir10_Req;
Dir10_Rply : Dir10_Rep;
Dir12_Rquest : Dir12_Req;
Dir12_Rply : Dir12_Rep;
Dir13_Rquest : Dir13_Req;
Dir13_Rply : Dir13_Rep;
Dir25_Rquest : Dir25_Req;
Dir25_Rply : Dir25_Rep;
Log15_Rquest : Log15_Req;
Log15_Rply : Log15_Rep;
Log16_Rquest : Log16_Req;
Log16_Rply : Log16_Rep;
Regs : Reg;
Comm1,
Comm2 : String;
Abort : Boolean;
Exc_File : Text;
Ex_FileName : String;
Result : Integer;
Source_Drive,
Dest_Drive : String[2];
The_Path : String[128];
Temp : String[128];
OS_Param : String;
F1_Handle,
F2_Handle,
Bytes_Req : Integer;
S_Base,
D_Base,
S_Server,
D_Server : Byte;
More_Files : Boolean;
Bind_Array : Array[1..Num_Bind_Files] of String;
OS_Array : Array[1..Num_OS_Files] of String;
Buffer1 : Array[1..30000] of Byte;
Buffer2 : Array[1..30000] of Byte;
{$I UTVARS.DEF}
{$I UTPROCS.DEF}
{$I UTFILEIO.DEF}
External Procedure DOS_VRead( Handle : Integer; Buffer : StringPtr;
VAR Bytes_Requested : Integer;
VAR Error : Integer );
External Procedure Intr( Intr_No : Integer; VAR Regs : Reg );
External Function SwapL( Long : LongInt ) : LongInt;
External Function Segm( Variable : StringPtr ) : Word;
External Function Offs( Variable : StringPtr ) : Word;
External Function BldPtr( Segm, Offs : Word ) : StringPtr;
External Procedure Close_Bindery;
External Procedure Open_Bindery;
{+----------------------------------------------------------------------------+}
Function SwapW( InWord : Word ) : Word;
Begin
SwapW := Short( Long( Swap( InWord ) ) );
End;
{+----------------------------------------------------------------------------+}
Procedure CharArray_To_String( VAR Ch_Array : Array[ Lo..Hi : Integer ] of Char;
VAR Str : String );
Var
Idx : Integer;
Jdx : Integer;
Abort : Boolean;
Begin
Abort := True;
For Idx := 1 to Hi Do
If Ch_Array[ Idx ] <> ' ' Then Abort := False;
If Not Abort Then
Begin
Idx := Hi;
While (Ch_Array[Idx] = ' ') or (Ch_Array[Idx] = Chr( 0 )) Do
Idx := Idx - 1;
Str[0] := Chr( Idx );
For Jdx := 1 to Idx Do
Str[Jdx] := Ch_Array[Jdx];
End
Else
Str[0] := Chr( 0 );
End; { CharArray_To_String }
{+----------------------------------------------------------------------------+}
Procedure Set_Preferred_Server( Server : Byte );
Var
Regs : Reg;
Begin
Regs.A.H := $f0;
Regs.A.L := 0;
Regs.D.L := Server;
Intr( $21, Regs );
End; { Set_Preferred_Server }
{+----------------------------------------------------------------------------+}
Procedure Setup;
Var
ShellPtr : StringPtr;
Begin
Initialize;
Get_Command( 1, Comm1 );
UpperCase( Comm1 );
If (Not ( Comm1[1] In ['A'..'Z'] )) or (Comm1[2] <> ':') or (Length( Comm1) <> 2) Then
Begin
Writeln( 'Source must be a drive letter A-Z, followed by a colon' );
Abort := True;
Exit;
End;
Source_Drive := Comm1;
The_Path := '';
Regs.A.H := $ef;
Regs.A.L := 0;
Intr( $21, Regs );
ShellPtr := BldPtr( Regs.ES, Regs.SI );
S_Base := Ord( ShellPtr^[ Ord( Source_Drive[1] ) - Ord( 'A' ) ] );
If (S_Base = 0) Then
Begin
Writeln( 'Source drive must be a mapped network drive' );
Abort := True;
Exit;
End;
Regs.A.H := $ef;
Regs.A.L := 2;
Intr( $21, Regs );
ShellPtr := BldPtr( Regs.ES, Regs.SI );
S_Server := Ord( ShellPtr^[ Ord( Source_Drive[1] ) - Ord( 'A' ) ] );
Get_Command( 2, Comm2 );
UpperCase( Comm2 );
If (Not ( Comm2[1] In ['A'..'Z'] )) or (Comm2[2] <> ':') or (Length( Comm2) <> 2) Then
Begin
Writeln( 'Destination must be a drive letter A-Z, followed by a colon' );
Abort := True;
Exit;
End;
Dest_Drive := Comm2;
If (Source_Drive = Dest_Drive) Then
Begin
Writeln( 'Source and destination drives cannot be the same' );
Abort := True;
Exit;
End;
Get_Command( 3, Ex_FileName );
UpperCase( Ex_FileName );
If (Ex_FileName = '') Then
Begin
Writeln( 'An exception file name must be specified' );
Abort := True;
Exit;
End;
Assign( Exc_File, Ex_FileName );
Rewrite( Exc_File );
If (IORESULT <> 0) Then
Begin
Writeln( 'Could not create exception file' );
Abort := True;
Exit;
End;
Regs.A.H := $ef;
Regs.A.L := 0;
Intr( $21, Regs );
ShellPtr := BldPtr( Regs.ES, Regs.SI );
D_Base := Ord( ShellPtr^[ Ord( Dest_Drive[1] ) - Ord( 'A' ) ] );
If (D_Base = 0) Then
Begin
Writeln( 'Destination drive must be a mapped network drive' );
Abort := True;
Exit;
End;
Get_Command( 4, OS_Param );
UpperCase( OS_Param );
If Pos( 'OS', OS_Param ) > 0 Then
OS_Param := 'OS'
Else
OS_Param := '';
Regs.A.H := $ef; { Get pointer to drive server table }
Regs.A.L := 2;
Intr( $21, Regs );
ShellPtr := BldPtr( Regs.ES, Regs.SI );
D_Server := Ord( ShellPtr^[ Ord( Dest_Drive[1] ) - Ord( 'A' ) ] );
Regs.A.H := $dd; { Set error mode so that user intervention not required }
Regs.D.L := 1;
Intr( $21, Regs );
Bind_Array[1] := 'NET$BIND.SYS';
Bind_Array[2] := 'NET$BVAL.SYS';
OS_Array[1] := 'NET$OS.EXE';
OS_Array[2] := 'NET$OS.SYS';
End; { Setup }
{+----------------------------------------------------------------------------+}
Procedure Create_Dest_SubDir( Param_Block : StringPtr );
Var
Regs : Reg;
Begin
Set_Preferred_Server( D_Server );
With Dir10_Rquest Do
Begin
PathSpec := The_Path;
Delete( PathSpec, Length( PathSpec ), 1 );
PacketLength := Length( PathSpec ) + 4;
Func := 10;
SourceBase := D_Base;
AccessMask := Ord( Param_Block^[8] );
End;
With Dir10_Rply Do
ReturnLength := 0;
Regs.A.H := $e2;
Regs.DS := Segm( Addr( Dir10_Rquest ) );
Regs.SI := Offs( Addr( Dir10_Rquest ) );
Regs.ES := Segm( Addr( Dir10_Rply ) );
Regs.DI := Offs( Addr( Dir10_Rply ) );
Intr( $21, Regs );
With Dir25_Rquest Do
Begin
PathSpec := The_Path;
Delete( PathSpec, Length( PathSpec ), 1 );
PacketLength := Length( PathSpec ) + 12;
Func := 25;
BaseNumber := D_Base;
Move( Param_Block^[0], CreatDate[1], 9 );
End;
With Dir25_Rply Do
ReturnLength := 0;
Regs.A.H := $e2;
Regs.DS := Segm( Addr( Dir25_Rquest ) );
Regs.SI := Offs( Addr( Dir25_Rquest ) );
Regs.ES := Segm( Addr( Dir25_Rply ) );
Regs.DI := Offs( Addr( Dir25_Rply ) );
Intr( $21, Regs );
End; { Create_Dest_SubDir }
{+----------------------------------------------------------------------------+}
Procedure Xfer_Directory_Trustees;
Var
Regs : Reg;
More_Trustees : Boolean;
Idx : Integer;
Begin
With Dir12_Rquest Do
Begin
PathSpec := The_Path;
Delete( PathSpec, Length( PathSpec ), 1 );
PacketLength := Length( PathSpec ) + 4;
Func := 12;
SourceBase := S_Base;
SetNumber := 1;
End;
With Dir12_Rply Do
ReturnLength := 49;
With Dir13_Rquest Do
Begin
PathSpec := The_Path;
Delete( PathSpec, Length( PathSpec ), 1 );
PacketLength := Length( PathSpec ) + 8;
Func := 13;
SourceBase := D_Base;
End;
With Dir13_Rply Do
ReturnLength := 0;
Repeat
Set_Preferred_Server( S_Server );
Regs.A.H := $e2;
Regs.DS := Segm( Addr( Dir12_Rquest ) );
Regs.SI := Offs( Addr( Dir12_Rquest ) );
Regs.ES := Segm( Addr( Dir12_Rply ) );
Regs.DI := Offs( Addr( Dir12_Rply ) );
Intr( $21, Regs );
More_Trustees := (Regs.A.L = 0);
If More_Trustees Then
Begin
Set_Preferred_Server( D_Server );
Idx := 1;
While (Dir12_Rply.Trustee[Idx] <> #0) and (Idx <= 5) Do
Begin
With Dir13_Rquest Do
Begin
Trustee := Dir12_Rply.Trustee[Idx];
AccessMask := Dir12_Rply.TrustMask[Idx];
End;
Regs.A.H := $e2;
Regs.DS := Segm( Addr( Dir13_Rquest ) );
Regs.SI := Offs( Addr( Dir13_Rquest ) );
Regs.ES := Segm( Addr( Dir13_Rply ) );
Regs.DI := Offs( Addr( Dir13_Rply ) );
Intr( $21, Regs );
Idx := Idx + 1;
End;
End;
With Dir12_Rquest Do
SetNumber := SetNumber + 1;
Until Not More_Trustees;
End; { Xfer_Directory_Trustees }
{+----------------------------------------------------------------------------+}
Procedure Try_Changing_File_Attributes;
Var
Regs : Reg;
Tmp : String;
Begin
Regs.A.H := $43;
Regs.A.L := 1;
Regs.C.X := 0;
Tmp := Concat( Dest_Drive, Temp, Chr( 0 ) );
Regs.DS := Segm( Addr( Tmp[1] ) );
Regs.D.X := Offs( Addr( Tmp[1] ) );
Intr( $21, Regs );
End; { Try_Changing_File_Attributes }
{+----------------------------------------------------------------------------+}
Function Bindery_File( FileSpec : String ) : Boolean;
Var
Temp_Bool : Boolean;
Idx : Integer;
Begin
Temp_Bool := False;
While Pos( '\', FileSpec ) > 0 Do { strip the path from the filespec }
Delete( FileSpec, 1, Pos( '\', FileSpec ) );
For Idx := 1 to Num_Bind_Files Do
If (Scomp( FileSpec, Bind_Array[Idx] ) = 0) Then
Temp_Bool := True;
Bindery_File := Temp_Bool;
End; { Bindery_File }
{+----------------------------------------------------------------------------+}
Function Net_OS( FileSpec : String ) : Boolean;
Var
Temp_Bool : Boolean;
Idx : Integer;
Begin
Temp_Bool := False;
If OS_Param <> 'OS' Then
Begin
While Pos( '\', FileSpec ) > 0 Do { strip the path from the filespec }
Delete( FileSpec, 1, Pos( '\', FileSpec ) );
For Idx := 1 to Num_OS_Files Do
If (Scomp( FileSpec, OS_Array[Idx] ) = 0) Then
Temp_Bool := True;
End;
Net_OS := Temp_Bool;
End; { Net_OS }
{+----------------------------------------------------------------------------+}
Function Copy_File : Boolean;
Var
Bind_Closed : Boolean;
Begin
Bind_Closed := False;
CharArray_to_String( Log15_Rply.FileName, Temp );
Temp := Concat( The_Path, Temp );
If Net_OS( Temp ) Then
Result := 255
Else
Begin
DOS_Open( Concat( Source_Drive, Temp ), 0, F1_Handle, Result );
If (Result <> 0) and (Bindery_File( Temp )) Then
Begin
Set_Preferred_Server( D_Server );
Close_Bindery;
Set_Preferred_Server( S_Server );
Close_Bindery;
Bind_Closed := True;
DOS_Open( Concat( Source_Drive, Temp ), 0, F1_Handle, Result );
End;
If Result <> 0 Then
Begin
Set_Preferred_Server( 0 );
Writeln( Exc_File, 'Unable to open source file ', Source_Drive, Temp );
Set_Preferred_Server( S_Server );
End
Else
Begin
DOS_Create( Concat( Dest_Drive, Temp ), F2_Handle, Result );
If Result <> 0 Then
Begin
Try_Changing_File_Attributes;
DOS_Create( Concat( Dest_Drive, Temp ), F2_Handle, Result );
End;
If Result <> 0 Then
Begin
Set_Preferred_Server( 0 );
Writeln( Exc_File, 'Unable to create destination file ', Dest_Drive, Temp );
Set_Preferred_Server( S_Server );
End
Else
Begin
Writeln( 'Copying ', Source_Drive, Temp );
Bytes_Req := -5536;
Repeat
DOS_VRead( F1_Handle, Addr( Buffer1 ), Bytes_Req, Result );
DOS_Write( F2_Handle, Addr( Buffer1 ), Bytes_Req, Result );
Until Bytes_Req <> -5536;
DOS_Close( F1_Handle, Result );
DOS_Close( F2_Handle, Result );
End;
End;
End;
If Bind_Closed Then
Begin
Set_Preferred_Server( D_Server );
Open_Bindery;
Set_Preferred_Server( S_Server );
Open_Bindery;
End;
Copy_File := (Result = 0);
End; { Copy_File }
{+----------------------------------------------------------------------------+}
Procedure Log_Setup;
Begin
With Log15_Rquest Do
Begin
ModPath := Concat( The_Path, '*' );
Packet_Length := Length( ModPath ) + 6;
Func := 15;
Base := S_Base;
SearchAttributes := 6;
End;
With Log15_Rply Do
Begin
ReturnLength := 94;
SlotNumber := $ffff;
SlotNumber := SwapW( SlotNumber );
End;
With Log16_Rquest Do
Begin
Func := 16;
Base := D_Base;
SearchAttributes := 6;
End;
With Log16_Rply Do
ReturnLength := 0;
End; { Log_Setup }
{+----------------------------------------------------------------------------+}
Procedure Log_Transfer;
Begin
With Log16_Rquest Do
Begin
CharArray_to_String( Log15_Rply.FileName, ModPath );
ModPath := Concat( The_Path, ModPath );
PacketLength := Length( ModPath ) + 82;
Move( Log15_Rply.FileAttributes, Log16_Rquest.FileAttributes, 78 );
End;
End; { Log_Transfer }
{+----------------------------------------------------------------------------+}
Procedure Lookup_Files;
Var
Sav_Len : Integer;
Regs : Reg;
Dir2_Rquest : Dir2_Req;
Dir2_Rply : Dir2_Rep;
Begin
(*********************************************************)
(* Copy all files from source to destination directory *)
(*********************************************************)
Log_Setup;
Repeat
Set_Preferred_Server( S_Server );
Log15_Rquest.LastSlot := Log15_Rply.SlotNumber;
Regs.A.H := $e3;
Regs.DS := Segm( Addr( Log15_Rquest ) );
Regs.SI := Offs( Addr( Log15_Rquest ) );
Regs.ES := Segm( Addr( Log15_Rply ) );
Regs.DI := Offs( Addr( Log15_Rply ) );
Intr( $21, Regs );
More_Files := (Regs.A.L = 0);
If More_Files Then
If Copy_File Then
Begin
Set_Preferred_Server( D_Server );
Log_Transfer;
Regs.A.H := $e3;
Regs.DS := Segm( Addr( Log16_Rquest ) );
Regs.SI := Offs( Addr( Log16_Rquest ) );
Regs.ES := Segm( Addr( Log16_Rply ) );
Regs.DI := Offs( Addr( Log16_Rply ) );
Intr( $21, Regs );
End;
Until Not More_Files;
(**************************************************)
(* Now look for subdirectories and go recursive *)
(**************************************************)
Set_Preferred_Server( S_Server );
With Dir2_Rquest Do
Begin
PathSpec := Concat( The_Path, '*' );
PacketLength := Length( PathSpec ) + 5;
Func := 2;
SourceBase := S_Base;
SearchStart := 1;
SearchStart := SwapW( SearchStart );
End;
With Dir2_Rply Do
ReturnLength := 28;
Repeat
Regs.A.H := $e2;
Regs.DS := Segm( Addr( Dir2_Rquest ) );
Regs.SI := Offs( Addr( Dir2_Rquest ) );
Regs.ES := Segm( Addr( Dir2_Rply ) );
Regs.DI := Offs( Addr( Dir2_Rply ) );
Intr( $21, Regs );
If (Regs.A.L = 0) Then
Begin
CharArray_to_String( Dir2_Rply.SubDirName, Temp );
Sav_Len := Length( Temp );
The_Path := Concat( The_Path, Temp, '\' );
Create_Dest_SubDir( Addr( Dir2_Rply.CreatDate[1] ) );
Xfer_Directory_Trustees;
Lookup_Files;
Delete( The_Path, Length( The_Path ) - Sav_Len, Sav_Len + 1 );
End;
With Dir2_Rply Do
Begin
SubDirNumber := SwapW( SubDirNumber );
SubDirNumber := Short( Long( SubDirNumber ) ) + 1;
End;
With Dir2_Rquest Do
Begin
SearchStart := Dir2_Rply.SubDirNumber;
SearchStart := SwapW( SearchStart );
End;
Until Regs.A.L <> 0;
End; { Lookup_Files }
{+----------------------------------------------------------------------------+}
Begin { Main procedure }
Abort := False;
Setup;
If Abort Then Exit;
Lookup_Files;
Set_Preferred_Server( 0 );
Close( Exc_File, Result );
End.