"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "cfitsio/cfileio.c" of archive cfitsio3100.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*  This file, cfileio.c, contains the low-level file access routines.     */
    2 
    3 /*  The FITSIO software was written by William Pence at the High Energy    */
    4 /*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
    5 /*  Goddard Space Flight Center.                                           */
    6 
    7 #include <string.h>
    8 #include <stdlib.h>
    9 #include <math.h>
   10 #include <ctype.h>
   11 #include <errno.h>
   12 #include <stddef.h>  /* apparently needed to define size_t */
   13 #include "fitsio2.h"
   14 #include "group.h"
   15 
   16 #define MAX_PREFIX_LEN 20  /* max length of file type prefix (e.g. 'http://') */
   17 #define MAX_DRIVERS 23     /* max number of file I/O drivers */
   18 
   19 typedef struct    /* structure containing pointers to I/O driver functions */
   20 {   char prefix[MAX_PREFIX_LEN];
   21     int (*init)(void);
   22     int (*shutdown)(void);
   23     int (*setoptions)(int option);
   24     int (*getoptions)(int *options);
   25     int (*getversion)(int *version);
   26     int (*checkfile)(char *urltype, char *infile, char *outfile);
   27     int (*open)(char *filename, int rwmode, int *driverhandle);
   28     int (*create)(char *filename, int *drivehandle);
   29     int (*truncate)(int drivehandle, LONGLONG size);
   30     int (*close)(int drivehandle);
   31     int (*remove)(char *filename);
   32     int (*size)(int drivehandle, LONGLONG *size);
   33     int (*flush)(int drivehandle);
   34     int (*seek)(int drivehandle, LONGLONG offset);
   35     int (*read)(int drivehandle, void *buffer, long nbytes);
   36     int (*write)(int drivehandle, void *buffer, long nbytes);
   37 } fitsdriver;
   38 
   39 fitsdriver driverTable[MAX_DRIVERS];  /* allocate driver tables */
   40 
   41 FITSfile *FptrTable[NMAXFILES];  /* this table of Fptr pointers is */
   42                                  /* used by fits_already_open */
   43 
   44 int need_to_initialize = 1;    /* true if CFITSIO has not been initialized */
   45 int no_of_drivers = 0;         /* number of currently defined I/O drivers */
   46 
   47 static int pixel_filter_helper(fitsfile **fptr, char *outfile,
   48 				char *expr,  int *status);
   49 
   50 
   51 /*--------------------------------------------------------------------------*/
   52 int ffomem(fitsfile **fptr,      /* O - FITS file pointer                   */
   53            const char *name,     /* I - name of file to open                */
   54            int mode,             /* I - 0 = open readonly; 1 = read/write   */
   55            void **buffptr,       /* I - address of memory pointer           */
   56            size_t *buffsize,     /* I - size of buffer, in bytes            */
   57            size_t deltasize,     /* I - increment for future realloc's      */
   58            void *(*mem_realloc)(void *p, size_t newsize), /* function       */
   59            int *status)          /* IO - error status                       */
   60 /*
   61   Open an existing FITS file in core memory.  This is a specialized version
   62   of ffopen.
   63 */
   64 {
   65     int driver, handle, hdutyp, slen, movetotype, extvers, extnum;
   66     char extname[FLEN_VALUE];
   67     LONGLONG filesize;
   68     char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME];
   69     char extspec[FLEN_FILENAME], rowfilter[FLEN_FILENAME];
   70     char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME];
   71     char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME];
   72     char *url, errmsg[FLEN_ERRMSG];
   73     char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"};
   74 
   75     if (*status > 0)
   76         return(*status);
   77 
   78     *fptr = 0;                   /* initialize null file pointer */
   79 
   80     if (need_to_initialize)           /* this is called only once */
   81     {
   82         if (need_to_initialize != 1) {
   83 	  /* This is bad. looks like memory has been corrupted. */
   84 	  ffpmsg("Vital CFITSIO parameters held in memory have been corrupted!!");
   85 	  ffpmsg("Fatal condition detected in ffomem.");
   86 	  *status = FILE_NOT_OPENED;
   87 	  return(*status);
   88 	}
   89 
   90         *status = fits_init_cfitsio();
   91 
   92         if (*status > 0)
   93             return(*status);
   94     }
   95 
   96     url = (char *) name;
   97     while (*url == ' ')  /* ignore leading spaces in the file spec */
   98         url++;
   99 
  100         /* parse the input file specification */
  101     ffiurl(url, urltype, infile, outfile, extspec,
  102               rowfilter, binspec, colspec, status);
  103 
  104     strcpy(urltype, "memkeep://");   /* URL type for pre-existing memory file */
  105 
  106     *status = urltype2driver(urltype, &driver);
  107 
  108     if (*status > 0)
  109     {
  110         ffpmsg("could not find driver for pre-existing memory file: (ffomem)");
  111         return(*status);
  112     }
  113 
  114     /* call driver routine to open the memory file */
  115     *status =   mem_openmem( buffptr, buffsize,deltasize,
  116                             mem_realloc,  &handle);
  117 
  118     if (*status > 0)
  119     {
  120          ffpmsg("failed to open pre-existing memory file: (ffomem)");
  121          return(*status);
  122     }
  123 
  124         /* get initial file size */
  125     *status = (*driverTable[driver].size)(handle, &filesize);
  126 
  127     if (*status > 0)
  128     {
  129         (*driverTable[driver].close)(handle);  /* close the file */
  130         ffpmsg("failed get the size of the memory file: (ffomem)");
  131         return(*status);
  132     }
  133 
  134         /* allocate fitsfile structure and initialize = 0 */
  135     *fptr = (fitsfile *) calloc(1, sizeof(fitsfile));
  136 
  137     if (!(*fptr))
  138     {
  139         (*driverTable[driver].close)(handle);  /* close the file */
  140         ffpmsg("failed to allocate structure for following file: (ffomem)");
  141         ffpmsg(url);
  142         return(*status = MEMORY_ALLOCATION);
  143     }
  144 
  145         /* allocate FITSfile structure and initialize = 0 */
  146     (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile));
  147 
  148     if (!((*fptr)->Fptr))
  149     {
  150         (*driverTable[driver].close)(handle);  /* close the file */
  151         ffpmsg("failed to allocate structure for following file: (ffomem)");
  152         ffpmsg(url);
  153         free(*fptr);
  154         *fptr = 0;
  155         return(*status = MEMORY_ALLOCATION);
  156     }
  157 
  158     slen = strlen(url) + 1;
  159     slen = maxvalue(slen, 32); /* reserve at least 32 chars */
  160     ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */
  161 
  162     if ( !(((*fptr)->Fptr)->filename) )
  163     {
  164         (*driverTable[driver].close)(handle);  /* close the file */
  165         ffpmsg("failed to allocate memory for filename: (ffomem)");
  166         ffpmsg(url);
  167         free((*fptr)->Fptr);
  168         free(*fptr);
  169         *fptr = 0;              /* return null file pointer */
  170         return(*status = MEMORY_ALLOCATION);
  171     }
  172 
  173     /* mem for headstart array */
  174     ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG));
  175 
  176     if ( !(((*fptr)->Fptr)->headstart) )
  177     {
  178         (*driverTable[driver].close)(handle);  /* close the file */
  179         ffpmsg("failed to allocate memory for headstart array: (ffomem)");
  180         ffpmsg(url);
  181         free( ((*fptr)->Fptr)->filename);
  182         free((*fptr)->Fptr);
  183         free(*fptr);
  184         *fptr = 0;              /* return null file pointer */
  185         return(*status = MEMORY_ALLOCATION);
  186     }
  187 
  188         /* store the parameters describing the file */
  189     ((*fptr)->Fptr)->MAXHDU = 1000;              /* initial size of headstart */
  190     ((*fptr)->Fptr)->filehandle = handle;        /* file handle */
  191     ((*fptr)->Fptr)->driver = driver;            /* driver number */
  192     strcpy(((*fptr)->Fptr)->filename, url);      /* full input filename */
  193     ((*fptr)->Fptr)->filesize = filesize;        /* physical file size */
  194     ((*fptr)->Fptr)->logfilesize = filesize;     /* logical file size */
  195     ((*fptr)->Fptr)->writemode = mode;      /* read-write mode    */
  196     ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */
  197     ((*fptr)->Fptr)->curbuf = -1;             /* undefined current IO buffer */
  198     ((*fptr)->Fptr)->open_count = 1;     /* structure is currently used once */
  199     ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */
  200 
  201     ffldrc(*fptr, 0, REPORT_EOF, status);     /* load first record */
  202 
  203     fits_store_Fptr( (*fptr)->Fptr, status);  /* store Fptr address */
  204 
  205     if (ffrhdu(*fptr, &hdutyp, status) > 0)  /* determine HDU structure */
  206     {
  207         ffpmsg(
  208           "ffomem could not interpret primary array header of file: (ffomem)");
  209         ffpmsg(url);
  210 
  211         if (*status == UNKNOWN_REC)
  212            ffpmsg("This does not look like a FITS file.");
  213 
  214         ffclos(*fptr, status);
  215         *fptr = 0;              /* return null file pointer */
  216     }
  217 
  218     /* ---------------------------------------------------------- */
  219     /* move to desired extension, if specified as part of the URL */
  220     /* ---------------------------------------------------------- */
  221 
  222     imagecolname[0] = '\0';
  223     rowexpress[0] = '\0';
  224 
  225     if (*extspec)
  226     {
  227        /* parse the extension specifier into individual parameters */
  228        ffexts(extspec, &extnum,
  229          extname, &extvers, &movetotype, imagecolname, rowexpress, status);
  230 
  231 
  232       if (*status > 0)
  233           return(*status);
  234 
  235       if (extnum)
  236       {
  237         ffmahd(*fptr, extnum + 1, &hdutyp, status);
  238       }
  239       else if (*extname) /* move to named extension, if specified */
  240       {
  241         ffmnhd(*fptr, movetotype, extname, extvers, status);
  242       }
  243 
  244       if (*status > 0)
  245       {
  246         ffpmsg("ffomem could not move to the specified extension:");
  247         if (extnum > 0)
  248         {
  249           sprintf(errmsg,
  250           " extension number %d doesn't exist or couldn't be opened.",extnum);
  251           ffpmsg(errmsg);
  252         }
  253         else
  254         {
  255           sprintf(errmsg,
  256           " extension with EXTNAME = %s,", extname);
  257           ffpmsg(errmsg);
  258 
  259           if (extvers)
  260           {
  261              sprintf(errmsg,
  262              "           and with EXTVERS = %d,", extvers);
  263              ffpmsg(errmsg);
  264           }
  265 
  266           if (movetotype != ANY_HDU)
  267           {
  268              sprintf(errmsg,
  269              "           and with XTENSION = %s,", hdtype[movetotype]);
  270              ffpmsg(errmsg);
  271           }
  272 
  273           ffpmsg(" doesn't exist or couldn't be opened.");
  274         }
  275         return(*status);
  276       }
  277     }
  278 
  279     return(*status);
  280 }
  281 /*--------------------------------------------------------------------------*/
  282 int ffdkopn(fitsfile **fptr,      /* O - FITS file pointer                   */
  283            const char *name,     /* I - full name of file to open           */
  284            int mode,             /* I - 0 = open readonly; 1 = read/write   */
  285            int *status)          /* IO - error status                       */
  286 /*
  287   Open an existing FITS file on magnetic disk with either readonly or
  288   read/write access.  The routine does not support CFITSIO's extended
  289   filename syntax and simply uses the entire input 'name' string as
  290   the name of the file.
  291 */
  292 {
  293     if (*status > 0)
  294         return(*status);
  295 
  296     *status = OPEN_DISK_FILE;
  297 
  298     ffopen(fptr, name, mode, status);
  299 
  300     return(*status);
  301 }
  302 /*--------------------------------------------------------------------------*/
  303 int ffdopn(fitsfile **fptr,      /* O - FITS file pointer                   */
  304            const char *name,     /* I - full name of file to open           */
  305            int mode,             /* I - 0 = open readonly; 1 = read/write   */
  306            int *status)          /* IO - error status                       */
  307 /*
  308   Open an existing FITS file with either readonly or read/write access. and
  309   move to the first HDU that contains 'interesting' data, if the primary
  310   array contains a null image (i.e., NAXIS = 0).
  311 */
  312 {
  313     if (*status > 0)
  314         return(*status);
  315 
  316     *status = SKIP_NULL_PRIMARY;
  317 
  318     ffopen(fptr, name, mode, status);
  319 
  320     return(*status);
  321 }
  322 /*--------------------------------------------------------------------------*/
  323 int fftopn(fitsfile **fptr,      /* O - FITS file pointer                   */
  324            const char *name,     /* I - full name of file to open           */
  325            int mode,             /* I - 0 = open readonly; 1 = read/write   */
  326            int *status)          /* IO - error status                       */
  327 /*
  328   Open an existing FITS file with either readonly or read/write access. and
  329   move to the first HDU that contains 'interesting' table (not an image).
  330 */
  331 {
  332     int hdutype;
  333 
  334     if (*status > 0)
  335         return(*status);
  336 
  337     *status = SKIP_IMAGE;
  338 
  339     ffopen(fptr, name, mode, status);
  340 
  341     if (ffghdt(*fptr, &hdutype, status) <= 0) {
  342         if (hdutype == IMAGE_HDU)
  343             *status = NOT_TABLE;
  344     }
  345 
  346     return(*status);
  347 }
  348 /*--------------------------------------------------------------------------*/
  349 int ffiopn(fitsfile **fptr,      /* O - FITS file pointer                   */
  350            const char *name,     /* I - full name of file to open           */
  351            int mode,             /* I - 0 = open readonly; 1 = read/write   */
  352            int *status)          /* IO - error status                       */
  353 /*
  354   Open an existing FITS file with either readonly or read/write access. and
  355   move to the first HDU that contains 'interesting' image (not an table).
  356 */
  357 {
  358     int hdutype;
  359 
  360     if (*status > 0)
  361         return(*status);
  362 
  363     *status = SKIP_TABLE;
  364 
  365     ffopen(fptr, name, mode, status);
  366 
  367     if (ffghdt(*fptr, &hdutype, status) <= 0) {
  368         if (hdutype != IMAGE_HDU)
  369             *status = NOT_IMAGE;
  370     }
  371 
  372     return(*status);
  373 }
  374 /*--------------------------------------------------------------------------*/
  375 int ffopentest(double version,   /* I - CFITSIO version number, from the    */
  376                                  /*     application program (fitsio.h file) */
  377            fitsfile **fptr,      /* O - FITS file pointer                   */
  378            const char *name,     /* I - full name of file to open           */
  379            int mode,             /* I - 0 = open readonly; 1 = read/write   */
  380            int *status)          /* IO - error status                       */
  381 /*
  382   Open an existing FITS file with either readonly or read/write access.
  383   First test that the version of fitsio.h used to build the CFITSIO library
  384   is the same as the version used in building the application program that
  385   links to the library.
  386 */
  387 {
  388     if (version != CFITSIO_VERSION)
  389     {
  390         printf("ERROR: Mismatch in the version of the fitsio.h include file used to build\n");
  391 	printf("the CFITSIO library, and the version included by the application program:\n");
  392 	printf("   Version used to build the CFITSIO library   = %f\n",CFITSIO_VERSION);
  393 	printf("   Version included by the application program = %f\n",version);
  394 
  395         *status = FILE_NOT_OPENED;
  396 	return(*status);
  397     }
  398 
  399     /* now call the normal file open routine */
  400     ffopen(fptr, name, mode, status);
  401     return(*status);
  402 }
  403 /*--------------------------------------------------------------------------*/
  404 int ffopen(fitsfile **fptr,      /* O - FITS file pointer                   */
  405            const char *name,     /* I - full name of file to open           */
  406            int mode,             /* I - 0 = open readonly; 1 = read/write   */
  407            int *status)          /* IO - error status                       */
  408 /*
  409   Open an existing FITS file with either readonly or read/write access.
  410 */
  411 {
  412     fitsfile *newptr;
  413     int  driver, hdutyp, hdunum, slen, writecopy, isopen;
  414     LONGLONG filesize;
  415     long rownum, nrows, goodrows;
  416     int extnum, extvers, handle, movetotype, tstatus = 0;
  417     char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME];
  418     char origurltype[MAX_PREFIX_LEN], extspec[FLEN_FILENAME];
  419     char extname[FLEN_VALUE], rowfilter[FLEN_FILENAME], tblname[FLEN_VALUE];
  420     char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME];
  421     char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME], pixfilter[FLEN_FILENAME];
  422     char histfilename[FLEN_FILENAME];
  423     char filtfilename[FLEN_FILENAME];
  424     char wtcol[FLEN_VALUE];
  425     char minname[4][FLEN_VALUE], maxname[4][FLEN_VALUE];
  426     char binname[4][FLEN_VALUE];
  427 
  428     char *url;
  429     double minin[4], maxin[4], binsizein[4], weight;
  430     int imagetype, naxis = 1, haxis, recip;
  431     int skip_null = 0, skip_image = 0, skip_table = 0, open_disk_file = 0;
  432     char colname[4][FLEN_VALUE];
  433     char errmsg[FLEN_ERRMSG];
  434     char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"};
  435     char *rowselect = 0;
  436 
  437     if (*status > 0)
  438         return(*status);
  439 
  440     if (*status == SKIP_NULL_PRIMARY)
  441     {
  442       /* this special status value is used as a flag by ffdopn to tell */
  443       /* ffopen to skip over a null primary array when opening the file. */
  444 
  445        skip_null = 1;
  446        *status = 0;
  447     }
  448     else if (*status == SKIP_IMAGE)
  449     {
  450       /* this special status value is used as a flag by fftopn to tell */
  451       /* ffopen to move to 1st significant table when opening the file. */
  452 
  453        skip_image = 1;
  454        *status = 0;
  455     }
  456     else if (*status == SKIP_TABLE)
  457     {
  458       /* this special status value is used as a flag by ffiopn to tell */
  459       /* ffopen to move to 1st significant image when opening the file. */
  460 
  461        skip_table = 1;
  462        *status = 0;
  463     }
  464     else if (*status == OPEN_DISK_FILE)
  465     {
  466       /* this special status value is used as a flag by ffdkopn to tell */
  467       /* ffopen to not interpret the input filename using CFITSIO's    */
  468       /* extended filename syntax, and simply open the specified disk file */
  469 
  470        open_disk_file = 1;
  471        *status = 0;
  472     }
  473 
  474     *fptr = 0;              /* initialize null file pointer */
  475     writecopy = 0;  /* have we made a write-able copy of the input file? */
  476 
  477     if (need_to_initialize) {          /* this is called only once */
  478 
  479        if (need_to_initialize != 1) {
  480 	  /* This is bad. looks like memory has been corrupted. */
  481 	  ffpmsg("Vital CFITSIO parameters held in memory have been corrupted!!");
  482 	  ffpmsg("Fatal condition detected in ffopen.");
  483 	  *status = FILE_NOT_OPENED;
  484 	  return(*status);
  485        }
  486 
  487        *status = fits_init_cfitsio();
  488     }
  489 
  490     if (*status > 0)
  491         return(*status);
  492 
  493     url = (char *) name;
  494     while (*url == ' ')  /* ignore leading spaces in the filename */
  495         url++;
  496 
  497     if (*url == '\0')
  498     {
  499         ffpmsg("Name of file to open is blank. (ffopen)");
  500         return(*status = FILE_NOT_OPENED);
  501     }
  502 
  503     if (open_disk_file)
  504     {
  505       /* treat the input URL literally as the name of the file to open */
  506       /* and don't try to parse the URL using the extended filename syntax */
  507 
  508         if (strlen(url) > FLEN_FILENAME - 1) {
  509             ffpmsg("Name of file to open is too long. (ffopen)");
  510             return(*status = FILE_NOT_OPENED);
  511         }
  512 
  513         strcpy(infile,url);
  514         strcpy(urltype, "file://");
  515         outfile[0] = '\0';
  516         extspec[0] = '\0';
  517         binspec[0] = '\0';
  518         colspec[0] = '\0';
  519         rowfilter[0] = '\0';
  520         pixfilter[0] = '\0';
  521     }
  522     else
  523     {
  524         /* parse the input file specification */
  525 
  526         /* NOTE: This routine tests that all the strings do not */
  527 	/* overflow the standard buffer sizes (FLEN_FILENAME, etc.) */
  528 	/* therefore in general we do not have to worry about buffer */
  529 	/* overflow of any of the returned strings. */
  530 
  531         fits_parse_input_filename(url, urltype, infile, outfile, extspec,
  532               rowfilter, binspec, colspec, pixfilter, status);
  533     }
  534 
  535     if (*status > 0)
  536     {
  537         ffpmsg("could not parse the input filename: (ffopen)");
  538         ffpmsg(url);
  539         return(*status);
  540     }
  541 
  542     imagecolname[0] = '\0';
  543     rowexpress[0] = '\0';
  544 
  545     if (*extspec)
  546     {
  547        /* parse the extension specifier into individual parameters */
  548        ffexts(extspec, &extnum,
  549          extname, &extvers, &movetotype, imagecolname, rowexpress, status);
  550 
  551       if (*status > 0)
  552           return(*status);
  553     }
  554 
  555     /*-------------------------------------------------------------------*/
  556     /* special cases:                                                    */
  557     /*-------------------------------------------------------------------*/
  558 
  559     histfilename[0] = '\0';
  560     filtfilename[0] = '\0';
  561     if (*outfile && (*binspec || *imagecolname || *pixfilter))
  562     {
  563         /* if binspec or imagecolumn are specified, then the  */
  564         /* output file name is intended for the final image,  */
  565         /* and not a copy of the input file.                  */
  566 
  567         strcpy(histfilename, outfile);
  568         outfile[0] = '\0';
  569     }
  570     else if (*outfile && (*rowfilter || *colspec))
  571     {
  572         /* if rowfilter or colspece are specified, then the    */
  573         /* output file name is intended for the filtered file  */
  574         /* and not a copy of the input file.                   */
  575 
  576         strcpy(filtfilename, outfile);
  577         outfile[0] = '\0';
  578     }
  579 
  580     /*-------------------------------------------------------------------*/
  581     /* check if this same file is already open, and if so, attach to it  */
  582     /*-------------------------------------------------------------------*/
  583 
  584     if (fits_already_open(fptr, url, urltype, infile, extspec, rowfilter,
  585             binspec, colspec, mode, &isopen, status) > 0)
  586     {
  587         return(*status);
  588     }
  589 
  590     if (isopen)
  591        goto move2hdu;
  592 
  593     /* get the driver number corresponding to this urltype */
  594     *status = urltype2driver(urltype, &driver);
  595 
  596     if (*status > 0)
  597     {
  598         ffpmsg("could not find driver for this file: (ffopen)");
  599         ffpmsg(urltype);
  600         ffpmsg(url);
  601         return(*status);
  602     }
  603 
  604     /*-------------------------------------------------------------------
  605         deal with all those messy special cases which may require that
  606         a different driver be used:
  607             - is disk file compressed?
  608             - are ftp:, gsiftp:, or http: files compressed?
  609             - has user requested that a local copy be made of
  610               the ftp or http file?
  611       -------------------------------------------------------------------*/
  612 
  613     if (driverTable[driver].checkfile)
  614     {
  615         strcpy(origurltype,urltype);  /* Save the urltype */
  616 
  617         /* 'checkfile' may modify the urltype, infile and outfile strings */
  618         *status =  (*driverTable[driver].checkfile)(urltype, infile, outfile);
  619 
  620         if (*status)
  621         {
  622             ffpmsg("checkfile failed for this file: (ffopen)");
  623             ffpmsg(url);
  624             return(*status);
  625         }
  626 
  627         if (strcmp(origurltype, urltype))  /* did driver changed on us? */
  628         {
  629             *status = urltype2driver(urltype, &driver);
  630             if (*status > 0)
  631             {
  632                 ffpmsg("could not change driver for this file: (ffopen)");
  633                 ffpmsg(url);
  634                 ffpmsg(urltype);
  635                 return(*status);
  636             }
  637         }
  638     }
  639 
  640     /* call appropriate driver to open the file */
  641     if (driverTable[driver].open)
  642     {
  643         *status =  (*driverTable[driver].open)(infile, mode, &handle);
  644         if (*status > 0)
  645         {
  646             ffpmsg("failed to find or open the following file: (ffopen)");
  647             ffpmsg(url);
  648             return(*status);
  649        }
  650     }
  651     else
  652     {
  653         ffpmsg("cannot open an existing file of this type: (ffopen)");
  654         ffpmsg(url);
  655         return(*status = FILE_NOT_OPENED);
  656     }
  657 
  658         /* get initial file size */
  659     *status = (*driverTable[driver].size)(handle, &filesize);
  660     if (*status > 0)
  661     {
  662         (*driverTable[driver].close)(handle);  /* close the file */
  663         ffpmsg("failed get the size of the following file: (ffopen)");
  664         ffpmsg(url);
  665         return(*status);
  666     }
  667 
  668         /* allocate fitsfile structure and initialize = 0 */
  669     *fptr = (fitsfile *) calloc(1, sizeof(fitsfile));
  670 
  671     if (!(*fptr))
  672     {
  673         (*driverTable[driver].close)(handle);  /* close the file */
  674         ffpmsg("failed to allocate structure for following file: (ffopen)");
  675         ffpmsg(url);
  676         return(*status = MEMORY_ALLOCATION);
  677     }
  678 
  679         /* allocate FITSfile structure and initialize = 0 */
  680     (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile));
  681 
  682     if (!((*fptr)->Fptr))
  683     {
  684         (*driverTable[driver].close)(handle);  /* close the file */
  685         ffpmsg("failed to allocate structure for following file: (ffopen)");
  686         ffpmsg(url);
  687         free(*fptr);
  688         *fptr = 0;
  689         return(*status = MEMORY_ALLOCATION);
  690     }
  691 
  692     slen = strlen(url) + 1;
  693     slen = maxvalue(slen, 32); /* reserve at least 32 chars */
  694     ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */
  695 
  696     if ( !(((*fptr)->Fptr)->filename) )
  697     {
  698         (*driverTable[driver].close)(handle);  /* close the file */
  699         ffpmsg("failed to allocate memory for filename: (ffopen)");
  700         ffpmsg(url);
  701         free((*fptr)->Fptr);
  702         free(*fptr);
  703         *fptr = 0;              /* return null file pointer */
  704         return(*status = MEMORY_ALLOCATION);
  705     }
  706 
  707     /* mem for headstart array */
  708     ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG));
  709 
  710     if ( !(((*fptr)->Fptr)->headstart) )
  711     {
  712         (*driverTable[driver].close)(handle);  /* close the file */
  713         ffpmsg("failed to allocate memory for headstart array: (ffopen)");
  714         ffpmsg(url);
  715         free( ((*fptr)->Fptr)->filename);
  716         free((*fptr)->Fptr);
  717         free(*fptr);
  718         *fptr = 0;              /* return null file pointer */
  719         return(*status = MEMORY_ALLOCATION);
  720     }
  721         /* store the parameters describing the file */
  722     ((*fptr)->Fptr)->MAXHDU = 1000;              /* initial size of headstart */
  723     ((*fptr)->Fptr)->filehandle = handle;        /* file handle */
  724     ((*fptr)->Fptr)->driver = driver;            /* driver number */
  725     strcpy(((*fptr)->Fptr)->filename, url);      /* full input filename */
  726     ((*fptr)->Fptr)->filesize = filesize;        /* physical file size */
  727     ((*fptr)->Fptr)->logfilesize = filesize;     /* logical file size */
  728     ((*fptr)->Fptr)->writemode = mode;           /* read-write mode    */
  729     ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */
  730     ((*fptr)->Fptr)->curbuf = -1;            /* undefined current IO buffer */
  731     ((*fptr)->Fptr)->open_count = 1;      /* structure is currently used once */
  732     ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */
  733 
  734     ffldrc(*fptr, 0, REPORT_EOF, status);     /* load first record */
  735 
  736     fits_store_Fptr( (*fptr)->Fptr, status);  /* store Fptr address */
  737 
  738     if (ffrhdu(*fptr, &hdutyp, status) > 0)  /* determine HDU structure */
  739     {
  740         ffpmsg(
  741           "ffopen could not interpret primary array header of file: ");
  742         ffpmsg(url);
  743 
  744         if (*status == UNKNOWN_REC)
  745            ffpmsg("This does not look like a FITS file.");
  746 
  747         ffclos(*fptr, status);
  748         *fptr = 0;              /* return null file pointer */
  749         return(*status);
  750     }
  751 
  752     /* ------------------------------------------------------------- */
  753     /* At this point, the input file has been opened. If outfile was */
  754     /* specified, then we have opened a copy of the file, not the    */
  755     /* original file so it is safe to modify it if necessary         */
  756     /* ------------------------------------------------------------- */
  757 
  758     if (*outfile)
  759         writecopy = 1;
  760 
  761 move2hdu:
  762 
  763     /* ---------------------------------------------------------- */
  764     /* move to desired extension, if specified as part of the URL */
  765     /* ---------------------------------------------------------- */
  766 
  767     if (*extspec)
  768     {
  769       if (extnum)  /* extension number was specified */
  770       {
  771         ffmahd(*fptr, extnum + 1, &hdutyp, status);
  772       }
  773       else if (*extname) /* move to named extension, if specified */
  774       {
  775         ffmnhd(*fptr, movetotype, extname, extvers, status);
  776       }
  777 
  778       if (*status > 0)  /* clean up after error */
  779       {
  780         ffpmsg("ffopen could not move to the specified extension:");
  781         if (extnum > 0)
  782         {
  783           sprintf(errmsg,
  784           " extension number %d doesn't exist or couldn't be opened.",extnum);
  785           ffpmsg(errmsg);
  786         }
  787         else
  788         {
  789           sprintf(errmsg,
  790           " extension with EXTNAME = %s,", extname);
  791           ffpmsg(errmsg);
  792 
  793           if (extvers)
  794           {
  795              sprintf(errmsg,
  796              "           and with EXTVERS = %d,", extvers);
  797              ffpmsg(errmsg);
  798           }
  799 
  800           if (movetotype != ANY_HDU)
  801           {
  802              sprintf(errmsg,
  803              "           and with XTENSION = %s,", hdtype[movetotype]);
  804              ffpmsg(errmsg);
  805           }
  806 
  807           ffpmsg(" doesn't exist or couldn't be opened.");
  808         }
  809 
  810         ffclos(*fptr, status);
  811         *fptr = 0;              /* return null file pointer */
  812         return(*status);
  813       }
  814     }
  815     else if (skip_null || skip_image || skip_table ||
  816             (*imagecolname || *colspec || *rowfilter || *binspec))
  817     {
  818       /* ------------------------------------------------------------------
  819 
  820       If no explicit extension specifier is given as part of the file
  821       name, and, if a) skip_null is true (set if ffopen is called by
  822       ffdopn) or b) skip_image or skip_table is true (set if ffopen is
  823       called by fftopn or ffdopn) or c) other file filters are
  824       specified, then CFITSIO will attempt to move to the first
  825       'interesting' HDU after opening an existing FITS file (or to
  826       first interesting table HDU if skip_image is true);
  827 
  828       An 'interesting' HDU is defined to be either an image with NAXIS
  829       > 0 (i.e., not a null array) or a table which has an EXTNAME
  830       value which does not contain any of the following strings:
  831          'GTI'  - Good Time Interval extension
  832          'OBSTABLE'  - used in Beppo SAX data files
  833 
  834       The main purpose for this is to allow CFITSIO to skip over a null
  835       primary and other non-interesting HDUs when opening an existing
  836       file, and move directly to the first extension that contains
  837       significant data.
  838       ------------------------------------------------------------------ */
  839 
  840       fits_get_hdu_num(*fptr, &hdunum);
  841       if (hdunum == 1) {
  842 
  843         fits_get_img_dim(*fptr, &naxis, status);
  844 
  845         if (naxis == 0 || skip_image) /* skip primary array */
  846         {
  847           while(1)
  848           {
  849             /* see if the next HDU is 'interesting' */
  850             if (fits_movrel_hdu(*fptr, 1, &hdutyp, status))
  851             {
  852                if (*status == END_OF_FILE)
  853                   *status = 0;  /* reset expected error */
  854 
  855                /* didn't find an interesting HDU so move back to beginning */
  856                fits_movabs_hdu(*fptr, 1, &hdutyp, status);
  857                break;
  858             }
  859 
  860             if (hdutyp == IMAGE_HDU && skip_image) {
  861 
  862                 continue;   /* skip images */
  863 
  864             } else if (hdutyp != IMAGE_HDU && skip_table) {
  865 
  866                 continue;   /* skip tables */
  867 
  868