Task

Truncate a file to a specific length.   This should be implemented as a routine that takes two parameters: the filename and the required file length (in bytes).



Truncation can be achieved using system or library calls intended for such a task, if such methods exist, or by creating a temporary file of a reduced size and renaming it, after first deleting the original file, if no other method is available.   The file may contain non human readable binary data in an unspecified format, so the routine should be "binary safe", leaving the contents of the untruncated part of the file unchanged.

If the specified filename does not exist, or the provided length is not less than the current file length, then the routine should raise an appropriate error condition.

On some systems, the provided file truncation facilities might not change the file or may extend the file, if the specified length is greater than the current length of the file.

This task permits the use of such facilities.   However, such behaviour should be noted, or optionally a warning message relating to an non change or increase in file size may be implemented.




INCLUDE "D2:IO.ACT" ;from the Action! Tool Kit
 
PROC Dir(CHAR ARRAY filter)
  BYTE dev=[1]
  CHAR ARRAY line(255)
 
  Close(dev)
  Open(dev,filter,6)
  DO
    InputSD(dev,line)
    PrintE(line)
    IF line(0)=0 THEN
      EXIT
    FI
  OD
  Close(dev)
RETURN
 
BYTE FUNC Find(CHAR ARRAY text CHAR c)
  BYTE i
 
  i=1
  WHILE i<=text(0)
  DO
    IF text(i)=c THEN
      RETURN (i)
    FI
    i==+1
  OD
RETURN (0)
 
PROC MakeRenameCommand(CHAR ARRAY left,right,result)
  BYTE i,len,pos
 
  SCopy(result,left)
  len=left(0)+1
  result(len)=32
  pos=Find(right,':)
  FOR i=pos+1 TO right(0)
  DO
    len==+1
    result(len)=right(i)
  OD
  result(0)=len
RETURN
 
PROC DeleteFile(CHAR ARRAY fname)
  BYTE dev=[1]
 
  Close(dev)
  Xio(dev,0,33,0,0,fname)
RETURN
 
PROC TruncateFile(CHAR ARRAY fname CARD maxlen)
  DEFINE BUF_LEN="100"
  CHAR ARRAY tmp="D:TEMP.TMP",cmd(255)
  BYTE in=[1], out=[2]
  BYTE ARRAY buff(BUF_LEN)
  CARD len,size
 
  Close(in)
  Close(out)
  Open(in,fname,4)
  Open(out,tmp,8)
 
  DO
    IF maxlen>BUF_LEN THEN
      size=BUF_LEN
    ELSE
      size=maxlen
    FI
    len=Bget(in,buff,size)
    maxlen==-len
    IF len>0 THEN
      Bput(out,buff,len)
    FI
  UNTIL len#BUF_LEN
  OD
 
  Close(in)
  Close(out)
 
  MakeRenameCommand(tmp,fname,cmd)
  DeleteFile(fname)
  Rename(cmd)
RETURN
 
PROC Main()
  CHAR ARRAY filter="D:*.*", fname="D:INPUT.TXT"
  CARD len=[400]
 
  Put(125) PutE() ;clear screen
 
  PrintF("Dir ""%S""%E",filter)
  Dir(filter)
 
  PrintF("Truncate ""%S"" to %U bytes.%E%E",fname,len)
  TruncateFile(fname,len)
 
  PrintF("Dir ""%S""%E",filter)
  Dir(filter)
RETURN