[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 961108: CDL support in netCDF library



>Subject: CDL support in netCDF library
>Organization: Harvard
>Keywords: 199611082101.AA14359

Bob,

> > something like what you suggest, I'd probably create the file in /tmp/
> > rather than in memory (some systems keep /tmp/ in swap space anyway) and
> > write a wrapper around ncopen() that would invoke system() to have ncgen
> > create the netCDF file from the CDL file much as I do currently in the
> > program described above.  The wrapper would be able to open either CDL
> > or netCDF files and in the former case return a valid netCDF file ID to
> > the transient file in /tmp/.
> 
> that sounds like a good idea.  can you send me the code you mentioned?
> i could make one added subroutine, cdl_open(), which would:
>  *) do ncgen, and put the result in /tmp
>  *) open the /tmp CDF file
>  *) return the ncid
> this would be pretty transparent and easy-to-use

I've appended some code for this, extracted from a package of
meteorological decoders that we distribute:

    http://www.unidata.ucar.edu/packages/decoders/

Unless it was designed with reusable parts in mind, it's often difficult
to extract a small part of an existing package like this without getting
tendrils that would pull in a large part of other package code,
e.g. error handling.  Hence I haven't included some of these parts.

For example, a function is called that is not provided here named
diraccess() that you probably don't need, in which case you can just
delete the call to it.  If you do need it, you can find it in the
decoders package referenced above, in src/gribtonc/mkdirs_open.c

--Russ

_____________________________________________________________________

Russ Rew                                         UCAR Unidata Program
address@hidden                     http://www.unidata.ucar.edu


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <netcdf.h>

/*
 * Name of environment variable containing directory in which to search for
 * CDL files if not found relative to directory from which this process is
 * invoked.
 */
#define LDM_ETCDIR      "LDM_ETCDIR"

/*
 * Checks to see if netCDF file with specified name exists.  If not,
 * makes netCDF file from CDL template file.
 * Returns netCDF file ID on success, or -1 on error.
 */
int
cdl_netcdf (cdlname, ncname)
     char *cdlname;     /* CDL file specifying netCDF structure */
     char *ncname;      /* filename of netcdf file to be created */
{
    char cmnd[2*_POSIX_PATH_MAX+20];
    char *cdlfile = cdlname;
    static char *cdldir = 0;
    char envcdl[_POSIX_PATH_MAX];

    ncopts = 0;                 /* turn off netCDF error messages from
                                   library, means we will have to check all
                                   netCDF status returns and interpret */

    if (access(ncname, (R_OK|W_OK)) != 0) { /* no writable ncname exists */
        if (cdlfile == 0) {
            uerror("%s doesn't exist, and didn't specify a CDL filename",
                   ncname);
            return -1;
        }

        /* Try to create any directories in output path that don't exist */
        if (diraccess(ncname,  (R_OK | W_OK), !0) == -1) {
            serror("can't access directories leading to %s", ncname);
            return -1;
        }

        /* If CDL file not found, look in environment variable LDM_ETCDIR */
        if (access(cdlname, R_OK) == -1) { /* no CDL file or unreadable */
            if (cdldir == 0) {  /* executed once, when cdldir first needed */
                char *ldm_etcdir = getenv(LDM_ETCDIR);
                int slen;
                
                if (ldm_etcdir == 0) {
                    uerror("CDL file %s not found & LDM_ETCDIR not in 
environment",
                           cdlname);
                    return -1;
                }
                slen = strlen(ldm_etcdir);
                cdldir = (char *)malloc((slen+2));
                if (cdldir == 0) {
                    uerror("Out of memory!");
                    return -1;
                }
                strcpy(cdldir, ldm_etcdir);
                if (cdldir[slen-1] != '/') { /* append "/" to dir name */
                    strcat(cdldir, "/");
                }
            }
            strcat(envcdl,cdldir);
            strcat(envcdl,cdlname);
            if (access(envcdl, R_OK) == -1) {
                uerror("can't find CDL file %s, or unreadable", envcdl);
                return -1;
            }
            cdlfile = envcdl;
        }
        
        (void) strcpy(cmnd, "ncgen -o ");
        (void) strcat(cmnd, ncname);
        (void) strcat(cmnd , " ");
        (void) strcat(cmnd, cdlfile);
        
        if (system(cmnd) != 0) {
            uerror("can't run \"%s\"", cmnd);
            return -1;
        }
    }
    return ncopen(ncname, NC_WRITE);
}