/**************************************************************************************************
	$Header: /pub/cvsroot/yencode/src/support.c,v 1.10 2002/03/15 05:59:02 bboy Exp $

	Copyright (C) 2002  Don Moore <bboy@bboy.net>

	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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#include "y.h"

extern int		opt_overwrite;
extern int		opt_line_length;
extern size_t	opt_multipart_size;
extern int		opt_keep_paths;								/* Strip paths from filenames? */


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	YENCODE_AND_WRITE_BUFFER
	Writes a buffer to a file, encoding as it goes.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
yencode_and_write_buffer(FILE *out, const char *filename, const unsigned char *buf, size_t buflen)
{
	crc32_t crc;
	register size_t ct;
	register int linect = 0;
	register unsigned char c;

	fprintf(out, "=ybegin line=%d size=%u name=%s\r\n", opt_line_length, buflen, filename);
	CRC_START(crc);
	for (ct = 0; ct < buflen; ct++)
	{
		c = buf[ct];
		CRC_UPDATE(crc, c);
		c = YENCODE(c);
		if (YSHOULD_ESCAPE(c,linect,opt_line_length))
		{
			fputc(c, out);
			c = YESCAPE(c);
			linect++;
		}
		fputc(c, out);
		linect++;
		if (linect >= opt_line_length)
		{
			fputc('\r', out);
			fputc('\n', out);
			linect = 0;
		}
	}
	if (linect)
	{
		fputc('\r', out);
		fputc('\n', out);
	}
	CRC_FINISH(crc);
	fprintf(out, "=yend size=%u crc32=%08x\r\n", buflen, crc);
}
/*--- yencode_and_write_buffer() ----------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	YENCFILE_DEFAULT_FILENAME
	If no filename was specified, this sets a default based on the first item in the YENCFILE.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
char *
yencfile_default_filename(const char *filename, const char *default_filename, const char *extension)
{
	static char outfile[PATH_MAX];
	char			name[PATH_MAX], *c;

	if (filename)
		strncpy(name, filename, sizeof(name)-1);
	else {
		strncpy(name, default_filename, sizeof(name)-1);
		if ((c = strrchr(name, '.')))							// Strip short extension
			if (c > (name + strlen(name)) - 6)
				*c = '\0';
	}

	snprintf(outfile, sizeof(outfile), "%s%s", name, extension);
	return (outfile);
}
/*--- yencfile_default_filename() ---------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	SFV_CONSTRUCT
	Constructs the SFV file data.  Returns a buffer containing the data.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
unsigned char *
sfv_construct(YENCFILE **y, int ysize)
{
	unsigned char	*buf = NULL;								/* Output buffer */
	time_t			now = time(NULL);							/* Current time */
	char				timebuf[80];								/* Buffer for date/time string */
	const struct tm *tm;											/* Broken down time */
	int				ct;											/* Current position in `y' */
	struct stat		st;											/* File info for input file */

	tm = gmtime(&now);
	strftime(timebuf, sizeof(timebuf)-1, "%Y-%m-%d at %H:%M.%S %Z", tm);
	sdprintf(&buf, "; Generated by WIN-SFV32 v1.1a (%s %s for %s) on %s\r\n;\r\n",
				PACKAGE, VERSION, SYSTYPE && strlen(SYSTYPE) ? SYSTYPE : "Unknown OS", timebuf);
	for (ct = 0; ct < ysize; ct++)							/* Output file sizes etc in comments */
		if (!YSUPPORT_IS_SPECIAL(y[ct]->file_type) && y[ct]->ok && !stat(y[ct]->input_filename, &st))
		{
			tm = gmtime(&st.st_mtime);
			strftime(timebuf, sizeof(timebuf)-1, "%H:%M.%S %Y-%m-%d", tm);
			sdprintf(&buf, "; %12lu  %s %s\r\n", (unsigned long)st.st_size, timebuf,
						STRIP_PATH(y[ct]->input_filename));
		}
	for (ct = 0; ct < ysize; ct++)							/* Output checksums */
		if (!YSUPPORT_IS_SPECIAL(y[ct]->file_type) && y[ct]->ok)
			sdprintf(&buf, "%s %08X\r\n", STRIP_PATH(y[ct]->input_filename), y[ct]->crc);

	return (buf);
}
/*--- sfv_construct() ---------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	SFV_CREATE
	Creates an SFV file for the specified file set.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
sfv_create(const char *filename, YENCFILE **y, int ysize, const char *output_dir)
{
	char				*outbase, outfile[PATH_MAX];			/* Name of output file */
	FILE				*fp;											/* Output file pointer */
	unsigned char	*buf = NULL;								/* Output buffer */

	outbase = yencfile_default_filename(filename, STRIP_PATH(y[0]->input_filename), ".sfv");

	if (output_dir)
		snprintf(outfile, sizeof(outfile), "%s/%s.ync", output_dir, outbase);
	else
		snprintf(outfile, sizeof(outfile), "%s.ync", outbase);

	if (!(fp = open_output_file(outfile, opt_overwrite, NULL)))
		return;

	buf = sfv_construct(y, ysize);

	yencode_and_write_buffer(fp, outbase, buf, strlen(buf));
	fclose(fp);
	free(buf);
	usermsg(NULL, outfile, 0, 0, _("SFV file created OK"), NULL);
}
/*--- sfv_create() ------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	CRC_CONSTRUCT
	Constructs the CRC file data.  Returns a buffer containing the data.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
unsigned char *
crc_construct(YENCFILE **y, int ysize)
{
	unsigned char	*buf = NULL;								/* Output buffer */
	int				ct;											/* Current position in `y' */

	for (ct = 0; ct < ysize; ct++)							/* Output checksums */
		if (!YSUPPORT_IS_SPECIAL(y[ct]->file_type) && y[ct]->ok)
			sdprintf(&buf, "%s -- %08X\r\n", STRIP_PATH(y[ct]->input_filename), y[ct]->crc);
	return (buf);
}
/*--- crc_construct() ---------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	CRC_CREATE
	Creates a CRC file for the specified file set.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
crc_create(const char *filename, YENCFILE **y, int ysize, const char *output_dir)
{
	char				*outbase, outfile[PATH_MAX];			/* Name of output file */
	FILE				*fp;											/* Output file pointer */
	unsigned char	*buf = NULL;								/* Output buffer */

	outbase = yencfile_default_filename(filename, STRIP_PATH(y[0]->input_filename), ".crc");

	if (output_dir)
		snprintf(outfile, sizeof(outfile), "%s/%s.ync", output_dir, outbase);
	else
		snprintf(outfile, sizeof(outfile), "%s.ync", outbase);

	if (!(fp = open_output_file(outfile, opt_overwrite, NULL)))
		return;

	buf = crc_construct(y, ysize);
	yencode_and_write_buffer(fp, outbase, buf, strlen(buf));
	fclose(fp);
	free(buf);
	usermsg(NULL, outfile, 0, 0, _("CRC file created OK"), NULL);
}
/*--- crc_create() ------------------------------------------------------------------------------*/

/* vi:set ts=3: */


syntax highlighted by Code2HTML, v. 0.9.1