/*-
 * RIPCORD.C
 *
 * The xpkdisk.device code that takes care of disk space availability.
 *
 * $Id: ripcord.c,v 1.4 1995/04/08 20:23:48 Rhialto Exp $
 * $Log: ripcord.c,v $
 * Revision 1.4  1995/04/08  20:23:48  Rhialto
 * Add/correct version strings.
 *
 * Revision 1.3  1995/04/02  14:58:51  Rhialto
 * Don't call EasyRequest() on older Intuition versions.
 * Abort writing ripcord file when the write fails.
 *
 * Revision 1.2  1993/12/29  17:27:46  Rhialto
 * Creating the ripcord file was not done right.
 *
 * Revision 1.1  1993/11/08  13:29:16  Rhialto
 * Initial revision
 *
 *
 * This code is (C) Copyright 1993 by Olaf Seibert. All rights reserved.
 * May not be used or copied without a licence.
-*/

#include <string.h>
#include <stdio.h>
#include "xpkdisk.h"
#include <intuition/intuitionbase.h>
#include <clib/intuition_protos.h>

extern struct DosLibrary   *DOSBase;
extern struct IntuitionBase *IntuitionBase;

/*#undef DEBUG			*/
#if DEBUG
#   include "syslog.h"
#else
#   define	debug(x)
#endif

static const char rcsId[] = "$Id: ripcord.c,v 1.4 1995/04/08 20:23:48 Rhialto Exp $";
static const char   Ripcord[] = XPKDISKDIR "Ripcord";
static const char   XpkdiskRequest[] = "xpkdisk Request";

int
RipTryAbort(UNIT *unit, int ripcord)
{
    static struct EasyStruct es = {
	sizeof(es),
	0,
	XpkdiskRequest,
	"Help!!!\n" XPKDISKDIR " medium is (nearly) full!\n%s",
	NULL
    };
    char	   *extra;
    int 	    choice;

    if (ripcord) {
	extra = "(but the ripcord is still there)";
	es.es_GadgetFormat = "Rip Cord|Try Anyway|Abort";
    } else {
	extra = "(and no ripcord is present)";
	es.es_GadgetFormat = "Try Anyway|Abort";
    }

    if (IntuitionBase->LibNode.lib_Version < 37) {
	choice = 1;
    } else {
	choice = EasyRequest(NULL, &es, NULL, extra);
    }
    if ((ripcord == 0) && (choice == 1))
	choice = 2;
    return choice;
}

Prototype int MakeRipcord(UNIT *unit);

int
MakeRipcord(UNIT *unit)
{
    void	   *v;
    BPTR	    fh;
    long	    length;

    /*
     * Reserve space for 2 tracks, and add 1 sector for the file header
     * of the second track.
     */
    length = XD_BPS + (2 * unit->xu_TrackLen);
    unit->xu_RipcordBlocks = length / XD_BPS;

    v = AllocMem(1024, MEMF_ANY | MEMF_CLEAR);
    if (v) {
	if (fh = Open(Ripcord, MODE_READWRITE)) {
	    int 	    i;

	    Seek(fh, 0, OFFSET_END);
	    i = (length - Seek(fh, 0, OFFSET_CURRENT)) / 1024;
	    while (i > 0) {
		if (Write(fh, v, 1024) <= 0)
		    break;
		i--;
	    }
	    Close(fh);
	}
	FreeMem(v, 1024);
    }
    return v && fh;
}

int
DeleteRipcord(UNIT *unit)
{
    return DeleteFile(Ripcord);
}

Prototype int CheckRipcord(UNIT *unit);

int
CheckRipcord(UNIT *unit)
{
    __aligned struct InfoData infodata;
    BPTR	    fl;
    BPTR	    ripcord;
    int 	    choice;
    int 	    result = 1;

    ripcord = Lock(Ripcord, SHARED_LOCK);
    UnLock(ripcord);
    fl = Lock("", SHARED_LOCK);
    if (Info(fl, &infodata)) {
	if ((infodata.id_NumBlocks - infodata.id_NumBlocksUsed) <
						unit->xu_RipcordBlocks) {
	    /* Disk nearly full */
	    /*       1  2  0 */
	    choice = RipTryAbort(unit, ripcord);
	    switch (choice) {
	    case 0:	/* Abort */
		result = 0;
		break;
	    case 1:	/* Rip Cord */
		DeleteRipcord(unit);
	    case 2:	/* Try Anyway */
		result = 1;
		break;
	    }
	}
    }
    UnLock(fl);
    return result;
}

Prototype int FullRetry(UNIT *unit, char *file, int xpkerr, int ioerr, char *msg);

int
FullRetry(UNIT *unit, char *file, int xpkerr, int ioerr, char *msg)
{
    static struct EasyStruct es = {
	sizeof(es),
	0,
	XpkdiskRequest,
	"Panic!!!\n"
	    "Writing " XPKDISKDIR "%s failed!\n"
	    "(%s)\n"
	    "XPK error: %ld, IoErr(): %ld.%s",
	"Retry|Revert To Old|Abort"
    };
    int choice;
    char *sugg = " Perhaps the disk is full?";

    if (xpkerr == -4 && ioerr == ERROR_DISK_FULL) {
	sugg = "\nDidn't you see all those \"Disk Full\" requesters?";
    }

    if (IntuitionBase->LibNode.lib_Version < 37) {
	choice = 1;
    } else {
	choice = EasyRequest(NULL, &es, NULL, file, msg,
			     (long)xpkerr, (long)ioerr, sugg);
    }
    return choice;
}
