[net.micro.pc] CALLING ALL DOS 2.0 EXPERTS

geller@rlgvax.UUCP (David Geller) (02/15/84)

I'm an IBM PC DOS 2.0 / Lattice "C" (ver 2.0-d) user and I would
like to know how to get a directory listing of both root and sub-
directories, preferably through Lattice/Microsoft "C".

It would help if I knew, without dissassembling, how DIR and TREE
worked. I suspect that they both use the DOS interupts to search
for and continue a directory search, however I'm not at all sure.

I would appreciate any help that you could offer. I'll post a
follow-up article to this query as soon as I receive some help.
Thanks in advance,


	{seismo}!rlgvax!geller	David Geller
				Computer Consoles, Inc.
				Office Systems Group
				1760 Reston Avenue
				Reston, VA  22090

				703-471-6860

jph@whuxle.UUCP (02/23/84)

#R:rlgvax:-171200:whuxle:22700016:000:6083
whuxle!jph    Feb 18 21:35:00 1984

Here is the source code for WHEREIS which takes a file name
of pattern (e.g., *.BAS) as an argument and finds where it
is in the file system by starting at the root and working it
way down through all the sub-directories. You might take
this algorithm and use it in your function for C. I obtained
this from a BBS.
============================================

title WHEREIS
page	62,132
cgroup	group	code_seg,data_seg
	assume	cs:cgroup,ds:cgroup

;this is the format for the dos data transfer area used when dos 2.0
;searches for file match in directories

dta	struc
	reserved	db	21 dup (?)
	attribute	db
	time		dw
	date		dw
	size		dd
	name_found	db	13 dup (?)
dta	ends

data_seg	segment public
star_name	db	'*.*',0
path_name	db	'\',0
		db	80 dup (0)	;space for 64 char pathname and
					;13 char filename
file_name	db	13 dup (0)	;save room for full dos filename
disk_transfer_areas label byte		;this starts at the end of whereis
data_seg	ends

;  this is the main program that sets up the initial conditions for
;  search_directory which in turn, does a recursive search.
;	reads:	path_name
;	writes: file_name
;	calls:	search_directory
;
code_seg	segment
		org	100h
whereis proc	near
	mov	si, 82h 		;start of command line
	mov	di, offset cgroup:file_name

wh10:	lodsb				;get first char
	cmp	al, 0dh
	je	wh20			;if carriage return
	stosb
	jmp	wh10			;Loop --

wh20:	xor	al,al			;store zero at end
	stosb
	mov	di, offset cgroup:path_name
	xor	al, al
	cld
	mov	cx, 64
  repnz scasb
	mov	bx,di
	dec	bx			;ds:bx points to end of path_name
	mov	dx, 0
	call search_directory
	int	20h
whereis endp

; this procedure searches all the files in the current directory
; looking for a match.	It also prints the full name for each match
;
;	ds:bx	pointer to end of current path name
;	ds:dx	old disk transfer area (dta)
;
; reads:	disk transfer area (dta)
; writes:	disk transfer area (dta)
; calls 	build_name, get_first_Match
;		write_matched_name, get_next_match
;		build_star_name, search_sub_directory
;
search_directory proc	near

	push	si
	push	dx
	call	build_name
	call	get_first_match
	jc	sd20				;If no match --
	call	write_matched_name
sd10:	call	get_next_match
	jc	sd20
	call	write_matched_name
	jmp	sd10				;Loop --

sd20:	pop	dx
	push	dx
	call	build_star_name
	call	get_first_match
	jc	sd50				;If no match --
	mov	si,dx
	test	[si].attribute,10h
	jnz	sd40				;If directory entry --
sd30:	call	get_next_match
	jc	sd50				;If no more entries --
	test	[si].attribute,10h
	jz	sd30				;If not a directory --
sd40:	cmp	[si].name_found,'.'
	je	sd30				;If it's . or ..
	call	search_sub_directory		;search sub directory
	push	ax
	mov	ah,1ah
	int	21h
	pop	ax
	jmp	sd30

sd50:	pop	dx
	pop	si
	ret

search_directory  endp
page
; This procedure searches the sub directory who's name is in dta
;
;	ds:bx	end of the current pathname
;	ds:[dx].name_found	name of subdirectory for search
;
; reads:	path_name
; writes:	path_name
; calls:	search_directory
;

search_sub_directory  proc  near

	push	di
	push	si
	push	ax
	push	bx
	cld
	mov	si, dx
	add	si, offset name_found
	mov	di,bx
ss10:	lodsb
	stosb
	or	al,al
	jnz	ss10
	mov	bx,di
	std
	stosb
	mov	al,'\'
	stosb
	call	search_directory
	pop	bx
	mov	byte ptr [bx], 0
	pop	ax
	pop	si
	pop	di
	ret

search_sub_directory  endp
page

; This procedure prints the matched name after the path name
;
;  ds:dx	pointer to current disk transfer area
;
; reads:	path_name, name_found (in dta)
; writes:	write_string, send_crlf
;

write_matched_name	proc	near

	push	ax
	push	dx
	mov	dx,offset cgroup:path_name
	mov	al,[bx]
	mov	byte ptr [bx],0
	call	write_string
	mov	[bx],al
	pop	dx
	push	dx
	add	dx, offset name_found
	call	write_string
	call	send_crlf
	pop	dx
	pop	ax
	ret
write_matched_name endp


;  This procedure builds an absolute search name from path_name
;  followed by file_name
;
;  reads:	file_name
;  calls:	build	(to build the name)
;

build_name	proc	near

	push	si
	mov	si, offset cgroup:file_name
	call	build
	pop	si
	ret
build_name	endp

build_star_name proc	near
	push	si
	mov	si, offset cgroup:star_name
	call	build
	pop	si
	ret
build_star_name endp

page
; This procedure appends the string at ds:si to path_name in
; path_name.  It knows where the path name ends from knowing
; how long path_name is.
;
;	ds:si	name of file
;	ds:bx	end of path_name
;
; reads:	ds:si
; writes:	path_name
;

build	proc	near
	push	ax
	push	di
	mov	di,bx
	cld
bd10:	lodsb
	stosb
	or	al,al
	jnz	bd10			;If not end of string yet --
	pop	di
	pop	ax
	ret
build	endp

; This procedure find the first match between the name given by
; ds:dx and the directory entries found in the directory path_name
;
;	ds:dx	pointer to current disk transfer area
;
;  returns:
;	cf	0	a match was found
;		1	no match found
;	ax		error code returned
;		2	file not found
;		18	no more files
;	ds:dx		pointer to new disk transfer area
;
; reads:	path_name
; writes:	disk_transfer_areas
;

get_first_match proc	near

	push	cx
	cmp	dx,0
	ja	gf10			;go allocate space --
	mov	dx, offset cgroup:disk_transfer_areas-type dta
gf10:	add	dx,type dta
	mov	cx,10h
	mov	ah,1ah
	int	21h
	push	dx
	mov	dx, offset cgroup:path_name
	mov	ah,4eh			;call for find first match
	int	21h
	pop	dx
	pop	cx
	ret
get_first_match endp


; This procedure is much line get_first_match
;
; returns:
;	cf	0	a match was found
;		1	no match found
;	ax		error code returned
;		2	file not found
;		18	no more files
;
; reads:	path_name
; writes:	disk_transfer_areas
;

get_next_match	proc	near

	push	cx
	push	dx
	mov	dx, offset cgroup:path_name
	mov	cx,10h
	mov	ah,4fh
	int	21h
	pop	dx
	pop	cx
	ret
get_next_match	endp

; This procedure sends a crlf pair of characters to the screen
;

send_crlf	proc	near

	push	ax
	push	dx
	mov	ah,02
	mov	dl,0ah
	int	21h
	mov	dl,0dh
	int	21h
	pop	dx
	pop	ax
	ret
send_crlf	endp

; This procedure writes the asciiz string at
;  ds:dx	address of asciiz string
;

write_string	proc	near

	push	ax
	push	dx
	push	si
	cld
	mov	si,dx
	mov	ah,2
	lodsb
ws10:	mov	dl,al
	int	21h
	lodsb
	or	al,al
	jnz	ws10
	pop	si
	pop	dx
	pop	ax
	ret
write_string	endp

code_seg	ends

	end	whereis