/*
**  Copyright 1998-2003 University of Illinois Board of Trustees
**  Copyright 1998-2003 Mark D. Roth
**  All rights reserved.
**
**  wrapper.c - libtar high-level wrapper code
**
**  Mark D. Roth <roth@uiuc.edu>
**  Campus Information Technologies and Educational Services
**  University of Illinois at Urbana-Champaign
*/

#define DEBUG
#include <internal.h>

#include <stdio.h>
#include <sys/param.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#ifdef STDC_HEADERS
# include <string.h>
#endif

int
tar_extract_glob(TAR *t, char *globname, char *prefix)
{
	char *filename;
	char buf[MAXPATHLEN];
	int i, fd = 0;

	while ((i = th_read(t)) == 0)
	{
		filename = th_get_pathname(t);
		if (fnmatch(globname, filename, FNM_PATHNAME | FNM_PERIOD))
		{
			if (TH_ISREG(t) && tar_skip_regfile(t))
				return -1;
			continue;
		}
		if (t->options & TAR_VERBOSE)
			th_print_long_ls(t);
		if (prefix != NULL)
			snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
		else
			strlcpy(buf, filename, sizeof(buf));
		if (tar_extract_file(t, filename, prefix, &fd) != 0)
			return -1;
	}

	return (i == 1 ? 0 : -1);
}


int
tar_extract_all(TAR *t, char *prefix, const int *progress_fd)
{
	char *filename;
	char buf[MAXPATHLEN];
	int i;
	printf("prefix: %s\n", prefix);
#ifdef DEBUG
	printf("==> tar_extract_all(TAR *t, \"%s\")\n",
	       (prefix ? prefix : "(null)"));
#endif
	while ((i = th_read(t)) == 0)
	{
#ifdef DEBUG
		puts("    tar_extract_all(): calling th_get_pathname()");
#endif
		filename = th_get_pathname(t);
		if (t->options & TAR_VERBOSE)
			th_print_long_ls(t);
		if (prefix != NULL)
			snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
		else
			strlcpy(buf, filename, sizeof(buf));
#ifdef DEBUG
		printf("    tar_extract_all(): calling tar_extract_file(t, "
		       "\"%s\")\n", buf);
#endif
		printf("item name: '%s'\n", filename);
		if (tar_extract_file(t, buf, prefix, progress_fd) != 0)
			return -1;
	}
	return (i == 1 ? 0 : -1);
}


int
tar_append_tree(TAR *t, char *realdir, char *savedir, char *exclude)
{
#ifdef DEBUG
	printf("==> tar_append_tree(0x%lx, \"%s\", \"%s\")\n",
	       (long unsigned int)t, realdir, (savedir ? savedir : "[NULL]"));
#endif

	char temp[1024];
	int skip = 0, i, n_spaces = 0;
	char ** excluded = NULL;
	char * p = NULL;
	if (exclude) {
		strcpy(temp, exclude);
		p = strtok(exclude, " ");
		if (p == NULL) {
			excluded = realloc(excluded, sizeof(char*) * (++n_spaces));
			excluded[0] = temp;
		} else {
			while (p) {
				excluded = realloc(excluded, sizeof(char*) * (++n_spaces));
				excluded[n_spaces-1] = p;
				p = strtok(NULL, " ");
			}
		}
		excluded = realloc(excluded, sizeof(char*) * (n_spaces+1));
		excluded[n_spaces] = 0;
		for (i = 0; i < (n_spaces+1); i++) {
			if (realdir == excluded[i]) {
				printf("    excluding '%s'\n", excluded[i]);
				skip = 1;
				break;
			}
		}
	}
	if (skip == 0) {
		if (tar_append_file(t, realdir, savedir) != 0)
			return -1;
	}

	char realpath[MAXPATHLEN];
	char savepath[MAXPATHLEN];
	struct dirent *dent;
	DIR *dp;
	struct stat s;

	dp = opendir(realdir);
	if (dp == NULL) {
		if (errno == ENOTDIR)
			return 0;
		return -1;
	}
	while ((dent = readdir(dp)) != NULL) {
		if(strcmp(dent->d_name, ".") == 0
		|| strcmp(dent->d_name, "..") == 0)
			continue;

		if (exclude) {
			int omit = 0;
			for (i = 0; i < (n_spaces+1); i++) {
				if (excluded[i] != NULL) {
						if (strcmp(dent->d_name, excluded[i]) == 0 || strcmp(excluded[i], realdir) == 0) {
							printf("    excluding '%s'\n", excluded[i]);
							omit = 1;
							break;
						}
				}
			}
			if (omit)
				continue;
		}

		snprintf(realpath, MAXPATHLEN, "%s/%s", realdir, dent->d_name);
		if (savedir)
			snprintf(savepath, MAXPATHLEN, "%s/%s", savedir, dent->d_name);

		if (lstat(realpath, &s) != 0)
			return -1;

		if (S_ISDIR(s.st_mode)) {
			if (tar_append_tree(t, realpath, (savedir ? savepath : NULL), (exclude ? exclude : NULL)) != 0)
				return -1;
			continue;
		} else {
			if (tar_append_file(t, realpath, (savedir ? savepath : NULL)) != 0)
				return -1;
			continue;
		}
	}
	closedir(dp);
	free(excluded);

	return 0;
}


int
tar_find(TAR *t, char *searchstr)
{
	if (!searchstr)
		return 0;

	char *filename;
	int i, entryfound = 0;
#ifdef DEBUG
	printf("==> tar_find(0x%lx, %s)\n", (long unsigned int)t, searchstr);
#endif
	while ((i = th_read(t)) == 0) {
		filename = th_get_pathname(t);
		if (fnmatch(searchstr, filename, FNM_FILE_NAME | FNM_PERIOD) == 0) {
			entryfound++;
#ifdef DEBUG
			printf("Found matching entry: %s\n", filename);
#endif
			break;
		}
	}
#ifdef DEBUG
	if (!entryfound)
		printf("No matching entry found.\n");
#endif

	return entryfound;
}
