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

#if defined(_BGL)
#include <rts.h>
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#endif

#include <sys/time.h>

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

#include <unistd.h>

#if defined(_SION_BGP)
#include <stdio_ext.h>
#endif

#include "sion.h"
#include "sion_fd.h"
#include "printts.h"

/* INTERNAL */
/*!\brief Calculate the start pointers
 *
 * @param  ntasks               number of processes
 * @param *chunksizes           chunksizes of of all tasks
 * @param  fsblksize            blocksize of filesystem
 * @param *startpointers        array of the starting pointers
 * @param *globalskip           array of pointers to the mem to skip
 *
 * @retval 1 if ok
 */
int _sion_calculate_startpointers(int ntasks, sion_int64 *chunksizes, sion_int32 fsblksize, sion_int64 *startpointers, sion_int64 *globalskip)
{

  int       rc = 1;
  int       i, firstsize;
  sion_int64 lsize;

  DPRINTFP((2, "_sion_calculate_startpointers", -1, "enter ntasks=%d fsblksize=%d chunksizes[0]=%lld\n", ntasks, fsblksize, chunksizes[0]));

  /* calculate size of first block for meta-information */
  firstsize = strlen(SION_ID) + 5 * sizeof(sion_int32)          // length of SION_ID + endianness+fsblksize+ntasks+nfiles+filenumber 
    + SION_FILENAME_LENGTH                                      // prefix
    + ntasks * sizeof(sion_int64) + ntasks * sizeof(sion_int64) // globalranks + chunksizes
    + sizeof(sion_int32) + 3 * sizeof(sion_int64);              // maxblocks + start_of_varheader + 2 x 64bit-flags

  DPRINTFP((2, "_sion_calculate_startpointers", -1, "firstsize=%d\n", firstsize));

  startpointers[0] = (firstsize % fsblksize == 0) ? firstsize : ((firstsize / fsblksize) + 1) * fsblksize;

  i = 0;
  DPRINTFP((32, "_sion_calculate_startpointers", -1, "  startpointers[%2d]=%10lld (%10.4fMB) chunksizes[%2d]=%8lld\n",
            i, startpointers[i], startpointers[i] / 1024.0 / 1024.0, i, chunksizes[i]));
  *globalskip = 0;
  for (i = 1; i < ntasks; i++) {
    lsize = (chunksizes[i - 1] % fsblksize == 0) ? chunksizes[i - 1] : ((chunksizes[i - 1] / fsblksize) + 1) * fsblksize;
    *globalskip += lsize;
    startpointers[i] = startpointers[i - 1] + lsize;
    DPRINTFP((32, "_sion_calculate_startpointers", -1, "  startpointers[%2d]=%10lld (%10.4fMB) chunksizes[%2d]=%8lld\n",
              i, startpointers[i], startpointers[i] / 1024.0 / 1024.0, i, chunksizes[i]));
  }
  lsize = (chunksizes[ntasks - 1] % fsblksize == 0) ? chunksizes[ntasks - 1] : ((chunksizes[ntasks - 1] / fsblksize) + 1) * fsblksize;
  *globalskip += lsize;
  DPRINTFP((2, "_sion_calculate_startpointers", -1, "leave globalskip is %lld\n", *globalskip));
  return (rc);
}

/*!\brief Create and open a new file for writing
 *
 * @param  *fname               filename to use
 *
 * @return fileptr              file handle
 */
FILE     *_sion_create_and_open_file_for_write(char *fname)
{
  FILE     *fileptr;
#if defined(_SION_LINUX)
  fileptr = fopen(fname, "w");
#elif defined(_SION_AIX)
  fileptr = fopen64(fname, "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");

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

/*!\brief Open an existing file for writing
 *
 * @param  *fname               filename to use
 *
 * @return fileptr              file handle
 */
FILE     *_sion_open_existing_file_for_write(char *fname)
{
  FILE     *fileptr;
#if defined(_SION_LINUX)
  fileptr = fopen(fname, "w");
#elif defined(_SION_AIX)
  fileptr = fopen64(fname, "w");
#elif defined(_SION_BGL)
  {
    int       fd_oflag = 0;
    int       fd;

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

    fileptr = fdopen(fd, "w");

    /* fileptr=fopen64(fname,"w");  */
  }
#elif defined(_SION_BGP)
  {
    int       fd_oflag = 0;
    int       fd;

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

    fileptr = fdopen(fd, "w");

    /* fileptr=fopen64(fname,"w");  */
  }
#elif defined(_XT)
  fileptr = fopen(fname, "w");
#endif
  return (fileptr);
}

/*!\brief Open an existing file for reading
 *
 * @param  *fname               filename to use
 *
 * @return fileptr              file handle
 */
FILE     *_sion_open_file_for_read(char *fname)
{
  FILE     *fileptr;
#if defined(_SION_LINUX)
  fileptr = fopen(fname, "r");
#elif defined(_SION_AIX)
  fileptr = fopen64(fname, "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");

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

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

#if defined(_SION_LINUX)
  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_XT)
  if (stat(fname, &sbuf) == 0)  file_exists=1;
#endif
  return (file_exists);
}

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

#if defined(_SION_LINUX)
  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_XT)
  if (fstat(fd, &sbuf) == 0)  opt_size=(long) sbuf.st_blksize;
#endif
  return (opt_size);
}

/*!\brief Write the SION Meta Block 1
 *
 * @param  *fileptr             file handle
 * @param  fsblksize            blocksize of filesystem
 * @param  ntasks               number of tasks that write to the file
 * @param  *globalranks         array of global ranks for all tasks
 * @param  *chunksizes          array of the chunksizes of all tasks
 * @param  nfiles               number of files in the set (or 1)
 * @param  filenumber           number of current file in the set (or 1)
 * @param  *prefix              prefix used in case of a file set
 *
 * @retval 1 if OK
 */
int _sion_write_header(FILE *fileptr,
                       sion_int32 fsblksize,
                       int ntasks,
                       sion_int64 *globalranks,
                       sion_int64 *chunksizes, 
		       int nfiles, 
		       int filenumber, 
		       sion_int64 flag1, 
		       sion_int64 flag2, 
		       char *prefix, int endianness)
{
  int       rc = 1;
  size_t    nwrite;
  char     *lprefix;

  char        *sionstr = SION_ID;
  sion_int32   lfsblksize = fsblksize;
  sion_int32   lntasks = ntasks;
  sion_uint32  endianness_writeval;
  sion_int32   sion_version, sion_version_patchlevel, sion_fileformat_version;


  DPRINTFP((2, "_sion_write_header", -1, "enter write\n"));

  nwrite = fwrite(sionstr, 1, strlen(sionstr), fileptr);
  if (nwrite != strlen(sionstr)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(SIONID) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote sionstr nwrite=%lu\n", (unsigned long) nwrite));

  if (endianness)
    endianness_writeval = 0x01010101;
  else
    endianness_writeval = 0x00000000;

  nwrite = fwrite(&endianness_writeval, 1, sizeof(endianness_writeval), fileptr);
  if (nwrite != sizeof(endianness_writeval)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(endianness) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote endianness %ld nwrite=%lu\n", endianness_writeval, (unsigned long) nwrite));

  /* VERSION Information */
  sion_version = 1000 * SION_MAIN_VERSION + SION_SUB_VERSION;
  sion_version_patchlevel = SION_VERSION_PATCHLEVEL;
  sion_fileformat_version = SION_FILEFORMAT_VERSION;

  nwrite = fwrite(&sion_version, 1, sizeof(sion_version), fileptr);
  if (nwrite != sizeof(sion_version)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(sion_version) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote sion_version %ld nwrite=%lu\n", sion_version, (unsigned long) nwrite));

  nwrite = fwrite(&sion_version_patchlevel, 1, sizeof(sion_version_patchlevel), fileptr);
  if (nwrite != sizeof(sion_version_patchlevel)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(sion_version_patchlevel) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote sion_version_patchlevel %ld nwrite=%lu\n", sion_version_patchlevel, (unsigned long) nwrite));

  nwrite = fwrite(&sion_fileformat_version, 1, sizeof(sion_fileformat_version), fileptr);
  if (nwrite != sizeof(sion_fileformat_version)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(sion_fileformat_version) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote sion_fileformat_version %ld nwrite=%lu\n", sion_fileformat_version, (unsigned long) nwrite));

  nwrite = fwrite(&lfsblksize, 1, sizeof(lfsblksize), fileptr);
  if (nwrite != sizeof(lfsblksize)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(fsblksize) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote fsblksize %ld nwrite=%lu\n", lfsblksize, (unsigned long) nwrite));

  nwrite = fwrite(&lntasks, 1, sizeof(lntasks), fileptr);
  if (nwrite != sizeof(lntasks)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(ntasks) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote ntasks %ld nwrite=%lu\n", ntasks, (unsigned long) nwrite));

  nwrite = fwrite(&nfiles, 1, sizeof(nfiles), fileptr);
  if (nwrite != sizeof(nfiles)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(nfiles) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote nfiles %d nwrite=%lu\n", nfiles, (unsigned long) nwrite));

  nwrite = fwrite(&filenumber, 1, sizeof(filenumber), fileptr);
  if (nwrite != sizeof(filenumber)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(filenumber) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote filenumber %d nwrite=%lu\n", filenumber, (unsigned long) nwrite));

  nwrite = fwrite(&flag1, 1, sizeof(flag1), fileptr);
  if (nwrite != sizeof(flag1)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(flag1) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote flag1 %d nwrite=%lu\n", flag1, (unsigned long) nwrite));

  nwrite = fwrite(&flag2, 1, sizeof(flag2), fileptr);
  if (nwrite != sizeof(flag2)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(flag2) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote flag2 %d nwrite=%lu\n", flag2, (unsigned long) nwrite));

  lprefix = calloc(SION_FILENAME_LENGTH,1);
  if (lprefix == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot allocate temporary memory of size %lu (lprefix), aborting ...\n", (unsigned long) SION_FILENAME_LENGTH));
  }
  strncpy(lprefix,prefix,SION_FILENAME_LENGTH);
  nwrite = fwrite(lprefix, 1, SION_FILENAME_LENGTH, fileptr);
  if (nwrite != SION_FILENAME_LENGTH) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(lprefix) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  free(lprefix); lprefix=NULL;
  DPRINTFP((32, "_sion_write_header", -1, " wrote prefix     =%s\n", prefix));

  nwrite = fwrite(globalranks, sizeof(sion_int64), ntasks, fileptr);
  if (nwrite != ntasks) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(globalranks) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote globalranks nwrite=%lu\n", (unsigned long) nwrite));

  nwrite = fwrite(chunksizes, sizeof(sion_int64), ntasks, fileptr);
  if (nwrite != ntasks) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot write header(chunksizes) to file, aborting ... (%lu)\n", (unsigned long) nwrite));
  }
  DPRINTFP((32, "_sion_write_header", -1, " wrote chunksizes nwrite=%lu\n", (unsigned long) nwrite));

  _sion_flush_file_fp(fileptr);
  DPRINTFP((2, "_sion_write_header", -1, "leave write\n"));
  return (rc);
}

/*!\brief Read part of the SION Meta Block 1
 *
 * @param  *fileptr             file handle
 * @param  *endianness          endianness used
 * @param  *fsblksize           blocksize of filesystem
 * @param  *ntasks              number of tasks that wrote to the file
 * @param  *nfiles              number of files in the set (or 1)
 * @param  *filenumber          number of current file in the set (or 1)
 * @param  *prefix              prefix used in case of a file set
 *
 * @retval 1 if OK
 */
int _sion_read_header_fixed_part(FILE *fileptr,
                                 int *endianness,
                                 int *swapbytes,
                                 sion_int32 *fsblksize,
                                 int *ntasks,
                                 int *nfiles,
                                 int *filenumber,
                                 sion_int64 *flag1,
                                 sion_int64 *flag2,
                                 char *prefix, 
				 sion_int32 *sion_version, 
				 sion_int32 *sion_version_patchlevel, 
				 sion_int32 *sion_fileformat_version)
{
  size_t    nread;
  char     *sionstr, *lprefix;
  sion_uint32 lendianness;
  sion_int32 lfsblksize;
  sion_int32 lntasks, lnfiles, lfilenumber;
  sion_int32 Rsion_version, Rsion_version_patchlevel, Rsion_fileformat_version;
  sion_int64 lflag1, lflag2;

  DPRINTFP((2, "_sion_read_header_fixed_part", -1, "enter read fixed_part\n"));

  sionstr = (char *) malloc(strlen(SION_ID) * sizeof(char));
  nread = fread(sionstr, 1, strlen(SION_ID), fileptr);
  if (nread != strlen(SION_ID)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(SION_ID) from file, aborting ... (%lu!=%lu)\n",
            (unsigned long) nread, (unsigned long) strlen(SION_ID)));
  }
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " sionstr  =>%c%c%c%c<\n", sionstr[0], sionstr[1], sionstr[2], sionstr[3]));
  /* Check if this is a sion file */
  if (strncmp(sionstr, SION_ID, strlen(SION_ID))) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: not a sion file(ID: %c%c%c%c)\n", sionstr[0], sionstr[1], sionstr[2], sionstr[3]));
  }
  free(sionstr);

  nread = fread(&lendianness, 1, sizeof(lendianness), fileptr);
  if (nread != sizeof(lendianness)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_write_header: cannot read header(endianness) from file, aborting ... (%lu!=%lu)\n",(unsigned long) nread, (unsigned long) sizeof(lendianness)));
  }
  if (lendianness > 0)
    *endianness = 1;
  else
    *endianness = 0;
  *swapbytes = (*endianness != sion_get_endianness());
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " endianness =%d swapbytes=%d\n", *endianness, *swapbytes));


  /* VERSION Information */
  nread = fread(&Rsion_version, 1, sizeof(Rsion_version), fileptr);
  if (nread != sizeof(Rsion_version)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(sion_version) from file, aborting ... (%lu!=%lu)\n", (unsigned long) nread, (unsigned long) sizeof(Rsion_version)));
  }
  sion_swap(&Rsion_version, &Rsion_version, sizeof(Rsion_version), 1, *swapbytes);
  *sion_version = Rsion_version;
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " sion_version=%d\n", *sion_version));

  nread = fread(&Rsion_version_patchlevel, 1, sizeof(Rsion_version_patchlevel), fileptr);
  if (nread != sizeof(Rsion_version_patchlevel)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(sion_version_patchlevel) from file, aborting ... (%lu!=%lu)\n",
            (unsigned long) nread, (unsigned long) sizeof(Rsion_version_patchlevel)));
  }
  sion_swap(&Rsion_version_patchlevel, &Rsion_version_patchlevel, sizeof(Rsion_version_patchlevel), 1, *swapbytes);
  *sion_version_patchlevel = Rsion_version_patchlevel;
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " sion_version_patchlevel=%d\n", *sion_version_patchlevel));

  nread = fread(&Rsion_fileformat_version, 1, sizeof(Rsion_fileformat_version), fileptr);
  if (nread != sizeof(Rsion_fileformat_version)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(sion_fileformat_version) from file, aborting ... (%lu!=%lu)\n",
            (unsigned long) nread, (unsigned long) sizeof(Rsion_fileformat_version)));
  }
  sion_swap(&Rsion_fileformat_version, &Rsion_fileformat_version, sizeof(Rsion_fileformat_version), 1, *swapbytes);
  *sion_fileformat_version = Rsion_fileformat_version;
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " sion_fileformat_version=%d\n", *sion_fileformat_version));

  if (Rsion_fileformat_version != SION_FILEFORMAT_VERSION) {
    if(Rsion_fileformat_version<2) {
      return(_sion_errorprint(0,_SION_ERROR_RETURN,"sionlib: FATAL ERROR: file format version of file differs, aborting ... (%lu!=%lu)\n",
	      (unsigned long) Rsion_fileformat_version, (unsigned long) SION_FILEFORMAT_VERSION));
    } else {
      _sion_errorprint(0,_SION_ERROR_WARN,"sionlib: FATAL WARNING: old file format version of file differs, trying to read ... (%lu!=%lu)\n",
	      (unsigned long) Rsion_fileformat_version, (unsigned long) SION_FILEFORMAT_VERSION);
    }
  }

  /* file block size */
  nread = fread(&lfsblksize, 1, sizeof(lfsblksize), fileptr);

  if (nread != sizeof(lfsblksize)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(fsblksize) from file, aborting ... (%lu!=%lu)\n",
            (unsigned long) nread, (unsigned long) sizeof(lfsblksize)));
  }
  sion_swap(&lfsblksize, &lfsblksize, sizeof(lfsblksize), 1, *swapbytes);
  *fsblksize = lfsblksize;
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " fsblksize=%d\n", *fsblksize));

  /* number of tasks */
  nread = fread(&lntasks, 1, sizeof(lntasks), fileptr);
  if (nread != sizeof(lntasks)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(ntasks) from file, aborting ... (%lu!=%lu)\n",
            (unsigned long) nread, (unsigned long) sizeof(lntasks)));
  }
  sion_swap(&lntasks, &lntasks, sizeof(lntasks), 1, *swapbytes);
  *ntasks = lntasks;
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " ntasks     =%d\n", *ntasks));

  /* number of files */
  nread = fread(&lnfiles, 1, sizeof(lnfiles), fileptr);
  if (nread != sizeof(lnfiles)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(nfiles) from file, aborting ... (%lu!=%lu)\n",
			    (unsigned long) nread, (unsigned long) sizeof(lnfiles)));
  }
  sion_swap(&lnfiles, &lnfiles, sizeof(lnfiles), 1, *swapbytes);
  *nfiles = lnfiles;
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " nfiles     =%d\n", *nfiles));

  /* current file number */
  if(Rsion_fileformat_version>=3) {
    nread = fread(&lfilenumber, 1, sizeof(lfilenumber), fileptr);
    if (nread != sizeof(lfilenumber)) {
      return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(filenumber) from file, aborting ... (%lu!=%lu)\n",
			      (unsigned long) nread, (unsigned long) sizeof(lfilenumber)));
    }
    sion_swap(&lfilenumber, &lfilenumber, sizeof(lfilenumber), 1, *swapbytes);
    *filenumber = lfilenumber;
  } else {
    *filenumber = lfilenumber = 1;
  }
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " filenumber =%d\n", *filenumber));


  /* flag1 */
  if(Rsion_fileformat_version>=3) {
    nread = fread(&lflag1, 1, sizeof(lflag1), fileptr);
    if (nread != sizeof(lflag1)) {
      return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(flag1) from file, aborting ... (%lu!=%lu)\n",
			      (unsigned long) nread, (unsigned long) sizeof(lflag1)));
    }
    sion_swap(&lflag1, &lflag1, sizeof(lflag1), 1, *swapbytes);
    *flag1 = lflag1;
  } else {
    *flag1 = lflag1 = _SION_FLAG1_NONE;
  }
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " flag1 =%d\n", *flag1));
    
  /* flag2 */
  if(Rsion_fileformat_version>=3) {
    nread = fread(&lflag2, 1, sizeof(lflag2), fileptr);
    if (nread != sizeof(lflag2)) {
      return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(flag2) from file, aborting ... (%lu!=%lu)\n",
			      (unsigned long) nread, (unsigned long) sizeof(lflag2)));
    }
    sion_swap(&lflag2, &lflag2, sizeof(lflag2), 1, *swapbytes);
    *flag2 = lflag2;
  } else {
    *flag2 = lflag2 = _SION_FLAG2_NONE;
  }
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " flag2 =%d\n", *flag2));

  /* file name prefix */
  lprefix = malloc(SION_FILENAME_LENGTH);
  nread = fread(lprefix, 1, SION_FILENAME_LENGTH, fileptr);
  if (nread != SION_FILENAME_LENGTH) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_fixed_part: cannot read header(lprefix) from file, aborting ... (%lu!=%d)\n", (unsigned long) nread, SION_FILENAME_LENGTH));
  }
  strcpy(prefix, lprefix);
  free(lprefix);
  DPRINTFP((32, "_sion_read_header_fixed_part", -1, " prefix     =%s\n", prefix));

  _sion_flush_file_fp(fileptr);

  DPRINTFP((2, "_sion_read_header_fixed_part", -1, "leave read fixed_part\n"));

  return (1);
}

/*!\brief Read the second part of SION Meta Block 1
 *
 * @param[in]   *fileptr                file handle
 * @param[in]    ntasks                 number of processes
 * @param[out]  *globalranks            array of global ranks for all tasks that wrote to the file
 * @param[out]  *chunksizes             array of the chunksizes of all tasks
 * @param[out]  *maxblocks              maximum number of chunks written by all tasks
 * @param[out]  *start_of_varheader     the beginning of the block 2
 *
 * @retval       1 if OK
 */
int _sion_read_header_var_part(FILE *fileptr,
                               int ntasks,
                               sion_int64 *globalranks,
                               sion_int64 *chunksizes, 
			       sion_int32 *maxblocks, 
			       sion_int64 *start_of_varheader, 
			       int swapbytes)
{
  size_t    nread;

  DPRINTFP((32, "_sion_read_header_var_part", -1, "enter read var_part\n"));

  nread = fread(globalranks, sizeof(sion_int64), ntasks, fileptr);
  if (nread != ntasks) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part: cannot read header(globalranks) from file, aborting ... (%d)\n", ntasks));
  }
  sion_swap(globalranks, globalranks, sizeof(sion_int64), ntasks, swapbytes);

  nread = fread(chunksizes, sizeof(sion_int64), ntasks, fileptr);
  if (nread != ntasks) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part: cannot read header(chunksizes) from file, aborting ... (%d!=%lu)\n", ntasks, (unsigned long) nread));
  }
  sion_swap(chunksizes, chunksizes, sizeof(sion_int64), ntasks, swapbytes);

  nread = fread(maxblocks, 1, sizeof(sion_int32), fileptr);
  if (nread != sizeof(sion_int32)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part: cannot read header(maxblocks) from file, aborting ... (%lu!=%lu)\n",
			    (unsigned long) nread, (unsigned long) sizeof(sion_int32)));
  }
  sion_swap(maxblocks, maxblocks, sizeof(sion_int32), 1, swapbytes);
  DPRINTFP((32, "_sion_read_header_var_part", -1, " maxblocks=%d\n", *maxblocks));

  nread = fread(start_of_varheader, 1, sizeof(sion_int64), fileptr);
  if (nread != sizeof(sion_int64)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part: cannot read header(start_of_varheader) from file, aborting ... (%lu!=%lu)\n",
			    (unsigned long) nread, (unsigned long) sizeof(sion_int64)));
  }
  sion_swap(start_of_varheader, start_of_varheader, sizeof(sion_int64), 1, swapbytes);

  DPRINTFP((32, "_sion_read_header_var_part", -1, "leave read var_part start_of_varheader=%lld\n", *start_of_varheader));

  return (1);

}

/*!\brief Read the second part of SION Meta Block 1 only for one rank
 *
 * @param[in]   *fileptr                file handle
 * @param[in]    ntasks                 number of processes
 * @param[out]  *globalranks            array of global ranks for all tasks that wrote to the file
 * @param[out]  *chunksizes             array of the chunksizes of all tasks
 * @param[out]  *maxblocks              maximum number of chunks written by all tasks
 * @param[out]  *start_of_varheader     the beginning of the block 2
 *
 * @retval       1 if OK
 */
int _sion_read_header_var_part_rank(FILE *fileptr,
				    int rank,
				    int ntasks,
				    sion_int64 *globalrank,
				    sion_int64 *chunksize, 
				    sion_int32 *maxblocks, 
				    sion_int64 *start_of_varheader, 
				    int swapbytes)
{
  size_t    nread;
  sion_int64 fileposition, pos;

  DPRINTFP((32, "_sion_read_header_var_part_rank", -1, "enter read\n"));

  fileposition = _sion_get_position(fileptr);

  pos = fileposition + rank * sizeof(sion_int64);
  _sion_purge_file_fp(fileptr);
  _sion_set_position(fileptr, pos);
  nread = fread(globalrank, sizeof(sion_int64), 1, fileptr);
  if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_rank: cannot read header(globalrank) from file, aborting ... (%d!=%lu)\n", 1, (unsigned long) nread));
  }
  sion_swap(globalrank, globalrank, sizeof(sion_int64), 1, swapbytes);

  pos = fileposition + ntasks * sizeof(sion_int64) + rank * sizeof(sion_int64);
  _sion_purge_file_fp(fileptr);
  _sion_set_position(fileptr, pos);
  nread = fread(chunksize, sizeof(sion_int64), 1, fileptr);
  if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_rank: cannot read header(chunksizes) from file, aborting ... (%d!=%lu)\n", 1, (unsigned long) nread));
  }
  sion_swap(chunksize, chunksize, sizeof(sion_int64), 1, swapbytes);

  pos = fileposition + ntasks * sizeof(sion_int64) + ntasks * sizeof(sion_int64);
  _sion_purge_file_fp(fileptr);
  _sion_set_position(fileptr, pos);
  nread = fread(maxblocks, 1, sizeof(sion_int32), fileptr);
  if (nread != sizeof(sion_int32)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_rank: cannot read header(maxblocks) from file, aborting ... (%lu!=%lu)\n",
			    (unsigned long) nread, (unsigned long) sizeof(sion_int32)));
  }
  sion_swap(maxblocks, maxblocks, sizeof(sion_int32), 1, swapbytes);
  DPRINTFP((32, "_sion_read_header_var_part", -1, " maxblocks=%d\n", *maxblocks));

  nread = fread(start_of_varheader, 1, sizeof(sion_int64), fileptr);
  if (nread != sizeof(sion_int64)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_rank: cannot read header(start_of_varheader) from file, aborting ... (%lu!=%lu)\n",
			    (unsigned long) nread, (unsigned long) sizeof(sion_int64)));
  }
  sion_swap(start_of_varheader, start_of_varheader, sizeof(sion_int64), 1, swapbytes);

  DPRINTFP((32, "_sion_read_header_var_part", -1, "leave read var_part start_of_varheader=%lld\n", *start_of_varheader));

  return (1);

}

/*!\brief Read the SION Meta Block 2
 *
 * @param[in]   *fileptr                        file handle
 * @param[in]    ntasks                 number of processes that wrote the file
 * @param[in]    maxblocks              maxblocks
 * @param[in]    start_of_varheader     the beginning of the block 2
 * @param[out]  *sion_blockcount        array of the number of chunk written by each task (0..ntasks)
 * @param[out]  *sion_blocksizes        array of the chunksizes for all processes ((0..ntasks*maxblocks)
 *
 * @retval      1 if OK
 */
int _sion_read_header_var_part_locations(FILE *fileptr,
                                         int ntasks,
                                         sion_int32 maxblocks,
                                         sion_int64 start_of_varheader, sion_int64 *sion_blockcount, sion_int64 *sion_blocksizes, int swapbytes)
{
  size_t    nread;
  int       i;

  DPRINTFP((32, "_sion_read_header_var_part_locations", -1, "enter read\n"));

  _sion_purge_file_fp(fileptr);
  _sion_set_position(fileptr, start_of_varheader);

  nread = fread(sion_blockcount, sizeof(sion_int64), ntasks, fileptr);
  if (nread != ntasks) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_locations: cannot read header from file(sion_blockcount), aborting ... (%d)\n", ntasks));
  }
  sion_swap(sion_blockcount, sion_blockcount, sizeof(sion_int64), ntasks, swapbytes);
  for (i = 0; i < ntasks; i++)
    DPRINTFP((32, "_sion_read_header_var_part_locations", -1, " read, numblocks on task %02d is %10lld\n", i, sion_blockcount[i]));

  nread = fread(sion_blocksizes, sizeof(sion_int64), ntasks * maxblocks, fileptr);
  if (nread != ntasks * maxblocks) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_locations: cannot read header(sion_blocksizes) from file, aborting ... (%lu!=%lu)\n",
			    (unsigned long) ntasks * maxblocks, (unsigned long) nread));
  }
  sion_swap(sion_blocksizes, sion_blocksizes, sizeof(sion_int64), ntasks * maxblocks, swapbytes);

  //for(i=0;i<ntasks;i++)  DPRINTFP(( 32,"_sion_read_header_var_part_locations",-1," read, chunksize on task %02d is %10lld\n",i,sion_blockcount[i]));

  DPRINTFP((32, "_sion_read_header_var_part_locations", -1, "leave read\n"));
  return (1);

}

/*!\brief Read the SION Meta Block 2
 *
 * @param  *fileptr                             file handle
 * @param  rank                                 rank of the current process
 * @param  ntasks                                       number of processes
 * @param  start_of_varheader   the beginning of the block 2
 * @param  *numblocks                   number of chunks written by task with rank
 * @param  *blocksizes                  array of the chunksizes for all processes
 * @param  *sion_filedesc               sion file handle
 *
 * @retval 1 if OK
 */
/* TODO: _sion_filedesc *sion_filedesc -> fileptr */
int _sion_read_header_var_part_locations_rank(FILE *fileptr,
                                              int rank,
                                              int ntasks,
                                              sion_int64 start_of_varheader,
                                              sion_int64 *numblocks, 
					      sion_int64 *blocksizes, 
					      _sion_filedesc *sion_filedesc, 
					      int swapbytes)
{
  int       i, rc = 1;
  size_t    nread;
  sion_int64 pos;
  sion_int64 helpint64;

  DPRINTFP((32, "_sion_read_header_var_part_locations_rank", -1, "enter read rank=%d ntasks=%d\n",rank,ntasks));

  pos = start_of_varheader + rank * sizeof(sion_int64);
  _sion_purge_file_fp(SIONFP);
  _sion_set_position(SIONFP, start_of_varheader);
  nread = fread(&helpint64, sizeof(sion_int64), 1, fileptr);
  sion_swap(&helpint64,&helpint64, sizeof(sion_int64), 1, swapbytes);
  *numblocks = helpint64;
  if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_locations_rank: cannot read header(numblocks) from file, aborting ... (%d)\n", ntasks));
  }

  for (i = 0; i < *numblocks; i++) {
    pos = start_of_varheader + (i + 1) * ntasks * sizeof(sion_int64) + rank * sizeof(sion_int64);
    _sion_purge_file_fp(SIONFP);
    _sion_set_position(SIONFP, pos);
    nread = fread(&helpint64, sizeof(sion_int64), 1, fileptr);
    sion_swap(&helpint64,&helpint64, sizeof(sion_int64), 1, swapbytes);
    blocksizes[i] = helpint64;
    DPRINTFP((32, "_sion_read_header_var_part_locations_rank", -1, "read blocksizes[%i], %lld start_of_varheader=%lld\n", i, helpint64,
              start_of_varheader));

    if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_locations_rank: cannot read header(blocksizes) from file, aborting ... (%d!=%lu)\n", 1, (unsigned long) nread));
    }
  }
  DPRINTFP((32, "_sion_read_header_var_part_locations_rank", -1, "leave read\n"));
  return (rc);

}


/*!\brief Read the mapping data at end of SION Meta Block 2
 *
 * @param  *fileptr                             file handle
 * @param  *mapping_size                        size of table
 * @param  **mapping                            pointer to table
 *
 *  file pointer will be set to the correct position
 *
 * @retval 1 if OK
 */
int _sion_read_header_var_part_mapping(FILE        *fileptr,
				       int          ntasks,
				       sion_int32   maxblocks,
				       sion_int64   start_of_varheader,
				       int         *mapping_size,
				       sion_int32 **mapping,
				       int          swapbytes)
  {
  int       rc = 1;
  int msize;
  size_t    nread;
  sion_int64 pos;
  sion_int32 helpint32;

  DPRINTFP((32, "_sion_read_header_var_part_mapping", -1, "enter read\n"));

  pos = start_of_varheader + ntasks * (maxblocks+1) * sizeof(sion_int64);
  _sion_purge_file_fp(fileptr);
  _sion_set_position(fileptr, pos);
  DPRINTFP((32, "_sion_read_header_var_part_mapping", -1, "calculate pos %lld + %d * %d = %lld\n",start_of_varheader,ntasks,maxblocks+1,pos ));

  /* read mapping_size */
  nread = fread(&helpint32, sizeof(sion_int32), 1, fileptr);
  if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_mapping: cannot read header(mapping_size) from file, aborting ... (%d)\n", ntasks));
  }
  DPRINTFP((32, "_sion_read_header_var_part_mapping", -1, "helpint32=%ld\n", (unsigned long) helpint32));
  sion_swap(&helpint32,&helpint32, sizeof(sion_int32), 1, swapbytes);
  msize = *mapping_size = helpint32;
  DPRINTFP((32, "_sion_read_header_var_part_mapping", -1, "mapping_size=%ld\n", (unsigned long) msize));
  
  /* allocate mapping vector */
  *mapping = (sion_int32 *) malloc(msize * 2 * sizeof(sion_int32));
  if (*mapping == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_mapping: cannot allocate temporary memory of size %lu (sion_chunksizes), aborting ...\n", (unsigned long) 2 * msize * sizeof(sion_int64)));
  }
  DPRINTFP((32, "_sion_read_header_var_part_mapping", -1, "alloc mapping vector size=%d (%lu bytes)\n", msize, (unsigned long) msize * 2 * sizeof(sion_int32)));

  /* read mapping */
  nread = fread(*mapping, sizeof(sion_int32), msize * 2, fileptr);
  DPRINTFP((32, "_sion_read_header_var_part_mapping", -1, "read mapping, %d \n", nread));
  if (nread != (msize * 2)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_mapping: cannot read header(mapping) from file, aborting ... (%d!=%lu)\n", msize*2, (unsigned long) nread));
  }

  DPRINTFP((32, "_sion_read_header_var_part_mapping", -1, "leave read\n"));
  return (rc);

}

/*!\brief Read the mapping data at end of SION Meta Block 2
 *
 * @param  *fileptr                             file handle
 * @param  *mapping_size                        size of table
 * @param  **mapping                            pointer to table
 *
 *  file pointer will be set to the correct position
 *
 * @retval 1 if OK
 */
int _sion_read_header_var_part_mapping_rank(FILE        *fileptr,
					    int          rank,
					    int          ntasks,
					    sion_int32   maxblocks,
					    sion_int64   start_of_varheader,
					    int         *mapping_filenr,
					    int         *mapping_lrank,
					    int          swapbytes)
{
  int       rc = 1;
  int       msize;
  size_t    nread;
  sion_int64 pos;
  sion_int32 helpint32;

  DPRINTFP((32, "_sion_read_header_var_part_mapping_rank", -1, "enter read for rank %d of %d\n",rank,ntasks));

  pos = start_of_varheader + ntasks * (maxblocks+1) * sizeof(sion_int64);
  _sion_purge_file_fp(fileptr);
  _sion_set_position(fileptr, pos);

  /* read mapping_size */
  nread = fread(&helpint32, sizeof(sion_int32), 1, fileptr);
  if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_mapping_rank: cannot read header(mapping_size) from file, aborting ... (%d)\n", ntasks));
  }
  sion_swap(&helpint32,&helpint32, sizeof(sion_int32), 1, swapbytes);
  msize = helpint32;
  DPRINTFP((32, "_sion_read_header_var_part_mapping_rank", -1, "read mapping_size %d \n", msize));
  
  if((rank<0) || (rank>=msize)) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_mapping_rank: wrong rank %d not between 0 .. %d aborting ...\n", rank,msize));
  }

  /* move to position in mapping table for rank */
  pos = start_of_varheader + ntasks * (maxblocks+1) * sizeof(sion_int64) + sizeof(sion_int32) + 2*rank*sizeof(sion_int32);
  _sion_purge_file_fp(fileptr);
  _sion_set_position(fileptr, pos);
 
  /* read mapping for rank */
  nread = fread(&helpint32, sizeof(sion_int32), 1, fileptr);
  DPRINTFP((32, "_sion_read_header_var_part_mapping_rank", -1, "read mapping_filenr nread=%d \n", nread));
  if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_mapping_rank: cannot read header(mapping_filenr) from file, aborting ... (%d!=%lu)\n", 1, (unsigned long) nread));
  }
  sion_swap(&helpint32,&helpint32, sizeof(sion_int32), 1, swapbytes);
  *mapping_filenr=helpint32;

  nread = fread(&helpint32, sizeof(sion_int32), 1, fileptr);
  DPRINTFP((32, "_sion_read_header_var_part_mapping_rank", -1, "read mapping_lrank, nread=%d \n", nread));
  if (nread != 1) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_read_header_var_part_mapping_rank: cannot read header(mapping_lrank) from file, aborting ... (%d!=%lu)\n", 1, (unsigned long) nread));
  }
  sion_swap(&helpint32,&helpint32, sizeof(sion_int32), 1, swapbytes);
  *mapping_lrank=helpint32;
   
  DPRINTFP((32, "_sion_read_header_var_part_mapping_rank", -1, "leave read filenumber=%d lrank=%d\n",*mapping_filenr,*mapping_lrank));
  return (rc);

}


/*!\brief Set the start position for the current task
 *
 * @param  fname                file name
 * @param  filenumber           file number
 *
 * @retval pointer to new filename
 */
char * _sion_get_multi_filename(char *fname, int filenumber)
{
  char *newfname;

  newfname = malloc(SION_FILENAME_LENGTH);
  if (newfname == NULL) {
    _sion_errorprint(0,_SION_ERROR_RETURN,"_sion_get_multi_filename: Cannot allocate string newfname\n");
    return(NULL);
  }
  if(filenumber>0) {
    if(strlen(fname)<SION_FILENAME_LENGTH-7) {
      sprintf(newfname, "%s.%06d", fname, filenumber);
    } else {
      _sion_errorprint(0,_SION_ERROR_RETURN,"_sion_get_multi_filename: filename too long\n");
      return(NULL);
    }
  } else {
    strcpy(newfname, fname);
  }

  return(newfname);
}

/*!\brief Set the start position for the current task
 *
 * @param  *fileptr                     file handle
 * @param  startpointer         the position for the current task
 *
 * @retval 1 if OK
 */
int _sion_set_position(FILE *fileptr, sion_int64 startpointer)
{
  int       rc = 1;
  int       fd;

  fd = fileno(fileptr);

  DPRINTFP((32, "_sion_set_position", -1, "enter\n"));

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

#if defined(_SION_LINUX)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    if (offset != startpointer) {
      return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_set_position: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			      offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    result = lseek(fd, offset, SEEK_SET);
/*        fprintf(stderr, "[SION]                lseek return new position %lld\n",result);  */
  }
#elif defined(_SION_AIX)
  off64_t   offset = (off_t) startpointer;
  off64_t   result;
  if (offset != startpointer) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_set_position: 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);
  result = ftello64(fileptr);
  /*    fprintf(stderr, "[SION]               fseeko64/ftello64 return new position %lld\n",result); */
#elif defined(_SION_BGL)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  result = lseek(fd, offset, SEEK_SET);
  /*    fprintf(stderr, "[SION][%d]               lseek[BGL] return new position %lld\n",rank,result); */
#elif defined(_SION_BGP)
  off_t     offset = (off_t) startpointer;
  off_t     result;
  result = lseek(fd, offset, SEEK_SET);
#elif defined(_SION_XT)
  {
    off_t     offset = (off_t) startpointer;
    off_t     result;
    if (offset != startpointer) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_set_position: cannot set position to %ld (%lu),%lld (%lu)  offset conversion error\n",
			    offset, (unsigned long) sizeof(offset), startpointer, (unsigned long) sizeof(startpointer)));
    }
    result = lseek(fd, offset, SEEK_SET);
    /*    fprintf(stderr, "[SION]                lseek return new position %lld\n",result); */
  }
#endif
  DPRINTFP((32, "_sion_set_position", -1, "leave\n"));

  return (rc);
}

/*!\brief Get the current position for the current task
 *
 * @param  *fileptr                     file handle
 *
 * @retval 1 if OK
 */
sion_int64 _sion_get_position(FILE *fileptr)
{
  sion_int64 result;
#if defined(_SION_LINUX)
  {
    off_t     resulto;
    /*     int myerrno; */
    int       fd = fileno(fileptr);
    /*     fsync(fd); */
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    /*     result=ftell(fileptr); */
    /*     myerrno=errno; */
    /*    fprintf(stderr, "[SION]               ftell return new position %ld errno=%d\n",result,myerrno);   */
  }
#elif defined(_SION_AIX)
  {
    result = ftell(fileptr);
/*     DPRINTFP((1024, "_sion_get_position", -1, "got position=%lld  (BGP)\n", result)); */
  }
#elif defined(_SION_BGL)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    /*    fprintf(stderr, "[SION]               fseek return new position %lld o=%lld sizeof(%d ,%d)\n",result,resulto,sizeof(result),sizeof(resulto));  */
  }
#elif defined(_SION_BGP)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    /*     fsync(fd); */
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
    /*    fprintf(stderr, "[SION]               fseek return new position %lld o=%lld sizeof(%d ,%d)\n",result,resulto,sizeof(result),sizeof(resulto));   */
/*     DPRINTFP((1024, "_sion_get_position", -1, "got position=%lld  (BGP)\n", result)); */
  }
#elif defined(_SION_XT)
  {
    off_t     resulto;
    int       fd = fileno(fileptr);
    resulto = lseek(fd, 0, SEEK_CUR);
    result = (sion_int64) resulto;
  }
#endif

/*   DPRINTFP((2048, "_sion_get_position", -1, "got position=%ld\n", result)); */

  return (result);
}

/*!\brief Flush the data to the disk for the current task
 *
 * @param  sid          sion file handle
 *
 * @retval 1 if OK
 */
int _sion_flush_file(int sid)
{
  int       rc = 1;
  _sion_filedesc *sion_filedesc;

  if ((_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_flush_file: invalid sion_filedesc, aborting %d ...\n", sid));
  }
  DPRINTFP((32, "_sion_flush_file_fp", sion_filedesc->rank, "flush sid=%d\n", sid));

  _sion_flush_file_fp(SIONFP);
  return (rc);
}

/*!\brief Flush the data to the disk for the current task
 *
 * @param  *fileptr             file handle
 *
 * @retval 1 if OK
 */
int _sion_flush_file_fp(FILE *fileptr)
{
  int       rc = 1;
  DPRINTFP((32, "_sion_flush_file_fp", -1, "flush fileptr\n"));
#if defined(_SION_BGP)
  /*   int fd = fileno(fileptr); */
  /*   fsync(fd); */
  fflush(fileptr);
#else
  fflush(fileptr);
#endif
  return (rc);
}

/*!\brief purge buffer data 
 *
 * @param  *fileptr             file handle
 *
 * @retval 1 if OK
 */
int _sion_purge_file_fp(FILE *fileptr)
{
  int       rc = 1;
  DPRINTFP((32, "_sion_purge_file_fp", -1, "purge fileptr\n"));
#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 */
  fflush(fileptr);
#elif defined(_SION_AIX)
  fflush(fileptr);
#else
  fflush(fileptr);
#endif
  return (rc);
}


/*!\brief Update the internal data structure
 *
 * @param  sid          sion file handle
 *
 * @retval 1 if OK
 */
int _sion_flush_block(int sid)
{
  int       rc = 1;
  sion_int64 fileposition;
  sion_int64 byteswritten;
  _sion_filedesc *sion_filedesc;

  if ((_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_flush_block: invalid sion_filedesc, aborting %d ...\n", sid));
  }

  DPRINTFP((2, "_sion_flush_block", sion_filedesc->rank, "enter sid=%d\n", sid));

  _sion_flush_file_fp(SIONFP);

  fileposition = _sion_get_position(SIONFP);
  byteswritten = fileposition - sion_filedesc->startpos;

  if (byteswritten > 0) {
    sion_filedesc->chunksizes[sion_filedesc->numblocks] = byteswritten;
    /*     sion_filedesc->numblocks++; */
    DPRINTFP((2, "_sion_flush_block", sion_filedesc->rank,
              "flushed sid=%d numblocks->%d byteswritten=%lld fileposition=%lld startpos=%lld (%lld)\n", sid, sion_filedesc->numblocks,
              byteswritten, fileposition, sion_filedesc->startpos, sion_filedesc->chunksizes[0]));
  }
  else {
    rc = 0;
    DPRINTFP((2, "_sion_flush_block", sion_filedesc->rank, "not flushed sid=%d numblocks->%d byteswritten=%lld fileposition=%lld startpos=%lld\n",
              sid, sion_filedesc->numblocks, byteswritten, fileposition, sion_filedesc->startpos));
  }

  DPRINTFP((2, "_sion_flush_block", sion_filedesc->rank, "leave sid=%d\n", sid));
  return (rc);
}

/*!\brief Create a new block for the internal data structure
 *
 * @param  sid          sion file handle
 *
 * @retval      1 if OK
 */
int _sion_create_new_block(int sid)
{
  int       rc = 1;
  _sion_filedesc *sion_filedesc;

  if ((_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_create_new_block: invalid sion_filedesc, aborting %d ...\n", sid));
  }

  DPRINTFP((2, "_sion_create_new_block", -1, "enter alloc arrays sid=%d\n", sid));

  if ((sion_filedesc->numblocks + 1) >= sion_filedesc->maxblocks) {
    _sion_realloc_blocklist(sion_filedesc, sion_filedesc->maxblocks + MAXBLOCKS);
  }

  /* flush current block */
  _sion_flush_block(sid);

  /* advance fp to next block */
  sion_filedesc->startpos += sion_filedesc->globalskip;
  sion_filedesc->numblocks++;
  _sion_flush_file_fp(SIONFP);
  rc = _sion_set_position(SIONFP, sion_filedesc->startpos);

  DPRINTFP((2, "_sion_create_new_block", -1, "leave alloc arrays sid=%d numblocks->%d startpos=%lld\n", sid, sion_filedesc->numblocks,
            sion_filedesc->startpos));

  return (rc);
}

/*!\brief Allocate memory for the internal sion arrays
 *
 * @param  ntasks                                               number of processes
 * @param  **sion_chunksizes            array of the chunksizes of all tasks
 * @param  **sion_startpointers         array of the starting pointers
 * @param  **sion_globalranks           array of global ranks for all tasks
 *
 * @retval      1 if OK
 */
int _sion_allocate_sion_arrays(int ntasks, sion_int64 **sion_chunksizes, sion_int64 **sion_startpointers, sion_int64 **sion_globalranks)
{
  int       i;
  sion_int64 *p;

  DPRINTFP((2, "_sion_allocate_sion_arrays", -1, "enter alloc arrays size=%d (%lu bytes)\n", ntasks, (unsigned long) ntasks * sizeof(sion_int64)));
  *sion_chunksizes = p = (sion_int64 *) malloc(ntasks * sizeof(sion_int64));
  if (sion_chunksizes == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_allocate_sion_arrays: cannot allocate temporary memory of size %lu (sion_chunksizes), aborting ...\n", 
			    (unsigned long) ntasks * sizeof(sion_int64)));
  }
  for (i = 0; i < ntasks; i++)
    p[i] = -1;

  *sion_startpointers = p = (sion_int64 *) malloc(ntasks * sizeof(sion_int64));
  if (sion_startpointers == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_allocate_sion_arrays: cannot allocate temporary memory of size %lu (sion_startpointers), aborting ...\n",
			    (unsigned long) ntasks * sizeof(sion_int64)));
  }
  for (i = 0; i < ntasks; i++)
    p[i] = -1;

  *sion_globalranks = p = (sion_int64 *) malloc(ntasks * sizeof(sion_int64));
  if (sion_globalranks == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_allocate_sion_arrays: cannot allocate temporary memory of size %lu (sion_globalranks), aborting ...\n", 
			    (unsigned long) ntasks * sizeof(sion_int64)));
  }
  for (i = 0; i < ntasks; i++)
    p[i] = -1;

  DPRINTFP((2, "_sion_allocate_sion_arrays", -1, "leave alloc arrays size=%d\n", ntasks));
  return (1);
}

/*!\brief free memory for the internal sion arrays
 *
 * @param  **sion_chunksizes            array of the chunksizes of all tasks
 * @param  **sion_startpointers         array of the starting pointers
 * @param  **sion_globalranks           array of global ranks for all tasks
 *
 * @retval      1 if OK
 */
int _sion_free_sion_arrays(sion_int64 **sion_chunksizes, sion_int64 **sion_startpointers, sion_int64 **sion_globalranks)
{

  DPRINTFP((2, "_sion_free_sion_arrays", -1, "enter free arrays\n"));
  if (*sion_chunksizes != NULL) {
    free(*sion_chunksizes);
    *sion_chunksizes=NULL;
  }

  if (*sion_startpointers != NULL) {
    free(*sion_startpointers);
    *sion_startpointers=NULL;
  }

  if (*sion_globalranks != NULL) {
    free(*sion_globalranks);
    *sion_globalranks=NULL;
  }
  DPRINTFP((2, "_sion_free_sion_arrays", -1, "leave alloc arrays\n"));
  return (1);
}

/*!\brief Allocate memory for the internal sion structure
 *
 * @param  ntasks                       number of tasks
 * @param  maxblocks                    max number of blocks
 * @param  **sion_blockcount            array of blockcounts of all tasks
 * @param  **sion_currentpos            array of current position pointers
 * @param  **sion_currentblocknr        array of current block numbers for all tasks
 * @param  **sion_blocksizes            array of current block sizes for all tasks
 *
 * @retval      1 if OK
 */
int _sion_allocate_sion_arrays_locations(int ntasks,
                                         sion_int32 maxblocks,
                                         sion_int64 **sion_blockcount,
                                         sion_int64 **sion_currentpos, sion_int64 **sion_currentblocknr, sion_int64 **sion_blocksizes)
{
  int       i;
  sion_int64 *p;

  DPRINTFP((2, "_sion_allocate_sion_arrays_locations", -1, "enter alloc locations size=%d, maxblocks=%d\n", ntasks, maxblocks));
  *sion_blockcount = p = (sion_int64 *) malloc(ntasks * sizeof(sion_int64));
  if (sion_blockcount == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_allocate_sion_arrays_locations: cannot allocate temporary memory of size %lu (sion_blockcount), aborting ...\n", 
			    (unsigned long) ntasks * sizeof(sion_int64)));
  }
  for (i = 0; i < ntasks; i++)
    p[i] = -1;

  *sion_currentpos = p = (sion_int64 *) malloc(ntasks * sizeof(sion_int64));
  if (sion_currentpos == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_allocate_sion_arrays_locations: cannot allocate temporary memory of size %lu (sion_currentpos), aborting ...\n", 
			    (unsigned long) ntasks * sizeof(sion_int64)));
  }
  for (i = 0; i < ntasks; i++)
    p[i] = -1;

  *sion_currentblocknr = p = (sion_int64 *) malloc(ntasks * sizeof(sion_int64));
  if (sion_currentblocknr == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_allocate_sion_arrays_locations: cannot allocate temporary memory of size %lu (sion_currentblocknr), aborting ...\n",
			    (unsigned long) ntasks * sizeof(sion_int64)));
  }
  for (i = 0; i < ntasks; i++)
    p[i] = -1;

  *sion_blocksizes = p = (sion_int64 *) malloc(maxblocks * ntasks * sizeof(sion_int64));
  if (sion_blocksizes == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_allocate_sion_arrays_locations: cannot allocate temporary memory of size %lu (sion_blocksizes), aborting ...\n", 
			    (unsigned long) ntasks * sizeof(sion_int64)));
  }
  for (i = 0; i < maxblocks; i++)
    p[i] = -1;


  DPRINTFP((2, "_sion_allocate_sion_arrays_locations", -1, "leave alloc locations size=%d, maxblocks=%d\n", ntasks, maxblocks));
  return (1);
}

/*!\brief Free the memory used by the internal sion arrays
 *
 * @param  **sion_chunksizes            array of the chunksizes of all tasks
 * @param  **sion_startpointers         array of the starting pointers
 * @param  **sion_globalranks           array of global ranks for all tasks
 *
 * @retval      1 if OK
 */
int _sion_deallocate_sion_arrays(sion_int64 **sion_chunksizes, sion_int64 **sion_startpointers, sion_int64 **sion_globalranks)
{
  int       rc = 1;
  DPRINTFP((2, "_sion_deallocate_sion_arrays", -1, "enter\n"));
  if (*sion_chunksizes != NULL) {
    free(*sion_chunksizes);
    *sion_chunksizes = NULL;
  }
  if (*sion_startpointers != NULL) {
    free(*sion_startpointers);
    *sion_startpointers = NULL;
  }
  if (*sion_globalranks != NULL) {
    free(*sion_globalranks);
    *sion_globalranks = NULL;
  }
  DPRINTFP((2, "_sion_deallocate_sion_arrays", -1, "leave\n"));
  return (rc);
}

/*!\brief Free the memory for the internal sion structure
 *
 * @param  ntasks                       number of processes
 * @param  maxblocks                    maxblocks
 * @param  **sion_blockcount            array of blockcounts of all tasks
 * @param  **sion_currentpos            array of current position pointers
 * @param  **sion_currentblocknr        array of current block numbers for all tasks
 * @param  **sion_blocksizes            array of current block sizes for all tasks
 *
 * @retval 1 if OK
 */
int _sion_deallocate_sion_arrays_locations(int ntasks,
                                           sion_int32 maxblocks,
                                           sion_int64 **sion_blockcount,
                                           sion_int64 **sion_currentpos, sion_int64 **sion_currentblocknr, sion_int64 **sion_blocksizes)
{
  int       rc = 1;
  DPRINTFP((2, "_sion_deallocate_sion_arrays_locations", -1, "enter dealloc location\n"));
  if (*sion_blockcount != NULL) {
    free(*sion_blockcount);
    *sion_blockcount = NULL;
  }
  if (*sion_currentpos != NULL) {
    free(*sion_currentpos);
    *sion_currentpos = NULL;
  }
  if (*sion_currentblocknr != NULL) {
    free(*sion_currentblocknr);
    *sion_currentblocknr = NULL;
  }
  if (*sion_blocksizes != NULL) {
    free(*sion_blocksizes);
    *sion_blocksizes = NULL;
  }
  DPRINTFP((2, "_sion_deallocate_sion_arrays_locations", -1, "leave dealloc location\n"));
  return (rc);
}

/*!\brief Increase the memory used by the internal sion structure
 *
 * @param  *sion_filedesc                       sion file description struct (_sion_filedesc)
 * @param  maxblocks                            maximum number of chunks written by all tasks
 *
 * @retval      1 if OK
 */
int _sion_realloc_blocklist(_sion_filedesc *sion_filedesc, sion_int32 maxblocks)
{
  int       rc = 1;
  int       i;
  if (sion_filedesc->maxblocks <= 0) {
    sion_filedesc->chunksizes = (sion_int64 *) malloc(maxblocks * sizeof(sion_int64));
    if (sion_filedesc->chunksizes == NULL) {
      return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_realloc_blocklist: cannot allocate temporary memory of size %lu (sion_blocksizes), aborting ...\n",
			      (unsigned long) maxblocks * sizeof(sion_int64)));
    }
    for (i = 0; i < maxblocks; i++)
      sion_filedesc->chunksizes[i] = 0; /* init */
    sion_filedesc->maxblocks = maxblocks;
  }
  else {
    if (sion_filedesc->maxblocks <= maxblocks) {
      sion_filedesc->chunksizes = (sion_int64 *) realloc(sion_filedesc->chunksizes, maxblocks * sizeof(sion_int64));
      for (i = sion_filedesc->maxblocks; i < maxblocks; i++)
        sion_filedesc->chunksizes[i] = 0;       /* init */
      sion_filedesc->maxblocks = maxblocks;
    }
    else {
      fprintf(stderr, "allocate temporary memory of size %lu (sion_blocksizes) not necessary (allocated size %lu) ...\n",
              (unsigned long) maxblocks * sizeof(sion_int64), (unsigned long) sion_filedesc->maxblocks * sizeof(sion_int64));
    }
  }
  return (rc);
}



/*!\brief Initialize the sion file description
 *
 * @param *sion_filedesc        sion file description struct (_sion_filedesc)
 *
 * @retval      1 if OK
 */
int _sion_init_filedesc(_sion_filedesc *sion_filedesc)
{

  int       rc = 1;

  if (sion_filedesc == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_init_filedesc: cannot initalized, data structure is not allocated, aborting ...\n"));
  }
  sion_filedesc->fd = NULL;
  sion_filedesc->secondfd = NULL;
  sion_filedesc->fname = NULL;
  sion_filedesc->rank = -1;
  sion_filedesc->ntasks = -1;
  sion_filedesc->state = SION_FILESTATE_UNKNOWN;
  sion_filedesc->mode = SION_FILEMODE_UNKNOWN;
  sion_filedesc->endianness = -1;
  sion_filedesc->swapbytes = 0;
  sion_filedesc->fileversion = SION_FILEFORMAT_VERSION;
  sion_filedesc->fsblksize = -1;        /* fs block size */
  sion_filedesc->numblocks = -1;        /* number of current block */
  sion_filedesc->maxblocks = -1;

  sion_filedesc->startpos = -1;
  sion_filedesc->chunksize = -1;
  sion_filedesc->chunksizes = NULL;     /* vector of written bytes in each blovk for current task */

  sion_filedesc->globalskip = -1;       /* number of bytes to skip to next block of same processor */
  sion_filedesc->end_of_header = -1;
  sion_filedesc->start_of_varheader = -1;
  sion_filedesc->start_of_data = -1;

  sion_filedesc->all_chunksizes = NULL; /* only used if sion is opened from a single task for read  */
  sion_filedesc->all_globalranks = NULL;        /* only used if sion is opened from a single task for read  */
  sion_filedesc->all_startpointers = NULL;      /* only used if sion is opened from a single task for read  */

  sion_filedesc->all_currentpos = NULL; /* only used if sion is opened from a single task for write  */
  sion_filedesc->all_currentblocknr = NULL;     /* only used if sion is opened from a single task for write  */

  sion_filedesc->all_blockcount = NULL; /* size, only used if sion is opened from a single task for read  */
  sion_filedesc->all_blocksizes = NULL; /* size*maxblocks, only used if sion is opened from a single task for read  */

  sion_filedesc->currentpos = -1;       /* only used if opened  for one rank, reading */
  sion_filedesc->currentblocknr = -1;   /* only used if opened  for one rank, reading */
  sion_filedesc->debug = -1;    /* 0 or 1 for debugging */

  sion_filedesc->nfiles = -1;
  sion_filedesc->filenumber = -1;
  sion_filedesc->mapping_size = -1;
  sion_filedesc->mapping = NULL;

  sion_filedesc->flag1 = _SION_FLAG1_NONE;
  sion_filedesc->flag2 = _SION_FLAG2_NONE;
  sion_filedesc->prefix = NULL;
  sion_filedesc->newfname = NULL;

  return (rc);
}

int _sion_free_filedesc(_sion_filedesc *sion_filedesc)
{

  int       rc = 1;

  if (sion_filedesc == NULL) {
    return (0);
  }

  if (sion_filedesc->fname)
    free(sion_filedesc->fname);
  if (sion_filedesc->chunksizes)
    free(sion_filedesc->chunksizes);
  if (sion_filedesc->all_chunksizes)
    free(sion_filedesc->all_chunksizes);
  if (sion_filedesc->all_globalranks)
    free(sion_filedesc->all_globalranks);
  if (sion_filedesc->all_startpointers)
    free(sion_filedesc->all_startpointers);
  if (sion_filedesc->all_currentpos)
    free(sion_filedesc->all_currentpos);
  if (sion_filedesc->all_currentblocknr)
    free(sion_filedesc->all_currentblocknr);
  if (sion_filedesc->all_blockcount)
    free(sion_filedesc->all_blockcount);
  if (sion_filedesc->all_blocksizes)
    free(sion_filedesc->all_blocksizes);
  if (sion_filedesc->prefix)
    free(sion_filedesc->prefix);
  if (sion_filedesc->newfname)
    free(sion_filedesc->newfname);
  if (sion_filedesc->mapping)
    free(sion_filedesc->mapping);

  free(sion_filedesc);

  return (rc);
}

/*!\brief Print the initialized sion file description
 *
 * @retval      1 if OK
 */
int _sion_print_filedesc(_sion_filedesc *sion_filedesc, int level, char *desc, int all)
{

  int       rc = 1;
  int       i;

  if (sion_filedesc == NULL) {
    return(_sion_errorprint(0,_SION_ERROR_RETURN,"_sion_print_filedesc: cannot print, data structure is not allocated, aborting ...\n"));
  }

  DPRINTFP((level, desc, sion_filedesc->rank, "DUMP: sion_filedesc\n"));
  DPRINTFP((level, desc, sion_filedesc->rank, "-------------------\n"));

  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%x\n", "fd", sion_filedesc->fd));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%x\n", "secondfd", sion_filedesc->secondfd));

  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%s\n", "fname", sion_filedesc->fname));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "rank", sion_filedesc->rank));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "ntasks", sion_filedesc->ntasks));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "state", sion_filedesc->state));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "mode", sion_filedesc->mode));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "endianness", sion_filedesc->endianness));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "swapbytes", sion_filedesc->swapbytes));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "fileversion", sion_filedesc->fileversion));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "fsblksize", sion_filedesc->fsblksize));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "numblocks", sion_filedesc->numblocks));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "maxblocks", sion_filedesc->maxblocks));

  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%lld\n", "startpos", sion_filedesc->startpos));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%lld\n", "chunksize", sion_filedesc->chunksize));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%lld\n", "globalskip", sion_filedesc->globalskip));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%lld\n", "end_of_header", sion_filedesc->end_of_header));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%lld\n", "start_of_varheader", sion_filedesc->start_of_varheader));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%lld\n", "start_of_data", sion_filedesc->start_of_data));

  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "nfiles", sion_filedesc->nfiles));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=%d\n", "filenumber", sion_filedesc->filenumber));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=\"%s\"\n", "prefix", sion_filedesc->prefix));
  DPRINTFP((level, desc, sion_filedesc->rank, "D: %-20s=\"%s\"\n", "newfname", sion_filedesc->newfname));

  //  if (sion_filedesc->nfiles > 1)
  //    for(i=0;i<sion_filedesc->nfiles;i++)
  //      DPRINTFP((  level,desc,sion_filedesc->rank,"D: file[%d]=%s\n", i,    sion_filedesc->files[i]));


  for (i = 0; i < sion_filedesc->numblocks; i++) {
    DPRINTFP((level, desc, sion_filedesc->rank, "D:  %-20s[%4d]=%lld\n", "chunksizes", i, sion_filedesc->chunksizes[i]));
  }

  if (all) {
    /*
       sion_filedesc->all_chunksizes     = NULL;
       sion_filedesc->all_globalranks    = NULL;
       sion_filedesc->all_startpointers  = NULL;

       sion_filedesc->all_currentpos     = NULL;
       sion_filedesc->all_currentblocknr = NULL ;

       sion_filedesc->all_blockcount     = NULL;
       sion_filedesc->all_blocksizes     = NULL;

       sion_filedesc->currentpos         = -1;
       sion_filedesc->currentblocknr     = -1;
       sion_filedesc->debug              = -1;
     */

  }

  return (rc);
}

/*!\brief Internal SION error
 *
 * Exit the program with an error status
 */
int _sion_errorprint(int rc, int level, const char *format, ...)
{
  int       rank=-1;
  va_list ap;
  
  switch (level) {
    case _SION_ERROR_RETURN: 
      fprintf(stderr,"SION_ERROR_RETURN on rank %d, rc=%d: ",rank,rc);
      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);
      fprintf(stderr,"\n");
      return (rc);
      break;
    case _SION_ERROR_WARN: 
      fprintf(stderr,"SION_ERROR_WARN on rank %d, rc=%d: ",rank,rc);
      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);
      fprintf(stderr,"\n");
      return (rc);
      break;
    case _SION_ERROR_ABORT: 
      fprintf(stderr,"SION_ERROR_ABORT on rank %d, rc=%d: \n",rank,rc);
      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);
      fprintf(stderr,"\n");
      exit (rc);
      break;
  default:
      fprintf(stderr,"SION_ERROR_UNKNOWN on rank %d, rc=%d: ",rank,rc);
      va_start(ap, format);
      vfprintf(stderr, format, ap);
      va_end(ap);
      fprintf(stderr,"\n");
      return (rc);
  }
  return (rc);
}
