PC-DOS/MS-DOS `touch' command
Gino Bloch
gino at voder.UUCP
Tue Oct 2 02:56:15 AEST 1984
[don't touch this line]
A while back someone asked how to touch(*) a file under PC-DOS. Since I
had a need for that capability, I wrote a program to do that; here it is.
* ie, change its date & time fields to the current time without any
other changes - useful with a `make' facility, for instance.
...................... tear on the dotted line .........................
title "touch files"
page ,132
; Touch changes the date & time of directory entries to the current
; date & time. It requires one argument (and ignores extra arguments).
; The argument is the full path name of a file. You can also specify
; a set of files by using wild card characters in the file name portion,
; but not the path name portion, of the argument. In the absence of path
; name specifiers, only the default directory is searched. In the absence
; of a drive name specifier, only the default drive is searched. Thus there
; are four ways to invoke touch; `d:\dd' means the default drive and its
; default directory, and `x:\xd' means some other drive and its default
; directory:
; touch file.ext affects d:\dd\file.ext
; touch x:file.ext affects x:\xd\file.ext
; touch \path\file.ext affects d:\path\file.ext
; touch x:\path\file.ext affects x:\path\file.ext
; In all four cases, `file.ext' can contain `?' and `*' characters by the
; usual rules.
; Copyright (C) 1984 by Gene E. Bloch
assume ds:dseg,ss:sseg
sseg segment stack 'stack'
db 512 dup (?)
stk equ $
sseg ends
dseg segment 'data'
no_file db 'touch: file not found',0dh,0ah,'$'
no_tail db 'syntax: touch file_descriptor (may be ambiguous)',0dh,0ah,'$'
unopen db " (can't be opened)$"
crlf db 0dh,0ah,'$'
clk_time dw 2 dup (?)
clk_date dw 2 dup (?)
file_time dw ?
file_date dw ?
handle dw ?
file_name db 80h dup (?),'$'
name_end equ $
name_tail dw file_name
dseg ends
cseg segment 'code'
assume cs:cseg
; main
touch:
mov ax,dseg ; set up ds
mov ds,ax
call read_clok ; set up current date & time
call set_date
call set_time
call find_first ; get first file name
jnz short err_out ; no file, analyze error
more:
call make_name ; make up the full path name
call show_name ; print the full path name
call open ; open the file
jnc short open_ok ; successful
mov dx,offset unopen ; unsuccessful, report it
mov ah,9
int 21h
jmp short finder ; and skip the rest
open_ok:
call touch_it ; re-date & -time the file
call close ; close it
finder:
mov dx,offset crlf ; newline
mov ah,9
int 21h
call find_next ; try to get next file
je short more ; got one, touch it
done:
mov ah,4ch ; exit
mov al,0
int 21h
err_out:
mov dx,offset no_file ; get `no file found' message
jg short print_it
mov dx,offset no_tail ; get `no command tail' message
print_it:
mov ah,9 ; print string
int 21h
jmp done ; bye
; subroutines
read_clok:
mov ah,2ch ; get clock time
int 21h
mov clk_time,cx
mov clk_time[2],dx
mov ah,2ah ; get clock date
int 21h
mov clk_date,cx
mov clk_date[2],dx
ret
set_date:
mov ax,clk_date ; convert date to directory fmt
sub ax,1980 ; year first
mov cl,9
shl ax,cl
mov bx,clk_date[2] ; month next
mov cl,3
shr bx,cl
or ax,bx
and ax,0ffe0h
mov bx,clk_date[2] ; finally day
and bl,1fh
or al,bl
mov file_date,ax ; that's it
ret
set_time:
mov ax,clk_time ; convert time to directory format
mov cl,3 ; hours
shl ax,cl
and ax,0f800h
mov bh,byte ptr clk_time ; minutes
mov cl,3
shr bx,cl
or ax,bx
and ax,0ffe0h
mov bl,byte ptr clk_time[3] ; seconds
shr bl,1
or al,bl
mov file_time,ax ; done
ret
printable:
cmp al,'!' ; see if legal
jb short p_done ; no
cmp al,7fh ; more legality
ja short p_done ; no printable
cmp al,al ; set flag 0 == ok
p_done: ret
to_upper:
cmp al,'a' ; convert to UC
jb short uc_end ; this isn't lc
cmp al,'z'
ja short uc_end ; nor is this
xor al,'a' xor 'A' ; this one was
uc_end: ret
file_delim:
cmp al,':' ; could be drive designator
je short set_mark ; if so, make a mark
cmp al,'\' ; could be subdirectory
je short set_mark ; yeah
cmp al,'/' ; even this kind of subdirectory
jne short fd_end ; no
set_mark:
mov bx,di ; remember this place
mov es:name_tail,bx
fd_end: ret
find_first:
cld ; copy filename from parameter block
mov ch,0 ; set up count
mov cl,es:[80h] ; get the arg length for loops below
push ds ; save ds
push es ; save es
push es ; point ds & si to command tail in PSP
pop ds
mov si,81h
mov ax,dseg ; point es & di to file_name buffer
mov es,ax
mov di,offset file_name
blank_loop:
jcxz short no_arg ; still trucking?
dec cx ; loop counter
lodsb ; skip white space
cmp al,' ' ; space
je blank_loop
cmp al,9 ; tab
je blank_loop
or al,al ; look out for spacy args
jz short no_arg
dec si ; get last (nonblank) char back
inc cx ; and count it
copy_loop:
lodsb ; get next char
call printable ; see if printable
jnz short copy_end ; not printable
call to_upper ; all letters to UPPERCASE
stosb ; good character, save it
call file_delim ; remember the last tree delimiter
cl_end:
loop copy_loop ; continue
copy_end:
xor al,al ; add the terminating null
stosb
pop es ; restore extra seg
pop ds ; restore data seg
mov dx,offset file_name ; set up find_first call
mov cx,0 ; attribute: normal files only
mov ah,4eh
int 21h
or ax,ax ; set condition code
ret
no_arg:
pop es ; restore extra seg
pop ds ; restore data seg
mov ax,-1 ; set an error flag
or ax,ax
ret
make_name:
push es ; save the hummers
push ds
mov ah,2fh ; find the DTA
int 21h
push es ; we'll need this value in just a mo'
mov ax,name_tail ; this is where new name will go
mov di,ax
mov ax,dseg
mov es,ax
add bx,30 ; point to file name field of DTA
mov si,bx ; source of the copy
pop ds ; this was pushed right after int 21/2f
cld
mov cx,13 ; max size of filename
name_loop:
lodsb ; copy name to path prefix
stosb
or al,al ; quit on '\0'
loopnz name_loop
name_done:
mov al,'$' ; terminate the print command
stosb
pop ds ; restore segments
pop es
ret
show_name:
mov dx,offset file_name ; get file name string
mov ah,9 ; print string
int 21h
ret
open:
mov dx,offset file_name ; going to open this one
mov al,2 ; open for append
mov ah,3dh
int 21h
mov handle,ax ; save it
ret
touch_it:
mov dx,file_date ; set file's date & time
mov cx,file_time
mov bx,handle
mov ah,57h
mov al,1
int 21h
ret
close:
mov bx,handle ; close this one
mov ah,3eh
int 21h
ret
find_next:
mov ah,4fh ; set up find_next call
int 21h
or ax,ax ; set condition code
ret
cseg ends
end touch
--
Gene E. Bloch (...!nsc!voder!gino)
More information about the Comp.sources.unix
mailing list