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

#include <internal.h>

#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>

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


/*
** parse EPLF directories
**
** EPLF format documented here:
** http://cr.yp.to/ftp/list/eplf.html
*/
int
_ftp_list_parse_eplf(FTP *ftp, char *buf, file_info_t *fip)
{
	char *fieldp, *nextp;
	unsigned long ul;
	unsigned int ui;

#ifdef DEBUG
	printf("==> _ftp_list_parse_eplf(ftp=0x%lx (%s), buf=0x%lx, "
	       "fip=0x%lx)\n",
	       ftp, ftp->ftp_host, buf, fip);
#endif

	/* skip leading '+' */
	if (buf[0] != '+')
	{
		errno = EINVAL;
		return FLP_ERROR;
	}
	nextp = buf + 1;

	/* extract filename */
	fieldp = strchr(nextp, '\t');
	if (fieldp == NULL)
	{
		errno = EINVAL;
		return FLP_ERROR;
	}
	*fieldp++ = '\0';
	strlcpy(fip->fi_filename, fieldp, sizeof(fip->fi_filename));

	/* parse facts */
	while ((fieldp = strsep(&nextp, ",")) != NULL)
	{
		if (*fieldp == '\0')
			continue;

		switch (*fieldp)
		{
		case 'r':	/* RETR may succeed */
			fip->fi_stat.fs_mode |= S_IFREG;
			continue;

		case '/':	/* CWD may succeed */
			fip->fi_stat.fs_mode |= S_IFDIR;
			continue;

		case 's':	/* file size */
			sscanf(fieldp + 1, "%lu", &ul);
			fip->fi_stat.fs_size = (off_t)ul;
			continue;

		case 'm':	/* mtime */
			sscanf(fieldp + 1, "%lu", &ul);
			fip->fi_stat.fs_mtime = (time_t)ul;
			continue;

		case 'u':	/* "up" - file mode */
			/* if it's not "up", treat as an unknown fact */
			if (fieldp[1] != 'p')
				continue;

			sscanf(fieldp + 2, "%lo", &ui);
			fip->fi_stat.fs_mode |= (mode_t)ui;
			continue;

		default:	/* unknown fact */
			break;
		}

		/* otherwise, unknown fact, so just ignore it */
	}

	/* EPLF doesn't encode these fields at all, so set defaults */
	strlcpy(fip->fi_stat.fs_username, "-1",
		sizeof(fip->fi_stat.fs_username));
	strlcpy(fip->fi_stat.fs_groupname, "-1",
		sizeof(fip->fi_stat.fs_groupname));
	fip->fi_stat.fs_nlink = 1;

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

	return 0;
}




syntax highlighted by Code2HTML, v. 0.9.1