ðUSyntax10.Scn.Fnt8öÿÿÿpdðIStampElemsAlloc7 Aug 97qªMODULE TarDump; (* Aubrey.McIntosh@mail.utexas.edu *  * This module should dump a standard Unix Tar file, and may be spiffy to read a Tar file from a CD. * It should work on any ETH Oberon system, V3 or V4. CS, 28.08.96, TarDump.OpenText now also works with Windows Oberon files (include a separate header) Extract: now also works with Windows Oberon files (include a separate header), extracting of file rewritten with ReadBytes, WriteBytes *) IMPORT Files, MenuViewers, Oberon, TextFrames, Texts, Viewers, Strings; CONST Namsize = 100; Normal = 0X; Hard = 1X; Symbolic = 2X; TextKey = 496; UnixShow = FALSE; TYPE OberonName = ARRAY 64 OF CHAR; Name = ARRAY Namsize OF CHAR; ObjDesc = RECORD END; BlockDesc = RECORD (ObjDesc) dummy : ARRAY 512 OF CHAR END; Header = POINTER TO HeaderDesc; HeaderDesc = RECORD (ObjDesc) name : Name; mode, uid, gid : ARRAY 8 OF CHAR; size, mtime : ARRAY 12 OF CHAR; chksum : ARRAY 8 OF CHAR; linkflag : CHAR; linkname : Name END; VAR W : Texts.Writer; key : INTEGER; PROCEDURE ConvertOctal( msg : ARRAY OF CHAR; VAR n : LONGINT ); VAR ix : INTEGER; aux : LONGINT; ch : CHAR; BEGIN ix := 0; aux := 0; LOOP IF (ix >= LEN(msg)) OR (msg[ix] = 0X) THEN EXIT END; ch := msg[ix]; IF ( "0" <= ch ) & ( ch <= "7" ) THEN aux := 8*aux - ORD( "0" ) + ORD( ch ) END; INC(ix) END; n := aux END ConvertOctal; PROCEDURE WriteString( msg : ARRAY OF CHAR ); VAR ix : INTEGER; BEGIN ix := 0; LOOP IF (ix >= LEN(msg)) OR (msg[ix] = 0X) THEN EXIT END; Texts.Write( W, msg[ix] ); INC(ix) END END WriteString; PROCEDURE DumpFile( fn : ARRAY OF CHAR ); VAR f : Files.File; r : Files.Rider; header : Header; inc, pos : LONGINT; BEGIN f := Files.Old( fn ); IF f # NIL THEN pos := 0; Texts.WriteString( W, "Filename" ); Texts.Write( W, 09X ); Texts.WriteString( W, "position" ); Texts.Write( W, 09X ); Texts.WriteString( W, "size" ); Texts.Write( W, 09X ); Texts.WriteLn( W ); NEW( header ); LOOP Files.Set( r, f, pos ); Files.ReadBytes( r, header^, SIZE( HeaderDesc )); ConvertOctal( header.size, inc ); IF (inc=0) THEN EXIT END; WriteString( header.name ); Texts.Write( W, 09X ); Texts.WriteInt( W, 512+pos, 8); Texts.Write( W, 09X ); Texts.WriteInt( W, inc, 8); Texts.Write( W, 09X ); IF UnixShow THEN WriteString( header.mode ); Texts.Write( W, 09X ); WriteString( header.uid ); Texts.Write( W, 09X ); WriteString( header.gid ); Texts.Write( W, 09X ); WriteString( header.size ); Texts.Write( W, 09X ); WriteString( header.mtime ); Texts.Write( W, 09X ); WriteString( header.chksum ); Texts.Write( W, 09X ); Texts.Write( W, header.linkflag ); Texts.Write( W, 09X ); WriteString( header.linkname ); Texts.Write( W, 09X ) END; Texts.WriteLn( W ); inc := (( inc + 512 - 1 ) DIV 512) * 512; (*bump to next larger 512 multiple.*) INC( pos, 512 + inc ) END ELSE Texts.WriteString( W, " --- failed " ); END; Texts.WriteLn( W ) END DumpFile; PROCEDURE Directory*; VAR S : Texts.Scanner; t : Texts.Text; beg, end, time : LONGINT; X, Y : INTEGER; V : Viewers.Viewer; BEGIN Texts.OpenScanner( S, Oberon.Par.text, Oberon.Par.pos ); Texts.Scan( S ); IF (S.class = Texts.Char) & (S.c = "^") THEN Oberon.GetSelection( t, beg, end, time ); IF (t#NIL) & ( 0 < time ) THEN Texts.OpenScanner(S, t, beg); Texts.Scan( S ) END END; Texts.WriteString( W, "TarDump.Directory " ); Texts.WriteLn( W ); WHILE (S.class IN {Texts.Name, Texts.String}) DO Texts.WriteString( W, S.s ); Texts.Append ( Oberon.Log, W.buf ); Oberon.AllocateUserViewer( Oberon.Mouse.X, X, Y ); V := MenuViewers.New( TextFrames.NewMenu( S.s, "System.Close System.Copy System.Grow TarDump.OpenText TarDump.Extract " ), TextFrames.NewText ( TextFrames.Text (""), 0 ), TextFrames.menuH, X, Y ); DumpFile( S.s ); Texts.Append ( V.dsc.next(TextFrames.Frame).text, W.buf ); Texts.Scan( S ) END; Texts.Write( W, "~" ); Texts.WriteLn( W ); Texts.Append ( Oberon.Log, W.buf ) END Directory; PROCEDURE OpenText*; VAR S : Texts.Scanner; vtext, text : Texts.Text; pos, beg, end, time : LONGINT; X, Y : INTEGER; tname : ARRAY 64 OF CHAR; fname : Name; r : Files.Rider; f : Files.File; V : Viewers.Viewer; key1, key2 : CHAR; BEGIN IF (Oberon.Par.vwr.dsc = Oberon.Par.frame) (*is menuframe*) THEN (*get tar file name*) Texts.OpenScanner( S, Oberon.Par.text, 0 ); Texts.Scan( S ); COPY( S.s, tname ); Oberon.GetSelection( text, beg, end, time ); IF (text#NIL) & ( 0 < time ) THEN Texts.OpenScanner(S, text, beg); Texts.Scan( S ); (*filename*) COPY( S.s, fname ); Texts.Scan( S ); (*file position*) pos := S.i; END; f := Files.Old( tname ); IF f # NIL THEN Oberon.AllocateUserViewer( Oberon.Mouse.X, X, Y ); Files.Set( r, f, pos ); Files.Read( r, key1 ); Files.Read( r, key2 ); IF (key1 = "o") & (key2 = "B") THEN Files.Set(r, f, pos + 34); Files.Read( r, key1 ); Files.Read( r, key2 ) END ; (*Files.ReadInt( r, key ); (*read the Text key*) *) IF ((key1 = 0F0X) OR (key1 = 01X)) & ((key2 = 0F0X) OR (key2 = 01X)) THEN NEW( vtext ); vtext.notify := TextFrames.NotifyDisplay; Texts.Load( r, vtext ); V := MenuViewers.New( TextFrames.NewMenu( fname, "System.Close System.Copy System.Grow Edit.Search Edit.Replace Edit.Store " ), TextFrames.NewText ( vtext, 0 ), TextFrames.menuH, X, Y ); ELSE Texts.WriteString( W, fname); Texts.WriteString( W, " --- not a Text file. " ); Texts.WriteLn(W) END ELSE Texts.WriteString( W, tname); Texts.WriteString( W, " --- tar file not found. " ); Texts.WriteLn(W) END END; Texts.Append( Oberon.Log, W.buf ) END OpenText; PROCEDURE NoNotify (T: Texts.Text; op: INTEGER; beg, end: LONGINT); END NoNotify; PROCEDURE Extract*; CONST N = 4096; VAR S : Texts.Scanner; tname : ARRAY 64 OF CHAR; fname : Name; vtext, text : Texts.Text; ix, pos, beg, end, size, time, remaining, n : LONGINT; buf: ARRAY N OF CHAR; or, ir : Files.Rider; f, out : Files.File; ch, key1, key2 : CHAR; BEGIN IF (Oberon.Par.vwr.dsc = Oberon.Par.frame) (*is menuframe*) THEN (*get tar file name*) Texts.OpenScanner( S, Oberon.Par.text, 0 ); Texts.Scan( S ); COPY( S.s, tname ); Oberon.GetSelection( text, beg, end, time ); IF (text#NIL) & ( 0 < time ) THEN Texts.OpenScanner(S, text, beg); Texts.Scan( S ); (*filename*) COPY( S.s, fname ); Texts.Scan( S ); (*file position*) pos := S.i; Texts.Scan( S ); (*file size*) size := S.i END; f := Files.Old( tname ); Texts.WriteString( W, tname ); Texts.WriteString( W, " -- " ); Texts.WriteString( W, fname ); IF f # NIL THEN Files.Set(ir, f, pos); Files.Read( ir, key1 ); Files.Read( ir, key2 ); IF (key1 = "o") & (key2 = "B") THEN Files.Set(ir, f, pos + 34); Files.Read( ir, key1 ); Files.Read( ir, key2 ) END ; IF ((key1 = 0F0X) OR (key1 = 01X)) & ((key2 = 0F0X) OR (key2 = 01X)) THEN NEW( vtext ); vtext.notify := NoNotify; Texts.Load(ir, vtext); Texts.Close(vtext, fname) ELSE out := Files.New(fname); Files.Set( or, out, 0 ); Files.Set( ir, f, pos ); remaining := size; WHILE remaining > 0 DO IF remaining > N THEN n := N ELSE n := remaining END ; Files.ReadBytes(ir, buf, n); Files.WriteBytes(or, buf, n); DEC(remaining, n) END ; Files.Register( out ) END ; Texts.WriteString( W, " --- extracted. " ) ELSE Texts.WriteString( W, tname); Texts.WriteString( W, " --- tar file not found. " ); Texts.WriteLn(W) END END; Texts.Append( Oberon.Log, W.buf ) END Extract; BEGIN Texts.OpenWriter( W ) END TarDump.