// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1994
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        plainfile.C
// 
// Purpose:     
// 
// Created:     4 May 95   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// $Id: plainfile.C,v 1.10 1997/01/29 15:01:09 gorasche Exp $
//
// $Log: plainfile.C,v $
// Revision 1.10  1997/01/29 15:01:09  gorasche
// derived methods for different file I/O under WIn32
// ::errno moved to errno, otherwise NT is not compiling
//
// Revision 1.9  1996/10/03 15:59:07  jfasch
// adaptions due to moving it from the previous location in DcCommon to HgUtilities
//
// Revision 1.8  1996/07/22 08:18:19  jfasch
// *** empty log message ***
//
// Revision 1.7  1996/05/14 09:35:17  jfasch
// changed File to read DcFile because of namespace issues
//
// Revision 1.6  1996/03/22 16:23:11  jfasch
// *** empty log message ***
//
// Revision 1.5  1996/02/21 14:32:47  jfasch
// due to changes to class File had to remove set_close_() and get_close_().
//
// Revision 1.4  1995/12/31 09:59:33  jfasch
// - minor pretty(ugly)fying changes
//
// Revision 1.3  1995/12/27 11:46:11  jfasch
// - RCSified
//
// 
// </file> 
#include "plainfile.h"

#include "assert.h"

// both for perror() on the various platforms
#include <stdio.h>
#include <errno.h>

#ifndef VERBOSE
#  define VERBOSE
#endif
#include "verbose.h"



// --------------------------------------------------------------------
const char* PlainFile :: version1 = "$Id" ;

PlainFile :: PlainFile()
: HgFile() {}

PlainFile :: PlainFile (int fd)
: HgFile (fd) {}

PlainFile :: PlainFile (const char* path, int flags, int mode) {
   open (path, flags, mode) ;
}
PlainFile :: ~PlainFile() {
   if (! closed())
      close() ;
}

boolean PlainFile :: open (const char* path, int flags, int mode) {
   hgassert (fd()<0, "PlainFile::open(): already using a file number") ;

   int file = ::open (path, flags, mode) ;
   if (file < 0) {
      set_errno_(errno) ;
      perror_("PlainFile::open(): ::open()") ;
      return false ;
   }

   set_fd_(file) ;
   return true ;
}

boolean PlainFile :: sync() {
   hgassert (fd()>=0, "PlainFile::sync(): not using a file number yet") ;
   if (::fsync (fd()) < 0) {
      set_errno_(errno) ;
      perror_("PlainFile::sync(): ::fsync()") ;
      return false ;
   }
   return true ;
}

boolean PlainFile :: trunc (off_t offset) {
   hgassert (fd()>=0, "PlainFile::trunc(): not using a file number yet") ;
   if (::ftruncate (fd(), offset) < 0) {
      set_errno_(errno) ;
      perror_("PlainFile::trunc(): ::ftruncate()") ;
      return false ;
   }
   return true ;
}

off_t PlainFile :: seek (off_t offset, int whence) {
   hgassert (fd()>=0, "PlainFile::seek(): not using a file number yet") ;
   off_t rv = ::lseek (fd(), offset, whence) ;
   if (rv < 0) {
      set_errno_(errno) ;
      perror_("PlainFile::seek(): lseek()") ;
   }
   return rv ;
}

// gorasche
// this is overloaded in Win32, because we can't write on sockets the same way...
#ifdef WIN32
int PlainFile::write(const char* buf, int nbytes)
{
   hgassert (fd()>=0, "PlainFile::write: invalid file number") ;
   int nwritten ;
   while((nwritten=::write(fd(),buf,nbytes)) < 0 && WSAGetLastError()==WSAEINTR);
   if (nwritten < 0)
   {
      set_errno_(errno);
      ::perror ("PlainFile::write()");
   }
   return nwritten;
}

int PlainFile::read(char* buf, int nbytes)
{
   hgassert (fd()>=0, "PlainFile::read(): invalid file number") ;
   int nread ;
   while((nread=::read(fd(),buf,nbytes)) < 0 && WSAGetLastError()==WSAEINTR);
   if (nread < 0)
   {
      set_errno_(errno);
      ::perror ("PlainFile::read()") ;
   }
   return nread;
}
#endif