/****************************************************************************
**  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       **
****************************************************************************/
/*!
 * @file sion_fortran.c
 *
 * @brief Fortran API
 *
 * @author Ventsislav Petkov
 * @date 14.08.2008
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* #define _FORTRANUNDERSCORE
   #define _FORTRANNOCAPS
   #define _FORTRANCAPS
   #define _FORTRANDOUBLEUNDERSCORE */
#include "sion_fd.h"
#include "sion_fortran.h"

/*!
 * @brief Fortran procedure to open a sion file in serial mode.
 *
 * This function opens a sion file in serial mode
 *
 * @param[in]           fname           name of file, should equal on all tasks
 * @param[in,out]       file_mode       like the type parameter of fopen (currently recognized options: "rb", "wb")
 * @param[in]           ntasks          number of tasks used to write this file
 * @param[in,out]       chunksizes      chunksize for each task
 * @param[in,out]       fsblksize       blocksize of filesystem, must be equal on all processors
 * @param[in]           globalranks     rank numbers for which the file should be open;
 *                                      will be stored in sion file, usefull if comm is not MPI_COMM_WORLD
 *                                      typical: globalrank= rank in MPI_COMM_WORLD
 * @param[in]           fname_len       (internal) length of the fname string
 * @param[in]           file_mode_len   (internal) length of the file_mode string
 *
 * @retval              sid             sion file handle or -1 if error occured
 *
 */
void fsion_open(char *fname,
                char *file_mode,
                int *ntasks, 
                int *nfiles, 
		sion_int32 *fsblksize, 
		int *globalranks, 
		int *sid, 
		long fname_len, 
		long file_mode_len)
{

  FILE     *fileptr;
  /* Fortran strings are not NULL-terminated => insert \0 at the end */
  char     *fname_tmp, *fmode_tmp;
  


  fname_tmp = (char *) malloc((size_t) ((fname_len + 1) * sizeof(char)));
  fmode_tmp = (char *) malloc((size_t) ((file_mode_len + 1) * sizeof(char)));
  /* Copy the strings to the new buffers and pad with nulls */
  strncpy(fname_tmp, fname, fname_len);
  strncpy(fmode_tmp, file_mode, file_mode_len);

  fname_tmp[fname_len] = '\0';
  fmode_tmp[file_mode_len] = '\0';


  DPRINTFP((2, "fsion_open", -1, "params: %s %s %d %ld \n", fname_tmp, fmode_tmp, (int) *ntasks, (long) *fsblksize)); 

  (*sid) = sion_open(fname_tmp, fmode_tmp, ntasks, nfiles, NULL, fsblksize, &globalranks, &fileptr);

  DPRINTFP((2, "fsion_open", -1, "sid: %d\n", *sid));

  /* Free the used memory */
  free(fname_tmp);
  free(fmode_tmp);
}


/*!
 * @brief Fortran procedure to open a sion file for a specific rank
 *
 * This function opens a sion file for a specific rank.  It can be
 * used to open the sion file independently from each task.
 * (e.g. if no MPI is available or only a subset of tasks chunks are needed)
 *
 * Using this function the meta data at beginning of the sion file are read
 * from each task instead of read once and distribute (sion_open).
 * sion_open_rank reads only the tasks specific meta data  from the meta data
 * block at the end of the sion file.
 *
 * Warning: Only read operations are currently supported.
 *
 * @param[in]           fname           name of file, should equal on all tasks
 * @param[in,out]       file_mode       like the type parameter of fopen (currently recognized options: "rb", "wb")
 * @param[in,out]       chunksize       chunksize for this task
 * @param[in,out]       fsblksize       blocksize of filesystem, must be equal on all processors
 * @param[in]           rank            rank number for which the file should be open;
 *                                      will be stored in sion file, usefull if comm is not MPI_COMM_WORLD
 *                                      typical: globalrank= rank in MPI_COMM_WORLD
 * @param[in]           fname_len       (internal) length of the fname string *
 * @param[in]           file_mode_len   (internal) length of the file_mode string
 *
 * @retval              sid             sion file handle or -1 if error occured
 */
void fsion_open_rank(char *fname,
                     char *file_mode, sion_int64 *chunksize, sion_int32 *fsblksize, int *rank, int *sid, long fname_len, long file_mode_len)
{

  FILE     *fileptr;
  /* Fortran strings are not NULL-terminated => insert \0 at the end */
  char     *fname_tmp, *fmode_tmp;

  fname_tmp = (char *) malloc((size_t) ((fname_len + 1) * sizeof(char)));
  fmode_tmp = (char *) malloc((size_t) ((file_mode_len + 1) * sizeof(char)));
  /* Copy the strings to the new buffers and pad with nulls */
  strncpy(fname_tmp, fname, fname_len);
  strncpy(fmode_tmp, file_mode, file_mode_len);
  fname_tmp[fname_len] = '\0';
  fmode_tmp[file_mode_len] = '\0';

  (*sid) = sion_open_rank(fname_tmp, fmode_tmp, chunksize, fsblksize, rank, &fileptr);

  /* Free the used memory */
  free(fname_tmp);
  free(fmode_tmp);
}

#ifdef SION_MPI

/*!
 * @brief Wrapper function that calls fsion_paropen_multi_mpi for 1 file
 *
 * This function opens the file in parallel. It has to be called from
 * each processor at the same time (like a MPI collective operation).
 *
 * @param[in]           fname           name of file, should equal on all tasks
 * @param[in]           file_mode       like the type parameter of fopen ("rb", "wb")
 * @param[in]           comm            MPI communicator, which contains all tasks involved in this operation
 *                                      typical: MPI_COMM_WORLD
 * @param[in,out]       chunksize       chunksize for this task
 * @param[in,out]       fsblksize       filesystem blocksize, must be equal on all processors
 * @param[in,out]       globalrank      any global unique id for this task
 *                                      will be stored in sion file, usefull if comm is not MPI_COMM_WORLD
 *                                      typical: globalrank= rank in MPI_COMM_WORLD
 *
 * @param[in]           fname_len       (internal) length of the fname string *
 * @param[in]           file_mode_len   (internal) length of the file_mode string
 *
 * @retval              sid             sion file handle or -1 if error occured
 */
void fsion_paropen_mpi(char *fname,
                       char *file_mode,
		       int  *numFiles,
                       MPI_Fint * fgComm,
                       MPI_Fint * flComm,
                       sion_int64 *chunksize, 
		       sion_int32 *fsblksize, 
		       int *globalrank, 
		       char *newfname,
		       int *sid, 
		       long fname_len, 
		       long file_mode_len,
		       long newfname_len) {

  FILE     *fileptr;
  char     *fname_tmp,*fmode_tmp,*newfname_tmp;
  MPI_Comm  cgComm,clComm;


#ifdef SION_DEBUG_BUG_OPENMPI
  {
    int grank;
    MPI_Comm newcomm;
    MPI_Comm_rank(MPI_COMM_WORLD,&grank);
    fprintf(stderr,"fsion_paropen_mpi: grank: %d\n", (int) grank);
    MPI_Comm_dup(MPI_COMM_WORLD,&newcomm);
    MPI_Comm_split(MPI_COMM_WORLD,0,grank,&newcomm);
  }
#endif

  fname_tmp = (char *) malloc((size_t) ((fname_len + 1) * sizeof(char)));
  fmode_tmp = (char *) malloc((size_t) ((file_mode_len + 1) * sizeof(char)));
/*   newfname_tmp = (char *) malloc((size_t) ((newfname_len + 1) * sizeof(char))); */

  /* Copy the strings to the new buffers and pad with nulls */
  strncpy(fname_tmp, fname, fname_len);
  strncpy(fmode_tmp, file_mode, file_mode_len);

  fname_tmp[fname_len] = '\0';
  fmode_tmp[file_mode_len] = '\0';
/*   newfname_tmp[newfname_len] = '\0'; */
/*   strncpy(newfname_tmp, newfname, newfname_len); */

  cgComm = MPI_Comm_f2c(*fgComm);
  clComm = MPI_Comm_f2c(*flComm); 

#ifdef SION_DEBUG
  if (*globalrank == 0){
    if (cgComm == MPI_COMM_WORLD) fprintf(stderr,"COMM_WORLD selected\n");
    fprintf(stderr,"fsion_paropen_mpi: filename_len: %d\n", (int) fname_len);
    fprintf(stderr,"fsion_paropen_mpi: filename: %s\n",fname_tmp);
    /*
      fprintf(stderr,"fsion_paropen_mpi: newfname_len: %d\n",(int) newfname_len);
      fprintf(stderr,"fsion_paropen_mpi: newfname: %s\n",newfname_tmp);
    */
    fprintf(stderr,"fsion_paropen_mpi: filemode_len: %d\n", (int) file_mode_len);
    fprintf(stderr,"fsion_paropen_mpi: filemode: %s\n",fmode_tmp);
    
    fprintf(stderr,"fsion_paropen_mpi: chunksize: %lld\n",*chunksize);
    fprintf(stderr,"fsion_paropen_mpi: fsblksize: %d\n",*fsblksize);
    fprintf(stderr,"fsion_paropen_mpi: numFiles:  %d\n",*numFiles);
  }
#endif

  (*sid) = sion_paropen_mpi(fname_tmp, fmode_tmp, numFiles, cgComm, &clComm, chunksize, fsblksize, globalrank, &fileptr, NULL);

  *flComm = MPI_Comm_c2f(clComm);
/*   strncpy(newfname, newfname_tmp, newfname_len); */

  /* Free the used memory */
  free(fname_tmp);
  free(fmode_tmp);

}

/*!
 * @brief Fortran procedure to open multiple sion files in parallel.
 *
 * This function opens numFiles files in parallel. It has to be called from
 * each processor at the same time (like a MPI collective operation).
 *
 * @param[in]           fname           name of file, should equal on all tasks
 * @param[in]           file_mode       like the type parameter of fopen ("rb", "wb")
 * @param[in]           numFiles        number of files to open
 * @param[in]           gComm           global MPI communicator, which contains all tasks writing to the files
 *                                      typical: MPI_COMM_WORLD
 * @param[in,out]       lComm           new local MPI communicator, which contains all tasks writing to the current file
 * @param[in,out]       chunksize       chunksize for this task
 * @param[in,out]       fsblksize       filesystem blocksize, must be equal on all processors
 * @param[in,out]       globalrank      any global unique id for this task
 *                                      will be stored in sion file, usefull if comm is not MPI_COMM_WORLD
 *                                      typical: globalrank= rank in MPI_COMM_WORLD
 *
 * @param[in]           fname_len       (internal) length of the fname string *
 * @param[in]           file_mode_len   (internal) length of the file_mode string
 * @param[in]           newfname_len    (internal) length of the newfname string
 *
 *
 * @retval              sid             sion file handle or -1 if error occured
 * @retval              newfname        filename of the new file
 */
void fsion_paropen_multi_mpi(char *fname,
                             char *file_mode,
                             int *numFiles,
                             MPI_Fint * fgComm,
                             MPI_Fint * flComm,
                             sion_int64 *chunksize,
                             sion_int32 *fsblksize,
                             int *globalrank, int *sid, char *newfname, long fname_len, long file_mode_len, long newfname_len)
{
  FILE     *fileptr;
  MPI_Comm  cgComm, clComm;

  /* Fortran strings are not NULL-terminated => insert \0 at the end */
  char     *fname_tmp, *fmode_tmp, *newfname_tmp;


  fname_tmp = (char *) malloc((size_t) ((fname_len + 1) * sizeof(char)));
  fmode_tmp = (char *) malloc((size_t) ((file_mode_len + 1) * sizeof(char)));
  newfname_tmp = (char *) malloc((size_t) ((newfname_len + 1) * sizeof(char)));
  /* Copy the strings to the new buffers and pad with nulls */
  strncpy(fname_tmp, fname, fname_len);
  strncpy(fmode_tmp, file_mode, file_mode_len);

  fname_tmp[fname_len] = '\0';
  fmode_tmp[file_mode_len] = '\0';
  newfname_tmp[newfname_len] = '\0';
  strncpy(newfname_tmp, newfname, newfname_len);

  cgComm = MPI_Comm_f2c(*fgComm);
  /*        clComm = MPI_Comm_f2c(*flComm); */

  /*
     #ifdef SION_DEBUG
     if (*globalrank == 0){
     if (cgComm == MPI_COMM_WORLD) fprintf(stderr,"COMM_WORLD selected\n");
     fprintf(stderr,"fsion_paropen_mpi: filename_len: %d\n", fname_len);
     fprintf(stderr,"fsion_paropen_mpi: filename: %s\n",fname_tmp);

     fprintf(stderr,"fsion_paropen_mpi: newfname_len: %d\n", newfname_len);
     fprintf(stderr,"fsion_paropen_mpi: newfname: %s\n",newfname_tmp);

     fprintf(stderr,"fsion_paropen_mpi: filemode_len: %d\n", file_mode_len);
     fprintf(stderr,"fsion_paropen_mpi: filemode: %s\n",fmode_tmp);

     fprintf(stderr,"fsion_paropen_mpi: chunksize: %lld\n",*chunksize);
     fprintf(stderr,"fsion_paropen_mpi: fsblksize: %d\n",*fsblksize);
     fprintf(stderr,"fsion_paropen_mpi: numFiles:  %d\n",*numFiles);
     }
     #endif
   */
  (*sid) = sion_paropen_multi_mpi(fname_tmp, fmode_tmp, numFiles, cgComm, &clComm, chunksize, fsblksize, globalrank, &fileptr, newfname_tmp);

  *flComm = MPI_Comm_c2f(clComm);
  strncpy(newfname, newfname_tmp, newfname_len);

  /* Free the used memory */
  free(fname_tmp);
  free(fmode_tmp);
  free(newfname_tmp);
}

/*!
 * @brief Fortran procedure to close a sion file in parallel.
 *
 * This function closes the sion in parallel on all tasks included in comm.
 * The communicator should be the same used in the parallel open statement.
 *
 * @param[in]   sid     sion file handle
 * @param[in]   comm    MPI communicator, which contains all tasks involved in this operation
 *                      typical: MPI_COMM_WORLD
 * @retval      ierr    1 if close is ok
 */
void fsion_parclose_mpi(int *sid, int *ierr)
{
  (*ierr) = sion_parclose_mpi(*sid);
}

#endif


/*!
 * @brief Fortran procedure to close a sion file.
 *
 * This procedure closes a sion file which was opened in serial mode with sion_open or sion_open_rank.
 * In Write mode this function will also save all meta data to the meta data block of the sion file
 * at the beginning and the end of t
 * he file.
 * The function is a task local function, which can be called independently from other MPI tasks.
 *
 * @param[in]   sid     sion file handle
 *
 * @param[out]  ierr    1 if close is ok
 */
void fsion_close(int *sid, int *ierr)
{
  (*ierr) = sion_close(*sid);
}

/*!
 * @brief Fortran function that indicates the end of file for this task.
 *
 * This function indicates if the end of file is reached for this task.
 * This means that the file pointer is behind of the last bytes of last chunk of this task.
 * If all bytes of the current chunk are already read and there are more chunks available
 * for this task, sion_feof will advance the filepointer to the start position of the
 * next chunk in the sion file.
 * The function is a task local function, which can be called independently from other MPI tasks.
 *
 * @param[in]   sid     sion file handle
 * @param[out]  eof     1 if the End of the File is reached
 *
 * @retval      1 if end of last chunk reached
 *              0 otherwise
 */
void fsion_feof(int *sid, int *eof)
{

  *eof = sion_feof(*sid);
}

/*!
 * @brief Fortran procedure to set the file pointer to a new position.
 *
 * This procedure sets the file pointer to a new position according to the specified parameters.
 * It can only be used when the sion file was opened for reading in serial mode.
 * In Write mode currently only the rank can be modified!
 * SION_CURRENT_BLK and SION_CURRENT_POS are required
 *
 * @param[in]   sid             sion file handle
 * @param[in]   rank            rank number of the process (SION_CURRENT_RANK to select the current rank)
 * @param[in]   currentblocknr  block number (SION_CURRENT_BLK to select the current block)
 * @param[in]   posinblk        position in the block (SION_CURRENT_POS to select the current position)
 *
 * @param[out]  ierr            1 if file pointer can be moved to new position
 *                              0 otherwise
 */
void fsion_seek(int *sid, int *rank, int *currentblocknr, sion_int64 *posinblk, int *ierr)
{

  DPRINTFP((2, "fsion_seek", -1, "params: %d %d %d %lld\n", *sid, *rank, *currentblocknr, *posinblk));

  (*ierr) = sion_seek(*sid, *rank, *currentblocknr, *posinblk);
}

/*!
 * @brief Fortran procedure to ensure that enough space is available.
 *
 * This procedure ensures that there is enough space available for writing numbytes bytes
 * to the sion file. It allocates a new block at the end of the sion file of size chunksize
 * if numbytes cannot be written in the current block.
 * This procedure is only be needed if the caller function from the user program does not count
 * the number of bytes written. It is a task local function, which can be called independently
 * from other MPI tasks, and it moves in some cases the filepointer to a new position and flushes
 * also the local filepointer.
 *
 * @param[in]   sid     sion file handle
 * @param[in]   bytes   number of bytes which will be written
 *
 * @param[out]  ierr    1 if ok
 */
void fsion_ensure_free_space(int *sid, sion_int64 *bytes, int *ierr)
{

  (*ierr) = sion_ensure_free_space(*sid, *bytes);
}

/*!
 * @brief Fortran procedure to write to a sion file.
 *
 * This fortran procedure writes nitems objects, each size bytes long, to a sion file,
 * obtaining them from the location given by data. It advances the file position indicator
 * by the number of bytes written.
 *
 * @param[in]   data    pointer to the data to be written
 * @param[in]   size    size of the data
 * @param[in]   nitems  number of items of data to write to the file
 * @param[in]   sid     sion file handle
 *
 * @param[out]  rc      number of objects written or a short object count (or zero)
 *                      if an error occurs, or the end-of-file is reached
 */
void fsion_write(const void *data, int *size, sion_int64 *nitems, int *sid, sion_int64 *rc)
{
  (*rc) = (sion_int64) fwrite(data, *size, (int) *nitems, sion_get_fp(*sid));
}

/*!
 * @brief Fortran procedure to flush a sion file.
 *
 * This fortran procedure flushes the buffers and writes the data to the sion file.
 *
 * @param[in]   sid     sion file handle
 *
 * @param[out]  ierr    1 if ok
 */
void fsion_flush(int *sid, int *ierr)
{

  (*ierr) = sion_flush(*sid);

}

/*!
 * @brief Fortran procedure to read from a sion file.
 *
 * This fortran procedure reads nitems objects, each size bytes long, from a sion file,
 * storing them at the location given by data. It advances the file position indicator
 * by the number of bytes read or written.
 *
 * @param[in]   data    pointer to the store location
 * @param[in]   size    size of the data
 * @param[in]   nitems  number of items of data to read from the file
 * @param[in]   sid             sion file handle
 *
 * @param[out]  rc              number of objects read or a short object count (or zero)
 *                                              if an error occurs, or the end-of-file is reached
 */
void fsion_read(void *data, int *size, sion_int64 *nitems, int *sid, sion_int64 *rc)
{
  (*rc) = (sion_int64) fread(data, *size, (int) *nitems, sion_get_fp(*sid));
}

/*!@brief Fortran function that returns the number of bytes available in the current chunk.
 *
 * This function returns the number of bytes currently available in the current chunk (bytes not read).
 * It is a local function, which can be called independently from other MPI tasks.
 *
 * @param[in]   sid             sion file handle
 *
 * @returns     INTEGER*4       rc>0  number of bytes
 *                                              rc<=0 file position is after end of block
 */
sion_int64 fsion_bytes_avail_in_block(int *sid)
{

  return sion_bytes_avail_in_block(*sid);
}

/*!
 * @brief Fortran procedure that returns pointers to internal fields.
 *
 * This procedure returns pointers to internal fields, containing the number of chunks written
 * by each task (sion_chunkcount) and their sizes (sion_chunksizes).
 * This function is only needed if the sion file was opened for reading in serial mode.
 *
 * @param[in]   sid                     sion file handle
 * @param[out]  ntasks                  number of tasks wrote to the sion file
 * @param[out]  maxblocks               maximum number of chunks per tasks used
 * @param[out]  globalskip              distance in bytes between the first bytes
 *                                      of two subsequent chunks of a task
 * @param[out]  start_of_varheader      start position of the meta data block at the end of sion file
 * @param[out]  sion_localsizes         field containing requested chunk size of each task
 * @param[out]  sion_globalranks        field containing global unique id of each task
 * @param[out]  sion_chunkcount         field containing number of chunks used by each task
 * @param[out]  sion_chunksizes         field containing for each task and chunk the number of bytes
 *                                                                      used in this chunk
 *                                                                      e.g. access: sion_chunksizes[rank*chunks+chunknr]
 * @param[out]  ierr                            1 if ok
 */
void fsion_get_locations(int *sid,
                         int *ntasks,
                         int *maxblocks,
                         sion_int64 *globalskip,
                         sion_int64 *start_of_varheader,
                         sion_int64 **sion_localsizes,
                         sion_int64 **sion_globalranks, sion_int64 **sion_chunkcount, sion_int64 **sion_chunksizes, int *ierr)
{

  (*ierr) = sion_get_locations(*sid, ntasks, maxblocks, globalskip, start_of_varheader, sion_localsizes,
                               sion_globalranks, sion_chunkcount, sion_chunksizes);
}

/*!
 * @brief Fortran function that returns the current file position
 *
 * This fortran function returns an INTEGER*8 containing the current file possition.
 *
 * @param[in]   sid                     sion file handle (in)
 * @returns             INTEGER*8       current file position
 */
sion_int64 fsion_get_position(int *sid)
{

  return sion_get_position(*sid);
}

/* OTHER UNDOCUMENTED FUNCTIONS */

void fsion_get_current_locations(int *sid, int *ntasks, sion_int64 **sion_currentpos, sion_int64 **sion_currentblocknr, int *ierr)
{

  (*ierr) = sion_get_current_locations(*sid, ntasks, sion_currentpos, sion_currentblocknr);
}


void fsion_get_chunksizes(int         *sid,
			  sion_int64  *chunksizes, 
			  int         *ierr)
{
  _sion_filedesc *sion_filedesc;
  int i;
  ierr=0;

  if ((_sion_vcdtype(*sid) != SION_FILEDESCRIPTOR)
      || !(sion_filedesc = _sion_vcdtovcon(*sid))) {
    fprintf(stderr, "invalid sion_filedesc, aborting %d ...\n", *sid);
    *ierr=-1;
    return;
  }
  if(sion_filedesc->chunksizes) {
    for(i=0;i<sion_filedesc->ntasks;i++) {
      chunksizes[i]=sion_filedesc->all_chunksizes[i];
    }
  }

}

void fsion_get_mapping_spec(int         *sid,
			    int         *mapping_size, 
			    int         *numfiles, 
			    int         *ierr)
{
  ierr=0;
  _sion_filedesc *sion_filedesc;
  if ((_sion_vcdtype(*sid) != SION_FILEDESCRIPTOR)
      || !(sion_filedesc = _sion_vcdtovcon(*sid))) {
    fprintf(stderr, "invalid sion_filedesc, aborting %d ...\n", *sid);
    *ierr=-1;
    return;
  }
  *mapping_size = sion_filedesc->mapping_size;
  *numfiles     = sion_filedesc->nfiles;

}

void fsion_get_mapping(int *sid, sion_int32 *mapping, int *ierr)
{
  _sion_filedesc *sion_filedesc;
  int rank;

  if ((_sion_vcdtype(*sid) != SION_FILEDESCRIPTOR)
      || !(sion_filedesc = _sion_vcdtovcon(*sid))) {
    fprintf(stderr, "invalid sion_filedesc, aborting %d ...\n", *sid);
    *ierr=-1;
    return;
  }
  if(sion_filedesc->nfiles>1) {
    for (rank = 0; rank < sion_filedesc->mapping_size; rank++) {
      DPRINTFP((32, "fsion_get_mapping", 0, " mapping[%d] = %d , %d \n", rank,sion_filedesc->mapping[rank*2+0],sion_filedesc->mapping[rank*2+1]));
      mapping[rank*2+0]=sion_filedesc->mapping[rank*2+0];
      mapping[rank*2+1]=sion_filedesc->mapping[rank*2+1];
    }
  } else {
    *ierr=-1;
  }
}

/*!
 * @brief Fortran function that returns the current file position
 *
 * This fortran function returns an INTEGER*8 containing the current file possition.
 *
 * @param[in]   sid                     sion file handle (in)
 * @returns             INTEGER*8       current file position
 */
void fsion_get_fileno(int *sid, int *filenumber)
{
  _sion_filedesc *sion_filedesc;
  if ((_sion_vcdtype(*sid) != SION_FILEDESCRIPTOR)
      || !(sion_filedesc = _sion_vcdtovcon(*sid))) {
    fprintf(stderr, "invalid sion_filedesc, aborting %d ...\n", *sid);
    *filenumber=-1;
    return;
  }
  *filenumber = fileno(SIONFP);
  return;
}
