home *** CD-ROM | disk | FTP | other *** search
- {
- ┌─────────────────────────────────────────────────┐
- │ Joe Forster/STA │
- │ │
- │ FS.PAS │
- │ │
- │ File Split │
- └─────────────────────────────────────────────────┘
- }
-
- {$M 8192, 0, 65536}
-
- uses
- Crt, DOS;
-
- const
- BufferMax = 64512;
- BlankLine = ' ';
- HexaNum : array [0..15] of Char = '0123456789ABCDEF';
- NameLen = 39;
- HeaderEnd : string[40] = ' Start pos End pos Length Remaining';
-
- type
- TBuffer = array [0..BufferMax - 1] of Byte;
- PBuffer = ^TBuffer;
-
- var
- DummyBool,
- OverWrite,
- FreeOk,
- AppendFile,
- DeleteFile,
- ErrorBeep,
- AskNum,
- VolBeep,
- AskExt,
- VolYes,
- AlreadyBeep,
- AutoSize,
- ZeroChunk,
- FirstChunk,
- Esc,
- DelYes,
- DelNo,
- VolOk : Boolean;
- Count,
- Drive : Byte;
- CmdChar,
- Answer : Char;
- ChunkNum,
- Remaining,
- LastChunk,
- NumOk,
- ChunkOk,
- IOError : Integer;
- DecSize,
- FreeSize,
- OrigSize,
- ReadSize,
- ReadDate,
- BigPos,
- ChunkMax,
- ChunkSize,
- CopySize,
- CopiedSize,
- BufferSize : Longint;
- Buffer : PBuffer;
- Ext1,
- Ext2 : ExtStr;
- Name1,
- Name2 : NameStr;
- Dir1,
- Dir2 : DirStr;
- Command,
- DummyStr,
- Header,
- Text,
- ComStr,
- BigStr,
- ChunkStr,
- SizeStr,
- BigName,
- ChunkBase,
- ChunkName : string;
- BigFile,
- ChunkFile : file;
-
- procedure ClrLine;
- begin
- Write(#13, BlankLine, #13);
- end;
-
- function CloneName(Str1, Str2: string): string;
- var
- C : Char;
- I,
- J : Integer;
- S : string;
- begin
- I := 1;
- J := 1;
- S := '';
- while (J <= Length(Str2)) and ((I <= Length(Str1)) or ((Str2[J] <> '?') and (Str2[J] <> '*'))) do
- begin
- if Str2[J] = '?' then
- begin
- C := Str1[I];
- Inc(I);
- Inc(J);
- end
- else
- begin
- if Str2[J] = '*' then
- begin
- C := Str1[I];
- Inc(I);
- end
- else
- begin
- C := Str2[J];
- Inc(I);
- Inc(J);
- end;
- end;
- S := S + C;
- end;
- CloneName := S;
- end;
-
- function MakeName(S: string; L: Integer; F: Boolean): string;
- var
- T : string;
- begin
- T := S;
- if Length(T) > L then T := Copy(T, 1, 3) + '...' + Copy(T, Length(T) - L + 7, L - 6);
- if F then while Length(T) < L do T := T + ' ';
- MakeName := T;
- end;
-
- procedure SplitName(Path: PathStr; var Dir: DirStr; var Name: NameStr; var Ext: ExtStr);
- begin
- FSplit(Path, Dir, Name, Ext);
- if (Ext = '') and (Name = '') then
- begin
- Name := '*';
- Ext := '.**';
- end;
- if Ext = '.' then Ext := '. ';
- end;
-
- function MakeExt(N: Integer): string;
- var
- S : string;
- begin
- Str(N, S);
- while Length(S) < 3 do S := '0' + S;
- MakeExt := S;
- end;
-
- function MakeNum(S: string): Integer;
- var
- I,
- N : Integer;
- begin
- S := Copy(S, 2, 3);
- if (S = '') or (S[1] = '*') then
- begin
- N := 0;
- end
- else
- begin
- I := 1;
- N := 0;
- while (I <= 3) and (N >= 0) do
- begin
- if (S[I] >= '0') and (S[I] <= '9') then N := N * 10 + (Ord(S[I]) - 48) else N := -1;
- Inc(I);
- end;
- end;
- MakeNum := N;
- end;
-
- procedure MakeHeader;
- begin
- if BigPos > 0 then
- begin
- Str(BigPos, Header);
- Header := Command + ' ' + MakeName(BigName + ' at pos ' + Header, 38 - Length(Command), True);
- end
- else
- begin
- Header := Command + ' ' + MakeName(BigName, 38 - Length(Command), True);
- end;
- end;
-
- procedure Percent;
- var
- I : Integer;
- P : Longint;
- S : string;
- begin
- P := ChunkSize div 50;
- if P = 0 then P := 100 else P := CopiedSize div P;
- if P > 100 then P := 100;
- Str(P:3, S);
- Write(' ', S, '% complete', #13);
- end;
-
- procedure Beep; assembler;
- asm
- mov ah, 2;
- mov dl, 7;
- int $21;
- end;
-
- procedure MakeVolBeep;
- begin
- if VolBeep and not AlreadyBeep then Beep;
- AlreadyBeep := True;
- end;
-
- procedure MakeErrorBeep;
- begin
- if ErrorBeep then Beep;
- AlreadyBeep := True;
- end;
-
- function AskStr(Text: string; Len: Integer; Min, Max: Char): string;
- var
- O : Boolean;
- C : Char;
- S : string;
- begin
- ClrLine;
- S := '';
- O := True;
- repeat
- if O then
- begin
- O := False;
- Write(#13, Text, S, ' ', #8);
- end;
- C := UpCase(ReadKey);
- if ((C >= Min) and (C <= Max)) and (Length(S) < Len) then
- begin
- S := S + C;
- O := True;
- end;
- if (C = #8) and (S <> '') then
- begin
- S := Copy(S, 1, Length(S) - 1);
- O := True;
- end;
- if C = #27 then
- begin
- S := '';
- C := #13;
- end;
- until (C = #13);
- ClrLine;
- AskStr := S;
- end;
-
- function Eval(S: string; var Code: Integer): Longint;
- var
- I,
- X : Integer;
- V : Longint;
- begin
- if S[1] = '$' then
- begin
- V := 0;
- I := 2;
- Code := 0;
- while (Code = 0) and (I <= Length(S)) do
- begin
- X := Pos(UpCase(S[I]), HexaNum);
- if X = 0 then Code := I else V := V shl 4 + X - 1;
- Inc(I);
- end;
- end
- else
- begin
- Val(S, V, Code);
- end;
- Eval := V;
- end;
-
- function ReadPar(S: string): Boolean;
- var
- O : Boolean;
- C : Char;
- I : Integer;
- begin
- O := True;
- C := S[1];
- if (C = '/') or (C = '-') then I := 2 else I := 1;
- while O and (I <= Length(S)) do
- begin
- O := False;
- C := UpCase(S[I]);
- if C = 'A' then
- begin
- AppendFile := True;
- O := True;
- end;
- if C = 'D' then
- begin
- DeleteFile := True;
- O := True;
- end;
- if C = 'E' then
- begin
- ErrorBeep := True;
- O := True;
- end;
- if C = 'L' then
- begin
- DecSize := Eval(Copy(S, I + 1, Length(S)), NumOk);
- if NumOk = 0 then I := Length(S) else DecSize := 512;
- O := True;
- end;
- if C = 'N' then
- begin
- LastChunk := Eval(Copy(S, I + 1, Length(S)), NumOk);
- AskNum := (NumOk <> 0);
- if not AskNum then I := Length(S);
- O := True;
- end;
- if C = 'S' then
- begin
- BigPos := Eval(Copy(S, I + 1, Length(S)), NumOk);
- if NumOk = 0 then I := Length(S) else BigPos := 0;
- O := True;
- end;
- if C = 'V' then
- begin
- VolBeep := True;
- O := True;
- end;
- if C = 'X' then
- begin
- AskExt := True;
- O := True;
- end;
- if C = 'Y' then
- begin
- VolYes := True;
- O := True;
- end;
- if O then Inc(I);
- end;
- ReadPar := O;
- end;
-
- function Question(T, A, E: string; B, H: Boolean): Char;
- var
- C : Char;
- begin
- Write(T);
- Write(' (Yes/No');
- if A <> '' then Write('/', A);
- if E <> '' then Write('/', E);
- Write(') ? ');
- if B then Beep;
- repeat
- C := UpCase(ReadKey);
- case C of
- #13: C := 'Y';
- #27: C := 'N';
- end;
- until (H and ((C = 'C') or (C = 'P'))) or ((A <> '') and (C = 'A')) or ((E <> '') and (C = 'E')) or
- (C = 'N') or (C = 'Y');
- Write(C);
- Question := C;
- ClrLine;
- end;
-
- function Query(T, A, E: string; var Y, N: Boolean; Z, B, H: Boolean): Boolean;
- var
- Q : Boolean;
- C : Char;
- X : ExtStr;
- O : NameStr;
- D : DirStr;
- P : string;
- begin
- repeat
- Q := True;
- if (Y or N) and Z then
- begin
- if B then Beep;
- if Y then C := 'Y' else C := 'N';
- end
- else
- begin
- C := Question(T, A, E, B, H);
- if C = 'A' then
- begin
- Y := True;
- N := False;
- C := 'Y';
- end;
- if C = 'E' then
- begin
- Y := False;
- N := True;
- C := 'N';
- end;
- if C = 'C' then
- begin
- GetDir(0, P);
- Exec(GetEnv('COMSPEC'), '');
- ChDir(P);
- MakeHeader;
- WriteLn(Header, HeaderEnd);
- Q := False;
- end;
- if C = 'P' then
- begin
- ClrLine;
- SplitName(ChunkName, D, O, X);
- P := AskStr('Enter new path : ', 61, ' ', #255);
- if P <> '' then
- begin
- if (P[Length(P)] <> ':') and (P[Length(P)] <> '\') then P := P + '\';
- SplitName(P, Dir1, Name1, Ext1);
- if CmdChar = 'A' then
- begin
- ChunkBase := Dir1 + O + '.';
- if ChunkBase[2] = ':' then Drive := Ord(ChunkBase[1]) - 64 else Drive := 0;
- end
- else
- begin
- ChunkBase := Dir1 + O + '.';
- end;
- end;
- ClrLine;
- Q := False;
- end;
- end;
- B := False;
- until Q;
- Query := (C = 'Y');
- end;
-
- function Escape: Boolean;
- var
- B : Boolean;
- C : Word;
- begin
- B := False;
- if KeyPressed then
- begin
- C := Ord(ReadKey);
- if C = 0 then C := 256 + Ord(ReadKey);
- if C = 27 then
- begin
- ClrLine;
- B := (Question('Abort program', '', '', ErrorBeep, False) = 'Y');
- if not B then Percent;
- end;
- end;
- Escape := B;
- end;
-
- function NextVol(N: Integer; Y: Boolean): Boolean;
- var
- T : string;
- begin
- Str(N, T);
- T := 'Process chunk ' + T;
- NextVol := Query(T, 'All yes', '', VolYes, DummyBool, Y, VolBeep and not AlreadyBeep, True);
- AlreadyBeep := True;
- end;
-
- function UpperCase(S: string): string;
- var
- I : Integer;
- T : string;
- begin
- T[0] := Chr(Length(S));
- for I := 1 to Length(S) do T[I] := UpCase(S[I]);
- UpperCase := T;
- end;
-
- begin
- WriteLn('File Split by Joe Forster/STA');
- WriteLn;
- ComStr := UpperCase(ParamStr(1));
- CmdChar := ComStr[1];
- if (ParamCount = 0) or (((CmdChar = '/') or (CmdChar = '-')) and ((ComStr[2] = '?') or (ComStr[2] = 'H'))) then
- begin
- WriteLn('This program splits big files into smaller chunks that can easily be carried');
- WriteLn('on floppy disks and builds the chunks back to the original big file. During the');
- WriteLn('splitting the extension and the size of the big file is stored in the 0th chunk');
- WriteLn('so that there is no additional information in the normal chunks.');
- WriteLn;
- WriteLn('Usage: FS <command> <chunkfile> [<bigfile>] [<chunksize>] [-|/<options>]');
- WriteLn;
- WriteLn('Commands:');
- WriteLn(' A: Split up big file into chunks X: Build chunks into big file');
- WriteLn;
- WriteLn('Chunk sizes:');
- WriteLn(' A[UTO]: Auto-detect free space xxxx[K]: Maximum of xxxx [K]B chunks');
- WriteLn(' 1.2[M]: 1.2 MB chunks 1.44[M]: 1.44 MB chunks');
- WriteLn;
- WriteLn('Options:');
- WriteLn(' A: Append big file if exists Sxxxx: Start splitting from pos xxxx');
- WriteLn(' D: Delete processed files V: Beep between chunks');
- WriteLn(' E: Beep on errors X: Ask extension of big file');
- WriteLn('Lxxxx: Dec length of first chunk with xxxx Y: All yes on next chunk query');
- WriteLn('N[xx]: Last chunk is #xx (ask if not given)');
- end
- else
- begin
- if (CmdChar <> 'A') and (CmdChar <> 'X') then
- begin
- WriteLn('Invalid command');
- end
- else
- begin
- AutoSize := False;
- AppendFile := False;
- DeleteFile := False;
- ErrorBeep := False;
- AskNum := False;
- VolBeep := False;
- AskExt := False;
- VolYes := False;
- DelYes := False;
- ZeroChunk := False;
- FirstChunk := True;
- AlreadyBeep := True;
- LastChunk := 0;
- BigPos := 0;
- DecSize := 512;
- ChunkSize := 0;
- OrigSize := 0;
- CmdChar := ComStr[1];
- ChunkStr := UpperCase(ParamStr(2));
- ComStr := UpperCase(ParamStr(3));
- BigStr := ComStr;
- if (CmdChar = 'X') and ((BigStr[1] = '-') or (BigStr[1] = '/')) then BigStr := '';
- SizeStr := UpperCase(ParamStr(4));
- if SizeStr <> '' then if (SizeStr[1] = '-') or (SizeStr[1] = '/') then SizeStr := '';
- SplitName(ChunkStr, Dir1, Name1, Ext1);
- SplitName(BigStr, Dir2, Name2, Ext2);
- if ((CmdChar = 'A') and (ParamCount < 3)) or ((CmdChar = 'X') and (ParamCount < 2)) then
- begin
- WriteLn('Parameters missing');
- end
- else
- begin
- if (CmdChar = 'A') and (SizeStr <> '') then Count := 5 else
- if (CmdChar = 'X') and ((ParamCount < 3) or (ComStr[1] = '-') or (ComStr[1] = '/')) then
- Count := 3 else Count := 4;
- while (Count <= ParamCount) and ReadPar(ParamStr(Count)) do Inc(Count);
- if Count <= ParamCount then
- begin
- WriteLn('Invalid switch: ', UpperCase(ParamStr(Count)));
- end
- else
- begin
- if CmdChar = 'A' then
- begin
- ChunkOk := MaxInt;
- if (SizeStr = '') or (SizeStr = 'A') or (SizeStr = 'AUTO') then
- begin
- AutoSize := True;
- ChunkMax := MaxLongInt;
- ChunkOk := 0;
- end
- else
- begin
- ChunkMax := 0;
- ChunkOk := 0;
- if Copy(SizeStr, 1, 3) = '1.2' then ChunkMax := 1213952;
- if Copy(SizeStr, 1, 4) = '1.44' then ChunkMax := 1457664;
- if ChunkMax = 0 then
- begin
- if SizeStr[Length(SizeStr)] = 'K' then ChunkMax := Eval(Copy(SizeStr, 1, Length(SizeStr) - 1), ChunkOk) shl 10
- else ChunkMax := Eval(SizeStr, ChunkOk);
- if (ChunkOk <> 0) or (ChunkMax = 0) or (ChunkMax >= MaxLongint shr 10) then
- begin
- WriteLn('Invalid chunk size');
- MakeErrorBeep;
- ChunkOk := 1;
- end
- else
- begin
- ChunkOk := 0;
- end;
- end;
- end;
- if ChunkOk = 0 then
- begin
- ChunkBase := Dir1 + CloneName(Name2, Name1) + '.';
- BigName := BigStr;
- ChunkNum := MakeNum(Ext1);
- if ChunkNum < 0 then
- begin
- WriteLn('Invalid chunk number');
- MakeErrorBeep;
- end
- else
- begin
- if (BigPos > 0) and (ChunkNum = 0) then ChunkNum := 1;
- if ChunkBase[2] = ':' then Drive := Ord(ChunkBase[1]) - 64 else Drive := 0;
- Assign(BigFile, BigName);
- FileMode := 0;
- Reset(BigFile, 1);
- IOError := IOResult;
- if (IOError = 0) and (FileSize(BigFile) >= BigPos) then
- begin
- GetFTime(BigFile, ReadDate);
- ReadSize := FileSize(BigFile) - BigPos;
- Command := 'Splitting';
- MakeHeader;
- Close(BigFile);
- while (ReadSize > 0) and (IOResult = 0) do
- begin
- VolOk := False;
- if ChunkSize = 0 then if ReadSize > ChunkMax then ChunkSize := ChunkMax else ChunkSize := ReadSize;
- FreeSize := DiskFree(Drive);
- if (FreeSize = 0) or (FreeSize = -1) then
- begin
- ClrLine;
- if FreeSize = 0 then Write('Disk full. ') else Write('Drive not ready. ');
- if not NextVol(ChunkNum, False) then ReadSize := 0;
- end
- else
- begin
- if ChunkMax = MaxLongInt then
- if ReadSize > FreeSize then ChunkSize := FreeSize else ChunkSize := ReadSize;
- if ChunkSize > FreeSize then
- begin
- Str(FreeSize, Text);
- Text := 'Insufficient free space - ' + Text + ' bytes. Try again';
- ClrLine;
- Answer := Question(Text, 'use All space', '', ErrorBeep, False);
- if Answer = 'N' then ReadSize := 0;
- if Answer = 'A' then if ReadSize > FreeSize then ChunkSize := FreeSize else ChunkSize := ReadSize;
- end
- else
- begin
- FileMode := 0;
- Reset(BigFile, 1);
- if IOResult = 0 then
- begin
- Seek(BigFile, BigPos);
- ChunkName := ChunkBase + MakeExt(ChunkNum);
- AlreadyBeep := False;
- Assign(ChunkFile, ChunkName);
- Reset(ChunkFile, 1);
- if IOResult = 0 then
- begin
- Close(BigFile);
- Close(ChunkFile);
- ClrLine;
- if Question(MakeName(ChunkName, 35, False) + ' already exists. Overwrite', '', '',
- ErrorBeep, False) = 'Y' then Erase(ChunkFile) else ReadSize := 0;
- ChunkSize := 0;
- end
- else
- begin
- Rewrite(ChunkFile, 1);
- if IOResult = 0 then
- begin
- if ZeroChunk and (ChunkNum = 1) and not AutoSize and (ChunkSize <> ReadSize) and
- (ChunkSize > DecSize) then Dec(ChunkSize, DecSize);
- if ChunkNum > 0 then Dec(ReadSize, ChunkSize);
- ClrLine;
- if FirstChunk then WriteLn(Header, HeaderEnd);
- Write(MakeName(ChunkName, NameLen, True));
- if ChunkNum > 0 then
- begin
- Write(BigPos:10, (BigPos + ChunkSize):10, ChunkSize:10);
- if ReadSize > 0 then Write(ReadSize:10);
- end;
- WriteLn;
- New(Buffer);
- if ChunkNum = 0 then
- begin
- ZeroChunk := True;
- CopySize := 7;
- FillChar(Buffer^, 7, 0);
- if Ext2 <> '' then for Count := 1 to Length(Ext2) do
- Buffer^[Count - 1] := Ord(Ext2[Count + 1]);
- Move(ReadSize, Buffer^[3], 4);
- end
- else
- begin
- CopySize := ChunkSize;
- end;
- CopiedSize := 0;
- Percent;
- IOError := IOResult;
- Esc := Escape;
- while (CopySize > 0) and (IOError = 0) and not Esc do
- begin
- if CopySize > BufferMax then BufferSize := BufferMax else BufferSize := CopySize;
- Dec(CopySize, BufferSize);
- if ChunkNum > 0 then BlockRead(BigFile, Buffer^, BufferSize);
- Inc(CopiedSize, BufferSize);
- Percent;
- Esc := Escape;
- if not Esc then
- begin
- BlockWrite(ChunkFile, Buffer^, BufferSize);
- Inc(CopiedSize, BufferSize);
- Percent;
- Esc := Escape;
- end;
- IOError := IOResult;
- end;
- Dispose(Buffer);
- SetFTime(ChunkFile, ReadDate);
- Close(ChunkFile);
- Close(BigFile);
- ClrLine;
- if Esc then
- begin
- ReadSize := 0;
- VolOk := False;
- Write('Deleting ', MakeName(ChunkName, 70, False));
- Erase(ChunkFile);
- ClrLine;
- end
- else
- begin
- if IOError = 0 then
- begin
- if ChunkNum > 0 then Inc(BigPos, ChunkSize);
- Inc(ChunkNum);
- ChunkSize := 0;
- VolOk := True;
- end;
- FirstChunk := False;
- end;
- end
- else
- begin
- Close(BigFile);
- ClrLine;
- Write(MakeName(ChunkName, 23, False) , ' cannot be created. ');
- if ErrorBeep then
- begin
- AlreadyBeep := True;
- Beep;
- end;
- if not NextVol(ChunkNum, False) then ReadSize := 0;
- ChunkSize := 0;
- end;
- end;
- if (ReadSize > 0) and VolOk then
- begin
- ClrLine;
- VolOk := False;
- if not ZeroChunk or (ChunkNum > 1) then if not NextVol(ChunkNum, True) then ReadSize := 0;
- end
- else
- begin
- MakeVolBeep;
- end;
- end
- else
- begin
- WriteLn(MakeName(BigName, 69, False), ' not found');
- MakeErrorBeep;
- end;
- end;
- end;
- end;
- if (ReadSize = 0) and VolOk and DeleteFile then
- begin
- if Query('Delete ' + BigName, '', '', DummyBool, DummyBool, False, False, False) then
- begin
- Write('Deleting ', MakeName(BigName, 70, False));
- Erase(BigFile);
- ClrLine;
- end;
- end;
- end
- else
- begin
- if IOError = 0 then WriteLn(MakeName(BigName, 69, False), ' too short') else
- WriteLn(MakeName(BigName, 69, False), ' not found');
- MakeErrorBeep;
- end;
- end;
- end;
- end;
- if CmdChar = 'X' then
- begin
- ChunkBase := Dir1 + Name1 + '.';
- BigName := Dir2 + CloneName(Name1, Name2);
- ChunkNum := MakeNum(Ext1);
- if ChunkNum < 0 then
- begin
- WriteLn('Invalid chunk number');
- end
- else
- begin
- if AskNum then Val(AskStr('Enter number of last chunk : ', 3, '0', '9'), LastChunk, ChunkOk);
- if ChunkNum > 0 then if Ext2 <> '.**' then BigName := BigName + CloneName(Ext1, Ext2) else
- if AskExt then BigName := BigName + '.' + AskStr('Enter extension of big file : ', 3, '!', #255);
- if BigName[Length(BigName)] = '.' then BigName := Copy(BigName, 1, Length(BigName) - 1);
- if BigName[2] = ':' then Drive := Ord(BigName[1]) - 64 else Drive := 0;
- ChunkOk := MaxInt;
- OverWrite := False;
- ReadSize := MaxLongInt;
- if ChunkNum = 0 then
- begin
- ChunkName := ChunkBase + MakeExt(ChunkNum);
- Assign(ChunkFile, ChunkName);
- FileMode := 0;
- while (ChunkOk > 0) and (ReadSize > 0) do
- begin
- Reset(ChunkFile, 1);
- if IOResult = 0 then
- begin
- New(Buffer);
- BlockRead(ChunkFile, Buffer^, 7);
- Close(ChunkFile);
- Count := 0;
- Ext2 := '';
- while (Count < 3) and (Buffer^[Count] <> 0) do
- begin
- Ext2 := Ext2 + Chr(Buffer^[Count]);
- Inc(Count);
- end;
- if Ext2 <> '' then BigName := BigName + '.' + Ext2;
- Move(Buffer^[3], OrigSize, 4);
- Dispose(Buffer);
- ChunkOk := 0;
- Inc(ChunkNum);
- if DeleteFile then
- begin
- AlreadyBeep := True;
- if Query('Delete ' + MakeName(ChunkName, 31, False), 'Always', 'nEver', DelYes, DelNo,
- True, VolBeep, False) then
- begin
- ClrLine;
- Write('Deleting ', MakeName(ChunkName, 70, False));
- Erase(ChunkFile);
- ClrLine;
- end;
- end;
- end
- else
- begin
- ClrLine;
- Write(MakeName(ChunkName, 31, False), ' not found. ');
- MakeErrorBeep;
- if not NextVol(ChunkNum, False) then ReadSize := 0;
- end;
- end;
- end;
- if ReadSize > 0 then
- begin
- ChunkOk := MaxInt;
- Assign(BigFile, BigName);
- FileMode := 2;
- Reset(BigFile, 1);
- IOError := IOResult;
- if IOError = 0 then
- begin
- BigPos := FileSize(BigFile);
- Close(BigFile);
- if AppendFile then Answer := 'A' else Answer :=
- Question(MakeName(BigName, 35, False) + ' already exists. Overwrite', 'Append', '', ErrorBeep, False);
- if Answer = 'Y' then
- begin
- OverWrite := True;
- ChunkOk := 0;
- BigPos := 0;
- end;
- if Answer = 'A' then ChunkOk := 0;
- end
- else
- begin
- if (IOError >= 2) and (IOError <= 5) then
- begin
- OverWrite := True;
- ChunkOk := 0;
- BigPos := 0;
- end;
- end;
- if ChunkOk = 0 then
- begin
- ClrLine;
- Command := 'Building';
- MakeHeader;
- if OrigSize = 0 then ReadSize := MaxLongInt else ReadSize := OrigSize;
- while (ReadSize > 0) and (IOResult = 0) do
- begin
- VolOk := False;
- ChunkName := ChunkBase + MakeExt(ChunkNum);
- Assign(ChunkFile, ChunkName);
- FileMode := 0;
- Reset(ChunkFile, 1);
- if IOResult = 0 then
- begin
- GetFTime(ChunkFile, ReadDate);
- ChunkSize := FileSize(ChunkFile);
- FreeSize := DiskFree(Drive);
- if FreeSize = 0 then
- begin
- Close(ChunkFile);
- ClrLine;
- Write('Disk full. ');
- if not NextVol(ChunkNum, False) then ReadSize := 0;
- end
- else
- begin
- if ChunkSize > FreeSize then
- begin
- Close(ChunkFile);
- Str(FreeSize, Text);
- Text := 'Insufficient free space - ' + Text + ' bytes. Try again';
- ClrLine;
- Answer := Question(Text, 'use All space', '', ErrorBeep, False);
- if Answer = 'N' then ReadSize := 0;
- if Answer = 'A' then ChunkSize := FreeSize;
- end
- else
- begin
- if OverWrite then
- begin
- Rewrite(BigFile, 1);
- end
- else
- begin
- FileMode := 2;
- Reset(BigFile, 1);
- end;
- AlreadyBeep := False;
- if IOResult = 0 then
- begin
- Seek(BigFile, BigPos);
- Dec(ReadSize, ChunkSize);
- ClrLine;
- if FirstChunk then WriteLn(Header, HeaderEnd);
- Write(MakeName(ChunkName, NameLen, True), BigPos:10, (BigPos + ChunkSize):10, ChunkSize:10);
- if OrigSize = 0 then
- begin
- Remaining := LastChunk - ChunkNum;
- if (LastChunk > 0) and (Remaining > 0) then
- if Remaining = 1 then Write( ' 1 file ') else Write(Remaining:4, ' files');
- end
- else
- begin
- if ReadSize > 0 then Write(ReadSize:10);
- end;
- WriteLn;
- New(Buffer);
- CopySize := ChunkSize;
- CopiedSize := 0;
- Percent;
- IOError := IOResult;
- Esc := Escape;
- while (CopySize > 0) and (IOError = 0) and not Esc do
- begin
- if CopySize > BufferMax then BufferSize := BufferMax else BufferSize := CopySize;
- Dec(CopySize, BufferSize);
- BlockRead(ChunkFile, Buffer^, BufferSize);
- Inc(CopiedSize, BufferSize);
- Percent;
- Esc := Escape;
- if not Esc then
- begin
- BlockWrite(BigFile, Buffer^, BufferSize);
- Inc(CopiedSize, BufferSize);
- Percent;
- Esc := Escape;
- end;
- IOError := IOResult;
- end;
- Dispose(Buffer);
- SetFTime(BigFile, ReadDate);
- Close(ChunkFile);
- Close(BigFile);
- ClrLine;
- if Esc then
- begin
- ReadSize := 0;
- VolOk := False;
- if BigPos = 0 then
- begin
- Write('Deleting ', MakeName(BigName, 70, False));
- Erase(BigFile);
- ClrLine;
- end
- else
- begin
- Write('Truncating ', MakeName(BigName, 50, False), ' at pos ', BigPos);
- FileMode := 2;
- Reset(BigFile, 1);
- Seek(BigFile, BigPos);
- Truncate(BigFile);
- SetFTime(BigFile, ReadDate);
- Close(BigFile);
- ClrLine;
- end;
- end
- else
- begin
- if IOError = 0 then
- begin
- if DeleteFile then
- begin
- AlreadyBeep := True;
- if Query('Delete ' + MakeName(ChunkName, 31, False), 'Always', 'nEver', DelYes, DelNo,
- True, VolBeep, False) then
- begin
- ClrLine;
- Write('Deleting ', MakeName(ChunkName, 70, False));
- Erase(ChunkFile);
- ClrLine;
- end;
- end;
- Inc(BigPos, ChunkSize);
- Inc(ChunkNum);
- ChunkSize := 0;
- VolOk := True;
- OverWrite := False;
- end;
- FirstChunk := False;
- end;
- end
- else
- begin
- Close(ChunkFile);
- ClrLine;
- if OverWrite then Write(MakeName(BigName, 23, False) , ' cannot be created. ') else
- Write(MakeName(BigName, 22, False) , ' cannot be appended. ');
- MakeErrorBeep;
- if not NextVol(ChunkNum, False) then ReadSize := 0;
- ChunkSize := 0;
- end;
- if (ReadSize > 0) and VolOk then
- begin
- ClrLine;
- if ((LastChunk <> 0) and (LastChunk + 1 = ChunkNum)) or not NextVol(ChunkNum, True) then
- ReadSize := 0;
- end
- else
- begin
- MakeVolBeep;
- end;
- end;
- end;
- end
- else
- begin
- ClrLine;
- Write(MakeName(ChunkName, 31, False), ' not found. ');
- MakeErrorBeep;
- if not NextVol(ChunkNum, False) then ReadSize := 0;
- end;
- end;
- end;
- end;
- end;
- end;
- end;
- end;
- ClrLine;
- end;
- end;
- end.
-