/****************************************************************************
**  SIONLIB     http://www.fz-juelich.de/jsc/sionlib                       **
*****************************************************************************
**  Copyright (c) 2008-2015                                                **
**  Forschungszentrum Juelich, Juelich Supercomputing Centre               **
**                                                                         **
**  See the file COPYRIGHT in the package base directory for details       **
****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <assert.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "sion.h"
#include "sion_debug.h"
#include "sion_internal.h"
#include "sion_file.h"



/*!\brief Create and open a new file for writing
 *
 * @param  fname               filename to use
 * @param  flags               flags
 * @param  addflags            optional additional flags
 *
 * @return  file handle
 */
_sion_fileptr   *_lsion_file_open(const char *fname, unsigned int flags, unsigned int addflags)  {

  _sion_fileptr *sion_fileptr;

  /* allocate file pointer structure */
  sion_fileptr = _lsion_file_alloc_and_init_sion_fileptr();
  
  if(flags & SION_FILE_FLAG_ANSI) {
    sion_fileptr->flags |= SION_FILE_FLAG_ANSI;
    if(flags & SION_FILE_FLAG_WRITE) {
      sion_fileptr->flags |= SION_FILE_FLAG_WRITE;

      if(flags & SION_FILE_FLAG_CREATE) {
	sion_fileptr->flags |= SION_FILE_FLAG_CREATE;
	sion_fileptr->fileptr=_lsion_file_open_ansi_write_create(fname,addflags);
      } else {
	sion_fileptr->fileptr=_lsion_file_open_ansi_write_existing(fname,addflags);
      }
    } else {
      sion_fileptr->flags |= SION_FILE_FLAG_READ;
      sion_fileptr->fileptr=_lsion_file_open_ansi_read(fname,addflags);
    }
  } else {
    if (flags & SION_FILE_FLAG_POSIX) {
      sion_fileptr->flags |= SION_FILE_FLAG_POSIX;

      if(flags & SION_FILE_FLAG_WRITE) {
	sion_fileptr->flags |= SION_FILE_FLAG_WRITE;
	if(flags & SION_FILE_FLAG_CREATE) {
	  sion_fileptr->flags |= SION_FILE_FLAG_CREATE;
	  sion_fileptr->fd=_lsion_file_open_posix_write_create(fname,addflags);
      } else {
	sion_fileptr->fd=_lsion_file_open_posix_write_existing(fname,addflags);
	}
      } else {
	sion_fileptr->flags |= SION_FILE_FLAG_READ;
	sion_fileptr->fd=_lsion_file_open_posix_read(fname,addflags);
      }
    }
  }

  /* could not open ANSI file */
  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI ) {
    if(!sion_fileptr->fileptr) {
      free(sion_fileptr);
      _lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"error: could not open file (ANSI), %s %d %d, aborting ...\n", fname, flags, addflags);
      return(NULL);
    }
  }

  /* could not open POSIX file */
  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX ) {
    if(sion_fileptr->fd<0) {
      free(sion_fileptr);
      _lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"error: could not open file (POSIX), %s %d %d, aborting ...\n", fname, flags, addflags);
      return(NULL);
    }
  }

  /* unknown mode? */
  if(sion_fileptr->flags == 0) {
    free(sion_fileptr);
    _lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"internal error: unknown open type, %s %d %d, aborting ...\n", fname, flags, addflags);
    return(NULL);
  }

  return(sion_fileptr);
}


#define DFUNCTION "_lsion_file_close"
/*!\brief Close file and destroys fileptr structure
 *
 * @param[in,out]  sion_fileptr  file handle
 *
 * @return SION_SUCCESS if success
 */
int  _lsion_file_close( _sion_fileptr *sion_fileptr ) {
  int rc = SION_SUCCESS;
  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI) {
      _lsion_file_close_ansi(sion_fileptr->second_fileptr);
      sion_fileptr->second_fileptr=NULL;
    }
    rc=_lsion_file_close_ansi(sion_fileptr->fileptr);
    sion_fileptr->fileptr=NULL;
  } 
  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    rc=_lsion_file_close_posix(sion_fileptr->fd);
  }

  DPRINTFP((32, DFUNCTION, -1, "free now fileptr=%x %d rc=%d\n",sion_fileptr,sion_fileptr->flags,rc));

  free(sion_fileptr);

  return (rc);
}
#undef DFUNCTION

/*!\brief Write data to file
 *
 * @param  data                 pointer to data
 * @param  bytes                number of bytes to write
 * @param  sion_fileptr         file handle
 *
 * @return  number of bytes to written
 */
sion_int64 _lsion_file_write(const void *data, sion_int64 bytes, _sion_fileptr *sion_fileptr ) {
  sion_int64 bytes_written=0;
  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  bytes_written=_lsion_file_write_ansi(data,bytes,sion_fileptr->second_fileptr);
    else                                               bytes_written=_lsion_file_write_ansi(data,bytes,sion_fileptr->fileptr);
  } else if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    bytes_written=_lsion_file_write_posix(data,bytes,sion_fileptr->fd);
  } else {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_lsion_file_write: cannot find valid file flag (flags=%d)\n",sion_fileptr->flags));
  }
  return(bytes_written);
}

/*!\brief Read data from file
 *
 * @param  data                 pointer to data
 * @param  bytes                number of bytes to write
 * @param  sion_fileptr         file handle
 *
 * @return  number of bytes to read
 */
sion_int64 _lsion_file_read(void *data, sion_int64 bytes, _sion_fileptr *sion_fileptr ) {

  sion_int64 bytes_read=0;
  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  bytes_read=_lsion_file_read_ansi(data,bytes,sion_fileptr->second_fileptr);
    else                                               bytes_read=_lsion_file_read_ansi(data,bytes,sion_fileptr->fileptr);
  } else if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    bytes_read=_lsion_file_read_posix(data,bytes,sion_fileptr->fd);
  } else {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_lsion_file_read: cannot find valid file flag (flags=%d)\n",sion_fileptr->flags));
  }
  return (bytes_read);
}


/*!\brief Get optional file system block size for a file
 *
 * @param  sion_fileptr  fileptr
 *
 * @return  blocksize or -1 if not defined
 */
long _lsion_file_get_opt_blksize( _sion_fileptr *sion_fileptr ) {
  long opt_size=SION_SIZE_NOT_VALID;

  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    opt_size=_lsion_file_get_opt_blksize_ansi(sion_fileptr->fileptr);
  }

  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    opt_size=_lsion_file_get_opt_blksize_posix(sion_fileptr->fd);
  }

  return (opt_size);
}

/*!\brief Check if file exists  (LARGE_FILE support on BlueGene)
 *
 * @param  *fname               filename to use
 *
 * @return flag                 0 or 1
 */
int _lsion_file_stat_file(const char *fname) {
  struct stat sbuf;
  int file_exists=0;

#if defined(_SION_LINUX)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#elif defined(_SION_DARWIN)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#elif defined(_SION_AIX)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#elif defined(_SION_BGL)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#elif defined(_SION_BGP)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#elif defined(_SION_BGQ)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#elif defined(_SION_XT)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#endif
  return (file_exists);
}

/*!\brief Set new position in file
 *
 * @param  sion_fileptr         fileptr
 * @param  startpointer         new position
 *
 * @return  new position in file, -1 if fails
 */
sion_int64 _lsion_file_set_position( _sion_fileptr *sion_fileptr, sion_int64 startpointer ) {
  sion_int64 posinfile=SION_SIZE_NOT_VALID;

  /* needed to flush data written before set fp to new position */
#ifdef FLUSH_BEFORE_SETPOS
  _sion_flush_file_fp(sion_fileptr);
#endif

  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      posinfile=_lsion_file_set_position_ansi(sion_fileptr->second_fileptr, startpointer);
    } else {
      posinfile=_lsion_file_set_position_ansi(sion_fileptr->fileptr, startpointer);
    }
  }

  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    posinfile=_lsion_file_set_position_posix(sion_fileptr->fd, startpointer);
  }

  return (posinfile);
}


/*!\brief Get new position in file
 *
 * @param  sion_fileptr  fileptr
 *
 * @return  new position in file, -1 if fails
 */
sion_int64 _lsion_file_get_position( _sion_fileptr *sion_fileptr ) {
  sion_int64 posinfile=SION_SIZE_NOT_VALID;

  /* needed to flush data written before set fp to new position */
#ifdef FLUSH_BEFORE_SETPOS
  _lsion_flush_file(sion_fileptr);
#endif

  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      posinfile=_lsion_file_get_position_ansi(sion_fileptr->second_fileptr);
    } else {
      posinfile=_lsion_file_get_position_ansi(sion_fileptr->fileptr);
    }
  }

  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    posinfile=_lsion_file_get_position_posix(sion_fileptr->fd);
  }

  return (posinfile);
}


/*!\brief flush data to file
 *
 * @param  sion_fileptr  fileptr
 *
 * @return  SION_SUCCESS if ok
 */
int _lsion_file_flush( _sion_fileptr *sion_fileptr ) {
  int rc=SION_SUCCESS;

  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      rc=_lsion_file_flush_ansi(sion_fileptr->second_fileptr);
    } else {
      rc=_lsion_file_flush_ansi(sion_fileptr->fileptr);
    }
  }

  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    rc=_lsion_file_flush_posix(sion_fileptr->fd);
  }

  return (rc);
}

/*!\brief purge data to file
 *
 * @param  sion_fileptr  fileptr
 *
 * @return  SION_SUCCESS if ok
 */
int _lsion_file_purge( _sion_fileptr *sion_fileptr ) {
  int rc=SION_SUCCESS;

  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      rc=_lsion_file_purge_ansi(sion_fileptr->second_fileptr);
    } else {
      rc=_lsion_file_purge_ansi(sion_fileptr->fileptr);
    }
  }

  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    rc=_lsion_file_purge_posix(sion_fileptr->fd);
  }

  return (rc);
}

/*!\brief set buffer of fp
 *
 * @param  *sion_fileptr        file handle
 * @param  *buffer              pointer buffer
 * @param  *buffer_size         buffer size
 *
 * @retval SION_SUCCESS if OK
 */
int _lsion_file_set_buffer(_sion_fileptr *sion_fileptr, char *buffer, sion_int32 buffer_size) {

  int rc=SION_SUCCESS;

  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      rc=_lsion_file_set_buffer_ansi(sion_fileptr->second_fileptr, buffer, buffer_size);
    } else {
      rc=_lsion_file_set_buffer_ansi(sion_fileptr->fileptr, buffer, buffer_size);
    }
  }

  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    rc=_lsion_file_set_buffer_posix(sion_fileptr->fd, buffer, buffer_size);
  }

  return (rc);

}

/*!\brief Set second fileptr for file if opened with ANSI
 *
 * @param  sion_fileptr         file handle
 * @param  fileptr              second file pointer
 *
 * @return rc                   SION_SUCCESS if success
 */
int _lsion_file_set_second_fileptr( _sion_fileptr *sion_fileptr, FILE* fileptr) {
  int rc=SION_SUCCESS;
  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"internal error: second fileptr already set, aborting ...\n"));
    }
    sion_fileptr->flags |= SION_FILE_FLAG_SCNDANSI;
    sion_fileptr->second_fileptr=fileptr;
  } else {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"internal error: second fileptr could not be set for POSIX file, aborting ...\n"));
  }
  return (rc);
}

/*!\brief Unset second fileptr for file if opened with ANSI
 *
 * @param  sion_fileptr         file handle
 *
 * @return rc                   SION_SUCCESS if success
 */
int _lsion_file_unset_second_fileptr( _sion_fileptr *sion_fileptr) {
  int rc=SION_SUCCESS;
  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      sion_fileptr->flags &= ~SION_FILE_FLAG_SCNDANSI;
      sion_fileptr->second_fileptr=NULL;
    } else {
      return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"internal error: second fileptr was not set, aborting ...\n"));
    }
  } else {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"internal error: second fileptr could not be unset for POSIX file, aborting ...\n"));
  }
  return (rc);
}

/*!\brief Utility function: Get POSIX fp
 *
 * @param  sion_fileptr         file handle
 *
 * @return fd                   if success
 */
int _lsion_file_get_fd( _sion_fileptr *sion_fileptr) {
  int fd=SION_ID_UNDEF;
  if(sion_fileptr->flags & SION_FILE_FLAG_POSIX) {
    fd=sion_fileptr->fd;
  }
  if(sion_fileptr->flags & SION_FILE_FLAG_ANSI) {
    if(sion_fileptr->flags & SION_FILE_FLAG_SCNDANSI)  {
      fd=fileno(sion_fileptr->second_fileptr);
    } else {
      fd=fileno(sion_fileptr->fileptr);
    }
  }

  return (fd);
}



/* ********************************************************************************************** */
/* *** INTERFACE Functions                                                                        */
/* ********************************************************************************************** */

/*!\brief ANSI: Create and open a new file for writing
 *
 * @param  *fname               filename to use
 * @param  addflags             optional additional flags
 *
 * @return fileptr              file handle
 */
FILE  *_lsion_file_open_ansi_write_create(const char *fname, unsigned int addflags) {
  FILE     *fileptr=NULL;
#if defined(_SION_LINUX)
  fileptr = fopen(fname, "w");
#elif defined(_SION_DARWIN)
  fileptr = fopen(fname, "w");
#elif defined(_SION_AIX)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "w");

  }
#elif defined(_SION_BGL)
  fileptr = fopen(fname, "w");
#elif defined(_SION_BGP)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "w");

  }
#elif defined(_SION_BGQ)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "w");

  }
#elif defined(_SION_XT)
  fileptr = fopen(fname, "w");
#endif
  return (fileptr);
}

/*!\brief ANSI: Open a new file for writing
 *
 * @param  *fname               filename to use
 * @param  addflags             optional additional flags
 *
 * @return fileptr              file handle
 */
FILE  *_lsion_file_open_ansi_write_existing(const char *fname, unsigned int addflags) {
  FILE     *fileptr=NULL;
#if defined(_SION_LINUX)
  /* changed from w to r+ to prevent time truncation of empty existing file */
  fileptr = fopen(fname, "r+");
#elif defined(_SION_DARWIN)
  fileptr = fopen(fname, "r+");
#elif defined(_SION_AIX)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "r+");

  }
#elif defined(_SION_BGL)
  fileptr = fopen(fname, "r+");
#elif defined(_SION_BGP)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_RDWR;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "r+");

  }
#elif defined(_SION_BGQ)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_RDWR;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "r+");

  }
#elif defined(_SION_XT)
  fileptr = fopen(fname, "r+");
#endif
  return (fileptr);
}


/*!\brief ANSI: Open a file for reading
 *
 * @param  *fname               filename to use
 * @param  addflags             optional additional flags
 *
 * @return fileptr              file handle
 */
FILE *_lsion_file_open_ansi_read(const char *fname, unsigned int addflags) {
  FILE     *fileptr=NULL;
#if defined(_SION_LINUX)
  fileptr = fopen(fname, "r");
#elif defined(_SION_DARWIN)
  fileptr = fopen(fname, "r");
#elif defined(_SION_AIX)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_RDONLY;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "r");

  }
#elif defined(_SION_BGL)
  fileptr = fopen(fname, "r");
#elif defined(_SION_BGP)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_RDONLY;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "r");

  }
#elif defined(_SION_BGQ)
  {
    int       fd_oflag = 0;
    int       fd;

    fd_oflag |= O_RDONLY;
    fd = open64(fname, fd_oflag, 0664);

    fileptr = fdopen(fd, "r");

  }
#elif defined(_SION_XT)
  fileptr = fopen(fname, "r");
#endif
  return (fileptr);
}

/*!\brief ANSI: Close a file
 *
 * @param  *fileptr             ANSI file pointer 
 *
 * @return rc                   SION_SUCCESS ok
 */ int _lsion_file_close_ansi(FILE *fileptr) {
  int rc=SION_SUCCESS;
  int frc;
#if defined(_SION_LINUX)
  frc= fclose(fileptr);
#elif defined(_SION_DARWIN)
  frc= fclose(fileptr);
#elif defined(_SION_AIX)
  frc= fclose(fileptr);
#elif defined(_SION_BGL)
  frc= fclose(fileptr);
#elif defined(_SION_BGP)
  frc= fclose(fileptr);
#elif defined(_SION_BGQ)
  frc= fclose(fileptr);
#elif defined(_SION_XT) 
  frc= fclose(fileptr);
#endif
  if(frc) rc=SION_NOT_SUCCESS;
  return(rc);
}

/*!\brief ANSI: Get optional file system block size for a file
 *
 * @param  fileptr  fileptr
 *
 * @return  blocksize or -1 if not defined
 */
long _lsion_file_get_opt_blksize_ansi( FILE *fileptr ) {
  struct stat sbuf;
  int fd;
  long opt_size=SION_SIZE_NOT_VALID;
  
  fd = fileno(fileptr);

#if defined(_SION_LINUX)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_DARWIN)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_AIX)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_BGL)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_BGP)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_BGQ)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_XT)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#endif
  return (opt_size);
}

/*!\brief ANSI: Set the start position for the current task
 *
 * @param  *fileptr                     file handle
 * @param  startpointer         the position for the current task
 *
 * @return  new position in file, -1 if fails
 */
sion_int64 _lsion_file_set_position_ansi(FILE *fileptr, sion_int64 startpointer) {

  sion_int64 newpos = SION_SIZE_NOT_VALID;

  DPRINTFP((32, "_sion_set_position_ansi", -1, "enter (to %lld) (to %ld)\n", (long long) startpointer, (long) startpointer));

#if defined(_SION_LINUX)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    int       fd;
    fd = fileno(fileptr);
    if (offset != startpointer) {
      DPRINTFP((32, "_sion_set_position_ansi", -1, "_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			      offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
      return(_lsion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			      offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    newpos = result = lseek(fd, offset, SEEK_SET);
    DPRINTFP((1024, "_sion_set_position_ansi", -1, "set position=%lld  (LINUX)\n", (long long) result)); 
  }
#elif defined(_SION_DARWIN)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    if (offset != startpointer) {
      return(_lsion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			      offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    newpos = result = fseek(fileptr, offset, SEEK_SET);
    DPRINTFP((1024, "_sion_set_position_ansi", -1, "set position=%lld  (LINUX)\n", (long long) result));
  }
#elif defined(_SION_AIX)
  off64_t   offset = (off_t) startpointer;
  off64_t   result;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  result = fseeko64(fileptr, offset, SEEK_SET);
  newpos = result = ftello64(fileptr);
#elif defined(_SION_BGL)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  int       fd;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  fd = fileno(fileptr);
  newpos = result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_BGP)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  int       fd;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  fd = fileno(fileptr);
  newpos = result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_BGQ)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  int       fd;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  fd = fileno(fileptr);
  newpos = result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_XT)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    int       fd;
    if (offset != startpointer) {
    return(_lsion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_set_position_ansi: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    fd = fileno(fileptr);
    newpos = result = lseek(fd, offset, SEEK_SET);
  }
#endif
  DPRINTFP((32, "_sion_set_position_ansi", -1, "leave (to %lld)\n",(long long) startpointer));

  return (newpos);
}


/*!\brief ANSI: Get the current position in file
 *
 * @param  *fileptr                     file handle
 *
 * @retval position in file
 */
sion_int64 _lsion_file_get_position_ansi(FILE *fileptr) {

  sion_int64 result;
#if defined(_SION_LINUX)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd,0,SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (LINUX)\n", (long) result));
  }
#elif defined(_SION_DARWIN)
  {
    off_t     resulto;
    resulto = ftello(fileptr);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (DARWIN)\n", (long) result)); 
  }
#elif defined(_SION_AIX)
  {
    result = ftell(fileptr);
    DPRINTFP((4096, "_sion_get_position", -1, "got position=%lld (AIX)\n", result));
  }
#elif defined(_SION_BGL)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "got position=%lld (BGL)\n", result));
  }
#elif defined(_SION_BGP)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "got position=%lld (BGP)\n", result));
  }
#elif defined(_SION_BGQ)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "got position=%lld (BGQ)\n", result));
  }
#elif defined(_SION_XT)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "got position=%lld (XT)\n", result));
  }
#endif

  return (result);
}


/*!\brief ANSI: Flush the data to the disk 
 *
 * @param  *fileptr             file handle
 *
 * @retval SION_SUCCESS if OK
 */
int _lsion_file_flush_ansi(FILE *fileptr) {

  int rc = SION_SUCCESS;
  int frc;

#if defined(_SION_BGP)
  frc=fflush(fileptr);
#elif defined(_SION_BGQ)
  frc=fflush(fileptr);
#else
  frc=fflush(fileptr);
#endif
  if(frc) rc=SION_NOT_SUCCESS;
  return (rc);
}


/*!\brief ANSI: Purge the data to the disk 
 *
 * @param  *fileptr             file handle
 *
 * @retval 1 if OK
 */
int _lsion_file_purge_ansi(FILE *fileptr) {

  int rc = SION_SUCCESS;
  int frc;

#if defined(_SION_BGP)
  /*   1: int fd = fileno(fileptr); */
  /*      fsync(fd); */
  /*  2: __fpurge(fileptr); */
  /*  restored to fflush due to a not working fpurge in scalasca */
  frc=fflush(fileptr);
#elif defined(_SION_BGQ)
  /*   1: int fd = fileno(fileptr); */
  /*      fsync(fd); */
  /*  2: __fpurge(fileptr); */
  /*  restored to fflush due to a not working fpurge in scalasca */
  frc=fflush(fileptr);
#else
  frc=fflush(fileptr);
#endif

  if(frc) rc=SION_NOT_SUCCESS;
  return (rc);
}




/*!\brief ANSI: set buffer of fp
 *
 * @param  *fileptr             file handle
 * @param  *buffer              pointer buffer
 * @param  *buffer_size         buffer size
 *
 * @retval SION_SUCCESS if OK
 */
int _lsion_file_set_buffer_ansi(FILE *fileptr, char *buffer, sion_int32 buffer_size) {

  int rc = SION_SUCCESS;
  int frc;

  DPRINTFP((32, "_lsion_file_set_buffer", -1, "set buffer of fileptr\n"));
#if defined(_SION_BGP)
  frc=setvbuf(fileptr, buffer, _IOFBF, (size_t) buffer_size);
#elif defined(_SION_BGQ)
  frc=setvbuf(fileptr, buffer, _IOFBF, (size_t) buffer_size);
#elif defined(_SION_AIX)
  frc=setvbuf(fileptr, buffer, _IOFBF, (size_t) buffer_size);
#else
  frc=setvbuf(fileptr, buffer, _IOFBF, (size_t) buffer_size);
#endif

  if(frc) rc=SION_NOT_SUCCESS;
  return (rc);
}


/*!\brief ANSI: Write data to file
 *
 * @param  data                 pointer to data
 * @param  bytes                number of bytes to write
 * @param  fileptr              file handle
 *
 * @return rc                   number of bytes to written
 */
sion_int64 _lsion_file_write_ansi(const void *data, sion_int64 bytes, FILE *fileptr ) {
  sion_int64  left,bsumwrote;
  size_t      bwrite, bwrote;
  char       *dataptr;
  
  left      = bytes;
  bsumwrote = 0;
  dataptr   = (char*) data;

  while (left > 0) {
    bwrite     = left;
    bwrote     = fwrite(dataptr, 1, bwrite, fileptr);
    left      -= bwrote;
    dataptr   += bwrote;
    bsumwrote += bwrote;
  }
  return (bsumwrote);
}

/*!\brief ANSI: Read data from file
 *
 * @param  data                 pointer to data
 * @param  bytes                number of bytes to write
 * @param  fileptr              file handle
 *
 * @return rc                   number of bytes to read
 */
sion_int64 _lsion_file_read_ansi(void *data, sion_int64 bytes, FILE *fileptr ) {

  sion_int64  left,bsumread;
  size_t      btoread, bread;
  char       *dataptr;
  
  left      = bytes;
  bsumread  = 0;
  dataptr   = (char*) data;
  bread     = 0;

  while ((left > 0) && (!feof(fileptr))) {
    btoread    = left;
    bread      = fread(dataptr, 1, btoread, fileptr);
    left      -= bread;
    dataptr   += bread;
    bsumread  += bread;
  }
  return (bsumread);
}




/*!\brief POSIX: Create and open a new file for writing
 *
 * @param  *fname               filename to use
 * @param  addflags             optional additional flags
 *
 * @return fileptr              file handle
 */
int _lsion_file_open_posix_write_create(const char *fname, unsigned int addflags) {

  int    fd;
  int    fd_oflag = 0;

#if defined(_SION_LINUX)
  fd_oflag |= O_CREAT | O_RDWR;
  fd = open(fname, fd_oflag, 0664);
#elif defined(_SION_DARWIN)
  fd_oflag |= O_CREAT | O_RDWR;
  fd = open(fname, fd_oflag, 0664);
#elif defined(_SION_AIX)
  fd_oflag |= O_CREAT | O_RDWR;
  fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGL)
    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGP)
    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGQ)
    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_XT)
    fd_oflag |= O_CREAT | O_RDWR;
    fd = open64(fname, fd_oflag, 0664);
#endif
  return (fd);
}

/*!\brief POSIX: Open a new file for writing
 *
 * @param  *fname               filename to use
 * @param  addflags             optional additional flags
 *
 * @return fileptr              file handle
 */
int  _lsion_file_open_posix_write_existing(const char *fname, unsigned int addflags) {

  int    fd;
  int    fd_oflag = 0;

#if defined(_SION_LINUX)
  fd_oflag |= O_RDWR;
  fd = open(fname, fd_oflag, 0664);
#elif defined(_SION_DARWIN)
  fd_oflag |= O_RDWR;
  fd = open(fname, fd_oflag, 0664);
#elif defined(_SION_AIX)
  fd_oflag |= O_RDWR;
  fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGL)
    fd_oflag |= O_RDWR;
    fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGP)
    fd_oflag |= O_RDWR;
    fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGQ)
    fd_oflag |= O_RDWR;
    fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_XT)
    fd_oflag |= O_RDWR|O_NOATIME;
    fd = open64(fname, fd_oflag, 0664);
#endif
  return (fd);
}

/*!\brief POSIX: Open a file for reading
 *
 * @param  *fname               filename to use
 * @param  addflags             optional additional flags
 *
 * @return fileptr              file handle
 */
int _lsion_file_open_posix_read(const char *fname, unsigned int addflags) {
  int    fd;
  int    fd_oflag = 0;

#if defined(_SION_LINUX)
  fd_oflag |= O_RDONLY;
  fd = open(fname, fd_oflag, 0664);
#elif defined(_SION_DARWIN)
  fd_oflag |= O_RDONLY;
  fd = open(fname, fd_oflag, 0664);
#elif defined(_SION_AIX)
  fd_oflag |= O_RDONLY;
  fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGL)
  fd_oflag |= O_RDONLY;
  fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGP)
  fd_oflag |= O_RDONLY;
  fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_BGQ)
  fd_oflag |= O_RDONLY;
  fd = open64(fname, fd_oflag, 0664);
#elif defined(_SION_XT)
  fd_oflag |= O_RDONLY|O_NOATIME;
  fd = open(fname, fd_oflag, 0664);
#endif
  return (fd);
}



/*!\brief POSIX: Close a file
 *
 * @param  fd                   POSIX file pointer 
 *
 * @return rc                   0 not ok; 1 ok
 */
int _lsion_file_close_posix(int fd) {
  int rc=SION_SUCCESS;
  int frc;

#if defined(_SION_LINUX)
  frc= close(fd);
#elif defined(_SION_DARWIN)
  frc= close(fd);
#elif defined(_SION_AIX)
  frc= close(fd);
#elif defined(_SION_BGL)
  frc= close(fd);
#elif defined(_SION_BGP)
  frc= close(fd);
#elif defined(_SION_BGQ)
  frc= close(fd);
#elif defined(_SION_XT) 
  frc= close(fd);
#endif

  if(frc) rc=SION_NOT_SUCCESS;
  return(rc);
}

/*!\brief POSIX: Get optional file system block size for a file
 *
 * @param  fd  file descriptor
 *
 * @return  blocksize or -1 if not defined
 */
long _lsion_file_get_opt_blksize_posix( int fd ) {
  struct stat sbuf;
  long opt_size=SION_SIZE_NOT_VALID;
  
#if defined(_SION_LINUX)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_DARWIN)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_AIX)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_BGL)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_BGP)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_BGQ)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#elif defined(_SION_XT)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#endif
  return (opt_size);
}



/*!\brief POSIX: Set the start position for the current task
 *
 * @param  fd                   file descriptor
 * @param  startpointer         the position for the current task
 *
 * @return  new position in file, -1 if fails
 */
sion_int64 _lsion_file_set_position_posix(int fd, sion_int64 startpointer) {
  sion_int64  newpos = SION_SIZE_NOT_VALID;

  DPRINTFP((32, "_sion_set_position_posix", -1, "enter (to %lld)\n", (long long) startpointer));

#if defined(_SION_LINUX)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    if (offset != startpointer) {
      return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_sion_set_position_posix: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			      offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    newpos = result = lseek(fd, offset, SEEK_SET);
    DPRINTFP((4096, "_sion_set_position_posix", -1, "set position=%lld  (LINUX)\n", (long long) result)); 
  }
#elif defined(_SION_DARWIN)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    if (offset != startpointer) {
      return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_sion_set_position_posix: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			      offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    newpos = result = lseek(fd, offset, SEEK_SET);
    DPRINTFP((4096, "_sion_set_position_posix", -1, "set position=%lld  (LINUX)\n", (long long) result));
  }
#elif defined(_SION_AIX)
  off64_t   offset = (off_t) startpointer;
  off64_t   result;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_sion_set_position_posix: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  newpos = result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_BGL)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_sion_set_position_posix: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  newpos = result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_BGP)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_sion_set_position_posix: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  newpos = result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_BGQ)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  if (offset != startpointer) {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_sion_set_position_posix: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
  }
  newpos = result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_XT)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    if (offset != startpointer) {
    return(_lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"_sion_set_position_posix: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    newpos = result = lseek(fd, offset, SEEK_SET);
  }
#endif
  DPRINTFP((32, "_sion_set_position_posix", -1, "leave (to %lld)\n",(long long) startpointer));

  return (newpos);
}

/*!\brief POSIX: Get the current position in file
 *
 * @param  fd                           file handle
 *
 * @retval position in file
 */
sion_int64 _lsion_file_get_position_posix(int fd) {

  sion_int64 result=SION_SIZE_NOT_VALID;

#if defined(_SION_LINUX)
  {
    off_t     resulto;
    resulto = lseek(fd,0,SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (LINUX)\n", (long) result));
  }
#elif defined(_SION_DARWIN)
  {
    off_t     resulto;
    resulto = lseek(fd,0,SEEK_CUR);
    /* resulto = ftello(fileptr); */
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (DARWIN)\n", (long) result)); 
  }
#elif defined(_SION_AIX)
  {
    off_t     resulto;
    resulto = lseek(fd,0,SEEK_CUR);
    /* resulto = ftello(fileptr); */
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (AIX)\n", (long) result)); 
  }
#elif defined(_SION_BGL)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (BGL)\n", (long) result)); 
  }
#elif defined(_SION_BGP)
  {
    off_t     resulto;
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (BGP)\n", (long) result)); 
  }
#elif defined(_SION_BGQ)
  {
    off_t     resulto;
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (BGQ)\n", (long) result)); 
  }
#elif defined(_SION_XT)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    DPRINTFP((4096, "_sion_get_position", -1, "get position=%ld  (XT)\n", (long) result)); 
  }
#endif

  return (result);
}

/*!\brief POSIX: Flush the data to the disk 
 *
 * @param  fd  file descriptor
 *
 * @retval SION_SUCCESS if OK
 */
int _lsion_file_flush_posix(int fd) {

  int rc = SION_SUCCESS;
  int frc; 
#if defined(_SION_BGP)
  frc=fsync(fd); 
#elif defined(_SION_BGQ)
  /* BGQ 20.09.13: bad fsync performance since V1R2M1, try without */
  /* rc=fsync(fd);  */
#else
  frc=fsync(fd); 
#endif

  if(frc) rc=SION_NOT_SUCCESS;
  return (rc);
}

/*!\brief POSIX: Purge the data to the disk 
 *
 * Purge is only relevant for ANSI, using fsync instead
 *
 * @param  fd  file descriptor
 *
 * @retval 1 if OK
 */
int _lsion_file_purge_posix(int fd) {

  int rc = SION_SUCCESS;
  int frc; 
#if defined(_SION_BGP)
  frc=fsync(fd); 
#elif defined(_SION_BGQ)
  /* BGQ 20.09.13: bad fsync performance since V1R2M1, try without */
  /* rc=fsync(fd);  */
#else
  frc=fsync(fd); 
#endif

  if(frc) rc=SION_NOT_SUCCESS;
  return (rc);
}

/*!\brief POSIX: set buffer of fd
 *
 * @param  fd                   file descriptor
 * @param  *buffer              pointer buffer
 * @param  *buffer_size         buffer size
 *
 * @retval  1 if OK
 */
int _lsion_file_set_buffer_posix(int fd, char *buffer, sion_int32 buffer_size) {

  int rc = SION_SUCCESS;
  int frc = 0; 
  DPRINTFP((32, "_lsion_file_set_buffer", -1, "set buffer of fileptr\n"));
#if defined(_SION_BGP)
#elif defined(_SION_AIX)
#else
#endif
  if(frc) rc=SION_NOT_SUCCESS;
  return (rc);
}

/*!\brief POSIX: Write data to file
 *
 * @param  data                 pointer to data
 * @param  bytes                number of bytes to write
 * @param  fd                   file handle
 *
 * @return rc                   number of bytes to written
 */
sion_int64 _lsion_file_write_posix(const void *data, sion_int64 bytes, int fd ) {
  sion_int64  left,bsumwrote;
  size_t      bwrite, bwrote;
  char       *dataptr;
  
  left      = bytes;
  bsumwrote = 0;
  dataptr   = (char*) data;

  while (left > 0) {
    bwrite     = left;
    bwrote     = write(fd, dataptr, bwrite);
    left      -= bwrote;
    dataptr   += bwrote;
    bsumwrote += bwrote;
  }
  return (bsumwrote);
}

/*!\brief POSIX: Read data from file
 *
 * @param  data                 pointer to data
 * @param  bytes                number of bytes to write
 * @param  fd                   file handle
 *
 * @return rc                   number of bytes to read
 */
sion_int64 _lsion_file_read_posix(void *data, sion_int64 bytes, int fd ) {

  sion_int64  left,bsumread;
  size_t      btoread, bread;
  char       *dataptr;
  
  left      = bytes;
  bsumread  = 0;
  dataptr   = (char*) data;
  bread     = 0;

  while (left > 0)  {
    btoread    = left;
    bread      = read(fd, dataptr, btoread);
    if(bread>0) {
      left      -= bread;
      dataptr   += bread;
      bsumread  += bread;
    } else {
      if(bread==0) return(bsumread);
      else         return(bread);
    }
  }
  return (bsumread);
}

/*!\brief Create and return _sion_fileptr
 *
 * @return _sion_fileptr
 */
_sion_fileptr *_lsion_file_alloc_and_init_sion_fileptr() {
  _sion_fileptr *sion_fileptr;

  sion_fileptr = (_sion_fileptr *) malloc(sizeof(_sion_fileptr));
  if (sion_fileptr == NULL) {
    _lsion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"cannot allocate _sion_fileptr structure of size %lu (_sion_fileptr), aborting ...\n", 
		     (unsigned long) sizeof(_sion_fileptr));
    return(NULL);
  }
  sion_fileptr->fileptr        = NULL;
  sion_fileptr->second_fileptr = NULL;
  sion_fileptr->fd             = -1;
  sion_fileptr->flags          = 0;

  return (sion_fileptr);
}

#define STR_PRT(X) case X: return # X
char* _lsion_fileptrflags_to_str (unsigned int flag) {
  switch (flag) {
    STR_PRT(SION_FILE_FLAG_ANSI);
    STR_PRT(SION_FILE_FLAG_SCNDANSI);
    STR_PRT(SION_FILE_FLAG_POSIX);
    STR_PRT(SION_FILE_FLAG_CREATE);
    STR_PRT(SION_FILE_FLAG_WRITE);
    STR_PRT(SION_FILE_FLAG_READ);
  }	           
  return "";
}

char* _lsion_get_fileptr_desc(_sion_fileptr *sion_fileptr) {
  int flags;
  if(!sion_fileptr) return("<undefined>");
  flags = sion_fileptr->flags;

  if(flags & SION_FILE_FLAG_ANSI) {
    if(flags & SION_FILE_FLAG_WRITE) {
      if(flags & SION_FILE_FLAG_CREATE) {
	return("<ANSI,WRITE,CREATE>");
      } else {
	return("<ANSI,WRITE>");
      }
    } else {
	return("<ANSI,READ>");
    }
  } else {
    if (flags & SION_FILE_FLAG_POSIX) {
      if(flags & SION_FILE_FLAG_WRITE) {
	if(flags & SION_FILE_FLAG_CREATE) {
	  return("<POSIX,WRITE,CREATE>");
      } else {
	  return("<POSIX,WRITE>");
	}
      } else {
	  return("<POSIX,READ>");
      }
    }
  }
  return("<unknown>");
  
}
