;   ReDate 1.1/ SetDate DIRs according to contents
;        - Jim Butterfield.  April 7/90.
; Exec library calls
_LVOAllocMem          EQU -$C6
_LVOFreeMem           EQU -$D2
_LVOFindTask          EQU -$126
_LVOSetSignal         EQU -$132
_LVOAllocSignal       EQU -$14A
_LVOFreeSignal        EQU -$150
_LVOPutMsg            EQU -$16E
_LVOGetMsg            EQU -$174
_LVOWaitPort          EQU -$180
_LVOCloseLibrary      EQU -$19E
_LVOOpenLibrary       EQU -$228
; DOS library calls
_LVOOpen              EQU -$1E
_LVOClose             EQU -$24
_LVORead              EQU -$2A
_LVOWrite             EQU -$30
_LVOOutput            EQU -$3C
_LVOLock              EQU -$54
_LVOUnLock            EQU -$5A
_LVOExamine           EQU -$66
_LVOExNext            EQU -$6C
_LVOCurrentDir        EQU -$7E
_LVOIoErr             EQU -$84
_LVODeviceProc        EQU -$AE
;
ACCESS_READ            equ -2
MODE_OLDFILE           equ 1005
INFOSIZE               equ 260
; sizeof (struct MsgPort+struct Message+struct DosPacket+108+4)
DATASIZE               equ $24+$14+$30+112
; FileInfoBlock items
fib_FileName           equ 8
fib_EntryType          equ 120
fib_Date               equ 132
; IO Error Type
NO_MORE_ENTRIES        equ 232
;
;-- Initial setup:
;        offsets from A5 (Globals)
FileErr   equ -4
; Level not needed this version, but might be useful for expansion
Level     equ -8
DevProc   equ -12
dosBase   equ -16
argv      equ -20
OutHandle equ -24
DataBlk   equ -28    ;Mport/Msg/dos packet/Name block
message   equ -32
DosPkt    equ -36
Nope      equ -37    ;byte .. update didn't work
Yup       equ -38    ;byte .. update worked
Mebbe     equ -39    ;byte .. update tried
Abort     equ -40    ;byte

go     link   a5,#-40         ; common work area
       moveq  #0,d1
       move.l d1,Abort(a5)    ; four bytes
       move.b d1,-1(a0,d0)    ; c style string
spdump move.b (a0)+,d0        ; skip init spaces
       cmp.b  #$20,d0
       beq.s  spdump
       move.b -(a0),d7        ; grab first char
       move.l a0,argv(a5)
;**  Level=0;
       move.l d1,Level(a5)
; set up dos, DevProc, output, here
       moveq  #1,d0
       move.l d0,FileErr(a5)
       moveq  #20,d6            ; return FAIL
       lea    dosname(pc),a1    ; Name 'dos.library'.
       moveq  #33,d0            ;   1.2 or later
       move.l $4,a6             ;   Using Exec library
       jsr    _LVOOpenLibrary(a6)  ;   Open Dos library.
       move.l d0,dosBase(a5)    ; Remember DosBase ptr.
       beq    StartupQuit       ;      dos not opened
       move.l d0,a6             ; set Dos library
       jsr    _LVOOutput(a6)    ;   get CLI outhandle,
       move.l d0,OutHandle(a5)       ;   & then remember it.
       tst.b  d7                ; no file name?
       beq    Prompt
       move.l argv(a5),d1       ; file name
       jsr    _LVODeviceProc(A6)
       move.l d0,DevProc(a5)    ; device handler
       beq    DosQuit
; MakePort(Az=0,D7=0)
       move.l 4,a6              ; exec library 
       move.l #DATASIZE,d0
       move.l  #$10001,d1       ;public|clear
       jsr     _LVOAllocMem(a6)
       move.l  d0,a3
       move.l  a3,DataBlk(a5)
       beq     DosQuit
       lea     $24(a3),a0   ;keep longword alignment!
       move.l  a0,message(a5)
       lea     $14(a0),a0
       move.l  a0,DosPkt(a5)
; make the port .. alloc signal
       moveq   #-1,d0
       jsr     _LVOAllocSignal(a6)
       cmp.b   #$FF,d0
       beq.s   _NoSignal      ;couldn't get signal
       move.b  d0,15(a3)      ;mp_SigBit
       move.b  #4,8(a3)       ;mp_Node.ln_Type=NT_MSGPORT
       clr.b   14(a3)         ;mp_Flags=PA_SIGNAL
       sub.l   a1,a1
       jsr     _LVOFindTask(a6)
       move.l  d0,$10(a3)     ;*mp_SigTask
; construct empty MsgList
       lea     $18(a3),a0     ;mp_MsgList.lh_Tail (contns 0)
       move.l  a0,$14(a3)     ; to mp_MsgList.lh_Head
       lea     $14(a3),A0     ;mp_MsgList.lh_Head
       move.l  a0,$1C(a3)     ; to mp_MsgList.lhTailPred
       clr.l   $18(a3)        ;mp_MsgList.lh_Tail
       move.b  #2,$20(a3)     ;mp_MsgList.lh_type
;**    GetToWork(argv[1]);
       move.l argv(a5),a0
       bsr    GetToWork

; Wind up port here; Scrap(A3=address)
        move.l  DataBlk(a5),a3
	MOVE.B	#$FF,8(A3)
	MOVEQ	#-1,D0
	MOVE.L	D0,$14(A3)
	MOVEQ	#0,D0
	MOVE.B	15(A3),D0
	MOVE.L	4,A6
	JSR	_LVOFreeSignal(A6)
; Can't get the signal
_NoSignal	MOVE.L	A3,A1
	MOVE.L	#DATASIZE,D0       
	JSR	_LVOFreeMem(A6)
; Can't get the allocate
DosQuit  move.l dosBase(a5),a6    ; set Dos Library

;**    switch (FileErr)
       move.l argv(a5),a0
       move.l FileErr(a5),d0
;**      {
;**      case 0:
       bne.s  Ncase0
       tst.b  Yup(a5)
       beq.s  NotYup
       moveq  #0,d6            ; return OK
       move.l OutHandle(a5),d1 ; file handle
       lea    SDupMsg(pc),a1
       move.l a1,d2            ; outbuffer
       moveq  #SDupLen,d3      ; length
       jsr    _LVOWrite(A6)

NotYup tst.b  Nope(a5)
       beq.s  NotNo
       moveq  #5,d6             ; return WARN
       move.l OutHandle(a5),d1  ; file handle
       lea    SDnupMsg(pc),a1
       move.l a1,d2             ; outbuffer
       moveq  #SDnupLen,d3      ; length
       jsr    _LVOWrite(A6)

NotNo  tst.b  Mebbe(a5)
       bne.s  endSwitch
       moveq  #10,d6            ; return ERROR
       move.l OutHandle(a5),d1  ; file handle
       lea    SDnfMsg(pc),a1 
       move.l a1,d2             ; outbuffer
       moveq  #SDnfLen,d3       ; length
       jsr    _LVOWrite(A6)
;**        break;
       bra.s  endSwitch
;**      case 1:
;**        printf("Out of Memory\n");
Ncase0 cmp.l  #1,d0
       bne.s  Ncase1
       move.l OutHandle(a5),d1  ;file handle
       lea    NoMemMsg(pc),a1
       move.l a1,d2             ;outbuffer
       moveq  #NoMemLen,d3      ;length
       jsr    _LVOWrite(A6)
;**        break;
       bra.s  endSwitch
;**      case 2:
;**        printf("Can't find directory.\n");
Ncase1      cmp.l  #2,d0
       bne.s  endSwitch
       move.l OutHandle(a5),d1  ;file handle
       lea    NoFileMsg(pc),a1
       move.l a1,d2             ;outbuffer
       moveq  #NoFileLen,d3     ;length
       jsr    _LVOWrite(A6)
endSwitch   bra.s  LastGasp
;**      }
;**    }
;**  else printf("FORMAT:  ReDate <DirectoryName>\n");
Prompt      move.l OutHandle(a5),d1
       lea    PromptMsg(pc),a1
       move.l a1,d2
       moveq  #PromptLen,d3
       jsr    _LVOWrite(A6)
       moveq  #0,d6             ; return OK
;**  }
LastGasp: move.l dosBase(a5),a1 ; DosBase to a1;
       move.l $4,a6             ; using Exec library,
       jsr    _LVOCloseLibrary(a6)   ;   close Dos library.
StartupQuit unlk   a5
       move.l d6,d0                  ; return code
       rts                           ; End of Program

;** *struct DateStamp GetToWork(char * Name)
;**  {
;**  unsigned long newLock, oldLock;
;**  struct FileInfoBlock *fibb;
;**  char *NameSave;
;            offsets from A4
Days        equ    -4
Minutes     equ    -8
Ticks       equ    -12
newLock     equ    -16
oldLock     equ    -20
fibb        equ    -24
NameSave    equ    -28

GetToWork     link   A4,#-28
       move.l a0,NameSave(a4)
;**  Date[]=0;
       moveq  #90,d0         ;for April 1 1978
       move.l d0,Days(a4)
       move.l d0,Minutes(a4)
       move.l d0,Ticks(a4)
;**  FileErr =1;   /* Alloc error */
       moveq  #1,d0
       move.l d0,FileErr(a5)
;**  if ((fibb = AllocMem(INFOSIZE,0)) != 0)
       move.l $4,a6             ; this calls for Exec
       moveq  #0,d1             ; any type of memory
       move.l #INFOSIZE,d0      ; size of block needed
       jsr    _LVOAllocMem(a6)  ; go get it
       move.l dosBase(a5),a6    ; restore Dos Library
       move.l d0,fibb(a4)       ; save the block address
       beq    GDExit            ; quit if no memory
;**    {
;**      FileErr =2;   /* file unreadable */
       moveq  #2,d0
       move.l d0,FileErr(a5)
;**      if ((newLock = Lock(Name,ACCESS_READ)) != 0)
       move.l NameSave(a4),d1
       moveq  #ACCESS_READ,D2   ; get a read lock
       jsr    _LVOLock(a6)
       move.l d0,newLock(a4)    ; store the lock pointer
       beq    DropMem           ; couldn't get lock
;**      { if ((Examine(newLock,fibb)) != 0)
       move.l d0,d1             ; lock
       move.l fibb(a4),d2       ; file info block address
       jsr _LVOExamine(a6)      ; go for the data
;   Assume Examine never fails.  Go for the data.
;**        {
;**        FileErr =0;    /* got file, normal error sequence */
       moveq  #0,d0
       move.l d0,FileErr(a5)
;**        if (fibb->fib_EntryType < 0)
       move.l fibb(a4),a3       ; file info block address
       move.l fib_EntryType(a3),d0
       bpl.s  DirLoop
;**          {
;**          printf(" Not a Directory!/n");
       move.l OutHandle(a5),d1
       lea    NotDirMsg(pc),a1
       move.l a1,d2
       moveq  #NotDirLen,d3
       jsr    _LVOWrite(A6)
       bra    DropLock
;**        else
DirLoop:
;**    {
;**            if ((ExNext(newLock,fibb)) == 0)
       move.l newLock(a4),d1   ; lock
       move.l fibb(a4),d2      ; file info block address
       jsr    _LVOExNext(a6)      ; go for the data
       tst.l  d0
       beq    DropLock
;**         {
;**              if (fibb->fib_EntryType < 0)
       tst.l  fib_EntryType(a3)
       bmi    TypeFile
;**  We found a directory .. we got work.
;**           {
;**                oldLock = CurrentDir(newLock);
       move.l newLock(a4),d1
       jsr    _LVOCurrentDir(a6)
       move.l d0,oldLock(a4)
;**                Level += 1;
       addq   #1,Level(a5)
;**                GetDir(fibb->fib_FileName);
       lea    fib_FileName(a3),a0
       bsr    GetToWork
       move.l fibb(a4),a3       ; file info block address
       move.l d0,fib_Date(a3)
       move.l d1,fib_Date+4(a3)
       move.l d2,fib_Date+8(a3)
;**            Level -= 1;
       subq   #1,Level(a5)
;**                newLock = CurrentDir(oldLock);
       move.l oldLock(a4),d1
       jsr    _LVOCurrentDir(a6)
       move.l d0,newLock(a4)
;**         This is where we build the packet.  Ouch.
; sendpkt(a3=struct MsgPort *pid,a2=LONG args)
        move.l  DosPkt(a5),a0
        lea     $30(a0),a0         ;BSTR site
        lea     fib_FileName(a3),a1  ;name
        moveq   #0,d0
NmLp    move.b  0(a1,d0.w),1(a0,d0.w)
        beq.s   NmEnd
        addq.w  #1,d0
        cmp.w   #108,d0
        bne.s   NmLp
NmEnd   move.b  d0,(a0)    ;len
        move.l  a0,d7
        lsr.l   #2,d7      ;BSTR address
; message.mn_Node.ln_Name = &(dosPacket);
	MOVE.L	DosPkt(A5),A0
	MOVE.L	message(A5),A1
	MOVE.L	A0,10(A1)
; dosPacket.dp_Link = &(message);
	MOVE.L	A1,0(A0)
; dosPacket.dp_Port = replyport;
	MOVE.L	DataBlk(A5),$18(A1)
; dosPacket.dp_Type = action;
	MOVE.L	#34,$1C(A1)
; dosPacket.dp_Arg1 = 0;
	LEA	$28(A1),A0    ;arg1
; arg1=NULL	MOVE.L	#0,0(A0)
; dosPacket.dp_Arg2 = parentlock;
       move.l newLock(a4),4(a0)   ; lock
; dosPacket.dp_Arg3 = BSTR(filename);
       move.l d7,8(A0)     ; BSTR
; dosPacket.dp_Arg4 = &datestamp;
       lea    fib_Date(a3),a1
       move.l a1,12(A0)    ; Ptr to datestamp
; PutMsg(pid,message);
       move.l DevProc(A5),A0
	MOVE.L	message(A5),A1
	MOVE.L	4,A6
	JSR	_LVOPutMsg(A6)
; WaitPort(replyport); GetMsg(replyport);
	MOVE.L	DataBlk(A5),A0
	JSR	_LVOWaitPort(A6)
	MOVE.L	DataBlk(A5),A0
	JSR	_LVOGetMsg(A6)
; res1 = dosPacket.dp_Res1;
       moveq   #1,d1
       lea     Nope(a5),a1
       move.l  message(A5),A0
       move.l  $20(A0),D0
; $FFFFF is success
       beq.s  NGood
       lea    Yup(a5),a1
NGood  move.b d1,(a1)
       move.b d1,Mebbe(a5)
;**                }  /* dir */
TypeFile:
; if FileName <> #?.info
       lea    fib_FileName(a3),a0
TryChx move.b (a0)+,d0
       bne.s  TryChx
       lea    -6(a0),a0
       lea    InfoLine(pc),a1
InfLp  cmp.b  (a0)+,(a1)+
       beq.s  InfLp
       tst.b  -1(a0)
       beq.s  Rejoin2        
;**                {
       move.l fib_Date(a3),d0
       move.l fib_Date+4(a3),d1
       move.l fib_Date+8(a3),d2
       cmp.l  Days(a4),d0
       bne.s  ckDate
       cmp.l  Minutes(a4),d1
       bne.s  ckDate
       cmp.l  Ticks(a4),d2
ckDate bcs.s  Rejoin2
       move.l d0,Days(a4)
       move.l d1,Minutes(a4)
       move.l d2,Ticks(a4)
;**                }  /* file */
Rejoin2:
       tst.b  Abort(a5)
       bne.s  DropLock
       moveq  #0,d0
       move.l #$1000,d1
       move.l $4,a6
       jsr    _LVOSetSignal(a6)
       move.l dosBase(a5),a6    ; restore Dos Library
       and.l  #$1000,d0
       beq.s  NotCtrlC
       move.b #1,Abort(a5)
NotCtrlC:   tst.b Abort(a5)
       beq   DirLoop
; print Ctrl-C signal       
       move.l OutHandle(a5),d1
       lea    CtrlCMsg(pc),a1
       move.l a1,d2
       moveq  #CtrlCLen,d3
       jsr    _LVOWrite(A6)
;**        } /* primary dir not file */
;**       }   /* Examine OK */
;**      UnLock(newLock);
DropLock    move.l dosBase(a5),a6    ; set Dos Library
       move.l newLock(a4),d1    ; take off the lock
       jsr    _LVOUnLock(a6)
;**      }      /* Lock OK */
;**    FreeMem(fibb,INFOSIZE);
DropMem:    move.l $4,a6             ; set Exec library
       move.l fibb(a4),a1       ; memory block address
       move.l #INFOSIZE,d0      ; size of block
       jsr    _LVOFreeMem(a6)   ; release this memory
       move.l dosBase(a5),a6    ; set Dos Library
;**    }        /* Alloc OK */
       move.l Days(a4),d0
       move.l Minutes(a4),d1
       move.l Ticks(a4),d2
GDExit:     unlk   A4
       rts
;**  }

NotDirMsg   dc.b   'Not a directory!',$a
NotDirLen   equ    *-NotDirMsg
PromptMsg   dc.b   'ReDate (by Jim Butterfield) V1.0',$0a
            dc.b   'FORMAT:  ReDate <directory>',$0a
PromptLen   equ    *-PromptMsg
SDupMsg     dc.b   'Subdirectories updated.',$a
SDupLen     equ    *-SDupMsg
SDnupMsg    dc.b   'Subdirectories not updated.',$a
SDnupLen    equ    *-SDnupMsg
SDnfMsg     dc.b   'No subdirectories seen.',$a
SDnfLen     equ    *-SDnfMsg
NoMemMsg    dc.b   'Out of Memory',$0a
NoMemLen    equ    *-NoMemMsg
NoFileMsg   dc.b   'Can t find file.',$0a
NoFileLen   equ    *-NoFileMsg
CtrlCMsg    dc.b   '^C',$0a
CtrlCLen    equ    *-CtrlCMsg
InfoLine    dc.b   '.info'
dosname     dc.b   'dos.library',0
            end

