// ddiff/dpatch - manipulate differences between debian packages.
// Copyright 2000 Tom Rothamel <tom-ddiff@onegeek.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "pkg.h"
#include "genfile.h"

struct DebPkg : public Pkg {
	GFILE *gf;
	GARCHIVE *ar;
	GFILE *gz;
	GARCHIVE *tar;

	int didcontrol;
	char *namestr;
	char *versionstr;
	char *archstr;
	
	GFILE *element(char *, char *);
	char *name();
	char *version();
	char *arch();
		
	GFILE *tarpart(char *);
	void control();
	
	DebPkg(GARCHIVE *, GFILE *);
	~DebPkg();
};

GFILE *DebPkg::element(char *arel, char *tarel) {
	if (ar->finfo->name) {
		if (!strcmp(ar->finfo->name, arel)) {
			ar->seek(0);
			return tarpart(tarel);
		}
	}

	if(!ar->find(arel)) return NULL;

	if (tar) delete tar;
	if (gz) delete gz;

	tar = NULL;
	gz = NULL;
		
	return tarpart(tarel);	
}

GFILE *DebPkg::tarpart(char *tarel) {
	if (!tarel) return ar;

	if (!gz) {
		gz = open_gfgzip(ar);
		if (!gz) return NULL;
	}

	if (!tar) {
		tar = open_gftar(gz);
		if (!tar) return NULL;
	}

	if (tar->find(tarel)) return tar;

	return NULL;
}

static void chomp(char *s) {
	int l;

	l = strlen(s);
	if (s[l-1] == '\n') s[l-1] = 0;
}
	
void DebPkg::control() {
	GFILE *gf;
	char buf[128];
	char *s;
	
	if (didcontrol) return;
	didcontrol = 1;

	gf = element("control.tar.gz", "control");
	if (!gf) return;

	while(gf->gets(buf, 128)) {
		chomp(buf);

		s = strstr(buf, ": ");
		if (!s) continue;

		*s = 0;
		s += 2;

		if (!strcmp("Package", buf)) {
			namestr = strdup(s);
		} else if (!strcmp("Version", buf)) {
			versionstr = strdup(s);
		} else if (!strcmp("Architecture", buf)) {
			archstr = strdup(s);
		}
	}
}

char *DebPkg::name() {
	control();
	return namestr;
}

char *DebPkg::version() {
	control();
	return versionstr;
}

char *DebPkg::arch() {
	control();
	return archstr;
}
	
DebPkg::DebPkg(GARCHIVE *argf, GFILE *gfin) {
	gf = gfin;
	ar = argf;
	gz = NULL;
	tar = NULL;

	namestr = NULL;
	archstr = NULL;
	versionstr = NULL;
	
	didcontrol = 0;
}

DebPkg::~DebPkg() {
	if (tar) delete tar;
	if (gz) delete gz;
	if (ar) delete ar;
	if (gf) delete gf;

	if (namestr) free(namestr);
	if (versionstr) free(versionstr);
	if (archstr) free(archstr);			  
}

Pkg *open_deb_gfile(GFILE *gf) {
	GARCHIVE *ar;

	ar = open_gfarchive(gf);
	if (!ar) {
		delete gf;
		return NULL;
	}

	return new DebPkg(ar, gf);
}

Pkg *open_deb(char *fn) {
	GFILE *gf;

	gf = open_gfstdio(fn);
	if (!gf) return NULL;

	return open_deb_gfile(gf);
}

