/*
** file.c GFL Basisfunktionen Random Access Files
** (C) Helmut Leitner Software 1990-1995
*/

/**M File**/
/**MN File**/
/**MNK Funktionssammlung fr den Datentyp File.**/

#include <gf_all.h>

/*=*/

/**MV1**/
IN NetworkFlag=0;
/**MVK Zentrales Flag fr Multiuser-Filesharing (1=Locking EIN).**/
/* 1=Netzwerk EIN (multiuser locking ein) */

IN FileOpenModeNetwork     =(IN)FO_NET;
IN FileOpenMode            =(IN)FO_NONET;
IN FileOpenModeReadNetwork =(IN)FO_READNET;
IN FileOpenModeRead        =(IN)FO_READNONET;
IN FileOpenModeWriteNetwork=(IN)FO_WRITENET;
IN FileOpenModeWrite       =(IN)FO_WRITENONET;
IN FileOpenShareMode       =(IN)FO_PERM;

/**MV1**/
VO (*FileRedirectHandle)(CH *fnam)=NULL;
/**MVK
Handle fr die Umwandlung logischer in physikalischer Filename.
Siehe die Funktion 'FileRedirect'.
**/

/*=*//**MF1**/
VO FileRedirect(CH *fnam)
/**MFK Verwandelt logische in physikalische Filenamen.**/
{
   if(FileRedirectHandle) {
      (*FileRedirectHandle)(fnam);
   }
}
/**MFT
Die Funktion wirkt nur, wenn die Variable 'FileRedirectHandle' mit einer
entsprechenden Funktion belegt ist.
**/

/*=*//**MF1**/
INT_FILE FileOpenPlus(CH *fnam,IN ofmode,IN opmode,IN sflag)
/**MFK Öffnet einen File (Redirektion + open).**/
{
   INT_FILE f;
   CH rnam[MAXPATH];
   StrCpy(rnam,fnam);
   FileRedirect(rnam);
#if defined(TURBO_C)
   USE_N(sflag);
   f=open(rnam,ofmode,opmode);
#else
#if defined(HLS_UNIX)
   f=open(rnam,ofmode,opmode);
#else
   if(sflag) {
      f=sopen(rnam,ofmode,SH_DENYNO,opmode);
   } else {
      f=open(rnam,ofmode,opmode);
   }
#endif   
// MessNormal("FileOpenPlus %s (fnr=%hd) ofm=%hd opm=%hd sflag=%hd",rnam,f,ofmode,opmode,sflag);
#endif
   return(f);
}
/**MFR Filehandle (oder bei Fehler -1).**/

/*=*//**MF1**/
INT_FILE FileOpen(CH *fnam)
/**MFK ™ffnet einen File zum Lesen und Schreiben.**/
{
   IN ofmode=NetworkFlag ? FileOpenModeNetwork : FileOpenMode;
   IN opmode=FileOpenShareMode;
   return FileOpenPlus(fnam,ofmode,opmode,NetworkFlag);
}
/**MFR Filehandle (oder bei Fehler -1).**/

/*=*//**MF1**/
INT_FILE FileOpenRead(CH *fnam)
/**MFK ™ffnet einen File frs Lesen.**/
{
   IN ofmode=NetworkFlag ? FileOpenModeReadNetwork : FileOpenModeRead;
   IN opmode=FileOpenShareMode;
   return FileOpenPlus(fnam,ofmode,opmode,NetworkFlag);
}
/**MFR Filehandle (oder bei Fehler -1).**/

/*=*//**MF1**/
INT_FILE FileOpenWrite(CH *fnam)
/**MFK ™ffnet einen File frs Schreiben.**/
{
   IN ofmode=NetworkFlag ? FileOpenModeWriteNetwork : FileOpenModeWrite;
   IN opmode=FileOpenShareMode;
   return FileOpenPlus(fnam,ofmode,opmode,NetworkFlag);
}
/**MFR Filehandle (oder bei Fehler -1).**/

/*=*/
/**MF1**/
INT_FILE FileCreate(CH *fnam)
/**MFK Erzeugt einen neuen File.**/
{
   IN ofmode=NetworkFlag ? FileOpenModeNetwork : FileOpenMode;
   IN opmode=FileOpenShareMode;
   return FileOpenPlus(fnam,ofmode|O_CREAT|O_TRUNC,opmode,NetworkFlag);
}
/**MFR Filehandle (oder bei Fehler -1).**/

/*=*//**MF1**/
ER FileClose(INT_FILE *pf)
/**MFK Schlieát einen offenen File.**/
{
   INT_FILE f= *pf;
   if(f<0) {
      return(-1);
   }   
   close(f);
   *pf=-1;
   return(0);
}

/*=*//**MF1**/
IN FileDelete(CH *fnam)
/**MFK L”scht einen File (Redirektion + unlink).**/
{
   IN stat;
   CH rnam[MAXPATH];
   StrCpy(rnam,fnam);
   FileRedirect(rnam);
   stat=unlink(rnam);
   return(stat);
}

/*=*//**MF1**/
ER FileRename(CH *fnam1,CH *fnam2)
/**MFK Žndert den Namen eines Files.**/
{
   IN stat;
   CH rnam1[MAXPATH];
   CH rnam2[MAXPATH];
   StrCpy(rnam1,fnam1); FileRedirect(rnam1);
   StrCpy(rnam2,fnam2); FileRedirect(rnam2);
   stat=rename(rnam1,rnam2);
   return(stat);
}

/*=*//**MF1**/
IN FileExist(CH *fnam)
/**MFK Liefert ein Flag fr die Existenz eines Files.**/
{
   INT_FILE f=-1;
   f=FileOpenRead(fnam);
   if(f<0) {
      return(0);
   }
   FileClose(&f);
   return(1);
}

/*=*//**MF1**/
OS FileWriteLen(INT_FILE f,VO *buf,OS len)
/**MFK Liest einen Bufferbereich von der aktuellen Fileposition.**/
{
   return write(f,buf,len);
}
/**MFR Tats„chlich geschriebene Byte-Anzahl.**/

/*=*/
/**MF1**/
OS FileReadLen(INT_FILE f,VO *buf,OS len)
/**MFK Schreibt einen Bufferbereich an der aktuellen Fileposition.**/
{
   return read(f,buf,len);
}
/**MFR Tats„chlich gelesene Byte-Anzahl.**/

/*=*//**MF1**/
ER FilePosWrite(INT_FILE f,LO pos,VO *buf,OS len)
/**MFK Schreibt einen Bufferbereich in einen Filebereich. **/
{
   LO apos;
   OS alen;
   
   apos=lseek(f,pos,0);
   if(pos!=apos) {
      return(-1);
   }
   alen=write(f,buf,len);
   if(len!=alen) {
      return(-2);
   }
   return(0);
}

/*=*//**MF1**/
ER FilePosRead(INT_FILE f,LO pos,VO *buf,OS len)
/**MFK Liest einen Filebereich in einen vorhandenen Bufferbereich.**/
{
   LO apos;
   OS alen;
   apos=lseek(f,pos,0);
   if(pos!=apos) {
      return(-1);
   }
   alen=read(f,buf,len);
   if(len!=alen) {
      return(-1);
   }
   return(0);
}

/*=*//**MF1**/
ER FileRead(CH *fnam,VO *adr,OS maxsize)
/**MFK Liest einen File in einen vorhanden Bufferbereich ein.**/
{
   INT_FILE f;                                                                               
   LO fsize;
   LO alen;

   f=FileOpenRead(fnam);
   if(f<0) {
      return(-1);
   }
   fsize=FileRetSize(f);
   if(fsize>(LO)maxsize) {
      MessErrorFmt("FileRead: len=%ld Buffer=%lu %s",fsize,(UL)maxsize,MessStr_OutOfRange[MessLanguage]);
   }
   alen=read(f,adr,maxsize);
   FileClose(&f);
   if(alen!=fsize) {
      return(-1);
   }
   return(0);
}

/*=*//**MF1**/
ER FileWrite(CH *fnam,VO *adr,OS len)
/**MFK Schreibt einen Speicherinhalt in einen File.**/
{
   INT_FILE f;
   OS alen;
   f=FileCreate(fnam);
   if(f<0) {
      return(-1);
   }
   alen=write(f,adr,len);
   if(alen!=len) {
      return(-2);
   }
   FileClose(&f);
   return(0);
}

/*=*/
/**MF1**/
CH *FileReadSavePlus(CH *fnam,OS headbytes,OS tailbytes,UL *pflen)
/**MFK Žhnlich FileReadSave. Allokiert zus„tzliche Bytes. **/                                      
{
   INT_FILE f=FileOpenRead(fnam);
   OS rlen;
   CH *p;

   if(f<0) {
      return(NULL);
   }
   *pflen=FileRetSize(f);
   rlen=(OS)*pflen;
   if(rlen!=(*pflen)) {
      return(NULL);
   }
   if(tailbytes==0) {
      tailbytes=1;
   }   
   p=PtrAllocClear((LO)headbytes+rlen+tailbytes);
   if(p) {
      if(FilePosRead(f,0L,p+headbytes,rlen)) {
         PtrFree(&p);
         return(NULL);
      }
   }
   FileClose(&f);
   return(p);
}

/**MF1**/
CH *FileReadSave(CH *fnam)
/**MFK Liest einen File in dynamisch allokierten Speicher.**/
/**MFR Pointer oder NULL (File fehlt/Speichermangel).**/
{
   UL dummy;
   return FileReadSavePlus(fnam,0,0,&dummy);
}

/*=*//**MF1**/
VO FileFlush(INT_FILE f)
/**MFK Erzwingt das Schreiben gebufferter Fileinhalte.**/
{
   INT_FILE fdup=dup(f);
   if(fdup>=0) {
      close(fdup);
   }
}

