/***********************************************************
	append.c -- append to archive
***********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <farstr.h>
#include <io.h>
#include <dos.h>
#include "lh.h"
#include "intrface.h"
#include "disp.h"
#include "errmes.h"

struct interfacing interface;

void copylzh(void)
{
	update_arcstamp();
	writehdr();
	copyfile(file1, file2, hpb.packed, 0);
}

struct extension {
	struct extension *nxt;
	char ext[1];
};

struct extension *extptr;

void regext(char *ext)
{
	struct extension *p;

	if (*ext == '.') ext++;
	p = malloc(strlen(ext) + sizeof(struct extension));
	p -> nxt = extptr;
	strcpy(p -> ext, ext);
	extptr = p;
}

static int isarc(char *name)
{
	static char arc[6][4] = {"zoo", "arc", "pak", "zip", "lzs", "lzh"};
	char *p;
	struct extension *q;
	int i;

	p = strrchr(name, '.');
	if (p == NULL) p = name + strlen(name) - 1;
	p++;
	for (i = 0; i < sizeof(arc) / 3; i++) {
		if (*matchfname(arc[i], p) == '\0') return 1;
	}
	for (q = extptr; q; q = q -> nxt) {
		if (*matchfname(q -> ext, p) == '\0') return 1;
	}
	return 0;
}

void freeze(char *path, char *name)
{
	static int method = -1;

	hpb.pathname = name;
	hpb.filename = getfilename(name);
	file3 = myropen(path);

	if (method < 0) {
		method = 5;
		if (flg_o) method = 1;
		if (flg_z == 1)	method = 0;
		if (method > 0) method = encode_alloc(method);
	}
	_dos_getfileattr(path, &hpb.attr);
	if (!flg_a) hpb.attr &= 0x21;
	hpb.utc = getfiletime(file3);
	hpb.level = flg_h;
	hpb.info = 0;
	hpb.original = hpb.packed = filelength(fileno(file3));
	strcpy(hpb.method, "-lh5-");
	interface.method = method;
	interface.dicbit = (method == 1 || method == 4) ? 12 : 13;
	interface.original = hpb.original;
	regdisp("Freezing", path);
	disp(0, outredir);
	initdisp();

	if (hpb.original == 0 || flg_z == 2 && isarc(hpb.filename))
		interface.method = 0;

	if (interface.method > 0) {
		makehdr();
		writehdr();
		interface.infile = file3;
		interface.outfile = file2;
		encode(&interface);
		if (interface.packed >= interface.original) {
			rewind(file3);
			fseek(file2, hpb.currentpos, SEEK_SET);
			interface.method = 0;
			dispname();
			initdisp();
		}
		hpb.packed = interface.packed;
	}
	hpb.method[3] = interface.method + '0';
	if (interface.method == 0) {
		makehdr();
		writehdr();
		copyfile(file3, file2, hpb.original, 1);
	}
	update_arcstamp();
	hpb.filecrc = crc;
	adjusthdr();
	fclose(file3);
	if (ferror(file2)) error(WTERR, filename2);
	if (flg_n != 2)
		eprintf((flg_l) ? "\r  ==> %3d%%\n" : "\r==> %3d%%\n", 
		        ratio(hpb.packed, hpb.original, 2));
}

static void freeze_fb(struct fb far *fp)
{
	char *p;
	char far *path;

	path = fp -> fname;
	p = e_malloc(far_strlen(path) + 1);
	far_strcpy(p, path);
	freeze(p, p + (fp -> cpos - path));
	free(p);
}

int append(void)
{
	struct fb far *fp;

	if ((fp = searchfile(hpb.pathname)) != NULL
		&& (flg_c || fp -> time > hpb.utc))
	{
		freeze_fb(fp);
		return 1;
	} else {
		if (fp != NULL) increment_disp();
		copylzh();
		return 0;
	}
}

int endappend(void)
{
	struct fb far *fp;
	int modified;

	modified = 0;
	for (fp = fbuf; fp != NULL; fp = fp -> nxt) {
		if (fp -> used == 0){
			freeze_fb(fp);
			modified++;
		}
	}
	return modified;
}

void deletefiles(void)
{
	struct fb far *fp;

	for (fp = fbuf; fp != NULL; fp = fp -> nxt) {
		far_strcpy(work, fp -> fname);
		remove(work);
	}
}

int freshen(char far *bdir)
{
	char *path, *name;
	struct find_t srchbuf;
	int flag;

	if (bdir) {
		path = e_malloc(far_strlen(bdir) + strlen(hpb.pathname) + 1);
		far_strcpy(path, bdir);
		if (*hpb.pathname == DELIM) {
			if (path[1] == ':') {
				path[2] = '\0';
			} else {
				*path = '\0';
			}
		}
		name = path + strlen(path);
		strcpy(name, hpb.pathname);
		flag = !_dos_findfirst(path, flg_a ? 0x07 : 0x01, &srchbuf);
		if (flag) {
			if (!flg_c) {
				if (hpb.utc >= dos2unix((struct ftime *)&(srchbuf.wr_time)))
					flag = 0;
			}
		}
	} else {
		flag = 0;
	}
	if (flag) {
		freeze(path, name);
	} else {
		copylzh();
	}
	free(path);
	return flag;
}
