/*  $Id: SFSconfig.cpp 1.4 2002/03/23 18:14:44 Helios Exp $

    Sets and queries SmartFilesystem parameters
*/

#include <dos/dos.h>
#include <dos/dosextens.h>
#include <utility/tagitem.h>
#include "fs/packets.h"
#include "fs/query.h"

#include <proto/dos.h>

const char *version_str = "\0$VER: SFSconfig 1.4 (23.3.2002) (C) by Martin Steigerwald\r\n";

#define TEMPLATE "DEVICE/A,LINES/N,READAHEAD=READAHEADSIZE/N,MAXNAMELENGTH=MAXNAME/N,ACTIVITYFLUSH/N,INACTIVITYFLUSH/N,COPYBACK/S,NOCOPYBACK/S"

int main(void);

int main(void)
{
    int rc=RETURN_OK;
    struct RDArgs *rdargs=NULL;

    struct {
        char *device;
        LONG *lines;
        ULONG *readahead;
        ULONG *maxname;
        ULONG *activityflush;
        ULONG *inactivityflush;
        ULONG copyback;
        ULONG nocopyback;
    } args={NULL};

    rdargs = ReadArgs(TEMPLATE, (LONG *)&args, NULL);

    if (rdargs == NULL) {
        PrintFault(IoErr(), "SFSconfig");
        exit(RETURN_ERROR);
    }
    else {
        struct DosList *dl;
        struct MsgPort *port;
        UBYTE *devname=args.device;

        if (args.copyback!=0 && args.nocopyback!=0) {
            PutStr("SFSConfig: Make a decision. Copyback or not? ;-)\n");
            FreeArgs(rdargs);
            exit(RETURN_ERROR);
        }

        // remove colon from devicename
        while(*devname!=0) {
            if(*devname==':') {
                *devname=0;
                break;
            }
            devname++;
        }

        dl=LockDosList(LDF_DEVICES|LDF_READ);

        if ((dl = FindDosEntry(dl, args.device, LDF_DEVICES))!=0) {
            LONG errorcode;
            struct TagItem vtags[]={
                ASQ_VERSION, 0
            };

            port=dl->dol_Task;

            if ((errorcode = DoPkt(port, ACTION_SFS_QUERY, (LONG)&vtags, 0, 0, 0, 0))!=DOSFALSE) {
                LONG version, revision;
                // show all informations
                struct TagItem qtags[]={
                    ASQ_IS_CASESENSITIVE, 0,
                    ASQ_HAS_RECYCLED, 0,
                    ASQ_CACHE_LINES, 0,
                    ASQ_CACHE_READAHEADSIZE, 0,
                    ASQ_CACHE_MODE, 0,
                    TAG_DONE
                };

                version=vtags[0].ti_Data / 65536;
                revision=vtags[0].ti_Data - (version * 65536);

                // set filename length?
                if (args.maxname != 0) {
                    struct TagItem stags[]={
                        ASS_MAX_NAME_LENGTH, *args.maxname,
                        TAG_DONE
                    };

                    PutStr("Setting maximum filename length ...\n");
                    if ((errorcode = DoPkt(port, ACTION_SFS_SET, (LONG)&stags, 0, 0, 0, 0))==DOSFALSE) {
                        PrintFault(IoErr(), "SFSConfig");
                        rc=RETURN_WARN;
                    }
                }

                // set maximum activity flush time?
                if (args.activityflush != 0) {
                    struct TagItem stags[]={
                        ASS_ACTIVITY_FLUSH_TIMEOUT, *args.activityflush,
                        TAG_DONE
                    };

                    PutStr("Setting activity flush timeout ...\n");
                    if ((errorcode = DoPkt(port, ACTION_SFS_SET, (LONG)&stags, 0, 0, 0, 0))==DOSFALSE) {
                        PrintFault(IoErr(), "SFSconfig");
                        rc=RETURN_WARN;
                    }
                }

                // set maximum activity flush time?
                if (args.inactivityflush != 0) {
                    struct TagItem stags[]={
                        ASS_INACTIVITY_FLUSH_TIMEOUT, *args.inactivityflush,
                        TAG_DONE
                    };

                    PutStr("Setting inactivity flush timeout ...\n");
                    if ((errorcode = DoPkt(port, ACTION_SFS_SET, (LONG)&stags, 0, 0, 0, 0))==DOSFALSE) {
                        PrintFault(IoErr(), "SFSConfig");
                        rc=RETURN_WARN;
                    }
                }

                // set the cache?
                if (args.lines != 0 || args.readahead !=0 || args.copyback != 0 || args.nocopyback !=0) {
                    struct TagItem ctags[]={
                        ASQ_CACHE_LINES, 0,
                        ASQ_CACHE_READAHEADSIZE, 0,
                        ASQ_CACHE_MODE, 0,
                        TAG_DONE
                    };

                    PutStr("Setting cache ...\n");

                    if ((errorcode = DoPkt(port, ACTION_SFS_QUERY, (LONG)&ctags, 0, 0, 0, 0))!=DOSFALSE) {
                        LONG lines = ctags[0].ti_Data;
                        LONG readahead = ctags[1].ti_Data;
                        LONG copyback = ctags[2].ti_Data;

                        if (args.lines!=0) {
                            lines = *args.lines;
                        }
                        if (args.readahead!=0) {
                            readahead = *args.readahead;
                        }
                        if (args.copyback!=0) {
                            copyback=1;
                        }
                        if (args.nocopyback!=0) {
                            copyback=0;
                        }

                        if ((errorcode = DoPkt(port, ACTION_SET_CACHE, lines, readahead, copyback, 0, 0))==DOSFALSE) {
                            PrintFault(IoErr(), "SFSconfig");
                            rc=RETURN_WARN;
                        }

                    }
                    else {
                        PutStr("SFSConfig: Could not query cache parameters!\n");
                        PrintFault(IoErr(), "SFSconfig");
                        rc=RETURN_WARN;
                    } // query cache parameters
                } // set the cache?

                Printf("Devicename:     %s:\n", args.device);

                Printf("SFS version:    %ld.%ld\n", version, revision);

                if ((errorcode = DoPkt(port, ACTION_SFS_QUERY, (LONG)&qtags, 0, 0, 0, 0))!=DOSFALSE) {

                    Printf("Cache:          %ld lines * %ld bytes readahead size = %ld bytes.\n",
                        qtags[2].ti_Data, qtags[3].ti_Data, qtags[2].ti_Data * qtags[3].ti_Data);

                    Printf("                Copyback mode");

                    if (qtags[4].ti_Data==0) {
                        Printf(" disabled.\n");
                    }
                    else {
                        Printf(" enabled.\n");
                    }

                    Printf("Fixed options:  ");

                    if (qtags[0].ti_Data!=0) {
                        Printf("(case sensitive) ");
                    }
                    else {
                        Printf("(not case-sensitive) ");
                    }

                    if (qtags[1].ti_Data!=0) {
                        Printf("(recycled)");
                    }
                    else {
                        Printf("(no recycled)");
                    }

                    Printf("\n");
                }
                else {
                    Printf("SFSconfig: Second SFSQuery failed. This should rarely happen!\n");
                    PrintFault(IoErr(), "SFSconfig");
                    rc=RETURN_WARN;

                }
            }
            else {
                Printf("SFSconfig: SFSQUERY failed. Maybe no SFS device?\n");
                PrintFault(IoErr(), "SFSconfig");
                rc=RETURN_ERROR;
            }
        }
        else {
            Printf("Couldn't find device: '%s:'\n", args.device);
            rc=RETURN_ERROR;
        }
        UnLockDosList(LDF_DEVICES|LDF_READ);

        FreeArgs(rdargs);
    } // ReadArgs
    exit(rc);
}

