 
#include "dir.h"
#include "backup.h"


extern char *strsave ();


struct dir_st *
getdir ( path )
char *path;
{
	struct DPTR *dptr;
	int dir;
	char *name;
	struct DateStamp date;
	struct dir_st **pp;
	struct dir_st *p;
	struct dir_st *next;
	struct dir_st *head;

	dptr = dopen ( path , &dir );
	if ( dptr == NULL ) {
		printf ( "Failed to open directory '%s'\n" , path );
		return ( NULL );
	}
	if ( ! dir ) {
		printf ( "'%s' is a file, not a directory\n" , path );
		return ( NULL );
	}
	head = (struct dir_st *) malloc ( sizeof ( struct dir_st ) );
	if ( head == NULL ) {
		puts ( "Out of memory!" );
		return ( NULL );
	}
	head->filename = strsave ( path );
	head->dir = dir;
	head->date = dptr->fib->fib_Date;
	head->next = NULL;
	pp = &head->next;
	while ( dnext ( dptr , &name , &dir , &date ) ) {

		/* ignore .dobackup files - dont want to accidently override */
		/* any existing file */

		if ( strcmp ( name , DO_BACKUP ) == 0 )
			continue;

		p = (struct dir_st *) malloc ( sizeof ( struct dir_st ) );
		if ( p == NULL
		||  ( p->filename = strsave ( name ) ) == NULL ) {
			for ( p = head; p != NULL; p = next ) {
				next = p->next;
				free ( p->filename );
				free ( p );
			}
			puts ( "Out of memory!" );
			return ( NULL );
		}
		p->dir = dir;
		p->date = date;
		p->next = NULL;
		*pp = p;
		pp = &p->next;
	}
	dclose ( dptr );
	return ( head );
}


void
freedir ( dir )
struct dir_st *dir;
{
	struct dir_st *p , *next;

	for ( p = dir; p != NULL; p = next ) {
		next = p->next;
		free ( p->filename );
		free ( p );
	}
}


/*
 * Disk directory routines
 *
 * dptr = dopen(name, stat)
 *    struct DPTR *dptr;
 *    char *name;
 *    int *stat;
 *
 * dnext(dptr, name, stat, date)
 *    struct DPTR *dptr;
 *    char **name;
 *    int  *stat;
 *    struct DateStamp *date;
 *
 * dclose(dptr)                  -may be called with NULL without harm
 *
 * dopen() returns a struct DPTR, or NULL if the given file does not
 * exist.  stat will be set to 1 if the file is a directory.  If the
 * name is "", then the current directory is openned.
 *
 * dnext() returns 1 until there are no more entries.  The **name and
 * *stat are set.  *stat = 1 if the file is a directory.
 *
 * dclose() closes a directory channel.
 *
 */
 
struct DPTR *
dopen(name, stat)
char *name;
int *stat;
{
	struct DPTR *dp;
	int namelen, endslash = 0;

	namelen = strlen(name);
	if (namelen && name[namelen - 1] == '/') { 
		name[namelen - 1] = '\0';           
		endslash = 1;
	}
	*stat = 0;
    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
    dp->lock = Lock (name, (LONG)ACCESS_READ);
    if (endslash)
        name[namelen - 1] = '/';
    if (dp->lock == '\0') {
        free (dp);
        return (NULL);
    }
    dp->fib = (struct FileInfoBlock *)
         AllocMem((LONG)sizeof(struct FileInfoBlock), (LONG)MEMF_PUBLIC);
    if (!Examine (dp->lock, dp->fib)) {
        perror (name);
        dclose (dp);
        return (NULL);
    }
    if (dp->fib->fib_DirEntryType >= 0)
        *stat = 1;
	return (dp);
}
 
dnext(dp, pname, stat, date)
struct DPTR *dp;
char **pname;
int *stat;
struct DateStamp *date;
{
	if (dp == NULL)
		return (0);
	if (ExNext (dp->lock, dp->fib)) {
		*stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
		*date = dp->fib->fib_Date;
		*pname = dp->fib->fib_FileName;
		return (1);
	}
	return (0);
}
 
 
dclose(dp)
struct DPTR *dp;
{
	if (dp == NULL)
		return (1);
	if (dp->fib)
		FreeMem (dp->fib, (LONG)sizeof(*dp->fib));
	if (dp->lock)
		UnLock (dp->lock);
	free (dp);
	return (1);
}
