/*
 * fdformat.c  -  Low-level formats a floppy disk - Werner Almesberger
 */
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/fd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>

#include "c.h"
#include "blkdev.h"
#include "strutils.h"
#include "closestream.h"
#include "nls.h"
#include "xalloc.h"

#define SECTOR_SIZE 512

static struct floppy_struct param;


static void format_begin(int ctrl)
{
	if (ioctl(ctrl, FDFMTBEG, NULL) < 0)
		err(EXIT_FAILURE, "ioctl: FDFMTBEG");
}

static void format_end(int ctrl)
{
	if (ioctl(ctrl, FDFMTEND, NULL) < 0)
		err(EXIT_FAILURE, "ioctl: FDFMTEND");
}

static void format_track_head(int ctrl, struct format_descr *descr)
{
	if (ioctl(ctrl, FDFMTTRK, (long) descr) < 0)
		err(EXIT_FAILURE, "ioctl: FDFMTTRK");
}

static void seek_track_head(int ctrl, struct format_descr *descr)
{
	lseek(ctrl, (descr->track * param.head + descr->head) * param.sect * SECTOR_SIZE, SEEK_SET);
}

static void format_disk(int ctrl, unsigned int track_from, unsigned int track_to)
{
	struct format_descr current;

	printf(_("Formatting ... "));
	fflush(stdout);

	format_begin(ctrl);

	for (current.track = track_from; current.track <= track_to; current.track++) {
		for (current.head = 0; current.head < param.head; current.head++) {
			printf("%3u/%u\b\b\b\b\b", current.track, current.head);
			fflush(stdout);
			format_track_head(ctrl, &current);
		}
	}

	format_end(ctrl);

	printf("     \b\b\b\b\b%s", _("done\n"));
}

static void verify_disk(int ctrl, unsigned int track_from, unsigned int track_to, unsigned int repair)
{
	unsigned char *data;
	struct format_descr current;
	int track_size, count;
	unsigned int retries_left;

	track_size = param.sect * SECTOR_SIZE;
	data = xmalloc(track_size);
	printf(_("Verifying ... "));
	fflush(stdout);

	current.track = track_from;
	current.head = 0;
	seek_track_head (ctrl, &current);

	for (current.track = track_from; current.track <= track_to; current.track++) {
		for (current.head = 0; current.head < param.head; current.head++) {
			int read_bytes;

			printf("%3u\b\b\b", current.track);
			fflush(stdout);

			retries_left = repair;
			do {
				read_bytes = read(ctrl, data, track_size);
				if (read_bytes != track_size) {
					if (retries_left) {
						format_begin(ctrl);
						format_track_head(ctrl, &current);
						format_end(ctrl);
						seek_track_head (ctrl, &current);
						retries_left--;
						if (retries_left)
							continue;
					}
					if (read_bytes < 0)
						perror(_("Read: "));
					fprintf(stderr,
						_("Problem reading track/head %u/%u,"
						  " expected %d, read %d\n"),
						current.track, current.head, track_size, read_bytes);
					free(data);
					exit(EXIT_FAILURE);
				}
				for (count = 0; count < track_size; count++)
					if (data[count] != FD_FILL_BYTE) {
						if (retries_left) {
							format_begin(ctrl);
							format_track_head(ctrl, &current);
							format_end(ctrl);
							seek_track_head (ctrl, &current);
							retries_left--;
							if (retries_left)
								continue;
						}
						printf(_("bad data in track/head %u/%u\n"
							 "Continuing ... "), current.track, current.head);
						fflush(stdout);
						break;
					}
				break;
			} while (retries_left);
		}
	}

	free(data);
	printf(_("done\n"));
}

static void __attribute__((__noreturn__)) usage(void)
{
	FILE *out = stdout;
	fputs(USAGE_HEADER, out);
	fprintf(out, _(" %s [options] <device>\n"),
		program_invocation_short_name);

	fputs(USAGE_SEPARATOR, out);
	fputs(_("Do a low-level formatting of a floppy disk.\n"), out);

	fputs(USAGE_OPTIONS, out);
	fputs(_(" -f, --from <N>    start at the track N (default 0)\n"), out);
	fputs(_(" -t, --to <N>      stop at the track N\n"), out);
	fputs(_(" -r, --repair <N>  try to repair tracks failed during\n"
                "                     the verification (max N retries)\n"), out);
	fputs(_(" -n, --no-verify   disable the verification after the format\n"), out);

	fputs(USAGE_SEPARATOR, out);
	printf(USAGE_HELP_OPTIONS(19));
	printf(USAGE_MAN_TAIL("fdformat(8)"));

	exit(EXIT_SUCCESS);
}

int main(int argc, char **argv)
{
	int ch;
	int ctrl;
	int verify = 1;
	unsigned int repair = 0;
	unsigned int track_from = 0;
	unsigned int track_to = 0;
	int has_user_defined_track_to = 0;
	struct stat st;

	static const struct option longopts[] = {
		{"from", required_argument, NULL, 'f'},
		{"to", required_argument, NULL, 't'},
		{"repair", required_argument, NULL, 'r'},
		{"no-verify", no_argument, NULL, 'n'},
		{"version", no_argument, NULL, 'V'},
		{"help", no_argument, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	atexit(close_stdout);

	while ((ch = getopt_long(argc, argv, "f:t:r:nVh", longopts, NULL)) != -1)
		switch (ch) {
		case 'f':
			track_from = strtou32_or_err(optarg, _("invalid argument - from"));
			break;
		case 't':
			has_user_defined_track_to = 1;
			track_to = strtou32_or_err(optarg, _("invalid argument - to"));
			break;
		case 'r':
			repair = strtou32_or_err(optarg, _("invalid argument - repair"));
			break;
		case 'n':
			verify = 0;
			break;
		case 'V':
			printf(UTIL_LINUX_VERSION);
			exit(EXIT_SUCCESS);
		case 'h':
			usage();
		default:
			errtryhelp(EXIT_FAILURE);
		}

	argc -= optind;
	argv += optind;

	if (argc < 1) {
		warnx(_("no device specified"));
		errtryhelp(EXIT_FAILURE);
	}
	if (stat(argv[0], &st) < 0)
		err(EXIT_FAILURE, _("stat of %s failed"), argv[0]);
	if (!S_ISBLK(st.st_mode))
		/* do not test major - perhaps this was an USB floppy */
		errx(EXIT_FAILURE, _("%s: not a block device"), argv[0]);
	ctrl = open_blkdev_or_file(&st, argv[0], O_RDWR);
	if (ctrl < 0)
		err(EXIT_FAILURE, _("cannot open %s"), argv[0]);
	if (ioctl(ctrl, FDGETPRM, (long) &param) < 0)
		err(EXIT_FAILURE, _("could not determine current format type"));

	printf(_("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n"),
		(param.head == 2) ? _("Double") : _("Single"),
		param.track, param.sect, param.size >> 1);

	if (!has_user_defined_track_to)
		track_to = param.track - 1;

	if (track_from >= param.track)
		err(EXIT_FAILURE, _("user defined start track exceeds the medium specific maximum"));
	if (track_to >= param.track)
		err(EXIT_FAILURE, _("user defined end track exceeds the medium specific maximum"));
	if (track_from > track_to)
		err(EXIT_FAILURE, _("user defined start track exceeds the user defined end track"));

	format_disk(ctrl, track_from, track_to);

	if (verify)
		verify_disk(ctrl, track_from, track_to, repair);

	if (close_fd(ctrl) != 0)
		err(EXIT_FAILURE, _("close failed"));

	return EXIT_SUCCESS;
}
