1 ; **************************************************************************** 2 ; mv8086.s (mv0.s) - by Erdogan Tan - 22/05/2022 3 ; ---------------------------------------------------------------------------- 4 ; Retro UNIX 8086 v1 - mv -- move (or rename) file (or directory) 5 ; 6 ; [ Last Modification: 27/05/2022 ] 7 ; 8 ; Derived from (original) UNIX v7 'mv.c' source Code 9 ; Ref: 10 ; www.tuhs.org (https://minnie.tuhs.org) 11 ; **************************************************************************** 12 ; [ v7.tar.gz - usr/src/cmd/mv.c (archive date: 10-01-1979) ] 13 ; 14 ; Assembler: NASM v2.15 15 ; ((nasm mv0.s -l mv0.txt -o mv0 -Z error.txt)) 16 17 ; mv2.s - 27/05/2022 - Retro UNIX 386 v1.2 & v2 18 ; mv1.s - 27/05/2022 - Retro UNIX 386 v1 & v1.1 19 ; mv0.s - 27/05/2022 - Retro UNIX 8086 v1 (16 bit 'mv1.s') 20 21 ; 12/01/2022 (Retro UNIX 386 v1.2) 22 ; 13/10/2015 23 24 ; UNIX v1 system calls 25 _rele equ 0 26 _exit equ 1 27 _fork equ 2 28 _read equ 3 29 _write equ 4 30 _open equ 5 31 _close equ 6 32 _wait equ 7 33 _creat equ 8 34 _link equ 9 35 _unlink equ 10 36 _exec equ 11 37 _chdir equ 12 38 _time equ 13 39 _mkdir equ 14 40 _chmod equ 15 41 _chown equ 16 42 _break equ 17 43 _stat equ 18 44 _seek equ 19 45 _tell equ 20 46 _mount equ 21 47 _umount equ 22 48 _setuid equ 23 49 _getuid equ 24 50 _stime equ 25 51 _quit equ 26 52 _intr equ 27 53 _fstat equ 28 54 _emt equ 29 55 _mdate equ 30 56 _stty equ 31 57 _gtty equ 32 58 _ilgins equ 33 59 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 60 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 61 _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 62 ; 12/01/2022 - Retro UNIX 386 v1.2 63 ; Retro UNIX 386 v2 system calls 64 _setgid equ 37 65 _getgid equ 38 66 _sysver equ 39 ; (get) Retro Unix 386 version 67 68 ;;; 69 ESCKey equ 1Bh 70 EnterKey equ 0Dh 71 72 ;%macro sys 1-4 73 ; ; 03/09/2015 74 ; ; 13/04/2015 75 ; ; Retro UNIX 386 v1 system call. 76 ; %if %0 >= 2 77 ; mov ebx, %2 78 ; %if %0 >= 3 79 ; mov ecx, %3 80 ; ;%if %0 = 4 81 ; %if %0 >= 4 ; 11/03/2022 82 ; mov edx, %4 83 ; %endif 84 ; %endif 85 ; %endif 86 ; mov eax, %1 87 ; int 30h 88 ;%endmacro 89 90 %macro sys 1-4 91 ; Retro UNIX 8086 v1 system call. 92 %if %0 >= 2 93 mov bx, %2 94 %if %0 >= 3 95 mov cx, %3 96 %if %0 >= 4 97 mov dx, %4 98 %endif 99 %endif 100 %endif 101 mov ax, %1 102 int 20h 103 %endmacro 104 105 ;; Retro UNIX 386 v1 system call format: 106 ;; sys systemcall (eax) , , 107 108 ;; 11/03/2022 109 ;; Note: Above 'sys' macro has limitation about register positions; 110 ;; ebx, ecx, edx registers must not be used after their 111 ;; positions in sys macro. 112 ;; for example: 113 ;; 'sys _write, 1, msg, ecx' is defective, because 114 ;; ecx will be used/assigned before edx in 'sys' macro. 115 ;; correct order may be: 116 ;; 'sys _write, 1, msg, eax ; (eax = byte count) 117 118 ; Retro UNIX 8086 v1 system call format: 119 ; sys systemcall (ax) , , 120 121 struc stat 122 ; Note: This is for Retro UNIX v1 'sysstat' output !!! 123 ; (34 bytes) 124 00000000 ???? .inode: resw 1 125 00000002 ???? .mode: resw 1 126 00000004 ?? .nlinks: resb 1 127 00000005 ?? .uid: resb 1 128 00000006 ???? .size: resw 1 129 00000008 .dskptr: resw 8 130 00000018 ???????? .ctime: resd 1 131 0000001C ???????? .mtime: resd 1 132 00000020 ???? .rsvd: resw 1 133 .strucsize: 134 endstruc 135 136 ;struc stat 137 ; ; Note: This is for Retro UNIX v1.2 'sysstat' output !!! 138 ; ; (66 bytes) 139 ; .inode: resw 1 140 ; .mode: resw 1 141 ; .nlinks: resw 1 142 ; .uid: resw 1 143 ; .gid: resb 1 144 ; .size_h: resb 1 145 ; .size: resd 1 146 ; .dskptr: resd 10 147 ; .atime: resd 1 148 ; .mtime: resd 1 149 ; .ctime: resd 1 150 ; .strucsize: 151 ;endstruc 152 153 ;;struc stat 154 ;; ; Note: Retro UNIX v2 'sysstat' output DRAFT !!! 155 ;; ; (72 bytes) 156 ;; .idev: resb 1 157 ;; .rsvd: resb 3 158 ;; .inum: resd 1 159 ;; .mode: resw 1 160 ;; .nlinks: resw 1 161 ;; .uid: resw 1 162 ;; .gid: resb 1 163 ;; .size_h: resb 1 164 ;; .size: resd 1 165 ;; .dskptr: resd 10 166 ;; .atime: resd 1 167 ;; .mtime: resd 1 168 ;; .ctime: resd 1 169 ;; .strucsize: 170 ;;endstruc 171 172 ;S_IFMT equ 0F000h ; /* type of file */ 173 ;S_IFDIR equ 04000h ; /* directory */ 174 ;S_IFCHR equ 02000h ; /* character special */ 175 ;S_IFBLK equ 06000h ; /* block special */ 176 ;S_IFREG equ 08000h ; /* regular */ 177 ;S_ISUID equ 00800h ; /* set user id on execution */ 178 ;S_ISGID equ 00400h ; /* set group id on execution */ 179 ;S_IREAD equ 00100h ; /* read permission, owner */ 180 ;S_IWRITE equ 00080h ; /* write permission, owner */ 181 ;S_IEXEC equ 00040h ; /* execute/search permission, owner */ 182 183 S_IFMT equ 0F0h ; /* type of file */ 184 S_IFDIR equ 040h ; /* directory */ 185 S_IFCHR equ 020h ; /* character special */ 186 S_IFBLK equ 060h ; /* block special */ 187 S_IFREG equ 080h ; /* regular */ 188 S_ISUID equ 008h ; /* set user id on execution */ 189 S_ISGID equ 004h ; /* set group id on execution */ 190 S_IREAD equ 001h ; /* read permission, owner */ 191 S_IWRITE equ 080h ; /* write permission, owner */ 192 S_IEXEC equ 040h ; /* execute/search permission, owner */ 193 194 ;; UNIX v1 inode 195 ;; byte 1 196 ;S_ALLOC equ 080h ; Allocated flag 197 ;S_IFDIR equ 040h ; Directory flag 198 ;S_IFMDF equ 020h ; File modified flag (always on) 199 ;S_IFLRG equ 010h ; Large File flag 200 ;; byte 0 201 ;S_ISUID equ 020h ; Set User ID On Execution flag 202 ;S_IEXEC equ 010h ; Executable File flag 203 ;S_IREAD equ 008h ; Owner's Read Permission flag 204 ;S_IWRITE equ 004h ; Owner's Write Permission flag 205 206 ;%define DOT "." 207 ;%define DOTDOT ".." 208 %define DELIM '/' 209 ;%define SDELIM "/" 210 MODEBITS equ 11111b ; Retro UNIX v1 211 ;MODEBITS equ 111111111b ; Retro UNIX v1.2 (v2) 212 ROOTINO equ 41 ; Retro UNIX v1 213 ;ROOTINO equ 1 ; Retro UNIX v1.2 (v2) 214 215 STDIN equ 0 216 ; 23/05/2022 217 MAXN equ 112 218 219 ;----------------------------------------------------------------- 220 ; text - code 221 ;----------------------------------------------------------------- 222 223 [BITS 16] ; 16-bit intructions (for 8086 real mode) 224 225 [ORG 0] 226 227 START_CODE: 228 ; 27/05/2022 229 ; (32 bit to 16 bit conversions for Retro UNIX 8086 v1) 230 ; 27/05/2022 231 ; 26/05/2022 232 ; 24/05/2022 233 ; 23/05/2022 234 ; 22/05/2022 235 00000000 58 pop ax ; number of arguments 236 00000001 5A pop dx ; argv[0] ýgg 237 ;mov [argc], ax 238 00000002 A2[4B06] mov [argc], al 239 240 ;cmp ax, 3 241 00000005 3C03 cmp al, 3 242 00000007 730F jnb short mv_0 243 00000009 FEC8 dec al 244 0000000B 7506 jnz short mv_usage 245 ;sys _msg, program_msg, 255, 0Fh 246 ; 27/05/2022 (Retro UNIX 8086 v1) 247 0000000D B8[6006] mov ax, program_msg 248 00000010 E82006 call print_msg 249 mv_usage: 250 ;sys _msg, usage_msg, 255, 07h 251 00000013 B8[9806] mov ax, usage_msg 252 ;call print_msg 253 00000016 EB1B jmp print_exit ; 24/05/2022 254 ;mv_exit: 255 ; sys _exit ; sys exit 256 ;;hlt: 257 ;; nop 258 ;; nop 259 ;; jmp short hlt 260 261 mv_0: 262 00000018 5F pop di ; argv[1] 263 264 ; 26/05/2022 265 sys _stat, di, st1buf 91 <1> 92 <1> %if %0 >= 2 93 00000019 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 0000001B B9[1009] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000001E B81200 <1> mov ax, %1 102 00000021 CD20 <1> int 20h 266 00000023 731E jnc short mv_1 267 268 00000025 B8[FA06] mov ax, msg_cant_access 269 ; 24/05/2022 270 00000028 E80806 call print_msg 271 0000002B 89F8 mov ax, di ; argv[1] 272 0000002D E80306 call print_msg 273 00000030 B8[CA06] mov ax, nextline 274 print_exit: 275 00000033 E8FD05 call print_msg 276 _exit_: 277 sys _exit 91 <1> 92 <1> %if %0 >= 2 93 <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000036 B80100 <1> mov ax, %1 102 00000039 CD20 <1> int 20h 278 279 hang_em_high: 280 0000003B 90 nop 281 0000003C EBFD jmp short hang_em_high 282 283 mv_61: 284 0000003E B8[0109] mov ax, msg_ok 285 00000041 EBF0 jmp short print_exit 286 287 mv_1: 288 ; Retro UNIX 386 v1.2 289 ;mov [st1dev], eax 290 ;mov al, byte [st1buf+stat.mode+1] 291 ;and al, S_IFREG|S_IFDIR 292 ;cmp al, S_IFREG|S_IFDIR 293 ;jne short mv_2 294 295 ; Retro UNIX 386 v1 296 ;mov [st1dev], ax ; device number 297 ; (0 = root fs) 298 ; (1 = mounted fs) 299 00000043 F606[1309]40 test byte [st1buf+stat.mode+1], S_IFDIR 300 00000048 740F jz short mv_2 301 302 0000004A 803E[4B06]03 cmp byte [argc], 3 303 0000004F 75C2 jne short mv_usage 304 305 00000051 5D pop bp ; argv[2] 306 307 00000052 E8F001 call mvdir 308 00000055 73E7 jnc short mv_61 ; "OK." 309 00000057 EBDD jmp short _exit_ 310 311 mv_2: 312 ;setuid(getuid()); 313 sys _getuid 91 <1> 92 <1> %if %0 >= 2 93 <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000059 B81800 <1> mov ax, %1 102 0000005C CD20 <1> int 20h 314 sys _setuid, ax 91 <1> 92 <1> %if %0 >= 2 93 0000005E 89C3 <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000060 B81700 <1> mov ax, %1 102 00000063 CD20 <1> int 20h 315 00000065 7305 jnc short mv_3 316 317 ; error (permission denied) 318 00000067 B8[F508] mov ax, err_msg 319 0000006A EBC7 jmp short print_exit 320 mv_3: 321 ; (here [sp] = argv[2]) 322 0000006C A0[4B06] mov al, [argc] 323 ;dec al ; (if [argc] = 3 then al = 2) 324 ;mov cl, 2 325 ;sub al, cl ; argv[0], argv[1] 326 0000006F 2C03 sub al, 3 327 00000071 D1E0 shl ax, 1 ; * 2 328 00000073 89E5 mov bp, sp 329 00000075 01C5 add bp, ax 330 ; bp = argv[argc-1] 331 ;mov [target], bp 332 333 ; 26/05/2022 334 00000077 8B6E00 mov bp, [bp] 335 336 ; 24/05/2022 337 ;cmp byte [argc], 3 338 0000007A 802E[4B06]02 sub byte [argc], 2 339 0000007F 803E[4B06]01 cmp byte [argc], 1 340 00000084 7616 jna short mv_6 341 342 ; (target must a -valid- directory) 343 344 sys _stat, bp, st2buf 91 <1> 92 <1> %if %0 >= 2 93 00000086 89EB <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000088 B9[3409] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000008B B81200 <1> mov ax, %1 102 0000008E CD20 <1> int 20h 345 00000090 7303 jnc short mv_5 346 mv_4: 347 00000092 E97EFF jmp mv_usage 348 mv_5: 349 ; Retro UNIX 386 v1.2 350 ;mov [st2dev], eax 351 ;mov al, byte [st2buf+stat.mode+1] 352 ;and al, S_IFREG|S_IFDIR 353 ;cmp al, S_IFREG|S_IFDIR 354 ;jne short mv_4 355 356 ; Retro UNIX 386 v1 357 ;mov [st2dev], ax ; device number 358 ; (0 = root fs) 359 ; (1 = mounted fs) 360 00000095 F606[3709]40 test byte [st2buf+stat.mode+1], S_IFDIR 361 0000009A 74F6 jz short mv_4 362 363 ; 26/05/2022 364 ;sub byte [argc], 2 ; [argc] >= 1 365 ; ; i = 1 366 mv_6: 367 ; di = argv[i] 368 ; bp = argv[argc-1] 369 0000009C E81F00 call move 370 0000009F 7304 jnc short mv_7 371 000000A1 FE06[4C06] inc byte [errors] 372 mv_7: 373 000000A5 FE0E[4B06] dec byte [argc] ; i++ 374 000000A9 7403 jz short mv_8 375 ; i < argc-1 376 000000AB 5F pop di ; argv[i] 377 000000AC EBEE jmp short mv_6 378 mv_8: 379 000000AE 803E[4C06]00 cmp byte [errors], 0 380 000000B3 7706 ja short mv_9 381 382 000000B5 B8[0109] mov ax, msg_ok 383 ;jmp print_exit 384 000000B8 E87805 call print_msg 385 mv_9: 386 000000BB E978FF jmp _exit_ 387 388 ;----------------------------------------------------------------- 389 390 move: 391 ; 27/05/2022 392 ; 26/05/2022 393 ; 24/05/2022 394 ; 22/05/2022 395 396 ; move(source, target) 397 398 ; INPUT: 399 ; di = source 400 ; bp = target 401 ; OUTPUT: 402 ; cf = 0 -> ok 403 ; cf = 1 -> error 404 405 ; if (stat(source, &s1) < 0) 406 sys _stat, di, st1buf 91 <1> 92 <1> %if %0 >= 2 93 000000BE 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 000000C0 B9[1009] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000000C3 B81200 <1> mov ax, %1 102 000000C6 CD20 <1> int 20h 407 000000C8 7313 jnc short mv_10 408 409 000000CA B8[FA06] mov ax, msg_cant_access 410 ; 24/05/2022 411 000000CD E86305 call print_msg 412 000000D0 89F8 mov ax, di ; source 413 000000D2 E85E05 call print_msg 414 000000D5 B8[CA06] mov ax, nextline 415 move_err: 416 000000D8 E85805 call print_msg 417 000000DB F9 stc 418 000000DC C3 retn 419 mv_10: 420 ; Retro UNIX 386 v1.2 421 ;mov [st1dev], eax 422 ;mov al, byte [st1buf+stat.mode+1] 423 ;and al, S_IFREG|S_IFDIR 424 ;cmp al, S_IFREG|S_IFDIR 425 ;jne short mv_11 426 427 ; Retro UNIX 386 v1 (& v1.1) 428 000000DD A3[0E09] mov [st1dev], ax ; device number 429 ; (0 = root fs) 430 ; (1 = mounted fs) 431 432 ; if ((s1.st_mode & S_IFMT) == S_IFDIR) 433 000000E0 F606[1309]40 test byte [st1buf+stat.mode+1], S_IFDIR 434 000000E5 7405 jz short mv_11 435 436 000000E7 B8[0F07] mov ax, msg_rename_only 437 000000EA EBEC jmp short move_err 438 mv_11: 439 ; 26/05/2022 440 000000EC 892E[0C09] mov [target], bp 441 442 ; if (stat(target, &s2) >= 0) 443 sys _stat, bp, st2buf 91 <1> 92 <1> %if %0 >= 2 93 000000F0 89EB <1> mov bx, %2 94 <1> %if %0 >= 3 95 000000F2 B9[3409] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000000F5 B81200 <1> mov ax, %1 102 000000F8 CD20 <1> int 20h 444 ;jc short mv_19 445 ; 23/05/2022 446 000000FA 7303 jnc short mv_12 447 000000FC E9CF00 jmp mv_19 448 mv_12: 449 ; Retro UNIX 386 v1.2 450 ;mov [st2dev], eax 451 ;mov al, byte [st2buf+stat.mode+1] 452 ;and al, S_IFREG|S_IFDIR 453 ;cmp al, S_IFREG|S_IFDIR 454 ;jne short mv_14 455 456 ; Retro UNIX 386 v1 (& v1.1) 457 000000FF A3[3209] mov [st2dev], ax ; device number 458 ; (0 = root fs) 459 ; (1 = mounted fs) 460 461 ; if ((s2.st_mode & S_IFMT) == S_IFDIR) 462 00000102 F606[3709]40 test byte [st2buf+stat.mode+1], S_IFDIR 463 00000107 742E jz short mv_14 464 465 ; sprintf(buf, "%s/%s", target, dname(source)); 466 467 ; mov si, bp ; target 468 ; mov bx, di ; source 469 ; mov dx, bx ; source 470 ; mov di, buf ; pathname buffer (100 bytes) 471 ; mov [target], di 472 ;mv_12: 473 ; lodsb 474 ; or al, al 475 ; jz short mv_13 476 ; stosb 477 ; jmp short mv_12 478 ; 479 ;mv_13: 480 ; mov al, DELIM ; '/' 481 ; stosb 482 ; 483 ; ; dx = source (pathname) 484 ; ; di = buffer (offset) position 485 ; call dname 486 ; mov di, bx ; source 487 ; ; target = buf; 488 ; 22/05/2022 489 00000109 E87A03 call strcpy ; 27/05/2022 490 491 ;if (stat(target, &s2) >= 0) 492 493 sys _stat, buf, st2buf 91 <1> 92 <1> %if %0 >= 2 93 0000010C BB[5609] <1> mov bx, %2 94 <1> %if %0 >= 3 95 0000010F B9[3409] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000112 B81200 <1> mov ax, %1 102 00000115 CD20 <1> int 20h 494 ;jc short mv_20 ; 26/05/2022 495 ; 26/05/2022 496 00000117 7303 jnc short mv_13 497 00000119 E9B200 jmp mv_20 498 mv_13: 499 ; Retro UNIX 386 v1.2 500 ;mov [st2dev], eax 501 ;mov al, byte [st2buf+stat.mode+1] 502 ;and al, S_IFREG|S_IFDIR 503 ;cmp al, S_IFREG|S_IFDIR 504 ;jne short mv_14 505 506 ; Retro UNIX 386 v1 (& v1.1) 507 0000011C A3[3209] mov [st2dev], ax ; device number 508 ; (0 = root fs) 509 ; (1 = mounted fs) 510 511 ; if ((s2.st_mode & S_IFMT) == S_IFDIR) 512 0000011F F606[3709]40 test byte [st2buf+stat.mode+1], S_IFDIR 513 00000124 7411 jz short mv_14 514 515 ;fprintf(stderr, "mv: %s is a directory\n", target); 516 00000126 B8[CD06] mov ax, mv_header 517 00000129 E80705 call print_msg 518 0000012C B8[5609] mov ax, buf ; target 519 0000012F E80105 call print_msg 520 00000132 B8[E706] mov ax, msg_is_a_dir 521 00000135 EBA1 jmp move_err 522 523 mv_14: 524 ; if (s1.st_dev==s2.st_dev && s1.st_ino==s2.st_ino) 525 00000137 A1[1009] mov ax, [st1buf+stat.inode] 526 0000013A 3B06[3409] cmp ax, [st2buf+stat.inode] 527 0000013E 7526 jne short mv_15 528 ; 26/05/2022 529 00000140 A1[0E09] mov ax, [st1dev] 530 00000143 3B06[3209] cmp ax, [st2dev] 531 00000147 751D jne short mv_15 532 533 ;fprintf(stderr, "mv: %s and %s are identical\n", 534 ; source, target); 535 536 ; di = source 537 ; (buf = target or) [target] = target 538 539 00000149 B8[CD06] mov ax, mv_header 540 0000014C E8E404 call print_msg 541 0000014F 89F8 mov ax, di ; source 542 00000151 E8DF04 call print_msg 543 00000154 B8[7E08] mov ax, msg_and 544 00000157 E8D904 call print_msg 545 0000015A A1[0C09] mov ax, [target] ; target ; 26/05/2022 546 0000015D E8D304 call print_msg 547 00000160 B8[8408] mov ax, msg_identical 548 00000163 E972FF jmp move_err 549 550 mv_15: 551 ; if (access(target, 2) < 0 && isatty(fileno(stdin))) 552 00000166 BE[3409] mov si, st2buf 553 00000169 E83304 call access 554 0000016C 7544 jnz short mv_18 555 ; not permitted 556 557 0000016E E84404 call isatty 558 00000171 723F jc short mv_18 ; not a tty 559 560 ;fprintf(stderr, "mv: %s: %o mode ", target, 561 ; s2.st_mode & MODEBITS); 562 563 00000173 B8[CD06] mov ax, mv_header 564 00000176 E8BA04 call print_msg 565 00000179 A1[0C09] mov ax, [target] ; target ; 26/05/2022 566 0000017C E8B404 call print_msg 567 0000017F 8B1E[3609] mov bx, [st2buf+stat.mode] 568 00000183 83E31F and bx, MODEBITS 569 00000186 BE[F90A] mov si, octm 570 00000189 E84704 call octalnumber 571 ; 27/05/2022 572 ;mov ax, octm 573 0000018C C606[F80A]20 mov byte [octms], 20h 574 00000191 B8[F80A] mov ax, octms 575 00000194 E89C04 call print_msg 576 00000197 B8[D708] mov ax, msg_mode 577 0000019A E89604 call print_msg 578 579 ; i = c = getchar(); 580 0000019D E86604 call getchar 581 582 000001A0 3C79 cmp al, 'y' 583 000001A2 7408 je short mv_17 584 585 000001A4 B8[EE08] mov ax, msg_no 586 mv_16: 587 000001A7 E88904 call print_msg 588 000001AA F9 stc 589 000001AB C3 retn 590 mv_17: 591 000001AC B8[E608] mov ax, msg_yes 592 000001AF E88104 call print_msg 593 mv_18: 594 ; if (unlink(target) < 0) 595 sys _unlink, [target] ; 26/05/2022 91 <1> 92 <1> %if %0 >= 2 93 000001B2 8B1E[0C09] <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000001B6 B80A00 <1> mov ax, %1 102 000001B9 CD20 <1> int 20h 596 000001BB 7311 jnc short mv_20 597 598 ; fprintf(stderr, "mv: cannot unlink %s\n", target); 599 000001BD B8[2D07] mov ax, msg_cant_unlink 600 000001C0 E87004 call print_msg 601 000001C3 A1[0C09] mov ax, [target] ; 26/05/2022 602 000001C6 E86A04 call print_msg 603 000001C9 B8[CA06] mov ax, nextline 604 000001CC EBD9 jmp short mv_16 605 mv_19: 606 ; 26/05/2022 607 ;mov [target], bp ; target 608 mv_20: 609 ; if (link(source, target) < 0) 610 611 sys _link, di, [target] 91 <1> 92 <1> %if %0 >= 2 93 000001CE 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 000001D0 8B0E[0C09] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000001D4 B80900 <1> mov ax, %1 102 000001D7 CD20 <1> int 20h 612 000001D9 7350 jnc short mv_25 613 614 000001DB BB[EA01] mov bx, mv_21 ; child process jump address 615 sys _fork 91 <1> 92 <1> %if %0 >= 2 93 <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000001DE B80200 <1> mov ax, %1 102 000001E1 CD20 <1> int 20h 616 000001E3 7320 jnc short mv_22 ; parent return and jump 617 618 000001E5 B8[4207] mov ax, msg_try_again 619 000001E8 EBBD jmp short mv_16 620 mv_21: 621 ; child process will continue from here 622 623 000001EA A1[0C09] mov ax, [target] 624 000001ED A3[5906] mov [cp_target], ax 625 000001F0 893E[5706] mov [cp_source], di 626 627 sys _exec, cp_cmd, cp_args 91 <1> 92 <1> %if %0 >= 2 93 000001F4 BB[4D06] <1> mov bx, %2 94 <1> %if %0 >= 3 95 000001F7 B9[5506] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000001FA B80B00 <1> mov ax, %1 102 000001FD CD20 <1> int 20h 628 629 ; fprintf(stderr, "mv: cannot exec cp\n"); 630 000001FF B8[5407] mov ax, msg_cant_exec_cp 631 ;call print_msg 632 ;jmp _exit_ 633 ; 23/05/2022 634 00000202 E92EFE jmp print_exit 635 636 mv_22: 637 00000205 89C2 mov dx, ax ; child process id 638 mv_23: 639 ; while ((c = wait(&status)) != i && c != -1) 640 ;if (status != 0) 641 ; return(1); 642 ; utime(target, &s1.st_atime); 643 644 sys _wait 91 <1> 92 <1> %if %0 >= 2 93 <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000207 B80700 <1> mov ax, %1 102 0000020A CD20 <1> int 20h 645 0000020C 721C jc short mv_24 646 647 0000020E 39D0 cmp ax, dx 648 00000210 75F5 jne short mv_23 649 650 ; 26/05/2022 (check if /bin/cp has been failed) 651 sys _stat, [target], fstbuf 91 <1> 92 <1> %if %0 >= 2 93 00000212 8B1E[0C09] <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000216 B9[720A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000219 B81200 <1> mov ax, %1 102 0000021C CD20 <1> int 20h 652 0000021E 720A jc short mv_24 653 00000220 A1[780A] mov ax, [fstbuf+stat.size] 654 00000223 3B06[1609] cmp ax, [st1buf+stat.size] 655 00000227 7402 je short mv_25 656 00000229 F9 stc 657 mv_24: 658 0000022A C3 retn 659 660 ; utime(target, &s1.st_atime); 661 662 ;;; 663 mv_25: 664 ;if (unlink(source) < 0) { 665 ; fprintf(stderr, "mv: cannot unlink %s\n", source); 666 ; return(1); 667 ;} 668 669 sys _unlink, di 91 <1> 92 <1> %if %0 >= 2 93 0000022B 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000022D B80A00 <1> mov ax, %1 102 00000230 CD20 <1> int 20h 670 00000232 73F6 jnc short mv_24 671 672 00000234 B8[2D07] mov ax, msg_cant_unlink 673 00000237 E8F903 call print_msg 674 0000023A 89F8 mov ax, di ; source 675 0000023C E8F403 call print_msg 676 0000023F B8[CA06] mov ax, nextline 677 ;if (status != 0) 678 ; return(1); 679 00000242 E962FF jmp mv_16 680 681 ;----------------------------------------------------------------- 682 683 mvdir: 684 ; 27/05/2022 685 ; 26/05/2022 686 ; 23/05/2022 687 ; 22/05/2022 688 689 ; mvdir(source, target) 690 691 ; INPUT: 692 ; di = source 693 ; bp = target 694 ; OUTPUT: 695 ; cf = 0 -> ok 696 ; cf = 1 -> error 697 698 ; st1buf = source (inode) stat(us) buffer 699 700 ;if (stat(target, &s2) >= 0) 701 sys _stat, bp, st2buf 91 <1> 92 <1> %if %0 >= 2 93 00000245 89EB <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000247 B9[3409] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000024A B81200 <1> mov ax, %1 102 0000024D CD20 <1> int 20h 702 0000024F 722D jc short mv_29 703 704 ;if ((s2.st_mode&S_IFMT) != S_IFDIR) 705 706 ; Retro UNIX 386 v1.2 707 ;mov [st2dev], eax 708 ;mov al, byte [st2buf+stat.mode+1] 709 ;and al, S_IFREG|S_IFDIR 710 ;cmp al, S_IFREG|S_IFDIR 711 ;je short mv_28 712 713 ; Retro UNIX 386 v1 (& v1.1) 714 ;mov [st2dev], ax ; device number 715 ; (0 = root fs) 716 ; (1 = mounted fs) 717 718 ;if ((s2.st_mode & S_IFMT) == S_IFDIR) 719 00000251 F606[3709]40 test byte [st2buf+stat.mode+1], S_IFDIR 720 00000256 7513 jnz short mv_28 721 722 ;fprintf(stderr, "mv: %s exists\n", target); 723 724 00000258 55 push bp ; target 725 mv_27: 726 00000259 B8[CD06] mov ax, mv_header 727 0000025C E8D403 call print_msg 728 0000025F 58 pop ax ; target 729 00000260 E8D003 call print_msg 730 00000263 B8[6B07] mov ax, msg_exists 731 00000266 E8CA03 call print_msg 732 00000269 F9 stc 733 0000026A C3 retn 734 735 mv_28: 736 ;if (strlen(target) > MAXN-DIRSIZ-2) { 737 ; fprintf(stderr, "mv: target name too long\n"); 738 ; return(1); 739 ;} 740 741 ;strcpy(buf, target); 742 743 ; mov si, bp ; target 744 ; mov dx, di ; source 745 ; mov di, buf ; pathname buffer (100 bytes) 746 ; mov [target], di 747 ;mv_29: 748 ; lodsb 749 ; stosb 750 ; and al, al 751 ; jnz short mv_29 752 753 ;strcat(buf, SDELIM); 754 ;strcat(buf, dname(source)); 755 756 0000026B E81802 call strcpy ; 27/05/2022 757 758 sys _stat, buf, st2buf 91 <1> 92 <1> %if %0 >= 2 93 0000026E BB[5609] <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000271 B9[3409] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000274 B81200 <1> mov ax, %1 102 00000277 CD20 <1> int 20h 759 00000279 7207 jc short mv_30 760 761 0000027B 53 push bx ; buf ; [target] 762 0000027C EBDB jmp short mv_27 763 764 mv_29: 765 0000027E 892E[0C09] mov [target], bp 766 mv_30: 767 ; if (strcmp(source, target) == 0) { 768 769 00000282 57 push di 770 00000283 89FE mov si, di 771 00000285 8B3E[0C09] mov di, [target] 772 00000289 E82302 call strcmp 773 0000028C 5F pop di 774 0000028D 7508 jne short mv_32 775 776 0000028F B8[7607] mov ax, msg_src_target 777 mv_31: 778 00000292 E89E03 call print_msg 779 00000295 F9 stc 780 00000296 C3 retn 781 782 mv_32: 783 00000297 89FB mov bx, di 784 00000299 BF[720A] mov di, fstbuf ; (66 bytes buffer) 785 0000029C 53 push bx ; * 786 0000029D E81A02 call dname 787 ; bx = fstbuf = file name 788 789 ;!strcmp(p, "") 790 000002A0 803F00 cmp byte [bx], 0 791 000002A3 7419 je short mv_33 ; null 792 ;!strcmp(p, DOT) 793 000002A5 89DE mov si, bx 794 000002A7 803C2E cmp byte [si], '.' 795 000002AA 751E jne short mv_34 796 000002AC BF[5E06] mov di, DOT 797 000002AF E8FD01 call strcmp 798 000002B2 740A je short mv_33 ; '.' 799 ;!strcmp(p, DOTDOT) 800 000002B4 89DE mov si, bx 801 000002B6 BF[5D06] mov di, DOTDOT 802 000002B9 E8F301 call strcmp 803 000002BC 750C jne short mv_34 804 ; '..' 805 mv_33: 806 000002BE 5F pop di ; * 807 808 ;fprintf(stderr, "mv: cannot rename %s\n", p); 809 000002BF B8[5108] mov ax, msg_cant_rename 810 000002C2 E86E03 call print_msg 811 000002C5 B8[720A] mov ax, fstbuf 812 000002C8 EBC8 jmp short mv_31 813 814 mv_34: 815 000002CA 5F pop di ; * 816 000002CB BB[BA09] mov bx, sbuf 817 ; di = source 818 ; bx = buffer 819 000002CE E80602 call pname 820 ; si = parent directory name address 821 ; 822 ;if (stat(pname(source), &s1) < 0 || 823 sys _stat, si, pst1buf 91 <1> 92 <1> %if %0 >= 2 93 000002D1 89F3 <1> mov bx, %2 94 <1> %if %0 >= 3 95 000002D3 B9[B40A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000002D6 B81200 <1> mov ax, %1 102 000002D9 CD20 <1> int 20h 824 000002DB 7305 jnc short mv_36 825 mv_35: 826 000002DD B8[B307] mov ax, msg_cant_locate 827 000002E0 EBB0 jmp short mv_31 828 mv_36: 829 000002E2 A3[0E09] mov [st1dev], ax 830 000002E5 8B16[0C09] mov dx, [target] 831 000002E9 87D7 xchg dx, di 832 ;stat(pname(target), &s2) < 0) 833 ; di = source 834 000002EB BB[160A] mov bx, tbuf ; buffer 835 000002EE E8E601 call pname 836 ; si = parent directory name address 837 000002F1 89D7 mov di, dx 838 sys _stat, si, pst2buf 91 <1> 92 <1> %if %0 >= 2 93 000002F3 89F3 <1> mov bx, %2 94 <1> %if %0 >= 3 95 000002F5 B9[D60A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000002F8 B81200 <1> mov ax, %1 102 000002FB CD20 <1> int 20h 839 000002FD 72DE jc short mv_35 840 000002FF A3[3209] mov [st2dev], ax 841 ;if (access(pname(target), 2) < 0) 842 00000302 BE[D60A] mov si, pst2buf 843 00000305 E89702 call access 844 00000308 7516 jnz short mv_39 845 ; permission denied ! 846 0000030A BA[160A] mov dx, tbuf ; pname(target) 847 mv_37: 848 0000030D 52 push dx ; pname(target) or pname(source) 849 0000030E B8[D007] mov ax, msg_no_w_access 850 00000311 E81F03 call print_msg 851 00000314 58 pop ax ; pname(target) or pname(source) 852 00000315 E81B03 call print_msg 853 00000318 B8[CA06] mov ax, nextline 854 mv_38: 855 0000031B E81503 call print_msg 856 0000031E F9 stc 857 0000031F C3 retn 858 mv_39: 859 ;if (access(pname(source), 2) < 0) 860 00000320 BE[B40A] mov si, pst1buf 861 00000323 E87902 call access 862 00000326 7505 jnz short mv_40 863 ; permission denied ! 864 00000328 BA[BA09] mov dx, sbuf ; pname(source) 865 0000032B EBE0 jmp short mv_37 866 mv_40: 867 ;if (access(source, 2) < 0) 868 ; di = source 869 0000032D BE[1009] mov si, st1buf 870 ; source (inode) stat(us) buffer 871 00000330 E86C02 call access 872 00000333 7504 jnz short mv_41 873 00000335 89FA mov dx, di ; source 874 00000337 EBD4 jmp short mv_37 875 mv_41: 876 ;if (s1.st_dev != s2.st_dev) 877 00000339 A1[0E09] mov ax, [st1dev] 878 0000033C 3B06[3209] cmp ax, [st2dev] 879 00000340 7405 je short mv_42 880 ;fprintf(stderr, "mv: cannot move directories 881 ; across devices\n"); 882 00000342 B8[EA07] mov ax, msg_accross_devices 883 00000345 EBD4 jmp short mv_38 884 mv_42: 885 ;if (s1.st_ino != s2.st_ino) 886 00000347 A1[B40A] mov ax, [pst1buf+stat.inode] 887 0000034A 3B06[D60A] cmp ax, [pst2buf+stat.inode] 888 0000034E 7503 jne short mv_43 889 00000350 E9F400 jmp mv_57 890 mv_43: 891 ; (move dir from parent dir to another dir) 892 893 ;if (chkdot(source) || chkdot(target)) 894 00000353 89FB mov bx, di ; source 895 00000355 E81102 call chkdot 896 00000358 7305 jnc short mv_45 897 mv_44: 898 ;fprintf(stderr, "mv: Sorry, path names 899 ; including %s aren't allowed\n", DOTDOT); 900 0000035A B8[1908] mov ax, msg_pathname_dotdot 901 0000035D EBBC jmp short mv_38 902 mv_45: 903 0000035F 8B1E[0C09] mov bx, [target] ; target 904 00000363 E80302 call chkdot 905 00000366 72F2 jc short mv_44 906 mv_46: 907 ;stat(source, &s1); 908 ;if (check(pname(target), s1.st_ino)) 909 00000368 BB[160A] mov bx, tbuf 910 0000036B E89A01 call check 911 0000036E 722B jc short mv_49 ; return(1); 912 mv_47: 913 ;for (i = 1; i <= NSIG; i++) 914 ; signal(i, SIG_IGN); 915 ; if (link(source, target) < 0) { 916 917 sys _link, di, [target] 91 <1> 92 <1> %if %0 >= 2 93 00000370 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000372 8B0E[0C09] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000376 B80900 <1> mov ax, %1 102 00000379 CD20 <1> int 20h 918 0000037B 731F jnc short mv_50 919 920 ; fprintf(stderr, "mv: cannot link %s to %s\n", 921 ; target, source); 922 mv_48: 923 0000037D B8[6608] mov ax, msg_cant_link 924 00000380 E8B002 call print_msg 925 00000383 A1[0C09] mov ax, [target] ; target 926 00000386 E8AA02 call print_msg 927 00000389 B8[7908] mov ax, msg_to 928 0000038C E8A402 call print_msg 929 0000038F 89F8 mov ax, di ; source 930 00000391 E89F02 call print_msg 931 00000394 B8[CA06] mov ax, nextline 932 00000397 E89902 call print_msg 933 0000039A F9 stc 934 mv_49: 935 0000039B C3 retn 936 mv_50: 937 ;if (unlink(source) < 0) { 938 sys _unlink, di 91 <1> 92 <1> %if %0 >= 2 93 0000039C 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000039E B80A00 <1> mov ax, %1 102 000003A1 CD20 <1> int 20h 939 000003A3 731C jnc short mv_51 940 941 ;fprintf(stderr, "mv: %s: cannot unlink\n", source); 942 000003A5 B8[2D07] mov ax, msg_cant_unlink 943 000003A8 E88802 call print_msg 944 000003AB 89F8 mov ax, di ; source 945 000003AD E88302 call print_msg 946 000003B0 B8[CA06] mov ax, nextline 947 000003B3 E87D02 call print_msg 948 ;unlink(target); 949 sys _unlink, [target] 91 <1> 92 <1> %if %0 >= 2 93 000003B6 8B1E[0C09] <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000003BA B80A00 <1> mov ax, %1 102 000003BD CD20 <1> int 20h 950 ;return(1); 951 000003BF F9 stc 952 000003C0 C3 retn 953 mv_51: 954 ;strcat(dst, target); 955 ;strcat(dst, "/"); 956 ;strcat(dst, DOTDOT); 957 958 000003C1 8B36[0C09] mov si, [target] 959 000003C5 57 push di ; * 960 000003C6 BF[FE0A] mov di, nspth 961 mv_52: 962 000003C9 AC lodsb 963 000003CA AA stosb 964 000003CB 20C0 and al, al 965 000003CD 75FA jnz short mv_52 966 000003CF 4F dec di 967 ; 27/05/2022 968 000003D0 B82F2E mov ax, 2E2Fh ; db '/..', 0 969 000003D3 AB stosw 970 000003D4 B82E00 mov ax, 02Eh 971 000003D7 AB stosw 972 000003D8 5F pop di ; * 973 974 ;if (unlink(dst) < 0) 975 sys _unlink, nspth 91 <1> 92 <1> %if %0 >= 2 93 000003D9 BB[FE0A] <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000003DC B80A00 <1> mov ax, %1 102 000003DF CD20 <1> int 20h 976 000003E1 732A jnc short mv_56 977 978 ; fprintf(stderr, "mv: %s: cannot unlink\n", dst); 979 000003E3 B8[2D07] mov ax, msg_cant_unlink 980 000003E6 E84A02 call print_msg 981 000003E9 B8[FE0A] mov ax, nspth ; dst 982 000003EC E84402 call print_msg 983 000003EF B8[CA06] mov ax, nextline 984 000003F2 E83E02 call print_msg 985 mv_53: 986 ;if (link(target, source) >= 0) 987 ; unlink(target); 988 sys _link, di, [target] 91 <1> 92 <1> %if %0 >= 2 93 000003F5 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 000003F7 8B0E[0C09] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000003FB B80900 <1> mov ax, %1 102 000003FE CD20 <1> int 20h 989 00000400 720A jc short mv_55 990 mv_54: 991 ;unlink(target); 992 sys _unlink, [target] 91 <1> 92 <1> %if %0 >= 2 93 00000402 8B1E[0C09] <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000406 B80A00 <1> mov ax, %1 102 00000409 CD20 <1> int 20h 993 ;return(1); 994 0000040B F9 stc 995 mv_55: 996 0000040C C3 retn 997 mv_56: 998 ;if (link(pname(target), dst) < 0) 999 sys _link, tbuf, nspth 91 <1> 92 <1> %if %0 >= 2 93 0000040D BB[160A] <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000410 B9[FE0A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000413 B80900 <1> mov ax, %1 102 00000416 CD20 <1> int 20h 1000 00000418 73F2 jnc short mv_55 ;return(0) 1001 1002 ;fprintf(stderr, "mv: cannot link %s to %s\n", 1003 ; dst, pname(target)); 1004 0000041A B8[6608] mov ax, msg_cant_link 1005 0000041D E81302 call print_msg 1006 00000420 B8[FE0A] mov ax, nspth ; dst 1007 00000423 E80D02 call print_msg 1008 00000426 B8[7908] mov ax, msg_to 1009 00000429 E80702 call print_msg 1010 0000042C B8[160A] mov ax, tbuf ; pname(taget) 1011 0000042F E80102 call print_msg 1012 00000432 B8[CA06] mov ax, nextline 1013 00000435 E8FB01 call print_msg 1014 ;if (link(pname(source), dst) >= 0) 1015 sys _link, sbuf, nspth 91 <1> 92 <1> %if %0 >= 2 93 00000438 BB[BA09] <1> mov bx, %2 94 <1> %if %0 >= 3 95 0000043B B9[FE0A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000043E B80900 <1> mov ax, %1 102 00000441 CD20 <1> int 20h 1016 00000443 72C7 jc short mv_55 1017 ;if (link(target, source) >= 0) 1018 ; unlink(target); 1019 00000445 EBAE jmp short mv_53 1020 1021 mv_57: 1022 ; (move dir in same parent directory) 1023 1024 ;if (link(source, target) < 0) 1025 sys _link, di, [target] 91 <1> 92 <1> %if %0 >= 2 93 00000447 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000449 8B0E[0C09] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000044D B80900 <1> mov ax, %1 102 00000450 CD20 <1> int 20h 1026 00000452 731F jnc short mv_60 1027 ;fprintf(stderr, "mv: cannot link %s and %s\n", 1028 ; source, target); 1029 00000454 B8[6608] mov ax, msg_cant_link 1030 00000457 E8D901 call print_msg 1031 0000045A 89F8 mov ax, di ; source 1032 0000045C E8D401 call print_msg 1033 0000045F B8[7E08] mov ax, msg_and 1034 00000462 E8CE01 call print_msg 1035 00000465 A1[0C09] mov ax, [target] ; target 1036 mv_58: 1037 00000468 E8C801 call print_msg 1038 0000046B B8[CA06] mov ax, nextline 1039 0000046E E8C201 call print_msg 1040 ;return(1); 1041 00000471 F9 stc 1042 mv_59: 1043 00000472 C3 retn 1044 mv_60: 1045 ;if (unlink(source) < 0) { 1046 sys _unlink, di 91 <1> 92 <1> %if %0 >= 2 93 00000473 89FB <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000475 B80A00 <1> mov ax, %1 102 00000478 CD20 <1> int 20h 1047 0000047A 73F6 jnc short mv_59 ;return(0) 1048 1049 ;fprintf(stderr, "mv: ?? cannot unlink 1050 ; %s\n", source); 1051 1052 0000047C B8[2D07] mov ax, msg_cant_unlink 1053 0000047F E8B101 call print_msg 1054 00000482 89F8 mov ax, di ; source 1055 00000484 EBE2 jmp short mv_58 1056 1057 ;----------------------------------------------------------------- 1058 1059 strcpy: 1060 00000486 89EE mov si, bp ; target 1061 ; 27/05/2022 (bx -> cx, dx -> bx) 1062 00000488 89FB mov bx, di ; source 1063 0000048A 89D9 mov cx, bx 1064 0000048C BF[5609] mov di, buf ; pathname buffer (100 bytes) 1065 0000048F 893E[0C09] mov [target], di 1066 strcp_1: 1067 00000493 AC lodsb 1068 00000494 08C0 or al, al 1069 00000496 7403 jz short strcp_2 1070 00000498 AA stosb 1071 00000499 EBF8 jmp short strcp_1 1072 strcp_2: 1073 ; 27/05/2022 1074 0000049B B02F mov al, DELIM ; '/' 1075 0000049D 81FF[5609] cmp di, buf 1076 000004A1 7605 jna short strcp_3 1077 ;cmp byte [di-1], DELIM ; '/' 1078 000004A3 3845FF cmp byte [di-1], al ; '/' 1079 000004A6 7401 je short strcp_4 1080 strcp_3: 1081 ;mov al, DELIM ; '/' 1082 000004A8 AA stosb 1083 strcp_4: 1084 ; bx = source (pathname) 1085 ; di = buffer (offset) position 1086 000004A9 E80E00 call dname 1087 000004AC 89CF mov di, cx ; source 1088 ; target = buf; 1089 000004AE C3 retn 1090 1091 ;----------------------------------------------------------------- 1092 1093 strcmp: 1094 ; si = source 1095 ; di = target 1096 strcmp_1: 1097 000004AF AC lodsb 1098 000004B0 08C0 or al, al 1099 000004B2 7404 jz short strcmp_2 1100 000004B4 AE scasb 1101 000004B5 74F8 je short strcmp_1 1102 000004B7 C3 retn 1103 strcmp_2: 1104 ;cmp [di], al ; 0 1105 000004B8 AE scasb 1106 strcmp_3: 1107 ; zf = 1 -> same 1108 000004B9 C3 retn 1109 1110 ;----------------------------------------------------------------- 1111 1112 dname: ; dname(name) 1113 ; 27/05/2022 (dx -> bx) 1114 ; bx = source (pathname) 1115 ; di = buffer (offset) position 1116 dname_0: 1117 000004BA 89DE mov si, bx ; name 1118 ;p = name; 1119 ;while (*p) 1120 dname_1: 1121 000004BC AC lodsb 1122 000004BD 20C0 and al, al 1123 000004BF 740D jz short dname_2 1124 000004C1 3C2F cmp al, DELIM ; cmp al, '/' 1125 000004C3 75F7 jne short dname_1 1126 ;if (*p++ == DELIM && *p) 1127 000004C5 803C00 cmp byte [si], 0 1128 ;je short dname_1 1129 000004C8 7404 je short dname_2 1130 000004CA 89F3 mov bx, si 1131 000004CC EBEE jmp short dname_1 1132 dname_2: 1133 ; dx = file name 1134 000004CE 89DE mov si, bx 1135 dname_3: 1136 000004D0 AC lodsb 1137 000004D1 AA stosb 1138 000004D2 08C0 or al, al 1139 000004D4 75FA jnz short dname_3 1140 000004D6 C3 retn 1141 1142 ;----------------------------------------------------------------- 1143 1144 pname: ; pname(name) 1145 ; 23/05/2022 1146 1147 ; INPUT: 1148 ; di = source (pathname) 1149 ; bx = buffer address 1150 ; OUTPUT: 1151 ; si = parent dir name address 1152 pname_0: 1153 000004D7 89FE mov si, di ; source 1154 000004D9 57 push di ; * 1155 ;p = q = buf; 1156 000004DA 89DF mov di, bx 1157 000004DC 89D9 mov cx, bx 1158 ; while (c = *p++ = *name++) 1159 pname_1: 1160 000004DE AC lodsb 1161 000004DF AA stosb 1162 000004E0 20C0 and al, al 1163 000004E2 7409 jz short pname_2 1164 ;if (c == DELIM) 1165 ; q = p-1; 1166 000004E4 3C2F cmp al, DELIM ; cmp al, '/' 1167 000004E6 75F6 jne short pname_1 1168 000004E8 89FB mov bx, di 1169 000004EA 4B dec bx 1170 000004EB EBF1 jmp short pname_1 1171 pname_2: 1172 ;if (q == buf && *q == DELIM) 1173 ; q++; 1174 000004ED 39CB cmp bx, cx 1175 000004EF 7506 jne short pname_3 1176 000004F1 803F2F cmp byte [bx], DELIM ; '/' 1177 000004F4 7501 jne short pname_3 1178 000004F6 43 inc bx 1179 pname_3: 1180 ;*q = 0; 1181 000004F7 C60700 mov byte [bx], 0 1182 000004FA 89CE mov si, cx 1183 000004FC 5F pop di ; * 1184 ; return buf[0]? buf : DOT; 1185 000004FD 803C00 cmp byte [si], 0 1186 00000500 7705 ja short pname_4 1187 00000502 A1[5E06] mov ax, [DOT] ; db '.', 0 1188 00000505 8904 mov [si], ax 1189 pname_4: 1190 00000507 C3 retn 1191 1192 ;----------------------------------------------------------------- 1193 1194 check: ; check(spth, dinode) 1195 ; 23/05/2022 1196 1197 ; INPUT: 1198 ; bx = name buffer address 1199 ; [st1buf+stat.inode] = inode num to be compared 1200 ; OUTPUT: 1201 ; cf = 1 -> error 1202 ; cf = 0 -> no problem 1203 1204 ;strcpy(nspth, spth); 1205 1206 00000508 89DE mov si, bx 1207 0000050A 57 push di ; * 1208 0000050B BF[FE0A] mov di, nspth 1209 check_1: 1210 0000050E AC lodsb 1211 0000050F AA stosb 1212 00000510 20C0 and al, al 1213 00000512 75FA jnz short check_1 1214 00000514 29DE sub si, bx 1215 00000516 4E dec si ; si = strlen(nspth) 1216 00000517 5F pop di ; * 1217 check_2: 1218 ;if (stat(nspth, &sbuf) < 0) 1219 sys _stat, nspth, fstbuf 91 <1> 92 <1> %if %0 >= 2 93 00000518 BB[FE0A] <1> mov bx, %2 94 <1> %if %0 >= 3 95 0000051B B9[720A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000051E B81200 <1> mov ax, %1 102 00000521 CD20 <1> int 20h 1220 00000523 7314 jnc short check_5 1221 ;fprintf(stderr, "mv: cannot access %s\n", nspth); 1222 00000525 B8[FA06] mov ax, msg_cant_access 1223 00000528 E80801 call print_msg 1224 0000052B B8[FE0A] mov ax, nspth 1225 0000052E E80201 call print_msg 1226 00000531 B8[CA06] mov ax, nextline 1227 check_3: 1228 00000534 E8FC00 call print_msg 1229 00000537 F9 stc 1230 check_4: 1231 00000538 C3 retn 1232 check_5: 1233 ;if (sbuf.st_ino == dinode) 1234 00000539 A1[720A] mov ax, [fstbuf+stat.inode] 1235 0000053C 3B06[1009] cmp ax, [st1buf+stat.inode] 1236 00000540 7505 jne short check_6 1237 ; fprintf(stderr, "mv: cannot move a directory 1238 ; into itself\n"); 1239 00000542 B8[9508] mov ax, msg_cant_mv_itself 1240 00000545 EBED jmp short check_3 1241 check_6: 1242 ;while (sbuf.st_ino != ROOTINO) 1243 00000547 83F829 cmp ax, ROOTINO 1244 0000054A 74EC je short check_4 1245 1246 ;if (strlen(nspth) > MAXN-2-sizeof(DOTDOT)) 1247 0000054C 83FE6C cmp si, MAXN-4 1248 0000054F 7605 jna short check_7 1249 1250 ;fprintf(stderr, "mv: name too long\n"); 1251 00000551 B8[C108] mov ax, msg_too_long 1252 00000554 EBDE jmp short check_3 1253 check_7: 1254 ;strcat(nspth, SDELIM); 1255 ;strcat(nspth, DOTDOT); 1256 ;mov eax, 002E2E2Fh ; db '/..', 0 1257 ;mov [si+nspth], eax 1258 ; 27/05/2022 1259 00000556 B82F2E mov ax, 2E2Fh ; db '/.' 1260 00000559 8984[FE0A] mov [si+nspth], ax 1261 0000055D B82E00 mov ax, 02Eh ; db '.', 0 1262 00000560 8984[000B] mov [si+nspth+2], ax 1263 00000564 83C603 add si, 3 1264 00000567 EBAF jmp short check_2 1265 1266 ;----------------------------------------------------------------- 1267 1268 chkdot: ; chkdot(s) 1269 ; 23/05/2022 1270 1271 ;do { 1272 ; if (strcmp(dname(s), DOTDOT) == 0) 1273 ; return(1); 1274 ; s = pname(s); 1275 ;} while (strcmp(s, DOT) != 0 && strcmp(s, SDELIM) != 0); 1276 ;return(0); 1277 1278 ; INPUT: 1279 ; bx = name buffer address 1280 ; OUTPUT: 1281 ; cf = 1 -> DOTDOT (return 0) 1282 ; cf = 0 -> not DOTDOT (return 1) 1283 1284 ; get last '/' 1285 00000569 89DE mov si, bx 1286 chkdot_0: 1287 0000056B 89D9 mov cx, bx 1288 chkdot_1: 1289 0000056D AC lodsb 1290 0000056E 20C0 and al, al 1291 00000570 740E jz short chkdot_2 1292 00000572 3C2F cmp al, DELIM ; '/' 1293 00000574 75F7 jne short chkdot_1 1294 00000576 803C00 cmp byte [si], 0 1295 00000579 7605 jna short chkdot_2 1296 0000057B 89F1 mov cx, si 1297 0000057D 49 dec cx 1298 0000057E EBED jmp short chkdot_1 1299 chkdot_2: 1300 00000580 57 push di ; * 1301 00000581 89CE mov si, cx 1302 00000583 BF[5D06] mov di, DOTDOT 1303 00000586 E826FF call strcmp 1304 00000589 7412 jz short chkdot_4 ; DOTDOT 1305 0000058B 89DF mov di, bx 1306 0000058D BB[720A] mov bx, fstbuf 1307 00000590 E844FF call pname 1308 00000593 5F pop di ; * 1309 00000594 89F3 mov bx, si ; parent dir's pathname buf 1310 00000596 8B04 mov ax, [si] 1311 00000598 08E4 or ah, ah ; 0 ? 1312 0000059A 75CF jnz short chkdot_0 1313 ; (single character parent directory name) 1314 ; (it's name may be '.' or '/' or another char) 1315 ; pathname does not contain a DOTDOT 1316 0000059C C3 retn 1317 chkdot_4: 1318 ; pathname contains DOTDOT 1319 0000059D F9 stc 1320 0000059E C3 retn 1321 1322 ;----------------------------------------------------------------- 1323 1324 access: 1325 ; 22/05/2022 1326 ; Retro UNIX 386 v1 & v1.1 & v1.2 1327 1328 ; INPUT: 1329 ; si = stat(us) buffer 1330 ; OUTPUT: 1331 ; zf = 1 -> no write permission 1332 ; zf = 0 -> permitted to write 1333 1334 sys _getuid 91 <1> 92 <1> %if %0 >= 2 93 <1> mov bx, %2 94 <1> %if %0 >= 3 95 <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000059F B81800 <1> mov ax, %1 102 000005A2 CD20 <1> int 20h 1335 ;mov [uid], ax 1336 1337 ; Retro UNIX 386 v1.2 (v2 fs) 1338 ;mov dl, 80h ; write permission flag, owner 1339 1340 ; Retro UNIX 386 v1 1341 000005A4 B204 mov dl, 4 ; write permission flag, owner 1342 1343 ;or ax, ax 1344 000005A6 08C0 or al, al 1345 000005A8 7407 jz short access_1 ; root 1346 1347 ;cmp ax, [si+stat.uid] 1348 000005AA 3A4405 cmp al, [si+stat.uid] 1349 000005AD 7402 je short access_1 1350 1351 ; Retro UNIX 386 v1.2 (v2 fs inode) 1352 ;sys _getgid 1353 ;;mov [gid], al 1354 1355 ;mov dl, 10h 1356 ;cmp al, [si+stat.gid] 1357 ;je short access_1 1358 ; 1359 ;mov dl, 02h 1360 1361 ; Retro UNIX 386 v1 1362 000005AF B201 mov dl, 1 1363 access_1: 1364 000005B1 845402 test dl, [si+stat.mode] 1365 000005B4 C3 retn 1366 1367 ;----------------------------------------------------------------- 1368 1369 isatty: 1370 ; 22/05/2022 1371 ; Retro UNIX 386 v1 & v1.1 & v1.2 1372 1373 ; Input: stdin (= 0) 1374 ; output: 1375 ; cf = 1 -> not a tty 1376 1377 sys _fstat, STDIN, fstbuf 91 <1> 92 <1> %if %0 >= 2 93 000005B5 BB0000 <1> mov bx, %2 94 <1> %if %0 >= 3 95 000005B8 B9[720A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 000005BB B81C00 <1> mov ax, %1 102 000005BE CD20 <1> int 20h 1378 1379 000005C0 A1[720A] mov ax, [fstbuf+stat.inode] 1380 1381 ; Retro UNIX 386 v1.2 1382 ;cmp ax, 8 ; /dev/tty 1383 ;je short isatty_2 1384 ;cmp ax, 26 ; /dev/tty8 1385 ;ja short isatty_1 1386 ;cmp ax, 17 ; /dev/tty0 1387 ;retn 1388 1389 ; Retro UNIX 386 v1 (& v1.1) 1390 000005C3 83F801 cmp ax, 1 ; /dev/tty 1391 000005C6 740A je short isatty_2 1392 000005C8 83F813 cmp ax, 19 ; /dev/tty8 1393 000005CB 7704 ja short isatty_1 1394 000005CD 83F80A cmp ax, 10 ; /dev/tty0 1395 000005D0 C3 retn 1396 isatty_1: 1397 000005D1 F9 stc 1398 isatty_2: 1399 000005D2 C3 retn 1400 1401 ;----------------------------------------------------------------- 1402 1403 octalnumber: 1404 ; 27/05/2022 1405 1406 ; Input: 1407 ; bx = binary number (max. 9 bit) 1408 ; si = string buffer (4 byte) 1409 1410 000005D3 89D8 mov ax, bx 1411 000005D5 B103 mov cl, 3 1412 000005D7 D3EB shr bx, cl ; 3 1413 000005D9 2407 and al, 7 1414 000005DB 50 push ax 1415 000005DC 89D8 mov ax, bx 1416 000005DE D3EB shr bx, cl ; 3 1417 000005E0 2407 and al, 7 1418 000005E2 50 push ax 1419 000005E3 89D8 mov ax, bx 1420 000005E5 2407 and al, 7 1421 octn_0: 1422 ; 27/05/2022 1423 ;mov byte [si], 20h 1424 ;inc si 1425 000005E7 89F3 mov bx, si 1426 ;or al, al 1427 ;jz short octn_1 1428 000005E9 E80C00 call octn_3 1429 octn_1: 1430 000005EC 58 pop ax 1431 ; 27/05/2022 1432 000005ED E80800 call octn_3 1433 octn_2: 1434 000005F0 58 pop ax 1435 ;call octn_3 1436 000005F1 E80C00 call octn_4 ; 27/05/2022 1437 000005F4 30C0 xor al, al 1438 000005F6 EB0A jmp short octn_5 1439 1440 octn_3: 1441 ; 27/05/2022 1442 000005F8 20C0 and al, al 1443 000005FA 7504 jnz short octn_4 1444 000005FC 39DE cmp si, bx 1445 000005FE 7405 je short octn_6 1446 octn_4: 1447 00000600 0430 add al, '0' 1448 octn_5: 1449 00000602 8804 mov [si], al 1450 00000604 46 inc si 1451 octn_6: 1452 00000605 C3 retn 1453 1454 ;----------------------------------------------------------------- 1455 1456 getchar: 1457 ; i = c = getchar(); 1458 ; while (c != '\n' && c != EOF) 1459 ; c = getchar(); 1460 getc_0: 1461 sys _read, STDIN, char, 1 91 <1> 92 <1> %if %0 >= 2 93 00000606 BB0000 <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000609 B9[FD0A] <1> mov cx, %3 96 <1> %if %0 >= 4 97 0000060C BA0100 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 0000060F B80300 <1> mov ax, %1 102 00000612 CD20 <1> int 20h 1462 00000614 A0[FD0A] mov al, [char] 1463 00000617 3C79 cmp al, 'y' 1464 00000619 7417 je short getc_2 1465 0000061B 3C6E cmp al, 'n' 1466 0000061D 7413 je short getc_2 1467 0000061F 3C1B cmp al, ESCKey 1468 00000621 740F je short getc_2 1469 00000623 3C0D cmp al, EnterKey 1470 00000625 740B je short getc_2 1471 00000627 3C59 cmp al, 'Y' 1472 00000629 7503 jne short getc_1 1473 0000062B B079 mov al, 'y' 1474 0000062D C3 retn 1475 getc_1: 1476 0000062E 3C4E cmp al, 'N' 1477 00000630 75D4 jne short getc_0 1478 getc_2: 1479 00000632 C3 retn 1480 1481 ;----------------------------------------------------------------- 1482 1483 print_msg: 1484 ; ax = asciiz string address 1485 00000633 89C6 mov si, ax 1486 00000635 4E dec si 1487 nextchr: 1488 00000636 46 inc si 1489 00000637 803C00 cmp byte [si], 0 1490 0000063A 77FA ja short nextchr 1491 ;cmp [si], 0Dh 1492 ;ja short nextchr 1493 0000063C 29C6 sub si, ax 1494 ; si = asciiz string length 1495 ; 1496 sys _write, 1, ax, si 91 <1> 92 <1> %if %0 >= 2 93 0000063E BB0100 <1> mov bx, %2 94 <1> %if %0 >= 3 95 00000641 89C1 <1> mov cx, %3 96 <1> %if %0 >= 4 97 00000643 89F2 <1> mov dx, %4 98 <1> %endif 99 <1> %endif 100 <1> %endif 101 00000645 B80400 <1> mov ax, %1 102 00000648 CD20 <1> int 20h 1497 ; 1498 0000064A C3 retn 1499 1500 ;----------------------------------------------------------------- 1501 ; data - initialized data 1502 ;----------------------------------------------------------------- 1503 1504 ;argc: dd 0 1505 0000064B 00 argc: db 0 1506 0000064C 00 errors: db 0 1507 1508 cp_cmd: 1509 0000064D 2F62696E2F637000 db '/bin/cp', 0 1510 1511 ;cp_args: 1512 ; dd cp_cmd 1513 ;cp_source: 1514 ; dd 0 1515 ;cp_target: 1516 ; dd 0 1517 ; dd 0 1518 1519 ; 27/05/2022 - Retro UNIX 8086 v1 1520 cp_args: 1521 00000655 [4D06] dw cp_cmd 1522 cp_source: 1523 00000657 0000 dw 0 1524 cp_target: 1525 00000659 0000 dw 0 1526 0000065B 0000 dw 0 1527 1528 0000065D 2E DOTDOT: db '.' 1529 0000065E 2E00 DOT: db '.', 0 1530 ;db 0, 0 1531 1532 ; ---------------------------------------------------------------- 1533 1534 program_msg: 1535 00000660 0D0A db 0Dh, 0Ah 1536 00000662 526574726F20554E49- db 'Retro UNIX 8086 v1 MOVE by Erdogan TAN - 27/05/2022' 1536 0000066B 582038303836207631- 1536 00000674 204D4F564520627920- 1536 0000067D 4572646F67616E2054- 1536 00000686 414E202D2032372F30- 1536 0000068F 352F32303232 1537 00000695 0D0A00 db 0Dh, 0Ah, 0 1538 1539 usage_msg: 1540 00000698 0D0A db 0Dh, 0Ah 1541 0000069A 75736167653A206D76- db 'usage: mv f1 f2; or mv d1 d2; or mv f1 ... fn d1' 1541 000006A3 2066312066323B206F- 1541 000006AC 72206D762064312064- 1541 000006B5 323B206F72206D7620- 1541 000006BE 6631202E2E2E20666E- 1541 000006C7 206431 1542 nextline: 1543 000006CA 0D0A00 db 0Dh, 0Ah, 0 1544 1545 mv_header: 1546 000006CD 0D0A db 0Dh, 0Ah 1547 000006CF 6D763A20 db 'mv: ' 1548 000006D3 00 db 0 1549 msg_not_exists: 1550 ;db 0Dh, 0Ah 1551 000006D4 20646F6573206E6F74- db ' does not exist ' 1551 000006DD 20657869737420 1552 000006E4 0D0A00 db 0Dh, 0Ah, 0 1553 1554 msg_is_a_dir: 1555 000006E7 206973206120646972- db ' is a directory ' 1555 000006F0 6563746F727920 1556 000006F7 0D0A00 db 0Dh, 0Ah, 0 1557 1558 msg_cant_access: 1559 000006FA 0D0A db 0Dh, 0Ah 1560 000006FC 6D763A2063616E6E6F- db 'mv: cannot access ' 1560 00000705 742061636365737320 1561 0000070E 00 db 0 1562 1563 msg_rename_only: 1564 0000070F 0D0A db 0Dh, 0Ah 1565 00000711 6D763A206469726563- db 'mv: directory rename only' 1565 0000071A 746F72792072656E61- 1565 00000723 6D65206F6E6C79 1566 0000072A 0D0A00 db 0Dh, 0Ah, 0 1567 1568 msg_cant_unlink: 1569 0000072D 0D0A db 0Dh, 0Ah 1570 0000072F 6D763A2063616E6E6F- db 'mv: cannot unlink ' 1570 00000738 7420756E6C696E6B20 1571 00000741 00 db 0 1572 1573 msg_try_again: 1574 00000742 0D0A db 0Dh, 0Ah 1575 00000744 6D763A207472792061- db 'mv: try again' 1575 0000074D 6761696E 1576 00000751 0D0A00 db 0Dh, 0Ah, 0 1577 1578 msg_cant_exec_cp: 1579 00000754 0D0A db 0Dh, 0Ah 1580 00000756 6D763A2063616E6E6F- db 'mv: cannot exec cp' 1580 0000075F 742065786563206370 1581 00000768 0D0A00 db 0Dh, 0Ah, 0 1582 1583 msg_exists: 1584 0000076B 2065786973747320 db ' exists ' 1585 00000773 0D0A00 db 0Dh, 0Ah, 0 1586 1587 ;msg_long_target: 1588 ; db 0Dh, 0Ah 1589 ; db 'mv: target name too long' 1590 ; db 0Dh, 0Ah, 0 1591 1592 msg_src_target: 1593 00000776 0D0A db 0Dh, 0Ah 1594 00000778 6D763A203F3F20736F- db 'mv: ?? source == target, source exists and target doesnt' 1594 00000781 75726365203D3D2074- 1594 0000078A 61726765742C20736F- 1594 00000793 757263652065786973- 1594 0000079C 747320616E64207461- 1594 000007A5 7267657420646F6573- 1594 000007AE 6E74 1595 000007B0 0D0A00 db 0Dh, 0Ah, 0 1596 1597 msg_cant_locate: 1598 000007B3 0D0A db 0Dh, 0Ah 1599 000007B5 6D763A2063616E6E6F- db 'mv: cannot locate parent' 1599 000007BE 74206C6F6361746520- 1599 000007C7 706172656E74 1600 000007CD 0D0A00 db 0Dh, 0Ah, 0 1601 1602 msg_no_w_access: 1603 000007D0 0D0A db 0Dh, 0Ah 1604 000007D2 6D763A206E6F207772- db 'mv: no write access to ' 1604 000007DB 697465206163636573- 1604 000007E4 7320746F20 1605 000007E9 00 db 0 1606 1607 msg_accross_devices: 1608 000007EA 0D0A db 0Dh, 0Ah 1609 000007EC 6D763A2063616E6E6F- db 'mv: cannot move directories across devices' 1609 000007F5 74206D6F7665206469- 1609 000007FE 726563746F72696573- 1609 00000807 206163726F73732064- 1609 00000810 657669636573 1610 00000816 0D0A00 db 0Dh, 0Ah, 0 1611 1612 msg_pathname_dotdot: 1613 00000819 0D0A db 0Dh, 0Ah 1614 0000081B 6D763A20536F727279- db "mv: Sorry, path names including '..' aren't allowed" 1614 00000824 2C2070617468206E61- 1614 0000082D 6D657320696E636C75- 1614 00000836 64696E6720272E2E27- 1614 0000083F 206172656E27742061- 1614 00000848 6C6C6F776564 1615 0000084E 0D0A00 db 0Dh, 0Ah, 0 1616 1617 msg_cant_rename: 1618 00000851 0D0A db 0Dh, 0Ah 1619 00000853 6D763A2063616E6E6F- db 'mv: cannot rename ' 1619 0000085C 742072656E616D6520 1620 00000865 00 db 0 1621 1622 msg_cant_link: 1623 00000866 0D0A db 0Dh, 0Ah 1624 00000868 6D763A2063616E6E6F- db 'mv: cannot link ' 1624 00000871 74206C696E6B20 1625 00000878 00 db 0 1626 msg_to: 1627 00000879 20746F20 db ' to ' 1628 0000087D 00 db 0 1629 msg_and: 1630 0000087E 20616E6420 db ' and ' 1631 00000883 00 db 0 1632 1633 msg_identical: 1634 00000884 20617265206964656E- db ' are identical' 1634 0000088D 746963616C 1635 00000892 0D0A00 db 0Dh, 0Ah, 0 1636 1637 msg_cant_mv_itself: 1638 00000895 0D0A db 0Dh, 0Ah 1639 00000897 6D763A2063616E6E6F- db 'mv: cannot move a directory into itself' 1639 000008A0 74206D6F7665206120- 1639 000008A9 6469726563746F7279- 1639 000008B2 20696E746F20697473- 1639 000008BB 656C66 1640 000008BE 0D0A00 db 0Dh, 0Ah, 0 1641 1642 msg_too_long: 1643 000008C1 0D0A db 0Dh, 0Ah 1644 000008C3 6D763A206E616D6520- db 'mv: name too long' 1644 000008CC 746F6F206C6F6E67 1645 000008D4 0D0A00 db 0Dh, 0Ah, 0 1646 1647 msg_mode: 1648 000008D7 206D6F6465203F2028- db ' mode ? (y/n) ' 1648 000008E0 792F6E2920 1649 000008E5 00 db 0 1650 1651 msg_yes: 1652 000008E6 2059455320 db ' YES ' 1653 000008EB 0D0A00 db 0Dh, 0Ah, 0 1654 1655 msg_no: 1656 000008EE 204E4F20 db ' NO ' 1657 000008F2 0D0A00 db 0Dh, 0Ah, 0 1658 1659 err_msg: 1660 000008F5 0D0A db 0Dh, 0Ah 1661 000008F7 4572726F722120 db 'Error! ' 1662 000008FE 0D0A00 db 0Dh, 0Ah, 0 1663 1664 msg_ok: 1665 00000901 0D0A db 0Dh, 0Ah 1666 00000903 4F4B2E db 'OK.' 1667 00000906 0D0A00 db 0Dh, 0Ah, 0 1668 1669 ;----------------------------------------------------------------- 1670 ; bss - uninitialized data 1671 ;----------------------------------------------------------------- 1672 1673 00000909 90 align 4 1674 1675 bss_start: 1676 1677 ABSOLUTE bss_start 1678 1679 ;uid: resw 1 1680 ;;gid: resw 1 ; Retro UNIX 386 v1.2 1681 1682 ;target: resd 1 ; destination/target pathname pointer 1683 ; 27/05/2022 1684 0000090C ???? target: resw 1 ; Retro UNIX 8086 v1 1685 1686 0000090E ???? st1dev: resw 1 1687 00000910 st1buf: resb 34 ; for Retro UNIX 386 v1 & v1.1 1688 00000932 ???? st2dev: resw 1 1689 00000934 st2buf: resb 34 ; 1690 ;st1dev: resd 1 1691 ;st1buf: resb 66 ; for Retro UNIX 386 v1.2 1692 ;st2dev: resd 1 1693 ;st2buf: resb 66 ; 1694 1695 00000956 buf: resb 100 ; pathname buffer 1696 000009BA sbuf: resb 92 ; source, parent name buffer ; 23/05/2022 1697 00000A16 tbuf: resb 92 ; target, parent name buffer ; 23/05/2022 1698 00000A72 fstbuf: resb 66 ; fstat buffer 1699 ; 23/05/2022 1700 ;pst1buf: resb 66 1701 ;pst2buf: resb 66 1702 00000AB4 pst1buf: resb 34 1703 00000AD6 pst2buf: resb 34 1704 00000AF8 ?? octms: resb 1 ; 27/05/2022 1705 00000AF9 ???????? octm: resb 4 ; octal mode number 1706 00000AFD ?? char: resb 1 ; getchar buffer 1707 00000AFE nspth: resb MAXN ; 112 ; buffer for 'check' procedure 1708 1709 ; 22/05/2022 1710 ;----------------------------------------------------------------- 1711 ; Original UNIX v7 - mv (utility) c source code (mv.c) 1712 ;----------------------------------------------------------------- 1713 ;/* UNIX V7 source code: see www.tuhs.org for details. */; 1714 ; 1715 ;/* 1716 ; * mv file1 file2 1717 ; */ 1718 ; 1719 ;#include 1720 ;#include 1721 ;#include 1722 ;#include 1723 ;#include 1724 ; 1725 ;#define DOT "." 1726 ;#define DOTDOT ".." 1727 ;#define DELIM '/' 1728 ;#define SDELIM "/" 1729 ;#define MAXN 100 1730 ;#define MODEBITS 07777 1731 ;#define ROOTINO 2 1732 ; 1733 ;char *pname(); 1734 ;char *sprintf(); 1735 ;char *dname(); 1736 ;struct stat s1, s2; 1737 ; 1738 ;main(argc, argv) 1739 ;register char *argv[]; 1740 ;{ 1741 ; register i, r; 1742 ; 1743 ; if (argc < 3) 1744 ; goto usage; 1745 ; if (stat(argv[1], &s1) < 0) { 1746 ; fprintf(stderr, "mv: cannot access %s\n", argv[1]); 1747 ; return(1); 1748 ; } 1749 ; if ((s1.st_mode & S_IFMT) == S_IFDIR) { 1750 ; if (argc != 3) 1751 ; goto usage; 1752 ; return mvdir(argv[1], argv[2]); 1753 ; } 1754 ; setuid(getuid()); 1755 ; if (argc > 3) 1756 ; if (stat(argv[argc-1], &s2) < 0 || (s2.st_mode & S_IFMT) != S_IFDIR) 1757 ; goto usage; 1758 ; r = 0; 1759 ; for (i=1; i= 0) { 1783 ; if ((s2.st_mode & S_IFMT) == S_IFDIR) { 1784 ; sprintf(buf, "%s/%s", target, dname(source)); 1785 ; target = buf; 1786 ; } 1787 ; if (stat(target, &s2) >= 0) { 1788 ; if ((s2.st_mode & S_IFMT) == S_IFDIR) { 1789 ; fprintf(stderr, "mv: %s is a directory\n", target); 1790 ; return(1); 1791 ; } 1792 ; if (s1.st_dev==s2.st_dev && s1.st_ino==s2.st_ino) { 1793 ; fprintf(stderr, "mv: %s and %s are identical\n", 1794 ; source, target); 1795 ; return(1); 1796 ; } 1797 ; if (access(target, 2) < 0 && isatty(fileno(stdin))) { 1798 ; fprintf(stderr, "mv: %s: %o mode ", target, 1799 ; s2.st_mode & MODEBITS); 1800 ; i = c = getchar(); 1801 ; while (c != '\n' && c != EOF) 1802 ; c = getchar(); 1803 ; if (i != 'y') 1804 ; return(1); 1805 ; } 1806 ; if (unlink(target) < 0) { 1807 ; fprintf(stderr, "mv: cannot unlink %s\n", target); 1808 ; return(1); 1809 ; } 1810 ; } 1811 ; } 1812 ; if (link(source, target) < 0) { 1813 ; i = fork(); 1814 ; if (i == -1) { 1815 ; fprintf(stderr, "mv: try again\n"); 1816 ; return(1); 1817 ; } 1818 ; if (i == 0) { 1819 ; execl("/bin/cp", "cp", source, target, 0); 1820 ; fprintf(stderr, "mv: cannot exec cp\n"); 1821 ; exit(1); 1822 ; } 1823 ; while ((c = wait(&status)) != i && c != -1) 1824 ; ; 1825 ; if (status != 0) 1826 ; return(1); 1827 ; utime(target, &s1.st_atime); 1828 ; } 1829 ; if (unlink(source) < 0) { 1830 ; fprintf(stderr, "mv: cannot unlink %s\n", source); 1831 ; return(1); 1832 ; } 1833 ; return(0); 1834 ;} 1835 ; 1836 ;mvdir(source, target) 1837 ;char *source, *target; 1838 ;{ 1839 ; register char *p; 1840 ; register i; 1841 ; char buf[MAXN]; 1842 ; 1843 ; if (stat(target, &s2) >= 0) { 1844 ; if ((s2.st_mode&S_IFMT) != S_IFDIR) { 1845 ; fprintf(stderr, "mv: %s exists\n", target); 1846 ; return(1); 1847 ; } 1848 ; if (strlen(target) > MAXN-DIRSIZ-2) { 1849 ; fprintf(stderr, "mv :target name too long\n"); 1850 ; return(1); 1851 ; } 1852 ; strcpy(buf, target); 1853 ; target = buf; 1854 ; strcat(buf, SDELIM); 1855 ; strcat(buf, dname(source)); 1856 ; if (stat(target, &s2) >= 0) { 1857 ; fprintf(stderr, "mv: %s exists\n", buf); 1858 ; return(1); 1859 ; } 1860 ; } 1861 ; if (strcmp(source, target) == 0) { 1862 ; fprintf(stderr, "mv: ?? source == target, source exists and target doesnt\n"); 1863 ; return(1); 1864 ; } 1865 ; p = dname(source); 1866 ; if (!strcmp(p, DOT) || !strcmp(p, DOTDOT) || !strcmp(p, "") || p[strlen(p)-1]=='/') { 1867 ; fprintf(stderr, "mv: cannot rename %s\n", p); 1868 ; return(1); 1869 ; } 1870 ; if (stat(pname(source), &s1) < 0 || stat(pname(target), &s2) < 0) { 1871 ; fprintf(stderr, "mv: cannot locate parent\n"); 1872 ; return(1); 1873 ; } 1874 ; if (access(pname(target), 2) < 0) { 1875 ; fprintf(stderr, "mv: no write access to %s\n", pname(target)); 1876 ; return(1); 1877 ; } 1878 ; if (access(pname(source), 2) < 0) { 1879 ; fprintf(stderr, "mv: no write access to %s\n", pname(source)); 1880 ; return(1); 1881 ; } 1882 ; if (access(source, 2) < 0) { 1883 ; fprintf(stderr, "mv: no write access to %s\n", source); 1884 ; return(1); 1885 ; } 1886 ; if (s1.st_dev != s2.st_dev) { 1887 ; fprintf(stderr, "mv: cannot move directories across devices\n"); 1888 ; return(1); 1889 ; } 1890 ; if (s1.st_ino != s2.st_ino) { 1891 ; char dst[MAXN+5]; 1892 ; 1893 ; if (chkdot(source) || chkdot(target)) { 1894 ; fprintf(stderr, "mv: Sorry, path names including %s aren't allowed\n", DOTDOT); 1895 ; return(1); 1896 ; } 1897 ; stat(source, &s1); 1898 ; if (check(pname(target), s1.st_ino)) 1899 ; return(1); 1900 ; for (i = 1; i <= NSIG; i++) 1901 ; signal(i, SIG_IGN); 1902 ; if (link(source, target) < 0) { 1903 ; fprintf(stderr, "mv: cannot link %s to %s\n", target, source); 1904 ; return(1); 1905 ; } 1906 ; if (unlink(source) < 0) { 1907 ; fprintf(stderr, "mv: %s: cannot unlink\n", source); 1908 ; unlink(target); 1909 ; return(1); 1910 ; } 1911 ; strcat(dst, target); 1912 ; strcat(dst, "/"); 1913 ; strcat(dst, DOTDOT); 1914 ; if (unlink(dst) < 0) { 1915 ; fprintf(stderr, "mv: %s: cannot unlink\n", dst); 1916 ; if (link(target, source) >= 0) 1917 ; unlink(target); 1918 ; return(1); 1919 ; } 1920 ; if (link(pname(target), dst) < 0) { 1921 ; fprintf(stderr, "mv: cannot link %s to %s\n", 1922 ; dst, pname(target)); 1923 ; if (link(pname(source), dst) >= 0) 1924 ; if (link(target, source) >= 0) 1925 ; unlink(target); 1926 ; return(1); 1927 ; } 1928 ; return(0); 1929 ; } 1930 ; if (link(source, target) < 0) { 1931 ; fprintf(stderr, "mv: cannot link %s and %s\n", 1932 ; source, target); 1933 ; return(1); 1934 ; } 1935 ; if (unlink(source) < 0) { 1936 ; fprintf(stderr, "mv: ?? cannot unlink %s\n", source); 1937 ; return(1); 1938 ; } 1939 ; return(0); 1940 ;} 1941 ; 1942 ;char * 1943 ;pname(name) 1944 ;register char *name; 1945 ;{ 1946 ; register c; 1947 ; register char *p, *q; 1948 ; static char buf[MAXN]; 1949 ; 1950 ; p = q = buf; 1951 ; while (c = *p++ = *name++) 1952 ; if (c == DELIM) 1953 ; q = p-1; 1954 ; if (q == buf && *q == DELIM) 1955 ; q++; 1956 ; *q = 0; 1957 ; return buf[0]? buf : DOT; 1958 ;} 1959 ; 1960 ;char * 1961 ;dname(name) 1962 ;register char *name; 1963 ;{ 1964 ; register char *p; 1965 ; 1966 ; p = name; 1967 ; while (*p) 1968 ; if (*p++ == DELIM && *p) 1969 ; name = p; 1970 ; return name; 1971 ;} 1972 ; 1973 ;check(spth, dinode) 1974 ;char *spth; 1975 ;ino_t dinode; 1976 ;{ 1977 ; char nspth[MAXN]; 1978 ; struct stat sbuf; 1979 ; 1980 ; sbuf.st_ino = 0; 1981 ; 1982 ; strcpy(nspth, spth); 1983 ; while (sbuf.st_ino != ROOTINO) { 1984 ; if (stat(nspth, &sbuf) < 0) { 1985 ; fprintf(stderr, "mv: cannot access %s\n", nspth); 1986 ; return(1); 1987 ; } 1988 ; if (sbuf.st_ino == dinode) { 1989 ; fprintf(stderr, "mv: cannot move a directory into itself\n"); 1990 ; return(1); 1991 ; } 1992 ; if (strlen(nspth) > MAXN-2-sizeof(DOTDOT)) { 1993 ; fprintf(stderr, "mv: name too long\n"); 1994 ; return(1); 1995 ; } 1996 ; strcat(nspth, SDELIM); 1997 ; strcat(nspth, DOTDOT); 1998 ; } 1999 ; return(0); 2000 ;} 2001 ; 2002 ;chkdot(s) 2003 ;register char *s; 2004 ;{ 2005 ; do { 2006 ; if (strcmp(dname(s), DOTDOT) == 0) 2007 ; return(1); 2008 ; s = pname(s); 2009 ; } while (strcmp(s, DOT) != 0 && strcmp(s, SDELIM) != 0); 2010 ; return(0); 2011 ;} 2012 ;