1 ; **************************************************************************** 2 ; cp8086.s (cp0.s) - by Erdogan Tan - 20/04/2022 3 ; ---------------------------------------------------------------------------- 4 ; Retro UNIX 8086 v1 - copy -- cp oldfile newfile 5 ; 6 ; [ Last Modification: 10/05/2022 ] 7 ; 8 ; Derived from (original) UNIX v7 (& v7 x86) 'cp.c' source Code 9 ; Ref: 10 ; www.tuhs.org (https://minnie.tuhs.org) 11 ; v7.tar.gz 12 ; **************************************************************************** 13 ; [ v7.tar - usr/src/cmd/cp.c (archive date: 10-1-1979) ] 14 ; 15 ; Assembler: NASM v2.15 16 ; ((nasm cp8086.s -l cp8086.txt -o cp8086.bin -Z error.txt)) 17 ; 18 ; cp1.s - 21/04/2022 - Retro UNIX 386 v1.2 (modified unix v7 inode) 19 ; cp0.s - 21/04/2022 - Retro UNIX 386 v1 & v1.1 20 ; cp8086.s - 22/04/2022 - Retro UNIX 8086 v1 (16 bit 'cp0.s') 21 22 ; 12/01/2022 (Retro UNIX 386 v1.2) 23 ; 13/10/2015 24 25 ; UNIX v1 system calls 26 _rele equ 0 27 _exit equ 1 28 _fork equ 2 29 _read equ 3 30 _write equ 4 31 _open equ 5 32 _close equ 6 33 _wait equ 7 34 _creat equ 8 35 _link equ 9 36 _unlink equ 10 37 _exec equ 11 38 _chdir equ 12 39 _time equ 13 40 _mkdir equ 14 41 _chmod equ 15 42 _chown equ 16 43 _break equ 17 44 _stat equ 18 45 _seek equ 19 46 _tell equ 20 47 _mount equ 21 48 _umount equ 22 49 _setuid equ 23 50 _getuid equ 24 51 _stime equ 25 52 _quit equ 26 53 _intr equ 27 54 _fstat equ 28 55 _emt equ 29 56 _mdate equ 30 57 _stty equ 31 58 _gtty equ 32 59 _ilgins equ 33 60 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 61 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 62 _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 63 ; 12/01/2022 - Retro UNIX 386 v1.2 64 ; Retro UNIX 386 v2 system calls 65 _setgid equ 37 66 _getgid equ 38 67 _sysver equ 39 ; (get) Retro Unix 386 version 68 69 ;;; 70 ESCKey equ 1Bh 71 EnterKey equ 0Dh 72 73 ;%macro sys 1-4 74 ; ; 03/09/2015 75 ; ; 13/04/2015 76 ; ; Retro UNIX 386 v1 system call. 77 ; %if %0 >= 2 78 ; mov ebx, %2 79 ; %if %0 >= 3 80 ; mov ecx, %3 81 ; ;%if %0 = 4 82 ; %if %0 >= 4 ; 11/03/2022 83 ; mov edx, %4 84 ; %endif 85 ; %endif 86 ; %endif 87 ; mov eax, %1 88 ; int 30h 89 ;%endmacro 90 91 %macro sys 1-4 92 ; Retro UNIX 8086 v1 system call. 93 %if %0 >= 2 94 mov bx, %2 95 %if %0 >= 3 96 mov cx, %3 97 %if %0 >= 4 98 mov dx, %4 99 %endif 100 %endif 101 %endif 102 mov ax, %1 103 int 20h 104 %endmacro 105 106 ;; Retro UNIX 386 v1 system call format: 107 ;; sys systemcall (eax) , , 108 109 ;; 11/03/2022 110 ;; Note: Above 'sys' macro has limitation about register positions; 111 ;; ebx, ecx, edx registers must not be used after their 112 ;; positions in sys macro. 113 ;; for example: 114 ;; 'sys _write, 1, msg, ecx' is defective, because 115 ;; ecx will be used/assigned before edx in 'sys' macro. 116 ;; correct order may be: 117 ;; 'sys _write, 1, msg, eax ; (eax = byte count) 118 119 ; Retro UNIX 8086 v1 system call format: 120 ; sys systemcall (ax) , , 121 122 struc stat 123 ; Note: This is for Retro UNIX v1 'sysstat' output !!! 124 ; (34 bytes) 125 00000000 ???? .inode: resw 1 126 00000002 ???? .mode: resw 1 127 00000004 ?? .nlinks: resb 1 128 00000005 ?? .uid: resb 1 129 00000006 ???? .size: resw 1 130 00000008 .dskptr: resw 8 131 00000018 ???????? .ctime: resd 1 132 0000001C ???????? .mtime: resd 1 133 00000020 ???? .rsvd: resw 1 134 .strucsize: 135 endstruc 136 137 ;struc stat 138 ; ; Note: This is for Retro UNIX v1.2 'sysstat' output !!! 139 ; ; (66 bytes) 140 ; .inode: resw 1 141 ; .mode: resw 1 142 ; .nlinks: resw 1 143 ; .uid: resw 1 144 ; .gid: resb 1 145 ; .size_h: resb 1 146 ; .size: resd 1 147 ; .dskptr: resd 10 148 ; .atime: resd 1 149 ; .mtime: resd 1 150 ; .ctime: resd 1 151 ; .strucsize: 152 ;endstruc 153 154 ;S_IFMT equ 0F000h ; /* type of file */ 155 ;S_IFDIR equ 04000h ; /* directory */ 156 ;S_IFCHR equ 02000h ; /* character special */ 157 ;S_IFBLK equ 06000h ; /* block special */ 158 ;S_IFREG equ 08000h ; /* regular */ 159 ;S_ISUID equ 00800h ; /* set user id on execution */ 160 ;S_ISGID equ 00400h ; /* set group id on execution */ 161 ;S_IREAD equ 00100h ; /* read permission, owner */ 162 ;S_IWRITE equ 00080h ; /* write permission, owner */ 163 ;S_IEXEC equ 00040h ; /* execute/search permission, owner */ 164 165 ; 23/04/2022 166 ; 21/04/2022 - UNIX v1 inode 167 ; byte 1 168 S_ALLOC equ 080h ; Allocated flag 169 S_IFDIR equ 040h ; Directory flag 170 S_IFMDF equ 020h ; File modified flag (always on) 171 S_IFLRG equ 010h ; Large File flag 172 ; byte 0 173 S_ISUID equ 020h ; Set User ID On Execution flag 174 S_IEXEC equ 010h ; Executable File flag 175 S_IREAD equ 008h ; Owner's Read Permission flag 176 S_IWRITE equ 004h ; Owner's Write Permission flag 177 178 BSIZE equ 512 179 180 ;----------------------------------------------------------------- 181 ; text - code 182 ;----------------------------------------------------------------- 183 184 ;[BITS 32] ; 32-bit intructions (for 80386 protected mode) 185 186 [BITS 16] ; 16-bit (x86 real mode) intructions 187 188 [ORG 0] 189 190 START_CODE: 191 ; 10/05/2022 192 ; 09/05/2022 193 ; 22/04/2022 - 16 bit version (Retro UNIX 8086 v1) 194 ; 195 ; 20/04/2022 196 ; main(argc, argv) 197 198 ;mov esi, esp 199 ;mov edi, esi 200 ;lodsd ; number of arguments 201 ;;mov edi, esi 202 ;;mov [argc], eax 203 ;mov [argc], al 204 205 ; 22/04/2022 206 00000000 89E6 mov si, sp 207 00000002 89F7 mov di, si 208 00000004 AD lodsw 209 ;mov [argc], ax 210 00000005 A2[9E01] mov [argc], al 211 212 ;if (argc < 3) 213 ; goto usage; 214 215 ;;cmp eax, 3 216 ;cmp ax, 3 217 00000008 3C03 cmp al, 3 218 0000000A 732D jnb short cp_0 ; if (argc > 3) { 219 0000000C FEC8 dec al ; 21/04/2022 220 0000000E 7506 jnz short cp_usage 221 222 ;sys _msg, program_msg, 255, 0Fh 223 ; 22/04/2022 224 00000010 B8[9F01] mov ax, program_msg ; asciiz message address 225 00000013 E80B00 call print_msg 226 227 cp_usage: 228 ; fprintf(stderr, "Usage: cp: f1 f2; or cp f1 ... fn d2\n"); 229 ;sys _msg, usage_msg, 255, 07h 230 00000016 B8[D701] mov ax, usage_msg 231 00000019 E80500 call print_msg 232 cp_exit: 233 sys _exit ; sys exit 92 <1> 93 <1> %if %0 >= 2 94 <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 0000001C B80100 <1> mov ax, %1 103 0000001F CD20 <1> int 20h 234 ;hlt: 235 ; nop 236 ; nop 237 ; jmp short hlt 238 239 print_msg: 240 ; 22/04/2022 241 ; Modified registers: ax, bx, cx, dx 242 strlen: 243 ; ax = asciiz string address 244 00000021 89C3 mov bx, ax 245 00000023 4B dec bx 246 nextchr: 247 00000024 43 inc bx 248 00000025 803F00 cmp byte [bx], 0 249 00000028 77FA ja short nextchr 250 ;cmp [bx], 0Dh 251 ;ja short nextchr 252 0000002A 29C3 sub bx, ax 253 ; bx = asciiz string length 254 ;retn 255 print_str: 256 0000002C 89DA mov dx, bx 257 sys _write, 1, ax 92 <1> 93 <1> %if %0 >= 2 94 0000002E BB0100 <1> mov bx, %2 95 <1> %if %0 >= 3 96 00000031 89C1 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000033 B80400 <1> mov ax, %1 103 00000036 CD20 <1> int 20h 258 259 00000038 C3 retn 260 261 cp_0: 262 ;mov edx, eax ; [argc] 263 ;; 21/04/2022 264 ;;;dec edx ; argc-1 265 ;;dec dl 266 ;shl dl, 2 ; * 4 267 ;add edi, edx 268 269 ; 22/04/2022 270 00000039 89C2 mov dx, ax 271 0000003B D0E2 shl dl, 1 ; * 2 ; 16 bit argument pointers 272 0000003D 01D7 add di, dx 273 274 ; 21/04/2022 275 0000003F 3C03 cmp al,3 276 00000041 7613 jna short cp_1 277 278 ;sys _stat, [edi], stbuf2 279 sys _stat, [di], stbuf2 ; 22/04/2022 92 <1> 93 <1> %if %0 >= 2 94 00000043 8B1D <1> mov bx, %2 95 <1> %if %0 >= 3 96 00000045 B9[8202] <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000048 B81200 <1> mov ax, %1 103 0000004B CD20 <1> int 20h 280 0000004D 72C7 jc short cp_usage 281 282 ;; check retro unix v2 inode flags 283 ;; (a bit different than unix v7 inode flags) 284 ;; if it is a directory.. 285 ;; regular file flag and dir flag must be 1 286 ;mov al, [stbuf2+stat.mode+1] 287 ;and al, S_IFDIR|S_IFREG 288 ;cmp al, S_IFDIR|S_IFREG ; directory ? 289 ;jne short cp_usage ; no 290 291 ;; check if it is a device file 292 ;;test al, S_IFREG ; regular file ? 293 ;;jz short cp_usage ; no 294 ;;and al, S_IFDIR ; directory ? 295 ;;jz short cp_usage ; no 296 297 ; 21/04/2022 298 ; check (unix v1 inode) directory flag 299 0000004F F606[8502]40 test byte [stbuf2+stat.mode+1], S_IFDIR ; directory ? 300 00000054 74C0 jz short cp_usage ; no 301 302 cp_1: 303 ; esi = esp+4 = argv[0] ; executable file name (cp) 304 ;lodsd ; 21/04/2022 305 00000056 AD lodsw ; 22/04/2022 - Retro UNIX 8086 v1 306 cp_loop: ; for(i=1; i 93 <1> %if %0 >= 2 94 <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000072 B80100 <1> mov ax, %1 103 00000075 CD20 <1> int 20h 340 341 ;_halt: 342 ; nop 343 ; jmp short _halt 344 345 copy: ; copy(from, to) 346 ; 347 ; 10/05/2022 348 ; 09/05/2022 349 ; 22/04/2022 - 16 bit version (Retro UNIX 8086 v1) 350 ; 21/04/2022 351 ; 20/04/2022 352 ; INPUT: 353 ; esi = pointer to file name to be copied 354 ; edi = ptr to new file name or destination dir 355 ; OUTPUT: 356 ; cf = 0 -> OK 357 ; cf = 1 -> Error ! 358 ; 359 ; Modified registers: eax, ebx, ecx, edx, ebp 360 ; 361 362 ; open (old) file for read 363 ;sys _open, [esi], 0 364 sys _open, [si], 0 ; 22/04/2022 92 <1> 93 <1> %if %0 >= 2 94 00000077 8B1C <1> mov bx, %2 95 <1> %if %0 >= 3 96 00000079 B90000 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 0000007C B80500 <1> mov ax, %1 103 0000007F CD20 <1> int 20h 365 00000081 7313 jnc short cp_3 366 367 ; esi = file name (from) 368 369 ;fprintf(stderr, "cp: cannot open %s\n", from); 370 ; return(1); 371 372 ;sys _msg, cno_err_msg, 255, 07h 373 ; 22/04/2022 374 00000083 B8[0002] mov ax, cno_err_msg 375 00000086 E898FF call print_msg 376 377 ; file name (from) 378 ;sys _msg, [esi], 255, 07h 379 ; 22/04/2022 380 00000089 8B04 mov ax, [si] 381 write_err_nl: ; 24/04/2022 382 0000008B E893FF call print_msg 383 write_nl: 384 ; new/next line 385 ;sys _msg, nextline, 255, 07h 386 ; 22/04/2022 387 0000008E B8[FD01] mov ax, nextline 388 00000091 E88DFF call print_msg 389 ; 390 00000094 F9 stc ; return with error (cf=1) 391 00000095 C3 retn 392 393 cp_3: 394 ;mov [fold], eax ; file (descriptor) number 395 ; 22/04/2022 396 00000096 A3[7E02] mov [fold], ax ; file (descriptor) number 397 398 ; (from) 399 sys _fstat, [fold], stbuf1 92 <1> 93 <1> %if %0 >= 2 94 00000099 8B1E[7E02] <1> mov bx, %2 95 <1> %if %0 >= 3 96 0000009D B9[A402] <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 000000A0 B81C00 <1> mov ax, %1 103 000000A3 CD20 <1> int 20h 400 401 ; 10/05/2022 (new -retro unix 8086 v1- kernel) 402 ; save device number 403 ; ((device number = ax return from sysfstat)) 404 000000A5 A3[C602] mov [idev1], ax 405 406 ; save mode 407 ;mov ax, [stbuf1.mode] 408 ;mov [mode], ax 409 410 ; (to) 411 ;;sys _stat, [edi], stbuf2 ; stat(to, &stbuf2) 412 ; 22/04/2022 413 ;sys _stat, [di], stbuf2 414 ;jnc short cp_4 415 ;jmp cp_9 416 ; 22/04/2022 417 000000A8 8B2D mov bp, [di] 418 sys _stat, bp, stbuf2 ; stat(to, &stbuf2) 92 <1> 93 <1> %if %0 >= 2 94 000000AA 89EB <1> mov bx, %2 95 <1> %if %0 >= 3 96 000000AC B9[8202] <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 000000AF B81200 <1> mov ax, %1 103 000000B2 CD20 <1> int 20h 419 ;jnc short cp_4 420 ;jmp cp_9 421 000000B4 7262 jc short cp_9 422 cp_4: 423 ; /* is target a directory? */ 424 425 ;; check retro unix v2 inode flags 426 ;; (a bit different than unix v7 inode flags) 427 ;; regular file flag and dir flag must be 1 for a dir 428 ;mov al, [stbuf2+stat.mode+1] 429 ;and al, S_IFDIR|S_IFREG 430 ;cmp al, S_IFDIR|S_IFREG ; directory ? 431 ;jne short cp_8 ; no, overwrite (create file) 432 ; (if the new file is not same file) 433 434 ;; check if it is a device file 435 ;;test al, S_IFREG ; regular file ? 436 ;;jz short cp_error ; no 437 ;;and al, S_IFDIR ; directory ? 438 ;;jz short cp_error ; no 439 440 ; 21/04/2022 441 ; check (unix v1 inode) directory flag 442 000000B6 F606[8502]40 test byte [stbuf2+stat.mode+1], S_IFDIR ; directory ? 443 000000BB 7439 jz short cp_8 ; no, overwrite (create file) 444 ; (if the new file is not same file) 445 446 ; add (old) file name to (destination ) path 447 ; (directory name +'/'+ file name) 448 449 ;mov ebp, esi ; save esi 450 ;mov esi, [edi] ; directory name address 451 ;mov ebx, edi ; save edi 452 ;mov edi, iobuf ; (new) path name buffer addr 453 ; 22/04/2022 - Retro UNIX 8086 v1 (16 bit utility) 454 000000BD 89F5 mov bp, si 455 000000BF 8B35 mov si, [di] 456 000000C1 89FB mov bx, di 457 000000C3 BF[C802] mov di, iobuf 458 459 ; p1 = from; 460 ; p2 = to; 461 ; bp = iobuf; 462 cp_5: ; while(*bp++ = *p2++) 463 000000C6 AC lodsb 464 000000C7 AA stosb 465 000000C8 20C0 and al, al 466 000000CA 75FA jnz short cp_5 467 ;mov byte [edi-1], '/' ; bp[-1] = '/'; 468 ; 22/04/2022 469 000000CC C645FF2F mov byte [di-1], '/' 470 ; p2 = bp 471 ;mov edx, edi 472 ;mov esi, [ebp] ; *p1 ; from 473 ; 22/04/2022 474 000000D0 89FA mov dx, di 475 000000D2 8B7600 mov si, [bp] 476 477 cp_6: ; while(*bp = *p1++) 478 000000D5 AC lodsb 479 000000D6 AA stosb 480 000000D7 08C0 or al, al 481 000000D9 7408 jz short cp_7 482 000000DB 3C2F cmp al, '/' ; if (*bp++ == '/') 483 000000DD 75F6 jne short cp_6 484 ; bp = p2 485 ; 21/04/2022 486 ;mov edi, edx ; (discard path before file name) 487 ; 22/04/2022 488 000000DF 89D7 mov di, dx 489 000000E1 EBF2 jmp short cp_6 490 cp_7: 491 ;mov esi, ebp ; restore esi 492 ;mov edi, ebx ; restore edi 493 ; 22/04/2022 494 000000E3 89EE mov si, bp 495 000000E5 89DF mov di, bx 496 ; to = iobuf 497 ;mov ebp, iobuf 498 ; 22/04/2022 499 000000E7 BD[C802] mov bp, iobuf 500 501 ;sys _stat, ebp, stbuf2 ; stat(to, &stbuf2) >= 0 502 sys _stat, bp, stbuf2 ; 22/04/2022 92 <1> 93 <1> %if %0 >= 2 94 000000EA 89EB <1> mov bx, %2 95 <1> %if %0 >= 3 96 000000EC B9[8202] <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 000000EF B81200 <1> mov ax, %1 103 000000F2 CD20 <1> int 20h 503 000000F4 7222 jc short cp_10 ; create new file 504 505 cp_8: 506 ;if (stbuf1.st_dev == stbuf2.st_dev && 507 ; stbuf1.st_ino == stbuf2.st_ino) { 508 ; fprintf(stderr, "cp: cannot copy file to itself.\n"); 509 ; return(1); 510 511 ; 10/05/2022 (new -retro unix 8086 v1- kernel) 512 ; (is same device ?) 513 ; ((device number: ax return from sysstat)) 514 ; ax = [idev2] 515 516 000000F6 3B06[C602] cmp ax, [idev1] 517 000000FA 751C jne short cp_10 518 519 000000FC A1[A402] mov ax, [stbuf1+stat.inode] 520 000000FF 3B06[8202] cmp ax, [stbuf2+stat.inode] 521 00000103 7513 jne short cp_10 522 523 ; same file ! error... 524 ;mov ebp, cncis_err_msg ; error message 525 ; 09/05/2022 526 ; 22/04/2022 527 00000105 BD[1302] mov bp, cncis_err_msg ; error message 528 ; esi = file name (from) 529 write_err_msg: 530 ;sys _msg, ebp, 255, 07h 531 ; 22/04/2022 532 00000108 89E8 mov ax, bp 533 ; ax = error message address 534 0000010A E814FF call print_msg 535 ; 536 ; close (old) file 537 sys _close, [fold] 92 <1> 93 <1> %if %0 >= 2 94 0000010D 8B1E[7E02] <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000111 B80600 <1> mov ax, %1 103 00000114 CD20 <1> int 20h 538 00000116 F9 stc ; return with error (cf=1) 539 00000117 C3 retn 540 541 cp_9: 542 ; 22/04/2022 543 ; bp = [di] 544 ;; new file (asciiz name address) 545 ;;mov ebp, [edi] ; 21/04/2022 546 ;mov bp, [di] ; 22/04/2022 547 548 ; create new file (truncate if it exists) 549 cp_10: 550 ; fnew = creat(to, mode) 551 ;movzx ecx, word [stbuf1+stat.mode] 552 ; ecx = mode 553 ; 22/04/2022 554 00000118 8B0E[A602] mov cx, [stbuf1+stat.mode] 555 ;sys _creat, ebp 556 sys _creat, bp ; 22/04/2022 92 <1> 93 <1> %if %0 >= 2 94 0000011C 89EB <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 0000011E B80800 <1> mov ax, %1 103 00000121 CD20 <1> int 20h 557 00000123 7314 jnc short cp_11 558 559 ;if ((fnew = creat(to, mode)) < 0) { 560 ; fprintf(stderr, "cp: cannot create %s\n", to); 561 ; close(fold); 562 ; return(1); 563 564 cp_10_err: 565 ; 24/04/2022 566 sys _close, [fold] 92 <1> 93 <1> %if %0 >= 2 94 00000125 8B1E[7E02] <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000129 B80600 <1> mov ax, %1 103 0000012C CD20 <1> int 20h 567 568 ; error message 569 ;sys _msg, ccf_err_msg, 255, 07h 570 ; 22/04/2022 571 0000012E B8[3702] mov ax, ccf_err_msg ; 'can not create' error msg 572 00000131 E8EDFE call print_msg 573 574 ; and file name (to) -at the end of error message- 575 ;sys _msg, ebp, 255, 07h 576 ; 22/04/2022 577 00000134 89E8 mov ax, bp ; (new) file name 578 ;call print_msg 579 580 ; write next line (move cursor to next line) 581 ; and return (from this/copy subroutine) 582 ;jmp write_nl 583 00000136 E952FF jmp write_err_nl ; 24/04/2022 584 585 cp_11: 586 ; 25/04/2022 587 ; temporary solution 588 ; to overcome freezing/failure problem while 589 ; creating a new file (which does not appear 590 ; when the target file exists) 591 ; 592 ; [ possible reason: 593 ; buffer flush/update problem 594 ; in retro unix 8086 v1 kernel code ] 595 ; 25/04/2022 596 ; close new file 597 sys _close, ax ; flush buffers ? 92 <1> 93 <1> %if %0 >= 2 94 00000139 89C3 <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 0000013B B80600 <1> mov ax, %1 103 0000013E CD20 <1> int 20h 598 ; open it again 599 sys _open, bp, 1 ; open for write 92 <1> 93 <1> %if %0 >= 2 94 00000140 89EB <1> mov bx, %2 95 <1> %if %0 >= 3 96 00000142 B90100 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000145 B80500 <1> mov ax, %1 103 00000148 CD20 <1> int 20h 600 0000014A 72D9 jc short cp_10_err ; nonsense !? 601 602 ; 21/04/2022 603 ;mov [fnew], eax 604 ; 22/04/2022 - Retro UNIX 8086 v1 605 0000014C A3[8002] mov [fnew], ax ; (16 bit) 606 607 cp_rw_next: 608 ; while(n = read(fold, iobuf, BSIZE)) 609 sys _read, [fold], iobuf, BSIZE 92 <1> 93 <1> %if %0 >= 2 94 0000014F 8B1E[7E02] <1> mov bx, %2 95 <1> %if %0 >= 3 96 00000153 B9[C802] <1> mov cx, %3 97 <1> %if %0 >= 4 98 00000156 BA0002 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000159 B80300 <1> mov ax, %1 103 0000015C CD20 <1> int 20h 610 0000015E 730E jnc short cp_12 611 612 ;if (n < 0) { 613 ; fprintf(stderr, "cp: read error\n"); 614 615 ; write read error message 616 ;mov ebp, crd_err_msg 617 00000160 BD[4C02] mov bp, crd_err_msg ; 22/04/2022 618 619 cp_rw_err: 620 ; 21/04/2022 621 ; cf = 1 622 sys _close, [fnew] 92 <1> 93 <1> %if %0 >= 2 94 00000163 8B1E[8002] <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000167 B80600 <1> mov ax, %1 103 0000016A CD20 <1> int 20h 623 0000016C EB9A jmp write_err_msg 624 625 cp_12: 626 ; eax = read count 627 ; eax = 0 -> eof 628 ;or eax, eax 629 0000016E 09C0 or ax, ax ; 22/04/2022 (Retro UNIX 8086 v1) 630 00000170 7419 jz short cp_14 ; eof 631 632 ;mov ebp, eax ; n 633 00000172 89C2 mov dx, ax ; 22/04/2022 634 ; write(fnew, iobuf, n) 635 ;sys _write, [fnew], iobuf, ebp 636 ; 22/04/2022 637 sys _write, [fnew], iobuf 92 <1> 93 <1> %if %0 >= 2 94 00000174 8B1E[8002] <1> mov bx, %2 95 <1> %if %0 >= 3 96 00000178 B9[C802] <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 0000017B B80400 <1> mov ax, %1 103 0000017E CD20 <1> int 20h 638 00000180 7204 jc short cp_13 639 640 ;if (write(fnew, iobuf, n) != n) 641 ; fprintf(stderr, "cp: write error.\n"); 642 ; close(fold); 643 ; close(fnew); 644 ; return(1); 645 646 ; eax = written bytes 647 ;cmp eax, ebp 648 ;;je short cp_11 ; read next (block) 649 ;; 21/04/2022 650 ;je short cp_rw_next 651 ; 22/04/2022 652 00000182 39D0 cmp ax, dx 653 00000184 74C9 je short cp_rw_next 654 655 ; error ! 656 ;; eax < ebp --> cf = 1 657 ; 22/04/2022 - Retro UNIX 8086 v1 658 ; ax < dx --> cf = 1 659 cp_13: 660 ; close new file 661 ; and then write error mesage 662 ; and then close old file 663 ; and then write (move cursor to) next line 664 ; and then return (from subroutine) 665 ;sys _close, [fnew] 666 667 ; write error message 668 ;mov ebp, cwr_err_msg 669 ; 22/04/2022 670 00000186 BD[6002] mov bp, cwr_err_msg 671 ; 672 ;jmp short write_err_msg 673 ; 21/04/2022 674 00000189 EBD8 jmp short cp_rw_err 675 676 ; eof 677 cp_14: 678 ;close(fold); 679 ;close(fnew); 680 ;return(0); 681 682 sys _close, [fold] 92 <1> 93 <1> %if %0 >= 2 94 0000018B 8B1E[7E02] <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 0000018F B80600 <1> mov ax, %1 103 00000192 CD20 <1> int 20h 683 sys _close, [fnew] 92 <1> 93 <1> %if %0 >= 2 94 00000194 8B1E[8002] <1> mov bx, %2 95 <1> %if %0 >= 3 96 <1> mov cx, %3 97 <1> %if %0 >= 4 98 <1> mov dx, %4 99 <1> %endif 100 <1> %endif 101 <1> %endif 102 00000198 B80600 <1> mov ax, %1 103 0000019B CD20 <1> int 20h 684 685 ;clc 686 0000019D C3 retn 687 688 ;----------------------------------------------------------------- 689 ; data - initialized data 690 ;----------------------------------------------------------------- 691 692 ;argc: dd 0 693 0000019E 00 argc: db 0 694 695 ; ---------------------------------------------------------------- 696 697 program_msg: 698 0000019F 0D0A db 0Dh, 0Ah 699 000001A1 526574726F20554E49- db 'Retro UNIX 8086 v1 COPY by Erdogan TAN - 10/05/2022' 699 000001AA 582038303836207631- 699 000001B3 20434F505920627920- 699 000001BC 4572646F67616E2054- 699 000001C5 414E202D2031302F30- 699 000001CE 352F32303232 700 000001D4 0D0A00 db 0Dh, 0Ah, 0 701 702 usage_msg: 703 000001D7 0D0A db 0Dh, 0Ah 704 000001D9 55736167653A206370- db 'Usage: cp: f1 f2; or cp f1 ... fn d2' 704 000001E2 3A2066312066323B20- 704 000001EB 6F7220637020663120- 704 000001F4 2E2E2E20666E206432 705 nextline: 706 000001FD 0D0A00 db 0Dh, 0Ah, 0 707 708 cno_err_msg: 709 00000200 0D0A db 0Dh, 0Ah 710 00000202 63703A2063616E6E6F- db 'cp: cannot open ' 710 0000020B 74206F70656E20 711 00000212 00 db 0 712 cncis_err_msg: 713 00000213 0D0A db 0Dh, 0Ah 714 00000215 63703A2063616E6E6F- db 'cp: cannot copy file to itself.' 714 0000021E 7420636F7079206669- 714 00000227 6C6520746F20697473- 714 00000230 656C662E 715 00000234 0D0A00 db 0Dh, 0Ah, 0 716 717 ccf_err_msg: 718 00000237 0D0A db 0Dh, 0Ah 719 00000239 63703A2063616E6E6F- db 'cp: cannot create ' 719 00000242 742063726561746520 720 0000024B 00 db 0 721 722 crd_err_msg: 723 0000024C 0D0A db 0Dh, 0Ah 724 0000024E 63703A207265616420- db 'cp: read error.' 724 00000257 6572726F722E 725 0000025D 0D0A00 db 0Dh, 0Ah, 0 726 727 cwr_err_msg: 728 00000260 0D0A db 0Dh, 0Ah 729 00000262 63703A207772697465- db 'cp: write error.' 729 0000026B 206572726F722E 730 00000272 0D0A00 db 0Dh, 0Ah, 0 731 732 ok_msg: 733 00000275 0D0A db 0Dh, 0Ah 734 00000277 4F4B2E db 'OK.' 735 0000027A 0D0A00 db 0Dh, 0Ah, 0 736 737 0000027D 00 errors: db 0 738 739 ;----------------------------------------------------------------- 740 ; bss - uninitialized data 741 ;----------------------------------------------------------------- 742 743 align 2 744 745 bss_start: 746 747 ABSOLUTE bss_start 748 749 ; 20/04/2022 - Retro UNIX 386 v1 & v1.1 & v1.2 750 ;fold: resd 1 751 ;fnew: resd 1 752 ; 22/04/2022 - Retro UNIX 8086 v1 753 0000027E ???? fold: resw 1 754 00000280 ???? fnew: resw 1 755 756 ;stbuf2: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data) 757 ;stbuf1: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data) 758 ; 21/04/2022 759 00000282 stbuf2: resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data) 760 000002A4 stbuf1: resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data) 761 ; 10/05/2022 762 000002C6 ???? idev1: resw 1 ; device number (0= root, >0 or 1 = mounted) 763 ;idev2: resw 1 ; device number (0= root, >0 or 1 = mounted) 764 765 000002C8 iobuf: resb BSIZE ; resb 512 ; path name buffer 766 767 ; 20/04/2022 768 ;----------------------------------------------------------------- 769 ; Original UNIX v7 - cp (utility) c source code (cp.c) 770 ;----------------------------------------------------------------- 771 ;/* UNIX V7 source code: see www.tuhs.org for details. */; 772 ; 773 ;/* 774 ; * cp oldfile newfile 775 ; */ 776 ; 777 ;#define BSIZE 512 778 ;#include 779 ;#include 780 ;#include 781 ;struct stat stbuf1, stbuf2; 782 ;char iobuf[BSIZE]; 783 ; 784 ;main(argc, argv) 785 ;char *argv[]; 786 ;{ 787 ; register i, r; 788 ; 789 ; if (argc < 3) 790 ; goto usage; 791 ; if (argc > 3) { 792 ; if (stat(argv[argc-1], &stbuf2) < 0) 793 ; goto usage; 794 ; if ((stbuf2.st_mode&S_IFMT) != S_IFDIR) 795 ; goto usage; 796 ; } 797 ; r = 0; 798 ; for(i=1; i=0 && 820 ; (stbuf2.st_mode&S_IFMT) == S_IFDIR) { 821 ; p1 = from; 822 ; p2 = to; 823 ; bp = iobuf; 824 ; while(*bp++ = *p2++) 825 ; ; 826 ; bp[-1] = '/'; 827 ; p2 = bp; 828 ; while(*bp = *p1++) 829 ; if (*bp++ == '/') 830 ; bp = p2; 831 ; to = iobuf; 832 ; } 833 ; if (stat(to, &stbuf2) >= 0) { 834 ; if (stbuf1.st_dev == stbuf2.st_dev && 835 ; stbuf1.st_ino == stbuf2.st_ino) { 836 ; fprintf(stderr, "cp: cannot copy file to itself.\n"); 837 ; return(1); 838 ; } 839 ; } 840 ; if ((fnew = creat(to, mode)) < 0) { 841 ; fprintf(stderr, "cp: cannot create %s\n", to); 842 ; close(fold); 843 ; return(1); 844 ; } 845 ; while(n = read(fold, iobuf, BSIZE)) { 846 ; if (n < 0) { 847 ; fprintf(stderr, "cp: read error\n"); 848 ; close(fold); 849 ; close(fnew); 850 ; return(1); 851 ; } else 852 ; if (write(fnew, iobuf, n) != n) { 853 ; fprintf(stderr, "cp: write error.\n"); 854 ; close(fold); 855 ; close(fnew); 856 ; return(1); 857 ; } 858 ; } 859 ; close(fold); 860 ; close(fnew); 861 ; return(0); 862 ;}