home *** CD-ROM | disk | FTP | other *** search
- MODULE 'workbench/startup', 'dos/dos', 'utility/date', 'utility'
-
- CONST MEMSTART=$600000, BLOCKSIZE=$100, FILEINFOSIZE=$20, MAGIC=$2000
- CONST HEADEROFF=2*BLOCKSIZE, BLKPTRSIZE=2, FILELEN=13, DEL=0, START=0
- CONST FREEOFF=HEADEROFF+BLOCKSIZE, HEADER=HEADEROFF+MEMSTART
- CONST FREEBLOCKS=FREEOFF+MEMSTART, EOFB=$FFFE, EOC=$FFFF, LEN=FILELEN-1
- CONST SECSPERDAY=24*60*60
-
- ENUM NO_ERR, BAD_CARD, NO_FREE, IN_USE, W_PROTECT, SHORT_FILE, DUP_FILE,
- OPEN_ERR, EXAM_ERR, BAD_DIR, TOO_BIG, OPEN_LIB
- ENUM FORCE, FILES
-
- OBJECT fileinfo
- file, next
- ENDOBJECT
-
- RAISE EXAM_ERR IF ExamineFH()=NIL,
- OPEN_ERR IF Open()=NIL,
- OPEN_LIB IF OpenLibrary()=NIL
-
- /* lastinfo is a block pointer with MAGIC, e.g., $213A (not $13A) */
- DEF thefiles:PTR TO fileinfo, lastfile:PTR TO fileinfo, lastinfo
-
- PROC main() HANDLE
- DEF startup:PTR TO wbstartup, wargs:PTR TO wbarg, oldlock=NIL,
- templ, rdargs=NIL, args:PTR TO LONG, i, err
- utilitybase:=OpenLibrary('utility.library', 37)
- getinfo()
- IF (startup:=wbmessage)=NIL
- templ:='FORCE/S,FILE/M'
- args:=[0,0]
- rdargs:=ReadArgs(templ,args,NIL)
- IF rdargs
- IF (err:=checkwrite(args[FORCE]))<>NO_ERR THEN Raise(err)
- IF args:=args[FILES]
- WHILE args[] /* Loop through arguments */
- addfile(args[])
- args++
- ENDWHILE
- ENDIF
- ENDIF
- ELSE
- wargs:=startup.arglist
- wargs++
- FOR i:=1 TO startup.numargs-1 /* Loop through the arguments */
- IF wargs.lock=NIL
- addfile(wargs.name)
- ELSE
- oldlock:=CurrentDir(wargs.lock)
- addfile(wargs.name)
- CurrentDir(oldlock) /* Important: restore current dir */
- oldlock:=NIL
- ENDIF
- wargs++
- ENDFOR
- ENDIF
- Raise(NO_ERR)
- EXCEPT
- setwrite()
- IF oldlock THEN CurrentDir(oldlock)
- IF rdargs THEN FreeArgs(rdargs)
- IF utilitybase THEN CloseLibrary(utilitybase)
- SELECT exception
- CASE OPEN_LIB
- WriteF('Cannot open utility library\n')
- CASE BAD_CARD
- WriteF('No PCMCIA card, or not from Notepad\n')
- CASE IN_USE
- WriteF('PCMCIA card is in use, or not from Notepad\n')
- CASE W_PROTECT
- WriteF('No PCMCIA card, or write protected\n')
- CASE NO_FREE
- WriteF('No more free blocks -- card is full\n')
- ENDSELECT
- ENDPROC
-
- PROC addfile(fname) HANDLE
- DEF fh=NIL, file, b=START, next, len, i=0, going=TRUE,
- f:PTR TO fileinfo, found=NIL, name, fib:fileinfoblock
- fh:=Open(fname, OLDFILE)
- name:=FilePart(fname)
- ExamineFH(fh, fib)
- IF fib.direntrytype>0 THEN Raise(BAD_DIR)
- len:=fib.size
- IF (len<=0) OR (len>$FFFF) THEN Raise(TOO_BIG)
- f:=thefiles.next
- WHILE f
- IF deleted(f.file)
- IF found=NIL THEN found:=f.file
- ELSE
- IF equal(name, filename(f.file)) THEN Raise(DUP_FILE)
- ENDIF
- f:=f.next
- ENDWHILE
- IF found
- file:=found
- ELSE
- file:=FILEINFOSIZE+lastfile.file
- IF Mod(file, BLOCKSIZE)=0
- IF (b:=findfree(b))=EOFB THEN Raise(NO_FREE)
- initblock(b)
- useblock(lastinfo, b)
- lastinfo:=b
- useblock(b, EOC)
- file:=address(b)
- ENDIF
- ENDIF
- IF (b:=findfree(b))=EOFB THEN Raise(NO_FREE)
- lastfile.next:=newfile(file)
- lastfile:=lastfile.next
- setfirstblock(file, b)
- setname(file, name)
- setdate(file, fib.datestamp)
- going:=TRUE
- WHILE (i<len) AND going
- Read(fh, address(b), BLOCKSIZE)
- i:=i+BLOCKSIZE
- IF (next:=findfree(b))=EOFB
- going:=FALSE
- ELSE
- useblock(b, next)
- b:=next
- ENDIF
- ENDWHILE
- useblock(b, EOC)
- IF going=FALSE THEN Raise(SHORT_FILE)
- setsize(file, len)
- Raise(NO_ERR)
- EXCEPT
- IF fh THEN Close(fh)
- SELECT exception
- CASE BAD_DIR
- WriteF('"\s" is a directory\n', fname)
- CASE TOO_BIG
- WriteF('File "\s" is too large (or empty)\n', fname)
- CASE OPEN_ERR
- WriteF('Unable to open file "\s"\n', fname)
- CASE EXAM_ERR
- WriteF('Examine failed on "\s"\n', fname)
- CASE DUP_FILE
- WriteF('File "\s" already exists as "\s"\n', fname, filename(f.file))
- CASE NO_FREE
- Raise(NO_FREE)
- CASE SHORT_FILE
- setsize(file, i)
- WriteF('File "\s" will be short\n', fname)
- Raise(NO_FREE)
- ENDSELECT
- ENDPROC
-
- PROC getinfo()
- DEF info, nofiles=FALSE, atend=FALSE, file, d
- file:=HEADER
- lastinfo:=firstblock(file)
- thefiles:=lastfile:=newfile(file)
- IF validate(file)
- d:=filedate(file)
- file:=file+FILEINFOSIZE
- REPEAT /* for all info blocks */
- REPEAT /* for all files */
- IF blank(file)
- nofiles:=TRUE
- ELSE
- lastfile.next:=newfile(file)
- lastfile:=lastfile.next
- d:=filedate(file)
- file:=file+FILEINFOSIZE
- IF Mod(file, BLOCKSIZE)=0 THEN atend:=TRUE
- ENDIF
- UNTIL atend OR nofiles
- IF atend
- info:=follow(lastinfo)
- IF (info<>EOC) AND (info<>DEL)
- lastinfo:=info
- file:=address(lastinfo)
- atend:=FALSE
- ELSE
- nofiles:=TRUE
- ENDIF
- ENDIF
- UNTIL nofiles
- ELSE
- Raise(BAD_CARD)
- ENDIF
- ENDPROC
-
- PROC checkwrite(force)
- DEF err=NO_ERR, p
- p:=HEADER+12
- Forbid()
- IF (p[]=0) OR force
- p[]:=0
- IF p[]<>0 THEN err:=W_PROTECT
- p[]:=1
- IF p[]<>1 THEN err:=W_PROTECT
- ELSE
- err:=IN_USE
- ENDIF
- Permit()
- ENDPROC err
-
- PROC setwrite()
- DEF p
- p:=HEADER+12
- Forbid()
- p[]:=0
- Permit()
- ENDPROC
-
- PROC equal(s, t)
- DEF a[LEN]:STRING, b[LEN]:STRING
- StrCopy(a, s, ALL)
- StrCopy(b, t, ALL)
- UpperStr(a)
- UpperStr(b)
- RETURN StrCmp(a, b, ALL)
- ENDPROC
-
- PROC follow(block) RETURN int(blockaddr(block))
- PROC blockaddr(block) RETURN (block-MAGIC)*BLKPTRSIZE+FREEBLOCKS
- PROC blockptr(addr) RETURN (addr-FREEBLOCKS)/BLKPTRSIZE+MAGIC
- PROC address(block) RETURN (block-MAGIC)*BLOCKSIZE+MEMSTART
-
- PROC useblock(block, next)
- putint(blockaddr(block), next)
- ENDPROC
-
- PROC initblock(block)
- DEF p, i
- p:=address(block)
- FOR i:=1 TO BLOCKSIZE DO p[]++:=0
- ENDPROC
-
- PROC validate(file)
- RETURN StrCmp(filename(file), 'NC', 2) AND (firstblock(file)=HEADEROFF+MAGIC)
- ENDPROC
-
- PROC blank(file)
- DEF n
- FOR n:=0 TO FILEINFOSIZE-1 DO IF file[]++<>0 THEN RETURN FALSE
- ENDPROC TRUE
-
- PROC newfile(ptr)
- DEF p
- CopyMem([ptr, NIL]:fileinfo, p:=New(SIZEOF fileinfo), SIZEOF fileinfo)
- ENDPROC p
-
- PROC findfree(block)
- DEF p, b
- p:=IF block<>START THEN blockaddr(block+1) ELSE FREEBLOCKS
- WHILE (b:=int(p))<>EOFB
- IF b=0 THEN RETURN blockptr(p)
- p:=p+BLKPTRSIZE
- ENDWHILE
- RETURN EOFB
- ENDPROC
-
- PROC setname(file, name)
- DEF i, p
- p:=file
- FOR i:=0 TO FILELEN DO p[]++:=0
- i:=StrLen(name)
- CopyMem(name, file, IF i>=FILELEN THEN FILELEN-1 ELSE i)
- ENDPROC
-
- PROC setdate(file, ds:PTR TO datestamp)
- DEF secs, cd:clockdata, date
- secs:=Mul(ds.days,SECSPERDAY)+(ds.minute*60)+(ds.tick/50)
- Amiga2Date(secs, cd)
- date:=Shl(cd.year-1990, 25) OR Shl(cd.month, 21) OR Shl(cd.mday, 16) OR
- Shl(cd.hour, 11) OR Shl(cd.min, 5)
- putlong(file+16, date)
- ENDPROC
-
- PROC setsize(file, size)
- putint(file+14, size)
- ENDPROC
-
- PROC setfirstblock(file, block)
- putint(file+20, block)
- ENDPROC
-
- PROC putint(p, v)
- p[]++:=v AND $FF
- p[]:=Shr(v, 8) AND $FF
- ENDPROC
-
- PROC putlong(p, v)
- p[]++:=v AND $FF
- p[]++:=Shr(v, 8) AND $FF
- p[]++:=Shr(v, 16) AND $FF
- p[]:=Shr(v, 24) AND $FF
- ENDPROC
-
- PROC deleted(file) RETURN file[]=0
- PROC filename(file) RETURN file
- /*
- PROC size(file) RETURN int(file+14)
- */
- PROC filedate(file) RETURN long(file+16)
- PROC firstblock(file) RETURN int(file+20)
-
- PROC int(p) RETURN p[]++ OR Shl(p[],8)
- PROC long(p) RETURN p[]++ OR Shl(p[]++,8) OR Shl(p[]++,16) OR Shl(p[],24)
-