#include <alloca.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <rpmlib.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define FILENAME_TAG 1000000

int tags[] =  { RPMTAG_NAME, RPMTAG_VERSION, RPMTAG_RELEASE, RPMTAG_GROUP,
		RPMTAG_REQUIREFLAGS, RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION,
		RPMTAG_DESCRIPTION, RPMTAG_SUMMARY, RPMTAG_PROVIDES,
		RPMTAG_SIZE };
int numTags = sizeof(tags) / sizeof(int);

int ugdbTags[] =  { RPMTAG_NAME, RPMTAG_VERSION, RPMTAG_RELEASE, RPMTAG_SERIAL,
		RPMTAG_FILENAMES, RPMTAG_PROVIDES, RPMTAG_REQUIREFLAGS,
		RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION };

int numUgdbTags = sizeof(ugdbTags) / sizeof(int);

int main(int argc, char ** argv) {
    char buf[300];
    DIR * dir;
    int outfd, ugdboutfd;
    struct dirent * ent;
    int fd, rc, isSource;
    Header h, newh;
    int count, type;
    int i;
    void * ptr;

    if (argc != 2) {
	fprintf(stderr, "usage: genhdlist <dir>\n");
	exit(1);
    }

    strcpy(buf, argv[1]);
    strcat(buf, "/RedHat/RPMS");

    dir = opendir(buf);
    if (!dir) {
	fprintf(stderr,"error opening directory %s: %s\n", buf,
		strerror(errno));
	return 1;
    }
    chdir(buf);

    strcpy(buf, argv[1]);
    strcat(buf, "/RedHat/base/hdlist");
    
    outfd = open(buf, O_WRONLY | O_TRUNC | O_CREAT, 0644);
    if (outfd < 0) {
	fprintf(stderr,"error creating file %s: %s\n", buf, strerror(errno));
	return 1;
    }

    strcpy(buf, argv[1]);
    strcat(buf, "/RedHat/base/uglist");
    
    ugdboutfd = open(buf, O_WRONLY | O_TRUNC | O_CREAT, 0644);
    if (ugdboutfd < 0) {
	fprintf(stderr,"error creating file %s: %s\n", buf, strerror(errno));
	return 1;
    }

    errno = 0;
    ent = readdir(dir);
    if (errno) {
	perror("readdir");
	return 1;
    }

    while (ent) {
	if (!(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || 
	    ((ent->d_name[1] == '.') && (ent->d_name[2] == '\0'))))) {
	    fd = open(ent->d_name, O_RDONLY);

	    if (fd < 0) {
		perror("open");
		exit(1);
	    }

	    rc = pkgReadHeader(fd, &h, &isSource, NULL, NULL);

	    close(fd);
	    if (rc) {
		fprintf(stderr, "failed to pkgReadHeader %s\n", ent->d_name);
		exit(1);
	    }

	    /* Regular bit */
	    newh = newHeader();
	    for (i = 0; i < numTags; i++) {
		if (!getEntry(h, tags[i], &type, &ptr, &count)) {
		    switch (tags[i]) {
		      case RPMTAG_REQUIREFLAGS:
		      case RPMTAG_REQUIRENAME:
		      case RPMTAG_REQUIREVERSION:
		      case RPMTAG_SUMMARY:
		      case RPMTAG_PROVIDES:
			break;
		      default:
			fprintf(stderr, "tag %d not found in file %s\n", 
				tags[i], ent->d_name);
			exit(1);
		    }
		} else 
		    addEntry(newh, tags[i], type, ptr, count);
	    }
	    addEntry(newh, FILENAME_TAG, STRING_TYPE, ent->d_name, 1);
	    writeHeader(outfd, newh, 1);
	    freeHeader(newh);

	    /* Upgrade bit */
	    newh = newHeader();
	    for (i = 0; i < numUgdbTags; i++) {
		if (!getEntry(h, ugdbTags[i], &type, &ptr, &count)) {
		    switch (ugdbTags[i]) {
		      case RPMTAG_SERIAL:
		      case RPMTAG_PROVIDES:
		      case RPMTAG_REQUIREFLAGS:
		      case RPMTAG_REQUIRENAME:
		      case RPMTAG_REQUIREVERSION:
			break;
		      default:
			fprintf(stderr, "tag %d not found in file %s\n", 
				ugdbTags[i], ent->d_name);
			exit(1);
		    }
		} else
		    addEntry(newh, ugdbTags[i], type, ptr, count);
	    }
	    writeHeader(ugdboutfd, newh, 1);
	    freeHeader(newh);
	    
	    freeHeader(h);
	}

	errno = 0;
	ent = readdir(dir);
	if (errno) {
	    perror("readdir");
	    return 1;
	}
    } 

    closedir(dir);
    close(outfd);

    return 0;
}
