summaryrefslogtreecommitdiff
path: root/v2.0/source/COPYPROC.ASM
blob: f6e3bb1b0d7f9d032f2cf3dcc8fa7052330256e5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
TITLE   COPYRPOC             ;Procedures called by COPY

        INCLUDE COMSW.ASM

.xlist
.xcref
        INCLUDE DOSSYM.ASM
        INCLUDE DEVSYM.ASM
        INCLUDE COMSEG.ASM
.list
.cref

        INCLUDE COMEQU.ASM

DATARES SEGMENT PUBLIC
DATARES ENDS

TRANDATA        SEGMENT PUBLIC

        EXTRN   OVERWR:BYTE,FULDIR:BYTE,LOSTERR:BYTE
        EXTRN   DEVWMES:BYTE,INBDEV:BYTE,NOSPACE:BYTE

TRANDATA        ENDS

TRANSPACE       SEGMENT PUBLIC

        EXTRN   CFLAG:BYTE,NXTADD:WORD,DESTCLOSED:BYTE
        EXTRN   PLUS:BYTE,BINARY:BYTE,ASCII:BYTE,FILECNT:WORD
        EXTRN   WRITTEN:BYTE,CONCAT:BYTE,DESTBUF:BYTE,SRCBUF:BYTE
        EXTRN   SDIRBUF:BYTE,DIRBUF:BYTE,DESTFCB:BYTE,MELCOPY:BYTE
        EXTRN   FIRSTDEST:BYTE,DESTISDIR:BYTE,DESTSWITCH:WORD
        EXTRN   DESTTAIL:WORD,DESTINFO:BYTE,INEXACT:BYTE
        EXTRN   DESTVARS:BYTE,SRCINFO:BYTE,RDEOF:BYTE
        EXTRN   USERDIR1:BYTE,NOWRITE:BYTE
        EXTRN   SRCHAND:WORD,CPDATE:WORD,CPTIME:WORD
        EXTRN   SRCISDEV:BYTE,BYTCNT:WORD,TPA:WORD,TERMREAD:BYTE
        EXTRN   DESTHAND:WORD,DESTISDEV:BYTE,DIRCHAR:BYTE

TRANSPACE       ENDS

TRANCODE        SEGMENT PUBLIC BYTE

        PUBLIC  SEARCH,SEARCHNEXT,DOCOPY,CLOSEDEST,FLSHFIL,SETASC
        PUBLIC  BUILDNAME,COPERR

        EXTRN   PRINT:NEAR,BUILDPATH:NEAR,RESTUDIR1:NEAR
        EXTRN   COMPNAME:NEAR,ENDCOPY:NEAR

ASSUME  CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING


SEARCHNEXT:
        MOV     AH,DIR_SEARCH_NEXT
        TEST    [SRCINFO],2
        JNZ     SEARCH                  ; Do serach-next if ambig
        OR      AH,AH                   ; Reset zero flag
        return
SEARCH:
        PUSH    AX
        MOV     AH,SET_DMA
        MOV     DX,OFFSET TRANGROUP:DIRBUF
        INT     int_command             ; Put result of search in DIRBUF
        POP     AX                      ; Restore search first/next command
        MOV     DX,FCB
        INT     int_command             ; Do the search
        OR      AL,AL
        return

DOCOPY:
        mov     [RDEOF],0               ; No EOF yet
        mov     dx,offset trangroup:SRCBUF
        mov     ax,OPEN SHL 8
        INT     int_command
        retc                            ; If open fails, ignore
        mov     bx,ax                   ; Save handle
        mov     [SRCHAND],bx            ; Save handle
        mov     ax,(FILE_TIMES SHL 8)
        INT     int_command
        mov     [CPDATE],dx             ; Save DATE
        mov     [CPTIME],cx             ; Save TIME
        mov     ax,(IOCTL SHL 8)
        INT     int_command             ; Get device stuff
        and     dl,devid_ISDEV
        mov     [SRCISDEV],dl           ; Set source info
        jz      COPYLP                  ; Source not a device
        cmp     [BINARY],0
        jz      COPYLP                  ; ASCII device OK
        mov     dx,offset trangroup:INBDEV  ; Cannot do binary input
        jmp     COPERR

COPYLP:
        mov     bx,[SRCHAND]
        mov     cx,[BYTCNT]
        mov     dx,[NXTADD]
        sub     cx,dx                   ; Compute available space
        jnz     GOTROOM
        call    FLSHFIL
        CMP     [TERMREAD],0
        JNZ     CLOSESRC                ; Give up
        mov     cx,[BYTCNT]
GOTROOM:
        push    ds
        mov     ds,[TPA]
ASSUME  DS:NOTHING
        mov     ah,READ
        INT     int_command
        pop     ds
ASSUME  DS:TRANGROUP
        jc      CLOSESRC                ; Give up if error
        mov     cx,ax                   ; Get count
        jcxz    CLOSESRC                ; No more to read
        cmp     [SRCISDEV],0
        jnz     NOTESTA                 ; Is a device, ASCII mode
        cmp     [ASCII],0
        jz      BINREAD
NOTESTA:
        MOV     DX,CX
        MOV     DI,[NXTADD]
        MOV     AL,1AH
        PUSH    ES
        MOV     ES,[TPA]
        REPNE   SCASB                   ; Scan for EOF
        POP     ES
        JNZ     USEALL
        INC     [RDEOF]
        INC     CX
USEALL:
        SUB     DX,CX
        MOV     CX,DX
BINREAD:
        ADD     CX,[NXTADD]
        MOV     [NXTADD],CX
        CMP     CX,[BYTCNT]             ; Is buffer full?
        JB      TESTDEV                 ; If not, we may have found EOF
        CALL    FLSHFIL
        CMP     [TERMREAD],0
        JNZ     CLOSESRC                ; Give up
        JMP     SHORT COPYLP

TESTDEV:
        cmp     [SRCISDEV],0
        JZ      CLOSESRC                ; If file then EOF
        CMP     [RDEOF],0
        JZ      COPYLP                  ; On device, go till ^Z
CLOSESRC:
        mov     bx,[SRCHAND]
        mov     ah,CLOSE
        INT     int_command
        return

CLOSEDEST:
        cmp     [DESTCLOSED],0
        retnz                           ; Don't double close
        MOV     AL,BYTE PTR [DESTSWITCH]
        CALL    SETASC                  ; Check for B or A switch on destination
        JZ      BINCLOS
        MOV     BX,[NXTADD]
        CMP     BX,[BYTCNT]             ; Is memory full?
        JNZ     PUTZ
        call    TRYFLUSH                ; Make room for one lousy byte
        jz      NOCONC
CONCHNG:                                ; Concat flag changed on us
        stc
        return
NOCONC:
        XOR     BX,BX
PUTZ:
        PUSH    DS
        MOV     DS,[TPA]
        MOV     WORD PTR [BX],1AH       ; Add End-of-file mark (Ctrl-Z)
        POP     DS
        INC     [NXTADD]
        MOV     [NOWRITE],0             ; Make sure our ^Z gets written
        MOV     AL,[WRITTEN]
        XOR     AH,AH
        ADD     AX,[NXTADD]
        JC      BINCLOS                 ; > 1
        CMP     AX,1
        JZ      FORGETIT                ; WRITTEN = 0 NXTADD = 1 (the ^Z)
BINCLOS:
        call    TRYFLUSH
        jnz     CONCHNG
        cmp     [WRITTEN],0
        jz      FORGETIT                ; Never wrote nothin
        MOV     BX,[DESTHAND]
        MOV     CX,[CPTIME]
        MOV     DX,[CPDATE]
        CMP     [INEXACT],0             ; Copy not exact?
        JZ      DODCLOSE                ; If no, copy date & time
        MOV     AH,GET_TIME
        INT     int_command
        SHL     CL,1
        SHL     CL,1                    ; Left justify min in CL
        SHL     CX,1
        SHL     CX,1
        SHL     CX,1                    ; hours to high 5 bits, min to 5-10
        SHR     DH,1                    ; Divide seconds by 2 (now 5 bits)
        OR      CL,DH                   ; And stick into low 5 bits of CX
        PUSH    CX                      ; Save packed time
        MOV     AH,GET_DATE
        INT     int_command
        SUB     CX,1980
        XCHG    CH,CL
        SHL     CX,1                    ; Year to high 7 bits
        SHL     DH,1                    ; Month to high 3 bits
        SHL     DH,1
        SHL     DH,1
        SHL     DH,1
        SHL     DH,1                    ; Most sig bit of month in carry
        ADC     CH,0                    ; Put that bit next to year
        OR      DL,DH                   ; Or low three of month into day
        MOV     DH,CH                   ; Get year and high bit of month
        POP     CX                      ; Get time back
DODCLOSE:
        MOV     AX,(FILE_TIMES SHL 8) OR 1
        INT     int_command             ; Set date and time
        MOV     AH,CLOSE
        INT     int_command
        INC     [FILECNT]
        INC     [DESTCLOSED]
RET50:
        CLC
        return

FORGETIT:
        MOV     BX,[DESTHAND]
        CALL    DODCLOSE                ; Close the dest
        MOV     DX,OFFSET TRANGROUP:DESTBUF
        MOV     AH,UNLINK
        INT     int_command             ; And delete it
        MOV     [FILECNT],0             ; No files transferred
        JMP     RET50

TRYFLUSH:
        mov     al,[CONCAT]
        push    ax
        call    FLSHFIL
        pop     ax
        cmp     al,[CONCAT]
        return

FLSHFIL:
; Write out any data remaining in memory.
; Inputs:
;       [NXTADD] = No. of bytes to write
;       [CFLAG] <>0 if file has been created
; Outputs:
;       [NXTADD] = 0

        MOV     [TERMREAD],0
        cmp     [CFLAG],0
        JZ      NOTEXISTS
        JMP     EXISTS
NOTEXISTS:
        call    BUILDDEST               ; Find out all about the destination
        CALL    COMPNAME                ; Source and dest. the same?
        JNZ     PROCDEST                ; If not, go ahead
        CMP     [SRCISDEV],0
        JNZ     PROCDEST                ; Same name on device OK
        CMP     [CONCAT],0              ; Concatenation?
        MOV     DX,OFFSET TRANGROUP:OVERWR
        JZ      COPERRJ                 ; If not, overwrite error
        MOV     [NOWRITE],1             ; Flag not writting (just seeking)
PROCDEST:
        mov     ax,(OPEN SHL 8) OR 1
        CMP     [NOWRITE],0
        JNZ     DODESTOPEN              ; Don't actually create if NOWRITE set
        mov     ah,CREAT
        xor     cx,cx
DODESTOPEN:
        mov     dx,offset trangroup:DESTBUF
        INT     int_command
        MOV     DX,OFFSET TRANGROUP:FULDIR
        JC      COPERRJ
        mov     [DESTHAND],ax           ; Save handle
        mov     [CFLAG],1               ; Destination now exists
        mov     bx,ax
        mov     ax,(IOCTL SHL 8)
        INT     int_command             ; Get device stuff
        mov     [DESTISDEV],dl          ; Set dest info
        test    dl,devid_ISDEV
        jz      EXISTS                  ; Dest not a device
        mov     al,BYTE PTR [DESTSWITCH]
        AND     AL,ASWITCH+BSWITCH
        JNZ     TESTBOTH
        MOV     AL,[ASCII]              ; Neither set, use current setting
        OR      AL,[BINARY]
        JZ      EXSETA                  ; Neither set, default to ASCII
TESTBOTH:
        JPE     EXISTS                  ; Both are set, ignore
        test    AL,BSWITCH
        jz      EXISTS                  ; Leave in cooked mode
        mov     ax,(IOCTL SHL 8) OR 1
        xor     dh,dh
        or      dl,devid_RAW
        mov     [DESTISDEV],dl          ; New value
        INT     int_command             ; Set device to RAW mode
        jmp     short EXISTS

COPERRJ:
        jmp     SHORT COPERR

EXSETA:
; What we read in may have been in binary mode, flag zapped write OK
        mov     [ASCII],ASWITCH         ; Set ASCII mode
        or      [INEXACT],ASWITCH       ; ASCII -> INEXACT
EXISTS:
        cmp     [NOWRITE],0
        jnz     NOCHECKING              ; If nowrite don't bother with name check
        CALL    COMPNAME                ; Source and dest. the same?
        JNZ     NOCHECKING              ; If not, go ahead
        CMP     [SRCISDEV],0
        JNZ     NOCHECKING              ; Same name on device OK
; At this point we know in append (would have gotten overwrite error on first
; destination create otherwise), and user trying to specify destination which
; has been scribbled already (if dest had been named first, NOWRITE would
; be set).
        MOV     DX,OFFSET TRANGROUP:LOSTERR ; Tell him he's not going to get it
        CALL    PRINT
        MOV     [NXTADD],0              ; Set return
        INC     [TERMREAD]              ; Tell Read to give up
RET60:
        return

NOCHECKING:
        mov     bx,[DESTHAND]           ; Get handle
        XOR     CX,CX
        XCHG    CX,[NXTADD]
        JCXZ    RET60                   ; If Nothing to write, forget it
        INC     [WRITTEN]               ; Flag that we wrote something
        CMP     [NOWRITE],0             ; If NOWRITE set, just seek CX bytes
        JNZ     SEEKEND
        XOR     DX,DX
        PUSH    DS
        MOV     DS,[TPA]
ASSUME  DS:NOTHING
        MOV     AH,WRITE
        INT     int_command
        POP     DS
ASSUME  DS:TRANGROUP
        MOV     DX,OFFSET TRANGROUP:NOSPACE
        JC      COPERR                  ; Failure
        sub     cx,ax
        retz                            ; Wrote all supposed to
        test    [DESTISDEV],devid_ISDEV
        jz      COPERR                  ; Is a file, error
        test    [DESTISDEV],devid_RAW
        jnz     DEVWRTERR               ; Is a raw device, error
        cmp     [INEXACT],0
        retnz                           ; INEXACT so OK
        dec     cx
        retz                            ; Wrote one byte less (the ^Z)
DEVWRTERR:
        MOV     DX,OFFSET TRANGROUP:DEVWMES
COPERR:
        CALL    PRINT
        inc     [DESTCLOSED]
        cmp     [CFLAG],0
        jz      ENDCOPYJ                ; Never actually got it open
        MOV     bx,[DESTHAND]
        MOV     AH,CLOSE                ; Close the file
        INT     int_command
        MOV     DX,OFFSET TRANGROUP:DESTBUF
        MOV     AH,UNLINK
        INT     int_command             ; And delete it
        MOV     [CFLAG],0
ENDCOPYJ:
        JMP   ENDCOPY


SEEKEND:
        xor     dx,dx                   ; Zero high half of offset
        xchg    dx,cx                   ; cx:dx is seek location
        mov     ax,(LSEEK SHL 8) OR 1
        INT     int_command             ; Seek ahead in the file
        cmp     [RDEOF],0
        retz
; If a ^Z has been read we must set the file size to the current
; file pointer location
        MOV     AH,WRITE
        INT     int_command             ; CX is zero, truncates file
        return

SETASC:
; Given switch vector in AX,
;       Set ASCII switch if A is set
;       Clear ASCII switch if B is set
;       BINARY set if B specified
;       Leave ASCII unchanged if neither or both are set
; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set
        AND     AL,ASWITCH+BSWITCH
        JPE     LOADSW                  ; PE means both or neither are set
        PUSH    AX
        AND     AL,BSWITCH
        MOV     [BINARY],AL
        POP     AX
        AND     AL,ASWITCH
        MOV     [ASCII],AL
        OR      [INEXACT],AL
LOADSW:
        MOV     AL,[ASCII]
        OR      AL,AL
        return

BUILDDEST:
        cmp     [DESTISDIR],-1
        jnz     KNOWABOUTDEST           ; Already done the figuring
        MOV     DI,OFFSET TRANGROUP:USERDIR1
        mov     bp,offset trangroup:DESTVARS
        call    BUILDPATH
        call    RESTUDIR1

; Now know all about the destination

KNOWABOUTDEST:
        xor     al,al
        xchg    al,[FIRSTDEST]
        or      al,al
        jnz     FIRSTDST
        jmp     NOTFIRSTDEST
FIRSTDST:
        mov     si,[DESTTAIL]           ; Create an FCB of the original DEST
        mov     di,offset trangroup:DESTFCB
        mov     ax,PARSE_FILE_DESCRIPTOR SHL 8
        INT     int_command
        mov     ax,word ptr [DESTBUF]   ; Get drive
        cmp     ah,':'
        jz      DRVSPEC4
        mov     al,'@'
DRVSPEC4:
        MOV     CL,[ASCII]              ; Save current ASCII setting
        sub     al,'@'
        mov     [DESTFCB],al
        mov     al,[DESTINFO]
        mov     ah,[SRCINFO]
        and     ax,0202H
        or      al,al
        jz      NOTMELCOPY
        cmp     al,ah
        jnz     NOTMELCOPY
        cmp     [PLUS],0
        jz      NOTMELCOPY
        inc     [MELCOPY]               ; ambig source, ambig dest, and pluses
        xor     al,al
        jmp     short SETCONC

NOTMELCOPY:
        xor     al,2                    ; al=2 if unambig dest, =0 if ambig dest
        and     al,ah
        shr     al,1                    ; al=1 if unambig dest AND ambig sorce
                                        ;   Implies concatination
SETCONC:
        or      al,[PLUS]               ; al=1 if concat
        mov     [CONCAT],al
        shl     al,1
        shl     al,1
        mov     [INEXACT],al            ; Concat -> inexact copy
        cmp     [BINARY],0
        jnz     NOTFIRSTDEST            ; Binary explicitly given, all OK
        mov     [ASCII],al              ; Concat -> ASCII
        or      cl,cl
        jnz     NOTFIRSTDEST            ; ASCII flag set before, DATA read correctly
        or      al,al
        JZ      NOTFIRSTDEST            ; ASCII flag did not change states
; At this point there may already be binary read data in the read buffer.
; We need to find the first ^Z (if there is one) and trim the amount
; of data in the buffer correctly.
        MOV     CX,[NXTADD]
        JCXZ    NOTFIRSTDEST            ; No data, everything OK
        MOV     AL,1AH
        PUSH    ES
        XOR     DI,DI
        MOV     ES,[TPA]
        REPNE   SCASB                   ; Scan for EOF
        POP     ES
        JNZ     NOTFIRSTDEST            ; No ^Z in buffer, everything OK
        DEC     DI                      ; Point at ^Z
        MOV     [NXTADD],DI             ; New buffer
NOTFIRSTDEST:
        mov     bx,offset trangroup:DIRBUF+1    ; Source of replacement chars
        cmp     [CONCAT],0
        jz      GOTCHRSRC               ; Not a concat
        mov     bx,offset trangroup:SDIRBUF+1   ; Source of replacement chars
GOTCHRSRC:
        mov     si,offset trangroup:DESTFCB+1   ; Original dest name
        mov     di,[DESTTAIL]           ; Where to put result

BUILDNAME:
        mov     cx,8
BUILDMAIN:
        lodsb
        cmp     al,"?"
        jnz     NOTAMBIG
        mov     al,byte ptr [BX]
NOTAMBIG:
        cmp     al,' '
        jz      NOSTORE
        stosb
NOSTORE:
        inc     bx
        loop    BUILDMAIN
        mov     cl,3
        cmp     byte ptr [SI],' '
        jz      ENDDEST                 ; No extension
        mov     al,'.'
        stosb
BUILDEXT:
        lodsb
        cmp     al,"?"
        jnz     NOTAMBIGE
        mov     al,byte ptr [BX]
NOTAMBIGE:
        cmp     al,' '
        jz      NOSTOREE
        stosb
NOSTOREE:
        inc     bx
        loop    BUILDEXT
ENDDEST:
        xor     al,al
        stosb                           ; NUL terminate
        return

TRANCODE    ENDS
            END