/* CFS.h - common definitions for XFH.
   Copyright (C) 1991, 1992, 1993 Kristian Nielsen.

   This file is part of XFH, the compressing file system handler.

   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., 675 Mass Ave, Cambridge, MA 02139, USA.            */


/* #include "patchup.h" */      /* Compiling in 1.3. */
#include "version.h"

#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <dos/exall.h>
#include <dos/notify.h>

#define IONAME    "ram:CFSIO"

#define MAXFILENAME 30        /* Maximum length of file names. */
#define XROOTNAME "XFH"       /* Unit number and ':' will be appended. */
#define XROOTNAMESIZE 15      /* Max. size of root assign (unit 2^32-1) */

#define ALTOPTIONPATH ".xfhrc"

#define TMPNAMETEMPLATE "%lx.%lx_XFH"   /* Used in sprintf(..,task,num) */
#define TMPNAMEMAXSIZE  (8+ 1+8+4+  1)

#define AREXXPORTTEMPLATE "%s"         /* %s will be device name (XHx:) */
#define AREXXPORTMAXLEN 1              /* Plus device name size. */
#define AREXXPORTPRI 1

#define OUTOFMEM glob -> ioerr = ERROR_NO_FREE_STORE
#define DECLIOERR LONG saveioerr;
#define PUTIOERR saveioerr = glob->ioerr
#define SAVEIOERR LONG saveioerr = glob->ioerr
#define RESTIOERR glob->ioerr = saveioerr

#define XFH_ID "XFH A"

#define MAXSTRING 256   /* Maximum length of some strings (like a path). */
#ifdef DEBUG
#define debug(a) dprintf a
#include <DebugPrc.h>
#else
#define debug(a)
#endif


/* This is the structure used internally to represent a file/directory
 * lock. All locks we return contain the address of this structure in their
 * lock->fl_Key field.
 *
 * The CFSLock.refcount field is a sad hack nessesary to overcome a
 * problem with exclusive directory locks when compressing files. The
 * problem is that we need a copy of the parent lock used in RawCFSOpen()
 * when the file is Close()'d. However, if the parent lock is exclusive,
 * it cannot be DupLock()'ed, and so we must store a reference to it.
 * The refcount counts the number of such references, and prevents the
 * lock from going away until after the Close().
 */
struct CFSLock {
  LONG objtype;
  struct cfsfunctions *f;
  LONG mode;
  struct FileLock *xlock;
  LONG refcount;            /* Currently valid only for XOBJECT's. */
};


/* Structure for file handles. */
struct CFSFH {
  LONG objtype;
  struct cfsfunctions *f;
  LONG mode;
  struct FileHandle *xfh;
  char *filename;            /* Used when compressing file at Close(). */
  struct CFSLock *parent;   /* Used when compressing file at Close(). */
  /* A non-null 'filename' field means (for xobj's) that Close() will
   * attempt to compress the file. */
};

/* CFSLock filetypes. */
#define XOBJECTB  1      /* A simple handle on an object in ufs. */
/* #define NUKEOBJECTB 2 */   /* The NUKE format (U. Mueller). */
/* #define PPACKOBJB 3   */   /* Files packed with powerpacker. */
#define XPKOBJECTB 4     /* Xpk.library files. */

#define XOBJECT     (1 << XOBJECTB)
/* #define NUKEOBJECT  (1 << NUKEOBJECTB) */
/* #define PPACKOBJ    (1 << PPACKOBJB)   */
#define XPKOBJECT   (1 << XPKOBJECTB)


/* Blocksize to fake in Examine()/ExNext(). */
#define BLOCKSIZE glob->bytesperblock    

/* Global datastructure. This allow us to use global variables and still
 * be reentrant without using any kind of short addressing (no need for
 * any __saveds keywords or startup code).
 */
struct glob{
  /* Shared data buffers to save on dalloc()'s.*/
  /* Note that care should be taken when using these, since they are*/
  /* shared between a number of functions. A rule of thumb is that a*/
  /* lower level (dosfunc.c) shouldn't use something owned by a*/
  /* higher level (lock.c). This way, a call in lock.c to a function*/
  /* in dosfunc.c won't change your buffer, while a call to another*/
  /* lock.c-function potentially may.*/
	
   char stringbuf[MAXSTRING];        /* Buffer for dosfunctions (bstr conv.) */
   char stringbuf2[MAXSTRING];       /* Buffer for dosfunctions (bstr conv.) */
   char pktstringbuf[MAXSTRING];     /* Buffer for packet bstr->cstr. */
   char pktstringbuf2[MAXSTRING];    /* Buffer for packet bstr->cstr. */
   struct FileInfoBlock fib1;        /* Used during Lock(). */
   struct FileInfoBlock fib2;        /* General high-level in dosfunc.c */
   struct StandardPacket iopkt;      /* This will be long alligned. */
   struct InfoData infodata;
   
   struct MsgPort *dosport,          /* Dos Port (ProcId) of this handler. */
                  *ioport,           /* Port to use for DOS IO. */
                  *xpkport;          /* Port for calling Xpk in KS1.3. */
   struct Task *mytask;              /* Copy of FindTask(0L) */
   struct Process *myproc;
   void *DOSBase;
   struct Library *XpkBase;
   struct Library *IconBase;
   struct PPBase *PPBase;
   struct DeviceNode *devnode;
   char *devname;
   struct DeviceList *volnode;       /* Pointer to our volumenode. */
   BSTR bcplstartup;                 /* Copy of BPTR to startup string. */
   struct CFSLock *rootlock;         /* Our rootlock. */
   struct FileLock *xrootlock;       /* Rootlock for underlying fs. */
   struct MsgPort *xprocid;          /* ProcID of the underlying fs. */
   LONG ioerr;
   short opencnt;
   BOOL done;                        /* Flag for main packet loop. */
   LONG tmpfilecount;                /* used for tmpfile generation. */
   LONG bytesperblock;               /* Blocksize in the UFS. */
   struct MsgPort *arexxport;
   char *arexxportname;

   /* These are options handled by 'options.c'. */
   /* Also read by SetConfigSem() in gui.c. */
   char *badoption;                  /* Name of errorneous option. */
   BOOL optionsset;                  /* True when options has been set. */
   
   BOOL stepdown;                    /* Flag for XpkPack(). */
   BOOL autocompress;                /* Whether to compress on Write(). */
   BOOL truncateonpack;              /* Use SetFileSize() when packing? */
   char *packmode;                   /* Packmode for XpkPack(). */
   char *xRootName;                  /* 'True' name of our root dir. */
   char *uservolname;                /* User requested volume name. ONLY
                                      * accessed by createvolnode(). */
   char *xpkpassword;                /* Password used in Xpk(Un)Pack(). */
   BOOL xpksetpri;                   /* Change taskpri when (un)packing? */
   LONG xpkpri;                      /* priority to use if xpksetpri. */
   BOOL createvolnode;               /* Whether se have a volume. *NOTE*: */
                                     /* DON'T CHANGE AFTER createvolnode().*/
   BOOL FailOnExNext;                /* Silently gobble ModifyFIB() errors.*/
   BOOL compressreadwrite;           /* Whether to compress MODE_READWRITE.*/
   BOOL allowappend;                 /* Whether to support MODE_READWRITE.*/
   char *userarexxportname;	     /* User requested name of AREXX port. */

#ifdef DEBUG
   /* Extra fields for debug code. */
   char debugbuf1[MAXSTRING];
   char debugbuf2[MAXSTRING];        /* Used to print bcpl strings. */
#endif

};
typedef struct glob *glb;


/* For each of the supported file formats, there is an instance of this
 * structure. It holds pointers to fuctions that performs tasks such as
 * Read(), Lock(), etc.
 */
struct cfsfunctions {
/*********************** Input/Output functions. ************************/
      /* Open file from parent lock of this type and a simple filename
       * (no path specification). This will determine file type and
       * fetch the correct function to actually do the open.
       */
   struct CFSFH * (*Open)(glb, struct CFSLock *, char *, LONG);
      /* Read(), Write(), Seek(), Close() functions. */
   LONG (*Read)(glb, struct CFSFH *, UBYTE *, LONG );
   LONG (*Write)(glb, struct CFSFH *, UBYTE *, LONG );
   LONG (*Seek)(glb, struct CFSFH *, LONG, LONG );
   LONG (*Close)(glb, struct CFSFH *);
   BOOL (*SetFileSize)(glb, struct CFSFH *, LONG, LONG);
   BOOL (*LockRecord)(glb, struct CFSFH *, LONG, LONG, LONG, LONG);
   BOOL (*UnLockRecord)(glb, struct CFSFH *, LONG, LONG);
/*********************** Input/Output functions. ************************/
      /* Lock function. As with Open, the type refers to the parent lock. */
   struct CFSLock * (*Lock)(glb, struct CFSLock *, char *, LONG);
      /* Other functions related to locks. */
   struct CFSLock * (*DupLock)(glb, struct CFSLock *);
   BOOL (*UnLock)(glb, struct CFSLock *);   /* Always succesful. */
   BOOL (*Examine)(glb, struct CFSLock *, struct FileInfoBlock *);
   BOOL (*ExNext)(glb, struct CFSLock *, struct FileInfoBlock *);
   struct CFSLock * (*CreateDir)(glb, struct CFSLock *, char *);
   BOOL (*DeleteFile)(glb, struct CFSLock *, char *);
      /* Rename() is a bit tricky. As an example, how is a Rename()
       * from a powerpacked file to an archive to be handled?
		 * The correct Rename() function to call is determined from
		 * the type of the FROM directory. Each function must then
		 * check the type of the destination directory themselves.
       */
   BOOL (*Rename)(glb, struct CFSLock *, char *, struct CFSLock *, char *);
   struct CFSLock * (*Parent)(glb, struct CFSLock *);
   BOOL (*SetProtection)(glb, struct CFSLock *, char *, LONG);
   BOOL (*SetComment)(glb, struct CFSLock *, char *, char *);
   BOOL (*SetFileDate)(glb, struct CFSLock *, char *, struct DateStamp *);
   struct CFSFH *(*OpenFromLock)(glb, struct CFSLock *);
      /* ToDo: What is SameLock() really supposed to do, packet level?
       * In the CFS, internally, each filetype has a SameLock() that
       * expects two locks of the same type, and returns a bool.
       */
   BOOL (*SameLock)(glb, struct CFSLock *, struct CFSLock *);
      /* ToDo: Support for links also really needs some work... */
   BOOL (*MakeLink)(glb, struct CFSLock *, char *, void *, LONG);
   LONG (*ReadLink)();
   BOOL (*ChangeMode)(glb, LONG, void *, LONG);
   struct CFSLock * (*DupLockFromFH)(glb, struct CFSFH *);
   struct CFSLock * (*ParentOfFH)(glb, struct CFSFH *);
      /* The new 2.0 Examine..() type functions. ExAll() will be
       * simulated if NULL.
       */
   LONG (*ExAll)(glb, struct CFSLock *, char *, LONG, LONG, struct ExAllControl *);
   BOOL (*ExamineFH)(glb, struct CFSFH *, struct FileInfoBlock *);
      /* ToDo: The notify functions still need some thought. Remember,
       * a notify is on an absolute path, not relative to a Lock.
       */
   BOOL (*StartNotify)(glb, struct NotifyRequest *);
   BOOL (*EndNotify)(glb, struct NotifyRequest *);
};

extern struct cfsfunctions Xfunc,Xpkfunc;


/* Prototypes. */
/* CFS.c */
struct DosPacket *getpkt(glb glob);
ULONG getpktsigmask(glb glob);
struct DosPacket *checkpkt(glb glob);
void returnpkt(struct DosPacket *pkt,LONG res1,LONG res2,glb glob);
extern int sprintf(char *,const char *,...);
struct MsgPort *DoDeviceProc(LONG *res2,char *filedesc,glb glob);
BPTR getfile(char * desc,glb glob);
void closefile(BPTR file,glb glob);
void addvolnode(glb glob, struct DeviceList *volnode);
BOOL removevolnode(glb glob, struct DeviceList *volnode);
void DevNode_Stuff_Startup_String(glb glob, BSTR value);
BOOL createvolnode(glb glob, BOOL fixroot, struct FileInfoBlock *fib);
BOOL SetVolumeNameVolNode(glb glob, char *name);
BOOL freevolnode(glb glob);
BOOL diskinfo(glb glob, struct InfoData *infodata);

/* Packet.c */
void putpkt(struct StandardPacket *pkt,struct MsgPort *procid,struct MsgPort *retport,LONG type,int numarg,...);
LONG dopkt(struct StandardPacket *pkt,struct MsgPort *procid,struct MsgPort *retport,LONG *res2,LONG type,int numarg,...);


/* dosfunc.c */
struct FileLock *xLock(glb glob, struct FileLock *parent, char *name, LONG mode);
BOOL xExists1(glb glob, struct FileLock *parent, char *name);
BOOL xExamine(glb glob, struct FileLock *lock, struct FileInfoBlock *fib);
BOOL xExamineNext(glb glob, struct FileLock *lock, struct FileInfoBlock *fib);
struct FileLock *xCreateDir(glb glob, struct FileLock *parent, char *name);
BOOL xDeleteFile(glb glob, struct FileLock *parent, char *name);
BOOL xRename(glb glob, struct FileLock *parent1, char *name1, struct FileLock *parent2, char *name2);
struct FileLock *xParentDir(glb glob, struct FileLock *lock);
struct FileLock *xParentFH(glb glob, struct FileHandle *fh);
BOOL xSetProtection(glb glob, struct FileLock *parent, char *name, LONG bits);
BOOL xSetComment(glb glob, struct FileLock *parent, char *name, char *comment);
BOOL xSetFileDate(glb glob, struct FileLock *parent, char *name, struct DateStamp *ds);
struct FileLock *xDupLock(glb glob, struct FileLock *lock);
BOOL xUnLock(glb glob, struct FileLock *lock);
struct FileHandle *xOpen(glb glob, struct FileLock *parent, char *name, LONG mode);
struct FileHandle *xOpenFromLock( glb glob, struct FileLock *lock );
struct FileHandle *xOpenFromCopyOfLock( glb glob, struct FileLock *lock );
BOOL xClose(glb glob, struct FileHandle *fh);
LONG xRead(glb glob, struct FileHandle *fh, void *buf, LONG len);
LONG xWrite(glb glob, struct FileHandle *fh, void *buf, LONG len);
LONG xSeek(glb glob, struct FileHandle *fh, LONG pos, LONG offset);
BOOL xChangeMode(glb glob, ULONG type, void *obj, ULONG mode);
BOOL xInfo(glb glob, struct FileLock *lock, struct InfoData *info);
LONG xSameLock( glb glob, struct FileLock *l1, struct FileLock *l2 );
BOOL xgetpath(glb glob, struct FileLock *Lock, char *f, int max);
BOOL TransformXFH(glb glob, struct FileHandle *srcfh, struct FileLock *parent, char *name, BOOL (*f)(glb, struct FileHandle *, struct FileHandle *, void *), void *userdata);
BOOL TransformFile(glb glob, struct FileLock *parent, char *name, BOOL (*f)(glb, struct FileHandle *, struct FileHandle *, void *), void *userdata);
LONG xGetFileSize(glb glob, struct FileHandle *fh);
BOOL xWriteStr(glb glob, struct FileHandle *fh, char *str);


/* misc.c */
char *copybstr(BSTR bstr);
char *copystr(char *str);
void freestr(char *str);
char *safebstr2cinplace(UBYTE *pp, int buflen);
BSTR safecstr2binplace(char *pp, int buflen);
LONG ank( glb glob, ... );
LONG ank_fail( glb glob, ... );
LONG owt( glb glob, ... );
LONG abs_seek_pos( LONG currentpos, LONG filelen, LONG pos, LONG offset );
LONG xFileSizeXfh( glb glob, struct FileHandle *xfh );


/* lock.c */
struct CFSLock *RawCFSLock(glb glob, struct CFSLock *lock, char * name, LONG mode );
struct FileLock * CreateFileLock( glb glob, struct CFSLock *lock );
struct CFSLock *CFSLockParent( glb glob, struct CFSLock *parentlock, char **nameptr );
struct CFSLock * CFSLock(glb glob,struct CFSLock * parentlock, char * name,LONG mode);
struct CFSLock *makerootlockdayone(glb glob);
struct CFSLock *CFSDupLock( glb glob, struct CFSLock *lock );
struct CFSLock *CFSParentDir( glb glob, struct CFSLock *lock);
struct CFSLock *CFSParentFH( glb glob, struct CFSFH *fh);
BOOL CFSUnLock( glb glob,struct CFSLock *lock);
BOOL CFSExamine( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib);
BOOL CFSExamineNext(glb glob, struct CFSLock *lock, struct FileInfoBlock *fib);
struct CFSLock *CFSCreateDir( glb glob, struct CFSLock *parent, char *name );
BOOL CFSDeleteFile( glb glob, struct CFSLock *parent, char *name );
BOOL CFSRename( glb glob, struct CFSLock *parent1, char *name1, struct CFSLock *parent2, char *name2 );
BOOL CFSSetProtection( glb glob, struct CFSLock *parent, char *name, LONG bits );
BOOL CFSSetComment( glb glob, struct CFSLock *parent, char *name, char *comment );
BOOL CFSSetDate( glb glob, struct CFSLock *parent, char *name, struct DateStamp *ds );
BOOL CFSSameLock( glb glob, struct CFSLock *l1, struct CFSLock *l2 );


/* file.c */
struct CFSFH *RawCFSOpen(glb glob, struct CFSLock *lock, char * name, LONG mode );
struct CFSFH *CFSOpen(glb glob,struct CFSLock * parentlock, char * name,LONG mode);
BOOL CFSClose( glb glob, struct CFSFH *fh );
LONG CFSRead( glb glob, struct CFSFH *fh, void *buf, LONG len );
LONG CFSWrite( glb glob, struct CFSFH *fh, void *buf, LONG len );
LONG CFSSeek( glb glob, struct CFSFH *fh, LONG pos, LONG offset );

/* pack.c */
LONG xFileType( glb glob, struct FileHandle *xfh );

/* xobj.c */
struct XpkFH *XpkOpenOldFile( glb glob, struct FileHandle *xfh );
LONG XObjClose( glb glob, struct CFSFH *fh );
LONG XObjRead( glb glob, struct CFSFH *fh, UBYTE *buf, LONG len );
LONG XObjWrite( glb glob, struct CFSFH *fh, UBYTE *buf, LONG len );
LONG XObjSeek( glb glob, struct CFSFH *fh, LONG pos, LONG offset );
void XObjStealXpkFH(glb glob, struct CFSFH *fh);
BOOL XObjStuffFH(glb glob, struct CFSFH *fh, char *name, struct CFSLock *parent);
void XObjUnStuffFH(glb glob, struct CFSFH *fh);
void XObjFreeFH(glb glob, struct CFSFH *fh);
struct CFSFH *XObjCreateFH(glb glob, struct FileHandle *xfh, LONG mode, char *name,struct CFSLock *parent);
struct CFSLock *XObjMakeLock( glb glob, struct FileLock *xlock, LONG mode );
struct CFSLock *XObjDupLock( glb glob, struct CFSLock *lock );
void XObjAddReferenceToLock(glb glob, struct CFSLock *lock);
struct CFSLock *XObjParentDir( glb glob, struct CFSLock *lock );
struct CFSLock *XObjParentFH( glb glob, struct CFSFH *fh);
BOOL XObjUnLock( glb glob, struct CFSLock *lock );
BOOL XObjSameLock(glb glob, struct CFSLock *l1, struct CFSLock *l2 );
BOOL XObjExamine( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib );
BOOL XObjExNext( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib );
BOOL ModifyFIB( glb glob, struct CFSLock *lock, struct FileInfoBlock *fib );
BOOL XObjModifyFIB( glb glob, struct CFSLock *lock,struct FileInfoBlock *fib, struct FileHandle *xfh );
struct CFSLock *XObjCreateDir( glb glob, struct CFSLock *parentlock, char *name );
BOOL XObjSetProtection(glb glob, struct CFSLock *parent, char *name, LONG mask);
BOOL XObjSetComment(glb glob, struct CFSLock *parent, char *name, char *comment);
BOOL XObjSetFileDate(glb glob, struct CFSLock *parent, char *name, struct DateStamp *ds);
BOOL XObjDeleteFile(glb glob, struct CFSLock *parent, char *name);
BOOL XObjRename(glb glob, struct CFSLock *p1, char *n1, struct CFSLock *p2, char *n2);


/* xpk.c */
struct XpkLock;
struct XpkFib;

struct XpkFH *XpkOpenOldFile( glb glob, struct FileHandle *xfh );
struct XpkFH *XpkOpenOldFileFromCopyOfLock( glb glob, struct XpkLock *lock );
BOOL IsXpkFile( glb glob, struct FileHandle *xfh );
BOOL PackFile2File(glb glob, struct FileHandle *srcxfh, struct FileHandle *dstxfh, void *dummy);
BOOL UnPackFile2File(glb glob, struct FileHandle *srcxfh, struct FileHandle *dstxfh, void *dummy);
BOOL XpkExamine_FH( glb glob, struct FileHandle *xfh, struct XpkFib *fib );
LONG Xpk_Read( glb glob, struct XpkFH *fh, UBYTE *buf, LONG len );
LONG Xpk_Write(glb glob, struct XpkFH *fh, UBYTE *buf, LONG len);
LONG Xpk_Seek( glb glob, struct XpkFH *fh, LONG pos, LONG offset );
BOOL Xpk_Close( glb glob, struct XpkFH *fh );
struct XpkLock *XpkMakeLock( glb glob, struct FileLock *xlock, LONG mode );
struct XpkLock *XpkDupLock( glb glob, struct XpkLock *lock );
struct CFSLock *XpkParentDir( glb glob, struct XpkLock *lock );
struct CFSLock *XpkParentFH( glb glob, struct XpkFH *XpkFH );
BOOL XpkUnLock( glb glob, struct XpkLock *lock );
BOOL XpkSameLock(glb glob, struct XpkLock *l1, struct XpkLock *l2 );
BOOL XpkObjExamine( glb glob, struct XpkLock *lock, struct FileInfoBlock *fib );
BOOL XpkModifyFIB( glb glob, struct XpkLock *lock,struct FileInfoBlock *fib, struct FileHandle *xfh );
BOOL XpkFastModifyFIB( struct FileInfoBlock *FIB );
BOOL InitXpk( glb glob );
void CleanupXpk( glb glob );


/* packfunc.c */
BOOL ModifyFIB_type( glb glob, LONG type, struct CFSLock *lock,	struct FileInfoBlock *fib, struct FileHandle *xfh );


/* options.c */
BOOL set_option(glb glob, char *p);
BOOL InitOptions(glb glob);
void CleanupOptions(glb glob);
BOOL SetOptionPermanent(glb glob, char *opt, char *val);
BOOL SetOptionsFromFile(glb glob, struct FileLock *lock, char *name);


/* arexx.c */
void checkarexxmsg(glb glob);
ULONG arexxsigmask(glb glob);
BOOL InitArexx(glb glob);
void CleanupArexx(glb glob);


/* gui.c */
BOOL UpdateXFHNode(glb glob);
ULONG guisigmask(glb glob);


/* End of CFS.h */
