[comp.lang.c] Trying to C a directory.

root@mirror.TMC.COM (05/26/89)

I am having trouble trying to figure out how to read a directory in
MS-DOS.  I would like to be able to read in the directory contents
and then display them out onto the screen in a certain format.

No matter how I try to read the directory, I can't seem to get into
it.

I am using C, but if anyone knows how to read the directory, you can
explain it to me in pseudocode, or in pascal, or explain the situation
in general english.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
| Alex Haley was adopted!  |   Patrick McCartney                        |
|                          |   Mirror Systems                           |
|                          |   2067 Mass. Ave                           |
|                          |   Cambridge, MA  02140                     |
|                          |   (617)661-0777                            |
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

manes@marob.masa.com (Steve Manes) (05/28/89)

From article <236100013@mirror>, by root@mirror.TMC.COM:
> I am having trouble trying to figure out how to read a directory in
> MS-DOS.  I would like to be able to read in the directory contents
> and then display them out onto the screen in a certain format.

Why I Like Turbo-C: it has the two functions you need, findfirst and
findnext, already in the libraries.  There's also an example.

Alternatively, you will essentially need to recreate these functions
(something I had to do recently for a partner who refuses to do any DOS
programming except under VP/ix and Xenix) with DOS service calls. You
will also need to create two functions to get/save the current DTA and
to set a new DTA because the DTA is where DOS will dump each directory
record as it reads the disk.

Here's what I did (and it ain't purty).  You may need to tweak this for
your compiler.

--------cut here-----cut here------cut here------cut here------
#include <stdio.h>
#include <dos.h>

#define	D_RDONLY	0x01
#define	D_HIDDEN	0x02
#define	D_SYSTEM	0x04
#define	D_LABEL		0x08
#define	D_DIREC		0x10
#define	D_ARCHIVE	0x20

struct DOSDIR {
	char	ff_reserved[21];	/* reserved for DOS */
	char	ff_attrib;		/* DOS file attributes */
	int	ff_ftime;		/* file time */
	int	ff_fdate;		/* file date */
	long	ff_fsize;		/* file size */
	char	ff_name[13];		/* file name */
};

struct	DOSDIR	fcb;		/* FCB -- must maintain between calls! */

/* declarations */
void	get_dta( int *, int * ), set_dta( int, int );
int     dirfirst( char *name, struct DOSDIR *, int),
	dirnext( struct DOSDIR * );
	
main()
{
	int	done;
		
	printf("\nDirectory:\n");
	done = dirfirst("*.*", &fcb, D_ARCHIVE);
	while ( !done ) {
		printf("%s\n", fcb.ff_name);
		done = dirnext(&fcb);
	}
}

int	dirfirst( name, rec, attrib )
char	*name;
struct	DOSDIR	*rec;
int	attrib;
{
	union	REGS	inregs, outregs;
	struct	SREGS	segregs;
	int	dtaseg_old, dtaoff_old;
	int	rc;
					
	get_dta(&dtaseg_old, &dtaoff_old);	/* get current DTA */

	set_dta( FP_SEG(rec), FP_OFF(rec) );	/* set new DTA */
	
	inregs.h.ah = 0x4E;			/* get first match */
	inregs.x.cx = attrib;
	segregs.ds = FP_SEG(name);
	inregs.x.dx = FP_OFF(name);
	rc = intdosx(&inregs, &outregs, &segregs);
					
	set_dta( dtaseg_old, dtaoff_old);	/* reset DTA */
	return (outregs.x.cflag ? rc : 0 );
}

int	dirnext( rec )
struct	DOSDIR *rec;
{
	union	REGS	inregs, outregs;
	struct	SREGS	segregs;
	int	dtaseg_old, dtaoff_old;
	int	rc;
					
	get_dta(&dtaseg_old, &dtaoff_old);	/* get current DTA */
	set_dta( FP_SEG(rec), FP_OFF(rec) );	/* set new DTA */
	
	inregs.h.ah = 0x4F;			/* get next match */
	rc = intdosx(&inregs, &outregs, &segregs);
		
	set_dta(dtaseg_old, dtaoff_old);	/* reset DTA */
	return (outregs.x.cflag ? rc : 0 );
}
	
void	get_dta(segment, offset)
int	*segment, *offset;
{
	union	REGS inregs, outregs;
	struct	SREGS	segregs;
			
	inregs.h.ah = 0x2F;
	intdosx(&inregs, &outregs, &segregs);
	*segment = segregs.es;
	*offset  = outregs.x.bx;
}
					
void	set_dta(segment, offset)
int	segment, offset;
{
	union	REGS inregs;
	struct	SREGS	segregs;

	inregs.h.ah = 0x1A;
	segregs.ds  = segment;
	inregs.x.dx = offset;
	intdosx(&inregs, &inregs, &segregs);
}

-- 
Steve Manes            Roxy Recorders, Inc.             Magpie-HQ BBS
UUCP : {rutgers|cmcl2}!hombre!magpie!manes              (212)420-0527
Smail: manes@MASA.COM

scs@adam.pika.mit.edu (Steve Summit) (05/28/89)

In article <236100013@mirror> root@mirror.TMC.COM (Patrick McCartney) writes:
>I am having trouble trying to figure out how to read a directory in
>MS-DOS.  I would like to be able to read in the directory contents...

In article <708@marob.masa.com> manes@marob.masa.com (Steve Manes) writes:
>Why I Like Turbo-C: it has the two functions you need, findfirst and
>findnext, already in the libraries.  There's also an example.
>Alternatively, you will essentially need to recreate these functions
>with DOS service calls.

If you are at all interested in portability, the functions you
need are called opendir, readdir, and closedir, which neither
Microsoft nor (apparently) Borland have seen fit to provide.
These routines are in the POSIX standard and are the universally
recommended way of reading directories from within a C program.
Several implementations of MS-DOS opendir/readdir exist: I have
written one or two, which I can supply upon request; I have given
mine to Doug Gwyn for inclusion in his posted opendir/readdir
package; I have also heard that the FSF has an implementation so
that their tools can be ported to MS-DOS (if you have enough
memory :-) ).

                                            Steve Summit
                                            scs@adam.pika.mit.edu