home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / nxcopy / nxcopy.pas < prev    next >
Pascal/Delphi Source File  |  1987-08-07  |  24KB  |  814 lines

  1. Program Network_XCopy;
  2.  
  3. Const
  4.  
  5.     {$I UTCONSTS.DEF}
  6.  
  7.     Num_Bind_Files        =  2;
  8.     Num_OS_Files          =  2;
  9.  
  10. Type
  11.  
  12.     {$I UTTYPES.DEF}
  13.     {$I UTFILTYP.DEF}
  14.  
  15.     Reg                   =  RECORD
  16.          A                :  Register;
  17.          B                :  Register;
  18.          C                :  Register;
  19.          D                :  Register;
  20.          SI               :  Word;
  21.          DI               :  Word;
  22.          BP               :  Word;
  23.          DS               :  Word;
  24.          ES               :  Word;
  25.          Flags            :  Word;
  26.     End;
  27.  
  28.     Dir2_Req              =  RECORD    { Get a directory's information }
  29.          PacketLength     :  Word;
  30.          Func             :  Byte;
  31.          SourceBase       :  Byte;
  32.          SearchStart      :  Word;
  33.          PathSpec         :  String;
  34.     End;
  35.  
  36.     Dir2_Rep              =  RECORD
  37.          ReturnLength     :  Word;
  38.          SubDirName       :  Packed Array[1..16] of Char;
  39.          CreatDate        :  Array[1..2] of Byte;
  40.          CreatTime        :  Array[1..2] of Byte;
  41.          OwnerID          :  LongInt;
  42.          AccessRights     :  Byte;
  43.          PadByte          :  Byte;
  44.          SubDirNumber     :  Word;
  45.     End;
  46.  
  47.     Dir10_Req             =  RECORD    { Create a new directory }
  48.          PacketLength     :  Word;
  49.          Func             :  Byte;
  50.          SourceBase       :  Byte;
  51.          AccessMask       :  Byte;
  52.          PathSpec         :  String;
  53.     End;
  54.  
  55.     Dir10_Rep             =  RECORD
  56.          ReturnLength     :  Word;
  57.     End;
  58.  
  59.     Dir12_Req             =  RECORD    { Get a directory's trustees }
  60.          PacketLength     :  Word;
  61.          Func             :  Byte;
  62.          SourceBase       :  Byte;
  63.          SetNumber        :  Byte;
  64.          PathSpec         :  String;
  65.     End;
  66.  
  67.     Dir12_Rep             =  RECORD
  68.          ReturnLength     :  Word;
  69.          DirName          :  Packed Array[1..16] of Char;
  70.          CreatTime        :  Array[1..4] of Byte;
  71.          OwnerID          :  LongInt;
  72.          Trustee          :  Array[1..5] of LongInt;
  73.          TrustMask        :  Array[1..5] of Byte;
  74.     End;
  75.  
  76.     Dir13_Req             =  RECORD    { Add a trustee to a directory }
  77.          PacketLength     :  Word;
  78.          Func             :  Byte;
  79.          SourceBase       :  Byte;
  80.          Trustee          :  LongInt;
  81.          AccessMask       :  Byte;
  82.          PathSpec         :  String;
  83.     End;
  84.  
  85.     Dir13_Rep             =  RECORD
  86.          ReturnLength     :  Word;
  87.     End;
  88.  
  89.     Dir25_Req             =  RECORD    { Change a directory's information }
  90.          PacketLength     :  Word;
  91.          Func             :  Byte;
  92.          BaseNumber       :  Byte;
  93.          CreatDate        :  Array[1..2] of Byte;
  94.          CreatTime        :  Array[1..2] of Byte;
  95.          NewOwnerID       :  LongInt;
  96.          MaxAccessRights  :  Byte;
  97.          PathSpec         :  String;
  98.     End;
  99.  
  100.     Dir25_Rep             =  RECORD
  101.          ReturnLength     :  Word;
  102.     End;
  103.  
  104.     Log15_Req             =  RECORD    { Get a file's environmental info }
  105.          PacketLength     :  Word;
  106.          Func             :  Byte;
  107.          LastSlot         :  Word;
  108.          Base             :  Byte;
  109.          SearchAttributes :  Byte;
  110.          ModPath          :  String;
  111.     End;
  112.  
  113.     Log15_Rep             =  RECORD
  114.          ReturnLength     :  Word;
  115.          SlotNumber       :  Word;
  116.          FileName         :  Packed Array[1..14] of Char;
  117.          FileAttributes   :  Byte;
  118.          ExecuteType      :  Byte;
  119.          FileSize         :  LongInt;
  120.          CreateDate       :  Word;
  121.          LastAccessDate   :  Word;
  122.          LastDateUpdate   :  Word;
  123.          LastTimeUpdate   :  Word;
  124.          UniqueOwnerID    :  LongInt;
  125.          UndefinedInfo    :  Packed Array[1..60] of Char;
  126.     End;
  127.  
  128.     Log16_Req             =  RECORD    { Set a file's environmental info }
  129.          PacketLength     :  Word;
  130.          Func             :  Byte;
  131.          FileAttributes   :  Byte;
  132.          ExecuteType      :  Byte;
  133.          Filler           :  Array[1..4] of Byte;
  134.          CreateDate       :  Word;
  135.          LastAccessDate   :  Word;
  136.          LastDateUpdate   :  Word;
  137.          LastTimeUpdate   :  Word;
  138.          UniqueOwnerID    :  LongInt;
  139.          UndefinedInfo    :  Packed Array[1..60] of Char;
  140.          Base             :  Byte;
  141.          SearchAttributes :  Byte;
  142.          ModPath          :  String;
  143.     End;
  144.  
  145.     Log16_Rep             =  RECORD
  146.          ReturnLength     :  Word;
  147.     End;
  148.  
  149. Var
  150.     Dir2_Rquest      :  Dir2_Req;
  151.     Dir2_Rply        :  Dir2_Rep;
  152.     Dir10_Rquest     :  Dir10_Req;
  153.     Dir10_Rply       :  Dir10_Rep;
  154.     Dir12_Rquest     :  Dir12_Req;
  155.     Dir12_Rply       :  Dir12_Rep;
  156.     Dir13_Rquest     :  Dir13_Req;
  157.     Dir13_Rply       :  Dir13_Rep;
  158.     Dir25_Rquest     :  Dir25_Req;
  159.     Dir25_Rply       :  Dir25_Rep;
  160.     Log15_Rquest     :  Log15_Req;
  161.     Log15_Rply       :  Log15_Rep;
  162.     Log16_Rquest     :  Log16_Req;
  163.     Log16_Rply       :  Log16_Rep;
  164.     Regs             :  Reg;
  165.     Comm1,
  166.     Comm2            :  String;
  167.     Abort            :  Boolean;
  168.     Exc_File         :  Text;
  169.     Ex_FileName      :  String;
  170.     Result           :  Integer;
  171.     Source_Drive,
  172.     Dest_Drive       :  String[2];
  173.     The_Path         :  String[128];
  174.     Temp             :  String[128];
  175.     OS_Param         :  String;
  176.     F1_Handle,
  177.     F2_Handle,
  178.     Bytes_Req        :  Integer;
  179.     S_Base,
  180.     D_Base,
  181.     S_Server,
  182.     D_Server         :  Byte;
  183.     More_Files       :  Boolean;
  184.     Bind_Array       :  Array[1..Num_Bind_Files] of String;
  185.     OS_Array         :  Array[1..Num_OS_Files] of String;
  186.     Buffer1          :  Array[1..30000] of Byte;
  187.     Buffer2          :  Array[1..30000] of Byte;
  188.  
  189.     {$I UTVARS.DEF}
  190.  
  191. {$I UTPROCS.DEF}
  192. {$I UTFILEIO.DEF}
  193.  
  194. External Procedure DOS_VRead( Handle  :  Integer;  Buffer  :  StringPtr;
  195.                               VAR Bytes_Requested   :  Integer;
  196.                               VAR Error        :  Integer );
  197.  
  198. External Procedure Intr( Intr_No : Integer; VAR Regs : Reg );
  199.  
  200. External Function SwapL( Long : LongInt ) : LongInt;
  201.  
  202. External Function Segm( Variable : StringPtr ) : Word;
  203.  
  204. External Function Offs( Variable : StringPtr ) : Word;
  205.  
  206. External Function BldPtr( Segm, Offs : Word ) : StringPtr;
  207.  
  208. External Procedure Close_Bindery;
  209.  
  210. External Procedure Open_Bindery;
  211.  
  212. {+----------------------------------------------------------------------------+}
  213.  
  214.   Function SwapW( InWord : Word ) : Word;
  215.  
  216.     Begin
  217.  
  218.       SwapW := Short( Long( Swap( InWord ) ) );
  219.  
  220.     End;
  221.  
  222. {+----------------------------------------------------------------------------+}
  223.  
  224.   Procedure CharArray_To_String( VAR Ch_Array : Array[ Lo..Hi : Integer ] of Char;
  225.                                  VAR Str : String );
  226.     Var
  227.       Idx         :  Integer;
  228.       Jdx         :  Integer;
  229.       Abort       :  Boolean;
  230.  
  231.     Begin
  232.  
  233.       Abort := True;
  234.       For Idx := 1 to Hi Do
  235.         If Ch_Array[ Idx ] <> ' ' Then Abort := False;
  236.       If Not Abort Then
  237.         Begin
  238.           Idx := Hi;
  239.           While (Ch_Array[Idx] = ' ') or (Ch_Array[Idx] = Chr( 0 )) Do
  240.             Idx := Idx - 1;
  241.           Str[0] := Chr( Idx );
  242.           For Jdx := 1 to Idx Do
  243.             Str[Jdx] := Ch_Array[Jdx];
  244.         End
  245.       Else
  246.         Str[0] := Chr( 0 );
  247.  
  248.     End;  { CharArray_To_String }
  249.  
  250. {+----------------------------------------------------------------------------+}
  251.  
  252.   Procedure Set_Preferred_Server( Server : Byte );
  253.  
  254.     Var
  255.       Regs         :  Reg;
  256.  
  257.     Begin
  258.  
  259.       Regs.A.H := $f0;
  260.       Regs.A.L := 0;
  261.       Regs.D.L := Server;
  262.       Intr( $21, Regs );
  263.  
  264.     End;  { Set_Preferred_Server }
  265.  
  266. {+----------------------------------------------------------------------------+}
  267.  
  268.   Procedure Setup;
  269.  
  270.     Var
  271.       ShellPtr          :  StringPtr;
  272.  
  273.     Begin
  274.  
  275.       Initialize;
  276.       Get_Command( 1, Comm1 );
  277.       UpperCase( Comm1 );
  278.       If (Not ( Comm1[1] In ['A'..'Z'] )) or (Comm1[2] <> ':') or (Length( Comm1) <> 2) Then
  279.         Begin
  280.           Writeln( 'Source must be a drive letter A-Z, followed by a colon' );
  281.           Abort := True;
  282.           Exit;
  283.         End;
  284.       Source_Drive := Comm1;
  285.       The_Path := '';
  286.  
  287.       Regs.A.H := $ef;
  288.       Regs.A.L := 0;
  289.       Intr( $21, Regs );
  290.       ShellPtr := BldPtr( Regs.ES, Regs.SI );
  291.       S_Base := Ord( ShellPtr^[ Ord( Source_Drive[1] ) - Ord( 'A' ) ] );
  292.       If (S_Base = 0) Then
  293.         Begin
  294.           Writeln( 'Source drive must be a mapped network drive' );
  295.           Abort := True;
  296.           Exit;
  297.         End;
  298.  
  299.       Regs.A.H := $ef;
  300.       Regs.A.L := 2;
  301.       Intr( $21, Regs );
  302.       ShellPtr := BldPtr( Regs.ES, Regs.SI );
  303.       S_Server := Ord( ShellPtr^[ Ord( Source_Drive[1] ) - Ord( 'A' ) ] );
  304.  
  305.       Get_Command( 2, Comm2 );
  306.       UpperCase( Comm2 );
  307.       If (Not ( Comm2[1] In ['A'..'Z'] )) or (Comm2[2] <> ':') or (Length( Comm2) <> 2) Then
  308.         Begin
  309.           Writeln( 'Destination must be a drive letter A-Z, followed by a colon' );
  310.           Abort := True;
  311.           Exit;
  312.         End;
  313.       Dest_Drive := Comm2;
  314.       If (Source_Drive = Dest_Drive) Then
  315.         Begin
  316.           Writeln( 'Source and destination drives cannot be the same' );
  317.           Abort := True;
  318.           Exit;
  319.         End;
  320.  
  321.       Get_Command( 3, Ex_FileName );
  322.       UpperCase( Ex_FileName );
  323.       If (Ex_FileName = '') Then
  324.         Begin
  325.           Writeln( 'An exception file name must be specified' );
  326.           Abort := True;
  327.           Exit;
  328.         End;
  329.  
  330.       Assign( Exc_File, Ex_FileName );
  331.       Rewrite( Exc_File );
  332.       If (IORESULT <> 0) Then
  333.         Begin
  334.           Writeln( 'Could not create exception file' );
  335.           Abort := True;
  336.           Exit;
  337.         End;
  338.  
  339.       Regs.A.H := $ef;
  340.       Regs.A.L := 0;
  341.       Intr( $21, Regs );
  342.       ShellPtr := BldPtr( Regs.ES, Regs.SI );
  343.       D_Base := Ord( ShellPtr^[ Ord( Dest_Drive[1] ) - Ord( 'A' ) ] );
  344.       If (D_Base = 0) Then
  345.         Begin
  346.           Writeln( 'Destination drive must be a mapped network drive' );
  347.           Abort := True;
  348.           Exit;
  349.         End;
  350.  
  351.       Get_Command( 4, OS_Param );
  352.       UpperCase( OS_Param );
  353.       If Pos( 'OS', OS_Param ) > 0 Then
  354.         OS_Param := 'OS'
  355.       Else
  356.         OS_Param := '';
  357.  
  358.       Regs.A.H := $ef;  { Get pointer to drive server table }
  359.       Regs.A.L := 2;
  360.       Intr( $21, Regs );
  361.       ShellPtr := BldPtr( Regs.ES, Regs.SI );
  362.       D_Server := Ord( ShellPtr^[ Ord( Dest_Drive[1] ) - Ord( 'A' ) ] );
  363.  
  364.       Regs.A.H := $dd; { Set error mode so that user intervention not required }
  365.       Regs.D.L := 1;
  366.       Intr( $21, Regs );
  367.  
  368.       Bind_Array[1] := 'NET$BIND.SYS';
  369.       Bind_Array[2] := 'NET$BVAL.SYS';
  370.  
  371.       OS_Array[1] := 'NET$OS.EXE';
  372.       OS_Array[2] := 'NET$OS.SYS';
  373.  
  374.     End;  { Setup }
  375.  
  376. {+----------------------------------------------------------------------------+}
  377.  
  378.   Procedure Create_Dest_SubDir( Param_Block : StringPtr );
  379.  
  380.     Var
  381.       Regs              :  Reg;
  382.  
  383.     Begin
  384.  
  385.       Set_Preferred_Server( D_Server );
  386.  
  387.       With Dir10_Rquest Do
  388.         Begin
  389.           PathSpec := The_Path;
  390.           Delete( PathSpec, Length( PathSpec ), 1 );
  391.           PacketLength := Length( PathSpec ) + 4;
  392.           Func := 10;
  393.           SourceBase := D_Base;
  394.           AccessMask := Ord( Param_Block^[8] );
  395.         End;
  396.       With Dir10_Rply Do
  397.         ReturnLength := 0;
  398.  
  399.       Regs.A.H := $e2;
  400.       Regs.DS := Segm( Addr( Dir10_Rquest ) );
  401.       Regs.SI := Offs( Addr( Dir10_Rquest ) );
  402.       Regs.ES := Segm( Addr( Dir10_Rply ) );
  403.       Regs.DI := Offs( Addr( Dir10_Rply ) );
  404.  
  405.       Intr( $21, Regs );
  406.  
  407.       With Dir25_Rquest Do
  408.         Begin
  409.           PathSpec := The_Path;
  410.           Delete( PathSpec, Length( PathSpec ), 1 );
  411.           PacketLength := Length( PathSpec ) + 12;
  412.           Func := 25;
  413.           BaseNumber := D_Base;
  414.           Move( Param_Block^[0], CreatDate[1], 9 );
  415.         End;
  416.       With Dir25_Rply Do
  417.         ReturnLength := 0;
  418.  
  419.       Regs.A.H := $e2;
  420.       Regs.DS := Segm( Addr( Dir25_Rquest ) );
  421.       Regs.SI := Offs( Addr( Dir25_Rquest ) );
  422.       Regs.ES := Segm( Addr( Dir25_Rply ) );
  423.       Regs.DI := Offs( Addr( Dir25_Rply ) );
  424.  
  425.       Intr( $21, Regs );
  426.  
  427.     End;  { Create_Dest_SubDir }
  428.  
  429. {+----------------------------------------------------------------------------+}
  430.  
  431.   Procedure Xfer_Directory_Trustees;
  432.  
  433.     Var
  434.       Regs              :  Reg;
  435.       More_Trustees     :  Boolean;
  436.       Idx               :  Integer;
  437.  
  438.     Begin
  439.  
  440.       With Dir12_Rquest Do
  441.         Begin
  442.           PathSpec := The_Path;
  443.           Delete( PathSpec, Length( PathSpec ), 1 );
  444.           PacketLength := Length( PathSpec ) + 4;
  445.           Func := 12;
  446.           SourceBase := S_Base;
  447.           SetNumber := 1;
  448.         End;
  449.  
  450.       With Dir12_Rply Do
  451.         ReturnLength := 49;
  452.  
  453.       With Dir13_Rquest Do
  454.         Begin
  455.           PathSpec := The_Path;
  456.           Delete( PathSpec, Length( PathSpec ), 1 );
  457.           PacketLength := Length( PathSpec ) + 8;
  458.           Func := 13;
  459.           SourceBase := D_Base;
  460.         End;
  461.  
  462.       With Dir13_Rply Do
  463.         ReturnLength := 0;
  464.  
  465.       Repeat
  466.  
  467.         Set_Preferred_Server( S_Server );
  468.  
  469.         Regs.A.H := $e2;
  470.         Regs.DS := Segm( Addr( Dir12_Rquest ) );
  471.         Regs.SI := Offs( Addr( Dir12_Rquest ) );
  472.         Regs.ES := Segm( Addr( Dir12_Rply ) );
  473.         Regs.DI := Offs( Addr( Dir12_Rply ) );
  474.  
  475.         Intr( $21, Regs );
  476.  
  477.         More_Trustees := (Regs.A.L = 0);
  478.  
  479.         If More_Trustees Then
  480.           Begin
  481.             Set_Preferred_Server( D_Server );
  482.             Idx := 1;
  483.             While (Dir12_Rply.Trustee[Idx] <> #0) and (Idx <= 5) Do
  484.               Begin
  485.                 With Dir13_Rquest Do
  486.                   Begin
  487.                     Trustee := Dir12_Rply.Trustee[Idx];
  488.                     AccessMask := Dir12_Rply.TrustMask[Idx];
  489.                   End;
  490.  
  491.                 Regs.A.H := $e2;
  492.                 Regs.DS := Segm( Addr( Dir13_Rquest ) );
  493.                 Regs.SI := Offs( Addr( Dir13_Rquest ) );
  494.                 Regs.ES := Segm( Addr( Dir13_Rply ) );
  495.                 Regs.DI := Offs( Addr( Dir13_Rply ) );
  496.  
  497.                 Intr( $21, Regs );
  498.  
  499.                 Idx := Idx + 1;
  500.               End;
  501.           End;
  502.  
  503.         With Dir12_Rquest Do
  504.           SetNumber := SetNumber + 1;
  505.  
  506.       Until Not More_Trustees;
  507.  
  508.     End;  { Xfer_Directory_Trustees }
  509.  
  510. {+----------------------------------------------------------------------------+}
  511.  
  512.   Procedure Try_Changing_File_Attributes;
  513.  
  514.     Var
  515.       Regs         :  Reg;
  516.       Tmp          :  String;
  517.  
  518.     Begin
  519.  
  520.       Regs.A.H := $43;
  521.       Regs.A.L := 1;
  522.       Regs.C.X := 0;
  523.       Tmp     := Concat( Dest_Drive, Temp, Chr( 0 ) );
  524.       Regs.DS  := Segm( Addr( Tmp[1] ) );
  525.       Regs.D.X := Offs( Addr( Tmp[1] ) );
  526.       Intr( $21, Regs );
  527.  
  528.     End;  { Try_Changing_File_Attributes }
  529.  
  530. {+----------------------------------------------------------------------------+}
  531.  
  532.   Function Bindery_File( FileSpec : String ) : Boolean;
  533.  
  534.     Var
  535.       Temp_Bool         :  Boolean;
  536.       Idx               :  Integer;
  537.  
  538.     Begin
  539.  
  540.       Temp_Bool := False;
  541.       While Pos( '\', FileSpec ) > 0 Do   { strip the path from the filespec }
  542.         Delete( FileSpec, 1, Pos( '\', FileSpec ) );
  543.       For Idx := 1 to Num_Bind_Files Do
  544.         If (Scomp( FileSpec, Bind_Array[Idx] ) = 0) Then
  545.           Temp_Bool := True;
  546.       Bindery_File := Temp_Bool;
  547.  
  548.     End;  { Bindery_File }
  549.  
  550. {+----------------------------------------------------------------------------+}
  551.  
  552.   Function Net_OS( FileSpec : String ) : Boolean;
  553.  
  554.     Var
  555.       Temp_Bool         :  Boolean;
  556.       Idx               :  Integer;
  557.  
  558.     Begin
  559.  
  560.       Temp_Bool := False;
  561.       If OS_Param <> 'OS' Then
  562.         Begin
  563.           While Pos( '\', FileSpec ) > 0 Do   { strip the path from the filespec }
  564.             Delete( FileSpec, 1, Pos( '\', FileSpec ) );
  565.           For Idx := 1 to Num_OS_Files Do
  566.             If (Scomp( FileSpec, OS_Array[Idx] ) = 0) Then
  567.               Temp_Bool := True;
  568.         End;
  569.       Net_OS := Temp_Bool;
  570.  
  571.     End;  { Net_OS }
  572.  
  573. {+----------------------------------------------------------------------------+}
  574.  
  575.   Function Copy_File : Boolean;
  576.  
  577.     Var
  578.       Bind_Closed       :  Boolean;
  579.  
  580.     Begin
  581.  
  582.       Bind_Closed := False;
  583.       CharArray_to_String( Log15_Rply.FileName, Temp );
  584.       Temp := Concat( The_Path, Temp );
  585.  
  586.       If Net_OS( Temp ) Then
  587.         Result := 255
  588.       Else
  589.         Begin
  590.           DOS_Open( Concat( Source_Drive, Temp ), 0, F1_Handle, Result );
  591.  
  592.           If (Result <> 0) and (Bindery_File( Temp )) Then
  593.             Begin
  594.               Set_Preferred_Server( D_Server );
  595.               Close_Bindery;
  596.               Set_Preferred_Server( S_Server );
  597.               Close_Bindery;
  598.               Bind_Closed := True;
  599.               DOS_Open( Concat( Source_Drive, Temp ), 0, F1_Handle, Result );
  600.             End;
  601.  
  602.           If Result <> 0 Then
  603.             Begin
  604.               Set_Preferred_Server( 0 );
  605.               Writeln( Exc_File, 'Unable to open source file ', Source_Drive, Temp );
  606.               Set_Preferred_Server( S_Server );
  607.             End
  608.           Else
  609.             Begin
  610.               DOS_Create( Concat( Dest_Drive, Temp ), F2_Handle, Result );
  611.               If Result <> 0 Then
  612.                 Begin
  613.                   Try_Changing_File_Attributes;
  614.                   DOS_Create( Concat( Dest_Drive, Temp ), F2_Handle, Result );
  615.                 End;
  616.               If Result <> 0 Then
  617.                 Begin
  618.                   Set_Preferred_Server( 0 );
  619.                   Writeln( Exc_File, 'Unable to create destination file ', Dest_Drive, Temp );
  620.                   Set_Preferred_Server( S_Server );
  621.                 End
  622.               Else
  623.                 Begin
  624.                   Writeln( 'Copying ', Source_Drive, Temp );
  625.                   Bytes_Req := -5536;
  626.                   Repeat
  627.                     DOS_VRead( F1_Handle, Addr( Buffer1 ), Bytes_Req, Result );
  628.                     DOS_Write( F2_Handle, Addr( Buffer1 ), Bytes_Req, Result );
  629.                   Until Bytes_Req <> -5536;
  630.                   DOS_Close( F1_Handle, Result );
  631.                   DOS_Close( F2_Handle, Result );
  632.                 End;
  633.             End;
  634.         End;
  635.  
  636.       If Bind_Closed Then
  637.         Begin
  638.           Set_Preferred_Server( D_Server );
  639.           Open_Bindery;
  640.           Set_Preferred_Server( S_Server );
  641.           Open_Bindery;
  642.         End;
  643.  
  644.       Copy_File := (Result = 0);
  645.  
  646.     End;  { Copy_File }
  647.  
  648. {+----------------------------------------------------------------------------+}
  649.  
  650.   Procedure Log_Setup;
  651.  
  652.     Begin
  653.  
  654.       With Log15_Rquest Do
  655.         Begin
  656.           ModPath := Concat( The_Path, '*' );
  657.           Packet_Length := Length( ModPath ) + 6;
  658.           Func := 15;
  659.           Base := S_Base;
  660.           SearchAttributes := 6;
  661.         End;
  662.  
  663.       With Log15_Rply Do
  664.         Begin
  665.           ReturnLength := 94;
  666.           SlotNumber := $ffff;
  667.           SlotNumber := SwapW( SlotNumber );
  668.         End;
  669.  
  670.       With Log16_Rquest Do
  671.         Begin
  672.           Func := 16;
  673.           Base := D_Base;
  674.           SearchAttributes := 6;
  675.         End;
  676.  
  677.       With Log16_Rply Do
  678.         ReturnLength := 0;
  679.  
  680.     End;  { Log_Setup }
  681.  
  682. {+----------------------------------------------------------------------------+}
  683.  
  684.   Procedure Log_Transfer;
  685.  
  686.     Begin
  687.  
  688.       With Log16_Rquest Do
  689.         Begin
  690.           CharArray_to_String( Log15_Rply.FileName, ModPath );
  691.           ModPath := Concat( The_Path, ModPath );
  692.           PacketLength := Length( ModPath ) + 82;
  693.           Move( Log15_Rply.FileAttributes, Log16_Rquest.FileAttributes, 78 );
  694.         End;
  695.  
  696.     End;  { Log_Transfer }
  697.  
  698. {+----------------------------------------------------------------------------+}
  699.  
  700.   Procedure Lookup_Files;
  701.  
  702.     Var
  703.       Sav_Len           :  Integer;
  704.       Regs              :  Reg;
  705.       Dir2_Rquest       :  Dir2_Req;
  706.       Dir2_Rply         :  Dir2_Rep;
  707.  
  708.     Begin
  709.  
  710. (*********************************************************)
  711. (*  Copy all files from source to destination directory  *)
  712. (*********************************************************)
  713.  
  714.       Log_Setup;
  715.  
  716.       Repeat
  717.         Set_Preferred_Server( S_Server );
  718.         Log15_Rquest.LastSlot := Log15_Rply.SlotNumber;
  719.         Regs.A.H := $e3;
  720.         Regs.DS := Segm( Addr( Log15_Rquest ) );
  721.         Regs.SI := Offs( Addr( Log15_Rquest ) );
  722.         Regs.ES := Segm( Addr( Log15_Rply ) );
  723.         Regs.DI := Offs( Addr( Log15_Rply ) );
  724.  
  725.         Intr( $21, Regs );
  726.  
  727.         More_Files := (Regs.A.L = 0);
  728.         If More_Files Then
  729.           If Copy_File Then
  730.             Begin
  731.               Set_Preferred_Server( D_Server );
  732.               Log_Transfer;
  733.               Regs.A.H := $e3;
  734.               Regs.DS := Segm( Addr( Log16_Rquest ) );
  735.               Regs.SI := Offs( Addr( Log16_Rquest ) );
  736.               Regs.ES := Segm( Addr( Log16_Rply ) );
  737.               Regs.DI := Offs( Addr( Log16_Rply ) );
  738.               Intr( $21, Regs );
  739.             End;
  740.  
  741.  
  742.       Until Not More_Files;
  743.  
  744. (**************************************************)
  745. (*  Now look for subdirectories and go recursive  *)
  746. (**************************************************)
  747.  
  748.       Set_Preferred_Server( S_Server );
  749.  
  750.       With Dir2_Rquest Do
  751.         Begin
  752.           PathSpec := Concat( The_Path, '*' );
  753.           PacketLength := Length( PathSpec ) + 5;
  754.           Func := 2;
  755.           SourceBase := S_Base;
  756.           SearchStart := 1;
  757.           SearchStart := SwapW( SearchStart );
  758.         End;
  759.  
  760.       With Dir2_Rply Do
  761.         ReturnLength := 28;
  762.  
  763.       Repeat
  764.  
  765.         Regs.A.H := $e2;
  766.         Regs.DS := Segm( Addr( Dir2_Rquest ) );
  767.         Regs.SI := Offs( Addr( Dir2_Rquest ) );
  768.         Regs.ES := Segm( Addr( Dir2_Rply ) );
  769.         Regs.DI := Offs( Addr( Dir2_Rply ) );
  770.  
  771.         Intr( $21, Regs );
  772.  
  773.         If (Regs.A.L = 0) Then
  774.           Begin
  775.             CharArray_to_String( Dir2_Rply.SubDirName, Temp );
  776.             Sav_Len := Length( Temp );
  777.             The_Path := Concat( The_Path, Temp, '\' );
  778.             Create_Dest_SubDir( Addr( Dir2_Rply.CreatDate[1] ) );
  779.             Xfer_Directory_Trustees;
  780.             Lookup_Files;
  781.             Delete( The_Path, Length( The_Path ) - Sav_Len, Sav_Len + 1 );
  782.           End;
  783.  
  784.         With Dir2_Rply Do
  785.           Begin
  786.             SubDirNumber := SwapW( SubDirNumber );
  787.             SubDirNumber := Short( Long( SubDirNumber ) ) + 1;
  788.           End;
  789.  
  790.         With Dir2_Rquest Do
  791.           Begin
  792.             SearchStart := Dir2_Rply.SubDirNumber;
  793.             SearchStart := SwapW( SearchStart );
  794.           End;
  795.  
  796.       Until Regs.A.L <> 0;
  797.  
  798.     End;  { Lookup_Files }
  799.  
  800. {+----------------------------------------------------------------------------+}
  801.  
  802. Begin  { Main procedure }
  803.  
  804.   Abort := False;
  805.   Setup;
  806.   If Abort Then Exit;
  807.  
  808.   Lookup_Files;
  809.  
  810.   Set_Preferred_Server( 0 );
  811.   Close( Exc_File, Result );
  812.  
  813. End.
  814.