Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1092 lines
28 KiB

  1. page ,132
  2. title COMMAND COPY routines.
  3. ;/*
  4. ; * Microsoft Confidential
  5. ; * Copyright (C) Microsoft Corporation 1991
  6. ; * All Rights Reserved.
  7. ; */
  8. comment % -----------------------------------------------------------------
  9. ;*** COPY.ASM
  10. Source files: copy.asm, copypr1.asm, copypr2.asm
  11. ;*** MODIFICATION HISTORY
  12. 11/01/83 EE Added a few lines at the end of SCANSRC2 to get multiple
  13. file concatenations (eg copy a.*+b.*+c.*) to work properly.
  14. 11/02/83 EE Commented out the code in CPARSE which added drive designators
  15. to tokens which begin with path characters so that PARSELINE
  16. will work correctly.
  17. 11/04/83 EE Commented out the code in CPARSE that considered paren's to be
  18. individual tokens. That distinction is no longer needed for
  19. FOR loop processing.
  20. 11/17/83 EE CPARSE upper case conversion is now flag dependent. Flag is
  21. 1 when Cparse is called from COPY.
  22. 11/17/83 EE Took out the comment chars around code described in 11/04/83
  23. mod. It now is conditional on flag like previous mod.
  24. 11/21/83 NP Added printf
  25. 12/09/83 EE CPARSE changed to use CPYFLAG to determine when a colon should
  26. be added to a token.
  27. 05/30/84 MZ Initialize all copy variables. Fix confusion with destclosed
  28. NOTE: DestHand is the destination handle. There are two
  29. special values: -1 meaning destination was never opened and
  30. 0 which means that the destination has been openned and
  31. closed.
  32. 06/01/84 MZ Above reasoning totally specious. Returned things to normal
  33. 06/06/86 EG Change to fix problem of source switches /a and /b getting
  34. lost on large and multiple file (wildcard) copies.
  35. 06/09/86 EG Change to use xnametrans call to verify that source and
  36. destination are not equal.
  37. 06/24/90 DO If the destination of a file concatenation is the same as
  38. first source file AND we run out of disk space before
  39. completing the concatenation, restore the first source
  40. file as best we can. See SeekEnd and CopErr. Bug #859.
  41. M031 SR 10/11/90 Bug #3069. Use deny write sharing mode to open files
  42. instead of compatibility mode. This gives lesser sharing
  43. violations when files are opened for read on a copy.
  44. % -------------------------------------------------------------------------
  45. .xlist
  46. .xcref
  47. include comsw.asm
  48. include dossym.inc
  49. include syscall.inc
  50. include sf.inc
  51. include comseg.asm
  52. include comequ.asm
  53. .list
  54. .cref
  55. DATARES segment public byte
  56. extrn VerVal:word
  57. DATARES ends
  58. TRANDATA segment public byte
  59. extrn BadCd_Ptr:word
  60. extrn Copied_Ptr:word
  61. extrn Extend_Buf_Ptr:word
  62. extrn Extend_Buf_Sub:byte
  63. extrn File_Name_Ptr:word
  64. extrn InBDev_Ptr:word
  65. extrn Msg_Disp_Class:byte
  66. extrn Overwr_Ptr:word
  67. TRANDATA ends
  68. TRANSPACE segment public byte
  69. extrn AllSwitch:word
  70. extrn ArgC:byte
  71. extrn Ascii:byte
  72. extrn Binary:byte
  73. extrn BytCnt:word
  74. extrn CFlag:byte
  75. extrn Comma:byte
  76. extrn Concat:byte
  77. extrn Copy_Num:word
  78. extrn CpDate:word
  79. extrn CpTime:word
  80. extrn CpyFlag:byte
  81. extrn CurDrv:byte
  82. extrn DestBuf:byte
  83. extrn DestClosed:byte
  84. extrn DestFcb:byte
  85. extrn DestFcb2:byte
  86. extrn DestHand:word
  87. extrn DestInfo:byte
  88. extrn DestIsDir:byte
  89. extrn DestSiz:byte
  90. extrn DestSwitch:word
  91. extrn DestTail:word
  92. extrn DestVars:byte
  93. extrn DirBuf:byte
  94. extrn Expand_Star:byte
  95. extrn FileCnt:word
  96. extrn FirstDest:byte
  97. extrn FrstSrch:byte
  98. extrn Inexact:byte
  99. extrn MelCopy:byte
  100. extrn MelStart:word
  101. extrn Msg_Flag:byte
  102. extrn NoWrite:byte
  103. extrn NxtAdd:word
  104. extrn ObjCnt:byte
  105. extrn OCtrlZ:byte
  106. extrn OFilePtr_Hi:word
  107. extrn OFilePtr_Lo:word
  108. extrn One_Char_Val:byte
  109. extrn Parse_Last:word
  110. extrn Plus:byte
  111. extrn Plus_Comma:byte
  112. extrn RdEof:byte
  113. extrn ResSeg:word
  114. extrn ScanBuf:byte
  115. extrn SDirBuf:byte
  116. extrn SrcBuf:byte
  117. extrn SrcHand:word
  118. extrn SrcInfo:byte
  119. extrn SrcIsDev:byte
  120. extrn SrcPt:word
  121. extrn SrcSiz:byte
  122. extrn SrcTail:word
  123. extrn SrcVars:byte
  124. extrn SrcXName:byte
  125. extrn StartEl:word
  126. extrn String_Ptr_2:word
  127. extrn TermRead:byte
  128. extrn Tpa:word
  129. extrn UserDir1:byte
  130. extrn Written:word
  131. TRANSPACE ends
  132. ;*** COPY CODE
  133. TRANCODE segment public byte
  134. extrn CError:near
  135. extrn CopErr:near
  136. extrn TCommand:near
  137. public Copy
  138. assume cs:TRANGROUP,ds:TRANGROUP,es:TRANGROUP,ss:NOTHING
  139. break Copy
  140. Copy:
  141. assume ds:TRANGROUP,es:TRANGROUP
  142. ; Initialize internal variables.
  143. xor ax,ax ; AX = 0
  144. mov Copy_Num,ax ; # files copied (destinations) = 0
  145. mov SrcPt,ax ; cmd line ptr for source scan = 0
  146. mov SrcTail,ax ; ptr to last element of source pathname = 0
  147. mov CFlag,al ; 'destination file created' = false
  148. mov NxtAdd,ax ; ptr into TPA buffer = 0
  149. mov DestSwitch,ax ; destination switches = none
  150. mov StartEl,ax ; CParse ptr to last pathname element = 0
  151. mov DestTail,ax ; ptr to last element of dest pathname = 0
  152. mov DestClosed,al ; 'destination file closed' = false
  153. mov DestSiz,al ; length of destination pathname = 0
  154. mov SrcSiz,al ; length of source pathname = 0
  155. mov DestInfo,al ; destination pathname flags = none
  156. mov SrcInfo,al ; source pathname flags = none
  157. mov Inexact,al ; 'inexact copy' = false
  158. mov DestVars,al ; 'dest pathname is directory' = false
  159. mov SrcVars,al ; 'source pathname is directory' = false
  160. mov UserDir1,al ; saved working directory = null
  161. mov NoWrite,al ; 'no write' (source = dest) = false
  162. mov RdEof,al ; 'read end of file' = false
  163. mov SrcHand,ax ; source handle = 0
  164. mov CpDate,ax ; copy date = 0
  165. mov CpTime,ax ; copy time = 0
  166. mov SrcIsDev,al ; 'source is device' = false
  167. mov OCtrlZ,al ; 'Ctrl+Z removed from original' = false
  168. mov OFilePtr_Lo,ax
  169. mov OFilePtr_Hi,ax ; original destination file ptr = null
  170. mov TermRead,al ; 'terminate read' = false
  171. mov Comma,al ; '"+,," found' = false
  172. mov Plus_Comma,al ; '"+,," found last time' = false (?)
  173. mov Msg_Flag,al ;AN022; 'non-utility msg issued' = false
  174. mov AllSwitch,ax ; all switches = none
  175. mov ArgC,al ; source/dest argument count = 0
  176. mov Plus,al ; '"+" in command line' = false
  177. mov Binary,al ; 'binary copy' = false
  178. mov Ascii,al ; 'ascii copy' = false
  179. mov FileCnt,ax ; # files copied (destinations) = 0
  180. mov Written,ax ; 'destination written to' = false
  181. mov Concat,al ; 'concatenating' = false
  182. mov MelCopy,al ; 'Mel Hallerman copy' = false
  183. mov MelStart,ax ; Mel Hallerman cmd line ptr = 0
  184. ; Initialize buffers with double-nulls.
  185. mov word ptr ScanBuf,ax
  186. mov word ptr DestBuf,ax
  187. mov word ptr SrcBuf,ax
  188. mov word ptr SDirBuf,ax
  189. mov word ptr DirBuf,ax
  190. mov word ptr DestFcb,ax
  191. mov ObjCnt,al ; # CParse cmd-line objects found = 0
  192. dec ax ; AX = 0FFFFh
  193. mov DestHand,ax ; destination handle = 'never opened'
  194. mov FrstSrch,al ; 'first search for source' = true
  195. mov FirstDest,al ; 'first time for dest' = true
  196. mov DestIsDir,al ; 'haven't analyzed destination'
  197. mov si,81h ; SI = ptr to command line
  198. mov bl,PLUS_CHR ; BL = special delimiter = "+"
  199. inc Expand_Star ; CParse 'expand * to ?s' = true
  200. mov CpyFlag,1 ; CParse 'called from COPY' = true
  201. ;* Scan the command line for destination information.
  202. DestScan:
  203. xor bp,bp ; BP = switch flag accumulator
  204. mov di,offset TRANGROUP:ScanBuf ; ES:DI = ptr to pathname buf
  205. mov Parse_Last,si ;AN018; save cmd line ptr
  206. invoke CParse ; parse next object
  207. pushf ; save CParse flags
  208. inc ObjCnt ; count object
  209. test bh,80h
  210. jz @f ; no "+" delimiter
  211. mov Plus,1 ; "+" delimiter occurred
  212. @@:
  213. test bh,1
  214. jz TestP2 ; not a switch
  215. ; Found a switch.
  216. test bp,SwitchV ;AN038; Verify requested?
  217. jz Not_SlashV ;AN038; No - set the switch
  218. test AllSwitch,SwitchV ;AN038; Verify already entered?
  219. jz Not_SlashV ;AN038; No - set the switch
  220. ;AD018; or AllSwitch,FBadSwitch ;AN038; Set up bad switch
  221. or bp,FBadSwitch ;AN018; Set up bad switch
  222. Not_SlashV: ;AN038;
  223. or DestSwitch,bp ; assume destination
  224. or AllSwitch,bp ; keep tabs on all switches
  225. test bp,not SwitchCopy ;AN018; Bad switch?
  226. jz Not_Bad_Switch ;AN018; Switches are okay
  227. popf ;AN018; fix up stack
  228. mov ax,BadSwt_ptr ;AN018; get "Invalid switch" message number
  229. invoke Setup_Parse_Error_Msg ;AN018; setup to print the message
  230. jmp CError ;AC018; exit
  231. Not_Bad_Switch: ;AN018; switch okay
  232. popf ; restore CParse flags
  233. jc CheckDone ; found CR
  234. jmp short DestScan ; continue scanning for destination
  235. TestP2:
  236. popf ; restore CParse flags
  237. jc CheckDone ; found CR
  238. test bh,80h
  239. jnz @f ; found a "+pathname" argument
  240. inc ArgC ; count independent pathname args
  241. @@:
  242. push si ; save cmd line ptr
  243. mov ax,StartEl ; AX = ptr to last path element
  244. mov si,offset TRANGROUP:ScanBuf ; SI = ptr to path string
  245. sub ax,si ; AX = offset of last element
  246. mov di,offset TRANGROUP:DestBuf ; DI = ptr to destination buf
  247. add ax,di ; AX = ptr to last element in
  248. ; destination path buffer
  249. mov DestTail,ax ; save ptr to last element
  250. mov DestSiz,cl ; save path string length
  251. inc cx ; CX = mov length (incl null)
  252. rep movsb ; DestBuf = possible destination path
  253. mov DestInfo,bh ; save CParse info flags
  254. mov DestSwitch,0 ; clear destination switches
  255. pop si ; SI = ptr into cmd line again
  256. jmp DestScan ;AC018; continue scanning for dest
  257. CheckDone:
  258. ; We reached the CR. The destination scan is finished.
  259. ; Disallow "copy file1+" as file overwriting itself.
  260. ;
  261. ; (Note that "copy file1+file2+" will be accepted, and
  262. ; equivalent to "copy file1+file2".)
  263. ; Bugbug: it looks like "copy /x file1+" would slip
  264. ; through this check, since the switch would count
  265. ; as another object in ObjCnt.
  266. cmp Plus,1 ; "+" with
  267. jne cdCont
  268. cmp ArgC,1 ; one arg,
  269. jne cdCont
  270. cmp ObjCnt,2 ; two objects..
  271. jne cdCont
  272. mov dx,offset TRANGROUP:OverWr_ptr
  273. jmp CopErr ; is file overwrite.
  274. cdCont: mov al,Plus ; AL = '"+" occurred'
  275. mov Concat,al ; if "+" occurred, we're concatenating
  276. shl al,1
  277. shl al,1
  278. mov Inexact,al ; therefore making an inexact copy
  279. mov al,ArgC ; AL = # independent arguments
  280. or al,al
  281. jnz Try_Too_Many ; more than 0 args; check if too many
  282. mov dx,offset TRANGROUP:Extend_Buf_Ptr ; DX = ptr to msg block
  283. mov Extend_Buf_Ptr,LessArgs_Ptr ; set msg # "param missing"
  284. jmp short CError_ParseJ ; take parse error exit
  285. Try_Too_Many:
  286. cmp al,2
  287. jbe ACountOk ; <= 2 arguments - ok
  288. mov dx,offset TRANGROUP:Extend_Buf_Ptr ; DX = ptr to msg block
  289. mov Extend_Buf_Ptr,MoreArgs_Ptr ; set msg # "too many params"
  290. CError_ParseJ:
  291. mov Msg_Disp_Class,PARSE_MSG_CLASS ; parse error message
  292. CError4J:
  293. jmp CError ; command error exit
  294. ACountOk:
  295. mov bp,offset TRANGROUP:DestVars ; BP = base of dest variables
  296. ; Bugbug: use of BP without segment override implies SS.
  297. ; SS is implicitly assumed to point at TRANGROUP.
  298. cmp al,1
  299. jne Got2Args ; we have 2 arguments
  300. ; Only one independent pathname argument on command line.
  301. ; Set destination to d:*.*, where d: is current drive.
  302. ; Bugbug: but is this appropriate for "copy x:file1+x:file2"?
  303. ; The two files would be appended as d:file1, rather than x:file1.
  304. mov al,CurDrv ; AL = current drive (0 = A)
  305. add al,CAPITAL_A ; AL = current drive letter
  306. mov ah,':' ; AX = "d:"
  307. mov [bp].siz,2 ; pathname length = 2
  308. mov di,offset TRANGROUP:DestBuf ; ES:DI = ptr to dest path buf
  309. stosw ; store "d:"
  310. mov DestSwitch,0 ; clear destination switches
  311. mov [bp].info,2 ; mark destination 'wildcard present'
  312. mov [bp].isdir,0 ; mark destination 'not a directory'
  313. invoke SetStars ; add wildcards
  314. Got2Args:
  315. ; If destination pathname is "d:", add full wildcard filename
  316. cmp [bp].siz,2
  317. jne NotShortDest ; not two chars, can't be "d:"
  318. mov al,':'
  319. cmp destbuf+1,al
  320. jne NotShortDest ; it's just a 2-character filename
  321. or [bp].info,2 ; mark destination 'wildcard present'
  322. mov di,offset TRANGROUP:DestBuf+2
  323. ; ES:DI = ptr after "d:"
  324. mov [bp].isdir,0 ; mark destination 'not a directory'
  325. invoke SetStars ; add wildcards
  326. NotShortDest:
  327. ; If destination pathname ends with "\", try to make
  328. ; sure it's "d:\".
  329. mov di,[bp].ttail ; DI = ptr to last path element
  330. cmp byte ptr [di],0
  331. jne ChkSwtches ; not a null, so last char not "\"
  332. mov dx,offset TRANGROUP:BadCD_Ptr ; DX = ptr to msg block
  333. mov al,':'
  334. cmp byte ptr [di-2],al
  335. jne CError4J ; it's not "d:\", exit with error msg
  336. mov [bp].isdir,2 ; destination 'is a directory'
  337. or [bp].info,6 ; destination wildcarded and contains
  338. ; path character
  339. invoke SetStars ; add wildcards
  340. ChkSwtches:
  341. ;AD018; mov ax,[ALLSWITCH]
  342. ;AD018; test ax,NOT SwitchCopy
  343. ;AD018; jz NOT_BAD_SWITCH ;AN000; Switches are okay
  344. ;AD018; MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
  345. ;AD018; mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number
  346. ;AD018; jmp short CERROR_PARSEJ ;AC000; Switch specified which is not known
  347. ;AD018; NOT_BAD_SWITCH:
  348. ; We have enough information about the destination for now.
  349. ; Turn on verify if requested. Save the current verify flag.
  350. mov ax,AllSwitch ; AX = all switch flags
  351. test ax,SwitchV
  352. jz NoVerif ; no /v, no verify
  353. mov ah,GET_VERIFY_ON_WRITE ; AH = 'Get Verify Flag'
  354. int 21h ; call DOS
  355. push ds
  356. mov ds,ResSeg
  357. assume ds:RESGROUP
  358. xor ah,ah
  359. mov VerVal,ax ; save current verify flag
  360. pop ds
  361. assume ds:TRANGROUP
  362. mov ax,(SET_VERIFY_ON_WRITE shl 8) or 1 ; AX = 'Set Verify Flag'
  363. int 21h ; call DOS
  364. NoVerif:
  365. ;* Scan for first source.
  366. xor bp,bp ; BP = switch flags accumulator
  367. mov si,81h ; SI = ptr into command line
  368. mov bl,PLUS_CHR ; BL = special CParse delimiter = "+"
  369. ScanFSrc:
  370. mov di,offset TRANGROUP:ScanBuf ; DI = ptr to pathname buf
  371. invoke CParse ; parse first source pathname
  372. test bh,1 ; switch?
  373. jnz ScanFSrc ; yes, try again
  374. or DestSwitch,bp ; include copy-wide switches on dest
  375. ; Set ascii copying mode if concatenating, unless /b is specified.
  376. test bp,SWITCHB
  377. jnz NoSetCAsc ; /b - explicit binary copy
  378. cmp Concat,0
  379. je NoSetCAsc ; we're not concatenating
  380. mov Ascii,SWITCHA ; set ascii copy
  381. NoSetCAsc:
  382. call Source_Set ; set source variables
  383. call FrstSrc ; set up first source copy
  384. jmp FirstEnt ; jump into the copy loop
  385. public EndCopy
  386. EndCopy:
  387. ;* End of the road. Close destination, display # files
  388. ; copied (meaning # destinations), and go back to main
  389. ; transient COMMAND code.
  390. call CloseDest
  391. EndCopy2:
  392. mov dx,offset TRANGROUP:Copied_Ptr
  393. mov si,FileCnt
  394. mov Copy_Num,si
  395. invoke Std_PrintF
  396. jmp TCommand ; stack could be messed up
  397. SrcNonexist:
  398. ;* Source doesn't exist. If concatenating, ignore and continue.
  399. ; Otherwise, say 'file not found' and quit.
  400. cmp Concat,0
  401. jne NextSrc ; concatenating - go on to next source
  402. ; Set up error message.
  403. mov Msg_Disp_Class,EXT_MSG_CLASS ; extended error msg
  404. mov dx,offset TRANGROUP:Extend_Buf_Ptr ; DX = ptr to msg block
  405. mov Extend_Buf_Ptr,ERROR_FILE_NOT_FOUND ; 'file not found' msg#
  406. mov String_Ptr_2,offset TRANGROUP:SrcBuf ; point at bad pathname
  407. mov Extend_Buf_Sub,ONE_SUBST ; 1 substitution
  408. jmp CopErr ; print msg and clean up
  409. SourceProc:
  410. ;* Preparatory processing for each source file.
  411. ; Called at FrstSrc for first source file.
  412. call Source_Set ; set source variables & ascii/binary
  413. cmp Concat,0
  414. jne LeaveCFlag ; concatenating - leave CFlag alone
  415. FrstSrc:
  416. xor ax,ax
  417. mov CFlag,al ; 'destination not created'
  418. mov NxtAdd,ax ; copy buffer ptr = 0
  419. mov DestClosed,al ; 'destination not closed'
  420. LeaveCFlag:
  421. mov SrcPt,si ; save cmd-line ptr
  422. mov di,offset TRANGROUP:UserDir1 ; DI = ptr to buf for user's
  423. ; current dir
  424. mov bp,offset TRANGROUP:SrcVars ; BP = base of source variables
  425. invoke BuildPath ; cd to source dir, figure
  426. ; out stuff about source
  427. mov si,SrcTail ; SI = ptr to source filename
  428. return
  429. NextSrc:
  430. ;* Next source. Come here after handling each pathname.
  431. ; We're done unless there are additional source pathnames
  432. ; to be appended.
  433. ;
  434. ; Note that all files matching an ambiguous pathname
  435. ; are processed before coming here.
  436. cmp Plus,0
  437. jne MoreCp ; copying "+" sources - keep going
  438. EndCopyJ2:
  439. jmp EndCopy ; done copying
  440. MoreCp:
  441. xor bp,bp ; BP = switch flags accumulator
  442. mov si,SrcPt ; SI = ptr to current pos'n in cmd line
  443. mov bl,PLUS_CHR ; BL = special delimiter = "+"
  444. ScanSrc:
  445. mov di,offset TRANGROUP:ScanBuf ; DI = ptr to pathname buf
  446. invoke CParse ; parse first source name
  447. jc EndCopyJ2 ; CR found - we're done
  448. test bh,80h
  449. jz EndCopyJ2 ; no "+" delimiter - we're done
  450. test bh,1
  451. jnz ScanSrc ; switch found - keep looking
  452. ; ScanBuf contains the next source pathname.
  453. call SourceProc ; prepare this source
  454. cmp Comma,1 ;g was +,, found last time?
  455. jne NoStamp ;g no - try for a file
  456. mov Plus_Comma,1 ;g yes - set flag
  457. jmp SrcNonexist ;g we know we won't find it
  458. NoStamp: ;g
  459. mov Plus_Comma,0 ;g reset +,, flag
  460. FirstEnt:
  461. ;
  462. ;M047
  463. ; The only case we need to worry about is when the source is wildcarded and
  464. ;the destination is not. For this case, ConCat is not yet set to indicate
  465. ;concatenation. We check for this case.
  466. ;
  467. ;NB: This change has been backed out and replaced by M048. This is not the
  468. ;right place to do this check.
  469. ;
  470. ; This is where we enter the loop with the first source.
  471. mov di,FCB ; DI = ptr to FCB
  472. mov ax,PARSE_FILE_DESCRIPTOR shl 8 ; 'Parse Filename'
  473. int 21h ; call DOS
  474. cmp byte ptr [si],0 ; did we parse the whole thing?
  475. jne SrchDone ; no, error, simulate 'not found'
  476. mov ax,word ptr SrcBuf ; AX = possible "d:"
  477. cmp ah,':'
  478. je @f ; AX = definite "d:"
  479. mov al,'@' ; AL = drive 'letter' for current drive
  480. @@:
  481. or al,20h ; AL = lowercase drive letter
  482. sub al,60h ; AL = drive id (0=current,1=A,..)
  483. mov ds:FCB,al ; put drive id in FCB
  484. ; FCB contains drive and filename to search.
  485. mov ah,DIR_SEARCH_FIRST ; AH = 'Find First File'
  486. call Search
  487. SrchDone:
  488. pushf ; save flags from Search
  489. invoke RestUDir1 ; restore users current directory
  490. popf ; restore flags from search
  491. jz @f ; found the source - continue
  492. jmp SrcNonexist ; didn't find the source
  493. @@:
  494. xor al,al
  495. xchg al,FrstSrch
  496. or al,al
  497. jz NextAmbig
  498. SetNMel:
  499. mov cx,12
  500. mov di,offset TRANGROUP:SDirBuf
  501. mov si,offset TRANGROUP:DirBuf
  502. rep movsb ; save very first source name
  503. NextAmbig:
  504. xor al,al
  505. mov NoWrite,al ; turn off nowrite
  506. mov di,SrcTail
  507. mov si,offset TRANGROUP:DirBuf + 1
  508. invoke Fcb_To_Ascz ; SrcBuf has complete name
  509. MelDo:
  510. cmp Concat,0
  511. jne ShowCpNam ; concatenating - show name
  512. test SrcInfo,2 ; wildcard - show name
  513. jz DoRead
  514. ShowCpNam:
  515. mov dx,offset TRANGROUP:File_Name_Ptr
  516. invoke Std_PrintF
  517. invoke CrLf2
  518. DoRead:
  519. call DoCopy
  520. cmp Concat,0
  521. jne NoDClose ; concatenating - don't close dest
  522. call CloseDest ; close current destination
  523. jc NoDClose ; concatenating - dest not closed
  524. mov CFlag,0 ; 'destination not created'
  525. NoDClose:
  526. cmp Concat,0
  527. je NoFlush ; not concatenating - don't flush
  528. ; Concatenating - flush output between source files so LostErr
  529. ; stuff works correctly.
  530. invoke FlshFil
  531. test MelCopy,0FFh
  532. jz @f
  533. jmp short DoMelCopy
  534. @@:
  535. NoFlush:
  536. call SearchNext ; try next match
  537. jnz NextSrcJ ; not found - finished with
  538. ; this source spec
  539. mov DestClosed,0 ; 'destination not closed'
  540. jmp NextAmbig ; do next ambig match
  541. DoMelCopy:
  542. cmp MelCopy,0FFh
  543. je ContMel
  544. mov si,SrcPt
  545. mov MelStart,si
  546. mov MelCopy,0FFh
  547. ContMel:
  548. xor bp,bp
  549. mov si,SrcPt
  550. mov bl,PLUS_CHR
  551. ScanSrc2:
  552. mov di,offset TRANGROUP:ScanBuf
  553. invoke CParse
  554. test bh,80h
  555. jz NextMel ; no "+" - go back to start
  556. test bh,1
  557. jnz ScanSrc2 ; switch - keep scanning
  558. call SourceProc
  559. invoke RestUDir1
  560. mov di,offset TRANGROUP:DestFcb2
  561. mov ax,PARSE_FILE_DESCRIPTOR shl 8
  562. int 21h
  563. mov bx,offset TRANGROUP:SDirBuf + 1
  564. mov si,offset TRANGROUP:DestFcb2 + 1
  565. mov di,SrcTail
  566. invoke BuildName
  567. cmp Concat,0
  568. je MelDoJ ; not concatenating - continue
  569. ; Yes, turn off nowrite because this part of the code
  570. ; is only reached after the first file has been dealt with.
  571. mov NoWrite,0
  572. MelDoJ:
  573. jmp MelDo
  574. NextSrcJ:
  575. jmp NextSrc
  576. NextMel:
  577. call CloseDest
  578. xor ax,ax
  579. mov CFlag,al
  580. mov NxtAdd,ax
  581. mov DestClosed,al
  582. mov si,MelStart
  583. mov SrcPt,si
  584. call SearchNext
  585. jz SetNMelJ
  586. jmp EndCopy2
  587. SetNMelJ:
  588. jmp SetNMel
  589. SearchNext:
  590. mov ah,DIR_SEARCH_NEXT
  591. test SrcInfo,2
  592. jnz Search ; do search-next if ambig
  593. or ah,ah ; reset zero flag
  594. return
  595. Search:
  596. push ax
  597. mov ah,SET_DMA
  598. mov dx,offset TRANGROUP:DirBuf
  599. int 21h ; put result of search in dirbuf
  600. pop ax ; restore search first/next command
  601. mov dx,FCB
  602. int 21h ; Do the search
  603. or al,al
  604. return
  605. DoCopy:
  606. mov si,offset TRANGROUP:SrcBuf ;g do name translate of source
  607. mov di,offset TRANGROUP:SrcXName ;g save for name comparison
  608. mov ah,XNAMETRANS ;g
  609. int 21h ;g
  610. mov RdEof,0 ; no EOF yet
  611. mov ax,EXTOPEN shl 8 ; open the file
  612. ;M046
  613. ; For reads, the sharing mode should be deny none so that any process can
  614. ;open this file again in any other sharing mode. This is mainly to allow
  615. ;multiple command.com's to access the same file without getting sharing
  616. ;violations
  617. ;
  618. mov bx,DENY_NONE or READ_OPEN_MODE ; open mode for COPY ;M046
  619. xor cx,cx ; no special files
  620. mov dx,READ_OPEN_FLAG ; set up open flags
  621. int 21h
  622. jnc OpenOk
  623. ; Bogosity: IBM wants us to issue Access Denied in this case.
  624. ; They asked for it...
  625. jmp short Error_On_Source ;AC022; clean up and exit
  626. OpenOk:
  627. mov bx,ax ; save handle
  628. mov SrcHand,bx ; save handle
  629. mov ax,(FILE_TIMES shl 8)
  630. int 21h
  631. jc Error_On_Source
  632. mov CpDate,dx ; save date
  633. mov CpTime,cx ; save time
  634. jmp short No_Copy_Xa ; (xa copy code removed)
  635. Error_On_Source: ;AN022; we have a BAD error
  636. invoke Set_Ext_Error_Msg ;AN022; set up the error message
  637. mov String_Ptr_2,offset TRANGROUP:SrcBuf ;AN022; get address of failed string
  638. mov Extend_Buf_Sub,ONE_SUBST ;AN022; put number of subst in control block
  639. invoke Std_EprintF ;AN022; print it
  640. cmp SrcHand,0 ;AN022; did we open the file?
  641. je No_Close_Src ;AN022; no - don't close
  642. call CloseSrc ;AN022; clean up
  643. No_Close_Src: ;AN022;
  644. cmp CFlag,0 ;AN022; was destination created?
  645. je EndCopyJ3 ;AN022; no - just cleanup and exit
  646. jmp EndCopy ;AN022; clean up concatenation and exit
  647. EndCopyJ3: ;AN022;
  648. jmp EndCopy2 ;AN022;
  649. No_Copy_Xa:
  650. mov bx,SrcHand ;AN022; get handle back
  651. mov ax,(IOCTL shl 8)
  652. int 21h ; get device stuff
  653. and dl,DEVID_ISDEV
  654. mov SrcIsDev,dl ; set source info
  655. jz CopyLp ; source not a device
  656. cmp Binary,0
  657. je CopyLp ; ascii device ok
  658. mov dx,offset TRANGROUP:InBDev_Ptr ; cannot do binary input
  659. jmp CopErr
  660. CopyLp:
  661. mov bx,SrcHand
  662. mov cx,BytCnt
  663. mov dx,NxtAdd
  664. sub cx,dx ; compute available space
  665. jnz GotRoom
  666. invoke FlshFil
  667. cmp TermRead,0
  668. jne CloseSrc ; give up
  669. mov cx,BytCnt
  670. GotRoom:
  671. push ds
  672. mov ds,Tpa
  673. assume ds:NOTHING
  674. mov ah,READ
  675. int 21h
  676. pop ds
  677. assume ds:TRANGROUP
  678. jc Error_On_Source ;AC022; give up if error
  679. mov cx,ax ; get count
  680. jcxz CloseSrc ; no more to read
  681. cmp SrcIsDev,0
  682. jne NoTestA ; is a device, ascii mode
  683. cmp Ascii,0
  684. je BinRead
  685. NoTestA:
  686. mov dx,cx
  687. mov di,NxtAdd
  688. mov al,1Ah
  689. push es
  690. mov es,Tpa
  691. repne scasb ; scan for EOF
  692. pop es
  693. jne UseAll
  694. inc RdEof
  695. inc cx
  696. UseAll:
  697. sub dx,cx
  698. mov cx,dx
  699. BinRead:
  700. add cx,NxtAdd
  701. mov NxtAdd,cx
  702. cmp cx,BytCnt ; is buffer full?
  703. jb TestDev ; if not, we may have found eof
  704. invoke FlshFil
  705. cmp TermRead,0
  706. jne CloseSrc ; give up
  707. jmp short CopyLp
  708. TestDev:
  709. cmp SrcIsDev,0
  710. je CloseSrc ; if file then EOF
  711. cmp RdEof,0
  712. je CopyLp ; on device, go till ^Z
  713. CloseSrc:
  714. mov bx,SrcHand
  715. mov ah,CLOSE
  716. int 21h
  717. return
  718. CloseDest:
  719. ; We are called to close the destination.
  720. ; We need to note whether or not there is any internal data left
  721. ; to be flushed out.
  722. cmp DestClosed,0
  723. retnz ; don't double close
  724. mov al,byte ptr DestSwitch
  725. invoke SetAsc ; check for b or a switch
  726. jz BinClos ; on destination
  727. mov bx,NxtAdd
  728. ;
  729. ;M048 -- TryFlush changes the state of ConCat flag. So, before we append a
  730. ;^Z, let's always flush out. This way if the ConCat flag changes, we will
  731. ;just return without appending a ^Z incorrectly for the first file(since we
  732. ;are concatenating now). Also, in case it is a single file copy, we will
  733. ;anyway write the ^Z out separately. The only drawback is that there is a
  734. ;performance overhead on single ASCII file copies which now always involve
  735. ;2 writes instead of 1 before. Is this really that important?
  736. ;
  737. ;M048; cmp bx,BytCnt ; is memory full?
  738. ;M048; jne PutZ
  739. invoke TryFlush ; flush (and double-check for concat)
  740. je NoConc
  741. ConChng: ; concat flag changed on us
  742. stc
  743. return
  744. NoConc:
  745. xor bx,bx
  746. PutZ:
  747. push ds
  748. mov ds,Tpa
  749. mov word ptr [bx],1Ah ; add EOF mark (ctrl-Z)
  750. pop ds
  751. inc NxtAdd
  752. mov NoWrite,0 ; make sure our ^z gets written
  753. mov ax,Written
  754. add ax,NxtAdd
  755. jc BinClos ; > 1
  756. cmp ax,1
  757. je ForgetItJ ; Written = 0 NxtAdd = 1 (the ^Z)
  758. BinClos:
  759. invoke TryFlush
  760. jnz ConChng
  761. cmp Written,0
  762. ForgetItJ:
  763. jne No_Forget ; wrote something
  764. jmp ForgetIt ; never wrote nothing
  765. No_Forget:
  766. mov bx,DestHand
  767. mov cx,CpTime
  768. mov dx,CpDate
  769. cmp Inexact,0 ; copy not exact?
  770. je DoDClose ; if no, copy date & time
  771. mov ah,GET_TIME
  772. int 21h
  773. shl cl,1
  774. shl cl,1 ; left justify min in cl
  775. shl cx,1
  776. shl cx,1
  777. shl cx,1 ; hours to high 5 bits, min to 5-10
  778. shr dh,1 ; divide seconds by 2 (now 5 bits)
  779. or cl,dh ; and stick into low 5 bits of cx
  780. push cx ; save packed time
  781. mov ah,GET_DATE
  782. int 21h
  783. sub cx,1980
  784. xchg ch,cl
  785. shl cx,1 ; year to high 7 bits
  786. shl dh,1 ; month to high 3 bits
  787. shl dh,1
  788. shl dh,1
  789. shl dh,1
  790. shl dh,1 ; most sig bit of month in carry
  791. adc ch,0 ; put that bit next to year
  792. or dl,dh ; or low three of month into day
  793. mov dh,ch ; get year and high bit of month
  794. pop cx ; get time back
  795. DoDClose:
  796. cmp bx,0
  797. jle CloseDone
  798. mov ax,(FILE_TIMES shl 8) or 1
  799. int 21h ; set date and time
  800. jc Cleanup_Err ;AN022; handle error
  801. ; See if the destination has *anything* in it.
  802. ; If not, just close and delete it.
  803. mov ax,(LSEEK shl 8) + 2 ; seek to EOF
  804. xor dx,dx
  805. mov cx,dx
  806. int 21h
  807. ; DX:AX is file size
  808. or dx,ax
  809. pushf
  810. mov ax,(IOCTL SHL 8) + 0 ; get the destination attributes
  811. int 21h
  812. push dx ; save them away
  813. mov ah,CLOSE
  814. int 21h
  815. pop dx
  816. jnc Close_Cont ;AN022; handle error on close
  817. popf ;AN022; get the flags back
  818. Cleanup_Err: ;AN022;
  819. call CleanUpErr ;AN022; attempt to delete the target
  820. call DestDelete ;AN022; attempt to delete the target
  821. jmp short FileClosed ;AN022; close the file
  822. Close_Cont: ;AN022; no error - continue
  823. popf
  824. jnz CloseDone
  825. test dx,80h ; is the destination a device?
  826. jnz CloseDone ; yes, copy succeeded
  827. call DestDelete
  828. jmp short FileClosed
  829. CloseDone:
  830. inc FileCnt
  831. FileClosed:
  832. inc DestClosed
  833. Ret50:
  834. clc
  835. return
  836. ForgetIt:
  837. mov bx,DestHand
  838. call DoDClose ; close the dest
  839. call DestDelete
  840. mov FileCnt,0 ; no files transferred
  841. jmp Ret50
  842. DestDelete:
  843. mov dx,offset TRANGROUP:DestBuf
  844. mov ah,UNLINK
  845. int 21h ; and delete it
  846. return
  847. Source_Set proc near
  848. push si
  849. mov ax,StartEl
  850. mov si,offset TRANGROUP:ScanBuf ; adjust to copy
  851. sub ax,si
  852. mov di,offset TRANGROUP:SrcBuf
  853. add ax,di
  854. mov SrcTail,ax
  855. mov SrcSiz,cl ; save its size
  856. inc cx ; include the nul
  857. rep movsb ; save this source
  858. mov SrcInfo,bh ; save info about it
  859. pop si
  860. mov ax,bp ; switches so far
  861. invoke SetAsc ; set a,b switches accordingly
  862. invoke Switch ; get any more switches on this arg
  863. invoke SetAsc ; set
  864. return
  865. Source_Set endp
  866. ;****************************************************************
  867. ;*
  868. ;* ROUTINE: CleanupErr
  869. ;*
  870. ;* FUNCTION: Issues extended error message for destination
  871. ;* if not alreay issued
  872. ;*
  873. ;* INPUT: return from INT 21
  874. ;*
  875. ;* OUTPUT: none
  876. ;*
  877. ;****************************************************************
  878. CleanupErr proc near ;AN022;
  879. cmp Msg_Flag,0 ;AN022; have we already issued a message?
  880. jnz CleanupErr_Cont ;AN022; yes - don't issue duplicate error
  881. invoke Set_Ext_Error_Msg ;AN022; set up error message
  882. mov String_Ptr_2,offset TRANGROUP:DestBuf ;AN022; get address of failed string
  883. mov Extend_Buf_Sub,ONE_SUBST ;AN022; put number of subst in control block
  884. invoke Std_EPrintF ;AN022; issue the error message
  885. CleanupErr_Cont: ;AN022;
  886. ret ;AN022; return to caller
  887. CleanupErr endp ;AN022;
  888. TRANCODE ends
  889. end
  890.