     1                                  ; ****************************************************************************
     2                                  ; cp386.s (cp0.s) - by Erdogan Tan - 20/04/2022
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; Retro UNIX 386 v1 - copy -- cp oldfile newfile
     5                                  ;
     6                                  ; [ Last Modification: 17/06/2024 ]
     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 cp0.s -l cp0.txt -o cp0 -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                                  ; Retro UNIX 386 v1 system call format:
    92                                  ; sys systemcall (eax) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
    93                                  
    94                                  ; 11/03/2022
    95                                  ; Note: Above 'sys' macro has limitation about register positions;
    96                                  ;	ebx, ecx, edx registers must not be used after their
    97                                  ;	positions in sys macro.
    98                                  ; for example:
    99                                  ;	'sys _write, 1, msg, ecx' is defective, because
   100                                  ;	 ecx will be used/assigned before edx in 'sys' macro.
   101                                  ; correct order may be:
   102                                  ;	'sys _write, 1, msg, eax ; (eax = byte count)
   103                                  
   104                                  struc stat
   105                                  	; Note: This is for Retro UNIX v1.1 'sysstat' output !!!
   106                                  	; (34 bytes)
   107 00000000 ????                    	.inode:  resw 1	
   108 00000002 ????                    	.mode:	 resw 1
   109 00000004 ??                      	.nlinks: resb 1
   110 00000005 ??                      	.uid:	 resb 1
   111 00000006 ????                    	.size:	 resw 1
   112 00000008 <res 10h>               	.dskptr: resw 8
   113 00000018 ????????                	.ctime:	 resd 1
   114 0000001C ????????                	.mtime:	 resd 1
   115 00000020 ????                    	.rsvd:   resw 1
   116                                  	.strucsize:
   117                                  endstruc   
   118                                  
   119                                  ;struc stat
   120                                  ;	; Note: This is for Retro UNIX v1.2 'sysstat' output !!!
   121                                  ;	; (66 bytes)
   122                                  ;	.inode:  resw 1	
   123                                  ;	.mode:	 resw 1
   124                                  ;	.nlinks: resw 1 
   125                                  ;	.uid:	 resw 1
   126                                  ;	.gid:	 resb 1
   127                                  ;	.size_h: resb 1
   128                                  ;	.size:	 resd 1
   129                                  ;	.dskptr: resd 10
   130                                  ;	.atime:	 resd 1
   131                                  ;	.mtime:	 resd 1
   132                                  ;	.ctime:  resd 1
   133                                  ;	.strucsize:
   134                                  ;endstruc   
   135                                  
   136                                  ;S_IFMT   equ 0F000h ; /* type of file */
   137                                  ;S_IFDIR  equ 04000h ; /* directory */
   138                                  ;S_IFCHR  equ 02000h ; /* character special */
   139                                  ;S_IFBLK  equ 06000h ; /* block special */
   140                                  ;S_IFREG  equ 08000h ; /* regular */
   141                                  ;S_ISUID  equ 00800h ; /* set user id on execution */
   142                                  ;S_ISGID  equ 00400h ; /* set group id on execution */
   143                                  ;S_IREAD  equ 00100h ; /* read permission, owner */
   144                                  ;S_IWRITE equ 00080h ; /* write permission, owner */
   145                                  ;S_IEXEC  equ 00040h ; /* execute/search permission, owner */
   146                                  
   147                                  ; 24/04/2022
   148                                  ; 21/04/2022 - UNIX v1 inode
   149                                  ; byte 1
   150                                  S_ALLOC  equ 080h ; Allocated flag
   151                                  S_IFDIR  equ 040h ; Directory flag
   152                                  S_IFMDF  equ 020h ; File modified flag (always on)
   153                                  S_IFLRG  equ 010h ; Large File flag
   154                                  ; byte 0
   155                                  S_ISUID  equ 020h ; Set User ID On Execution flag
   156                                  S_IEXEC  equ 010h ; Executable File flag
   157                                  S_IREAD  equ 008h ; Owner's Read Permission flag
   158                                  S_IWRITE equ 004h ; Owner's Write Permission flag
   159                                  
   160                                  BSIZE equ 512
   161                                  
   162                                  ;-----------------------------------------------------------------
   163                                  ;  text - code
   164                                  ;-----------------------------------------------------------------
   165                                  
   166                                  [BITS 32] ; 32-bit intructions (for 80386 protected mode)
   167                                  
   168                                  [ORG 0] 
   169                                  
   170                                  START_CODE:
   171                                  	; 17/06/2024
   172                                  	; 20/04/2022
   173                                  	; main(argc, argv)
   174                                  
   175 00000000 89E6                    	mov	esi, esp		
   176 00000002 89F7                    	mov	edi, esi
   177 00000004 AD                      	lodsd		; number of arguments
   178                                  	;mov	edi, esi			
   179                                  	;mov	[argc], eax
   180 00000005 A2[72020000]            	mov	[argc], al
   181                                  
   182                                  	;if (argc < 3) 
   183                                  	;   goto usage;
   184                                  
   185                                  	;cmp	eax, 3
   186 0000000A 3C03                    	cmp	al, 3
   187 0000000C 7337                    	jnb	short cp_0  ; if (argc > 3) {
   188 0000000E FEC8                    	dec	al	; 21/04/2022
   189 00000010 7516                    	jnz	short cp_usage
   190                                  	sys	_msg, program_msg, 255, 0Fh
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000012 BB[73020000]        <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 00000017 B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 0000001C BA0F000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000021 B823000000          <1>  mov eax, %1
    88 00000026 CD30                <1>  int 30h
   191                                  cp_usage:
   192                                     ; fprintf(stderr, "Usage: cp: f1 f2; or cp f1 ... fn d2\n");
   193                                  	sys	_msg, usage_msg, 255, 07h
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000028 BB[AA020000]        <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 0000002D B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 00000032 BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000037 B823000000          <1>  mov eax, %1
    88 0000003C CD30                <1>  int 30h
   194                                  cp_exit:
   195                                  	sys	_exit	; sys exit
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78                              <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 0000003E B801000000          <1>  mov eax, %1
    88 00000043 CD30                <1>  int 30h
   196                                  ;hlt:
   197                                  ;	nop
   198                                  ;	nop
   199                                  ;	jmp	short hlt
   200                                  
   201                                  cp_0:
   202 00000045 89C2                    	mov	edx, eax ; [argc]
   203                                  	; 21/04/2022
   204                                  	;;dec	edx  ; argc-1
   205                                  	;dec	dl
   206 00000047 C0E202                  	shl	dl, 2 ; * 4 
   207 0000004A 01D7                    	add	edi, edx
   208                                  
   209                                  	; 21/04/2022
   210 0000004C 3C03                    	cmp	al,3
   211 0000004E 7619                    	jna	short cp_1
   212                                  
   213                                  	sys	_stat, [edi], stbuf2
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000050 8B1F                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 00000052 B9[5A030000]        <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000057 B812000000          <1>  mov eax, %1
    88 0000005C CD30                <1>  int 30h
   214 0000005E 72C8                    	jc	short cp_usage
   215                                  
   216                                  	;; check retro unix v2 inode flags
   217                                  	;;	(a bit different than unix v7 inode flags)
   218                                  	;; if it is a directory..
   219                                  	;;	regular file flag and dir flag must be 1
   220                                  	;mov	al, [stbuf2+stat.mode+1]
   221                                  	;and	al, S_IFDIR|S_IFREG
   222                                  	;cmp	al, S_IFDIR|S_IFREG ; directory ?
   223                                  	;jne	short cp_usage ; no
   224                                  	
   225                                  	;; check if it is a device file
   226                                  	;;test	al, S_IFREG ; regular file ?
   227                                  	;;jz	short cp_usage ; no
   228                                  	;;and	al, S_IFDIR ; directory ?
   229                                  	;;jz	short cp_usage ; no
   230                                  
   231                                  	; 21/04/2022
   232                                  	; check (unix v1 inode) directory flag
   233 00000060 F605[5D030000]40        	test	byte [stbuf2+stat.mode+1], S_IFDIR ; directory ?
   234 00000067 74BF                    	jz	short cp_usage ; no
   235                                   
   236                                  cp_1:	
   237                                  	; esi = esp+4 = argv[0] ; executable file name (cp)
   238 00000069 AD                      	lodsd	; 21/04/2022
   239                                  cp_loop: ; for(i=1; i<argc-1;i++)
   240                                  	;lodsd
   241                                  	; ((esi = esp+8 = argv[1] ; (old) file 1))
   242                                  	; esi = argv[i] 
   243                                   	; edi = argv[argc-1] ; *
   244 0000006A E833000000              	call	copy
   245 0000006F 7306                    	jnc	short cp_2
   246                                  
   247 00000071 FE05[50030000]          	inc	byte [errors]
   248                                  cp_2:
   249 00000077 AD                      	lodsd	; 21/04/2022
   250 00000078 39FE                    	cmp	esi, edi
   251 0000007A 72EE                    	jb	short cp_loop
   252                                  
   253                                  	; bypass 'OK.' message if there was an error
   254 0000007C 803D[50030000]00        	cmp	byte [errors], 0
   255 00000083 77B9                    	ja	short cp_exit
   256                                  cp_ok:
   257                                  	sys	_msg, ok_msg, 255, 07h
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000085 BB[48030000]        <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 0000008A B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 0000008F BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000094 B823000000          <1>  mov eax, %1
    88 00000099 CD30                <1>  int 30h
   258                                  ;cp_exit:
   259                                  	sys	_exit	; sys exit
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78                              <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 0000009B B801000000          <1>  mov eax, %1
    88 000000A0 CD30                <1>  int 30h
   260                                  
   261                                  ;_halt:
   262                                  ;	nop
   263                                  ;	jmp	short _halt
   264                                  
   265                                  copy:	; copy(from, to)
   266                                  	;
   267                                  	; 17/06/2024
   268                                  	; 21/04/2022
   269                                  	; 20/04/2022
   270                                  	; INPUT:
   271                                  	;	esi = pointer to file name to be copied
   272                                  	;  	edi = ptr to new file name or destination dir
   273                                  	; OUTPUT:
   274                                  	;	cf = 0 -> OK
   275                                  	;	cf = 1 -> Error !
   276                                  	;
   277                                  	; Modified registers: eax, ebx, ecx, edx, ebp
   278                                  	;
   279                                  	
   280                                  	; open (old) file for read
   281                                  	sys	_open, [esi], 0 
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000000A2 8B1E                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 000000A4 B900000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000000A9 B805000000          <1>  mov eax, %1
    88 000000AE CD30                <1>  int 30h
   282 000000B0 7341                    	jnc	short cp_3
   283                                  	
   284                                  	; esi = file name (from)
   285                                  
   286                                  	;fprintf(stderr, "cp: cannot open %s\n", from);
   287                                  	;	return(1);
   288                                  
   289                                  	sys	_msg, cno_err_msg, 255, 07h
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000000B2 BB[D3020000]        <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 000000B7 B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 000000BC BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000000C1 B823000000          <1>  mov eax, %1
    88 000000C6 CD30                <1>  int 30h
   290                                  	; file name (from) 
   291                                  	sys	_msg, [esi], 255, 07h
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000000C8 8B1E                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 000000CA B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 000000CF BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000000D4 B823000000          <1>  mov eax, %1
    88 000000D9 CD30                <1>  int 30h
   292                                  write_nl:
   293                                  	; new/next line
   294                                  	sys	_msg, nextline, 255, 07h
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000000DB BB[D0020000]        <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 000000E0 B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 000000E5 BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000000EA B823000000          <1>  mov eax, %1
    88 000000EF CD30                <1>  int 30h
   295 000000F1 F9                      	stc	; return with error (cf=1)
   296 000000F2 C3                      	retn
   297                                  
   298                                  cp_3:
   299 000000F3 A3[52030000]            	mov	[fold], eax ; file (descriptor) number
   300                                  
   301                                  	; (from)
   302                                  	sys	_fstat, [fold], stbuf1
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000000F8 8B1D[52030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 000000FE B9[7C030000]        <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000103 B81C000000          <1>  mov eax, %1
    88 00000108 CD30                <1>  int 30h
   303                                  
   304                                  	; 17/06/2024
   305                                  	; 09/05/2022 (retro unix 386 v1.2 kernel modification)
   306                                  	; save device number
   307                                  	; ((device number = eax return from sysfstat))
   308 0000010A A3[9E030000]            	mov	[idev1], eax
   309                                  
   310                                  	; save mode
   311                                  	;mov	ax, [stbuf1.mode]
   312                                  	;mov	[mode], ax
   313                                  
   314                                  	; (to)
   315                                  	;sys	_stat, [edi], stbuf2  ; stat(to, &stbuf2)
   316                                  	;jnc	short cp_4
   317                                  	;jmp	cp_9
   318                                  	
   319                                  	; 22/04/2022
   320 0000010F 8B2F                    	mov	ebp, [edi] ; ! (cp_8) !
   321                                  	sys	_stat, ebp, stbuf2  ; stat(to, &stbuf2)
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000111 89EB                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 00000113 B9[5A030000]        <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000118 B812000000          <1>  mov eax, %1
    88 0000011D CD30                <1>  int 30h
   322 0000011F 7305                    	jnc	short cp_4
   323 00000121 E988000000              	jmp	cp_9
   324                                  
   325                                  cp_4:
   326                                  	; /* is target a directory? */
   327                                  
   328                                  	;; check retro unix v2 inode flags
   329                                  	;;	(a bit different than unix v7 inode flags)
   330                                  	;; regular file flag and dir flag must be 1 for a dir
   331                                  	;mov	al, [stbuf2+stat.mode+1]
   332                                  	;and	al, S_IFDIR|S_IFREG
   333                                  	;cmp	al, S_IFDIR|S_IFREG ; directory ?
   334                                  	;jne	short cp_8 ; no, overwrite (create file)
   335                                  			   ; (if the new file is not same file)
   336                                  
   337                                  	;; check if it is a device file
   338                                  	;;test	al, S_IFREG ; regular file ?
   339                                  	;;jz	short cp_error ; no
   340                                  	;;and	al, S_IFDIR ; directory ?
   341                                  	;;jz	short cp_error ; no
   342                                  
   343                                  	; 21/04/2022
   344                                  	; check (unix v1 inode) directory flag
   345 00000126 F605[5D030000]40        	test	byte [stbuf2+stat.mode+1], S_IFDIR ; directory ?
   346 0000012D 7441                    	jz	short cp_8 ; no, overwrite (create file)
   347                                  			   ; (if the new file is not same file)
   348                                  
   349                                  	; add (old) file name to (destination ) path
   350                                  	; (directory name +'/'+ file name)  
   351                                  	
   352 0000012F 89F5                    	mov	ebp, esi   ; save esi
   353 00000131 8B37                    	mov	esi, [edi] ; directory name address
   354 00000133 89FB                    	mov	ebx, edi   ; save edi			
   355 00000135 BF[A0030000]            	mov	edi, iobuf ; (new) path name buffer addr	
   356                                  
   357                                  	; p1 = from;
   358                                  	; p2 = to;
   359                                  	; bp = iobuf;
   360                                  cp_5:	; while(*bp++ = *p2++)
   361 0000013A AC                      	lodsb	
   362 0000013B AA                      	stosb
   363 0000013C 20C0                    	and	al, al
   364 0000013E 75FA                    	jnz	short cp_5
   365 00000140 C647FF2F                	mov	byte [edi-1], '/' ; bp[-1] = '/';
   366                                  	; p2 = bp
   367 00000144 89FA                    	mov	edx, edi
   368 00000146 8B7500                  	mov	esi, [ebp] ; *p1 ; from
   369                                  cp_6:	; while(*bp = *p1++)
   370 00000149 AC                      	lodsb
   371 0000014A AA                      	stosb
   372 0000014B 08C0                    	or	al, al
   373 0000014D 7408                    	jz	short cp_7
   374 0000014F 3C2F                    	cmp	al, '/' ; if (*bp++ == '/')
   375 00000151 75F6                    	jne	short cp_6
   376                                  	; bp = p2
   377                                  	; 21/04/2022
   378 00000153 89D7                    	mov	edi, edx ; (discard path before file name)
   379 00000155 EBF2                    	jmp	short cp_6
   380                                  cp_7:	
   381 00000157 89EE                    	mov	esi, ebp ; restore esi
   382 00000159 89DF                    	mov	edi, ebx ; restore edi
   383                                  	; to = iobuf
   384 0000015B BD[A0030000]            	mov	ebp, iobuf
   385                                  		
   386                                  	sys	_stat, ebp, stbuf2  ; stat(to, &stbuf2) >= 0
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000160 89EB                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 00000162 B9[5A030000]        <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000167 B812000000          <1>  mov eax, %1
    88 0000016C CD30                <1>  int 30h
   387 0000016E 723E                    	jc	short cp_10 ; create new file
   388                                  
   389                                  cp_8:
   390                                  	;if (stbuf1.st_dev == stbuf2.st_dev &&
   391                                  	;   stbuf1.st_ino == stbuf2.st_ino) {
   392                                  	;	fprintf(stderr, "cp: cannot copy file to itself.\n");
   393                                  	; 	return(1);
   394                                  
   395                                  	; 17/06/2024
   396                                  	; 09/05/2022 (retro unix 386 v1.2 kernel modification)
   397                                  	; (is same device ?)
   398                                  	; ((device number: eax return from sysstat))
   399                                  	; eax = [idev2]
   400                                  
   401 00000170 3B05[9E030000]          	cmp	eax, [idev1]
   402 00000176 7536                    	jne	short cp_10
   403                                  
   404 00000178 66A1[7C030000]          	mov	ax, [stbuf1+stat.inode]
   405 0000017E 663B05[5A030000]        	cmp	ax, [stbuf2+stat.inode]
   406 00000185 7527                    	jne	short cp_10
   407                                  
   408                                  	; same file ! error...
   409 00000187 BD[E6020000]            	mov	ebp, cncis_err_msg ; error message
   410                                  	; esi = file name (from)
   411                                  write_err_msg:
   412                                  	sys	_msg, ebp, 255, 07h
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 0000018C 89EB                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 0000018E B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 00000193 BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000198 B823000000          <1>  mov eax, %1
    88 0000019D CD30                <1>  int 30h
   413                                  	; close (old) file
   414                                  	sys	_close, [fold]
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 0000019F 8B1D[52030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000001A5 B806000000          <1>  mov eax, %1
    88 000001AA CD30                <1>  int 30h
   415 000001AC F9                      	stc	; return with error (cf=1)
   416 000001AD C3                      	retn
   417                                  
   418                                  cp_9:
   419                                  	; 22/04/2022
   420                                  	; ebp = [edi]
   421                                  	; 21/04/2022
   422                                  	; new file (asciiz name address)
   423                                  	;mov	ebp, [edi]
   424                                  
   425                                  	; create new file (truncate if it exists) 
   426                                  cp_10:
   427                                  	; fnew = creat(to, mode)
   428 000001AE 0FB70D[7E030000]        	movzx 	ecx, word [stbuf1+stat.mode]
   429                                  	; ecx = mode 
   430                                  	sys	_creat, ebp 
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000001B5 89EB                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000001B7 B808000000          <1>  mov eax, %1
    88 000001BC CD30                <1>  int 30h
   431 000001BE 733B                    	jnc	short cp_11
   432                                  
   433                                  	;if ((fnew = creat(to, mode)) < 0) {
   434                                  	;	fprintf(stderr, "cp: cannot create %s\n", to);
   435                                  	;	close(fold);
   436                                  	;	return(1);
   437                                  
   438                                  	; 24/04/2022
   439                                  	sys	_close, [fold]
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000001C0 8B1D[52030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000001C6 B806000000          <1>  mov eax, %1
    88 000001CB CD30                <1>  int 30h
   440                                  	
   441                                  	; error message
   442                                  	sys	_msg, ccf_err_msg, 255, 07h
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000001CD BB[0A030000]        <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 000001D2 B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 000001D7 BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000001DC B823000000          <1>  mov eax, %1
    88 000001E1 CD30                <1>  int 30h
   443                                  
   444                                  	; 24/04/2022
   445                                  	; and file name (to) -at the end of error message-
   446                                  	sys	_msg, ebp, 255, 07h 
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 000001E3 89EB                <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 000001E5 B9FF000000          <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 000001EA BA07000000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 000001EF B823000000          <1>  mov eax, %1
    88 000001F4 CD30                <1>  int 30h
   447                                  	; write next line (move cursor to next line)
   448                                  	; and return (from this/copy subroutine)
   449 000001F6 E9E0FEFFFF              	jmp	write_nl
   450                                  
   451                                  cp_11:	
   452                                  	; 21/04/2022 
   453 000001FB A3[56030000]            	mov	[fnew], eax
   454                                  cp_rw_next:
   455                                  	; while(n = read(fold, iobuf, BSIZE))
   456                                  	sys	_read, [fold], iobuf, BSIZE
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000200 8B1D[52030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 00000206 B9[A0030000]        <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 0000020B BA00020000          <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000210 B803000000          <1>  mov eax, %1
    88 00000215 CD30                <1>  int 30h
   457 00000217 7317                    	jnc	short cp_12
   458                                  
   459                                  	;if (n < 0) {
   460                                  	;   fprintf(stderr, "cp: read error\n");
   461                                  
   462                                  	; write read error message
   463 00000219 BD[1F030000]            	mov	ebp, crd_err_msg
   464                                  
   465                                  cp_rw_err:
   466                                  	; 21/04/2022
   467                                  	; cf = 1
   468                                  	sys	_close, [fnew]	
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 0000021E 8B1D[56030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000224 B806000000          <1>  mov eax, %1
    88 00000229 CD30                <1>  int 30h
   469 0000022B E95CFFFFFF              	jmp	write_err_msg
   470                                  
   471                                  cp_12:
   472                                  	; eax = read count
   473                                  	; eax = 0 -> eof
   474 00000230 09C0                    	or	eax, eax
   475 00000232 7423                    	jz	short cp_14 ; eof
   476                                  
   477 00000234 89C5                    	mov	ebp, eax  ; n	
   478                                  	; write(fnew, iobuf, n)
   479                                  	sys	_write, [fnew], iobuf, ebp
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000236 8B1D[56030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80 0000023C B9[A0030000]        <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83 00000241 89EA                <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 00000243 B804000000          <1>  mov eax, %1
    88 00000248 CD30                <1>  int 30h
   480 0000024A 7204                    	jc	short cp_13
   481                                  
   482                                  	;if (write(fnew, iobuf, n) != n)
   483                                  	;   fprintf(stderr, "cp: write error.\n");
   484                                  	;   close(fold);
   485                                  	;   close(fnew);
   486                                  	;   return(1);
   487                                  
   488                                  	; eax = written bytes
   489 0000024C 39E8                    	cmp	eax, ebp
   490                                  	;je	short cp_11 ; read next (block)
   491                                  	; 21/04/2022
   492 0000024E 74B0                    	je	short cp_rw_next
   493                                  	; error !
   494                                  	; eax < ebp --> cf = 1
   495                                  cp_13:
   496                                  	; close new file
   497                                  	; and then write error mesage
   498                                  	; and then close old file
   499                                  	; and then write (move cursor to) next line
   500                                  	; and then return (from subroutine) 
   501                                  	;sys	_close, [fnew]
   502                                  
   503                                  	; write error message
   504 00000250 BD[33030000]            	mov	ebp, cwr_err_msg
   505                                  	;jmp	short write_err_msg
   506                                  	; 21/04/2022
   507 00000255 EBC7                    	jmp	short cp_rw_err
   508                                  
   509                                  	; eof
   510                                  cp_14:
   511                                  	;close(fold);
   512                                  	;close(fnew);
   513                                  	;return(0);
   514                                  	
   515                                  	sys	_close, [fold]
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000257 8B1D[52030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 0000025D B806000000          <1>  mov eax, %1
    88 00000262 CD30                <1>  int 30h
   516                                  	sys	_close, [fnew]
    74                              <1> 
    75                              <1> 
    76                              <1> 
    77                              <1>  %if %0 >= 2
    78 00000264 8B1D[56030000]      <1>  mov ebx, %2
    79                              <1>  %if %0 >= 3
    80                              <1>  mov ecx, %3
    81                              <1> 
    82                              <1>  %if %0 >= 4
    83                              <1>  mov edx, %4
    84                              <1>  %endif
    85                              <1>  %endif
    86                              <1>  %endif
    87 0000026A B806000000          <1>  mov eax, %1
    88 0000026F CD30                <1>  int 30h
   517                                  	
   518                                  	;clc
   519 00000271 C3                      	retn
   520                                  	
   521                                  ;-----------------------------------------------------------------
   522                                  ;  data - initialized data
   523                                  ;-----------------------------------------------------------------
   524                                  
   525                                  ;argc:	dd 0
   526 00000272 00                      argc:	db 0
   527                                  
   528                                  ; ----------------------------------------------------------------
   529                                  
   530                                  program_msg:
   531 00000273 0D0A                    	db  0Dh, 0Ah
   532 00000275 526574726F20554E49-     	db  'Retro UNIX 386 v1 COPY by Erdogan TAN - 17/06/2024'
   532 0000027E 582033383620763120-
   532 00000287 434F50592062792045-
   532 00000290 72646F67616E205441-
   532 00000299 4E202D2031372F3036-
   532 000002A2 2F32303234         
   533 000002A7 0D0A00                  	db  0Dh, 0Ah, 0
   534                                  
   535                                  usage_msg:
   536 000002AA 0D0A                    	db  0Dh, 0Ah
   537 000002AC 55736167653A206370-     	db  'Usage: cp: f1 f2; or cp f1 ... fn d2'
   537 000002B5 3A2066312066323B20-
   537 000002BE 6F7220637020663120-
   537 000002C7 2E2E2E20666E206432 
   538                                  nextline:
   539 000002D0 0D0A00                  	db  0Dh, 0Ah, 0
   540                                  
   541                                  cno_err_msg:
   542 000002D3 0D0A                    	db 0Dh, 0Ah
   543 000002D5 63703A2063616E6E6F-     	db 'cp: cannot open '
   543 000002DE 74206F70656E20     
   544 000002E5 00                      	db 0
   545                                  cncis_err_msg:
   546 000002E6 0D0A                    	db 0Dh, 0Ah
   547 000002E8 63703A2063616E6E6F-     	db 'cp: cannot copy file to itself.'
   547 000002F1 7420636F7079206669-
   547 000002FA 6C6520746F20697473-
   547 00000303 656C662E           
   548 00000307 0D0A00                  	db 0Dh, 0Ah, 0
   549                                  
   550                                  ccf_err_msg:
   551 0000030A 0D0A                    	db 0Dh, 0Ah
   552 0000030C 63703A2063616E6E6F-     	db 'cp: cannot create '
   552 00000315 742063726561746520 
   553 0000031E 00                      	db 0
   554                                  
   555                                  crd_err_msg:
   556 0000031F 0D0A                    	db 0Dh, 0Ah
   557 00000321 63703A207265616420-     	db 'cp: read error.'
   557 0000032A 6572726F722E       
   558 00000330 0D0A00                  	db 0Dh, 0Ah, 0
   559                                  
   560                                  cwr_err_msg:
   561 00000333 0D0A                    	db 0Dh, 0Ah
   562 00000335 63703A207772697465-     	db 'cp: write error.'
   562 0000033E 206572726F722E     
   563 00000345 0D0A00                  	db 0Dh, 0Ah, 0
   564                                  
   565                                  ok_msg:
   566 00000348 0D0A                    	db  0Dh, 0Ah
   567 0000034A 4F4B2E                  	db  'OK.'
   568 0000034D 0D0A00                  	db  0Dh, 0Ah, 0
   569                                  
   570 00000350 00                      errors:	db 0
   571                                  
   572                                  ;-----------------------------------------------------------------
   573                                  ;  bss - uninitialized data
   574                                  ;-----------------------------------------------------------------
   575                                  
   576 00000351 90                      align 2
   577                                  
   578                                  bss_start:
   579                                  
   580                                  ABSOLUTE bss_start
   581                                  
   582                                  ; 20/04/2022
   583 00000352 ????????                fold:	resd 1
   584 00000356 ????????                fnew:	resd 1
   585                                  
   586                                  ;stbuf2: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data)
   587                                  ;stbuf1: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data)
   588                                  ; 21/04/2022
   589 0000035A <res 22h>               stbuf2: resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data)
   590 0000037C <res 22h>               stbuf1: resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data)
   591                                  ; 17/06/2024
   592 0000039E ????                    idev1:	resw 1 ; device number (0= root, >0 or 1 = mounted)
   593                                  ;idev2:	resw 1 ; device number (0= root, >0 or 1 = mounted)
   594                                  
   595 000003A0 <res 200h>              iobuf:	resb BSIZE ; resb 512 ; path name buffer
   596                                  
   597                                  ; 20/04/2022
   598                                  ;-----------------------------------------------------------------
   599                                  ; Original UNIX v7 - cp (utility) c source code (cp.c)
   600                                  ;-----------------------------------------------------------------
   601                                  ;/* UNIX V7 source code: see www.tuhs.org for details. */;
   602                                  ;
   603                                  ;/*
   604                                  ; * cp oldfile newfile
   605                                  ; */
   606                                  ;
   607                                  ;#define BSIZE	512
   608                                  ;#include <stdio.h>
   609                                  ;#include <sys/types.h>
   610                                  ;#include <sys/stat.h>
   611                                  ;struct	stat stbuf1, stbuf2;
   612                                  ;char iobuf[BSIZE];
   613                                  ;
   614                                  ;main(argc, argv)
   615                                  ;char *argv[];
   616                                  ;{
   617                                  ;	register i, r;
   618                                  ;
   619                                  ;	if (argc < 3) 
   620                                  ;		goto usage;
   621                                  ;	if (argc > 3) {
   622                                  ;		if (stat(argv[argc-1], &stbuf2) < 0)
   623                                  ;			goto usage;
   624                                  ;		if ((stbuf2.st_mode&S_IFMT) != S_IFDIR) 
   625                                  ;			goto usage;
   626                                  ;	}
   627                                  ;	r = 0;
   628                                  ;	for(i=1; i<argc-1;i++)
   629                                  ;		r |= copy(argv[i], argv[argc-1]);
   630                                  ;	exit(r);
   631                                  ;usage:
   632                                  ;	fprintf(stderr, "Usage: cp: f1 f2; or cp f1 ... fn d2\n");
   633                                  ;	exit(1);
   634                                  ;}
   635                                  ;
   636                                  ;copy(from, to)
   637                                  ;char *from, *to;
   638                                  ;{
   639                                  ;	int fold, fnew, n;
   640                                  ;	register char *p1, *p2, *bp;
   641                                  ;	int mode;
   642                                  ;	if ((fold = open(from, 0)) < 0) {
   643                                  ;		fprintf(stderr, "cp: cannot open %s\n", from);
   644                                  ;		return(1);
   645                                  ;	}
   646                                  ;	fstat(fold, &stbuf1);
   647                                  ;	mode = stbuf1.st_mode;
   648                                  ;	/* is target a directory? */
   649                                  ;	if (stat(to, &stbuf2) >=0 &&
   650                                  ;	   (stbuf2.st_mode&S_IFMT) == S_IFDIR) {
   651                                  ;		p1 = from;
   652                                  ;		p2 = to;
   653                                  ;		bp = iobuf;
   654                                  ;		while(*bp++ = *p2++)
   655                                  ;			;
   656                                  ;		bp[-1] = '/';
   657                                  ;		p2 = bp;
   658                                  ;		while(*bp = *p1++)
   659                                  ;			if (*bp++ == '/')
   660                                  ;				bp = p2;
   661                                  ;		to = iobuf;
   662                                  ;	}
   663                                  ;	if (stat(to, &stbuf2) >= 0) {
   664                                  ;		if (stbuf1.st_dev == stbuf2.st_dev &&
   665                                  ;		   stbuf1.st_ino == stbuf2.st_ino) {
   666                                  ;			fprintf(stderr, "cp: cannot copy file to itself.\n");
   667                                  ;			return(1);
   668                                  ;		}
   669                                  ;	}
   670                                  ;	if ((fnew = creat(to, mode)) < 0) {
   671                                  ;		fprintf(stderr, "cp: cannot create %s\n", to);
   672                                  ;		close(fold);
   673                                  ;		return(1);
   674                                  ;	}
   675                                  ;	while(n = read(fold,  iobuf,  BSIZE)) {
   676                                  ;		if (n < 0) {
   677                                  ;			fprintf(stderr, "cp: read error\n");
   678                                  ;			close(fold);
   679                                  ;			close(fnew);
   680                                  ;			return(1);
   681                                  ;		} else
   682                                  ;			if (write(fnew, iobuf, n) != n) {
   683                                  ;				fprintf(stderr, "cp: write error.\n");
   684                                  ;				close(fold);
   685                                  ;				close(fnew);
   686                                  ;				return(1);
   687                                  ;			}
   688                                  ;	}
   689                                  ;	close(fold);
   690                                  ;	close(fnew);
   691                                  ;	return(0);
   692                                  ;}
