/*
**  Copyright 2000-2004 University of Illinois Board of Trustees
**  Copyright 2000-2004 Mark D. Roth
**  All rights reserved.
**
**  ftpdir.c - FTP directory access code
**
**  Mark D. Roth <roth@feep.net>
*/

#include <internal.h>

#include <errno.h>

#ifdef STDC_HEADERS
# include <string.h>
# include <stdlib.h>
#endif


struct ftpdir
{
	fget_list_t *fd_l;	/* directory list */
	fget_listptr_t fd_lp;	/* internal pointer */
	off_t fd_offset;	/* number of entries scanned so far */
	unsigned short fd_eof;	/* boolean EOF indicator */
};


/* open directory */
int
ftp_opendir(FTPDIR **ftpdir, FTP *ftp, char *dir)
{
	file_info_t *fip;
	fget_hash_t *file_h;
	fget_hashptr_t hp;

#ifdef DEBUG
	printf("==> ftp_opendir(ftpdir=0x%lx, ftp=0x%lx, dir=\"%s\")\n",
	       ftpdir, ftp, dir);
#endif

	if (dir == NULL || strlen(dir) == 0)
	{
		errno = EINVAL;
		return -1;
	}

	if (_ftp_dircache_find_dir(ftp, dir, &file_h) == -1)
		return -1;

	if (file_h == NULL)
	{
		errno = EACCES;
		return -1;
	}

	*ftpdir = (FTPDIR *)calloc(1, sizeof(FTPDIR));
	if (*ftpdir == NULL)
		return -1;
	(*ftpdir)->fd_l = fget_list_new(LIST_QUEUE, NULL);
	fget_listptr_reset(&(*ftpdir)->fd_lp);

	fget_hashptr_reset(&hp);
	while (fget_hash_next(file_h, &hp) != 0)
	{
		fip = (file_info_t *)fget_hashptr_data(&hp);
		fget_list_add((*ftpdir)->fd_l, strdup(fip->fi_filename));
#ifdef DEBUG
		printf("    ftp_opendir(): fip->fi_filename = \"%s\"\n",
		       fip->fi_filename);
#endif
	}

#ifdef DEBUG
	printf("<== ftp_opendir(): success\n");
#endif

	return 0;
}


/* read directory */
int
ftp_readdir(FTPDIR *ftpdir, struct ftpdirent *ftpdirent)
{
	int retval;

#ifdef DEBUG
	printf("==> ftp_readdir(ftpdir=0x%lx, ftpdirent=0x%lx)\n",
	       ftpdir, ftpdirent);
#endif

	if (ftpdir->fd_eof)
		return 0;

	ftpdir->fd_offset++;

	retval = fget_list_next(ftpdir->fd_l, &ftpdir->fd_lp);
	if (retval == 0)
		ftpdir->fd_eof = 1;
	else
		ftpdirent->fd_name = (char *)fget_listptr_data(&ftpdir->fd_lp);

#ifdef DEBUG
	printf("<== ftp_readdir(): returning %d (ftpdirent->fd_name=\"%s\")\n",
	       retval, ftpdirent->fd_name);
#endif

	return retval;
}


/* rewind directory */
void
ftp_rewinddir(FTPDIR *ftpdir)
{
	ftp_seekdir(ftpdir, 0);
}


/* tell where we are in the directory */
off_t
ftp_telldir(FTPDIR *ftpdir)
{
	return ftpdir->fd_offset;
}


/* seek to a given point in the directory */
void
ftp_seekdir(FTPDIR *ftpdir, off_t loc)
{
	struct ftpdirent fde;

	if (loc < ftpdir->fd_offset)
	{
		fget_listptr_reset(&ftpdir->fd_lp);
		ftpdir->fd_offset = 0;
	}

	while (ftpdir->fd_offset < loc && ftp_readdir(ftpdir, &fde) != 0);
}


/* close directory */
void
ftp_closedir(FTPDIR *ftpdir)
{
#ifdef DEBUG
	printf("=== ftp_closedir(ftpdir=0x%lx)\n", ftpdir);
#endif
	fget_list_free(ftpdir->fd_l, free);
	free(ftpdir);
}




syntax highlighted by Code2HTML, v. 0.9.1