Integrated latest changes to trunk, added preliminary CPack support.

This commit is contained in:
Ward Fisher 2012-08-02 22:56:57 +00:00
commit 0d90326575
96 changed files with 660 additions and 14169 deletions

View File

@ -2,8 +2,8 @@
cmake_minimum_required(VERSION 2.8.8)
#Project Name
project(NETCDF C)
SET(PACKAGE_VERSION 4.2.1)
project(NetCDF C)
SET(NetCDF_VERSION 4.2.1)
ADD_DEFINITIONS()
### Verbose make, for debugging.
@ -24,6 +24,13 @@ INCLUDE (${CMAKE_ROOT}/Modules/CheckSymbolExists.cmake)
INCLUDE (${CMAKE_ROOT}/Modules/FindPkgConfig.cmake)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
IF(APPLE)
SET(CPACK_BINARY_DRAGNDROP ON CACHE BOOL "")
SET(CPACK_BINARY_PACKAGEMAKER OFF CACHE BOOL "")
ENDIF()
#####
# Option checks
#####
@ -233,13 +240,13 @@ CHECK_FUNCTION_EXISTS(getrlimit HAVE_GETRLIMIT)
# Create config.h file
configure_file("${NETCDF_SOURCE_DIR}/cmake_config.h.in"
"${NETCDF_BINARY_DIR}/config.h")
configure_file("${NETCDF_SOURCE_DIR}/cmake_nc-config.in"
"${NETCDF_BINARY_DIR}/nc-config")
EXECUTE_PROCESS(COMMAND "chmod 755 ${NETCDF_BINARY_DIR}/nc-config")
configure_file("${NetCDF_SOURCE_DIR}/cmake_config.h.in"
"${NetCDF_BINARY_DIR}/config.h")
configure_file("${NetCDF_SOURCE_DIR}/cmake_nc-config.in"
"${NetCDF_BINARY_DIR}/nc-config")
EXECUTE_PROCESS(COMMAND "chmod 755 ${NetCDF_BINARY_DIR}/nc-config")
INCLUDE_DIRECTORIES(${NETCDF_BINARY_DIR})
INCLUDE_DIRECTORIES(${NetCDF_BINARY_DIR})
## End autotools-style checs for config.h
@ -247,13 +254,13 @@ INCLUDE_DIRECTORIES(${NETCDF_BINARY_DIR})
#----
# Set core names of the libraries.
#---
SET (NETCDF_LIB_CORENAME "netcdf")
SET (NetCDF_LIB_CORENAME "netcdf")
#---
# Set the true names of all the libraries, if customized by external project
#---
INCLUDE_DIRECTORIES(${NETCDF_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES(${NETCDF_SOURCE_DIR}/oc2)
INCLUDE_DIRECTORIES(${NetCDF_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES(${NetCDF_SOURCE_DIR}/oc2)
# Recurse into other subdirectories.
#add_subdirectory(h5_test)
@ -276,13 +283,12 @@ IF (BUILD_CDMREMOTE)
ENDIF()
add_subdirectory(liblib)
#add_subdirectory(nc_test4)
#add_subdirectory(nc_test)
#add_subdirectory(ncdump)
#add_subdirectory(ncgen3)
#add_subdirectory(ncgen)
#add_subdirectory(examples)
#add_subdirectory(libdap2)
#add_subdirectory(libcdmr)
#add_subdirectory(librpc)
#add_subdirectory(ncdap_test)
#####
# Moving on to CPack, install packages.
#####
#INSTALL(TARGETS liblib/netcdf DESTINATION lib)
INCLUDE(InstallRequiredSystemLibraries)
include(CPack)

4
cf
View File

@ -140,14 +140,14 @@ FLAGS="$FLAGS --enable-logging"
#FLAGS="$FLAGS --enable-large-file-tests"
#FLAGS="$FLAGS --disable-testsets"
#FLAGS="$FLAGS --disable-dap-remote-tests"
FLAGS="$FLAGS --enable-doxygen"
#FLAGS="$FLAGS --enable-doxygen"
FLAGS="$FLAGS --enable-logging"
#FLAGS="$FLAGS --disable-diskless"
#FLAGS="$FLAGS --enable-mmap"
#FLAGS="$FLAGS --with-udunits"
#FLAGS="$FLAGS --with-libcf"
#valgrind => not shared
FLAGS="$FLAGS --enable-valgrind-tests"
#FLAGS="$FLAGS --enable-valgrind-tests"
FLAGS="$FLAGS --disable-shared"
#FLAGS="$FLAGS --enable-shared"

View File

@ -589,8 +589,15 @@ AC_ARG_ENABLE([diskless],
[AS_HELP_STRING([--disable-diskless],
[disable support for in-memory (NC_DISKLESS) files])])
test "x$enable_diskless" = xno || enable_diskless=yes
if test "x$enable_dap" = "xyes" -o "x$enable_cdmremote" = "xyes" -o "x$enable_rpc" = "xyes" ; then
enable_diskless=yes
AC_MSG_NOTICE([--enable-dap requires --enable-diskless])
fi
AC_MSG_RESULT($enable_diskless)
# check for useful, but not essential, memio support
AC_CHECK_FUNCS([memmove getpagesize sysconf])

View File

@ -119,7 +119,7 @@ main()
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_STRONG)) ERR;
if (H5Pset_cache(fapl_id, 0, CHUNK_CACHE_NELEMS, CHUNK_CACHE_SIZE,
CHUNK_CACHE_PREEMPTION) < 0) ERR;
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_18, H5F_LIBVER_18) < 0) ERR;
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;
if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
H5P_CRT_ORDER_INDEXED)) < 0) ERR;

View File

@ -386,6 +386,9 @@ NC_sync(NC *ncp);
extern int
NC_calcsize(const NC *ncp, off_t *filesizep);
extern int
NC_set_readonly(NC *ncp, int onezero);
/* End defined in nc.c */
/* Begin defined in v1hpg.c */

View File

@ -168,7 +168,7 @@ struct nc_vlen_t;
#define NC_NETCDF4 0x1000
#define NC_CLASSIC_MODEL 0x0100
#define NC_ENOPAR (-114)
#endif /*USE_NETCDF4*/
#endif /*!USE_NETCDF4*/
struct NC;
@ -377,7 +377,9 @@ extern const char* NCDAP_urllookup(void* dapurl, const char* param);
MSC_NCDISPATCH_EXTRA extern const char* NC_findtestserver(const char*);
#else
extern const char* NC_findtestserver(const char*);
#endif
/* Ping a specific server */
extern int NCDAP_ping(const char*);

View File

@ -17,7 +17,7 @@
extern void ncloginit(void);
extern void ncsetlogging(int tf);
extern void nclogopen(const char* file);
extern int nclogopen(const char* file);
extern void nclogclose(void);
/* The tag value is an arbitrary integer */

View File

@ -864,10 +864,15 @@ NCerror
computeprojectedvars(NCDAPCOMMON* dapcomm, DCEconstraint* constraint)
{
NCerror ncstat = NC_NOERR;
NClist* vars = nclistnew();
NClist* vars = NULL;
int i;
vars = nclistnew();
if(dapcomm->cdf.projectedvars != NULL)
nclistfree(dapcomm->cdf.projectedvars);
dapcomm->cdf.projectedvars = vars;
if(constraint == NULL || constraint->projections == NULL)
goto done;

View File

@ -24,6 +24,7 @@ dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot)
OCerror ocstat = OC_NOERR;
NClist* allnodes;
OClink conn;
char* ocname = NULL;
conn = nccomm->oc.conn;
@ -37,7 +38,6 @@ dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot)
for(i=0;i<nclistlength(allnodes);i++) {
CDFnode* node = (CDFnode*)nclistget(allnodes,i);
OCddsnode ocnode = node->ocnode;
char* ocname;
size_t attrcount;
OCtype ocetype;
@ -47,6 +47,7 @@ dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot)
char** values = NULL;
NCattribute* att = NULL;
if(ocname != NULL) free(ocname); /* from last loop */
OCCHECK(oc_dds_attr(conn,ocnode,j,&ocname,&ocetype,&nvalues,NULL));
if(nvalues > 0) {
values = (char**)malloc(sizeof(char*)*nvalues);
@ -104,6 +105,7 @@ fprintf(stderr,"%s.Unlimited_Dimension=%s\n",node->ocname,nccomm->cdf.recorddimn
}
done:
if(ocname != NULL) free(ocname);
if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
return THROW(ncstat);
}

View File

@ -8,16 +8,18 @@ PROG=./ncd
P=`pwd`
T="synth1"
T="synth4"
F="file://$TOP/ncdap_test/testdata3/$T"
#F="http://motherlode.ucar.edu:8081/dts/$T"
#F="http://motherlode.ucar.edu:8080/thredds/dodsC/testdods/coads_climatology.nc"
F="http://motherlode.ucar.edu:8080/thredds/dodsC/testdods/coads_climatology.nc"
#F="http://nomads.ncep.noaa.gov:9090/dods/gfs_hd/gfs_hd20120801/gfs_hd_00z"
VAR=lat
PARMS="[log]"
#PARMS="${PARMS}[netcdf3]"
#PARMS="${PARMS}[fetch=disk]"
PARMS="${PARMS}[cache]"
PARMS="${PARMS}[fetch=disk]"
#PARMS="${PARMS}[cache]"
#PARMS="${PARMS}[prefetch]"
#PARMS="${PARMS}[nocache]"
#PARMS="${PARMS}[noprefetch]"
@ -41,9 +43,6 @@ fi
U="${PARMS}$F"
if test "x$CON" != "x" ; then U="${PARMS}$F?$CON"; fi
UALL="${PARMS}$F"
if test "x${VAR}" != "x" ; then
ARGS="$ARGS -v ${VAR}"
fi
#ARGS="-h $ARGS"
#ARGS="-w $ARGS"
#ARGS="-c $ARGS"
@ -54,6 +53,7 @@ alias qq="gdb --args $PROG $ARGS '$U'"
alias qv="valgrind $VARGS PROG $ARGS '$U'"
alias q0="$PROG $ARGS '$U'"
alias qh="$PROG -h $ARGS '$U'"
alias qvar="$PROG -v $VAR $ARGS '$U'"
alias qqh="gdb --args $PROG -h $ARGS '$U'"
alias qall="$PROG -h $ARGS '${UALL}'"
alias qv="valgrind $VARGS $PROG $ARGS '$U'"

View File

@ -53,14 +53,11 @@ nc3dinitialize(void)
dap_zero[i] = 0;
}
nc3dinitialized = 1;
#if 0
/* This is causing a hang */
#ifdef DEBUG
/* force logging to go to stderr */
nclogclose();
nclogopen(NULL);
ncsetlogging(1); /* turn it on */
#endif
if(nclogopen(NULL))
ncsetlogging(1); /* turn it on */
#endif
return NC_NOERR;
}
@ -184,11 +181,11 @@ NCD3_open(const char * path, int mode,
/* Turn on logging; only do this after oc_open*/
if((value = paramvalue34(dapcomm,"log")) != NULL) {
ncloginit();
ncsetlogging(1);
nclogopen(value);
if(nclogopen(value))
ncsetlogging(1);
oc_loginit();
oc_setlogging(1);
oc_logopen(value);
if(oc_logopen(value))
oc_setlogging(1);
}
/* fetch and build the unconstrained DDS for use as
@ -308,6 +305,35 @@ fprintf(stderr,"ncdap3: final constraint: %s\n",dapcomm->oc.url->constraint);
ncstat = buildncstructures3(dapcomm);
if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
/* Explicitly do not call enddef because it will complain
about variables that are too large.
*/
#if 0
ncstat = nc_endef(drno->substrate,NC_NOFILL,NULL);
if(ncstat != NC_NOERR && ncstat != NC_EVARSIZE)
{THROWCHK(ncstat); goto done;}
#endif
{
NC* ncsub;
NC* drno = dapcomm->controller;
CDFnode* unlimited = dapcomm->cdf.recorddim;
/* get the id for the substrate */
ncstat = NC_check_id(drno->substrate,&ncsub);
if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
if(unlimited != NULL) {
/* Set the effective size of UNLIMITED;
note that this cannot easily be done thru the normal API.*/
NC_set_numrecs(ncsub,unlimited->dim.declsize);
}
/* Pretend the substrate is read-only */
NC_set_readonly(ncsub,1);
}
/* Do any necessary data prefetch */
if(FLAGSET(dapcomm->controls,NCF_PREFETCH)) {
ncstat = prefetchdata3(dapcomm);
@ -317,18 +343,6 @@ fprintf(stderr,"ncdap3: final constraint: %s\n",dapcomm->oc.url->constraint);
}
}
#ifdef BUG
/* The libsrc code (NC_begins) assumes that
a created files is new and hence must have an
unlimited dimension of 0 initially, which will
wipe out the effect of the NC_set_numrecs in builddims.
There is no easy workaround, so we suppress the call
to nc_enddef
*/
ncstat = nc_enddef(drno->substrate);
if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
#endif
if(ncpp) *ncpp = (NC*)drno;
return ncstat;
@ -350,7 +364,10 @@ NCD3_close(int ncid)
if(ncstatus != NC_NOERR) return THROW(ncstatus);
dapcomm = (NCDAPCOMMON*)drno->dispatchdata;
ncstatus = nc_close(drno->substrate);
/* We call abort rather than close to avoid
trying to write anything or try to pad file length
*/
ncstatus = nc_abort(drno->substrate);
/* remove ourselves from NClist */
del_from_NCList(drno);
@ -429,9 +446,12 @@ builddims(NCDAPCOMMON* dapcomm)
ncstat = NC_check_id(drno->substrate,&ncsub);
if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}
#if 0
/* Set the effective size of UNLIMITED;
note that this cannot easily be done thru the normal API.*/
NC_set_numrecs(ncsub,unlimited->dim.declsize);
#endif
}
for(i=0;i<nclistlength(dimset);i++) {

View File

@ -38,6 +38,7 @@ freeNCDAPCOMMON(NCDAPCOMMON* dapcomm)
nclistfree(dapcomm->cdf.seqnodes);
nclistfree(dapcomm->cdf.gridnodes);
nclistfree(dapcomm->cdf.usertypes);
nclistfree(dapcomm->cdf.projectedvars);
nullfree(dapcomm->cdf.recorddimname);
/* free the trees */

View File

@ -33,16 +33,17 @@ static char* nctagname(int tag);
void
ncloginit(void)
{
const char* file = getenv(ENVFLAG);
ncinitlog = 1;
ncsetlogging(0);
nclogfile = NULL;
nclogstream = NULL;
/* Use environment variables to preset nclogging state*/
/* I hope this is portable*/
if(getenv(ENVFLAG) != NULL) {
const char* file = getenv(ENVFLAG);
ncsetlogging(1);
nclogopen(file);
if(file != NULL && strlen(file) > 0) {
if(nclogopen(file)) {
ncsetlogging(1);
}
}
nctagdfalt = NCTAGDFALT;
nctagset = nctagsetdfalt;
@ -55,7 +56,7 @@ ncsetlogging(int tf)
nclogging = tf;
}
void
int
nclogopen(const char* file)
{
if(!ncinitlog) ncloginit();
@ -89,9 +90,11 @@ nclogopen(const char* file)
nclogfile = NULL;
nclogstream = NULL;
ncsetlogging(0);
return 0;
}
ncsystemfile = 0;
}
return 1;
}
void

View File

@ -5,8 +5,8 @@ Copyright 2010 University Corporation for Atmospheric
Research/Unidata. See COPYRIGHT file for more info.
*/
#include <config.h>
#include <netcdf_f.h>
#include "config.h"
#include "netcdf_f.h"
#include "ncdispatch.h"
/* This function creates a file for use with parallel I/O. */

View File

@ -25,7 +25,7 @@ FOREACH(LIBS ${liblib_LIBS})
SET(LARGS ${LARGS} $<TARGET_OBJECTS:${LIBS}>)
ENDFOREACH()
ADD_LIBRARY(netcdf stub.c ${LARGS})
ADD_LIBRARY(netcdf stub.c ${LARGS} )
#####
# Add dependencies required for linking.
@ -43,3 +43,5 @@ IF(ENABLE_PNETCDF AND PNETCDF)
TARGET_LINK_LIBRARIES(netcdf ${PNETCDF})
ENDIF()
INSTALL(TARGETS netcdf DESTINATION lib)
#include(CPack)

View File

@ -208,10 +208,11 @@ memio_create(const char* path, int ioflags,
return status;
memio->size = 0;
if(!persist) {
memio->memory = (char*)malloc(memio->alloc);
if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;}
} else { /*persist */
/* malloc memory */
memio->memory = (char*)malloc(memio->alloc);
if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;}
if(persist) {
/* Open the file, but make sure we can write it if needed */
oflags = (persist ? O_RDWR : O_RDONLY);
#ifdef O_BINARY
@ -228,9 +229,6 @@ memio_create(const char* path, int ioflags,
if(fd < 0) {status = errno; goto unwind_open;}
(void)close(fd); /* will reopen at nc_close */
/* malloc memory */
memio->memory = (char*)malloc(memio->alloc);
if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;}
} /*!persist*/
#ifdef DEBUG
@ -259,6 +257,8 @@ fprintf(stderr,"memio_create: initial memory: %lu/%lu\n",(unsigned long)memio->m
return NC_NOERR;
unwind_open:
if(memio->memory != NULL)
free(memio->memory);
memio_close(nciop,1);
return status;
}
@ -484,11 +484,11 @@ memio_close(ncio* nciop, int doUnlink)
}
} else
status = errno;
/* Free up things */
if(memio->memory != NULL) free(memio->memory);
}
done:
if(memio->memory != NULL)
free(memio->memory);
/* do cleanup */
if(fd >= 0) (void)close(fd);
if(memio != NULL) free(memio);

View File

@ -1557,3 +1557,19 @@ nc_delete(const char * path)
return nc_delete_mp(path, 0);
}
int
NC_set_readonly(NC *ncp, int tf)
{
int old = 1;
if(ncp != NULL && ncp->nciop != NULL) {
old = NC_readonly(ncp) ? 1 : 0;
old = fIsSet(ncp->nciop->ioflags, NC_WRITE) ? 0 : 1;
if(tf == 1) {
fClr(ncp->nciop->ioflags, NC_WRITE);
} else {/*tf==0*/
fSet(ncp->nciop->ioflags, NC_WRITE);
}
}
return old;
}

View File

@ -286,7 +286,7 @@ nc4_create_file(const char *path, int cmode, MPI_Comm comm, MPI_Info info,
nc4_chunk_cache_size, nc4_chunk_cache_nelems, nc4_chunk_cache_preemption));
#endif /* USE_PARALLEL */
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_18, H5F_LIBVER_18) < 0)
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
BAIL(NC_EHDFERR);
/* Create the property list. */

View File

@ -110,8 +110,7 @@ chunkspec_parse(int ncid, const char *spec) {
}
chunkspecs.chunksizes[idim] = chunksize;
idim++;
if(dimname)
free(dimname);
free(dimname);
if(*cp == '\0')
break;
/* set np to point to first char after comma */

View File

@ -188,8 +188,6 @@ safebuf_t *
sbuf_new() {
size_t len = SAFEBUF_INIT_LEN;
safebuf_t *sb;
if (len == 0)
return 0;
sb = (safebuf_t *) emalloc(sizeof(safebuf_t));
sb->buf = (char *)emalloc(len + sizeof(int));
sb->len = len;

View File

@ -87,7 +87,7 @@ nc_inq_parid(int ncid, const char *fullname, int *locidp) {
NC_CHECK(NC_ENOMEM);
} else
last_slash = strrchr(parent, '/');
if(last_slash == parent) { /* parent is root */
if(last_slash == parent || last_slash == NULL) { /* parent is root */
free(parent);
parent = strdup(slash);
} else {

View File

@ -641,7 +641,7 @@ pr_att(
* Will include line breaks for longer lists. */
print_att_times(ncid, varid, att);
if(is_bounds_att(&att)) {
insert_bounds_info(ncid, varid, att);
insert_bounds_info(ncid, varid, &att);
}
}
#ifdef USE_NETCDF4
@ -860,7 +860,7 @@ pr_att_specials(
{
int endianness = 0;
NC_CHECK( nc_inq_var_endian(ncid, varid, &endianness) );
if(endianness != 0) {
if (endianness != NC_ENDIAN_NATIVE) { /* NC_ENDIAN_NATIVE is the default */
pr_att_name(ncid, varp->name, NC_ATT_ENDIANNESS);
printf(" = ");
switch (endianness) {
@ -870,9 +870,6 @@ pr_att_specials(
case NC_ENDIAN_BIG:
printf("\"big\"");
break;
case NC_ENDIAN_NATIVE:
printf("\"native\"");
break;
default:
error("pr_att_specials: bad endianness: %d", endianness);
break;

View File

@ -403,8 +403,7 @@ nc_free_iter(nciter_t *iterp) {
free(iterp->dimsizes);
if(iterp->chunksizes)
free(iterp->chunksizes);
if(iterp)
free(iterp);
free(iterp);
return NC_NOERR;
}

View File

@ -175,14 +175,14 @@ is_bounds_att(ncatt_t *attp) {
* later determine which variables are bounds variables for which
* other variables. att must be a variable "bounds" attribute. */
void
insert_bounds_info(int ncid, int varid, ncatt_t att) {
insert_bounds_info(int ncid, int varid, ncatt_t *attp) {
static boolean uninitialized = true;
if(uninitialized) {
bounds_list.nbnds = 0;
bounds_list.first = NULL;
}
assert(is_bounds_att(&att));
bounds_add(att.valgp, ncid, varid);
assert(is_bounds_att(attp));
bounds_add(attp->valgp, ncid, varid);
}
void

View File

@ -7,7 +7,7 @@
#include "nctime.h"
extern void insert_bounds_info(int ncid, int varid, ncatt_t att);
extern void insert_bounds_info(int ncid, int varid, ncatt_t *attp);
extern int is_valid_time_unit(const char *units);
extern int is_bounds_att(ncatt_t *attp);
extern void get_timeinfo(int ncid, int varid, ncvar_t *vp);

View File

@ -38,7 +38,7 @@
------------------------------------------------------------------------ */
#include <config.h>
#include "config.h"
#include "ConvertUTF.h"
#ifdef CVTUTF_DEBUG
#include <stdio.h>

View File

@ -1,7 +1,7 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include <config.h>
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

View File

@ -5,7 +5,7 @@
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* $Header: /upc/share/CVS/netcdf-3/ncgen/genlib.h,v 1.20 2010/05/17 23:26:45 dmh Exp $
*********************************************************************/
#include <config.h>
#include "config.h"
#include <stdlib.h>
#include <limits.h>
#include "generr.h"

View File

@ -5,7 +5,7 @@
/* $Id: list.c,v 1.3 2010/05/24 19:59:58 dmh Exp $ */
/* $Header: /upc/share/CVS/netcdf-3/ncgen/list.c,v 1.3 2010/05/24 19:59:58 dmh Exp $ */
#include <config.h>
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

View File

@ -4,7 +4,7 @@
* $Header: /upc/share/CVS/netcdf-3/ncgen3/genlib.c,v 1.54 2009/11/14 22:33:31 dmh Exp $
*********************************************************************/
#include <config.h>
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

View File

@ -4,7 +4,7 @@
* $Header: /upc/share/CVS/netcdf-3/ncgen3/main.c,v 1.20 2010/03/31 18:18:40 dmh Exp $
*********************************************************************/
#include <config.h>
#include "config.h"
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>

View File

@ -10,10 +10,10 @@
#ifdef sccs
static char SccsId[] = "$Id: ncgen.y,v 1.34 2010/03/31 18:18:41 dmh Exp $";
#endif
#include <config.h>
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <netcdf.h>
#include "netcdf.h"
#include "generic.h"
#include "ncgen.h"
#include "genlib.h" /* for grow_darray() et al */

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,8 @@
/* A Bison parser, made by GNU Bison 2.4.3. */
/* A Bison parser, made by GNU Bison 2.6.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2009, 2010 Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -31,6 +30,15 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef NCG_NCGEN_TAB_H
# define NCG_NCGEN_TAB_H
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int ncgdebug;
#endif
/* Tokens. */
#ifndef YYTOKENTYPE
@ -62,7 +70,6 @@
#endif
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
@ -72,4 +79,18 @@ typedef int YYSTYPE;
extern YYSTYPE ncglval;
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int ncgparse (void *YYPARSE_PARAM);
#else
int ncgparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int ncgparse (void);
#else
int ncgparse ();
#endif
#endif /* ! YYPARSE_PARAM */
#endif /* !NCG_NCGEN_TAB_H */

View File

@ -1,46 +0,0 @@
THISDIR=../oc
OCDIR=/home/dmh/svn/oc
all::
makeoc::
rm -f ${THISDIR}/*.[chy]
for f in ${OCDIR}/*.[chy] ; do \
base=`basename $$f` ; \
cat $$f | tr -d ' ' >${THISDIR}/$$base; \
done
rm -f ce.y ceparse.c celex.c ceparselex.h
rm -f octest.c config.h occompile.[ch]
rm -f ocdebug.h
sed -e 's|^[#]if 1|#if 0|g' \
< ${OCDIR}/ocdebug.h | tr -d '\r' >./ocdebug.h
# This should match the bison command in Makefile.am
rm -f dap.tab.c dap.tab.h
bison --debug -d -p dap dap.y
mv dap.tab.c daptab.c; mv dap.tab.h daptab.h
# # Temporary
# sed -e 's|dapdecode(parsestate->lexstate,|(|' \
# < ${OCDIR}/dap.y | tr -d '\r' >./dap.y
diffoc::
if ! test -e ${OCDIR} ; then echo "${OCDIR} not found"; exit ; fi
for f in ${OCDIR}/*.[chy] ; do \
x=`basename $$f | tr -d ' ' ` ; \
if test "x$${x}" = "xdaptab.c" -o "x$${x}" = "xdaptab.h" ; then echo "ignore: $${x}"; continue; fi ;\
if test -e ${THISDIR}/$$x -a -e ${OCDIR}/$$x ; then \
diff --brief -wBb ${THISDIR}/$$x $$f ; \
else \
echo "Only in ${OCDIR}: $$x"; \
fi; \
done
for f in ${OCDIR}/*.[chy] ; do \
x=`basename $$f|tr -d ' ' ` ; \
if test "x$${x}" = "xdaptab.c" -o "x$${x}" = "xdaptab.h" ; then echo "ignore: $${x}"; continue; fi ;\
if test -e ${THISDIR}/$$x -a -e ${OCDIR}/$$x ; then \
if ! diff --brief -wBb ${THISDIR}/$$x $$f > /dev/null ; then \
echo diff -wBb ${THISDIR}/$$x $$f ;\
diff -w ${THISDIR}/$$x $$f ; \
fi; \
fi; \
done

View File

@ -1,42 +0,0 @@
## This is a automake file, part of Unidata's netCDF package.
# Copyright 2005, see the COPYRIGHT file for more information.
# This automake file generates the Makefile to build netCDF-4. The
# generated makefile is not run unless the user selected to build
# netCDF-4.
# $Id: Makefile.am,v 1.1 2010/05/23 21:05:33 dmh Exp $
# Cause C preprocessor to search current and parent directory.
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include
# OC Sources; include the daptab.[ch] to avoid the need for bison by user
SRC= occurlfunctions.c dapparse.c daplex.c ocuri.c ochttp.c ocbytes.c \
oc.c occontent.c ocdebug.c ocdrno.c ocdump.c \
ocinternal.c oclist.c oclog.c ocnode.c ocutil.c occlientparams.c \
ocrc.c ocread.c xxdr.c daptab.c
HDRS= occurlfunctions.h occonstraints.h dapparselex.h ocuri.h ochttp.h \
ocbytes.h occontent.h ocdata.h ocdatatypes.h ocdebug.h ocdrno.h ocdump.h \
ocinternal.h oclist.h oclog.h ocnode.h occlientparams.h ocutil.h ocrc.h \
ocread.h xxdr.h daptab.h \
oc.h
if BUILD_DAP
noinst_LTLIBRARIES = liboc.la
liboc_la_SOURCES = $(SRC) $(HDRS)
liboc_la_CPPFLAGS = $(AM_CPPFLAGS)
endif
# These rule are used if someone wants to rebuild the grammar files.
# Otherwise never invoked, but records how to do it.
# BTW: note that renaming is essential because otherwise
# autoconf will forcibly delete files of the name *.tab.*
.PHONEY: bison
bison:: dap.y
rm -f dap.tab.c dap.tab.h
bison --debug -d -p dap dap.y
mv dap.tab.c daptab.c; mv dap.tab.h daptab.h

272
oc/dap.y
View File

@ -1,272 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
/*The lines down to DO NOT DELETE ... comment are specific to the C Parser.
They will be commennted out when building a java parser.
*/
%error-verbose
%pure-parser
%lex-param {DAPparsestate* parsestate}
%parse-param {DAPparsestate* parsestate}
%{
#include "config.h"
#include "dapparselex.h"
int dapdebug = 0;
%}
/*DO NOT DELETE THIS LINE*/
%token SCAN_ALIAS
%token SCAN_ARRAY
%token SCAN_ATTR
%token SCAN_BYTE
%token SCAN_CODE
%token SCAN_DATASET
%token SCAN_DATA
%token SCAN_ERROR
%token SCAN_FLOAT32
%token SCAN_FLOAT64
%token SCAN_GRID
%token SCAN_INT16
%token SCAN_INT32
%token SCAN_MAPS
%token SCAN_MESSAGE
%token SCAN_SEQUENCE
%token SCAN_STRING
%token SCAN_STRUCTURE
%token SCAN_UINT16
%token SCAN_UINT32
%token SCAN_URL
/* For errorbody */
%token SCAN_PTYPE
%token SCAN_PROG
/* Non-keywords */
%token WORD_WORD WORD_STRING
%start start
%%
start:
dataset datasetbody
| dataset datasetbody SCAN_DATA
| attr attributebody
| err errorbody
| error {dap_unrecognizedresponse(parsestate); YYABORT;}
;
dataset:
SCAN_DATASET
{dap_tagparse(parsestate,SCAN_DATASET);}
;
attr:
SCAN_ATTR
{dap_tagparse(parsestate,SCAN_ATTR);}
;
err:
SCAN_ERROR
{dap_tagparse(parsestate,SCAN_ERROR);}
;
datasetbody:
'{' declarations '}' datasetname ';'
{dap_datasetbody(parsestate,$4,$2);}
;
declarations:
/* empty */ {$$=dap_declarations(parsestate,null,null);}
| declarations declaration {$$=dap_declarations(parsestate,$1,$2);}
;
/* 01/21/08: James says: no dimensions for grids or sequences */
/* 05/08/09: James says: no duplicate map names */
declaration:
base_type var_name array_decls ';'
{$$=dap_makebase(parsestate,$2,$1,$3);}
| SCAN_STRUCTURE '{' declarations '}' var_name array_decls ';'
{if(($$=dap_makestructure(parsestate,$5,$6,$3))==null) {YYABORT;}}
| SCAN_SEQUENCE '{' declarations '}' var_name ';'
{if(($$=dap_makesequence(parsestate,$5,$3))==null) {YYABORT;}}
| SCAN_GRID '{' SCAN_ARRAY ':' declaration SCAN_MAPS ':'
declarations '}' var_name ';'
{if(($$=dap_makegrid(parsestate,$10,$5,$8))==null) {YYABORT;}}
| error
{daperror(parsestate,"Unrecognized type"); YYABORT;}
;
base_type:
SCAN_BYTE {$$=(Object)SCAN_BYTE;}
| SCAN_INT16 {$$=(Object)SCAN_INT16;}
| SCAN_UINT16 {$$=(Object)SCAN_UINT16;}
| SCAN_INT32 {$$=(Object)SCAN_INT32;}
| SCAN_UINT32 {$$=(Object)SCAN_UINT32;}
| SCAN_FLOAT32 {$$=(Object)SCAN_FLOAT32;}
| SCAN_FLOAT64 {$$=(Object)SCAN_FLOAT64;}
| SCAN_URL {$$=(Object)SCAN_URL;}
| SCAN_STRING {$$=(Object)SCAN_STRING;}
;
array_decls:
/* empty */ {$$=dap_arraydecls(parsestate,null,null);}
| array_decls array_decl {$$=dap_arraydecls(parsestate,$1,$2);}
;
array_decl:
'[' WORD_WORD ']' {$$=dap_arraydecl(parsestate,null,$2);}
| '[' '=' WORD_WORD ']' {$$=dap_arraydecl(parsestate,null,$3);}
| '[' name '=' WORD_WORD ']' {$$=dap_arraydecl(parsestate,$2,$4);}
| error
{daperror(parsestate,"Illegal dimension declaration"); YYABORT;}
;
datasetname:
var_name {$$=$1;}
| error
{daperror(parsestate,"Illegal dataset declaration"); YYABORT;}
;
var_name: name {$$=$1;};
attributebody:
'{' attr_list '}' {dap_attributebody(parsestate,$2);}
| error
{daperror(parsestate,"Illegal DAS body"); YYABORT;}
;
attr_list:
/* empty */ {$$=dap_attrlist(parsestate,null,null);}
| attr_list attribute {$$=dap_attrlist(parsestate,$1,$2);}
;
attribute:
alias ';' {$$=null;} /* ignored */
| SCAN_BYTE name bytes ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_BYTE);}
| SCAN_INT16 name int16 ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_INT16);}
| SCAN_UINT16 name uint16 ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_UINT16);}
| SCAN_INT32 name int32 ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_INT32);}
| SCAN_UINT32 name uint32 ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_UINT32);}
| SCAN_FLOAT32 name float32 ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_FLOAT32);}
| SCAN_FLOAT64 name float64 ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_FLOAT64);}
| SCAN_STRING name strs ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_STRING);}
| SCAN_URL name urls ';'
{$$=dap_attribute(parsestate,$2,$3,(Object)SCAN_URL);}
| name '{' attr_list '}' {$$=dap_attrset(parsestate,$1,$3);}
| error
{daperror(parsestate,"Illegal attribute"); YYABORT;}
;
bytes:
WORD_WORD {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_BYTE);}
| bytes ',' WORD_WORD
{$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_BYTE);}
;
int16:
WORD_WORD {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_INT16);}
| int16 ',' WORD_WORD
{$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_INT16);}
;
uint16:
WORD_WORD {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_UINT16);}
| uint16 ',' WORD_WORD
{$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_UINT16);}
;
int32:
WORD_WORD {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_INT32);}
| int32 ',' WORD_WORD
{$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_INT32);}
;
uint32:
WORD_WORD {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_UINT32);}
| uint32 ',' WORD_WORD {$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_UINT32);}
;
float32:
WORD_WORD {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_FLOAT32);}
| float32 ',' WORD_WORD {$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_FLOAT32);}
;
float64:
WORD_WORD {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_FLOAT64);}
| float64 ',' WORD_WORD {$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_FLOAT64);}
;
strs:
str_or_id {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_STRING);}
| strs ',' str_or_id {$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_STRING);}
;
urls:
url {$$=dap_attrvalue(parsestate,null,$1,(Object)SCAN_URL);}
| urls ',' url {$$=dap_attrvalue(parsestate,$1,$3,(Object)SCAN_URL);}
;
url:
name {$$=$1;}
;
str_or_id:
name {$$=$1;}
| WORD_STRING {$$=$1;}
;
/* Not used
float_or_int:
WORD_INT {$$=$1;}
| WORD_DOUBLE {$$=$1;}
;
*/
alias:
SCAN_ALIAS WORD_WORD WORD_WORD {$$=$2; $$=$3; $$=null;} /* Alias is ignored */
;
errorbody:
'{' errorcode errormsg errorptype errorprog '}' ';'
{dap_errorbody(parsestate,$2,$3,$4,$5);}
;
errorcode: /*empty*/ {$$=null;} | SCAN_CODE '=' WORD_WORD ';' {$$=$3;}
errormsg: /*empty*/ {$$=null;} | SCAN_MESSAGE '=' WORD_WORD ';' {$$=$3;}
errorptype: /*empty*/ {$$=null;} | SCAN_PTYPE '=' WORD_WORD ';' {$$=$3;}
errorprog : /*empty*/ {$$=null;} | SCAN_PROG '=' WORD_WORD ';' {$$=$3;}
/* Note that variable names like "byte" are legal names
and are disambiguated by context
*/
name:
WORD_WORD {$$=dapdecode(parsestate->lexstate,$1);}
| SCAN_ALIAS {$$=strdup("alias");}
| SCAN_ARRAY {$$=strdup("array");}
| SCAN_ATTR {$$=strdup("attributes");}
| SCAN_BYTE {$$=strdup("byte");}
| SCAN_DATASET {$$=strdup("dataset");}
| SCAN_DATA {$$=strdup("data");}
| SCAN_ERROR {$$=strdup("error");}
| SCAN_FLOAT32 {$$=strdup("float32");}
| SCAN_FLOAT64 {$$=strdup("float64");}
| SCAN_GRID {$$=strdup("grid");}
| SCAN_INT16 {$$=strdup("int16");}
| SCAN_INT32 {$$=strdup("int32");}
| SCAN_MAPS {$$=strdup("maps");}
| SCAN_SEQUENCE {$$=strdup("sequence");}
| SCAN_STRING {$$=strdup("string");}
| SCAN_STRUCTURE {$$=strdup("structure");}
| SCAN_UINT16 {$$=strdup("uint16");}
| SCAN_UINT32 {$$=strdup("uint32");}
| SCAN_URL {$$=strdup("url");}
| SCAN_CODE {$$=strdup("code");}
| SCAN_MESSAGE {$$=strdup("message");}
| SCAN_PROG {$$=strdup("program");}
| SCAN_PTYPE {$$=strdup("program_type");}
;
%%

View File

@ -1,350 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <strings.h>
#include "dapparselex.h"
#undef URLCVT /* NEVER turn this on */
#define DAP2ENCODE
/* Forward */
static void dumptoken(DAPlexstate* lexstate);
static void dapaddyytext(DAPlexstate* lex, int c);
#ifndef DAP2ENCODE
static int tohex(int c);
#endif
/****************************************************/
#if 0 /* Following definitions are for informational purposes */
/* Set of all ascii printable characters */
static char ascii[] = " !\"#$%&'()*+,-./:;<=>?@[]\\^_`|{}~";
/* Define the set of legal nonalphanum characters as specified in the DAP2 spec. */
static char* daplegal ="_!~*'-\"";
#endif
static char* ddsworddelims =
"{}[]:;=,";
/* Define 1 and > 1st legal characters */
static char* ddswordchars1 =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\.*";
static char* ddswordcharsn =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\.*#";
static char* daswordcharsn =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\.*#:";
static char* cewordchars1 =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
static char* cewordcharsn =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+_/%\\";
/* Current sets of legal characters */
/*
static char* wordchars1 = NULL;
static char* wordcharsn = NULL;
static char* worddelims = NULL;
*/
static char* keywords[] = {
"alias",
"array",
"attributes",
"byte",
"dataset",
"error",
"float32",
"float64",
"grid",
"int16",
"int32",
"maps",
"sequence",
"string",
"structure",
"uint16",
"uint32",
"url",
"code",
"message",
"program_type",
"program",
NULL /* mark end of the keywords list */
};
static int keytokens[] = {
SCAN_ALIAS,
SCAN_ARRAY,
SCAN_ATTR,
SCAN_BYTE,
SCAN_DATASET,
SCAN_ERROR,
SCAN_FLOAT32,
SCAN_FLOAT64,
SCAN_GRID,
SCAN_INT16,
SCAN_INT32,
SCAN_MAPS,
SCAN_SEQUENCE,
SCAN_STRING,
SCAN_STRUCTURE,
SCAN_UINT16,
SCAN_UINT32,
SCAN_URL,
SCAN_CODE,
SCAN_MESSAGE,
SCAN_PTYPE,
SCAN_PROG
};
/**************************************************/
int
daplex(YYSTYPE* lvalp, DAPparsestate* state)
{
DAPlexstate* lexstate = state->lexstate;
int token;
int c;
unsigned int i;
char* p;
char* tmp;
token = 0;
ocbytesclear(lexstate->yytext);
/* invariant: p always points to current char */
for(p=lexstate->next;token==0&&(c=*p);p++) {
if(c == '\n') {
lexstate->lineno++;
} else if(c <= ' ' || c == '\177') {
/* whitespace: ignore */
} else if(c == '#') {
/* single line comment */
while((c=*(++p))) {if(c == '\n') break;}
} else if(strchr(lexstate->worddelims,c) != NULL) {
/* don't put in lexstate->yytext to avoid memory leak */
token = c;
} else if(c == '"') {
int more = 1;
/* We have a string token; will be reported as WORD_STRING */
while(more && (c=*(++p))) {
#ifdef DAP2ENCODE
if(c == '"')
more = 0;
else if(c == '\\') {
/* Remove spec ambiguity by convering \c to c
for any character c */
c=*(++p);
if(c == '\0') more = 0;
}
#else /*Non-standard*/
switch (c) {
case '"': more=0; break;
case '\\':
c=*(++p);
switch (c) {
case 'r': c = '\r'; break;
case 'n': c = '\n'; break;
case 'f': c = '\f'; break;
case 't': c = '\t'; break;
case 'x': {
int d1,d2;
c = '?';
++p;
d1 = tohex(*p++);
if(d1 < 0) {
daperror(state,"Illegal \\xDD in TOKEN_STRING");
} else {
d2 = tohex(*p++);
if(d2 < 0) {
daperror(state,"Illegal \\xDD in TOKEN_STRING");
} else {
c=(((unsigned int)d1)<<4) | (unsigned int)d2;
}
}
} break;
default: break;
}
break;
default: break;
}
#endif /*!DAP2ENCODE*/
if(more) dapaddyytext(lexstate,c);
}
token=WORD_STRING;
} else if(strchr(lexstate->wordchars1,c) != NULL) {
int isdatamark = 0;
/* we have a WORD_WORD */
dapaddyytext(lexstate,c);
while((c=*(++p))) {
#ifdef URLCVT
if(c == '%' && p[1] != 0 && p[2] != 0
&& strchr(hexdigits,p[1]) != NULL
&& strchr(hexdigits,p[2]) != NULL) {
int d1,d2;
d1 = tohex(p[1]);
d2 = tohex(p[2]);
if(d1 >= 0 || d2 >= 0) {
c=(((unsigned int)d1)<<4) | (unsigned int)d2;
p+=2;
}
} else {
if(strchr(lexstate->wordcharsn,c) == NULL) {p--; break;}
}
dapaddyytext(lexstate,c);
#else
if(strchr(lexstate->wordcharsn,c) == NULL) {p--; break;}
dapaddyytext(lexstate,c);
#endif
}
/* Special check for Data: */
tmp = ocbytescontents(lexstate->yytext);
if(strcmp(tmp,"Data")==0 && *p == ':') {
dapaddyytext(lexstate,*p); p++;
if(p[0] == '\n') {
token = SCAN_DATA;
isdatamark = 1;
p++;
} else if(p[0] == '\r' && p[1] == '\n') {
token = SCAN_DATA;
isdatamark = 1;
p+=2;
}
}
if(!isdatamark) {
/* check for keyword */
token=WORD_WORD; /* assume */
for(i=0;;i++) {
if(keywords[i] == NULL) break;
if(strcasecmp(keywords[i],tmp)==0) {
token=keytokens[i];
break;
}
}
}
} else { /* illegal */
}
}
lexstate->next = p;
strncpy(lexstate->lasttokentext,ocbytescontents(lexstate->yytext),MAX_TOKEN_LENGTH);
lexstate->lasttoken = token;
if(ocdebug >= 2)
dumptoken(lexstate);
/*Put return value onto Bison stack*/
if(ocbyteslength(lexstate->yytext) == 0)
*lvalp = NULL;
else {
*lvalp = ocbytesdup(lexstate->yytext);
oclistpush(lexstate->reclaim,(ocelem)*lvalp);
}
return token; /* Return the type of the token. */
}
static void
dapaddyytext(DAPlexstate* lex, int c)
{
ocbytesappend(lex->yytext,(char)c);
}
#ifndef DAP2ENCODE
static int
tohex(int c)
{
if(c >= 'a' && c <= 'f') return (c - 'a') + 0xa;
if(c >= 'A' && c <= 'F') return (c - 'A') + 0xa;
if(c >= '0' && c <= '9') return (c - '0');
return -1;
}
#endif
static void
dumptoken(DAPlexstate* lexstate)
{
fprintf(stderr,"TOKEN = |%s|\n",ocbytescontents(lexstate->yytext));
}
/*
Simple lexer
*/
void
dapsetwordchars(DAPlexstate* lexstate, int kind)
{
switch (kind) {
case 0:
lexstate->worddelims = ddsworddelims;
lexstate->wordchars1 = ddswordchars1;
lexstate->wordcharsn = ddswordcharsn;
break;
case 1:
lexstate->worddelims = ddsworddelims;
lexstate->wordchars1 = ddswordchars1;
lexstate->wordcharsn = daswordcharsn;
break;
case 2:
lexstate->worddelims = ddsworddelims;
lexstate->wordchars1 = cewordchars1;
lexstate->wordcharsn = cewordcharsn;
break;
default: break;
}
}
void
daplexinit(char* input, DAPlexstate** lexstatep)
{
DAPlexstate* lexstate = (DAPlexstate*)malloc(sizeof(DAPlexstate));
if(lexstatep) *lexstatep = lexstate;
if(lexstate == NULL) return;
memset((void*)lexstate,0,sizeof(DAPlexstate));
lexstate->input = strdup(input);
lexstate->next = lexstate->input;
lexstate->yytext = ocbytesnew();
lexstate->reclaim = oclistnew();
dapsetwordchars(lexstate,0); /* Assume DDS */
}
void
daplexcleanup(DAPlexstate** lexstatep)
{
DAPlexstate* lexstate = *lexstatep;
if(lexstate == NULL) return;
if(lexstate->input != NULL) ocfree(lexstate->input);
if(lexstate->reclaim != NULL) {
while(oclistlength(lexstate->reclaim) > 0) {
char* word = (char*)oclistpop(lexstate->reclaim);
if(word) free(word);
}
oclistfree(lexstate->reclaim);
}
ocbytesfree(lexstate->yytext);
free(lexstate);
*lexstatep = NULL;
}
/* Dap identifiers will come to us with some
characters escaped using the URL notation of
%HH. The assumption here is that any character
that is encoded is left encoded, except as follows:
1. if the encoded character is in fact a legal DAP2 character
(alphanum+"_!~*'-\"") then it is decoded, otherwise not.
*/
#ifndef DECODE_IDENTIFIERS
static char* decodelist =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_!~*'-\"";
#endif
char*
dapdecode(DAPlexstate* lexstate, char* name)
{
char* decoded;
#ifdef DECODE_IDENTIFIERS
decoded = ocuridecode(name);
#else
decoded = ocuridecodeonly(name,decodelist);
#endif
oclistpush(lexstate->reclaim,(ocelem)decoded);
return decoded;
}

View File

@ -1,480 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include "dapparselex.h"
/* Forward */
static void addedges(OCnode* node);
static void setroot(OCnode*,OClist*);
static int isglobalname(char* name);
static OCnode* newocnode(char* name, OCtype octype, DAPparsestate* state);
static OCtype octypefor(Object etype);
static char* scopeduplicates(OClist* list);
static int check_int32(char* val, long* value);
/****************************************************/
/* Switch to DAS parsing SCAN_WORD definition */
/* Use the initial keyword to indicate what we are parsing */
void
dap_tagparse(DAPparsestate* state, int kind)
{
switch (kind) {
case SCAN_DATASET:
case SCAN_ERROR:
break;
case SCAN_ATTR:
dapsetwordchars(state->lexstate,1);
break;
default:
fprintf(stderr,"tagparse: Unknown tag argument: %d\n",kind);
}
}
Object
dap_datasetbody(DAPparsestate* state, Object name, Object decls)
{
OCnode* root = newocnode((char*)name,OC_Dataset,state);
root->subnodes = (OClist*)decls;
OCASSERT((state->root == NULL));
state->root = root;
state->root->root = state->root; /* make sure to cross link */
addedges(root);
setroot(root,state->ocnodes);
return NULL;
}
Object
dap_attributebody(DAPparsestate* state, Object attrlist)
{
OCnode* node = newocnode(NULL,OC_Attributeset,state);
OCASSERT((state->root == NULL));
state->root = node;
/* make sure to cross link */
state->root->root = state->root;
node->subnodes = (OClist*)attrlist;
addedges(node);
return NULL;
}
void
dap_errorbody(DAPparsestate* state,
Object code, Object msg, Object ptype, Object prog)
{
state->svcerror = 1;
state->code = nulldup((char*)code);
state->message = nulldup((char*)msg);
/* Ignore ptype and prog for now */
}
void
dap_unrecognizedresponse(DAPparsestate* state)
{
/* see if this is an HTTP error */
unsigned int httperr = 0;
int i;
char iv[32];
sscanf(state->lexstate->input,"%u ",&httperr);
sprintf(iv,"%u",httperr);
state->lexstate->next = state->lexstate->input;
/* Limit the amount of input to prevent runaway */
for(i=0;i<4096;i++) {if(state->lexstate->input[i] == '\0') break;}
state->lexstate->input[i] = '\0';
dap_errorbody(state,iv,state->lexstate->input,NULL,NULL);
}
Object
dap_declarations(DAPparsestate* state, Object decls, Object decl)
{
OClist* alist = (OClist*)decls;
if(alist == NULL)
alist = oclistnew();
else
oclistpush(alist,(ocelem)decl);
return alist;
}
Object
dap_arraydecls(DAPparsestate* state, Object arraydecls, Object arraydecl)
{
OClist* alist = (OClist*)arraydecls;
if(alist == NULL)
alist = oclistnew();
else
oclistpush(alist,(ocelem)arraydecl);
return alist;
}
Object
dap_arraydecl(DAPparsestate* state, Object name, Object size)
{
long value;
OCnode* dim;
if(!check_int32(size,&value))
dap_parse_error(state,"Dimension not an integer");
if(name != NULL)
dim = newocnode((char*)name,OC_Dimension,state);
else
dim = newocnode(NULL,OC_Dimension,state);
dim->dim.declsize = value;
return dim;
}
Object
dap_attrlist(DAPparsestate* state, Object attrlist, Object attrtuple)
{
OClist* alist = (OClist*)attrlist;
if(alist == NULL)
alist = oclistnew();
else {
char* dupname;
if(attrtuple != NULL) {/* NULL=>alias encountered, ignore */
oclistpush(alist,(ocelem)attrtuple);
if((dupname=scopeduplicates(alist))!=NULL) {
dap_parse_error(state,"Duplicate attribute names in same scope: %s",dupname);
/* Remove this attribute */
oclistpop(alist);
}
}
}
return alist;
}
Object
dap_attrvalue(DAPparsestate* state, Object valuelist, Object value, Object etype)
{
OClist* alist = (OClist*)valuelist;
if(alist == NULL) alist = oclistnew();
/* Watch out for null values */
if(value == NULL) value = "";
oclistpush(alist,(ocelem)strdup(value));
return alist;
}
Object
dap_attribute(DAPparsestate* state, Object name, Object values, Object etype)
{
OCnode* att;
att = newocnode((char*)name,OC_Attribute,state);
att->etype = octypefor(etype);
att->att.values = (OClist*)values;
return att;
}
Object
dap_attrset(DAPparsestate* state, Object name, Object attributes)
{
OCnode* attset;
attset = newocnode((char*)name,OC_Attributeset,state);
/* Check var set vs global set */
attset->att.isglobal = isglobalname(name);
attset->subnodes = (OClist*)attributes;
addedges(attset);
return attset;
}
static int
isglobalname(char* name)
{
int len = strlen(name);
int glen = strlen("global");
char* p;
if(len < glen) return 0;
p = name + (len - glen);
if(strcasecmp(p,"global") != 0)
return 0;
return 1;
}
#if 0
static int
isnumber(const char* text)
{
for(;*text;text++) {if(!isdigit(*text)) return 0;}
return 1;
}
#endif
static void
dimension(OCnode* node, OClist* dimensions)
{
unsigned int i;
unsigned int rank = oclistlength(dimensions);
node->array.dimensions = (OClist*)dimensions;
node->array.rank = rank;
for(i=0;i<rank;i++) {
OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
dim->dim.array = node;
dim->dim.arrayindex = i;
#if 0
if(dim->name == NULL) {
dim->dim.anonymous = 1;
dim->name = dimnameanon(node->name,i);
}
#endif
}
}
char*
dimnameanon(char* basename, unsigned int index)
{
char name[64];
sprintf(name,"%s_%d",basename,index);
return strdup(name);
}
Object
dap_makebase(DAPparsestate* state, Object name, Object etype, Object dimensions)
{
OCnode* node;
node = newocnode((char*)name,OC_Primitive,state);
node->etype = octypefor(etype);
dimension(node,(OClist*)dimensions);
return node;
}
Object
dap_makestructure(DAPparsestate* state, Object name, Object dimensions, Object fields)
{
OCnode* node;
char* dupname;
if((dupname=scopeduplicates((OClist*)fields))!= NULL) {
dap_parse_error(state,"Duplicate structure field names in same scope: %s.%s",(char*)name,dupname);
return (Object)NULL;
}
node = newocnode(name,OC_Structure,state);
node->subnodes = fields;
dimension(node,(OClist*)dimensions);
addedges(node);
return node;
}
Object
dap_makesequence(DAPparsestate* state, Object name, Object members)
{
OCnode* node;
char* dupname;
if((dupname=scopeduplicates((OClist*)members)) != NULL) {
dap_parse_error(state,"Duplicate sequence member names in same scope: %s.%s",(char*)name,dupname);
return (Object)NULL;
}
node = newocnode(name,OC_Sequence,state);
node->subnodes = members;
addedges(node);
return node;
}
Object
dap_makegrid(DAPparsestate* state, Object name, Object arraydecl, Object mapdecls)
{
OCnode* node;
/* Check for duplicate map names */
char* dupname;
if((dupname=scopeduplicates((OClist*)mapdecls)) != NULL) {
dap_parse_error(state,"Duplicate grid map names in same scope: %s.%s",(char*)name,dupname);
return (Object)NULL;
}
node = newocnode(name,OC_Grid,state);
node->subnodes = (OClist*)mapdecls;
oclistinsert(node->subnodes,0,(ocelem)arraydecl);
addedges(node);
return node;
}
static void
addedges(OCnode* node)
{
unsigned int i;
if(node->subnodes == NULL) return;
for(i=0;i<oclistlength(node->subnodes);i++) {
OCnode* subnode = (OCnode*)oclistget(node->subnodes,i);
subnode->container = node;
}
}
static void
setroot(OCnode* root, OClist* ocnodes)
{
int i;
for(i=0;i<oclistlength(ocnodes);i++) {
OCnode* node = (OCnode*)oclistget(ocnodes,i);
node->root = root;
}
}
int
daperror(DAPparsestate* state, const char* msg)
{
dap_parse_error(state,msg);
return 0;
}
static char*
flatten(char* s, char* tmp, int tlen)
{
int c;
char* p,*q;
strncpy(tmp,s,tlen);
tmp[tlen] = '\0';
p = (q = tmp);
while((c=*p++)) {
switch (c) {
case '\r': case '\n': break;
case '\t': *q++ = ' '; break;
case ' ': if(*p != ' ') *q++ = c; break;
default: *q++ = c;
}
}
*q = '\0';
return tmp;
}
/* Create an ocnode and capture in the state->ocnode list */
static OCnode*
newocnode(char* name, OCtype octype, DAPparsestate* state)
{
OCnode* node = ocmakenode(name,octype,state->root);
oclistpush(state->ocnodes,(ocelem)node);
return node;
}
static int
check_int32(char* val, long* value)
{
char* ptr;
int ok = 1;
long iv = strtol(val,&ptr,0); /* 0=>auto determine base */
if((iv == 0 && val == ptr) || *ptr != '\0') {ok=0; iv=1;}
else if(iv > OC_INT32_MAX || iv < OC_INT32_MIN) ok=0;
if(value != NULL) *value = iv;
return ok;
}
static char*
scopeduplicates(OClist* list)
{
unsigned int i,j;
for(i=0;i<oclistlength(list);i++) {
OCnode* io = (OCnode*)oclistget(list,i);
for(j=i+1;j<oclistlength(list);j++) {
OCnode* jo = (OCnode*)oclistget(list,j);
if(strcmp(io->name,jo->name)==0)
return io->name;
}
}
return NULL;
}
static OCtype
octypefor(Object etype)
{
switch ((long)etype) {
case SCAN_BYTE: return OC_Byte;
case SCAN_INT16: return OC_Int16;
case SCAN_UINT16: return OC_UInt16;
case SCAN_INT32: return OC_Int32;
case SCAN_UINT32: return OC_UInt32;
case SCAN_FLOAT32: return OC_Float32;
case SCAN_FLOAT64: return OC_Float64;
case SCAN_URL: return OC_URL;
case SCAN_STRING: return OC_String;
default: abort();
}
return OC_NAT;
}
void
dap_parse_error(DAPparsestate* state, const char *fmt, ...)
{
size_t len, suffixlen, prefixlen;
va_list argv;
char* tmp = NULL;
va_start(argv,fmt);
(void) vfprintf(stderr,fmt,argv) ;
(void) fputc('\n',stderr) ;
len = strlen(state->lexstate->input);
suffixlen = strlen(state->lexstate->next);
prefixlen = (len - suffixlen);
tmp = (char*)ocmalloc(len+1);
flatten(state->lexstate->input,tmp,prefixlen);
(void) fprintf(stderr,"context: %s",tmp);
flatten(state->lexstate->next,tmp,suffixlen);
(void) fprintf(stderr,"^%s\n",tmp);
(void) fflush(stderr); /* to ensure log files are current */
ocfree(tmp);
}
static void
dap_parse_cleanup(DAPparsestate* state)
{
daplexcleanup(&state->lexstate);
if(state->ocnodes != NULL) ocfreenodes(state->ocnodes);
state->ocnodes = NULL;
free(state);
}
static DAPparsestate*
dap_parse_init(char* buf)
{
DAPparsestate* state = (DAPparsestate*)ocmalloc(sizeof(DAPparsestate)); /*ocmalloc zeros*/
MEMCHECK(state,(DAPparsestate*)NULL);
if(buf==NULL) {
dap_parse_error(state,"dap_parse_init: no input buffer");
dap_parse_cleanup(state);
return NULL;
}
daplexinit(buf,&state->lexstate);
return state;
}
/* Wrapper for dapparse */
OCerror
DAPparse(OCstate* conn, OCtree* tree, char* parsestring)
{
DAPparsestate* state = dap_parse_init(parsestring);
int parseresult;
OCerror ocerr = OC_NOERR;
state->ocnodes = oclistnew();
state->conn = conn;
if(ocdebug >= 2)
dapdebug = 1;
parseresult = dapparse(state);
if(parseresult == 0) {/* 0 => parse ok */
/* Check to see if we ended up parsing an error message */
if(state->svcerror) {
conn->error.code = nulldup(state->code);
conn->error.message = nulldup(state->message);
tree->root = NULL;
/* Attempt to further decipher the error code */
if(state->code != NULL
&& (strcmp(state->code,"404") == 0 /* tds returns 404 */
|| strcmp(state->code,"5") == 0)) /* hyrax returns 5 */
ocerr = OC_ENOFILE;
else
ocerr = OC_EDAPSVC;
} else {
OCASSERT((state->root != NULL));
tree->root = state->root;
state->root = NULL; /* avoid reclaim */
tree->nodes = state->ocnodes;
state->ocnodes = NULL; /* avoid reclaim */
tree->root->tree = tree;
ocerr = OC_NOERR;
}
} else { /* Parse failed */
switch (tree->dxdclass) {
case OCDAS: ocerr = OC_EDAS; break;
case OCDDS: ocerr = OC_EDDS; break;
case OCDATADDS: ocerr = OC_EDATADDS; break;
default: ocerr = OC_EDAPSVC;
}
}
dap_parse_cleanup(state);
return ocerr;
}

View File

@ -1,95 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef DAPPARSELEX_H
#define DAPPARSELEX_H 1
#include "ocinternal.h"
#include "ocdebug.h"
#ifdef USE_DAP
/* To avoid "make distclean" wiping out dap.tab.h */
#include "daptab.h"
#else
#include "daptab.h"
#endif
#ifdef WIN32
#define strcasecmp stricmp
#define snprintf _snprintf
#endif
/* For consistency with Java parser */
#define null NULL
typedef void* Object;
#define YYSTYPE Object
#define MAX_TOKEN_LENGTH 1024
/*! Specifies the Lexstate. */
typedef struct DAPlexstate {
char* input;
char* next; /* next char in uri.query*/
OCbytes* yytext;
int lineno;
/*! Specifies the Lasttoken. */
int lasttoken;
char lasttokentext[MAX_TOKEN_LENGTH+1];
char* wordchars1;
char* wordcharsn;
char* worddelims;
OClist* reclaim; /* reclaim WORD_WORD instances */
} DAPlexstate;
/*! Specifies the DAPparsestate. */
typedef struct DAPparsestate {
struct OCnode* root;
DAPlexstate* lexstate;
OClist* ocnodes;
struct OCstate* conn;
/* For error returns from the server */
int svcerror; /* 1 => we had an error from the server */
char* code;
char* message;
char* progtype;
char* progname;
/* State for constraint expressions */
struct CEstate* cestate;
} DAPparsestate;
extern int daperror(DAPparsestate* state, const char* msg);
extern void dap_parse_error(DAPparsestate*,const char *fmt, ...);
/* bison parse entry point */
extern int dapparse(DAPparsestate*);
extern Object dap_datasetbody(DAPparsestate*,Object decls, Object name);
extern Object dap_declarations(DAPparsestate*,Object decls, Object decl);
extern Object dap_arraydecls(DAPparsestate*,Object arraydecls, Object arraydecl);
extern Object dap_arraydecl(DAPparsestate*,Object name, Object size);
extern void dap_dassetup(DAPparsestate*);
extern Object dap_attributebody(DAPparsestate*,Object attrlist);
extern Object dap_attrlist(DAPparsestate*,Object attrlist, Object attrtuple);
extern Object dap_attribute(DAPparsestate*,Object name, Object value, Object etype);
extern Object dap_attrset(DAPparsestate*,Object name, Object attributes);
extern Object dap_attrvalue(DAPparsestate*,Object valuelist, Object value, Object etype);
extern Object dap_makebase(DAPparsestate*,Object name, Object etype, Object dimensions);
extern Object dap_makestructure(DAPparsestate*,Object name, Object dimensions, Object fields);
extern Object dap_makesequence(DAPparsestate*,Object name, Object members);
extern Object dap_makegrid(DAPparsestate*,Object name, Object arraydecl, Object mapdecls);
extern void dap_errorbody(DAPparsestate*, Object, Object, Object, Object);
extern void dap_unrecognizedresponse(DAPparsestate*);
extern void dap_tagparse(DAPparsestate*,int);
/* Lexer entry points */
extern int daplex(YYSTYPE*, DAPparsestate*);
extern void daplexinit(char* input, DAPlexstate** lexstatep);
extern void daplexcleanup(DAPlexstate** lexstatep);
extern void dapsetwordchars(DAPlexstate* lexstate, int kind);
extern char* dapdecode(DAPlexstate*,char*);
#endif /*DAPPARSELEX_H*/

File diff suppressed because it is too large Load Diff

View File

@ -1,80 +0,0 @@
/* A Bison parser, made by GNU Bison 2.4.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2009, 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
SCAN_ALIAS = 258,
SCAN_ARRAY = 259,
SCAN_ATTR = 260,
SCAN_BYTE = 261,
SCAN_CODE = 262,
SCAN_DATASET = 263,
SCAN_DATA = 264,
SCAN_ERROR = 265,
SCAN_FLOAT32 = 266,
SCAN_FLOAT64 = 267,
SCAN_GRID = 268,
SCAN_INT16 = 269,
SCAN_INT32 = 270,
SCAN_MAPS = 271,
SCAN_MESSAGE = 272,
SCAN_SEQUENCE = 273,
SCAN_STRING = 274,
SCAN_STRUCTURE = 275,
SCAN_UINT16 = 276,
SCAN_UINT32 = 277,
SCAN_URL = 278,
SCAN_PTYPE = 279,
SCAN_PROG = 280,
WORD_WORD = 281,
WORD_STRING = 282
};
#endif
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif

View File

@ -1,16 +0,0 @@
CURL.VERBOSE=1
#CURL.DEFLATE=0
CURL.COOKIEJAR=.dods_cookies
#CURL.COOKIEFILE=
#CURL.CREDENTIALS.USER=
#CURL.CREDENTIALS.PASSWORD=
# SSL Support
CURL.SSL.VALIDATE=1
# For ESG access (e.g. http://ceda.ac.uk/...)
# CURL.SSL.CERTIFICATE and CURL.SSL.KEY should have same value
CURL.SSL.CERTIFICATE=/home/dmh/.globus/x509up_u13615
CURL.SSL.KEY=/home/dmh/.globus/x509up_u13615
#CURL.SSL.CAINFO=
CURL.SSL.CAPATH=/home/dmh/.globus/certificates
# Proxy configuration (optional parts in []s):
#CURL.PROXY_SERVER=http://[username:password@]host[:port]

957
oc/oc.c
View File

@ -1,957 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "oc.h"
#include "ocinternal.h"
#include "occontent.h"
#include "ocdebug.h"
#include "ocdump.h"
#include "oclog.h"
#include "occlientparams.h"
#include "ochttp.h"
#undef TRACK
/**************************************************/
static int ocinitialized = 0;
/**************************************************/
/* Track legal ids */
#ifdef OC_FASTCONSISTENCY
#define ocverify(object) ((object) != NULL && (*(object) == OCMAGIC)?1:0)
#define ocassign(object) ((OCobject)(object))
#define ocassignall(list)
#else /*!OC_FASTCONSISTENCY*/
static OClist* ocmap = NULL;
static int
ocverify(unsigned long object)
{
unsigned int i;
void** map = (void**)oclistcontents(ocmap);
unsigned int len = oclistlength(ocmap);
#ifdef TRACK
fprintf(stderr,"verify: %lu\n",object); fflush(stderr);
#endif
if(object > 0) {
for(i=0;i<len;i++,map++) {
if(*map == (void*)object) {
return 1;
}
}
}
fprintf(stderr,"illegal object id: %lu\n",(unsigned long)object);
fflush(stderr);
return 0;
}
static OCobject
ocassign(void* object)
{
#ifdef TRACK
fprintf(stderr,"assign: %lu\n",(unsigned long)object); fflush(stderr);
#endif
oclistpush(ocmap,(ocelem)object);
return (OCobject)object;
}
static void
ocassignall(OClist* list)
{
unsigned int i;
if(list != NULL)
for(i=0;i<oclistlength(list);i++) {
void* object = (void*)oclistget(list,i);
#ifdef TRACK
fprintf(stderr,"assign: %lu\n",(unsigned long)object); fflush(stderr);
#endif
oclistpush(ocmap,(ocelem)object);
}
}
#endif /*!OC_FASTCONSISTENCY*/
#define OCVERIFYX(T,s,x,r) if(!ocverify(x)) {return (r);}
#define OCVERIFY(T,s,x) OCVERIFYX(T,s,x,OC_EINVAL)
#define OCDEREF(T,s,x) (s)=(T)(x)
/**************************************************/
static int
oc_initialize(void)
{
int status = OC_NOERR;
#ifndef OC_FASTCONSISTENCY
ocmap = oclistnew();
oclistsetalloc(ocmap,1024);
#endif
status = ocinternalinitialize();
ocinitialized = 1;
return status;
}
/**************************************************/
OCerror
oc_open(const char* url, OCconnection* connp)
{
OCerror ocerr;
OCstate* state;
if(!ocinitialized) oc_initialize();
ocerr = ocopen(&state,url);
if(ocerr == OC_NOERR && connp) {
*connp = (OCconnection)ocassign(state);
}
return ocerr;
}
OCerror
oc_close(OCconnection conn)
{
OCstate* state;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
occlose(state);
return OC_NOERR;
}
/* Release/reclaim the tree of objects associated with a given root */
OCerror
oc_root_free(OCconnection conn, OCobject root0)
{
OCnode* root;
OCVERIFY(OCnode*,root,root0);
OCDEREF(OCnode*,root,root0);
ocfreeroot(root);
return OC_NOERR;
}
/* Return the # of OCobjects associated with a tree with specified root */
unsigned int
oc_inq_nobjects(OCconnection conn, OCobject root0)
{
OCnode* root;
OClist* nodes;
unsigned int nobjects;
OCVERIFYX(OCnode*,root,root0,-1);
OCDEREF(OCnode*,root,root0);
if(root == NULL) return 0;
root = root->root;
if(root == NULL) return 0;
nodes = root->tree->nodes;
nobjects = oclistlength(nodes);
return nobjects;
}
/* Return all the OCobjects associated with a tree with specified root */
OCobject*
oc_inq_objects(OCconnection conn, OCobject root0)
{
unsigned int i;
OCnode* root;
OClist* nodes;
OCobject* objects = NULL;
unsigned int nobjects;
OCVERIFYX(OCnode*,root,root0,OCNULL);
OCDEREF(OCnode*,root,root0);
if(root == NULL) return NULL;
root = root->root;
if(root == NULL) return NULL;
nodes = root->tree->nodes;
nobjects = oclistlength(nodes);
if(nodes != NULL && nobjects > 0) {
size_t len = sizeof(OCobject)*(1+nobjects);
objects = (OCobject*)ocmalloc(len);
for(i=0;i<oclistlength(nodes);i++) {
objects[i] = (OCobject)oclistget(nodes,i);
}
objects[nobjects] = OCNULL; /* null terminate */
}
return objects;
}
/* Return the text of the DDS or DAS as received from the server */
/* Return NULL if no fetch was ever made. */
const char*
oc_inq_text(OCconnection conn, OCobject root0)
{
OCnode* root;
OCVERIFYX(OCnode*,root,root0,NULL);
OCDEREF(OCnode*,root,root0);
if(root == NULL) return NULL;
root = root->root;
if(root == NULL) return NULL;
return root->tree->text;
}
OCerror
oc_inq_object(OCconnection conn,
OCobject node0,
char** namep,
OCtype* objecttypep,
OCtype* primitivetypep, /* if objecttype == OC_Primitive */
OCobject* containerp,
unsigned int* rankp,
unsigned int* subnodesp,
unsigned int* nattrp)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(namep) *namep = nulldup(node->name);
if(objecttypep) *objecttypep = node->octype;
if(primitivetypep) *primitivetypep = node->etype;
if(rankp) *rankp = node->array.rank;
if(containerp) *containerp = (OCobject)node->container;
if(subnodesp) *subnodesp = oclistlength(node->subnodes);
if(nattrp) {
if(node->octype == OC_Attribute) {
*nattrp = oclistlength(node->att.values);
} else {
*nattrp = oclistlength(node->attributes);
}
}
return OC_NOERR;
}
/* Useful accessor functions */
OCerror
oc_inq_name(OCconnection conn, OCobject node0, char** namep)
{
OCstate* state;
OCnode* node;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(state == NULL || node == NULL) return OC_EINVAL;
if(namep) *namep = nulldup(node->name);
return OC_NOERR;
}
OCerror
oc_inq_nsubnodes(OCconnection conn, OCobject node0, unsigned int* nsubnodesp)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(nsubnodesp) *nsubnodesp = oclistlength(node->subnodes);
return OC_NOERR;
}
OCerror
oc_inq_primtype(OCconnection conn, OCobject node0, OCtype* typep)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(typep) *typep = node->etype;
return OC_NOERR;
}
/* Alias for oc_inq_class */
OCerror
oc_inq_type(OCconnection conn, OCobject node0, OCtype* typep)
{
return oc_inq_class(conn,node0,typep);
}
OCerror
oc_inq_class(OCconnection conn, OCobject node0, OCtype* typep)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(typep) *typep = node->octype;
return OC_NOERR;
}
OCerror
oc_inq_rank(OCconnection conn, OCobject node0, unsigned int* rankp)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(rankp) *rankp = node->array.rank;
return OC_NOERR;
}
OCerror
oc_inq_nattr(OCconnection conn, OCobject node0, unsigned int* nattrp)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(nattrp) {
if(node->octype == OC_Attribute) {
*nattrp = oclistlength(node->att.values);
} else {
*nattrp = oclistlength(node->attributes);
}
}
return OC_NOERR;
}
OCerror
oc_inq_root(OCconnection conn, OCobject node0, OCobject* rootp)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(rootp) *rootp = (OCobject)node->root;
return OC_NOERR;
}
OCerror
oc_inq_container(OCconnection conn, OCobject node0, OCobject* containerp)
{
OCnode* node;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(containerp) *containerp = (OCobject)node->container;
return OC_NOERR;
}
/* Return the subnode objects, if any, for a given object */
/* Caller must free returned list */
OCerror
oc_inq_subnodes(OCconnection conn, OCobject node0, OCobject** subnodesp)
{
OCnode* node;
OCobject* subnodes = NULL;
unsigned int len;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
len = oclistlength(node->subnodes);
if(len > 0) {
unsigned int i;
subnodes = (OCobject*)occalloc(sizeof(OCobject),len+1);
for(i=0;i<len;i++) {
OCnode* ocnode = (OCnode*)oclistget(node->subnodes,i);
subnodes[i] = (OCobject)ocnode;
}
subnodes[len] = OCNULL; /* NULL terminate */
}
if(subnodesp) *subnodesp = subnodes;
return OC_NOERR;
}
OCerror
oc_inq_ith(OCconnection conn,
OCobject node0, unsigned int index, OCobject* subnodeidp)
{
OCnode* node;
OCobject subnodeid = OCNULL;
unsigned int nsubnodes;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
nsubnodes = oclistlength(node->subnodes);
if(nsubnodes > 0 && index < nsubnodes) {
subnodeid = (OCobject)oclistget(node->subnodes,index);
} else
return OC_EINVAL;
if(subnodeidp) *subnodeidp = subnodeid;
return OC_NOERR;
}
/* Return the dimension objects, if any, for a given object */
/* Caller must free returned dimids */
OCerror
oc_inq_dimset(OCconnection conn, OCobject node0, OCobject** dimids)
{
OCnode* node;
OCobject* dims = NULL;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(node->array.rank > 0) {
unsigned int i;
dims = (OCobject*)occalloc(sizeof(OCobject),node->array.rank+1);
for(i=0;i<node->array.rank;i++) {
OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
dims[i] = (OCobject)dim;
}
dims[node->array.rank] = OCNULL;
}
if(dimids) *dimids = dims;
return OC_NOERR;
}
OCerror
oc_inq_ithdim(OCconnection conn, OCobject node0, unsigned int index, OCobject* dimidp)
{
OCnode* node;
OCobject dimid = OCNULL;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
if(node->array.rank > 0 && index < node->array.rank) {
dimid = (OCobject)oclistget(node->array.dimensions,index);
} else
return OC_EINVAL;
if(dimidp) *dimidp = dimid;
return OC_NOERR;
}
OCerror
oc_inq_dim(OCconnection conn, OCobject node0, size_t* sizep, char** namep)
{
OCnode* dim;
OCVERIFY(OCnode*,dim,node0);
OCDEREF(OCnode*,dim,node0);
if(dim->octype != OC_Dimension) return OC_EINVAL;
if(sizep) *sizep = dim->dim.declsize;
if(namep) *namep = nulldup(dim->name);
return OC_NOERR;
}
/* Obtain info about the ith attribute attached to a given DDS node*/
/* This procedure returns the value as the original DAS string */
OCerror
oc_inq_attrstrings(OCconnection conn, OCobject node0, unsigned int i,
char** namep, OCtype* octypep,
unsigned int* nvaluesp, char*** stringsp)
{
OCnode* node;
OCattribute* attr;
unsigned int nattrs;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
nattrs = oclistlength(node->attributes);
if(i >= nattrs) return OC_EINVAL;
attr = (OCattribute*)oclistget(node->attributes,i);
if(namep) *namep = strdup(attr->name);
if(octypep) *octypep = attr->etype;
if(nvaluesp) *nvaluesp = attr->nvalues;
if(stringsp) {
if(attr->nvalues > 0) {
size_t space = attr->nvalues * sizeof(char*);
char** strings = ocmalloc(space);
for(i=0;i<attr->nvalues;i++)
strings[i] = nulldup(attr->values[i]);
*stringsp = strings;
} else
*stringsp = NULL;
}
return OC_NOERR;
}
/* This procedure returns the value as the default binary value
corresponding to the string value
*/
OCerror
oc_inq_attr(OCconnection conn, OCobject node0, unsigned int i,
char** namep, OCtype* octypep, unsigned int* nvaluesp, void** valuesp)
{
OCnode* node;
OCattribute* attr;
unsigned int nattrs;
OCVERIFY(OCnode*,node,node0);
OCDEREF(OCnode*,node,node0);
nattrs = oclistlength(node->attributes);
if(i >= nattrs) return OC_EINVAL;
attr = (OCattribute*)oclistget(node->attributes,i);
if(namep) *namep = strdup(attr->name);
if(octypep) *octypep = attr->etype;
if(nvaluesp) *nvaluesp = attr->nvalues;
if(valuesp && attr->nvalues > 0) {
void* memory = NULL;
memory = oclinearize(attr->etype,attr->nvalues,attr->values);
*valuesp = memory;
}
return OC_NOERR;
}
/* Convenience function */
void
oc_attr_reclaim(OCtype etype, unsigned int nvalues, void* values)
{
if(nvalues == 0 || values == NULL) return;
if(etype == OC_String || etype == OC_URL) {
unsigned int i;
char** strings = (char**)values;
for(i=0;i<nvalues;i++) {ocfree(strings[i]);}
}
ocfree(values);
}
OCerror
oc_inq_dasattr_nvalues(OCconnection conn, OCobject node0,
unsigned int* nvaluesp)
{
OCnode* attr;
OCVERIFY(OCnode*,attr,node0);
OCDEREF(OCnode*,attr,node0);
if(attr->octype != OC_Attribute) return OC_EINVAL;
if(nvaluesp) *nvaluesp = oclistlength(attr->att.values);
return OC_NOERR;
}
OCerror
oc_inq_dasattr(OCconnection conn, OCobject node0, unsigned int i,
OCtype* primtypep, char** valuep)
{
OCnode* attr;
unsigned int nvalues;
OCVERIFY(OCnode*,attr,node0);
OCDEREF(OCnode*,attr,node0);
if(attr->octype != OC_Attribute) return OC_EINVAL;
nvalues = oclistlength(attr->att.values);
if(i >= nvalues) return OC_EINVAL;
if(valuep) *valuep = nulldup((char*)oclistget(attr->att.values,i));
if(primtypep) *primtypep = attr->etype;
return OC_NOERR;
}
/**************************************************/
/* Fetch and parse a given class of DXD the server specified
at open time, and using a specified set of constraints.
Return the root node of the parsed tree of objects.
*/
OCerror oc_fetch(OCconnection conn, const char* constraint,
OCdxd dxdkind, OCobject* rootp)
{
return oc_fetchf(conn,constraint,dxdkind,0,rootp);
}
OCerror oc_fetchf(OCconnection conn, const char* constraint,
OCdxd dxdkind, OCflags flags, OCobject* rootp)
{
OCstate* state;
OCerror ocerr = OC_NOERR;
OCnode* root;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
ocerr = ocfetchf(state,constraint,dxdkind,flags,&root);
if(ocerr) return ocerr;
ocassignall(root->tree->nodes);
if(rootp) *rootp = (OCobject)ocassign(root);
return ocerr;
}
OCerror
oc_data_root(OCconnection conn, OCobject root0, OCdata content0)
{
OCstate* state;
OCnode* root;
OCcontent* content;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCnode*,root,root0);
OCDEREF(OCnode*,root,root0);
OCVERIFY(OCcontent*,content,content0);
OCDEREF(OCcontent*,content,content0);
if(root->tree == NULL) {OCTHROWCHK((ocerr=OC_EINVAL)); goto fail;}
ocerr = ocrootdata(state,root,content);
fail:
return ocerr;
}
OCdata
oc_data_new(OCconnection conn)
{
OCstate* state;
OCVERIFYX(OCstate*,state,conn,OCNULL);
OCDEREF(OCstate*,state,conn);
return (OCdata)ocassign(ocnewcontent(state));
}
OCerror
oc_data_free(OCconnection conn, OCdata content0)
{
OCstate* state;
OCcontent* content;
if(content0 == OCNULL) return OC_NOERR;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCcontent*,content,content0);
OCDEREF(OCcontent*,content,content0);
ocfreecontent(state,content);
return OC_NOERR;
}
OCerror
oc_data_ith(OCconnection conn, OCdata parentdata, size_t index, OCdata subdata)
{
OCstate* state;
OCcontent* parent;
OCcontent* child;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCcontent*,parent,parentdata);
OCDEREF(OCcontent*,parent,parentdata);
OCVERIFY(OCcontent*,child,subdata);
OCDEREF(OCcontent*,child,subdata);
ocerr = ocdataith(state,parent,index,child);
return ocerr;
}
OCerror
oc_data_get(OCconnection conn, OCdata currentcontent,
void* memory, size_t memsize, size_t start, size_t count)
{
OCstate* state;
OCcontent* current;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCcontent*,current,currentcontent);
OCDEREF(OCcontent*,current,currentcontent);
ocerr = ocgetcontent(state,current,memory,memsize,start,count);
if(ocerr == OC_EDATADDS) ocdataddsmsg(state,current->tree);
return ocerr;
}
OCerror
oc_data_count(OCconnection conn, OCdata content0, size_t* sizep)
{
OCstate* state;
OCcontent* current;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCcontent*,current,content0);
OCDEREF(OCcontent*,current,content0);
ocerr = ocdatacount(state, current, sizep);
return ocerr;
}
OCerror
oc_data_index(OCconnection conn, OCdata content0, size_t* sizep)
{
OCcontent* current;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCcontent*,current,content0);
OCDEREF(OCcontent*,current,content0);
if(sizep)
*sizep = (current->cache.valid ? current->cache.index : 0);
return ocerr;
}
OCerror
oc_data_object(OCconnection conn, OCdata content0, OCobject* op)
{
OCcontent* current;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCcontent*,current,content0);
OCDEREF(OCcontent*,current,content0);
if(op) *op = (OCobject)current->node;
return ocerr;
}
OCerror
oc_data_mode(OCconnection conn, OCdata content0, OCmode* modep)
{
OCcontent* current;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCcontent*,current,content0);
OCDEREF(OCcontent*,current,content0);
if(modep) *modep = current->mode;
return ocerr;
}
/**************************************************/
/* OCtype management */
size_t oc_typesize(OCtype etype)
{
return octypesize(etype);
}
const char*
oc_typetostring(OCtype octype)
{
return octypetoddsstring(octype);
}
OCerror
oc_typeprint(OCtype etype, char* buf, size_t bufsize, void* value)
{
return octypeprint(etype,buf,bufsize,value);
}
/**************************************************/
/* The oc_logXXX procedures are define in oclog.c */
/**************************************************/
/* Miscellaneous */
const char*
oc_errstring(int err)
{
return ocerrstring(err);
}
/* Get clientparameters from the URL */
const char*
oc_clientparam_get(OCconnection conn, const char* param)
{
OCstate* state;
OCVERIFYX(OCstate*,state,conn,NULL);
OCDEREF(OCstate*,state,conn);
return ocparamlookup(state,param);
}
#ifdef OCIGNORE
/* Delete client parameter
return value:
OC_NOERR => defined; deletion performed
OC_EINVAL => not already defined
*/
OCerror
oc_clientparam_delete(OCconnection conn, const char* param)
{
OCstate* state;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
return ocparamdelete(state->clientparams,param);
}
/* Insert client parameter
return value:
OC_NOERR => not already define; insertion performed
OC_EINVAL => already defined
*/
OCerror
oc_clientparam_insert(OCconnection conn, const char* param, const char* value)
{
OCstate* state;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
state->clientparams = dapparaminsert(state->clientparams,param,value);
return OC_NOERR;
}
/* Replace client parameter
return value:
OC_NOERR => already define; replacement performed
OC_EINVAL => not already defined
*/
OCerror
oc_clientparam_replace(OCconnection conn, const char* param, const char* value)
{
OCstate* state;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
return dapparamreplace(state->clientparams,param,value);
}
#endif
OCerror
oc_dd(OCconnection conn, OCobject root0, int level)
{
OCstate* state;
OCnode* root;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCnode*,root,root0);
OCDEREF(OCnode*,root,root0);
ocdd(state,root,1,level);
return OC_NOERR;
}
OCerror
oc_ddnode(OCconnection conn, OCobject root0)
{
OCnode* root;
OCVERIFY(OCnode*,root,root0);
OCDEREF(OCnode*,root,root0);
ocdumpnode(root);
return OC_NOERR;
}
/* Merge a specified DAS into a specified DDS or DATADDS */
OCerror
oc_attach_das(OCconnection conn, OCobject dasroot, OCobject ddsroot)
{
OCstate* state;
OCnode* das;
OCnode* dds;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCnode*,das,dasroot);
OCDEREF(OCnode*,das,dasroot);
OCVERIFY(OCnode*,dds,ddsroot);
OCDEREF(OCnode*,dds,ddsroot);
return ocddsdasmerge(state,das,dds);
}
#if 0
/*
I suppressed this operation because I realized that it
appears to be impossible to implement correctly in general.
It also exposes a flaw in the protocol.
If I have a dds with two identical Grids, G1 and G2,
and I ask for the projection ?G1.temp,G2.temp,
then I get back a DATADDS with duplicated temp fields,
which means the DATADDS is illegal. The problem is that
the protocol throws away important scoping information
about the fact that each temp field is part of a different
grid.
*/
/* Connect a specified DATADDS tree to a specified DDS tree */
OCerror
oc_attach_datadds(OCconnection conn, OCobject dataddsroot, OCobject ddsroot)
{
OCstate* state;
OCnode* dxd;
OCnode* dds;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCnode*,dxd,dataddsroot);
OCDEREF(OCnode*,dxd,dataddsroot);
OCVERIFY(OCnode*,dds,ddsroot);
OCDEREF(OCnode*,dds,ddsroot);
/* get the true roots */
dds = dds->root;
dxd = dxd->root;
if(dds == NULL || dxd == NULL) return OC_EBADID;
/* correlate the DATADDS to the DDS */
return occorrelate(dxd,dds);
}
/* Return the attached DATADDS object for a given DDS object */
OCerror oc_inq_datadds(OCconnection conn, OCobject dds0, OCobject* dataddsp)
{
OCstate* state;
OCnode* dds;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
OCVERIFY(OCnode*,dds,dds0);
OCDEREF(OCnode*,dds,dds0);
if(dataddsp) *dataddsp = (OCobject)dds->datadds;
return OC_NOERR;
}
#endif
/**************************************************/
OCerror
oc_svcerrordata(OCconnection conn, char** codep,
char** msgp, long* httpp)
{
OCstate* state;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
return ocsvcerrordata(state,codep,msgp,httpp);
}
/**************************************************/
/* Experimental: this is useful for the netcdf
DRNO project.
*/
/* New 10/31/2009: return the size (in bytes)
of the fetched datadds.
*/
OCerror
oc_raw_xdrsize(OCconnection conn, OCobject root0, size_t* sizep)
{
OCnode* root;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCnode*,root,root0);
OCDEREF(OCnode*,root,root0);
if(sizep == NULL) goto done;
if(root->tree == NULL || root->tree->dxdclass != OCDATADDS)
{OCTHROWCHK((ocerr=OC_EINVAL)); goto done;}
if(sizep) *sizep = root->tree->data.datasize;
done:
return ocerr;
}
/* Resend a url as a head request to check the Last-Modified time */
OCerror
oc_update_lastmodified_data(OCconnection conn)
{
OCstate* state;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
return ocupdatelastmodifieddata(state);
}
long
oc_get_lastmodified_data(OCconnection conn)
{
OCstate* state;
OCVERIFY(OCstate*,state,conn);
OCDEREF(OCstate*,state,conn);
return state->datalastmodified;
}
int
oc_dumpnode(OCconnection conn, OCobject root0)
{
OCnode* root;
OCerror ocerr = OC_NOERR;
OCVERIFY(OCnode*,root,root0);
OCDEREF(OCnode*,root,root0);
ocdumpnode(root);
return ocerr;
}
OCerror
oc_ping(const char* url)
{
return ocping(url);
}

443
oc/oc.h
View File

@ -1,443 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT dap for more information. */
/*
Draft OC External Interface
Created: 4/4/2009
Last Revised: 4/14/2009
*/
#ifndef OC_H
#define OC_H
#include <stdlib.h>
#include <stdio.h>
/* if defined, use magic numbers for consistency]) */
#define OC_FASTCONSISTENCY
/* OC_MAX_DIMS should be greater or equal to max allowed by dap or netcdf*/
#define OC_MAX_DIMS 1024
/* Specifies the OCtype.*/
/* Primitives = Duplicate of the NODE_Byte..Node_URL union nc_type*/
typedef unsigned long OCtype;
/* Note: use #define rather than enum so we can extend if needed
more easily */
/* Primitives*/
/* OC_Ubyte, OC_Char, OC_Int64 and OC_UInt64 are defined for future extension*/
#define OC_NAT ((OCtype)0)
#define OC_Char ((OCtype)1)
#define OC_Byte ((OCtype)2)
#define OC_UByte ((OCtype)3)
#define OC_Int16 ((OCtype)4)
#define OC_UInt16 ((OCtype)5)
#define OC_Int32 ((OCtype)6)
#define OC_UInt32 ((OCtype)7)
#define OC_Int64 ((OCtype)8)
#define OC_UInt64 ((OCtype)9)
#define OC_Float32 ((OCtype)10)
#define OC_Float64 ((OCtype)11)
#define OC_String ((OCtype)12)
#define OC_URL ((OCtype)13)
/* Non-primitives*/
#define OC_Dataset ((OCtype)100)
#define OC_Sequence ((OCtype)101)
#define OC_Grid ((OCtype)102)
#define OC_Structure ((OCtype)103)
#define OC_Dimension ((OCtype)104)
#define OC_Attribute ((OCtype)105)
#define OC_Attributeset ((OCtype)106)
#define OC_Primitive ((OCtype)107)
#define OC_Group ((OCtype)108)
#define OC_Type ((OCtype)109)
/* Define a set of error
positive are system errors
(needs work)
*/
typedef int OCerror;
#define OC_NOERR (0)
#define OC_EBADID (-1)
#define OC_ECHAR (-2)
#define OC_EDIMSIZE (-3)
#define OC_EEDGE (-4)
#define OC_EINVAL (-5)
#define OC_EINVALCOORDS (-6)
#define OC_ENOMEM (-7)
#define OC_ENOTVAR (-8)
#define OC_EPERM (-9)
#define OC_ESTRIDE (-10)
#define OC_EDAP (-11)
#define OC_EXDR (-12)
#define OC_ECURL (-13)
#define OC_EBADURL (-14)
#define OC_EBADVAR (-15)
#define OC_EOPEN (-16)
#define OC_EIO (-17)
#define OC_ENODATA (-18)
#define OC_EDAPSVC (-19)
#define OC_ENAMEINUSE (-20)
#define OC_EDAS (-21)
#define OC_EDDS (-22)
#define OC_EDATADDS (-23)
#define OC_ERCFILE (-24)
#define OC_ENOFILE (-25)
/* Define the classes of DAP DXD objects */
typedef int OCdxd;
#define OCDDS 0
#define OCDAS 1
#define OCDATADDS 2
#define OCDATA OCDATADDS
/* Define flags */
typedef int OCflags;
#define OCONDISK 1
typedef enum OCmode {
OCNULLMODE = 0,
OCFIELDMODE = 1,
OCSEQUENCEMODE = 2,
OCARRAYMODE = 3,
OCPRIMITIVEMODE = 4,
OCEMPTYMODE = 0x8000000 /* internal use only */
} OCmode;
/* Define an unsigned alternative to off(64)_t*/
typedef unsigned long long ocoffset_t;
/* Define a wrapper for dimension sizes */
typedef size_t ocindex_t;
/* Define the effective API */
#ifndef OCINTERNAL_H
/* The OCobject type references a component of a DAS or DDS
(e.g. Sequence, Grid, Dataset, etc). These objects
are nested, so most objects reference a container object
and subnode objects.
*/
#ifdef OC_FASTCONSISTENCY
/* Use unsigned int * so we can dereference to get magic number */
typedef unsigned int* OCobject;
#define OCNULL NULL
#else
typedef unsigned long OCobject;
#define OCNULL ((OCobject)0)
#endif
/* These are the two critical types*/
/* Think of OClink as analogous to the C stdio FILE structure;
it "holds" all the other state info about
a connection to the server, the url request, and the DAS/DDS/DATADDSinfo.
*/
/* Renamed from OCconnection because of confusion about term "connection"
3/24/2010 by dmh
*/
typedef OCobject OClink;
/* Keep old name for back compatibility */
typedef OClink OCconnection; /*Deprecated*/
/* Tag kind of log entry*/
#define OCLOGNOTE 0
#define OCLOGWARN 1
#define OCLOGERR 2
#define OCLOGDBG 3
/**************************************************/
#ifdef __cplusplus
extern "C" {
#endif
extern int oc_dumpnode(OClink conn, OCobject root0);
/**************************************************/
/* Link management */
extern OCerror oc_open(const char* url, OClink*);
extern OCerror oc_close(OClink);
/**************************************************/
/* Root management */
/* Fetch and parse a given class of DXD the server specified
at open time, and using a specified set of constraints
and flags.
Return the root node of the parsed tree of objects.
*/
extern OCerror oc_fetchf(OClink,
const char* constraints,
OCdxd,
OCflags,
OCobject* rootp);
/*
Equivalent to oc_fetchf with zero flag parameter
*/
extern OCerror oc_fetch(OClink,
const char* constraints,
OCdxd,
OCobject* rootp);
/* Release/reclaim the tree of objects associated with a given root */
extern OCerror oc_root_free(OClink, OCobject root);
/* Return the # of OCobjects associated with a tree with specified root */
extern unsigned int oc_inq_nobjects(OClink, OCobject root);
/* Return all the OCobjects associated with a tree with specified root */
extern OCobject* oc_inq_objects(OClink, OCobject root);
/* Return the text of the DDS or DAS as received from the server */
extern const char* oc_inq_text(OClink, OCobject root);
/**************************************************/
/* Object Management */
/* Any of the pointers may be NULL in the following procedure call;
If the object is of type Dataset, then return # of global attributes
If the object is of type Attribute, then return the # of values in nattrp.
The caller must free the resulting name string.
*/
extern OCerror oc_inq_object(OClink, OCobject,
char** namep,
OCtype* typep,
OCtype* primitivetypep, /* if objecttype == OC_Primitive */
OCobject* parentp,
unsigned int* rankp,
unsigned int* nsubnodesp,
unsigned int* nattrp);
/* Also define some more individual accessors */
extern OCerror oc_inq_name(OClink,OCobject,char**);
extern OCerror oc_inq_class(OClink,OCobject,OCtype*);
extern OCerror oc_inq_type(OClink,OCobject,OCtype*); /*alias for oc_inq_class*/
extern OCerror oc_inq_primtype(OClink,OCobject,OCtype*);
extern OCerror oc_inq_nsubnodes(OClink,OCobject,unsigned int*);
extern OCerror oc_inq_rank(OClink,OCobject,unsigned int*);
extern OCerror oc_inq_nattr(OClink,OCobject,unsigned int*);
extern OCerror oc_inq_root(OClink,OCobject,OCobject*);
extern OCerror oc_inq_container(OClink,OCobject,OCobject*);
/* Return the subnode objects, if any, associated with a given object.
Caller must free the returned subnodes memory.
*/
extern OCerror oc_inq_subnodes(OClink,OCobject,OCobject** subnodes);
/* Return the i'th subnode object, if any, associated with a given object */
/* If there is none such, then return OC_EINVAL */
extern OCerror oc_inq_ith(OClink,OCobject, unsigned int, OCobject*);
/* Return the dimension objects, if any, associated with a given object */
/* Caller must free returned vector for dimids */
/* If there are no dimensions (i.e. rank == 0), then return NULL */
extern OCerror oc_inq_dimset(OClink,OCobject, OCobject** dimids);
/* Return the i'th dim object, if any, associated with a given object */
/* If there is no such dim, then return OC_EINVAL */
extern OCerror oc_inq_ithdim(OClink,OCobject, unsigned int, OCobject*);
/* Return the size and name associated with a given dimension object
as defined in the DDS
*/
extern OCerror oc_inq_dim(OClink,OCobject,ocindex_t*,char**);
/* Attribute Management */
/* Added: 11/2/2009 DMH:
Provide access to DDS node attributes
in the form of the original underlying
DAS string.
One specifies the DDS root to get the global attributes.
Caller must free returned strings.
*/
extern OCerror oc_inq_attrstrings(OClink,OCobject, unsigned int i,
char** name, OCtype* octype,
unsigned int* nvalues,char*** stringvalues);
/* Obtain the attributes associated with a given DDS OCobject.
One specifies the DDS root to get the global attributes
This code takes the DAS strings and does a default
conversion to binary values.
*/
extern OCerror oc_inq_attr(OClink,OCobject, unsigned int i,
char** name,OCtype* octype,
unsigned int* nvalues,void** values);
/* Convenience function to simplify reclaiming the allocated attribute
value memory
*/
extern void oc_attr_reclaim(OCtype, unsigned int nvalues, void* values);
/* Access ith value string of a DAS object.
OCtype of the object is assumed to be OC_Attribute.
Note that this is different than the above inq_attr
and inq_attrstrings, which work on DDS
objects. Note also that the return value is always a string.
Caller must free returned string.
*/
extern OCerror oc_inq_dasattr_nvalues(OClink, OCobject,
unsigned int* nvaluesp);
extern OCerror oc_inq_dasattr(OClink,OCobject, unsigned int,
OCtype* primtypep, char** valuep);
/**************************************************/
/* Data management */
/*
These procedures allow for the location and extraction
of data from the data packet part of a DATADDS.
See ocuserman.html for detailed description.
*/
typedef OCobject OCdata;
/* Obtain the OCdata object that references the
whole data from a DATADDS fetch request specified
by the root object. This does not access the server.
*/
extern OCerror oc_data_root(OClink, OCobject root, OCdata);
/* Create an empty OCdata object */
extern OCdata oc_data_new(OClink);
/* Reclaim a no longer needed OCdata object */
extern OCerror oc_data_free(OClink, OCdata);
/* Given an OCdata object, set the nested subnode OCdata object
to refer to the data associated with the i'th element of
the parent data object. NOTE: if the i'th element is not
present then this function will return OC_ENODATA.
See the user's manual for details on mapping multi-
dimensional arrays to single indices.
*/
extern OCerror oc_data_ith(OClink,
OCdata parentdata,
ocindex_t index,
OCdata subdata);
/* Return the actual data values associated with the specified OCdata.
The OCdata is assumed to be referencing either a scalar
primitive value or a (1d) array of primitive values.
If scalar, then index must be 0 and count must be 1.
*/
extern OCerror oc_data_get(OClink,OCdata,
void* memory, size_t memsize,
ocindex_t index, ocindex_t count);
/* Return the OCdata's current index */
extern OCerror oc_data_index(OClink,OCdata, ocindex_t*);
/* Return the mode associated the specified OCdata object */
extern OCerror oc_data_mode(OClink,OCdata, OCmode*);
/* Return the OCobject associated the specified OCdata object */
extern OCerror oc_data_object(OClink,OCdata, OCobject*);
/* Compute the the count associated with the specified OCdata
instance. Note: this is potentially computationally costly
when computing # records.
*/
extern OCerror oc_data_count(OClink, OCdata, ocindex_t*);
/**************************************************/
/* Misc. OCtype-related functions */
/* Return size of the given type (Primitive only) */
extern size_t oc_typesize(OCtype);
/* Return a canonical printable string describing a given type:
e.g. Byte, Int16, etc.
*/
extern const char* oc_typetostring(OCtype);
/* Given a value of a primitive OC type, provide a canonical
string representing that value
*/
extern OCerror oc_typeprint(OCtype, char* buf, size_t bufsize, void* value);
/**************************************************/
/* Logging */
extern void oc_loginit(void);
extern void oc_setlogging(int onoff); /* 1=>start logging 0=>stop */
extern void oc_logopen(const char* logfilename);
extern void oc_logclose(void);
extern void oc_logtext(int tag, const char* text);
extern void oc_log(int tag, const char* fmt, ...);
/**************************************************/
/* Miscellaneous */
/* Convert an OCerror to a human readable string */
extern const char* oc_errstring(int err);
/* Get client parameters from the URL
DO NOT free the result
*/
extern const char* oc_clientparam_get(OClink, const char* param);
extern OCerror oc_clientparam_delete(OClink, const char* param);
extern OCerror oc_clientparam_insert(OClink, const char* param, const char* value);
extern OCerror oc_clientparam_replace(OClink, const char* param, const char* value);
/**************************************************/
/* Merging operations */
/* Merge a specified DAS into a specified DDS or DATADDS */
extern OCerror oc_attach_das(OClink, OCobject dasroot, OCobject ddsroot);
/**************************************************/
/* Debugging */
extern OCerror oc_dd(OClink,OCobject,int level);
extern OCerror oc_ddnode(OClink,OCobject);
/* When a server error is detected, then it is possible
to get the server error info using this procedure */
extern OCerror oc_svcerrordata(OClink link, char** codep,
char** msgp, long* httpp);
/**************************************************/
/* Experimental */
/* New 10/31/2009: return raw information about a datadds
*/
extern OCerror oc_raw_xdrsize(OClink, OCobject, size_t*);
/* Resend a url as a head request to check the Last-Modified time */
extern OCerror oc_update_lastmodified_data(OClink);
/* Get last known modification time; -1 => data unknown */
extern long oc_get_lastmodified_data(OClink);
extern OCerror oc_ping(const char* url);
/**************************************************/
#endif /*OCINTERNAL_H*/
#ifdef __cplusplus
}
#endif
#endif /*OC_H*/

View File

@ -1,190 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ocbytes.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define DEFAULTALLOC 1024
#define ALLOCINCR 1024
static int ocbytesdebug = 1;
static long
ocbytesfail(void)
{
fflush(stdout);
fprintf(stderr,"bytebuffer failure\n");
fflush(stderr);
if(ocbytesdebug) abort();
return FALSE;
}
OCbytes*
ocbytesnew(void)
{
OCbytes* bb = (OCbytes*)malloc(sizeof(OCbytes));
if(bb == NULL) return (OCbytes*)ocbytesfail();
bb->alloc=0;
bb->length=0;
bb->content=NULL;
bb->nonextendible = 0;
return bb;
}
int
ocbytessetalloc(OCbytes* bb, unsigned int sz)
{
char* newcontent;
if(bb == NULL) return ocbytesfail();
if(sz <= 0) {sz = (bb->alloc?2*bb->alloc:DEFAULTALLOC);}
if(bb->alloc >= sz) return TRUE;
if(bb->nonextendible) return ocbytesfail();
newcontent=(char*)calloc(sz,sizeof(char));
if(newcontent == NULL) return FALSE;
if(bb->alloc > 0 && bb->length > 0 && bb->content != NULL) {
memcpy((void*)newcontent,(void*)bb->content,sizeof(char)*bb->length);
}
if(bb->content != NULL) free(bb->content);
bb->content=newcontent;
bb->alloc=sz;
return TRUE;
}
void
ocbytesfree(OCbytes* bb)
{
if(bb == NULL) return;
if(!bb->nonextendible && bb->content != NULL) free(bb->content);
free(bb);
}
int
ocbytessetlength(OCbytes* bb, unsigned int sz)
{
if(bb == NULL) return ocbytesfail();
if(sz > bb->alloc) {if(!ocbytessetalloc(bb,sz)) return ocbytesfail();}
bb->length = sz;
return TRUE;
}
int
ocbytesfill(OCbytes* bb, char fill)
{
unsigned int i;
if(bb == NULL) return ocbytesfail();
for(i=0;i<bb->length;i++) bb->content[i] = fill;
return TRUE;
}
int
ocbytesget(OCbytes* bb, unsigned int index)
{
if(bb == NULL) return -1;
if(index >= bb->length) return -1;
return bb->content[index];
}
int
ocbytesset(OCbytes* bb, unsigned int index, char elem)
{
if(bb == NULL) return ocbytesfail();
if(index >= bb->length) return ocbytesfail();
bb->content[index] = elem;
return TRUE;
}
int
ocbytesappend(OCbytes* bb, char elem)
{
if(bb == NULL) return ocbytesfail();
/* We need space for the char + null */
while(bb->length+1 >= bb->alloc) {
if(!ocbytessetalloc(bb,0)) return ocbytesfail();
}
bb->content[bb->length] = elem;
bb->length++;
bb->content[bb->length] = '\0';
return TRUE;
}
/* This assumes s is a null terminated string*/
int
ocbytescat(OCbytes* bb, char* s)
{
ocbytesappendn(bb,(void*)s,strlen(s)+1); /* include trailing null*/
/* back up over the trailing null*/
if(bb->length == 0) return ocbytesfail();
bb->length--;
return 1;
}
int
ocbytesappendn(OCbytes* bb, void* elem, unsigned int n)
{
if(bb == NULL || elem == NULL) return ocbytesfail();
if(n == 0) {n = strlen((char*)elem);}
while(!ocbytesavail(bb,n+1)) {
if(!ocbytessetalloc(bb,0)) return ocbytesfail();
}
memcpy((void*)&bb->content[bb->length],(void*)elem,n);
bb->length += n;
bb->content[bb->length] = '\0';
return TRUE;
}
int
ocbytesprepend(OCbytes* bb, char elem)
{
int i; /* do not make unsigned */
if(bb == NULL) return ocbytesfail();
if(bb->length >= bb->alloc) if(!ocbytessetalloc(bb,0)) return ocbytesfail();
/* could we trust memcpy? instead */
for(i=bb->alloc;i>=1;i--) {bb->content[i]=bb->content[i-1];}
bb->content[0] = elem;
bb->length++;
return TRUE;
}
char*
ocbytesdup(OCbytes* bb)
{
char* result = (char*)malloc(bb->length+1);
memcpy((void*)result,(const void*)bb->content,bb->length);
result[bb->length] = '\0'; /* just in case it is a string*/
return result;
}
char*
ocbytesextract(OCbytes* bb)
{
char* result = bb->content;
bb->alloc = 0;
bb->length = 0;
bb->content = NULL;
return result;
}
int
ocbytessetcontents(OCbytes* bb, char* contents, unsigned int alloc)
{
if(bb == NULL) return ocbytesfail();
ocbytesclear(bb);
if(!bb->nonextendible && bb->content != NULL) free(bb->content);
bb->content = contents;
bb->length = 0;
bb->alloc = alloc;
bb->nonextendible = 1;
return 1;
}

View File

@ -1,54 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCBYTES_H
#define OCBYTES_H 1
typedef struct OCbytes {
int nonextendible; /* 1 => fail if an attempt is made to extend this buffer*/
unsigned int alloc;
unsigned int length;
char* content;
} OCbytes;
#if defined(_CPLUSPLUS_) || defined(__CPLUSPLUS__) || defined(__CPLUSPLUS)
#define EXTERNC extern "C"
#else
#define EXTERNC extern
#endif
EXTERNC OCbytes* ocbytesnew(void);
EXTERNC void ocbytesfree(OCbytes*);
EXTERNC int ocbytessetalloc(OCbytes*,unsigned int);
EXTERNC int ocbytessetlength(OCbytes*,unsigned int);
EXTERNC int ocbytesfill(OCbytes*, char fill);
/* Produce a duplicate of the contents*/
EXTERNC char* ocbytesdup(OCbytes*);
/* Extract the contents and leave buffer empty */
EXTERNC char* ocbytesextract(OCbytes*);
/* Return the ith byte; -1 if no such index */
EXTERNC int ocbytesget(OCbytes*,unsigned int);
/* Set the ith byte */
EXTERNC int ocbytesset(OCbytes*,unsigned int,char);
/* Append one byte */
EXTERNC int ocbytesappend(OCbytes*,char); /* Add at Tail */
/* Append n bytes */
EXTERNC int ocbytesappendn(OCbytes*,void*,unsigned int); /* Add at Tail */
/* Concatenate a null-terminated string to the end of the buffer */
EXTERNC int ocbytescat(OCbytes*,char*);
/* Set the contents of the buffer; mark the buffer as non-extendible */
EXTERNC int ocbytessetcontents(OCbytes*, char*, unsigned int);
/* Following are always "in-lined"*/
#define ocbyteslength(bb) ((bb)?(bb)->length:0U)
#define ocbytesalloc(bb) ((bb)?(bb)->alloc:0U)
#define ocbytescontents(bb) ((bb && bb->content)?(bb)->content:(char*)"")
#define ocbytesextend(bb,len) ocbytessetalloc((bb),(len)+(bb->alloc))
#define ocbytesclear(bb) ((bb)?(bb)->length=0:0U)
#define ocbytesavail(bb,n) ((bb)?((bb)->alloc - (bb)->length) >= (n):0U)
#endif /*OCBYTES_H*/

View File

@ -1,128 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include "ocinternal.h"
#include "ocdebug.h"
#define LBRACKET '['
#define RBRACKET ']'
/*
Client parameters are assumed to be
one or more instances of bracketed pairs:
e.g "[...][...]...".
The bracket content in turn is assumed to be a
comma separated list of <name>=<value> pairs.
e.g. x=y,z=,a=b.
If the same parameter is specifed more than once,
then the first occurrence is used; this is so that
is possible to forcibly override user specified
parameters by prefixing.
IMPORTANT: client parameter string is assumed to
have blanks compress out.
*/
int
ocparamdecode(OCstate* state)
{
int i;
i = ocuridecodeparams(state->uri);
return i?OC_NOERR:OC_EBADURL;
}
const char*
ocparamlookup(OCstate* state, const char* key)
{
if(state == NULL || key == NULL || state->uri == NULL) return NULL;
return ocurilookup(state->uri,key);
}
int
ocparamset(OCstate* state, const char* params)
{
int i;
i = ocurisetparams(state->uri,params);
return i?OC_NOERR:OC_EBADURL;
}
#ifdef OCIGNORE
void
ocparamfree(OClist* params)
{
int i;
if(params == NULL) return;
for(i=0;i<oclistlength(params);i++) {
char* s = (char*)oclistget(params,i);
if(s != NULL) free((void*)s);
}
oclistfree(params);
}
/*
Delete the entry.
return value = 1 => found and deleted;
0 => param not found
*/
int
ocparamdelete(OClist* params, const char* clientparam)
{
int i,found = 0;
if(params == NULL || clientparam == NULL) return 0;
for(i=0;i<oclistlength(params);i+=2) {
char* name = (char*)oclistget(params,i);
if(strcmp(clientparam,name)==0) {found=1; break;}
}
if(found) {
oclistremove(params,i+1); /* remove value */
oclistremove(params,i); /* remove name */
}
return found;
}
/*
Insert new client param (name,value);
return value = 1 => not already defined
0 => param already defined (no change)
*/
int
ocparaminsert(OClist* params, const char* clientparam, const char* value)
{
int i;
if(params == NULL || clientparam == NULL) return 0;
for(i=0;i<oclistlength(params);i+=2) {
char* name = (char*)oclistget(params,i);
if(strcmp(clientparam,name)==0) return 0;
}
/* not found, append */
oclistpush(params,(ocelem)nulldup(clientparam));
oclistpush(params,(ocelem)nulldup(value));
return 1;
}
/*
Replace new client param (name,value);
return value = 1 => replacement performed
0 => insertion performed
*/
int
ocparamreplace(OClist* params, const char* clientparam, const char* value)
{
int i;
if(params == NULL || clientparam == NULL) return 0;
for(i=0;i<oclistlength(params);i+=2) {
char* name = (char*)oclistget(params,i);
if(strcmp(clientparam,name)==0) {
oclistinsert(params,i+1,(ocelem)nulldup(value));
return 1;
}
}
ocparaminsert(params,clientparam,value);
return 0;
}
#endif

View File

@ -1,11 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCCLIENTPARAMS_H
#define OCCLIENTPARAMS_H
extern OClist* ocparamdecode(OCstate*);
extern const char* ocparamlookup(OCstate*, const char*);
extern void ocparamset(OCstate*,const char*);
#endif /*OCCLIENTPARAMS_H*/

View File

@ -1,39 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef CONSTRAINTS_H
#define CONSTRAINTS_H 1
/*! Specifies an OCslice. */
typedef struct OCslice {
size_t first;
size_t count;
size_t stride;
size_t stop; /* == first + count */
size_t declsize; /* from defining dimension, if any.*/
} OCslice;
/*! Specifies a form of path where each element can have a set of associated indices */
typedef struct OCpath {
OClist* names;
OClist* indexsets; /* oclist<oclist<Slice>> */
} OCpath;
/*! Specifies a ProjectionClause. */
typedef struct OCprojectionclause {
char* target; /* "variable name" as mentioned in the projection */
OClist* indexsets; /* oclist<oclist<OCslice>> */
struct OCnode* node; /* node with name matching target, if any. */
int gridconstraint; /* used only for testing purposes */
} OCprojectionclause;
/*! Selection is the node type for selection expression trees */
typedef struct OCselectionclause {
int op;
char* value;
struct OCselectionclause* lhs;
OClist* rhs;
} OCselectionclause;
#endif /*CONSTRAINTS_H*/

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCCONTENT_H
#define OCCONTENT_H
/*! Specifies the OCcontent*/
typedef struct OCcontent {
unsigned int magic;
OCmode mode;
struct OCstate* state;
struct OCnode* node;
struct OCtree* tree;
int packed; /* track OC_Char and OC_Byte specially*/
struct OCCACHE {
int valid;
ocindex_t index; /* index corresponding to offset */
ocindex_t maxindex; /* max allowable index, if known0 => max unknown */
ocoffset_t offset; /* location of this content in the xdr data */
} cache; /* track last xdr position and index of this content */
struct OCcontent* next;
} OCcontent;
extern OCcontent* ocnewcontent(OCstate* state);
extern void ocfreecontent(OCstate* state, OCcontent* content);
extern OCmode ocgetmode(OCcontent* content);
extern int ocdataith(struct OCstate*, OCcontent*, size_t, OCcontent*);
extern int ocdatacount(struct OCstate*, OCcontent*, size_t*);
extern int ocrootdata(struct OCstate*, struct OCnode*, struct OCcontent*);
extern int ocgetcontent(struct OCstate*, struct OCcontent*, void* memory,
size_t memsize, size_t start, size_t count);
#endif /*OCCONTENT_H*/

View File

@ -1,206 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include "ocinternal.h"
#include "ocdebug.h"
#include "ocdata.h"
#include "occontent.h"
#include "ocrc.h"
/* Condition on libcurl version */
/* Set up an alias as needed */
#ifndef HAVE_CURLOPT_KEYPASSWD
#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD
#endif
static char* combinecredentials(const char* user, const char* pwd);
/* Set various general curl flags */
int
ocset_curl_flags(OCstate* state)
{
CURLcode cstat = CURLE_OK;
CURL* curl = state->curl;
struct OCcurlflags* flags = &state->curlflags;
#ifdef CURLOPT_ENCODING
if (flags->compress) {
cstat = curl_easy_setopt(curl, CURLOPT_ENCODING,"deflate, gzip");
if(cstat != CURLE_OK) goto done;
OCDBG(1,"CURLOPT_ENCODING=deflate, gzip");
}
#endif
if (flags->cookiejar || flags->cookiefile) {
cstat = curl_easy_setopt(curl, CURLOPT_COOKIESESSION, 1);
if (cstat != CURLE_OK) goto done;
OCDBG(1,"CURLOPT_COOKIESESSION=1");
}
if (flags->cookiejar) {
cstat = curl_easy_setopt(curl, CURLOPT_COOKIEJAR, flags->cookiejar);
if (cstat != CURLE_OK) goto done;
OCDBG1(1,"CURLOPT_COOKIEJAR=%s",flags->cookiejar);
}
if (flags->cookiefile) {
cstat = curl_easy_setopt(curl, CURLOPT_COOKIEFILE, flags->cookiefile);
if (cstat != CURLE_OK) goto done;
OCDBG1(1,"CURLOPT_COOKIEFILE=%s",flags->cookiefile);
}
if (flags->verbose) {
cstat = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
if (cstat != CURLE_OK) goto done;
OCDBG1(1,"CURLOPT_VERBOSE=%ld",1L);
}
if (flags->timeout) {
cstat = curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)flags->timeout);
if (cstat != CURLE_OK) goto done;
OCDBG1(1,"CURLOPT_TIMEOUT=%ld",1L);
}
/* Following are always set */
cstat = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
OCDBG1(1,"CURLOPT_FOLLOWLOCATION=%ld",1L);
cstat = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10L);
OCDBG1(1,"CURLOPT_FOLLOWLOCATION=%ld",1L);
cstat = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, state->error.curlerrorbuf);
OCDBG1(1,"CURLOPT_ERRORBUFFER",0);
done:
return cstat;
}
int
ocset_proxy(OCstate* state)
{
CURLcode cstat;
CURL* curl = state->curl;
struct OCproxy *proxy = &state->proxy;
struct OCcredentials *creds = &state->creds;
cstat = curl_easy_setopt(curl, CURLOPT_PROXY, proxy->host);
if (cstat != CURLE_OK) return OC_ECURL;
OCDBG1(1,"CURLOPT_PROXY=%s",proxy->host);
cstat = curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxy->port);
if (cstat != CURLE_OK) return OC_ECURL;
OCDBG1(1,"CURLOPT_PROXYPORT=%d",proxy->port);
if (creds->username) {
char *combined = combinecredentials(creds->username,creds->password);
if (!combined) return OC_ENOMEM;
cstat = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, combined);
if (cstat != CURLE_OK) return OC_ECURL;
OCDBG1(1,"CURLOPT_PROXYUSERPWD=%s",combined);
#ifdef CURLOPT_PROXYAUTH
cstat = curl_easy_setopt(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
if(cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_PROXYAUTH=%ld",(long)CURLAUTH_ANY);
#endif
free(combined);
}
return OC_NOERR;
}
int
ocset_ssl(OCstate* state)
{
CURLcode cstat = CURLE_OK;
CURL* curl = state->curl;
struct OCSSL* ssl = &state->ssl;
long verify = (ssl->validate?1L:0L);
cstat=curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, verify);
if (cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_SSL_VERIFYPEER=%ld",verify);
cstat=curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (verify?2L:0L));
if (cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_SSL_VERIFYHOST=%ld",(verify?2L:0L));
#ifdef OCIGNORE
if(verify)
#endif
{
if(ssl->certificate) {
cstat = curl_easy_setopt(curl, CURLOPT_SSLCERT, ssl->certificate);
if(cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_SSLCERT=%s",ssl->certificate);
}
if(ssl->key) {
cstat = curl_easy_setopt(curl, CURLOPT_SSLKEY, ssl->key);
if(cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_SSLKEY=%s",ssl->key);
}
if(ssl->keypasswd) {
/* libcurl prior to 7.16.4 used 'CURLOPT_SSLKEYPASSWD' */
cstat = curl_easy_setopt(curl, CURLOPT_KEYPASSWD, ssl->keypasswd);
if(cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_SSLKEY=%s",ssl->key);
}
if(ssl->cainfo) {
cstat = curl_easy_setopt(curl, CURLOPT_CAINFO, ssl->cainfo);
if(cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_CAINFO=%s",ssl->cainfo);
}
if(ssl->capath) {
cstat = curl_easy_setopt(curl, CURLOPT_CAPATH, ssl->capath);
if(cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_CAPATH=%s",ssl->capath);
}
{
cstat = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, ssl->verifypeer);
if(cstat != CURLE_OK) goto fail;
OCDBG1(1,"CURLOPT_SSL_VERIFYPEER=%d",ssl->verifypeer);
}
}
return OC_NOERR;
fail:
return OC_ECURL;
}
/* This is called with arguments while the other functions in this file are
* used with global values read from the.dodsrc file. The reason is that
* we may have multiple password sources.
*/
int
ocset_user_password(OCstate* state)
{
CURLcode cstat;
CURL* curl = state->curl;
char* combined = NULL;
const char* userC = state->creds.username;
const char* passwordC = state->creds.password;
if(userC == NULL || passwordC == NULL) return OC_NOERR;
combined = combinecredentials(userC,passwordC);
if (!combined) return OC_ENOMEM;
cstat = curl_easy_setopt(curl, CURLOPT_USERPWD, combined);
if (cstat != CURLE_OK) goto done;
OCDBG1(1,"CURLOPT_USERPWD=%s",combined);
cstat = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long) CURLAUTH_ANY);
if (cstat != CURLE_OK) goto done;
OCDBG1(1,"CURLOPT_HTTPAUTH=%ld",(long)CURLAUTH_ANY);
done:
if(combined != NULL) free(combined);
return (cstat == CURLE_OK?OC_NOERR:OC_ECURL);
}
static char*
combinecredentials(const char* user, const char* pwd)
{
int userPassSize = strlen(user) + strlen(pwd) + 2;
char *userPassword = malloc(sizeof(char) * userPassSize);
if (!userPassword) {
oc_log(LOGERR,"Out of Memory\n");
return NULL;
}
strcpy(userPassword, user);
strcat(userPassword, ":");
strcat(userPassword, pwd);
return userPassword;
}

View File

@ -1,19 +0,0 @@
/*
* rc.h
*
* Created on: Mar 5, 2009
* Author: rikki
*/
#ifndef _CURLFUNCTION_H_
#define _CURLFUNCTION_H_
extern int ocset_curl_flags(OCstate*);
extern int ocset_user_password(OCstate*);
extern int ocset_proxy(OCstate*);
extern int ocset_ssl(OCstate*);
#endif /*_CURLFUNCTION_H_*/

View File

@ -1,362 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include "ocinternal.h"
#include "occontent.h"
#include "ocdata.h"
#include "ocdebug.h"
const char StartOfSequence = '\x5A';
const char EndOfSequence = '\xA5';
static int ocerrorstring(XXDR* xdrs);
#define LOCALMEMMAX 1024
/* Skip arbitrary object:
Cases:
astype = Grid|Structure: skip single set of fields
astype = Primitive array (or scalar): skip whole array.
astype = Sequence: skip whole sequence
astype = OC_NAT => use node's type
*/
OCerror
ocskipinstanceas(OCnode* node, XXDR* xdrs, OCtype astype)
{
unsigned int i;
int stat = OC_NOERR;
char tmp[XDRUNIT];
/* assume that xxdr_getpos points to start of the object (including leading counts) */
/* Make sure astype is defined */
if(astype == OC_NAT)
astype = node->octype;
switch (astype) {
case OC_Dataset:
case OC_Grid:
case OC_Structure:
if(node->skip.instancesize != OCINDETERMINATE
&& node->skip.count != OCINDETERMINATE) {
/* skip directly past it */
xxdr_skip(xdrs,node->skip.totalsize);
} else {/* Walk instance by instance */
for(i=0;i<oclistlength(node->subnodes);i++) {
OCnode* field = (OCnode*)oclistget(node->subnodes,i);
stat = ocskipinstanceas(field, xdrs, OC_NAT);
if(stat != OC_NOERR) {OCTHROWCHK(stat); break;}
}
if(stat != OC_NOERR) {OCTHROWCHK(stat); break;}
}
break;
case OC_Sequence:
/* skip whole sequence */
for(i=0;;i++) {
/* extract the tag byte*/
if(!xxdr_getbytes(xdrs,tmp,sizeof(tmp))) return xdrerror();
if(tmp[0] == EndOfSequence) {
/* we are done */
break;
} else if(tmp[0] == StartOfSequence) {
/* skip record instance */
stat = ocskipinstanceas(node, xdrs, OC_Structure);
if(stat != OC_NOERR) {OCTHROWCHK(stat); break;}
} else {stat = OCTHROW(OC_EXDR); break;}
}
break;
case OC_Primitive:
OCASSERT(node->skip.count != OCINDETERMINATE);
if(node->skip.instancesize != OCINDETERMINATE) {
/* skip directly past it */
xxdr_skip(xdrs,node->skip.totalsize);
} else {/* Walk instance by instance */
int skipstart = 0; /* worst case */
OCASSERT(node->etype == OC_String || node->etype == OC_URL);
#ifdef OCIGNORE
/* But first, check the cache, if any */
if(node->cache.cacheable && node->cache.valid) {
/* use the cache index to shorten how much we need to skip */
OCASSERT(node->cache.index <= node->skip.count);
if(!xxdr_setpos(xdrs,node->cache.offset))
return xdrerror();
skipstart = node->cache.index;
}
#endif
for(i=skipstart;i<node->skip.count;i++) {
/* read and skip the string */
unsigned int len;
/* read string size */
if(!xxdr_uint(xdrs,&len)) {stat = OCTHROW(OC_EXDR); break;}
/* round up to next XDRUNIT */
len = RNDUP(len);
if(!xxdr_skip(xdrs,(size_t)len)) {stat = OCTHROW(OC_EXDR); break;}
}
if(stat != OC_NOERR) {OCTHROWCHK(stat); break;}
}
break;
default:
OCPANIC1("ocskipinstance: encountered unexpected node type: %x",astype);
break;
}
return OCTHROW(stat);
}
/*
Extract data from the xdr packet into a chunk of memory.
Normally, it is assumed that we are (at least virtually)
"at" a single instance in the xdr packet; which we read.
Virtually because for packed data, we need to point to
the beginning of the packed data and use the index to indicate
which packed element to get. Assume that in any case,
any leading counts have been passed.
*/
OCerror
ocxdrread(OCcontent* content, XXDR* xdrs, char* memory, size_t memsize,
ocindex_t start, ocindex_t count)
{
int stat = OC_NOERR;
unsigned int i;
size_t elemsize;
size_t readsize;
size_t skipsize;
char localmem[LOCALMEMMAX];
char* srcmem;
unsigned int* p;
int packed;
int scalar;
OCtype octype,etype;
ocindex_t localstart = start; /* will change if node is cacheing */
OCnode* node;
node = content->node;
octype = node->octype;
etype = node->etype;
elemsize = octypesize(etype);
scalar = (node->array.rank == 0 ? 1 : 0);
/* check if the data is packed*/
packed = (octype == OC_Primitive && !scalar
&& (etype == OC_Byte || etype == OC_UByte || etype == OC_Char));
/* validate memory space*/
if(memsize < elemsize*count) return OCTHROW(OC_EINVAL);
#ifdef OCIGNORE
if(!scalar && (!node->cache.cacheable || !node->cache.valid)) {
unsigned int xdrcount0,xdrcount1;
/* assume xdr position is correct */
/* Read leading double count if ! scalar*/
if(!xxdr_uint(xdrs,&xdrcount0)) goto shortxdr;
if(!xxdr_uint(xdrs,&xdrcount1)) goto shortxdr;
if(xdrcount0 != xdrcount1) return OCTHROW(OC_EXDR);
if(xdrcount0 < start+count) goto shortxdr;
}
#endif
/* Handle packed data specially*/
if(packed) {
readsize = count*1; /* |OC_(Char,Byte,UByte)| == 1 */
skipsize = start*1; /* |OC_(Char,Byte,UByte)| == 1 */
/* skip to start of what we want to read */
if(!xxdr_skip(xdrs,skipsize)) goto shortxdr;
/* read data, keeping xdrs on XDRUNIT boundary */
if(!xxdr_opaque(xdrs,memory,readsize))
goto shortxdr;
return OCTHROW(OC_NOERR);
}
/* Not packed */
#ifdef OCIGNORE
/* If this (primitive) object is cacheable and is valid cache,
then modify start and set the xdr position accordingly
*/
if(node->cache.cacheable && node->cache.valid) {
if(node->cache.index <= start) {
localstart -= node->cache.index;
if(!xxdr_setpos(xdrs,node->cache.offset)) return xdrerror();
}
}
#endif
/* Compute how much to skip based on the content's cache index */
localstart = start - content->cache.index;
if(localstart < 0) localstart = 0;
/* extract count items; use xxdr_getbytes to speed up*/
srcmem = memory;
switch (etype) {
case OC_Float64: case OC_Int64: case OC_UInt64:
readsize = count*2*XDRUNIT;
skipsize = localstart*2*XDRUNIT;
/* skip to start of what we want to read */
if(!xxdr_skip(xdrs,skipsize)) goto shortxdr;
if(!xxdr_opaque(xdrs,(char*)srcmem,readsize)) goto shortxdr;
if(etype == OC_Float64) {
double* dp;
for(dp=(double*)srcmem,i=0;i<count;i++,dp++) {
double swap;
xxdrntohdouble((char*)dp,&swap);
*dp = swap;
}
} else if(!xxdr_network_order) {
unsigned long long* llp;
for(llp=(unsigned long long*)srcmem,i=0;i<count;i++,p++) {
swapinline64(llp);
}
}
break;
case OC_String: case OC_URL: {
/* Read string by string */
char* s = NULL;
char** pmem = (char**)srcmem;
/* First skip to the starting string */
for(i=0;i<localstart;i++) {
unsigned int slen;
if(!xxdr_uint(xdrs,&slen)) goto shortxdr;
slen = RNDUP(slen);
if(!xxdr_skip(xdrs,slen)) goto shortxdr;
}
/* Read count strings */
for(i=0;i<count;i++) {
off_t slen;
/* xxdr_string will always alloc the space */
if(!xxdr_string(xdrs,&s,&slen))
goto shortxdr;
pmem[i] = s;
}
} break;
case OC_Char: case OC_Byte: case OC_UByte:
case OC_Int16: case OC_UInt16:
/* We need to store the xdr data locally until we can convert it out
because elemsize < sizeof(int) */
srcmem = localmem;
if(count*elemsize > sizeof(localmem)) {
srcmem = (char*)ocmalloc(count*sizeof(unsigned int));
if(srcmem == NULL) {stat = OC_ENOMEM; goto done;}
}
/* fall thru */
case OC_Int32: case OC_UInt32:
case OC_Float32:
readsize = (count)*XDRUNIT;
skipsize = (localstart)*XDRUNIT;
if(!xxdr_skip(xdrs,skipsize)) goto shortxdr;
if(!xxdr_opaque(xdrs,(char*)srcmem,readsize)) goto shortxdr;
if(!xxdr_network_order) {
for(p=(unsigned int*)srcmem,i=0;i<count;i++,p++) {
swapinline32(p);
}
}
break;
default: OCPANIC("unexpected etype"); break;
}
/* Convert memory to right format */
p = (unsigned int*)memory;
switch (etype) {
case OC_Char: case OC_Byte: case OC_UByte: {
char* pmem = (char*)memory;
p = (unsigned int*)srcmem;
for(i=0;i<count;i++) {
unsigned int tmp = *p++;
*pmem++ = (unsigned char)tmp;
}
} break;
case OC_Int16: case OC_UInt16: {
unsigned short* pmem = (unsigned short*)memory;
p = (unsigned int*)srcmem;
for(i=0;i<count;i++) {
unsigned int tmp = *p++;
*pmem++ = (unsigned short)tmp;
}
} break;
default: break; /* already handled above */
}
/* set cache */
content->cache.index = start + count; /* should be our current index */
content->cache.offset = xxdr_getpos(xdrs); /* should be our current position */
done:
return OCTHROW(stat);
shortxdr:
content->cache.valid = 0; /* no longer valid */
if(!ocerrorstring(xdrs))
oc_log(LOGERR,"DAP DATADDS packet is apparently too short");
stat = OC_EDATADDS;
goto done;
}
int
occountrecords(OCnode* node, XXDR* xdrs, size_t* nrecordsp)
{
int stat = OC_NOERR;
size_t nrecords = 0;
if(node->octype != OC_Sequence) return OCTHROW(OC_EINVAL);
/* checkpoint the xdr position*/
for(;;) { unsigned int i;
/* pick up the sequence record begin marker*/
char tmp[sizeof(unsigned int)];
/* extract the tag byte*/
if(!xxdr_getbytes(xdrs,tmp,sizeof(tmp))) return xdrerror();
if(tmp[0] == StartOfSequence) {
/* Walk each member field*/
for(i=0;i<oclistlength(node->subnodes);i++) {
OCnode* member = (OCnode*)oclistget(node->subnodes,i);
stat = ocskipinstanceas(member,xdrs,OC_Structure);
if(stat != OC_NOERR) break;
}
nrecords++;
} else if(tmp[0] == EndOfSequence) {
break; /* we are done with the this sequence instance*/
} else {
oc_log(LOGERR,"missing/invalid begin/end record marker\n");
stat = OC_EINVALCOORDS;
break;
}
if(stat != OC_NOERR) break;
}
/* move to checkpoint position*/
if(nrecordsp != NULL) *nrecordsp = nrecords;
return OCTHROW(stat);
}
#define tag "Error {\n"
static int
ocerrorstring(XXDR* xdrs)
{
/* Check to see if the xdrs contains "Error {\n'; assume it is at the beginning of data */
off_t avail = xxdr_getavail(xdrs);
char* data = (char*)malloc(avail);
if(!xxdr_setpos(xdrs,0)) return 0;
if(!xxdr_opaque(xdrs,data,avail)) return 0;
/* check for error tag at front */
if(ocstrncmp(data,tag,sizeof(tag))==0) {
char* p;
if((p=strchr(data,'}')) != NULL) *(++p)='\0';
oc_log(LOGERR,"Server error: %s",data);
/* Since important, report to stderr as well */
fprintf(stderr,"Server error: %s",data);
return 1;
}
return 0;
}

View File

@ -1,28 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCDATA_H
#define OCDATA_H
typedef struct OCdimcounter {
int rank;
size_t index[OC_MAX_DIMS];
size_t size[OC_MAX_DIMS];
} OCdimcounter;
extern const char StartOfSequence;
extern const char EndOfSequence;
/*Forward */
struct OCcontent;
/* Skip arbitrary dimensioned instance; Handles dimensioning.*/
extern int ocskip(OCnode* node, XXDR* xdrs);
extern int occountrecords(OCnode* node, XXDR* xdrs, size_t* nrecordsp);
extern int ocxdrread(struct OCcontent*, XXDR*, char* memory, size_t, ocindex_t index, ocindex_t count);
extern int ocskipinstance(OCnode* node, XXDR* xdrs, int state, int* tagp);
#endif /*OCDATA_H*/

View File

@ -1,61 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCDATATYPES_H
#define OCDATATYPES_H
/* Define some useful info about the supported
primitive datatypes*/
#define DCHAR char
#define DBYTE signed char
#define DUBYTE unsigned char
#define DINT16 short
#define DUINT16 unsigned short
#define DINT32 int
#define DUINT32 unsigned int
#define DINT64 int
#define DUINT64 unsigned int
#define DFLOAT32 float
#define DFLOAT64 double
#define OC_CHAR_MIN ((char)0x00)
#define OC_CHAR_MAX ((char)0xff)
#define OC_BYTE_MIN -128
#define OC_BYTE_MAX 127
#define OC_UBYTE_MIN 0
#define OC_UBYTE_MAX 255U
#define OC_INT16_MIN -32768
#define OC_INT16_MAX 32767
#define OC_UINT16_MIN 0
#define OC_UINT16_MAX 65535U
#define OC_INT32_MIN (-2147483647 - 1)
#define OC_INT32_MAX 2147483647
#define OC_UINT32_MIN 0
#define OC_UINT32_MAX 4294967295U
#define OC_INT64_MIN (-9223372036854775807LL-1)
#define OC_INT64_MAX (9223372036854775807LL)
#define OC_UINT64_MIN 0LL
#define OC_UINT64_MAX (18446744073709551615ULL)
#define OC_FLOAT32_MAX 3.402823466E+38F /* max decimal value of a "float" */
#define OC_FLOAT32_MIN (-OC_FLOAT_MAX)
#define OC_FLOAT64_MAX 1.7976931348623157E+308 /* max decimal value of a double */
#define OC_FLOAT64_MIN (-OC_FLOAT64_MAX)
/* Similar to netcdf*/
#define OC_FILL_CHAR ((char)0)
#define OC_FILL_BYTE ((signed char)-127)
#define OC_FILL_UBYTE (255)
#define OC_FILL_INT16 ((short)-32767)
#define OC_FILL_UINT16 (65535)
#define OC_FILL_INT32 (-2147483647L)
#define OC_FILL_UINT32 (4294967295U)
#define OC_FILL_INT64 ((long long)-9223372036854775806LL)
#define OC_FILL_UINT64 ((unsigned long long)18446744073709551614ULL)
#define OC_FILL_FLOAT32 (9.9692099683868690e+36f) /* near 15 * 2^119 */
#define OC_FILL_FLOAT64 (9.9692099683868690e+36)
#define OC_FILL_STRING ""
#define OC_FILL_URL ""
#endif /*OCDATATYPES_H*/

View File

@ -1,67 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdarg.h>
#include "ocinternal.h"
#include "ocdebug.h"
int ocdebug;
#ifdef OCCATCHERROR
/* Place breakpoint here to catch errors close to where they occur*/
int
ocbreakpoint(int err) {return err;}
int
octhrow(int err)
{
if(err == 0) return err;
return ocbreakpoint(err);
}
#endif
int
xdrerror(void)
{
oc_log(LOGERR,"xdr failure");
return OCTHROW(OC_EDATADDS);
}
void*
occalloc(size_t size, size_t nelems)
{
return ocmalloc(size*nelems);
}
void*
ocmalloc(size_t size)
{
void* memory = calloc(size,1); /* use calloc to zero memory*/
if(memory == NULL) oc_log(LOGERR,"ocmalloc: out of memory");
return memory;
}
void
ocfree(void* mem)
{
if(mem != NULL) free(mem);
}
int
ocpanic(const char* fmt, ...)
{
va_list args;
if(fmt != NULL) {
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n" );
va_end( args );
} else {
fprintf(stderr, "panic" );
}
fprintf(stderr, "\n" );
fflush(stderr);
return 0;
}

View File

@ -1,93 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCOCDBG_H
#define OCOCDBG_H
#include <stdarg.h>
#if 0
#define OCDEBUG
#define DAPDEBUG 1
#endif
#ifdef OCDEBUG
#define OCVERBOSE
#endif
/* OCCATCHERROR is used to detect errors as close
to their point of origin as possible. When
enabled, one can set a breakpoint in ocbreakpoint()
to catch the failure. Turing it on incurs a significant
performance penalty, so it is off by default.*/
#define OCCATCHERROR
#define OCPANIC(msg) assert(ocpanic(msg))
#define OCPANIC1(msg,arg) assert(ocpanic(msg,arg))
#define OCPANIC2(msg,arg1,arg2) assert(ocpanic(msg,arg1,arg2))
/* Make it possible to catch assertion failures by breakpointing ocpanic*/
#define OCASSERT(expr) if(!(expr)) {OCPANIC((#expr));} else {}
/* Need some syntactic trickery to make these macros work*/
#ifdef OCDEBUG
#define OCDBG(l,msg) {oc_log(LOGDBG,msg);}
#define OCDBG1(l,msg,arg) {oc_log(LOGDBG,msg,arg);}
#define OCDBG2(l,msg,arg1,arg2) {oc_log(LOGDBG,msg,arg1,arg2);}
#define OCDBGTEXT(l,text) {oc_logtext(LOGNOTE,text);} else {}
#define OCDBGCODE(l,code) {code;}
#else
#define OCDBG(l,msg)
#define OCDBG1(l,msg,arg)
#define OCDBG2(l,msg,arg1,arg2)
#define OCDBGTEXT(l,text)
#define OCDBGCODE(l,code)
#endif
/*
OCPROGRESS attempts to provide some info
about how IO is getting along.
*/
#undef OCPROGRESS
extern int ocdebug;
extern int cedebug;
/*extern char* dent2(int n);*/
/*/extern char* dent(int n);*/
extern int ocpanic(const char* fmt, ...);
extern int xdrerror(void);
/*
Provide wrapped versions of calloc and malloc.
The wrapped version panics if memory
is exhausted. It also guarantees that the
memory has been zero'd.
*/
extern void* occalloc(size_t size, size_t nelems);
extern void* ocmalloc(size_t size);
extern void ocfree(void*);
#define MEMCHECK(var,throw) {if((var)==NULL) return (throw);}
#ifdef OCCATCHERROR
/* Place breakpoint on ocbreakpoint to catch errors close to where they occur*/
#define OCTHROW(e) octhrow(e)
#define OCTHROWCHK(e) (void)octhrow(e)
#define OCGOTO(label) {ocbreakpoint(-1); goto label;}
extern int ocbreakpoint(int err);
extern int octhrow(int err);
#else
#define OCTHROW(e) (e)
#define OCTHROWCHK(e)
#define OCGOTO(label) goto label
#endif
#endif /*OCOCDBG_H*/

View File

@ -1,62 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include "oc.h"
#include "ocinternal.h"
#include "ocdebug.h"
/*
This file exports procedures
that access the internals of
oc. They are intended to be called
by the drno code to avoid at least
the appearance of breaking the oc
encapsulation.
*/
#if 0
OCerror
oc_svcerrordata(OCconnection conn, char** codep, char** msgp, long* httpp)
{
OCstate* state = (OCstate*)conn;
if(codep) *codep = state->error.code;
if(msgp) *msgp = state->error.message;
if(httpp) *httpp = state->error.httpcode;
return OC_NOERR;
}
/* DRNO need to explicitly get and walk string values*/
int
oc_stringcontent(OCstate* state, OCcontent* content, char** stringp, size_t* slenp)
{
int stat = OC_NOERR;
XDR* xdrs;
unsigned int slen;
char* stringmemory;
if(state == NULL || content == NULL) return OCTHROW(OC_EINVAL);
if(content->node->octype != OC_Primitive) return OCTHROW(OC_EINVAL);
if(content->node->etype != OC_String
&& content->node->etype != OC_URL) return OCTHROW(OC_EINVAL);
xdrs = state->dap.xdrs;
if(xdrs == NULL) return OCTHROW(OC_EXDR);
if(oc_contentmode(state,content) != Datamode) return OCTHROW(OC_EINVAL);
/* We are at a single instance of a string data type*/
if(!xdr_setpos(xdrs,content->xdroffset)) return xdrerror();
if(!xdr_u_int(xdrs,&slen)) return xdrerror();
stringmemory = (char*)ocmalloc(slen+1);
MEMCHECK(stringmemory,OC_ENOMEM);
if(!xdr_opaque(xdrs,stringmemory,slen)) return xdrerror();
stringmemory[slen] = '\0';
/* restore location*/
if(!xdr_setpos(xdrs,content->xdroffset)) return xdrerror();
if(stringp != NULL) *stringp = stringmemory;
if(slenp != NULL) *slenp = slen;
return OCTHROW(stat);
}
#endif

View File

@ -1,18 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCDRNO_H
#define OCDRNO_H
/*
This file exports procedures
that access the internals of
oc. They are intended to be called
by the drno code to avoid at least
the appearance of breaking the oc
encapsulation.
*/
/* DO NOT FREE THE RETURNED STRINGS */
extern OCerror ocdaperrorcode(OCconnection,char**,char**,long*);
#endif /*OCDRNO_H*/

View File

@ -1,482 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information.
*/
#include "config.h"
#include <sys/stat.h>
#ifdef NETINET_IN_H
#include <netinet/in.h>
#endif
#include "ocinternal.h"
#include "ocdata.h"
#include "ocdebug.h"
#define MAXLEVEL 1
/*Forward*/
static void dumpocnode1(OCnode* node, int depth);
static void dumpdimensions(OCnode* node);
static void dumpattvalue(OCtype nctype, char** aset, int index);
static char* sindent = NULL;
static char*
dent(int n)
{
if(sindent == NULL) {
sindent = (char*)ocmalloc(102);
MEMCHECK(sindent,NULL);
memset((void*)sindent,(int)' ',(size_t)101);
sindent[101] = '\0';
}
if(n > 100) n = 100;
return sindent+(100-n);
}
/* support [dd] leader*/
static char*
dent2(int n) {return dent(n+4);}
void
ocdumpnode(OCnode* node)
{
if(node != NULL) {
dumpocnode1(node,0);
} else {
fprintf(stdout,"<NULL>\n");
}
fflush(stdout);
}
static void
dumpskip(OCnode* node)
{
char tmpc[64];
char tmpi[64];
char tmpt[64];
char tmpo[64];
if(node->skip.count == OCINDETERMINATE)
strcpy(tmpc,"?");
else
snprintf(tmpc,sizeof(tmpc),"%lu",(unsigned long)node->skip.count);
if(node->skip.instancesize == OCINDETERMINATE)
strcpy(tmpi,"?");
else
snprintf(tmpi,sizeof(tmpi),"%lu",(unsigned long)node->skip.instancesize);
if(node->skip.totalsize == OCINDETERMINATE)
strcpy(tmpt,"?");
else
snprintf(tmpt,sizeof(tmpt),"%lu",(unsigned long)node->skip.totalsize);
if(node->skip.offset == OCINDETERMINATE)
strcpy(tmpo,"?");
else
snprintf(tmpo,sizeof(tmpo),"%lu",(unsigned long)node->skip.offset);
fprintf(stdout," [(%s*%s)/%s@%s]",tmpi,tmpc,tmpt,tmpo);
}
static void
dumpocnode1(OCnode* node, int depth)
{
unsigned int n;
switch (node->octype) {
case OC_Primitive: {
fprintf(stdout,"[%2d]%s ",depth,dent(depth));
if(node->name == NULL) OCPANIC("prim without name");
fprintf(stdout,"%s %s",octypetostring(node->etype),node->name);
dumpdimensions(node);
#ifdef OCIGNORE
if(node->cache.cacheable) fprintf(stdout," [cached]");
#endif
dumpskip(node);
fprintf(stdout," &%lx",(unsigned long)node);
fprintf(stdout,"\n");
} break;
case OC_Dataset: {
fprintf(stdout,"[%2d]%s ",depth,dent(depth));
fprintf(stdout,"dataset %s\n",
(node->name?node->name:""));
for(n=0;n<oclistlength(node->subnodes);n++) {
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
}
} break;
case OC_Structure: {
fprintf(stdout,"[%2d]%s ",depth,dent(depth));
fprintf(stdout,"struct %s",
(node->name?node->name:""));
dumpdimensions(node);
dumpskip(node);
fprintf(stdout," &%lx",(unsigned long)node);
fprintf(stdout,"\n");
for(n=0;n<oclistlength(node->subnodes);n++) {
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
}
} break;
case OC_Sequence: {
fprintf(stdout,"[%2d]%s ",depth,dent(depth));
fprintf(stdout,"sequence %s",
(node->name?node->name:""));
dumpdimensions(node);
dumpskip(node);
fprintf(stdout," &%lx",(unsigned long)node);
fprintf(stdout,"\n");
for(n=0;n<oclistlength(node->subnodes);n++) {
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
}
} break;
case OC_Grid: {
unsigned int i;
fprintf(stdout,"[%2d]%s ",depth,dent(depth));
fprintf(stdout,"grid %s",
(node->name?node->name:""));
dumpdimensions(node);
dumpskip(node);
fprintf(stdout," &%lx",(unsigned long)node);
fprintf(stdout,"\n");
fprintf(stdout,"%sarray:\n",dent2(depth+1));
dumpocnode1((OCnode*)oclistget(node->subnodes,0),depth+2);
fprintf(stdout,"%smaps:\n",dent2(depth+1));
for(i=1;i<oclistlength(node->subnodes);i++) {
dumpocnode1((OCnode*)oclistget(node->subnodes,i),depth+2);
}
} break;
case OC_Attribute: {
fprintf(stdout,"[%2d]%s ",depth,dent(depth));
if(node->name == NULL) OCPANIC("Attribute without name");
fprintf(stdout,"%s %s",octypetostring(node->etype),node->name);
for(n=0;n<oclistlength(node->att.values);n++) {
char* value = (char*)oclistget(node->att.values,n);
if(n > 0) fprintf(stdout,",");
fprintf(stdout," %s",value);
}
fprintf(stdout," &%lx",(unsigned long)node);
fprintf(stdout,"\n");
} break;
case OC_Attributeset: {
fprintf(stdout,"[%2d]%s ",depth,dent(depth));
fprintf(stdout,"%s:\n",node->name?node->name:"Attributes");
for(n=0;n<oclistlength(node->subnodes);n++) {
dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
}
} break;
default:
OCPANIC1("encountered unexpected node type: %x",node->octype);
}
if(node->attributes != NULL) {
unsigned int i;
for(i=0;i<oclistlength(node->attributes);i++) {
OCattribute* att = (OCattribute*)oclistget(node->attributes,i);
fprintf(stdout,"%s[%s=",dent2(depth+2),att->name);
if(att->nvalues == 0)
OCPANIC("Attribute.nvalues == 0");
if(att->nvalues == 1) {
dumpattvalue(att->etype,att->values,0);
} else {
unsigned int j;
fprintf(stdout,"{");
for(j=0;j<att->nvalues;j++) {
if(j>0) fprintf(stdout,", ");
dumpattvalue(att->etype,att->values,j);
}
fprintf(stdout,"}");
}
fprintf(stdout,"]\n");
}
}
}
static void
dumpdimensions(OCnode* node)
{
unsigned int i;
for(i=0;i<node->array.rank;i++) {
OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
fprintf(stdout,"[%s=%lu]",
(dim->name?dim->name:"?"),
(unsigned long)dim->dim.declsize);
}
}
static void
dumpattvalue(OCtype nctype, char** strings, int index)
{
if(nctype == OC_String || nctype == OC_URL) {
fprintf(stdout,"\"%s\"",strings[index]);
} else {
fprintf(stdout,"%s",strings[index]);
}
}
void
ocdumpslice(OCslice* slice)
{
fprintf(stdout,"[");
fprintf(stdout,"%lu",(unsigned long)slice->first);
if(slice->stride > 1) fprintf(stdout,":%lu",(unsigned long)slice->stride);
fprintf(stdout,":%lu",(unsigned long)(slice->first+slice->count)-1);
fprintf(stdout,"]");
}
void
ocdumpclause(OCprojectionclause* ref)
{
unsigned int i;
OClist* path = oclistnew();
occollectpathtonode(ref->node,path);
for(i=0;i<oclistlength(path);i++) {
OClist* sliceset;
OCnode* node = (OCnode*)oclistget(path,i);
if(node->tree != NULL) continue; /* leave off the root node*/
fprintf(stdout,"%s%s",(i>0?PATHSEPARATOR:""),node->name);
sliceset = (OClist*)oclistget(ref->indexsets,i);
if(sliceset != NULL) {
unsigned int j;
for(j=0;j<oclistlength(sliceset);j++) {
OCslice* slice = (OCslice*)oclistget(sliceset,j);
ocdumpslice(slice);
}
}
}
}
static void
addfield(char* field, char* line, int align)
{
int len,rem;
strcat(line,"|");
strcat(line,field);
len = strlen(field);
rem = (align - len);
while(rem-- > 0) strcat(line," ");
}
static void
dumpfield(int index, char* n8, int isxdr)
{
char line[1024];
char tmp[32];
union {
unsigned int uv;
int sv;
char cv[4];
float fv;
} form;
union {
char cv[8];
unsigned long long ll;
double d;
} dform;
line[0] = '\0';
/* offset */
sprintf(tmp,"%6d",index);
addfield(tmp,line,5);
memcpy(form.cv,n8,4);
/* straight hex*/
sprintf(tmp,"%08x",form.uv);
addfield(tmp,line,8);
if(isxdr) {swapinline32(&form.uv);}
/* unsigned integer */
sprintf(tmp,"%12u",form.uv);
addfield(tmp,line,12);
/* signed integer */
sprintf(tmp,"%12d",form.sv);
addfield(tmp,line,12);
/* float */
sprintf(tmp,"%#g",form.fv);
addfield(tmp,line,12);
/* char[4] */
{
/* use raw form (i.e. n8)*/
int i;
tmp[0] = '\0';
for(i=0;i<4;i++) {
char stmp[64];
unsigned int c = (n8[i] & 0xff);
if(c < ' ' || c > 126)
sprintf(stmp,"\\%02x",c);
else
sprintf(stmp,"%c",c);
strcat(tmp,stmp);
}
}
addfield(tmp,line,16);
/* double */
memcpy(dform.cv,n8,2*XDRUNIT);
if(isxdr) xxdrntohdouble(dform.cv,&dform.d);
sprintf(tmp,"%#g",dform.d);
addfield(tmp,line,12);
fprintf(stdout,"%s\n",line);
}
static void
typedmemorydump(char* memory, size_t len, int fromxdr)
{
unsigned int i,count,rem;
char line[1024];
char* pmem;
char mem[8];
assert(memory[len] == 0);
/* build the header*/
line[0] = '\0';
addfield("offset",line,6);
addfield("hex",line,8);
addfield("uint",line,12);
addfield("int",line,12);
addfield("float",line,12);
addfield("char[4]",line,16);
addfield("double",line,12);
strcat(line,"\n");
fprintf(stdout,"%s",line);
count = (len / sizeof(int));
rem = (len % sizeof(int));
for(pmem=memory,i=0;i<count;i++,pmem+=4) {
memset(mem,0,8);
if(i<(count-1))
memcpy(mem,pmem,8);
else
memcpy(mem,pmem,4);
dumpfield(i*sizeof(unsigned int),mem,fromxdr);
}
if(rem > 0) {
memset(mem,0,8);
memcpy(mem,pmem,4);
dumpfield(i*sizeof(unsigned int),mem,fromxdr);
}
fflush(stdout);
}
static void
simplememorydump(char* memory, size_t len, int fromxdr)
{
unsigned int i,count,rem;
int* imemory;
char tmp[32];
char line[1024];
assert(memory[len] == 0);
/* build the header*/
line[0] = '\0';
addfield("offset",line,6);
addfield("XDR (hex)",line,9);
addfield("!XDR (hex)",line,10);
fprintf(stdout,"%s\n",line);
count = (len / sizeof(int));
rem = (len % sizeof(int));
if(rem != 0)
fprintf(stderr,"ocdump: |mem|%%4 != 0\n");
imemory = (int*)memory;
for(i=0;i<count;i++) {
unsigned int vx = (unsigned int)imemory[i];
unsigned int v = vx;
if(!xxdr_network_order) swapinline32(&v);
line[0] = '\0';
sprintf(tmp,"%6d",i);
addfield(tmp,line,6);
sprintf(tmp,"%08x",vx);
addfield(tmp,line,9);
sprintf(tmp,"%08x",v);
addfield(tmp,line,10);
fprintf(stdout,"%s\n",line);
}
fflush(stdout);
}
void
ocdumpmemory(char* memory, size_t len, int xdrencoded, int level)
{
if(level > MAXLEVEL) level = MAXLEVEL;
switch (level) {
case 1: /* Do a multi-type dump */
typedmemorydump(memory,len,xdrencoded);
break;
case 0: /* Dump a simple linear list of the contents of the memory as 32-bit hex and decimal */
default:
simplememorydump(memory,len,xdrencoded);
break;
}
}
static int
ocreadfile(FILE* file, int datastart, char** memp, size_t* lenp)
{
char* mem;
size_t len;
size_t pos;
size_t red;
struct stat stats;
pos = ftell(file);
fseek(file,0,SEEK_SET);
fseek(file,datastart,SEEK_SET);
fstat(fileno(file),&stats);
len = stats.st_size;
len -= datastart;
mem = (char*)calloc(len+1,1);
if(mem == NULL) return 0;
/* Read only the data part */
red = fread(mem,1,len,file);
if(red < len) {
fprintf(stderr,"ocreadfile: short file\n");
return 0;
}
fseek(file,pos,SEEK_SET); /* leave it as we found it*/
if(memp) *memp = mem;
if(lenp) *lenp = len;
return 1;
}
void
ocdd(OCstate* state, OCnode* root, int xdrencoded, int level)
{
char* mem;
size_t len;
if(root->tree->data.file != NULL) {
if(!ocreadfile(root->tree->data.file,root->tree->data.bod,&mem,&len)) {
fprintf(stderr,"ocdd could not read data file\n");
return;
}
ocdumpmemory(mem,len,xdrencoded,level);
free(mem);
} else {
mem = root->tree->data.memory;
mem += root->tree->data.bod;
len = root->tree->data.datasize;
len -= root->tree->data.bod;
ocdumpmemory(mem,len,xdrencoded,level);
}
}

View File

@ -1,16 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCDUMP_H
#define OCDUMP_H
extern void ocdumpnode(OCnode* node);
extern void ocdumpslice(OCslice* slice);
extern void ocdumpclause(OCprojectionclause* ref);
extern void ocdumpmemory(char* memory, size_t len, int xdrencoded, int level);
extern void ocdd(OCstate*,OCnode*,int xdrencoded, int level);
#endif /*OCDUMP_H*/

View File

@ -1,338 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include "ocinternal.h"
#include "ocdebug.h"
#include "ochttp.h"
#include "ocrc.h"
static size_t WriteFileCallback(void*, size_t, size_t, void*);
static size_t WriteMemoryCallback(void*, size_t, size_t, void*);
struct Fetchdata {
FILE* stream;
size_t size;
};
long
ocfetchhttpcode(CURL* curl)
{
long httpcode;
CURLcode cstat = CURLE_OK;
/* Extract the http code */
cstat = curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&httpcode);
if(cstat != CURLE_OK) httpcode = 0;
return httpcode;
}
int
ocfetchurl_file(CURL* curl, const char* url, FILE* stream,
unsigned long* sizep, long* filetime)
{
int stat = OC_NOERR;
CURLcode cstat = CURLE_OK;
struct Fetchdata fetchdata;
/* Set the URL */
cstat = curl_easy_setopt(curl, CURLOPT_URL, (void*)url);
if (cstat != CURLE_OK)
goto fail;
/* send all data to this function */
cstat = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteFileCallback);
if (cstat != CURLE_OK)
goto fail;
/* we pass our file to the callback function */
cstat = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&fetchdata);
if (cstat != CURLE_OK)
goto fail;
/* One last thing; always try to get the last modified time */
cstat = curl_easy_setopt(curl, CURLOPT_FILETIME, (long)1);
if (cstat != CURLE_OK)
goto fail;
fetchdata.stream = stream;
fetchdata.size = 0;
cstat = curl_easy_perform(curl);
if (cstat != CURLE_OK)
goto fail;
if (stat == OC_NOERR) {
/* return the file size*/
#ifdef OCDEBUG
oc_log(LOGNOTE,"filesize: %lu bytes",fetchdata.size);
#endif
if (sizep != NULL)
*sizep = fetchdata.size;
/* Get the last modified time */
if(filetime != NULL)
cstat = curl_easy_getinfo(curl,CURLINFO_FILETIME,filetime);
if(cstat != CURLE_OK) goto fail;
}
return OCTHROW(stat);
fail:
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
return OCTHROW(OC_ECURL);
}
int
ocfetchurl(CURL* curl, const char* url, OCbytes* buf, long* filetime)
{
int stat = OC_NOERR;
CURLcode cstat = CURLE_OK;
size_t len;
/* Set the URL */
cstat = curl_easy_setopt(curl, CURLOPT_URL, (void*)url);
if (cstat != CURLE_OK)
goto fail;
/* send all data to this function */
cstat = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
if (cstat != CURLE_OK)
goto fail;
/* we pass our file to the callback function */
cstat = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)buf);
if (cstat != CURLE_OK)
goto fail;
/* One last thing; always try to get the last modified time */
cstat = curl_easy_setopt(curl, CURLOPT_FILETIME, (long)1);
cstat = curl_easy_perform(curl);
if(cstat == CURLE_PARTIAL_FILE) {
/* Log it but otherwise ignore */
oc_log(LOGWARN, "curl error: %s; ignored",
curl_easy_strerror(cstat));
cstat = CURLE_OK;
}
if(cstat != CURLE_OK) goto fail;
/* Get the last modified time */
if(filetime != NULL)
cstat = curl_easy_getinfo(curl,CURLINFO_FILETIME,filetime);
if(cstat != CURLE_OK) goto fail;
/* Null terminate the buffer*/
len = ocbyteslength(buf);
ocbytesappend(buf, '\0');
ocbytessetlength(buf, len); /* dont count null in buffer size*/
#ifdef OCDEBUG
oc_log(LOGNOTE,"buffersize: %lu bytes",(unsigned long)ocbyteslength(buf));
#endif
return OCTHROW(stat);
fail:
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
return OCTHROW(OC_ECURL);
}
static size_t
WriteFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
{
size_t realsize = size * nmemb;
size_t count;
struct Fetchdata* fetchdata;
fetchdata = (struct Fetchdata*) data;
if(realsize == 0)
oc_log(LOGWARN,"WriteFileCallback: zero sized chunk");
count = fwrite(ptr, size, nmemb, fetchdata->stream);
if (count > 0) {
fetchdata->size += (count * size);
} else {
oc_log(LOGWARN,"WriteFileCallback: zero sized write");
}
#ifdef OCPROGRESS
oc_log(LOGNOTE,"callback: %lu bytes",(unsigned long)realsize);
#endif
return count;
}
static size_t
WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
size_t realsize = size * nmemb;
OCbytes* buf = (OCbytes*) data;
if(realsize == 0)
oc_log(LOGWARN,"WriteMemoryCallback: zero sized chunk");
/* Optimize for reading potentially large dods datasets */
if(!ocbytesavail(buf,realsize)) {
/* double the size of the packet */
ocbytessetalloc(buf,2*ocbytesalloc(buf));
}
ocbytesappendn(buf, ptr, realsize);
#ifdef OCPROGRESS
oc_log(LOGNOTE,"callback: %lu bytes",(unsigned long)realsize);
#endif
return realsize;
}
#if 0
static void
assembleurl(DAPURL* durl, OCbytes* buf, int what)
{
encodeurltext(durl->url,buf);
if(what & WITHPROJ) {
ocbytescat(buf,"?");
encodeurltext(durl->projection,buf);
}
if(what & WITHSEL) encodeurltext(durl->selection,buf);
}
static char mustencode="";
static char hexchars[16] = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f',
};
static void
encodeurltext(char* text, OCbytes* buf)
{
/* Encode the URL to handle illegal characters */
len = strlen(url);
encoded = ocmalloc(len*4+1); /* should never be larger than this*/
if(encoded==NULL) return;
p = url; q = encoded;
while((c=*p++)) {
if(strchr(mustencode,c) != NULL) {
char tmp[8];
int hex1, hex2;
hex1 = (c & 0x0F);
hex2 = (c & 0xF0) >> 4;
tmp[0] = '0'; tmp[1] = 'x';
tmp[2] = hexchars[hex2]; tmp[3] = hexchars[hex1];
tmp[4] = '\0';
ocbytescat(buf,tmp);
} else *q++ = (char)c;
}
}
#endif
int
occurlopen(CURL** curlp)
{
int stat = OC_NOERR;
CURLcode cstat = CURLE_OK;
CURL* curl;
/* initialize curl*/
curl = curl_easy_init();
if (curl == NULL)
stat = OC_ECURL;
else {
cstat = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
if (cstat != CURLE_OK)
stat = OC_ECURL;
/* some servers don't like requests that are made without a user-agent */
cstat = curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
if (cstat != CURLE_OK)
stat = OC_ECURL;
}
if (curlp)
*curlp = curl;
return OCTHROW(stat);
}
void
occurlclose(CURL* curl)
{
if (curl != NULL)
curl_easy_cleanup(curl);
}
int
ocfetchlastmodified(CURL* curl, char* url, long* filetime)
{
int stat = OC_NOERR;
CURLcode cstat = CURLE_OK;
/* Set the URL */
cstat = curl_easy_setopt(curl, CURLOPT_URL, (void*)url);
if (cstat != CURLE_OK)
goto fail;
/* Ask for head */
cstat = curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30); /* 30sec timeout*/
cstat = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2);
cstat = curl_easy_setopt(curl, CURLOPT_HEADER, 1);
cstat = curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
cstat = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
cstat = curl_easy_setopt(curl, CURLOPT_FILETIME, (long)1);
cstat = curl_easy_perform(curl);
if(cstat != CURLE_OK) goto fail;
if(filetime != NULL)
cstat = curl_easy_getinfo(curl,CURLINFO_FILETIME,filetime);
if(cstat != CURLE_OK) goto fail;
return OCTHROW(stat);
fail:
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
return OCTHROW(OC_ECURL);
}
int
ocping(const char* url)
{
int stat = OC_NOERR;
CURLcode cstat = CURLE_OK;
CURL* curl = NULL;
OCbytes* buf = NULL;
/* Create a CURL instance */
stat = occurlopen(&curl);
if(stat != OC_NOERR) return stat;
/* use a very short timeout: 10 seconds */
cstat = curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)10);
if (cstat != CURLE_OK)
goto done;
/* fail on HTTP 400 code errors */
cstat = curl_easy_setopt(curl, CURLOPT_FAILONERROR, (long)1);
if (cstat != CURLE_OK)
goto done;
/* Try to get the file */
buf = ocbytesnew();
stat = ocfetchurl(curl,url,buf,NULL);
if(stat == OC_NOERR) {
/* Don't trust curl to return an error when request gets 404 */
long http_code = 0;
cstat = curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &http_code);
if (cstat != CURLE_OK)
goto done;
if(http_code >= 400) {
cstat = CURLE_HTTP_RETURNED_ERROR;
goto done;
}
} else
goto done;
done:
ocbytesfree(buf);
occurlclose(curl);
if(cstat != CURLE_OK) {
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
stat = OC_EDAPSVC;
}
return OCTHROW(stat);
}

View File

@ -1,22 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef HTTP_H
#define HTTP_H 1
extern int curlopen(CURL** curlp);
extern void curlclose(CURL*);
extern int ocfetchurl(CURL*, const char*, OCbytes*, long*);
extern int ocfetchurl_file(CURL*, const char*, FILE*, unsigned long*, long*);
extern long ocfetchhttpcode(CURL* curl);
extern int ocfetchlastmodified(CURL* curl, char* url, long* filetime);
extern int occurlopen(CURL** curlp);
extern void occurlclose(CURL* curlp);
extern int ocping(const char* url);
#endif /*HTTP_H*/

View File

@ -1,574 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ocinternal.h"
#include "ocdebug.h"
#include "ocdata.h"
#include "occontent.h"
#include "occlientparams.h"
#include "ocrc.h"
#include "occurlfunctions.h"
#include "ochttp.h"
#include "ocread.h"
/* Note: TMPPATH must end in '/' */
#ifdef __CYGWIN__
#define TMPPATH1 "/cygdrive/c/temp/"
#define TMPPATH2 "./"
#elifdef WIN32
#define TMPPATH1 "c:\\temp/"
#define TMPPATH2 ".\\"
#else
#define TMPPATH1 "/tmp/"
#define TMPPATH2 "./"
#endif
/* Define default rc files and aliases*/
static char* rcfilenames[3] = {".dodsrc",".ocrc",NULL};
static int ocextractddsinmemory(OCstate*,OCtree*,int);
static int ocextractddsinfile(OCstate*,OCtree*,int);
static char* constraintescape(const char* url);
static OCerror createtempfile(OCstate*,OCtree*);
static int createtempfile1(char*,char**);
static void ocsetcurlproperties(OCstate*);
extern OCnode* makeunlimiteddimension(void);
#ifdef WIN32
#include <fcntl.h>
#define _S_IREAD 256
#define _S_IWRITE 128
#else
#include <sys/stat.h>
#endif
/* Global flags*/
int oc_curl_file_supported;
int oc_curl_https_supported;
int
ocinternalinitialize(void)
{
int stat = OC_NOERR;
/* Compute some xdr related flags */
xxdr_init();
oc_loginit();
/* Determine if this version of curl supports
"file://..." &/or "https://..." urls.
*/
{
const char* const* proto; /*weird*/
curl_version_info_data* curldata;
curldata = curl_version_info(CURLVERSION_NOW);
oc_curl_file_supported = 0;
oc_curl_https_supported = 0;
for(proto=curldata->protocols;*proto;proto++) {
if(strcmp("file",*proto)==0) {oc_curl_file_supported=1;break;}
if(strcmp("https",*proto)==0) {oc_curl_https_supported=1;break;}
}
if(ocdebug > 0) {
oc_log(LOGNOTE,"Curl file:// support = %d",oc_curl_file_supported);
oc_log(LOGNOTE,"Curl https:// support = %d",oc_curl_file_supported);
}
}
/* compile the .dodsrc, if any */
{
char* path = NULL;
char* homepath = NULL;
char** alias;
FILE* f = NULL;
/* locate the configuration files: . first in '.', then $HOME */
for(alias=rcfilenames;*alias;alias++) {
path = (char*)malloc(strlen("./")+strlen(*alias)+1);
if(path == NULL) return OC_ENOMEM;
strcpy(path,"./");
strcat(path,*alias);
/* see if file is readable */
f = fopen(path,"r");
if(f != NULL) break;
if(path != NULL) {free(path); path = NULL;} /* cleanup */
}
if(f == NULL) { /* try $HOME */
OCASSERT(path == NULL);
homepath = getenv("HOME");
if (homepath!= NULL) {
for(alias=rcfilenames;*alias;alias++) {
path = (char*)malloc(strlen(homepath)+1+strlen(*alias)+1);
if(path == NULL) return OC_ENOMEM;
strcpy(path,homepath);
strcat(path,"/");
strcat(path,*alias);
f = fopen(path,"r");
if(f != NULL) break;
if(path != NULL) {free(path); path=NULL;}
}
}
}
if(f == NULL) {
oc_log(LOGDBG,"Cannot find runtime configuration file");
} else {
OCASSERT(path != NULL);
fclose(f);
if(ocdebug > 1)
fprintf(stderr, "DODS RC file: %s\n", path);
if(ocdodsrc_read(*alias,path) == 0)
oc_log(LOGERR, "Error parsing %s\n",path);
}
if(path != NULL) free(path);
}
return OCTHROW(stat);
}
/**************************************************/
OCerror
ocopen(OCstate** statep, const char* url)
{
int stat = OC_NOERR;
OCstate * state = NULL;
OCURI* tmpurl = NULL;
CURL* curl = NULL; /* curl handle*/
if(!ocuriparse(url,&tmpurl)) {OCTHROWCHK(stat=OC_EBADURL); goto fail;}
stat = occurlopen(&curl);
if(stat != OC_NOERR) {OCTHROWCHK(stat); goto fail;}
state = (OCstate*)ocmalloc(sizeof(OCstate)); /* ocmalloc zeros memory*/
if(state == NULL) {OCTHROWCHK(stat=OC_ENOMEM); goto fail;}
/* Setup DAP state*/
state->magic = OCMAGIC;
state->curl = curl;
state->trees = oclistnew();
state->uri = tmpurl;
if(!ocuridecodeparams(state->uri)) {
oc_log(LOGWARN,"Could not parse client parameters");
}
state->packet = ocbytesnew();
ocbytessetalloc(state->packet,DFALTPACKETSIZE); /*initial reasonable size*/
/* set curl properties for this link */
ocsetcurlproperties(state);
/* Set up list to support reuse/reclamation of OCcontent objects. */
state->contentlist = NULL;
if(statep) *statep = state;
return OCTHROW(stat);
fail:
ocurifree(tmpurl);
if(state != NULL) ocfree(state);
if(curl != NULL) occurlclose(curl);
return OCTHROW(stat);
}
OCerror
ocfetchf(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
OCnode** rootp)
{
OCtree* tree = NULL;
OCnode* root = NULL;
OCerror stat = OC_NOERR;
tree = (OCtree*)ocmalloc(sizeof(OCtree));
MEMCHECK(tree,OC_ENOMEM);
memset((void*)tree,0,sizeof(OCtree));
tree->dxdclass = kind;
tree->state = state;
tree->constraint = constraintescape(constraint);
if(tree->constraint == NULL)
tree->constraint = nulldup(constraint);
/* Set curl properties: pwd, flags, proxies, ssl */
if((stat=ocset_user_password(state))!= OC_NOERR) goto fail;
if((stat=ocset_curl_flags(state)) != OC_NOERR) goto fail;
if((stat=ocset_proxy(state)) != OC_NOERR) goto fail;
if((stat=ocset_ssl(state)) != OC_NOERR) goto fail;
ocbytesclear(state->packet);
switch (kind) {
case OCDAS:
stat = readDAS(state,tree);
if(stat == OC_NOERR) {
tree->text = ocbytesdup(state->packet);
if(tree->text == NULL) stat = OC_EDAS;
}
break;
case OCDDS:
stat = readDDS(state,tree);
if(stat == OC_NOERR) {
tree->text = ocbytesdup(state->packet);
if(tree->text == NULL) stat = OC_EDDS;
}
break;
case OCDATADDS:
if((flags & OCONDISK) != 0) {/* store in file */
/* Create the datadds file immediately
so that DRNO can reference it*/
/* Make the tmp file*/
stat = createtempfile(state,tree);
if(stat) {OCTHROWCHK(stat); goto unwind;}
stat = readDATADDS(state,tree,flags);
if(stat == OC_NOERR) {
/* Separate the DDS from data and return the dds;
will modify packet */
stat = ocextractddsinfile(state,tree,flags);
}
} else { /*in memory*/
stat = readDATADDS(state,tree,flags);
if(stat == OC_NOERR) {
/* Separate the DDS from data and return the dds;
will modify packet */
stat = ocextractddsinmemory(state,tree,flags);
}
}
break;
}/*switch*/
if(stat != OC_NOERR) {
/* Obtain any http code */
state->error.httpcode = ocfetchhttpcode(state->curl);
if(state->error.httpcode >= 400) {
oc_log(LOGWARN,"oc_open: Could not read url; http error = %l",state->error.httpcode);
} else {
oc_log(LOGWARN,"oc_open: Could not read url");
}
return OCTHROW(stat);
}
tree->nodes = NULL;
stat = DAPparse(state,tree,tree->text);
/* Check and report on an error return from the server */
if(stat == OC_EDAPSVC && state->error.code != NULL) {
oc_log(LOGERR,"oc_open: server error retrieving url: code=%s message=\"%s\"",
state->error.code,
(state->error.message?state->error.message:""));
}
if(stat) {OCTHROWCHK(stat); goto unwind;}
root = tree->root;
/* make sure */
tree->root = root;
root->tree = tree;
/* Verify the parse */
switch (kind) {
case OCDAS:
if(root->octype != OC_Attributeset)
{OCTHROWCHK(stat=OC_EDAS); goto unwind;}
break;
case OCDDS:
if(root->octype != OC_Dataset)
{OCTHROWCHK(stat=OC_EDDS); goto unwind;}
break;
case OCDATADDS:
if(root->octype != OC_Dataset)
{OCTHROWCHK(stat=OC_EDATADDS); goto unwind;}
/* Modify the tree kind */
tree->dxdclass = OCDATADDS;
break;
default: return OC_EINVAL;
}
if(kind != OCDAS) {
/* Process ocnodes to assign offsets and sizes where possible */
occomputeskipdata(state,root);
/* Process ocnodes to mark those that are cacheable */
ocmarkcacheable(state,root);
/* Process ocnodes to handle various semantic issues*/
occomputesemantics(tree->nodes);
}
/* Process ocnodes to compute name info*/
occomputefullnames(tree->root);
if(kind == OCDATADDS) {
if((flags & OCONDISK) != 0) {
tree->data.xdrs = xxdr_filecreate(tree->data.file,tree->data.bod);
} else {
/* Switch to zero based memory */
tree->data.xdrs
= xxdr_memcreate(tree->data.memory,tree->data.datasize,tree->data.bod);
}
MEMCHECK(tree->data.xdrs,OC_ENOMEM);
}
/* Put root into the state->trees list */
oclistpush(state->trees,(ocelem)root);
if(rootp) *rootp = root;
return stat;
unwind:
ocfreetree(tree);
fail:
return OCTHROW(stat);
}
void
occlose(OCstate* state)
{
unsigned int i;
if(state == NULL) return;
/* Warning: ocfreeroot will attempt to remove the root from state->trees */
/* Ok in this case because we are popping the root out of state->trees */
for(i=0;i<oclistlength(state->trees);i++) {
OCnode* root = (OCnode*)oclistpop(state->trees);
ocfreeroot(root);
}
oclistfree(state->trees);
ocurifree(state->uri);
ocbytesfree(state->packet);
ocfree(state->error.code);
ocfree(state->error.message);
if(state->contentlist != NULL) {
struct OCcontent* next;
struct OCcontent* curr = state->contentlist;
while(curr != NULL) {
next = curr->next;
ocfree(curr);
curr = next;
}
}
ocfree(state->curlflags.useragent);
ocfree(state->curlflags.cookiejar);
ocfree(state->curlflags.cookiefile);
ocfree(state->ssl.certificate);
ocfree(state->ssl.key);
ocfree(state->ssl.keypasswd);
ocfree(state->ssl.cainfo);
ocfree(state->ssl.capath);
ocfree(state->proxy.host);
ocfree(state->creds.username);
ocfree(state->creds.password);
if(state->curl != NULL) occurlclose(state->curl);
ocfree(state);
}
static OCerror
ocextractddsinmemory(OCstate* state, OCtree* tree, OCflags flags)
{
OCerror stat = OC_NOERR;
size_t ddslen, bod, bodfound;
/* Read until we find the separator (or EOF)*/
bodfound = findbod(state->packet,&bod,&ddslen);
if(!bodfound) {/* No BOD; pretend */
bod = tree->data.bod;
ddslen = tree->data.datasize;
}
tree->data.bod = bod;
tree->data.ddslen = ddslen;
/* copy out the dds */
if(ddslen > 0) {
tree->text = (char*)ocmalloc(ddslen+1);
memcpy((void*)tree->text,(void*)ocbytescontents(state->packet),ddslen);
tree->text[ddslen] = '\0';
} else
tree->text = NULL;
/* Extract the inmemory contents */
tree->data.memory = ocbytesextract(state->packet);
#ifdef OCIGNORE
/* guarantee the data part is on an 8 byte boundary */
if(tree->data.bod % 8 != 0) {
unsigned long count = tree->data.datasize - tree->data.bod;
memcpy(tree->xdrmemory,tree->xdrmemory+tree->data.bod,count);
tree->data.datasize = count;
tree->data.bod = 0;
tree->data.ddslen = 0;
}
#endif
if(tree->text == NULL) stat = OC_EDATADDS;
return OCTHROW(stat);
}
static OCerror
ocextractddsinfile(OCstate* state, OCtree* tree, OCflags flags)
{
OCerror stat = OC_NOERR;
size_t ddslen, bod, bodfound;
/* Read until we find the separator (or EOF)*/
ocbytesclear(state->packet);
rewind(tree->data.file);
bodfound = 0;
do {
char chunk[1024];
size_t count;
/* read chunks of the file until we find the separator*/
count = fread(chunk,1,sizeof(chunk),tree->data.file);
if(count <= 0) break; /* EOF;*/
ocbytesappendn(state->packet,chunk,count);
bodfound = findbod(state->packet,&bod,&ddslen);
} while(!bodfound);
if(!bodfound) {/* No BOD; pretend */
bod = tree->data.bod;
ddslen = tree->data.datasize;
}
tree->data.bod = bod;
tree->data.ddslen = ddslen;
/* copy out the dds */
if(ddslen > 0) {
tree->text = (char*)ocmalloc(ddslen+1);
memcpy((void*)tree->text,(void*)ocbytescontents(state->packet),ddslen);
tree->text[ddslen] = '\0';
} else
tree->text = NULL;
/* reset the position of the tmp file*/
fseek(tree->data.file,tree->data.bod,SEEK_SET);
if(tree->text == NULL) stat = OC_EDATADDS;
return OCTHROW(stat);
}
static OCerror
createtempfile(OCstate* state, OCtree* tree)
{
int fd;
char* name = NULL;
fd = createtempfile1(TMPPATH1,&name);
if(fd < 0)
fd = createtempfile1(TMPPATH2,&name);
if(fd < 0) {
oc_log(LOGERR,"oc_open: attempt to open tmp file failed: %s",name);
return errno;
}
#ifdef OCDEBUG
oc_log(LOGNOTE,"oc_open: using tmp file: %s",name);
#endif
tree->data.filename = name; /* remember our tmp file name */
tree->data.file = fdopen(fd,"w+");
if(tree->data.file == NULL) return OC_EOPEN;
/* unlink the temp file so it will automatically be reclaimed */
if(ocdebug == 0) unlink(tree->data.filename);
return OC_NOERR;
}
int
createtempfile1(char* tmppath, char** tmpnamep)
{
int fd = 0;
char* tmpname = NULL;
tmpname = (char*)malloc(strlen(tmppath)+strlen("dataddsXXXXXX")+1);
if(tmpname == NULL) return -1;
strcpy(tmpname,tmppath);
#ifdef HAVE_MKSTEMP
strcat(tmpname,"dataddsXXXXXX");
/* Note Potential problem: old versions of this function
leave the file in mode 0666 instead of 0600 */
fd = mkstemp(tmpname);
#else /* !HAVE_MKSTEMP */
/* Need to simulate by using some kind of pseudo-random number */
strcat(tmpname,"datadds");
{
int rno = rand();
char spid[7];
if(rno < 0) rno = -rno;
sprintf(spid,"%06d",rno);
strcat(tmpname,spid);
# ifdef WIN32
fd=open(tmpname,O_RDWR|O_BINARY|O_CREAT|O_EXCL|FILE_ATTRIBUTE_TEMPORARY, _S_IREAD|_S_IWRITE);
# else
fd=open(tmpname,O_RDWR|O_CREAT|O_EXCL, S_IRWXU);
# endif
}
#endif /* !HAVE_MKSTEMP */
if(tmpname == NULL) return -1;
if(tmpnamep) *tmpnamep = tmpname;
return fd;
}
/* Allow these (non-alpha-numerics) to pass thru */
static char okchars[] = "&/:;,.=?@'\"<>{}!|\\^[]`~";
static char hexdigits[] = "0123456789abcdef";
/* Modify constraint to use %XX escapes */
static char*
constraintescape(const char* url)
{
size_t len;
char* p;
int c;
char* eurl;
if(url == NULL) return NULL;
len = strlen(url);
eurl = ocmalloc(1+3*len); /* worst case: c -> %xx */
MEMCHECK(eurl,NULL);
p = eurl;
*p = '\0';
while((c=*url++)) {
if(c >= '0' && c <= '9') {*p++ = c;}
else if(c >= 'a' && c <= 'z') {*p++ = c;}
else if(c >= 'A' && c <= 'Z') {*p++ = c;}
else if(strchr(okchars,c) != NULL) {*p++ = c;}
else {
*p++ = '%';
*p++ = hexdigits[(c & 0xf0)>>4];
*p++ = hexdigits[(c & 0xf)];
}
}
*p = '\0';
return eurl;
}
OCerror
ocupdatelastmodifieddata(OCstate* state)
{
OCerror status = OC_NOERR;
long lastmodified;
char* base = NULL;
base = ocuribuild(state->uri,NULL,NULL,OCURIENCODE);
status = ocfetchlastmodified(state->curl, base, &lastmodified);
free(base);
if(status == OC_NOERR) {
state->datalastmodified = lastmodified;
}
return status;
}
/*
Set curl properties for link based on rc files
*/
static void
ocsetcurlproperties(OCstate* state)
{
CURLcode cstat = CURLE_OK;
/* process the triple store wrt to this state */
if(ocdodsrc_process(state) != OC_NOERR) {
oc_log(LOGERR,"Malformed .opendaprc configuration file");
goto fail;
}
if(state->creds.username == NULL && state->creds.password == NULL) {
if(state->uri->user != NULL && state->uri->password != NULL) {
/* this overrides .dodsrc */
if(state->creds.password) free(state->creds.password);
state->creds.password = nulldup(state->uri->password);
if(state->creds.username) free(state->creds.username);
state->creds.username = nulldup(state->uri->user);
}
}
return;
fail:
if(cstat != CURLE_OK)
oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
return;
}

View File

@ -1,198 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCINTERNAL_H
#define OCINTERNAL_H
#include "config.h"
#ifdef _AIX
#include <netinet/in.h>
#endif
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#ifndef WIN32
#include <strings.h>
#endif
#include <stdarg.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#define CURL_DISABLE_TYPECHECK 1
#include <curl/curl.h>
#include "oclist.h"
#include "ocbytes.h"
#include "ocuri.h"
#define OCCACHEPOS
#include "oc.h"
#include "ocdatatypes.h"
#include "occonstraints.h"
#include "ocnode.h"
#include "ocutil.h"
#include "oclog.h"
#include "xxdr.h"
#include "ocdata.h"
#ifndef nulldup
#define nulldup(s) (s==NULL?NULL:strdup(s))
#endif
#define nullstring(s) (s==NULL?"(null)":s)
#define PATHSEPARATOR "."
/* Default initial memory packet size */
#define DFALTPACKETSIZE 0x20000 /*approximately 100k bytes*/
/* Default maximum memory packet size */
#define DFALTMAXPACKETSIZE 0x3000000 /*approximately 50M bytes*/
/* Extend the OCdxd type */
#define OCVER 3
/* Define a magic number to mark externally visible oc objects */
#define OCMAGIC ((unsigned int)0x0c0c0c0c) /*clever, huh?*/
/*! Specifies the OCstate. */
typedef struct OCstate
{
unsigned int magic; /* Mark each structure type */
CURL* curl; /* curl handle*/
OClist* trees; /* list<OCnode*> ; all root objects */
OCURI* uri; /* base URI*/
OCbytes* packet; /* shared by all trees during construction */
/* OCContent information */
struct OCcontent* contentlist;
struct OCerrdata {/* Hold info for an error return from server */
char* code;
char* message;
long httpcode;
char curlerrorbuf[CURL_ERROR_SIZE]; /* to get curl error message */
} error;
/* Store .rc file info */
struct OCcurlflags {
int compress;
int verbose;
int timeout;
int followlocation;
int maxredirs;
char* useragent;
char* cookiejar;
char* cookiefile;
} curlflags;
struct OCSSL {
int validate;
char* certificate;
char* key;
char* keypasswd;
char* cainfo; /* certificate authority */
char* capath;
int verifypeer;
} ssl;
struct OCproxy {
char *host;
int port;
} proxy;
struct OCcredentials {
char *username;
char *password;
} creds;
long ddslastmodified;
long datalastmodified;
} OCstate;
/*! Specifies all the info about a particular DAP tree
i.e. DAS, DDS, or DATADDS as obtained from a fetch response
This is associated with the root object.
*/
typedef struct OCtree
{
OCdxd dxdclass;
char* constraint;
char* text;
struct OCnode* root; /* cross link */
struct OCstate* state; /* cross link */
OClist* nodes; /* all nodes in tree*/
/* when dxdclass == OCDATADDS */
struct {
char* memory; /* allocated memory if OC_INMEMORY is set */
char* filename;
FILE* file;
unsigned long datasize; /* xdr size on disk or in memory */
unsigned long bod; /* offset of the beginning of packet data */
unsigned long ddslen; /* length of ddslen (assert(ddslen <= bod)) */
XXDR* xdrs; /* access either memory or file */
} data;
} OCtree;
/* (Almost) All shared procedure definitions are kept here
except for: ocdebug.h ocutil.h
The true external interface is defined in oc.h
*/
/* Location: ocnode.c */
extern OCnode* ocmakenode(char* name, OCtype ptype, OCnode* root);
extern void occollectpathtonode(OCnode* node, OClist* path);
extern void occomputefullnames(OCnode* root);
extern void occomputesemantics(OClist*);
extern void ocaddattribute(OCattribute* attr, OCnode* parent);
extern OCattribute* ocmakeattribute(char* name, OCtype ptype, OClist* values);
extern size_t ocsetsize(OCnode* node);
extern OCerror occorrelate(OCnode*,OCnode*);
extern OCerror occomputeskipdata(OCstate*, OCnode*);
extern void ocmarkcacheable(OCstate* state, OCnode* ddsroot);
/* Location: dapparselex.c*/
extern int dapdebug;
extern OCerror DAPparse(OCstate*, struct OCtree*, char*);
extern char* dimnameanon(char* basename, unsigned int index);
/* Location: ceparselex.c*/
extern int cedebug;
extern OClist* CEparse(OCstate*,char* input);
/* Location: ocinternal.c*/
extern OCerror ocopen(OCstate** statep, const char* url);
extern void occlose(OCstate* state);
extern OCerror ocfetchf(OCstate*, const char*, OCdxd, OCflags, OCnode**);
/* Location: ocinternal.c */
extern int oc_network_order;
extern int oc_invert_xdr_double;
extern int ocinternalinitialize(void);
/* Location: ocnode.c */
extern void ocfreetree(OCtree* tree);
extern void ocfreeroot(OCnode* root);
extern void ocfreenodes(OClist*);
extern void ocddsclear(struct OCstate*);
extern void ocdasclear(struct OCstate*);
extern void ocdataddsclear(struct OCstate*);
extern void* oclinearize(OCtype etype, unsigned int, char**);
/* Merge DAS with DDS or DATADDS*/
extern int ocddsdasmerge(struct OCstate*, OCnode* das, OCnode* dds);
extern OCerror ocupdatelastmodifieddata(OCstate* state);
extern int ocinternalinitialize(void);
extern OCerror ocsetrcfile(char* rcfile);
/* Global stateflags */
extern int oc_curl_file_supported;
extern int oc_curl_https_supported;
#endif /*COMMON_H*/

View File

@ -1,171 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "oclist.h"
static ocelem ocDATANULL = (ocelem)0;
/*static int ocinitialized=0;*/
int oclistnull(ocelem e) {return e == ocDATANULL;}
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define DEFAULTALLOC 16
#define ALLOCINCR 16
OClist* oclistnewn(int prealloc)
{
OClist* l;
/*
if(!ocinitialized) {
memset((void*)&ocDATANULL,0,sizeof(ocelem));
ocinitialized = 1;
}
*/
if(prealloc < 0) prealloc = 0;
l = (OClist*)malloc(sizeof(OClist));
if(l) {
l->alloc=prealloc;
l->length=prealloc;
l->content=(prealloc==0?NULL:(ocelem*)calloc(prealloc,sizeof(ocelem)));
if(l == NULL) {free(l);return 0;}
}
return l;
}
int
oclistfree(OClist* l)
{
if(l) {
l->alloc = 0;
if(l->content != NULL) {free(l->content); l->content = NULL;}
free(l);
}
return TRUE;
}
int
oclistsetalloc(OClist* l, unsigned int sz)
{
ocelem* newcontent;
if(l == NULL) return FALSE;
if(sz <= 0) {sz = (l->length?2*l->length:DEFAULTALLOC);}
if(l->alloc >= sz) {return TRUE;}
newcontent=(ocelem*)calloc(sz,sizeof(ocelem));
if(l->alloc > 0 && l->length > 0 && l->content != NULL) {
memcpy((void*)newcontent,(void*)l->content,sizeof(ocelem)*l->length);
free(l->content);
}
l->content=newcontent;
l->alloc=sz;
return TRUE;
}
int
oclistsetlength(OClist* l, unsigned int sz)
{
if(l == NULL) return FALSE;
if(sz > l->alloc && !oclistsetalloc(l,sz)) return FALSE;
l->length = sz;
return TRUE;
}
ocelem
oclistget(OClist* l, unsigned int index)
{
if(l == NULL || l->length == 0) return ocDATANULL;
if(index >= l->length) return ocDATANULL;
return l->content[index];
}
int
oclistset(OClist* l, unsigned int index, ocelem elem)
{
if(l == NULL) return FALSE;
if(index >= l->length) return FALSE;
l->content[index] = elem;
return TRUE;
}
/* Insert at position i of l; will push up elements i..|seq|. */
int
oclistinsert(OClist* l, unsigned int index, ocelem elem)
{
unsigned int i;
if(l == NULL) return FALSE;
if(index > l->length) return FALSE;
oclistsetalloc(l,0);
for(i=l->length;i>index;i--) l->content[i] = l->content[i-1];
l->content[index] = elem;
l->length++;
return TRUE;
}
int
oclistpush(OClist* l, ocelem elem)
{
if(l == NULL) return FALSE;
if(l->length >= l->alloc) oclistsetalloc(l,0);
l->content[l->length] = elem;
l->length++;
return TRUE;
}
ocelem
oclistpop(OClist* l)
{
if(l == NULL || l->length == 0) return ocDATANULL;
l->length--;
return l->content[l->length];
}
ocelem
oclisttop(OClist* l)
{
if(l == NULL || l->length == 0) return ocDATANULL;
return l->content[l->length - 1];
}
ocelem
oclistremove(OClist* l, unsigned int i)
{
unsigned int len;
ocelem elem;
if(l == NULL || (len=l->length) == 0) return ocDATANULL;
if(i >= len) return ocDATANULL;
elem = l->content[i];
for(i++;i<len;i++) l->content[i-1] = l->content[i];
l->length--;
return elem;
}
/* Duplicate and return the content (null terminate) */
ocelem*
oclistdup(OClist* l)
{
ocelem* result = (ocelem*)malloc(sizeof(ocelem)*(l->length+1));
memcpy((void*)result,(void*)l->content,sizeof(ocelem)*l->length);
result[l->length] = (ocelem)0;
return result;
}
int
oclistcontains(OClist* list, ocelem elem)
{
unsigned int i;
for(i=0;i<oclistlength(list);i++) {
if(elem == oclistget(list,i)) return 1;
}
return 0;
}

View File

@ -1,57 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCLIST_H
#define OCLIST_H 1
/* Define the type of the elements in the list*/
#if defined(_CPLUSPLUS_) || defined(__CPLUSPLUS__)
#define EXTERNC extern "C"
#else
#define EXTERNC extern
#endif
typedef unsigned long ocelem;
EXTERNC int oclistnull(ocelem);
typedef struct OClist {
unsigned int alloc;
unsigned int length;
ocelem* content;
} OClist;
EXTERNC OClist* oclistnewn(int);
EXTERNC int oclistfree(OClist*);
EXTERNC int oclistsetalloc(OClist*,unsigned int);
EXTERNC int oclistsetlength(OClist*,unsigned int);
/* Set the ith element */
EXTERNC int oclistset(OClist*,unsigned int,ocelem);
/* Get value at position i */
EXTERNC ocelem oclistget(OClist*,unsigned int);/* Return the ith element of l */
/* Insert at position i; will push up elements i..|seq|. */
EXTERNC int oclistinsert(OClist*,unsigned int,ocelem);
/* Remove element at position i; will move higher elements down */
EXTERNC ocelem oclistremove(OClist* l, unsigned int i);
/* Tail operations */
EXTERNC int oclistpush(OClist*,ocelem); /* Add at Tail */
EXTERNC ocelem oclistpop(OClist*);
EXTERNC ocelem oclisttop(OClist*);
/* Duplicate and return the content (null terminate) */
EXTERNC ocelem* oclistdup(OClist*);
/* Look for value match */
EXTERNC int oclistcontains(OClist*, ocelem);
/* Following are always "in-lined"*/
#define oclistnew() oclistnewn(0)
#define oclistclear(l) oclistsetlength((l),0U)
#define oclistextend(l,len) oclistsetalloc((l),(len)+(l->alloc))
#define oclistcontents(l) ((l)->content)
#define oclistlength(l) ((l)?(l)->length:0U)
#endif /*OCLIST_H*/

View File

@ -1,132 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include "ocinternal.h"
#include <stdio.h>
#include <fcntl.h>
#define PREFIXLEN 8
#define ENVFLAG "OCLOGFILE"
static int ocloginit = 0;
static int oclogging = 0;
static char* oclogfile = NULL;
static FILE* oclogstream = NULL;
void
oc_loginit(void)
{
ocloginit = 1;
oc_setlogging(0);
oclogfile = NULL;
oclogstream = NULL;
/* Use environment variables to preset oclogging state*/
/* I hope this is portable*/
if(getenv(ENVFLAG) != NULL) {
const char* file = getenv(ENVFLAG);
oc_setlogging(1);
oc_logopen(file);
}
}
void
oc_setlogging(int tf)
{
if(!ocloginit) oc_loginit();
oclogging = tf;
}
void
oc_logopen(const char* file)
{
if(!ocloginit) oc_loginit();
if(oclogfile != NULL) {
fclose(oclogstream);
free(oclogfile);
oclogfile = NULL;
}
if(file == NULL || strlen(file) == 0) {
/* use stderr*/
oclogstream = stderr;
oclogfile = NULL;
} else {
int fd;
oclogfile = (char*)malloc(strlen(file)+1);
strcpy(oclogfile,file);
oclogstream = NULL;
/* We need to deal with this file carefully
to avoid unauthorized access*/
fd = open(oclogfile,O_WRONLY|O_APPEND|O_CREAT,0600);
if(fd >= 0) {
oclogstream = fdopen(fd,"a");
} else {
free(oclogfile);
oclogfile = NULL;
oc_setlogging(0);
}
}
}
void
oc_logclose(void)
{
if(oclogfile != NULL && oclogstream != NULL) {
fclose(oclogstream);
oclogstream = NULL;
if(oclogfile != NULL) free(oclogfile);
oclogfile = NULL;
}
}
void
oc_log(int tag, const char* fmt, ...)
{
va_list args;
char* prefix;
if(!oclogging || oclogstream == NULL) return;
switch (tag) {
case LOGWARN: prefix = "Warning:"; break;
case LOGERR: prefix = "Error: "; break;
case LOGNOTE: prefix = "Note: "; break;
case LOGDBG: prefix = "Debug: "; break;
default:
fprintf(oclogstream,"Error: Bad log prefix: %d\n",tag);
prefix = "Error: ";
break;
}
fprintf(oclogstream,"%s:",prefix);
if(fmt != NULL) {
va_start(args, fmt);
vfprintf(oclogstream, fmt, args);
va_end( args );
}
fprintf(oclogstream, "\n" );
fflush(oclogstream);
}
void
oc_logtext(int tag, const char* text)
{
char line[1024];
size_t delta = 0;
const char* eol = text;
if(!oclogging || oclogstream == NULL) return;
while(*text) {
eol = strchr(text,'\n');
if(eol == NULL)
delta = strlen(text);
else
delta = (eol - text);
if(delta > 0) memcpy(line,text,delta);
line[delta] = '\0';
fprintf(oclogstream," %s\n",line);
text = eol+1;
}
}

View File

@ -1,20 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCLOG_H
#define OCLOG_H
#define LOGNOTE 0
#define LOGWARN 1
#define LOGERR 2
#define LOGDBG 3
extern void oc_loginit(void);
extern void oc_setlogging(int tf);
extern void oc_logopen(const char* file);
extern void oc_logclose(void);
extern void oc_log(int tag, const char* fmt, ...);
extern void oc_logtext(int tag, const char* text);
#endif /*OCLOG_H*/

View File

@ -1,757 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include "ocinternal.h"
#include "ocdebug.h"
static const unsigned int MAX_UINT = 0xffffffff;
static OCerror occomputeskipdatar(OCstate*, OCnode*, ocoffset_t offset);
static int mergedas1(OCnode* dds, OCnode* das);
static int converttype(OCtype etype, char* value, char* memory);
static char* pathtostring(OClist* path, char* separator, int usecdfname);
static void computefullname(OCnode* node);
/* Process ocnodes to fix various semantic issues*/
void
occomputesemantics(OClist* ocnodes)
{
unsigned int i;
OCASSERT((ocnodes != NULL));
for(i=0;i<oclistlength(ocnodes);i++) {
OCnode* node = (OCnode*)oclistget(ocnodes,i);
/* set the container for dims*/
if(node->octype == OC_Dimension && node->dim.array != NULL) {
node->container = node->dim.array->container;
}
}
}
void
occomputefullnames(OCnode* root)
{
unsigned int i;
if(root->name != NULL) computefullname(root);
if(root->subnodes != NULL) { /* recurse*/
for(i=0;i<oclistlength(root->subnodes);i++) {
OCnode* node = (OCnode*)oclistget(root->subnodes,i);
occomputefullnames(node);
}
}
}
static void
computefullname(OCnode* node)
{
char* tmp;
char* fullname;
OClist* path;
OCASSERT((node->name != NULL));
path = oclistnew();
occollectpathtonode(node,path);
tmp = pathtostring(path,PATHSEPARATOR,1);
if(tmp == NULL) {
fullname = nulldup(node->name);
} else {
fullname = tmp;
}
node->fullname = fullname;
oclistfree(path);
}
/* Convert path to a string; leave off the dataset name*/
static char*
pathtostring(OClist* path, char* separator, int usecdfname)
{
int slen,i,len;
char* pathname;
if(path == NULL || (len = oclistlength(path))==0) return NULL;
for(slen=0,i=0;i<len;i++) {
OCnode* node = (OCnode*)oclistget(path,i);
if(node->container == NULL || node->name == NULL) continue;
slen += strlen(node->name);
}
slen += ((len-1)*strlen(separator));
slen += 1; /* for null terminator*/
pathname = (char*)ocmalloc(slen);
MEMCHECK(pathname,NULL);
pathname[0] = '\0';
for(i=0;i<len;i++) {
OCnode* node = (OCnode*)oclistget(path,i);
if(node->container == NULL || node->name == NULL) continue;
if(strlen(pathname) > 0) strcat(pathname,separator);
strcat(pathname,node->name);
}
return pathname;
}
/* Collect the set of nodes ending in "node"*/
void
occollectpathtonode(OCnode* node, OClist* path)
{
if(node == NULL) return;
occollectpathtonode(node->container,path);
oclistpush(path,(ocelem)node);
}
OCnode*
ocmakenode(char* name, OCtype ptype, OCnode* root)
{
OCnode* cdf = (OCnode*)ocmalloc(sizeof(OCnode));
MEMCHECK(cdf,(OCnode*)NULL);
memset((void*)cdf,0,sizeof(OCnode));
cdf->magic = OCMAGIC;
cdf->name = (name?nulldup(name):NULL);
cdf->octype = ptype;
cdf->array.dimensions = NULL;
cdf->root = root;
return cdf;
}
OCattribute*
makeattribute(char* name, OCtype ptype, OClist* values)
{
OCattribute* att = (OCattribute*)ocmalloc(sizeof(OCattribute)); /* ocmalloc zeros*/
MEMCHECK(att,(OCattribute*)NULL);
att->name = nulldup(name);
att->etype = ptype;
att->nvalues = oclistlength(values);
att->values = NULL;
if(att->nvalues > 0) {
int i;
att->values = (char**)ocmalloc(sizeof(char*)*att->nvalues);
for(i=0;i<att->nvalues;i++)
att->values[i] = nulldup((char*)oclistget(values,i));
}
return att;
}
static void
marklostattribute(OCnode* att)
{
oc_log(LOGWARN,"Lost attribute: %s",att->name);
}
void*
oclinearize(OCtype etype, unsigned int nstrings, char** strings)
{
int i;
size_t typesize;
char* memp;
char* memory;
if(nstrings == 0) return NULL;
typesize = octypesize(etype);
memory = (char*)ocmalloc(nstrings*typesize);
MEMCHECK(memory,NULL);
memp = memory;
for(i=0;i<nstrings;i++) {
char* value = strings[i];
converttype(etype,value,memp);
memp += typesize;
}
return memory;
}
static int
converttype(OCtype etype, char* value, char* memory)
{
long iv;
unsigned long uiv;
double dv;
char c[1];
int outofrange = 0;
#ifdef HAVE_LONG_LONG_INT
long long llv;
unsigned long long ullv;
#endif
switch (etype) {
case OC_Char:
if(sscanf(value,"%c",c) != 1) goto fail;
*((char*)memory) = c[0];
break;
case OC_Byte:
if(sscanf(value,"%ld",&iv) != 1) goto fail;
else if(iv > OC_BYTE_MAX || iv < OC_BYTE_MIN) {iv = OC_BYTE_MAX; outofrange = 1;}
*((signed char*)memory) = (signed char)iv;
break;
case OC_UByte:
if(sscanf(value,"%lu",&uiv) != 1) goto fail;
else if(uiv > OC_UBYTE_MAX) {uiv = OC_UBYTE_MAX; outofrange = 1;}
*((unsigned char*)memory) = (unsigned char)uiv;
break;
case OC_Int16:
if(sscanf(value,"%ld",&iv) != 1) goto fail;
else if(iv > OC_INT16_MAX || iv < OC_INT16_MIN) {iv = OC_INT16_MAX; outofrange = 1;}
*((signed short*)memory) = (signed short)iv;
break;
case OC_UInt16:
if(sscanf(value,"%lu",&uiv) != 1) goto fail;
else if(uiv > OC_UINT16_MAX) {uiv = OC_UINT16_MAX; outofrange = 1;}
*((unsigned short*)memory) = (unsigned short)uiv;
break;
case OC_Int32:
if(sscanf(value,"%ld",&iv) != 1) goto fail;
else if(iv > OC_INT32_MAX || iv < OC_INT32_MIN) {iv = OC_INT32_MAX; outofrange = 1;}
*((signed int*)memory) = (signed int)iv;
break;
case OC_UInt32:
if(sscanf(value,"%lu",&uiv) != 1) goto fail;
else if(uiv > OC_UINT32_MAX) {uiv = OC_UINT32_MAX; outofrange = 1;}
*((unsigned char*)memory) = (unsigned int)uiv;
break;
#ifdef HAVE_LONG_LONG_INT
case OC_Int64:
if(sscanf(value,"%lld",&llv) != 1) goto fail;
/*else if(iv > OC_INT64_MAX || iv < OC_INT64_MIN) goto fail;*/
*((signed long long*)memory) = (signed long long)llv;
break;
case OC_UInt64:
if(sscanf(value,"%llu",&ullv) != 1) goto fail;
*((unsigned long long*)memory) = (unsigned long long)ullv;
break;
#endif
case OC_Float32:
if(sscanf(value,"%lf",&dv) != 1) goto fail;
*((float*)memory) = (float)dv;
break;
case OC_Float64:
if(sscanf(value,"%lf",&dv) != 1) goto fail;
*((double*)memory) = (double)dv;
break;
case OC_String: case OC_URL:
*((char**)memory) = nulldup(value);
break;
default:
goto fail;
}
if(outofrange)
oc_log(LOGWARN,"converttype range failure: %d: %s",etype,value);
return 1;
fail:
oc_log(LOGERR,"converttype bad value: %d: %s",etype,value);
return 0;
}
void
ocfreeroot(OCnode* root)
{
OCtree* tree;
OCstate* state;
int i;
if(root == NULL || root->tree == NULL) return;
tree = root->tree;
/* Remove the root from the state->trees list */
state = tree->state;
for(i=0;i<oclistlength(state->trees);i++) {
OCnode* node = (OCnode*)oclistget(state->trees,i);
if(root == node)
oclistremove(state->trees,i);
}
/* Note: it is ok if state->trees does not contain this root */
ocfreetree(tree);
}
void
ocfreetree(OCtree* tree)
{
if(tree == NULL) return;
ocfreenodes(tree->nodes);
ocfree(tree->constraint);
ocfree(tree->text);
if(tree->data.xdrs != NULL) {
xxdr_free(tree->data.xdrs);
}
ocfree(tree->data.filename); /* may be null */
if(tree->data.file != NULL) fclose(tree->data.file);
ocfree(tree->data.memory);
ocfree(tree);
}
void
ocfreenodes(OClist* nodes)
{
unsigned int i,j;
for(i=0;i<oclistlength(nodes);i++) {
OCnode* node = (OCnode*)oclistget(nodes,i);
ocfree(node->name);
ocfree(node->fullname);
while(oclistlength(node->att.values) > 0) {
char* value = (char*)oclistpop(node->att.values);
ocfree(value);
}
while(oclistlength(node->attributes) > 0) {
OCattribute* attr = (OCattribute*)oclistpop(node->attributes);
ocfree(attr->name);
/* If the attribute type is string, then we need to free them*/
if(attr->etype == OC_String || attr->etype == OC_URL) {
char** strings = (char**)attr->values;
for(j=0;j<attr->nvalues;j++) {ocfree(*strings); strings++;}
}
ocfree(attr->values);
ocfree(attr);
}
if(node->array.dimensions != NULL) oclistfree(node->array.dimensions);
if(node->subnodes != NULL) oclistfree(node->subnodes);
if(node->att.values != NULL) oclistfree(node->att.values);
if(node->attributes != NULL) oclistfree(node->attributes);
ocfree(node);
}
oclistfree(nodes);
}
/*
In order to be as compatible as possible with libdap,
we try to use the same algorithm for DAS->DDS matching.
As described there, the algorithm is as follows.
If the [attribute] name contains one or
more field separators then look for a [DDS]variable whose
name matches exactly. If the name contains no field separators then
the look first in the top level [of the DDS] and then in all subsequent
levels and return the first occurrence found. In general, this
searches constructor types in the order in which they appear
in the DDS, but there is no requirement that it do so.
Note: If a dataset contains two constructor types which have field names
that are the same (say point.x and pair.x) one should use fully qualified
names to get each of those variables.
*/
int
ocddsdasmerge(OCstate* state, OCnode* dasroot, OCnode* ddsroot)
{
OClist* dasglobals = oclistnew();
OClist* dasnodes = oclistnew();
OClist* varnodes = oclistnew();
OClist* ddsnodes;
unsigned int i,j;
if(dasroot->tree == NULL || dasroot->tree->dxdclass != OCDAS)
return OCTHROW(OC_EINVAL);
if(ddsroot->tree == NULL || (ddsroot->tree->dxdclass != OCDDS
&& ddsroot->tree->dxdclass != OCDATADDS))
return OCTHROW(OC_EINVAL);
ddsnodes = ddsroot->tree->nodes;
/* 1. collect all the relevant DAS nodes;
namely those that contain at least one
attribute value.
Simultaneously look for potential ambiguities
if found; complain but continue: result are indeterminate.
also collect globals separately*/
for(i=0;i<oclistlength(dasroot->tree->nodes);i++) {
OCnode* das = (OCnode*)oclistget(dasroot->tree->nodes,i);
int hasattributes = 0;
if(das->octype == OC_Attribute) continue; /* ignore these for now*/
if(das->name == NULL || das->att.isglobal) {
oclistpush(dasglobals,(ocelem)das);
continue;
}
for(j=0;j<oclistlength(das->subnodes);j++) {
OCnode* subnode = (OCnode*)oclistget(das->subnodes,j);
if(subnode->octype == OC_Attribute) {hasattributes = 1; break;}
}
if(hasattributes) {
/* Look for previously collected nodes with same name*/
for(j=0;j<oclistlength(dasnodes);j++) {
OCnode* das2 = (OCnode*)oclistget(dasnodes,j);
if(das->name == NULL || das2->name == NULL) continue;
if(strcmp(das->name,das2->name)==0) {
oc_log(LOGWARN,"oc_mergedas: potentially ambiguous DAS name: %s",das->name);
}
}
oclistpush(dasnodes,(ocelem)das);
}
}
/* 2. collect all the leaf DDS nodes (of type OC_Primitive)*/
for(i=0;i<oclistlength(ddsnodes);i++) {
OCnode* dds = (OCnode*)oclistget(ddsnodes,i);
if(dds->octype == OC_Primitive) oclistpush(varnodes,(ocelem)dds);
}
/* 3. For each das node, locate matching DDS node(s) and attach
attributes to the DDS node(s).
Match means:
1. DAS->fullname :: DDS->fullname
2. DAS->name :: DDS->fullname (support DAS names with embedded '.'
3. DAS->name :: DDS->name
*/
for(i=0;i<oclistlength(dasnodes);i++) {
OCnode* das = (OCnode*)oclistget(dasnodes,i);
for(j=0;j<oclistlength(varnodes);j++) {
OCnode* dds = (OCnode*)oclistget(varnodes,j);
if(strcmp(das->fullname,dds->fullname)==0
|| strcmp(das->name,dds->fullname)==0
|| strcmp(das->name,dds->name)==0) {
mergedas1(dds,das);
/* remove from dasnodes list*/
oclistset(dasnodes,i,(ocelem)NULL);
}
}
}
/* 4. If there are attributes left, then complain about them being lost.*/
for(i=0;i<oclistlength(dasnodes);i++) {
OCnode* das = (OCnode*)oclistget(dasnodes,i);
if(das != NULL) marklostattribute(das);
}
/* 5. Assign globals*/
for(i=0;i<oclistlength(dasglobals);i++) {
OCnode* das = (OCnode*)oclistget(dasglobals,i);
mergedas1(ddsroot,das);
}
/* cleanup*/
oclistfree(dasglobals);
oclistfree(dasnodes);
oclistfree(varnodes);
return OCTHROW(OC_NOERR);
}
static int
mergedas1(OCnode* dds, OCnode* das)
{
unsigned int i;
int stat = OC_NOERR;
if(das == NULL) return OC_NOERR; /* nothing to do */
if(dds->attributes == NULL) dds->attributes = oclistnew();
/* assign the simple attributes in the das set to this dds node*/
for(i=0;i<oclistlength(das->subnodes);i++) {
OCnode* attnode = (OCnode*)oclistget(das->subnodes,i);
if(attnode->octype == OC_Attribute) {
OCattribute* att = makeattribute(attnode->name,
attnode->etype,
attnode->att.values);
oclistpush(dds->attributes,(ocelem)att);
}
}
return OCTHROW(stat);
}
#ifdef OCIGNORE
int
ocddsdasmerge(OCstate* state, OCnode* ddsroot, OCnode* dasroot)
{
int i,j;
int stat = OC_NOERR;
OClist* globals = oclistnew();
if(dasroot == NULL) return OCTHROW(stat);
/* Start by looking for global attributes*/
for(i=0;i<oclistlength(dasroot->subnodes);i++) {
OCnode* node = (OCnode*)oclistget(dasroot->subnodes,i);
if(node->att.isglobal) {
for(j=0;j<oclistlength(node->subnodes);j++) {
OCnode* attnode = (OCnode*)oclistget(node->subnodes,j);
Attribute* att = makeattribute(attnode->name,
attnode->etype,
attnode->att.values);
oclistpush(globals,(ocelem)att);
}
}
}
ddsroot->attributes = globals;
/* Now try to match subnode names with attribute set names*/
for(i=0;i<oclistlength(dasroot->subnodes);i++) {
OCnode* das = (OCnode*)oclistget(dasroot->subnodes,i);
int match = 0;
if(das->att.isglobal) continue;
if(das->octype == OC_Attributeset) {
for(j=0;j<oclistlength(ddsroot->subnodes) && !match;j++) {
OCnode* dds = (OCnode*)oclistget(ddsroot->subnodes,j);
if(strcmp(das->name,dds->name) == 0) {
match = 1;
stat = mergedas1(dds,das);
if(stat != OC_NOERR) break;
}
}
}
if(!match) {marklostattribute(das);}
}
if(stat == OC_NOERR) ddsroot->attributed = 1;
return OCTHROW(stat);
}
/* Merge das attributes into the dds node*/
static int
mergedas1(OCnode* dds, OCnode* das)
{
int i,j;
int stat = OC_NOERR;
if(dds->attributes == NULL) dds->attributes = oclistnew();
/* assign the simple attributes in the das set to this dds node*/
for(i=0;i<oclistlength(das->subnodes);i++) {
OCnode* attnode = (OCnode*)oclistget(das->subnodes,i);
if(attnode->octype == OC_Attribute) {
Attribute* att = makeattribute(attnode->name,
attnode->etype,
attnode->att.values);
oclistpush(dds->attributes,(ocelem)att);
}
}
/* Try to merge any enclosed sets with subnodes of dds*/
for(i=0;i<oclistlength(das->subnodes);i++) {
OCnode* dasnode = (OCnode*)oclistget(das->subnodes,i);
int match = 0;
if(dasnode->octype == OC_Attribute) continue; /* already dealt with above*/
for(j=0;j<oclistlength(dds->subnodes) && !match;j++) {
OCnode* ddsnode = (OCnode*)oclistget(dds->subnodes,j);
if(strcmp(dasnode->name,ddsnode->name) == 0) {
match = 1;
stat = mergedas1(ddsnode,dasnode);
if(stat != OC_NOERR) break;
}
}
if(!match) {marklostattribute(dasnode);}
}
return OCTHROW(stat);
}
#endif
static void
ocuncorrelate(OCnode* root)
{
OCtree* tree = root->tree;
unsigned int i;
if(tree == NULL) return;
for(i=0;i<oclistlength(tree->nodes);i++) {
OCnode* node = (OCnode*)oclistget(tree->nodes,i);
node->datadds = NULL;
}
}
static OCerror
occorrelater(OCnode* dds, OCnode* dxd)
{
int i,j;
OCerror ocstat = OC_NOERR;
if(dds->octype != dxd->octype) {
OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
}
if(dxd->name != NULL && dxd->name != NULL
&& strcmp(dxd->name,dds->name) != 0) {
OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
} else if(dxd->name != dxd->name) { /* test NULL==NULL */
OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
}
if(dxd->array.rank != dds->array.rank) {
OCTHROWCHK((ocstat = OC_EINVAL)); goto fail;
}
dds->datadds = dxd;
switch (dds->octype) {
case OC_Dataset:
case OC_Structure:
case OC_Grid:
case OC_Sequence:
/* Remember: there may be fewer datadds fields than dds fields */
for(i=0;i<oclistlength(dxd->subnodes);i++) {
OCnode* dxd1 = (OCnode*)oclistget(dxd->subnodes,i);
for(j=0;j<oclistlength(dds->subnodes);j++) {
OCnode* dds1 = (OCnode*)oclistget(dds->subnodes,j);
if(strcmp(dxd1->name,dds1->name) == 0) {
ocstat = occorrelater(dds1,dxd1);
if(ocstat != OC_NOERR) {OCTHROWCHK(ocstat); goto fail;}
break;
}
}
}
break;
case OC_Dimension:
case OC_Primitive:
break;
default: OCPANIC1("unexpected node type: %d",dds->octype);
}
/* Correlate the dimensions */
if(dds->array.rank > 0) {
for(i=0;i<oclistlength(dxd->subnodes);i++) {
OCnode* ddsdim = (OCnode*)oclistget(dds->array.dimensions,i);
OCnode* dxddim = (OCnode*)oclistget(dxd->array.dimensions,i);
ocstat = occorrelater(ddsdim,dxddim);
if(!ocstat) goto fail;
}
}
fail:
return OCTHROW(ocstat);
}
OCerror
occorrelate(OCnode* dds, OCnode* dxd)
{
if(dds == NULL || dxd == NULL) return OC_EINVAL;
ocuncorrelate(dds);
return occorrelater(dds,dxd);
}
/*
Mark cacheable those primitive String/URL typed nodes
that are contained only in structures with rank > 0.
*/
void
ocmarkcacheable(OCstate* state, OCnode* ddsroot)
{
int i,j;
#ifdef OCIGNORE
int ok;
#endif
OClist* treenodes = ddsroot->tree->nodes;
OClist* path = oclistnew();
for(i=0;i<oclistlength(treenodes);i++) {
OCnode* node = (OCnode*)oclistget(treenodes,i);
if(node->octype != OC_Primitive) continue;
if(node->etype != OC_String && node->etype != OC_URL) continue;
/* collect node path */
oclistclear(path);
occollectpathtonode(node,path);
#ifdef OCIGNORE
ok = 1;
#endif
for(j=1;j<oclistlength(path)-1;j++) {/* skip top level dataset and node itself*/
OCnode* pathnode = (OCnode*)oclistget(path,j);
if(pathnode->octype != OC_Structure
|| pathnode->array.rank > 0) {
#ifdef OCIGNORE
ok=0;
#endif
break;
}
}
#ifdef OCIGNORE
if(ok) {
node->cache.cacheable = 1;
node->cache.valid = 0;
}
#endif
}
oclistfree(path);
}
/*
Fill in the OCnode.skip fields
*/
OCerror
occomputeskipdata(OCstate* state, OCnode* ddsroot)
{
OCerror stat = OC_NOERR;
OCASSERT(ddsroot->octype == OC_Dataset);
stat = occomputeskipdatar(state,ddsroot,0);
return stat;
}
/* Recursive helper for computeskipdata */
static OCerror
occomputeskipdatar(OCstate* state, OCnode* xnode, ocoffset_t offset)
{
OCerror stat = OC_NOERR;
int i,nfields;
int scalar = 0;
ocoffset_t instancesize = 0;
ocoffset_t totalsize = 0;
scalar = (xnode->array.rank == 0 ? 1 : 0);
/* Set skip count and offset*/
if(xnode->octype == OC_Sequence)
xnode->skip.count = OCINDETERMINATE;
else
xnode->skip.count = totaldimsize(xnode);
xnode->skip.offset = offset; /* possibly overridden below */
switch (xnode->octype) {
case OC_Primitive:
switch(xnode->etype) {
case OC_String: case OC_URL:
instancesize = OCINDETERMINATE;
totalsize = OCINDETERMINATE;
break;
case OC_Char: case OC_Byte: case OC_UByte:
if(!scalar) {/*=>packed*/
instancesize = octypesize(xnode->etype);
totalsize = instancesize * xnode->skip.count;
totalsize = RNDUP(totalsize);
totalsize += 2*XDRUNIT; /* overhead is double count */
break;
}
/* !packed => singleton char object */
/* fall thru */
case OC_Int16: case OC_UInt16:
case OC_Int32: case OC_UInt32:
case OC_Int64: case OC_UInt64:
case OC_Float32: case OC_Float64:
instancesize = octypesize(xnode->etype);
instancesize = RNDUP(instancesize); /* make multiple of XDRUNIT */
totalsize = (instancesize*xnode->skip.count); /* overhead is double count */
if(!scalar)
totalsize += 2*XDRUNIT; /* overhead is double count */
break;
default:
OCPANIC("unexpected etype"); /* better not happen */
}
break;
case OC_Sequence:
offset = (xnode->skip.offset = OCINDETERMINATE); /* do not know field offsets for arbitrary record */
case OC_Dataset:
case OC_Grid:
case OC_Structure:
/* Compute size of each field and sum */
nfields = oclistlength(xnode->subnodes);
instancesize = 0; /* of structure as a whole */
for(i=0;i<nfields;i++) {
OCnode* subnode = (OCnode*)oclistget(xnode->subnodes,i);
ocoffset_t fieldsize;
if(offset == OCINDETERMINATE || instancesize == OCINDETERMINATE)
stat = occomputeskipdatar(state,subnode,OCINDETERMINATE);
else
stat = occomputeskipdatar(state,subnode,offset+instancesize);
if(stat != OC_NOERR) goto done;
fieldsize = subnode->skip.totalsize;
if(instancesize == OCINDETERMINATE || fieldsize == OCINDETERMINATE)
instancesize = OCINDETERMINATE;
else
instancesize += fieldsize;
}
if(instancesize != OCINDETERMINATE) {
instancesize = RNDUP(instancesize); /* make multiple of XDRUNIT */
totalsize = (instancesize*xnode->skip.count); /* overhead is single count */
if(!scalar)
totalsize += XDRUNIT; /* overhead is single count */
} else {
totalsize = OCINDETERMINATE;
}
if(xnode->octype == OC_Sequence) {
totalsize = OCINDETERMINATE;
offset = OCINDETERMINATE;
}
break;
default: OCPANIC("unexpected octype"); /* better not happen */
}
xnode->skip.offset = offset;
xnode->skip.instancesize = instancesize;
xnode->skip.totalsize = totalsize;
done:
return stat;
}

View File

@ -1,81 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCNODE_H
#define OCNODE_H
/*! Specifies the Diminfo. */
/* Track info purely about declared dimensions.
More information is included in the Dimdata structure (dim.h)
*/
typedef struct OCdiminfo {
struct OCnode* array; /* defining array node (if known)*/
unsigned int arrayindex;/* rank position ofthis dimension in the array*/
ocindex_t declsize; /* from DDS*/
} OCdiminfo;
/*! Specifies the Arrayinfo.*/
typedef struct OCarrayinfo {
/* The complete set of dimension info applicable to this node*/
OClist* dimensions;
/* convenience (because they are computed so often*/
unsigned int rank; /* == |dimensions|*/
} OCarrayinfo;
/*! Specifies Attribute info */
typedef struct OCattribute {
char* name;
OCtype etype; /* type of the attribute */
size_t nvalues;
char** values; /* |values| = nvalues*sizeof(char**)*/
} OCattribute;
/*! Specifies the Attinfo.*/
/* This is the form as it comes out of the DAS parser*/
typedef struct OCattinfo {
int isglobal; /* is this supposed to be a global attribute set?*/
OClist* values; /* oclist<char*>*/
} OCattinfo;
/*! Specifies the OCnode. */
typedef struct OCnode {
unsigned int magic;
OCtype octype;
OCtype etype; /* essentially the dap type from the dds*/
char* name;
char* fullname;
struct OCnode* container; /* this node is subnode of container */
struct OCnode* root; /* root node of tree containing this node */
struct OCtree* tree; /* !NULL iff this is a root node */
struct OCnode* datadds; /* correlated datadds node, if any */
OCdiminfo dim; /* octype == OC_Dimension*/
OCarrayinfo array; /* octype == {OC_Structure, OC_Primitive}*/
OCattinfo att; /* octype == OC_Attribute */
/* primary edge info*/
OClist* subnodes; /*oclist<OCnode*>*/
/*int attributed;*/ /* 1 if merge was done*/
OClist* attributes; /* oclist<OCattribute*>*/
struct OCSKIP {/* Support fast skipping ; in following, 0 => undefined */
ocindex_t count; /* no. instances (== dimension cross product); may be indeterminate*/
ocoffset_t instancesize;/*size of single instance; may be indeterminate*/
ocoffset_t totalsize; /* usually: count*instancesize + overhead; may be indeterminate */
ocoffset_t offset; /* mostly for debugging */
} skip;
#ifdef OCIGNORE
struct {/* do simple index cache */
int cacheable; /* is this object cacheable? */
int valid; /* is this cache valid */
ocindex_t index; /* last index */
ocoffset_t offset; /* position of the last indexed instance */
} cache;
#endif
} OCnode;
#if SIZEOF_SIZE_T == 4
#define OCINDETERMINATE ((size_t)0xffffffff)
#endif
#if SIZEOF_SIZE_T == 8
#define OCINDETERMINATE ((size_t)0xffffffffffffffff)
#endif
#endif /*OCNODE_H*/

548
oc/ocrc.c
View File

@ -1,548 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ocinternal.h"
#include "ocdebug.h"
#include "ocdata.h"
#include "occontent.h"
#include "oclog.h"
#include "ocrc.h"
#define RTAG ']'
#define LTAG '['
#define TRIMCHARS " \t\r\n"
#define TRIM(x) rctrimright(rctrimleft((x),TRIMCHARS),TRIMCHARS)
#define HTTPPREFIXDEPRECATED "CURL."
#define HTTPPREFIX "HTTP."
/* the .dodsrc triple store */
struct OCTriplestore* ocdodsrc = NULL;
static int parseproxy(OCstate* state, char* v);
static int rcreadline(FILE* f, char* more, int morelen);
static char* rctrimright(char* more, char* trimchars);
static char* rctrimleft(char* more, char* trimchars);
static void ocdodsrcdump(char* msg, struct OCTriple*, int ntriples);
static char* curllookup(char* suffix,char* url);
/* The Username and password are in the URL if the URL is of the form:
* http://<name>:<passwd>@<host>/....
*/
int
occredentials_in_url(const char *url)
{
char *pos = strstr(url, "http://");
if (!pos)
return 0;
pos += 7;
if (strchr(pos, '@') && strchr(pos, ':'))
return 1;
return 0;
}
int
ocextract_credentials(const char *url, char **name, char **pw, char **result_url)
{
char *pos;
char *end;
char *middle;
int up_len = 0;
int mid_len = 0;
int midpas_len = 0;
int url_len = 0;
if (strchr(url, '@')) {
pos = strstr(url, "http://");
if (pos)
pos += 7;
middle = strchr(pos, ':');
mid_len = middle - pos;
*name = malloc(sizeof(char) * (mid_len + 1));
strncpy(*name, pos, mid_len);
(*name)[mid_len] = '\0';
if (middle)
middle += 1;
end = strchr(middle, '@');
midpas_len = end - middle;
*pw = malloc(sizeof(char) * (midpas_len + 1));
strncpy(*pw, middle, midpas_len);
(*pw)[midpas_len] = '\0';
up_len = end - pos;
url_len = strlen(url) - up_len;
*result_url = malloc(sizeof(char) * (url_len + 1));
if (!result_url)
return OC_ENOMEM;
strncpy(*result_url, url, pos - url);
strncpy(*result_url + (pos - url), end + 1, url_len - (pos - url));
#if 0
fprintf(stderr, "URL without username and password: %s:%d\n", sURL, url_len );
fprintf(stderr, "URL username and password: %s:%d\n", sUP, up_len);
fprintf(stderr, "URL username: %s:%d\n", sUser, mid_len);
fprintf(stderr, "URL password: %s:%d\n", sPassword, midpas_len);
#endif
(*result_url)[url_len] = '\0';
return OC_NOERR;
}
else {
return OC_EIO;
}
}
static int
rcreadline(FILE* f, char* more, int morelen)
{
int i = 0;
int c = getc(f);
if(c < 0) return 0;
for(;;) {
if(i < morelen) /* ignore excess characters */
more[i++]=c;
c = getc(f);
if(c < 0) break; /* eof */
if(c == '\n') break; /* eol */
}
/* null terminate more */
more[i] = '\0';
return 1;
}
/* Trim specified characters from front/left */
static char*
rctrimleft(char* more, char* trimchars)
{
char* p = more;
int c;
while((c=*p) != '\0') {if(strchr(trimchars,c) != NULL) p++; else break;}
return p;
}
/* Trim specified characters from end/right */
static char*
rctrimright(char* more, char* trimchars)
{
int len = strlen(more);
char* p = more + (len - 1);
while(p != more) {if(strchr(trimchars,*p) != NULL) p--; else break;}
/* null terminate */
p[1] = '\0';
return more;
}
static int
parseproxy(OCstate* state, char* v)
{
char *host_pos = NULL;
char *port_pos = NULL;
if(strlen(v) == 0) return OC_NOERR; /* nothing there*/
if (occredentials_in_url(v)) {
char *result_url = NULL;
ocextract_credentials(v, &state->creds.username,
&state->creds.password,
&result_url);
v = result_url;
}
/* allocating a bit more than likely needed ... */
host_pos = strstr(v, "http://");
if (host_pos)
host_pos += strlen("http://");
else
host_pos = v;
port_pos = strchr(host_pos, ':');
if (port_pos) {
int host_len;
char *port_sep = port_pos;
port_pos++;
*port_sep = '\0';
host_len = strlen(host_pos);
state->proxy.host = malloc(sizeof(char) * host_len + 1);
if (!state->proxy.host)
return OC_ENOMEM;
strncpy(state->proxy.host, host_pos, host_len);
state->proxy.host[host_len] = '\0';
state->proxy.port = atoi(port_pos);
} else {
int host_len = strlen(host_pos);
state->proxy.host = malloc(sizeof(char) * host_len + 1);
if (!state->proxy.host)
return OC_ENOMEM;
strncpy(state->proxy.host, host_pos, host_len);
state->proxy.host[host_len] = '\0';
state->proxy.port = 80;
}
#if 0
state->proxy.host[v_len] = '\0';
state->proxy.port = atoi(v);
s_len = strlen(v);
state->proxy.user = malloc(sizeof(char) * s_len + 1);
if (!state->proxy.user)
return OC_ENOMEM;
strncpy(state->proxy.user, v, s_len);
state->proxy.user[s_len] = '\0';
p_len = strlen(v);
state->proxy.password = malloc(sizeof(char) * p_len + 1);
if (!state->proxy.password)
return OC_ENOMEM;
strncpy(state->proxy.password, v, p_len);
state->proxy.password[p_len] = '\0';
#endif /*0*/
if (ocdebug > 1) {
oc_log(LOGNOTE,"host name: %s", state->proxy.host);
oc_log(LOGNOTE,"user name: %s", state->creds.username);
#ifdef INSECURE
oc_log(LOGNOTE,"password: %s", state->creds.password);
#endif
oc_log(LOGNOTE,"port number: %d", state->proxy.port);
}
if(v) free(v);
return OC_NOERR;
}
/* insertion sort the triplestore based on url */
static void
sorttriplestore(void)
{
int i, nsorted;
struct OCTriple* sorted = NULL;
if(ocdodsrc->ntriples <= 1) return; /* nothing to sort */
if(ocdebug > 2)
ocdodsrcdump("initial:",ocdodsrc->triples,ocdodsrc->ntriples);
sorted = (struct OCTriple*)malloc(sizeof(struct OCTriple)*ocdodsrc->ntriples);
if(sorted == NULL) {
oc_log(LOGERR,"sorttriplestore: out of memory");
return;
}
nsorted = 0;
while(nsorted < ocdodsrc->ntriples) {
int largest;
/* locate first non killed entry */
for(largest=0;largest<ocdodsrc->ntriples;largest++) {
if(ocdodsrc->triples[largest].key[0] != '\0') break;
}
OCASSERT(ocdodsrc->triples[largest].key[0] != '\0');
for(i=0;i<ocdodsrc->ntriples;i++) {
if(ocdodsrc->triples[i].key[0] != '\0') { /* avoid empty slots */
int lexorder = strcmp(ocdodsrc->triples[i].url,ocdodsrc->triples[largest].url);
int leni = strlen(ocdodsrc->triples[i].url);
int lenlarge = strlen(ocdodsrc->triples[largest].url);
/* this defines the ordering */
if(leni == 0 && lenlarge == 0) continue; /* if no urls, then leave in order */
if(leni != 0 && lenlarge == 0) largest = i;
else if(lexorder > 0) largest = i;
}
}
/* Move the largest entry */
OCASSERT(ocdodsrc->triples[largest].key[0] != 0);
sorted[nsorted] = ocdodsrc->triples[largest];
ocdodsrc->triples[largest].key[0] = '\0'; /* kill entry */
nsorted++;
if(ocdebug > 2)
ocdodsrcdump("pass:",sorted,nsorted);
}
memcpy((void*)ocdodsrc->triples,(void*)sorted,sizeof(struct OCTriple)*nsorted);
free(sorted);
if(ocdebug > 0)
ocdodsrcdump("final .dodsrc order:",ocdodsrc->triples,ocdodsrc->ntriples);
}
/* Create a triple store from a file */
int
ocdodsrc_read(char* basename, char* path)
{
char line0[MAXRCLINESIZE];
FILE *in_file = NULL;
int linecount = 0;
if(ocdodsrc == NULL) {
ocdodsrc = (struct OCTriplestore*)malloc(sizeof(struct OCTriplestore));
if(ocdodsrc == NULL) {
oc_log(LOGERR,"ocdodsrc_read: out of memory");
return 0;
}
}
ocdodsrc->ntriples = 0;
in_file = fopen(path, "r"); /* Open the file to read it */
if (in_file == NULL) {
oc_log(LOGERR, "Could not open configuration file: %s",basename);
return OC_EPERM;
}
for(;;) {
char *line,*key,*value;
if(!rcreadline(in_file,line0,sizeof(line0))) break;
linecount++;
if(linecount >= MAXRCLINES) {
oc_log(LOGERR, ".dodsrc has too many lines");
return 0;
}
line = line0;
/* check for comment */
if (line[0] == '#') continue;
/* trim leading blanks */
line = rctrimleft(line,TRIMCHARS);
if(strlen(line) >= MAXRCLINESIZE) {
oc_log(LOGERR, "%s line too long: %s",basename,line0);
return 0;
}
/* parse the line */
ocdodsrc->triples[ocdodsrc->ntriples].url[0] = '\0'; /*assume no url*/
if(line[0] == LTAG) {
char* url = ++line;
char* rtag = strchr(line,RTAG);
if(rtag == NULL) {
oc_log(LOGERR, "Malformed [url] in %s entry: %s",basename,line);
continue;
}
line = rtag + 1;
*rtag = '\0';
/* trim again */
line = rctrimleft(line,TRIMCHARS);
/* save the url */
strcpy(ocdodsrc->triples[ocdodsrc->ntriples].url,TRIM(url));
}
if(strlen(line)==0) continue; /* empty line */
/* split off key and value */
key=line;
value = strchr(line, '=');
if(value == NULL) {
/* add fake '=1' */
if(strlen(line) + strlen("=1") >= MAXRCLINESIZE) {
oc_log(LOGERR, "%s entry too long: %s",basename,line);
continue;
}
strcat(line,"=1");
value = strchr(line,'=');
}
*value = '\0';
value++;
strcpy(ocdodsrc->triples[ocdodsrc->ntriples].key,TRIM(key));
strcpy(ocdodsrc->triples[ocdodsrc->ntriples].value,TRIM(value));
ocdodsrc->ntriples++;
}
fclose(in_file);
sorttriplestore();
return 1;
}
int
ocdodsrc_process(OCstate* state)
{
int stat = 0;
char* value;
char* url = ocuribuild(state->uri,NULL,NULL,OCURIENCODE);
if(ocdodsrc == NULL) goto done;
value = curllookup("DEFLATE",url);
if(value != NULL) {
if(atoi(value)) state->curlflags.compress = 1;
if(ocdebug > 0)
oc_log(LOGNOTE,"Compression: %ld", state->curlflags.compress);
}
if((value = curllookup("VERBOSE",url)) != NULL) {
if(atoi(value)) state->curlflags.verbose = 1;
if(ocdebug > 0)
oc_log(LOGNOTE,"curl.verbose: %ld", state->curlflags.verbose);
}
if((value = curllookup("TIMEOUT",url)) != NULL) {
if(atoi(value)) state->curlflags.timeout = atoi(value);
if(ocdebug > 0)
oc_log(LOGNOTE,"curl.timeout: %ld", state->curlflags.timeout);
}
if((value = curllookup("COOKIEFILE",url)) != NULL) {
state->curlflags.cookiefile = strdup(TRIM(value));
if(!state->curlflags.cookiefile) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"COOKIEFILE: %s", state->curlflags.cookiefile);
}
if((value = curllookup("COOKIEJAR",url))
|| (value = curllookup("COOKIE_JAR",url))) {
state->curlflags.cookiejar = strdup(TRIM(value));
if(!state->curlflags.cookiejar) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"COOKIEJAR: %s", state->curlflags.cookiejar);
}
/* Some servers (e.g. thredds) appear to require a place
to put cookies in order for some security functions to work
*/
if(state->curlflags.cookiejar == NULL
&& state->curlflags.cookiefile == NULL) {
state->curlflags.cookiefile = strdup("");
}
if((value = curllookup("PROXY_SERVER",url)) != NULL) {
stat = parseproxy(state,TRIM(value));
if(stat != OC_NOERR) goto done;
}
if((value = curllookup("SSL.VALIDATE",url)) != NULL) {
if(atoi(value)) state->ssl.validate = 1;
if(ocdebug > 0)
oc_log(LOGNOTE,"CURL.SSL.VALIDATE: %ld", state->ssl.validate);
}
if((value = curllookup("SSL.CERTIFICATE",url)) != NULL) {
state->ssl.certificate = strdup(TRIM(value));
if(!state->ssl.certificate) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.SSL.CERTIFICATE: %s", state->ssl.certificate);
}
if((value = curllookup("SSL.KEY",url)) != NULL) {
state->ssl.key = strdup(TRIM(value));
if(!state->ssl.key) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.SSL.KEY: %s", state->ssl.key);
}
if((value = curllookup("SSL.KEYPASSWORD",url)) != NULL) {
state->ssl.keypasswd = strdup(TRIM(value));
if(!state->ssl.keypasswd) {stat = OC_ENOMEM; goto done;}
#ifdef INSECURE
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.SSL.KEYPASSWORD: %s", state->ssl.keypasswd);
#endif
}
if((value = curllookup("SSL.CAINFO",url)) != NULL) {
state->ssl.cainfo = strdup(TRIM(value));
if(!state->ssl.cainfo) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"SSL.CAINFO: %s", state->ssl.cainfo);
}
if((value = curllookup("SSL.CAPATH",url)) != NULL) {
state->ssl.capath = strdup(TRIM(value));
if(!state->ssl.capath) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"SSL.CAPATH: %s", state->ssl.capath);
}
if((value = curllookup("SSL.VERIFYPEER",url)) != NULL) {
char* s = strdup(TRIM(value));
int tf = 0;
if(s == NULL || strcmp(s,"0")==0 || strcasecmp(s,"false")==0)
tf = 0;
else if(strcmp(s,"1")==0 || strcasecmp(s,"true")==0)
tf = 1;
else
tf = 1; /* default if not null */
state->ssl.verifypeer = tf;
if(ocdebug > 0)
oc_log(LOGNOTE,"SSL.VERIFYPEER: %d", state->ssl.verifypeer);
}
if((value = curllookup("CREDENTIALS.USER",url)) != NULL) {
state->creds.username = strdup(TRIM(value));
if(!state->creds.username) {stat = OC_ENOMEM; goto done;}
if(ocdebug > 0)
oc_log(LOGNOTE,"CREDENTIALS.USER: %s", state->creds.username);
}
if((value = curllookup("CREDENTIALS.PASSWORD",url)) != NULL) {
state->creds.password = strdup(TRIM(value));
if(!state->creds.password) {stat = OC_ENOMEM; goto done;}
}
/* else ignore */
done:
if(url != NULL) free(url);
return stat;
}
char*
ocdodsrc_lookup(char* key, char* url)
{
int i,found;
struct OCTriple* triple = ocdodsrc->triples;
if(key == NULL || ocdodsrc == NULL) return NULL;
if(url == NULL) url = "";
/* Assume that the triple store has been properly sorted */
for(found=0,i=0;i<ocdodsrc->ntriples;i++,triple++) {
int triplelen = strlen(triple->url);
int t;
if(strcmp(key,triple->key) != 0) continue; /* keys do not match */
/* If the triple entry has no url, then use it (because we have checked all other cases)*/
if(triplelen == 0) {found=1;break;}
/* do url prefix comparison */
t = ocstrncmp(url,triple->url,triplelen);
if(t == 0) {found=1; break;}
}
if(ocdebug > 2)
{
if(found) {
fprintf(stderr,"lookup %s: [%s]%s = %s\n",url,triple->url,triple->key,triple->value);
}
}
return (found ? triple->value : NULL);
}
static void
ocdodsrcdump(char* msg, struct OCTriple* triples, int ntriples)
{
int i;
if(msg != NULL) fprintf(stderr,"%s\n",msg);
if(ocdodsrc == NULL) {
fprintf(stderr,"<EMPTY>\n");
return;
}
if(triples == NULL) triples= ocdodsrc->triples;
if(ntriples < 0 ) ntriples= ocdodsrc->ntriples;
for(i=0;i<ntriples;i++) {
fprintf(stderr,"\t%s\t%s\t%s\n",
(strlen(triples[i].url)==0?"--":triples[i].url),
triples[i].key,
triples[i].value);
}
}
/* Isolate the "CURL." prefix to allow changing to something else */
static char*
curllookup(char* suffix, char* url)
{
char key[2048];
char* value = NULL;
strcpy(key,HTTPPREFIX);
strcat(key,suffix);
value = ocdodsrc_lookup(key,url);
if(value == NULL) {
strcpy(key,HTTPPREFIXDEPRECATED);
strcat(key,suffix);
value = ocdodsrc_lookup(key,url);
}
return value;
}

View File

@ -1,36 +0,0 @@
/*
* rc.h
*
* Created on: Mar 5, 2009
* Author: rikki
*/
#ifndef RC_H_
#define RC_H_
/* Max .dodsrc line size */
#define MAXRCLINESIZE 2048
/* Max number of triples in a .dodsrc */
#define MAXRCLINES 2048
/* Create a triple store for (url,key,value) and sorted by url */
/* Actual triple store */
extern struct OCTriplestore {
int ntriples;
struct OCTriple {
char url[MAXRCLINESIZE];
char key[MAXRCLINESIZE];
char value[MAXRCLINESIZE];
} triples[MAXRCLINES];
} *ocdodsrc;
extern int ocdodsrc_read(char* basename,char *in_file_name);
extern int ocdodsrc_process(OCstate* state);
extern char* ocdodsrc_lookup(char* key, char* url);
extern int occredentials_in_url(const char *url);
extern int ocextract_credentials(const char *url, char **name, char **pw, char **result_url);
#endif /* RC_H_ */

View File

@ -1,202 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include "ocinternal.h"
#include "ocdebug.h"
#include "ochttp.h"
#include "ocread.h"
#include "ocrc.h"
#include "occurlfunctions.h"
extern int oc_curl_file_supported;
/*Forward*/
static int readpacket(CURL*, OCURI*, OCbytes*, OCdxd, long*);
static int readfile(char* path, char* suffix, OCbytes* packet);
static int readfiletofile(char* path, char* suffix, FILE* stream, unsigned long*);
int
readDDS(OCstate* state, OCtree* tree)
{
int stat = OC_NOERR;
long lastmodified = -1;
ocurisetconstraints(state->uri,tree->constraint);
ocset_user_password(state);
stat = readpacket(state->curl,state->uri,state->packet,OCDDS,
&lastmodified);
if(stat == OC_NOERR) state->ddslastmodified = lastmodified;
return stat;
}
int
readDAS(OCstate* state, OCtree* tree)
{
int stat = OC_NOERR;
ocurisetconstraints(state->uri,tree->constraint);
stat = readpacket(state->curl,state->uri,state->packet,OCDAS,NULL);
return stat;
}
int
readversion(CURL* curl, OCURI* url, OCbytes* packet)
{
return readpacket(curl,url,packet,OCVER,NULL);
}
static
char* ocdxdextension[] ={
".dds", /*OCDDS*/
".das", /*OCDAS*/
".dods", /*OCDATADDS*/
".vers", /*OCVERS*/
};
static int
readpacket(CURL* curl,OCURI* url,OCbytes* packet,OCdxd dxd,long* lastmodified)
{
int stat = OC_NOERR;
int fileprotocol = 0;
char* suffix = ocdxdextension[dxd];
char* fetchurl = NULL;
fileprotocol = (strcmp(url->protocol,"file")==0);
if(fileprotocol && !oc_curl_file_supported) {
/* Short circuit file://... urls*/
/* We do this because the test code always needs to read files*/
fetchurl = ocuribuild(url,NULL,NULL,0);
stat = readfile(fetchurl,suffix,packet);
} else {
int flags = 0;
if(!fileprotocol) flags |= OCURICONSTRAINTS;
flags |= OCURIENCODE;
fetchurl = ocuribuild(url,NULL,suffix,flags);
MEMCHECK(fetchurl,OC_ENOMEM);
if(ocdebug > 0)
{fprintf(stderr,"fetch url=%s\n",fetchurl); fflush(stderr);}
stat = ocfetchurl(curl,fetchurl,packet,lastmodified);
if(ocdebug > 0)
{fprintf(stderr,"fetch complete\n"); fflush(stderr);}
}
free(fetchurl);
return OCTHROW(stat);
}
int
readDATADDS(OCstate* state, OCtree* tree, OCflags flags)
{
int stat = OC_NOERR;
long lastmod = -1;
if((flags & OCONDISK) == 0) {
ocurisetconstraints(state->uri,tree->constraint);
stat = readpacket(state->curl,state->uri,state->packet,OCDATADDS,&lastmod);
if(stat == OC_NOERR)
state->datalastmodified = lastmod;
tree->data.datasize = ocbyteslength(state->packet);
} else {
OCURI* url = state->uri;
int fileprotocol = 0;
char* readurl = NULL;
fileprotocol = (strcmp(url->protocol,"file")==0);
if(fileprotocol && !oc_curl_file_supported) {
readurl = ocuribuild(url,NULL,NULL,0);
stat = readfiletofile(readurl, ".dods", tree->data.file, &tree->data.datasize);
} else {
int flags = 0;
if(!fileprotocol) flags |= OCURICONSTRAINTS;
flags |= OCURIENCODE;
ocurisetconstraints(url,tree->constraint);
readurl = ocuribuild(url,NULL,".dods",flags);
MEMCHECK(readurl,OC_ENOMEM);
if (ocdebug > 0)
{fprintf(stderr, "fetch url=%s\n", readurl);fflush(stderr);}
stat = ocfetchurl_file(state->curl, readurl, tree->data.file,
&tree->data.datasize, &lastmod);
if(stat == OC_NOERR)
state->datalastmodified = lastmod;
if (ocdebug > 0)
{fprintf(stderr,"fetch complete\n"); fflush(stderr);}
}
free(readurl);
}
return OCTHROW(stat);
}
static int
readfiletofile(char* path, char* suffix, FILE* stream, unsigned long* sizep)
{
int stat = OC_NOERR;
OCbytes* packet = ocbytesnew();
size_t len;
/* check for leading file:/// */
if(ocstrncmp(path,"file:///",8)==0) path += 7; /* assume absolute path*/
stat = readfile(path,suffix,packet);
if(stat != OC_NOERR) goto unwind;
len = oclistlength(packet);
if(stat == OC_NOERR) {
size_t written;
fseek(stream,0,SEEK_SET);
written = fwrite(ocbytescontents(packet),1,len,stream);
if(written != len) stat = OC_EIO;
}
if(sizep != NULL) *sizep = len;
unwind:
ocbytesfree(packet);
return OCTHROW(stat);
}
static int
readfile(char* path, char* suffix, OCbytes* packet)
{
int stat = OC_NOERR;
char buf[1024];
char filename[1024];
int count,size,fd;
/* check for leading file:/// */
if(ocstrncmp(path,"file://",7)==0) path += 7; /* assume absolute path*/
strcpy(filename,path);
if(suffix != NULL) strcat(filename,suffix);
fd = open(filename,O_RDONLY);
if(fd < 0) {
oc_log(LOGERR,"open failed:%s",filename);
return OCTHROW(OC_EOPEN);
}
size=0;
stat = OC_NOERR;
for(;;) {
count = read(fd,buf,sizeof(buf));
if(count <= 0)
break;
else if(count < 0) {
stat = OC_EIO;
oc_log(LOGERR,"read failed: %s",filename);
break;
}
ocbytesappendn(packet,buf,count);
size += count;
}
close(fd);
return OCTHROW(stat);
}

View File

@ -1,15 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef READ_H
#define READ_H
extern int readDDS(OCstate*, OCtree*);
extern int readDAS(OCstate*, OCtree*);
extern int readDATADDS(OCstate*, OCtree*, int inmemory);
extern int readversion(CURL*, OCURI*, OCbytes*);
#endif /*READ_H*/

View File

@ -1,737 +0,0 @@
/*********************************************************************
* Copyright 2010, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* $Header$
*********************************************************************/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "oc.h"
#include "ocuri.h"
#define OCURIDEBUG
#define LBRACKET '['
#define RBRACKET ']'
#ifndef FIX
#define FIX(s) ((s)==NULL?"":(s))
#endif
#ifndef NILLEN
#define NILLEN(s) ((s)==NULL?0:strlen(s))
#endif
#ifdef HAVE_STRDUP
# ifndef nulldup
# define nulldup(s) ((s)==NULL?NULL:strdup(s))
# endif
#endif
#ifndef HAVE_STRDUP
static char* nulldup(char* s)
{
char* dup = NULL;
if(s != NULL) {
dup = (char*)malloc(strlen(s)+1);
if(dup != NULL)
strcpy(dup,s);
}
return dup;
}
#endif
#ifdef OCIGNORE
/* Not all systems have strndup, so provide one*/
static char*
ocstrndup(const char* s, size_t len)
{
char* dup;
if(s == NULL) return NULL;
dup = (char*)ocmalloc(len+1);
MEMCHECK(dup,NULL);
memcpy((void*)dup,s,len);
dup[len] = '\0';
return dup;
}
#endif
/* Do not trust strncmp */
static int
ocuristrncmp(const char* s1, const char* s2, size_t len)
{
const char *p,*q;
if(s1 == s2) return 0;
if(s1 == NULL) return -1;
if(s2 == NULL) return +1;
for(p=s1,q=s2;len > 0;p++,q++,len--) {
if(*p != *q)
return (*p - *q);
if(*p == 0) return 0; /* *p == *q == 0 */
}
/* 1st len chars are same */
return 0;
}
static char* legalprotocols[] = {
"file:",
"http:",
"https:",
"ftp:",
NULL /* NULL terminate*/
};
/* Allowable character sets for encode */
static char* fileallow =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
static char* queryallow =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'()*+,-./:;=?@_~";
static void ocparamfree(char** params);
static int ocfind(char** params, const char* key);
/* Do a simple uri parse: return 0 if fail, 1 otherwise*/
int
ocuriparse(const char* uri0, OCURI** ocurip)
{
OCURI* ocuri = NULL;
char* uri;
char** pp;
char* p;
char* p1;
int c;
/* accumulate parse points*/
char* protocol = NULL;
char* params = NULL;
char* host = NULL;
char* port = NULL;
char* constraint = NULL;
char* user = NULL;
char* pwd = NULL;
char* file = NULL;
if(uri0 == NULL)
return OC_EBADURL;
ocuri = (OCURI*)calloc(1,sizeof(OCURI));
if(ocuri == NULL) return 0;
/* make local copy of uri */
uri = nulldup(uri0);
/* remove all whitespace*/
p = uri;
p1 = uri;
while((c=*p1++)) {if(c != ' ' && c != '\t') *p++ = c;}
p = uri;
/* break up the uri string into pieces*/
/* 1. leading bracketed parameters */
if(*p == LBRACKET) {
params = p+1;
/* find end of the clientparams*/
for(;*p;p++) {if(p[0] == RBRACKET && p[1] != LBRACKET) break;}
if(*p == 0) goto fail; /* malformed client params*/
*p = '\0'; /* leave off the trailing rbracket for now */
p++; /* move past the params*/
}
/* verify that the uri starts with an acceptable protocol*/
for(pp=legalprotocols;*pp;pp++) {
if(ocuristrncmp(p,*pp,strlen(*pp))==0) break;
}
if(*pp == NULL) goto fail; /* illegal protocol*/
/* save the protocol */
protocol = *pp;
/* 4. skip protocol */
p += strlen(protocol);
/* 5. skip // */
if(*p != '/' && *(p+1) != '/')
goto fail;
p += 2;
/* 6. Mark the end of the host section */
file = strchr(p,'/');
if(file) {
*file++ = '\0'; /* warning: we just overwrote the leading / */
} else
goto fail;
/* 7. extract any user:pwd */
p1 = strchr(p,'@');
if(p1) {/* Assume we have user:pwd@ */
*p1 = '\0';
user = p;
pwd = strchr(p,':');
if(!pwd) goto fail; /* malformed */
*pwd++ = '\0';
p = pwd+strlen(pwd)+1;
}
/* 8. extract host and port */
host = p;
port = strchr(p,':');
if(port) {
*port++ = '\0';
}
/* 9. Look for '?' */
constraint = strchr(file,'?');
if(constraint) {
*constraint++ = '\0';
}
/* assemble the component pieces*/
if(uri0 && strlen(uri0) > 0)
ocuri->uri = nulldup(uri0);
if(protocol && strlen(protocol) > 0) {
ocuri->protocol = nulldup(protocol);
/* remove trailing ':' */
ocuri->protocol[strlen(protocol)-1] = '\0';
}
if(user && strlen(user) > 0)
ocuri->user = nulldup(user);
if(pwd && strlen(pwd) > 0)
ocuri->password = nulldup(pwd);
if(host && strlen(host) > 0)
ocuri->host = nulldup(host);
if(port && strlen(port) > 0)
ocuri->port = nulldup(port);
if(file && strlen(file) > 0) {
/* Add back the leading / */
ocuri->file = malloc(strlen(file)+2);
strcpy(ocuri->file,"/");
strcat(ocuri->file,file);
}
if(constraint && strlen(constraint) > 0)
ocuri->constraint = nulldup(constraint);
ocurisetconstraints(ocuri,constraint);
if(params != NULL && strlen(params) > 0) {
ocuri->params = (char*)malloc(1+2+strlen(params));
strcpy(ocuri->params,"[");
strcat(ocuri->params,params);
strcat(ocuri->params,"]");
}
#ifdef OCXDEBUG
{
fprintf(stderr,"ocuri:");
fprintf(stderr," params=|%s|",FIX(ocuri->params));
fprintf(stderr," protocol=|%s|",FIX(ocuri->protocol));
fprintf(stderr," host=|%s|",FIX(ocuri->host));
fprintf(stderr," port=|%s|",FIX(ocuri->port));
fprintf(stderr," file=|%s|",FIX(ocuri->file));
fprintf(stderr," constraint=|%s|",FIX(ocuri->constraint));
fprintf(stderr,"\n");
}
#endif
free(uri);
if(ocurip != NULL) *ocurip = ocuri;
return 1;
fail:
if(ocuri) ocurifree(ocuri);
if(uri != NULL) free(uri);
return 0;
}
void
ocurifree(OCURI* ocuri)
{
if(ocuri == NULL) return;
if(ocuri->uri != NULL) {free(ocuri->uri);}
if(ocuri->protocol != NULL) {free(ocuri->protocol);}
if(ocuri->user != NULL) {free(ocuri->user);}
if(ocuri->password != NULL) {free(ocuri->password);}
if(ocuri->host != NULL) {free(ocuri->host);}
if(ocuri->port != NULL) {free(ocuri->port);}
if(ocuri->file != NULL) {free(ocuri->file);}
if(ocuri->constraint != NULL) {free(ocuri->constraint);}
if(ocuri->projection != NULL) {free(ocuri->projection);}
if(ocuri->selection != NULL) {free(ocuri->selection);}
if(ocuri->params != NULL) {free(ocuri->params);}
if(ocuri->paramlist != NULL) ocparamfree(ocuri->paramlist);
free(ocuri);
}
/* Replace the constraints */
void
ocurisetconstraints(OCURI* duri,const char* constraints)
{
char* proj = NULL;
char* select = NULL;
const char* p;
if(duri->constraint == NULL) free(duri->constraint);
if(duri->projection != NULL) free(duri->projection);
if(duri->selection != NULL) free(duri->selection);
duri->constraint = NULL;
duri->projection = NULL;
duri->selection = NULL;
if(constraints == NULL || strlen(constraints)==0) return;
duri->constraint = nulldup(constraints);
if(*duri->constraint == '?')
strcpy(duri->constraint,duri->constraint+1);
p = duri->constraint;
proj = (char*) p;
select = strchr(proj,'&');
if(select != NULL) {
size_t plen = (select - proj);
if(plen == 0) {
proj = NULL;
} else {
proj = (char*)malloc(plen+1);
memcpy((void*)proj,p,plen);
proj[plen] = '\0';
}
select = nulldup(select);
} else {
proj = nulldup(proj);
select = NULL;
}
duri->projection = proj;
duri->selection = select;
}
/* Construct a complete OC URI without the client params
and optionally with the constraints;
caller frees returned string.
Optionally encode the pieces.
*/
char*
ocuribuild(OCURI* duri, const char* prefix, const char* suffix, int flags)
{
size_t len = 0;
char* newuri;
char* tmpfile;
char* tmpsuffix;
char* tmpquery;
int withparams = ((flags&OCURIPARAMS)
&& duri->params != NULL);
int withuserpwd = ((flags&OCURIUSERPWD)
&& duri->user != NULL && duri->password != NULL);
int withconstraints = ((flags&OCURICONSTRAINTS)
&& duri->constraint != NULL);
#ifdef NEWESCAPE
int encode = (flags&OCURIENCODE);
#else
int encode = 0;
#endif
if(prefix != NULL) len += NILLEN(prefix);
if(withparams) {
len += NILLEN("[]");
len += NILLEN(duri->params);
}
len += (NILLEN(duri->protocol)+NILLEN("://"));
if(withuserpwd) {
len += (NILLEN(duri->user)+NILLEN(duri->password)+NILLEN(":@"));
}
len += (NILLEN(duri->host));
if(duri->port != NULL) {
len += (NILLEN(":")+NILLEN(duri->port));
}
tmpfile = duri->file;
if(encode)
tmpfile = ocuriencode(tmpfile,fileallow);
len += (NILLEN(tmpfile));
if(suffix != NULL) {
tmpsuffix = (char*)suffix;
if(encode)
tmpsuffix = ocuriencode(tmpsuffix,fileallow);
len += (NILLEN(tmpsuffix));
}
if(withconstraints) {
tmpquery = duri->constraint;
if(encode)
tmpquery = ocuriencode(tmpquery,queryallow);
len += (NILLEN("?")+NILLEN(tmpquery));
}
len += 1; /* null terminator */
newuri = (char*)malloc(len);
if(newuri == NULL) return NULL;
newuri[0] = '\0';
if(prefix != NULL) strcat(newuri,prefix);
if(withparams) {
strcat(newuri,"[");
strcat(newuri,duri->params);
strcat(newuri,"]");
}
if(duri->protocol != NULL)
strcat(newuri,duri->protocol);
strcat(newuri,"://");
if(withuserpwd) {
strcat(newuri,duri->user);
strcat(newuri,":");
strcat(newuri,duri->password);
strcat(newuri,"@");
}
if(duri->host != NULL) { /* may be null if using file: protocol */
strcat(newuri,duri->host);
}
if(duri->port != NULL) {
strcat(newuri,":");
strcat(newuri,duri->port);
}
strcat(newuri,tmpfile);
if(suffix != NULL) strcat(newuri,tmpsuffix);
if(withconstraints) {
strcat(newuri,"?");
strcat(newuri,tmpquery);
}
return newuri;
}
/**************************************************/
/* Parameter support */
/*
Client parameters are assumed to be
one or more instances of bracketed pairs:
e.g "[...][...]...".
The bracket content in turn is assumed to be a
comma separated list of <name>=<value> pairs.
e.g. x=y,z=,a=b.
If the same parameter is specifed more than once,
then the first occurrence is used; this is so that
is possible to forcibly override user specified
parameters by prefixing.
IMPORTANT: client parameter string is assumed to
have blanks compress out.
Returns 1 if parse suceeded, 0 otherwise;
*/
int
ocuridecodeparams(OCURI* ocuri)
{
char* cp;
char* cq;
int c;
int i;
int nparams;
char* params0;
char* params;
char* params1;
char** plist;
if(ocuri == NULL) return 0;
if(ocuri->params == NULL) return 1;
params0 = ocuri->params;
/* Pass 1 to replace beginning '[' and ending ']' */
if(params0[0] == '[')
params = nulldup(params0+1);
else
params = nulldup(params0);
if(params[strlen(params)-1] == ']')
params[strlen(params)-1] = '\0';
/* Pass 2 to replace "][" pairs with ','*/
params1 = nulldup(params);
cp=params; cq = params1;
while((c=*cp++)) {
if(c == RBRACKET && *cp == LBRACKET) {cp++; c = ',';}
*cq++ = c;
}
*cq = '\0';
free(params);
params = params1;
/* Pass 3 to break string into pieces and count # of pairs */
nparams=0;
for(cp=params;(c=*cp);cp++) {
if(c == ',') {*cp = '\0'; nparams++;}
}
nparams++; /* for last one */
/* plist is an env style list */
plist = (char**)calloc(1,sizeof(char*)*(2*nparams+1)); /* +1 for null termination */
/* Pass 4 to break up each pass into a (name,value) pair*/
/* and insert into the param list */
/* parameters of the form name name= are converted to name=""*/
cp = params;
for(i=0;i<nparams;i++) {
char* next = cp+strlen(cp)+1; /* save ptr to next pair*/
char* vp;
/*break up the ith param*/
vp = strchr(cp,'=');
if(vp != NULL) {*vp = '\0'; vp++;} else {vp = "";}
plist[2*i] = nulldup(cp);
plist[2*i+1] = nulldup(vp);
cp = next;
}
plist[2*nparams] = NULL;
free(params);
if(ocuri->paramlist != NULL)
ocparamfree(ocuri->paramlist);
ocuri->paramlist = plist;
return 1;
}
const char*
ocurilookup(OCURI* uri, const char* key)
{
int i;
if(uri == NULL || key == NULL || uri->params == NULL) return NULL;
if(uri->paramlist == NULL) {
i = ocuridecodeparams(uri);
if(!i) return 0;
}
i = ocfind(uri->paramlist,key);
if(i >= 0)
return uri->paramlist[(2*i)+1];
return NULL;
}
int
ocurisetparams(OCURI* uri, const char* newparams)
{
if(uri == NULL) return 0;
if(uri->paramlist != NULL) ocparamfree(uri->paramlist);
uri->paramlist = NULL;
if(uri->params != NULL) free(uri->params);
uri->params = nulldup(newparams);
return 1;
}
/* Internal version of lookup; returns the paired index of the key */
static int
ocfind(char** params, const char* key)
{
int i;
char** p;
for(i=0,p=params;*p;p+=2,i++) {
if(strcmp(key,*p)==0) return i;
}
return -1;
}
static void
ocparamfree(char** params)
{
char** p;
if(params == NULL) return;
for(p=params;*p;p+=2) {
free(*p);
if(p[1] != NULL) free(p[1]);
}
free(params);
}
#ifdef OCIGNORE
/*
Delete the entry.
return value = 1 => found and deleted;
0 => param not found
*/
int
ocparamdelete(char** params, const char* key)
{
int i;
char** p;
char** q;
if(params == NULL || key == NULL) return 0;
i = ocfind(params,key);
if(i < 0) return 0;
p = params+(2*i);
for(q=p+2;*q;) {
*p++ = *q++;
}
*p = NULL;
return 1;
}
static int
oclength(char** params)
{
int i = 0;
if(params != NULL) {
while(*params) {params+=2; i++;}
}
return i;
}
/*
Insert new client param (name,value);
return value = 1 => not already defined
0 => param already defined (no change)
*/
char**
ocparaminsert(char** params, const char* key, const char* value)
{
int i;
char** newp;
size_t len;
if(params == NULL || key == NULL) return 0;
i = ocfind(params,key);
if(i >= 0) return 0;
/* not found, append */
i = oclength(params);
len = sizeof(char*)*((2*i)+1);
newp = realloc(params,len+2*sizeof(char*));
memcpy(newp,params,len);
newp[2*i] = nulldup(key);
newp[2*i+1] = (value==NULL?NULL:nulldup(value));
return newp;
}
/*
Replace new client param (name,value);
return value = 1 => replacement performed
0 => key not found (no change)
*/
int
ocparamreplace(char** params, const char* key, const char* value)
{
int i;
if(params == NULL || key == NULL) return 0;
i = ocfind(params,key);
if(i < 0) return 0;
if(params[2*i+1] != NULL) free(params[2*i+1]);
params[2*i+1] = nulldup(value);
return 1;
}
#endif
/* Provide % encoders and decoders */
static char* hexchars = "0123456789abcdefABCDEF";
static void
toHex(unsigned int b, char hex[2])
{
hex[0] = hexchars[(b >> 4) & 0xff];
hex[1] = hexchars[(b) & 0xff];
}
static unsigned int
fromHex(int c)
{
if(c >= '0' && c <= '9') return (c - '0');
if(c >= 'a' && c <= 'f') return (10 + (c - 'a'));
if(c >= 'A' && c <= 'F') return (10 + (c - 'A'));
return -1;
}
/* Return a string representing encoding of input; caller must free;
watch out: will encode whole string, so watch what you give it.
Allowable argument specifies characters that do not need escaping.
*/
char*
ocuriencode(char* s, char* allowable)
{
size_t slen;
char* encoded;
char* inptr;
char* outptr;
if(s == NULL) return NULL;
slen = strlen(s);
encoded = (char*)malloc((3*slen) + 1); /* max possible size */
for(inptr=s,outptr=encoded;*inptr;) {
int c = *inptr++;
if(c == ' ') {
*outptr++ = '+';
} else {
/* search allowable */
int c2;
char* a = allowable;
while((c2=*a++)) {
if(c == c2) break;
}
if(c2) {*outptr++ = c;}
else {
char hex[2];
toHex(c,hex);
*outptr++ = '%';
*outptr++ = hex[0];
*outptr++ = hex[1];
}
}
}
*outptr = '\0';
return encoded;
}
/* Return a string representing decoding of input; caller must free;*/
char*
ocuridecode(char* s)
{
return ocuridecodeonly(s,NULL);
}
/* Return a string representing decoding of input only for specified
characters; caller must free
*/
char*
ocuridecodeonly(char* s, char* only)
{
size_t slen;
char* decoded;
char* outptr;
char* inptr;
unsigned int c;
if (s == NULL) return NULL;
if(only == NULL) only = "";
slen = strlen(s);
decoded = (char*)malloc(slen+1); /* Should be max we need */
outptr = decoded;
inptr = s;
while((c = *inptr++)) {
if(c == '+' && strchr(only,'+') != NULL)
*outptr++ = ' ';
else if(c == '%') {
/* try to pull two hex more characters */
if(inptr[0] != '\0' && inptr[1] != '\0'
&& strchr(hexchars,inptr[0]) != NULL
&& strchr(hexchars,inptr[1]) != NULL) {
/* test conversion */
int xc = (fromHex(inptr[0]) << 4) | (fromHex(inptr[1]));
if(strchr(only,xc) != NULL) {
inptr += 2; /* decode it */
c = xc;
}
}
}
*outptr++ = c;
}
*outptr = '\0';
return decoded;
}

View File

@ -1,52 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCURI_H
#define OCURI_H
/*! This is an open structure meaning
it is ok to directly access its fields*/
typedef struct OCURI {
char* uri; /* as passed by the caller */
char* protocol;
char* user; /* from user:password@ */
char* password; /* from user:password@ */
char* host; /*!< host*/
char* port; /*!< host */
char* file; /*!< file */
char* constraint; /*!< projection+selection */
char* projection; /*!< without leading '?'*/
char* selection; /*!< with leading '&'*/
char* params; /* all params */
char** paramlist; /*!<null terminated list */
} OCURI;
extern int ocuriparse(const char* s, OCURI** ocuri);
extern void ocurifree(OCURI* ocuri);
/* Replace the constraints */
extern void ocurisetconstraints(OCURI*,const char* constraints);
/* Construct a complete OC URI; caller frees returned string */
/* Define flags to control what is included */
#define OCURICONSTRAINTS 1
#define OCURIUSERPWD 2
#define OCURIPARAMS 4
#define OCURIENCODE 8 /* If output should be encoded */
extern char* ocuribuild(OCURI*,const char* prefix, const char* suffix, int flags);
/* Param Management */
extern int ocuridecodeparams(OCURI* ocuri);
extern int ocurisetparams(OCURI* ocuri,const char*);
/*! NULL result => entry not found.
Empty value should be represented as a zero length string */
extern const char* ocurilookup(OCURI*, const char* param);
extern char* ocuriencode(char* s, char* allowable);
extern char* ocuridecode(char* s);
extern char* ocuridecodeonly(char* s, char*);
#endif /*OCURI_H*/

View File

@ -1,442 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#include "config.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include "ocinternal.h"
#include "ocdebug.h"
#ifdef WIN32
#define snprintf _snprintf
#endif
/* Order is important: longest first */
static char* DDSdatamarks[3] = {"Data:\r\n","Data:\n",(char*)NULL};
/* Not all systems have strndup, so provide one*/
char*
ocstrndup(const char* s, size_t len)
{
char* dup;
if(s == NULL) return NULL;
dup = (char*)ocmalloc(len+1);
MEMCHECK(dup,NULL);
memcpy((void*)dup,s,len);
dup[len] = '\0';
return dup;
}
/* Do not trust strncmp semantics */
int
ocstrncmp(const char* s1, const char* s2, size_t len)
{
const char *p,*q;
if(s1 == s2) return 0;
if(s1 == NULL) return -1;
if(s2 == NULL) return +1;
for(p=s1,q=s2;len > 0;p++,q++,len--) {
if(*p == 0 && *q == 0) return 0; /* *p == *q == 0 */
if(*p != *q)
return (*p - *q);
}
/* 1st len chars are same */
return 0;
}
void
makedimlist(OClist* path, OClist* dims)
{
unsigned int i,j;
for(i=0;i<oclistlength(path);i++) {
OCnode* node = (OCnode*)oclistget(path,i);
unsigned int rank = node->array.rank;
for(j=0;j<rank;j++) {
OCnode* dim = (OCnode*)oclistget(node->array.dimensions,j);
oclistpush(dims,(ocelem)dim);
}
}
}
void
ocfreeprojectionclause(OCprojectionclause* clause)
{
if(clause->target != NULL) free(clause->target);
while(oclistlength(clause->indexsets) > 0) {
OClist* slices = (OClist*)oclistpop(clause->indexsets);
while(oclistlength(slices) > 0) {
OCslice* slice = (OCslice*)oclistpop(slices);
if(slice != NULL) free(slice);
}
oclistfree(slices);
}
oclistfree(clause->indexsets);
free(clause);
}
static void
freeAttributes(OClist* attset)
{
unsigned int i,j;
for(i=0;i<oclistlength(attset);i++) {
OCattribute* att = (OCattribute*)oclistget(attset,i);
if(att->name != NULL) free(att->name);
if(att->etype == OC_String || att->etype == OC_URL) {
for(j=0;j<att->nvalues;j++) {
char* s = ((char**)att->values)[j];
if(s != NULL) free(s);
}
} else {
free(att->values);
}
}
}
void
freeOCnode(OCnode* cdf, int deep)
{
unsigned int i;
if(cdf == NULL) return;
if(cdf->name != NULL) free(cdf->name);
if(cdf->fullname != NULL) free(cdf->fullname);
if(cdf->attributes != NULL) freeAttributes(cdf->attributes);
if(cdf->subnodes != NULL) {
if(deep) {
for(i=0;i<oclistlength(cdf->subnodes);i++) {
OCnode* node = (OCnode*)oclistget(cdf->subnodes,i);
freeOCnode(node,deep);
}
}
oclistfree(cdf->subnodes);
}
free(cdf);
}
int
findbod(OCbytes* buffer, size_t* bodp, size_t* ddslenp)
{
unsigned int i;
char* content;
size_t len = ocbyteslength(buffer);
char** marks;
content = ocbytescontents(buffer);
for(marks = DDSdatamarks;*marks;marks++) {
char* mark = *marks;
int tlen = strlen(mark);
for(i=0;i<len;i++) {
if((i+tlen) <= len
&& (ocstrncmp(content+i,mark,tlen)==0)) {
*ddslenp = i;
i += tlen;
*bodp = i;
return 1;
}
}
}
*ddslenp = 0;
*bodp = 0;
return 0; /* tag not found; not necessarily an error*/
}
/* Compute total # of elements if dimensioned*/
size_t
totaldimsize(OCnode* node)
{
unsigned int i;
size_t count = 1;
for(i=0;i<node->array.rank;i++) {
OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
count *= (dim->dim.declsize);
}
return count;
}
#ifdef OCIGNORE
size_t
totaldimsize(unsigned int rank, size_t* dimsizes)
{
unsigned int i;
int unlim = 0;
unsigned long size = 1;
for(i=0;i<rank;i++) {
if(dimsizes[i] != 0) size = (size * dimsizes[i]); else unlim = 1;
}
return size;
}
#endif
size_t
octypesize(OCtype etype)
{
switch (etype) {
case OC_Char: return sizeof(char);
case OC_Byte: return sizeof(signed char);
case OC_UByte: return sizeof(unsigned char);
case OC_Int16: return sizeof(short);
case OC_UInt16: return sizeof(unsigned short);
case OC_Int32: return sizeof(int);
case OC_UInt32: return sizeof(unsigned int);
case OC_Float32: return sizeof(float);
case OC_Float64: return sizeof(double);
#ifdef HAVE_LONG_LONG_INT
case OC_Int64: return sizeof(long long);
case OC_UInt64: return sizeof(unsigned long long);
#endif
case OC_String: return sizeof(char*);
case OC_URL: return sizeof(char*);
default: break; /* Ignore all others */
}
return 0;
}
char*
octypetostring(OCtype octype)
{
switch (octype) {
case OC_NAT: return "OC_NAT";
case OC_Char: return "OC_Char";
case OC_Byte: return "OC_Byte";
case OC_UByte: return "OC_UByte";
case OC_Int16: return "OC_Int16";
case OC_UInt16: return "OC_UInt16";
case OC_Int32: return "OC_Int32";
case OC_UInt32: return "OC_UInt32";
case OC_Int64: return "OC_Int64";
case OC_UInt64: return "OC_UInt64";
case OC_Float32: return "OC_Float32";
case OC_Float64: return "OC_Float64";
case OC_String: return "OC_String";
case OC_URL: return "OC_URL";
/* Non-primitives*/
case OC_Dataset: return "OC_Dataset";
case OC_Sequence: return "OC_Sequence";
case OC_Grid: return "OC_Grid";
case OC_Structure: return "OC_Structure";
case OC_Dimension: return "OC_Dimension";
case OC_Attribute: return "OC_Attribute";
case OC_Attributeset: return "OC_Attributeset";
case OC_Primitive: return "OC_Primitive";
default: break;
}
return NULL;
}
char*
octypetoddsstring(OCtype octype)
{
switch (octype) {
case OC_Byte: return "Byte";
case OC_Int16: return "Int16";
case OC_UInt16: return "UInt16";
case OC_Int32: return "Int32";
case OC_UInt32: return "UInt32";
case OC_Float32: return "Float32";
case OC_Float64: return "Float64";
case OC_String: return "String";
case OC_URL: return "Url";
default: break;
}
return "<unknown>";
}
OCerror
octypeprint(OCtype etype, char* buf, size_t bufsize, void* value)
{
if(buf == NULL || bufsize == 0 || value == NULL) return OC_EINVAL;
buf[0] = '\0';
switch (etype) {
case OC_Char:
snprintf(buf,bufsize,"'%c'",*(char*)value);
break;
case OC_Byte:
snprintf(buf,bufsize,"%d",*(signed char*)value);
break;
case OC_UByte:
snprintf(buf,bufsize,"%u",*(unsigned char*)value);
break;
case OC_Int16:
snprintf(buf,bufsize,"%d",*(short*)value);
break;
case OC_UInt16:
snprintf(buf,bufsize,"%u",*(unsigned short*)value);
break;
case OC_Int32:
snprintf(buf,bufsize,"%d",*(int*)value);
break;
case OC_UInt32:
snprintf(buf,bufsize,"%u",*(unsigned int*)value);
break;
case OC_Float32:
snprintf(buf,bufsize,"%g",*(float*)value);
break;
case OC_Float64:
snprintf(buf,bufsize,"%g",*(double*)value);
break;
#ifdef HAVE_LONG_LONG_INT
case OC_Int64:
snprintf(buf,bufsize,"%lld",*(long long*)value);
break;
case OC_UInt64:
snprintf(buf,bufsize,"%llu",*(unsigned long long*)value);
break;
#endif
case OC_String:
case OC_URL: {
char* s = *(char**)value;
snprintf(buf,bufsize,"\"%s\"",s);
} break;
default: break;
}
return OC_NOERR;
}
size_t
xxdrsize(OCtype etype)
{
switch (etype) {
case OC_Char:
case OC_Byte:
case OC_UByte:
case OC_Int16:
case OC_UInt16:
case OC_Int32:
case OC_UInt32:
return XDRUNIT;
case OC_Int64:
case OC_UInt64:
return (2*XDRUNIT);
case OC_Float32:
return XDRUNIT;
case OC_Float64:
return (2*XDRUNIT);
case OC_String:
case OC_URL:
default: break;
}
return 0;
}
/**************************************/
char*
ocerrstring(int err)
{
if(err == 0) return "no error";
if(err > 0) return strerror(err);
switch (err) {
case OC_EBADID:
return "OC_EBADID: Not a valid ID";
case OC_EINVAL:
return "OC_EINVAL: Invalid argument";
case OC_EPERM:
return "OC_EPERM: Write to read only";
case OC_EINVALCOORDS:
return "OC_EINVALCOORDS: Index exceeds dimension bound";
case OC_ENOTVAR:
return "OC_ENOTVAR: Variable not found";
case OC_ECHAR:
return "OC_ECHAR: Attempt to convert between text & numbers";
case OC_EEDGE:
return "OC_EEDGE: Start+count exceeds dimension bound";
case OC_ESTRIDE:
return "OC_ESTRIDE: Illegal stride";
case OC_ENOMEM:
return "OC_ENOMEM: Memory allocation (malloc) failure";
case OC_EDIMSIZE:
return "OC_EDIMSIZE: Invalid dimension size";
case OC_EDAP:
return "OC_EDAP: DAP failure";
case OC_EXDR:
return "OC_EXDR: XDR failure";
case OC_ECURL:
return "OC_ECURL: libcurl failure";
case OC_EBADURL:
return "OC_EBADURL: malformed url";
case OC_EBADVAR:
return "OC_EBADVAR: no such variable";
case OC_EOPEN:
return "OC_EOPEN: temporary file open failed";
case OC_EIO:
return "OC_EIO: I/O failure";
case OC_ENODATA:
return "OC_ENODATA: Variable has no data in DAP request";
case OC_EDAPSVC:
return "OC_EDAPSVC: DAP Server error";
case OC_ENAMEINUSE:
return "OC_ENAMEINUSE: Duplicate name in DDS";
case OC_EDAS:
return "OC_EDAS: Malformed or unreadable DAS";
case OC_EDDS:
return "OC_EDDS: Malformed or unreadable DDS";
case OC_EDATADDS:
return "OC_EDATADDS: Malformed or unreadable DATADDS";
case OC_ERCFILE:
return "OC_ERCFILE: Malformed or unreadable run-time configuration file";
case OC_ENOFILE:
return "OC_ENOFILE: cannot read content of URL";
default: break;
}
return "<unknown error code>";
}
OCerror
ocsvcerrordata(OCstate* state, char** codep, char** msgp, long* httpp)
{
if(codep) *codep = state->error.code;
if(msgp) *msgp = state->error.message;
if(httpp) *httpp = state->error.httpcode;
return OC_NOERR;
}
/* if we get OC_EDATADDS error, then try to capture any
error message and log it; assumes that in this case,
the datadds is not big.
*/
void
ocdataddsmsg(OCstate* state, OCtree* tree)
{
#define ERRCHUNK 1024
#define ERRFILL ' '
#define ERRTAG "Error {"
unsigned int i,j,len;
XXDR* xdrs;
char* contents;
off_t ckp;
if(tree == NULL) return;
/* get available space */
xdrs = tree->data.xdrs;
len = xxdr_length(xdrs);
if(len < strlen(ERRTAG))
return; /* no room */
ckp = xxdr_getpos(xdrs);
xxdr_setpos(xdrs,0);
/* read the whole thing */
contents = (char*)malloc(len+1);
xxdr_getbytes(xdrs,contents,len);
contents[len] = '\0';
/* Look for error tag */
for(i=0;i<len;i++) {
if(ocstrncmp(contents+i,ERRTAG,strlen(ERRTAG))==0) {
/* log the error message */
/* Do a quick and dirty escape */
for(j=i;j<len;j++) {
int c = contents[i+j];
if(c > 0 && (c < ' ' || c >= '\177'))
contents[i+j] = ERRFILL;
}
oc_log(LOGERR,"DATADDS failure, possible message: '%s'\n",
contents+i);
goto done;
}
}
xxdr_setpos(xdrs,ckp);
done:
return;
}

View File

@ -1,36 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
#ifndef OCUTIL_H
#define OCUTIL_H 1
/* Forward */
struct OCstate;
#define ocmax(x,y) ((x) > (y) ? (x) : (y))
extern char* ocstrndup(const char* s, size_t len);
extern int ocstrncmp(const char* s1, const char* s2, size_t len);
extern size_t octypesize(OCtype etype);
extern char* octypetostring(OCtype octype);
extern char* octypetoddsstring(OCtype octype);
extern char* ocerrstring(int err);
extern OCerror ocsvcerrordata(struct OCstate*,char**,char**,long*);
extern OCerror octypeprint(OCtype etype, char* buf, size_t bufsize, void* value);
extern size_t xxdrsize(OCtype etype);
extern size_t totaldimsize(OCnode*);
extern void makedimlist(OClist* path, OClist* dims);
extern int findbod(OCbytes* buffer, size_t*, size_t*);
/* Reclaimers*/
extern void freeOCnode(OCnode*,int);
extern void ocfreeprojectionclause(OCprojectionclause* clause);
/* Misc. */
extern void ocdataddsmsg(struct OCstate*, struct OCtree*);
#endif /*UTIL_H*/

View File

@ -1,243 +0,0 @@
/* @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";
#endif
/*
* xdr_stdio.c, XDR implementation on standard i/o file.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* This set of routines implements a XDR on a stdio stream.
* XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
* from the stream.
*/
/*
Modified to track the current position to avoid
the file io operation.
Not sure if this worth the effort because
I don't actually know the cost to doing
an fseek
*/
#include "config.h"
#include "ocinternal.h"
#ifdef HAVE_RPC_TYPES_H
#include <rpc/types.h>
#endif
#ifdef WIN32
#include <winsock2.h>
#define strcasecmp stricmp
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#endif
#include <stdio.h>
#ifdef HAVE_RPC_XDR_H
#include <rpc/xdr.h>
#else
#include <xdr.h>
#endif
#ifdef _AIX
#include <netinet/in.h>
#endif
static bool_t xxdrstdio_getlong();
static bool_t xxdrstdio_putlong();
static bool_t xxdrstdio_getbytes();
static bool_t xxdrstdio_putbytes();
static u_int xxdrstdio_getpos();
static bool_t xxdrstdio_setpos();
static int * xxdrstdio_inline();
static void xxdrstdio_destroy();
/* Need this to keep AIX quiet */
#ifdef _AIX
typedef long* (*LOCALINLINE)();
#endif
/*
* Ops vector for stdio type XDR
*/
static struct xdr_ops xxdrstdio_ops = {
xxdrstdio_getlong, /* deseraialize a 32 bit int */
xxdrstdio_putlong, /* seraialize a 32 bit int */
xxdrstdio_getbytes, /* deserialize counted bytes */
xxdrstdio_putbytes, /* serialize counted bytes */
xxdrstdio_getpos, /* get offset in the stream */
xxdrstdio_setpos, /* set offset in the stream */
#ifdef _AIX
(LOCALINLINE)xxdrstdio_inline, /* prime stream for inline macros */
#else
xxdrstdio_inline, /* prime stream for inline macros */
#endif
xxdrstdio_destroy /* destroy stream */
};
/*
* Initialize a stdio xdr stream.
* Sets the xdr stream handle xdrs for use on the stream file.
* Operation flag is set to op.
*/
void
xxdrstdio_create(xdrs, file, op)
register XDR *xdrs;
FILE *file;
enum xdr_op op;
{
xdrs->x_op = op;
xdrs->x_ops = &xxdrstdio_ops;
xdrs->x_private = (caddr_t)file;
xdrs->x_handy = 0;
xdrs->x_base = 0;
xdrs->x_public = 0;
}
/*
* Destroy a stdio xdr stream.
* Cleans up the xdr stream handle xdrs previously set up by xxdrstdio_create.
*/
static void
xxdrstdio_destroy(xdrs)
register XDR *xdrs;
{
(void)fflush((FILE *)xdrs->x_private);
/* xx should we close the file ?? */
}
static bool_t
xxdrstdio_getlong(xdrs, lp)
XDR *xdrs;
register unsigned int *lp;
{
#ifdef OCIGNORE
FILE* f = (FILE*)xdrs->x_private;
long fpos = ftell(f);
#endif
if(fread((caddr_t)lp,sizeof(unsigned int),1,(FILE *)(xdrs->x_private)) != 1)
return (FALSE);
#ifndef mc68000
*lp = ocntoh(*lp);
#endif
xdrs->x_public += sizeof(unsigned int);
return (TRUE);
}
static bool_t
xxdrstdio_putlong(xdrs, lp)
XDR *xdrs;
unsigned int* lp;
{
#ifndef mc68000
unsigned int mycopy = ochton(*lp);
lp = &mycopy;
#endif
if(fwrite((caddr_t)lp, sizeof(unsigned int), 1, (FILE *)xdrs->x_private) != 1)
return (FALSE);
xdrs->x_public += sizeof(unsigned int);
return (TRUE);
}
static bool_t
xxdrstdio_getbytes(xdrs, addr, len)
XDR *xdrs;
caddr_t addr;
u_int len;
{
if((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
return (FALSE);
xdrs->x_public += len;
return (TRUE);
}
static bool_t
xxdrstdio_putbytes(xdrs, addr, len)
XDR *xdrs;
caddr_t addr;
u_int len;
{
if((len != 0)
&& (fwrite(addr,(int)len,1,(FILE *)xdrs->x_private) != 1))
return (FALSE);
xdrs->x_public += len;
return (TRUE);
}
static u_int
xxdrstdio_getpos(xdrs)
XDR *xdrs;
{
unsigned long result = (unsigned long)xdrs->x_public;
return (unsigned int) result;
/* return ((u_int) ftell((FILE *)xdrs->x_private)); */
}
static bool_t
xxdrstdio_setpos(xdrs, pos)
XDR *xdrs;
u_int pos;
{
if(pos == (unsigned long)xdrs->x_public) return TRUE;
xdrs->x_public = (caddr_t)(unsigned long)pos;
return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
FALSE : TRUE);
}
static int *
xxdrstdio_inline(xdrs, len)
XDR *xdrs;
u_int len;
{
/*
* Must do some work to implement this: must insure
* enough data in the underlying stdio buffer,
* that the buffer is aligned so that we can indirect through a
* long *, and stuff this pointer in xdrs->x_buf. Doing
* a fread or fwrite to a scratch buffer would defeat
* most of the gains to be had here and require storage
* management on this buffer, so we don't do this.
*/
return (NULL);
}

463
oc/xxdr.c
View File

@ -1,463 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information. */
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* from: @(#)xdr.h 1.19 87/04/22 SMI
* from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
* $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $
* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $
*/
/* Define our own implementation of the needed
elements of XDR. Assumes read-only
*/
#undef XXDRTRACE
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "xxdr.h"
int xxdr_network_order; /* network order is big endian */
static int xxdr_big_endian; /* what is this machine? */
#ifdef XXDRTRACE
static void
xxdrtrace(XXDR* xdr, char* where, off_t arg)
{
fprintf(stderr,"xxdr: %s: arg=%ld ; pos=%ld len=%ld\n",
where,arg,(long)xdr->pos,(long)xdr->length);
fflush(stderr);
}
#else
#define xxdrtrace(x,y,z)
#endif
/* Read-only operations */
int xxdr_getbytes(XXDR* xdrs, char* memory, off_t count)
{
if(!memory) return 0;
if(!xdrs->getbytes(xdrs,memory,count))
return 0;
return 1;
}
/* get a unsigned int from underlying stream*/
int
xxdr_uint(XXDR* xdr, unsigned int* ip)
{
if(!ip) return 0;
if(!xdr->getbytes(xdr,(char*)ip,sizeof(*ip)))
return 0;
/*convert from network order*/
if(!xxdr_network_order) {
swapinline32(ip);
}
return 1;
}
/* get a long long from underlying stream*/
int
xxdr_ulonglong(XXDR* xdr, unsigned long* llp)
{
/* Pull two units */
if(!llp) return 0;
if(!xdr->getbytes(xdr,(char*)llp,sizeof(*llp)))
return 0;
/* Convert to signed/unsigned */
/*convert from network order*/
if(!xxdr_network_order) {
swapinline64(llp);
}
return 1;
}
/* get some bytes from underlying stream;
will move xdrs pointer to next XDRUNIT boundary*/
int
xxdr_opaque(XXDR* xdr, char* mem, off_t count)
{
off_t pos,rounded;
if(!xdr->getbytes(xdr,mem,count))
return 0;
pos = xxdr_getpos(xdr);
rounded = RNDUP(pos);
return xxdr_skip(xdr,(rounded - pos));
}
/* get counted string from underlying stream*/
int
xxdr_string(XXDR* xdrs, char** sp, off_t* lenp)
{
char* s;
unsigned int len;
if(!xxdr_uint(xdrs,&len)) return 0;
s = (char*)malloc((off_t)len+1);
if(s == NULL) return 0;
if(!xxdr_opaque(xdrs,s,len)) {
free((void*)s);
return 0;
}
s[len] = '\0'; /* make sure it is null terminated */
if(sp) *sp = s;
if(lenp) *lenp = len;
/* xxdr_opaque will have skippped any trailing bytes */
return 1;
}
/* returns bytes off from beginning*/
off_t
xxdr_getpos(XXDR* xdr)
{
return xdr->getpos(xdr);
}
/* reposition the stream*/
int
xxdr_setpos(XXDR* xdr, off_t pos)
{
return xdr->setpos(xdr,pos);
}
/* returns total available starting at current position */
off_t
xxdr_getavail(XXDR* xdr)
{
return xdr->getavail(xdr);
}
/* free up XXDR structure */
void
xxdr_free(XXDR* xdr)
{
xdr->free(xdr);
}
/***********************************/
/* Skip exacly "len" bytes in the input; any rounding must be done by the caller*/
int
xxdr_skip(XXDR* xdrs, off_t len)
{
unsigned int pos;
pos = xxdr_getpos(xdrs);
pos = (pos + len);
if(pos < 0) pos = 0;
return xxdr_setpos(xdrs,pos);
}
/* skip "n" string/bytestring instances in the input*/
int
xxdr_skip_strings(XXDR* xdrs, off_t n)
{
while(n-- > 0) {
unsigned int slen;
if(!xxdr_uint(xdrs,&slen)) return 0;
slen = RNDUP(slen);
if(xxdr_skip(xdrs,slen)) return 0;
}
return 1;
}
unsigned int
xdr_roundup(unsigned int n)
{
unsigned int rounded;
rounded = RNDUP(n);
return rounded;
}
unsigned int
ocbyteswap(unsigned int i)
{
unsigned int swap,b0,b1,b2,b3;
b0 = (i>>24) & 0x000000ff;
b1 = (i>>16) & 0x000000ff;
b2 = (i>>8) & 0x000000ff;
b3 = (i) & 0x000000ff;
swap = (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
return swap;
}
/**************************************************/
/* File based xdr */
static void
xxdr_filefree(XXDR* xdrs)
{
if(xdrs != NULL) {
(void)fflush((FILE *)xdrs->data);
free(xdrs);
}
}
static int
xxdr_filegetbytes(XXDR* xdrs, char* addr, off_t len)
{
int ok = 1;
int count;
xxdrtrace(xdrs,"getbytes",len);
if(len < 0) len = 0;
if(!xdrs->valid)
{
if(fseek((FILE *)xdrs->data, xdrs->pos + xdrs->base, 0) != 0) {
ok=0;
goto done;
}
xdrs->valid = 1;
}
if(xdrs->pos + len > xdrs->length)
return 0;
if(len > 0) {
count = fread(addr, len, 1, (FILE*)xdrs->data);
if(count <= 0) {
ok=0;
goto done;
}
}
xdrs->pos += len;
done:
return ok;
}
static off_t
xxdr_filegetpos(XXDR* xdrs)
{
xxdrtrace(xdrs,"getpos",0);
return xdrs->pos;
}
static off_t
xxdr_filegetavail(XXDR* xdrs)
{
xxdrtrace(xdrs,"getavail",0);
return (xdrs->length - xdrs->pos);
}
static int
xxdr_filesetpos(XXDR* xdrs, off_t pos)
{
int ok = 1;
xxdrtrace(xdrs,"setpos",pos);
if(pos == xdrs->pos) goto done;
if(pos < 0) pos = 0;
if(pos > xdrs->length) {ok=0;goto done;}
xdrs->pos = pos;
xdrs->valid = 0;
done:
return ok;
}
/*
Modified to track the current position to avoid the file io
operation. Not sure if this worth the effort because I
don't actually know the cost to doing an fseek
*/
/*
* Initialize a stdio xdr stream.
* Sets the xdr stream handle xdrs for use on the stream file.
* Operation flag is set to op.
*/
XXDR*
xxdr_filecreate(FILE* file, off_t base)
{
XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
if(xdrs != NULL) {
xdrs->data = (void*)file;
xdrs->base = base;
xdrs->pos = 0;
xdrs->valid = 0;
if(fseek(file,0L,SEEK_END)) return NULL;
xdrs->length = (off_t)ftell(file);
xdrs->length -= xdrs->base;
xdrs->getbytes = xxdr_filegetbytes;
xdrs->setpos = xxdr_filesetpos;
xdrs->getpos = xxdr_filegetpos;
xdrs->getavail = xxdr_filegetavail;
xdrs->free = xxdr_filefree;
}
xxdrtrace(xdrs,"create",base);
return xdrs;
}
/**************************************************/
/* memory based xdr */
static void
xxdr_memfree(XXDR* xdrs)
{
if(xdrs != NULL) {
free(xdrs);
}
}
static int
xxdr_memgetbytes(XXDR* xdrs, char* addr, off_t len)
{
int ok = 1;
xxdrtrace(xdrs,"getbytes",len);
if(len < 0) len = 0;
if(xdrs->pos+len > xdrs->length) {ok=0; goto done;}
if(len > 0) {
memcpy(addr,(char*)xdrs->data+xdrs->base+xdrs->pos, len);
}
xdrs->pos += len;
done:
return ok;
}
static off_t
xxdr_memgetpos(XXDR* xdrs)
{
xxdrtrace(xdrs,"getpos",0);
return xdrs->pos;
}
static off_t
xxdr_memgetavail(XXDR* xdrs)
{
xxdrtrace(xdrs,"getavail",0);
return (xdrs->length - xdrs->pos);
}
static int
xxdr_memsetpos(XXDR* xdrs, off_t pos)
{
int ok = 1;
xxdrtrace(xdrs,"setpos",pos);
if(pos == xdrs->pos) goto done;
if(pos > xdrs->length) {ok=0; goto done;}
xdrs->pos = pos;
done:
return ok;
}
/*
Modified to track the current position to avoid the file io
operation. Not sure if this worth the effort because I
don't actually know the cost to doing an fseek
*/
/*
* Initialize a stdio xdr stream.
* Sets the xdr stream handle xdrs for use on the
* given memory starting at base offset.
*/
XXDR*
xxdr_memcreate(char* mem, off_t memsize, off_t base)
{
XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
if(xdrs != NULL) {
/* zero base memory */
xdrs->data = (void*)(mem + base);
xdrs->base = 0;
xdrs->length = memsize - base;
xdrs->pos = 0;
xdrs->getbytes = xxdr_memgetbytes;
xdrs->setpos = xxdr_memsetpos;
xdrs->getpos = xxdr_memgetpos;
xdrs->getavail = xxdr_memgetavail;
xdrs->free = xxdr_memfree;
}
xxdrtrace(xdrs,"create",base);
return xdrs;
}
/* Float utility types */
/* get a float from underlying stream*/
int
xxdr_float(XXDR* xdr, float* fp)
{
int status = 0;
float f;
unsigned int* data = (unsigned int*)&f;
/* Pull one unit directly into a float */
status = xxdr_uint(xdr,data);
if(status && fp)
*fp = f;
return status;
}
/* Get a double from underlying stream */
int
xxdr_double(XXDR* xdr, double* dp)
{
int status = 0;
char data[2*XDRUNIT];
/* Pull two units */
status = xxdr_opaque(xdr,data,2*XDRUNIT);
if(status && dp) {
xxdrntohdouble(data,dp);
}
return status;
}
/* Double needs special handling */
void
xxdrntohdouble(char* c8, double* dp)
{
unsigned int ii[2];
memcpy(ii,c8,2*XDRUNIT);
if(!xxdr_big_endian) {
unsigned int tmp;
/* reverse byte order */
swapinline32(&ii[0]);
swapinline32(&ii[1]);
/* interchange ii[0] and ii[1] */
tmp = ii[0];
ii[0] = ii[1];
ii[1] = tmp;
}
if(dp) *dp = *(double*)ii;
}
void
xxdr_init()
{
/* Compute if we are same as network order v-a-v xdr */
int testint = 0x00000001;
char *byte = (char *)&testint;
xxdr_big_endian = (byte[0] == 0 ? 1 : 0);
xxdr_network_order = xxdr_big_endian;
}

183
oc/xxdr.h
View File

@ -1,183 +0,0 @@
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
See the COPYRIGHT file for more information.
*/
/*
* Copyright (c) 2009, Sun Microsystems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Sun Microsystems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* from: @(#)xdr.h 1.19 87/04/22 SMI
* from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
* $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $
* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $
*/
/* Define our own implementation of the needed
elements of XDR. Assumes read-only
*/
#ifndef XXDR_H
#define XXDR_H
/*
* This is the number of bytes per unit of external data.
*/
#define XDRUNIT (4)
#if 1
/* faster version when XDRUNIT is a power of two */
# define RNDUP(x) (((x) + XDRUNIT - 1) & ~(XDRUNIT - 1))
#else /* old version */
#define RNDUP(x) ((((x) + XDRUNIT - 1) / XDRUNIT) \
* XDRUNIT)
#endif
/* signature: void swapinline32(unsigned int* ip) */
#define swapinline32(ip) \
{ \
char dst[4]; \
char* src = (char*)(ip); \
dst[0] = src[3]; \
dst[1] = src[2]; \
dst[2] = src[1]; \
dst[3] = src[0]; \
*(ip) = *((unsigned int*)dst); \
}
/* signature: void swapinline64(unsigned long long* ip) */
#define swapinline64(ip) \
{ \
char dst[8]; \
char* src = (char*)(ip); \
dst[0] = src[7]; \
dst[1] = src[6]; \
dst[2] = src[5]; \
dst[3] = src[4]; \
dst[4] = src[3]; \
dst[5] = src[2]; \
dst[6] = src[1]; \
dst[7] = src[0]; \
*ip = *((unsigned long long*)dst); \
}
#ifdef OCIGNORE
/* Warning dst and src should not be the same memory (assert &iswap != &i) */
#define xxdrntoh(dst,src) if(xxdr_network_order){dst=src;}else{swapinline32(dst,src);}
#define xxdrntohll(dst,src) if(xxdr_network_order){dst=src;}else{swapinline64(dst,src);}
#define xxdrhton(dst,src) xxdrntoh(dst,src)
#define xxdrhtonll(dst,src) xxdrntohll(dst,src)
#endif
/* Double needs special handling */
extern void xxdrntohdouble(char*,double*);
/*
* The XDR handle.
* Contains operation which is being applied to the stream,
* an operations vector for the particular implementation (e.g. see xdr_mem.c),
* and two private fields for the use of the particular implementation.
*/
typedef struct XXDR XXDR; /* forward */
/* Assume |off_t| == |void*| */
struct XXDR {
char* data;
off_t pos; /* relative to data;
may be a cache of underlying stream pos */
int valid; /* 1=>underlying stream pos == pos */
off_t base; /* beginning of data in case bod != 0*/
off_t length; /* total size of available data (relative to base)*/
/* Define minimum needed case specific operators */
int (*getbytes)(XXDR*,char*,off_t);
int (*setpos)(XXDR*,off_t);
off_t (*getpos)(XXDR*);
off_t (*getavail)(XXDR*);
void (*free)(XXDR*); /* xdr kind specific free function */
};
/* Track network order */
extern int xxdr_network_order; /* does this machine match network order? */
/* Read-only operations */
/* Get exactly count bytes from underlying
stream; unlike opaque, this will
not round up to the XDRUNIT boundary
*/
extern int xxdr_getbytes(XXDR*,char*,off_t);
/* get an int from underlying stream*/
extern int xxdr_uint(XXDR* , unsigned int*);
/* get an int from underlying stream*/
extern int xxdr_ulonglong(XXDR* , unsigned long*);
/* get a float from underlying stream*/
extern int xxdr_float(XXDR* , float*);
/* get a double from underlying stream*/
extern int xxdr_double(XXDR* , double*);
/* get some bytes from underlying stream;
Warning: will read upto the next XDRUNIT boundary
*/
extern int xxdr_opaque(XXDR*, char*, off_t);
/* get counted string from underlying stream*/
extern int xxdr_string(XXDR*, char**, off_t*);
/* returns bytes off from beginning*/
extern off_t xxdr_getpos(XXDR*);
/* reposition the stream*/
extern int xxdr_setpos(XXDR*, off_t);
/* get remaining data available starting at current position */
extern off_t xxdr_getavail(XXDR*);
/* free up XXDR structure */
void xxdr_free(XXDR*);
/* File and memory creators */
extern XXDR* xxdr_filecreate(FILE* file, off_t bod);
extern XXDR* xxdr_memcreate(char* mem, off_t memsize, off_t bod);
/* Misc */
extern int xxdr_skip(XXDR* xdrs, off_t len); /* WARNING: will skip exactly len bytes;
any rounding must be done by caller */
extern int xxdr_skip_strings(XXDR* xdrs, off_t n);
extern unsigned int xxdr_roundup(off_t n); /* procedural version of RNDUP macro */
extern void xxdr_init();
/* Define some inlines */
#define xxdr_length(xdrs) ((xdrs)->length)
#endif /*XXDR_H*/

View File

@ -420,6 +420,7 @@ dap_parse_error(DAPparsestate* state, const char *fmt, ...)
(void) fprintf(stderr,"^%s\n",tmp);
(void) fflush(stderr); /* to ensure log files are current */
ocfree(tmp);
va_end(argv);
}
static void

View File

@ -180,13 +180,13 @@ a DAS, DDS, or DATADDS request exactly as sent by the server.
const char*
oc_tree_text(OCobject link, OCobject ddsroot)
{
OCnode* root;
OCnode* root = NULL;
OCVERIFYX(OC_Node,ddsroot,NULL);
OCDEREF(OCnode*,root,ddsroot);
if(root == NULL) return NULL;
root = root->root;
if(root == NULL) return NULL;
if(root->tree == NULL) return NULL;
return root->tree->text;
}

View File

@ -44,11 +44,11 @@ EXTERNC int ocbytescat(OCbytes*,const char*);
EXTERNC int ocbytessetcontents(OCbytes*, char*, unsigned int);
/* Following are always "in-lined"*/
#define ocbyteslength(bb) ((bb)?(bb)->length:0U)
#define ocbytesalloc(bb) ((bb)?(bb)->alloc:0U)
#define ocbytescontents(bb) ((bb && bb->content)?(bb)->content:(char*)"")
#define ocbyteslength(bb) ((bb)!=NULL?(bb)->length:0U)
#define ocbytesalloc(bb) ((bb)!=NULL?(bb)->alloc:0U)
#define ocbytescontents(bb) (((bb) !=NULL && (bb)->content != NULL)?(bb)->content:(char*)"")
#define ocbytesextend(bb,len) ocbytessetalloc((bb),(len)+(bb->alloc))
#define ocbytesclear(bb) ((bb)?(bb)->length=0:0U)
#define ocbytesavail(bb,n) ((bb)?((bb)->alloc - (bb)->length) >= (n):0U)
#define ocbytesclear(bb) ((bb)!=NULL?(bb)->length=0:0U)
#define ocbytesavail(bb,n) ((bb)!=NULL?((bb)->alloc - (bb)->length) >= (n):0U)
#endif /*OCBYTES_H*/

View File

@ -95,7 +95,7 @@ occompile1(OCstate* state, OCnode* xnode, XXDR* xxdrs, OCdata** datap)
fset(data->datamode,OCDT_ARRAY);
/* Determine # of instances */
nelements = octotaldimsize(xnode->array.rank,xnode->array.sizes);
if(nelements == 0) return OCTHROW(OC_ENODATA);
if(nelements == 0) {ocstat = OCTHROW(OC_ENODATA); goto fail;}
/* Validate and skip the leading count field */
if(!xxdr_uint(xxdrs,&xdrcount))
{ocstat = OC_EXDR; goto fail;}
@ -187,10 +187,10 @@ fail:
if(records != NULL) {
for(i=0;i<oclistlength(records);i++)
ocdata_free(state,(OCdata*)oclistget(records,i));
oclistfree(records);
}
if(data != NULL && data->instances != NULL) {
for(i=0;i<data->ninstances;i++)
ocdata_free(state,data->instances[i]);
if(data != NULL) {
ocdata_free(state,data);
}
return OCTHROW(ocstat);
}
@ -221,6 +221,7 @@ occompilefields(OCstate* state, OCdata* data, XXDR* xxdrs)
size_t nelements;
OCnode* xnode = data->template;
assert(data != NULL);
nelements = oclistlength(xnode->subnodes);
if(nelements == 0)
goto done;
@ -245,9 +246,10 @@ done:
return OCTHROW(ocstat);
fail:
if(data != NULL && data->instances != NULL) {
if(data->instances != NULL) {
for(i=0;i<data->ninstances;i++)
ocdata_free(state,data->instances[i]);
data->ninstances = 0;
}
return OCTHROW(ocstat);
}
@ -353,6 +355,7 @@ ocdata_free(OCstate* state, OCdata* data)
}
if(data->strings != NULL)
free(data->strings);
free(data);
}
static OCdata*

View File

@ -37,6 +37,7 @@
#define OCDBG2(l,msg,arg1,arg2) {oc_log(LOGDBG,msg,arg1,arg2);}
#define OCDBGTEXT(l,text) {oc_logtext(LOGNOTE,text);} else {}
#define OCDBGCODE(l,code) {code;}
#else
#define OCDBG(l,msg)
#define OCDBG1(l,msg,arg)

View File

@ -21,7 +21,7 @@
/* Note: TMPPATH must end in '/' */
#ifdef __CYGWIN__
#define TMPPATH1 "c:/temp/"
#define TMPPATH1 "/cygdrive/c/temp/"
#define TMPPATH2 "./"
#elif WIN32
#define TMPPATH1 "c:\\temp\\"
@ -208,7 +208,7 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
so that DRNO can reference it*/
/* Make the tmp file*/
stat = createtempfile(state,tree);
if(stat) {OCTHROWCHK(stat); goto unwind;}
if(stat) {OCTHROWCHK(stat); goto fail;}
stat = readDATADDS(state,tree,flags);
if(stat == OC_NOERR) {
/* Separate the DDS from data and return the dds;
@ -235,7 +235,7 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
} else {
oc_log(LOGWARN,"oc_open: Could not read url");
}
return OCTHROW(stat);
goto fail;
}
tree->nodes = NULL;
@ -246,7 +246,7 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
state->error.code,
(state->error.message?state->error.message:""));
}
if(stat) {OCTHROWCHK(stat); goto unwind;}
if(stat) {OCTHROWCHK(stat); goto fail;}
root = tree->root;
/* make sure */
tree->root = root;
@ -256,15 +256,15 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
switch (kind) {
case OCDAS:
if(root->octype != OC_Attributeset)
{OCTHROWCHK(stat=OC_EDAS); goto unwind;}
{OCTHROWCHK(stat=OC_EDAS); goto fail;}
break;
case OCDDS:
if(root->octype != OC_Dataset)
{OCTHROWCHK(stat=OC_EDDS); goto unwind;}
{OCTHROWCHK(stat=OC_EDDS); goto fail;}
break;
case OCDATADDS:
if(root->octype != OC_Dataset)
{OCTHROWCHK(stat=OC_EDATADDS); goto unwind;}
{OCTHROWCHK(stat=OC_EDATADDS); goto fail;}
/* Modify the tree kind */
tree->dxdclass = OCDATADDS;
break;
@ -293,7 +293,7 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
/* Compile the data into a more accessible format */
stat = occompile(state,tree->root);
if(stat != OC_NOERR)
goto unwind;
goto fail;
}
/* Put root into the state->trees list */
@ -302,16 +302,18 @@ ocfetch(OCstate* state, const char* constraint, OCdxd kind, OCflags flags,
if(rootp) *rootp = root;
return stat;
unwind:
octree_free(tree);
fail:
if(root != NULL)
ocroot_free(root);
else if(tree != NULL)
octree_free(tree);
return OCTHROW(stat);
}
static OCerror
createtempfile(OCstate* state, OCtree* tree)
{
int fd;
int fd = 0;
char* name = NULL;
fd = createtempfile1(TMPPATH1,&name);
if(fd < 0)
@ -334,7 +336,7 @@ createtempfile(OCstate* state, OCtree* tree)
int
createtempfile1(char* tmppath, char** tmpnamep)
{
int fd;
int fd = 0;
char* tmpname = NULL;
tmpname = (char*)malloc(strlen(tmppath)+strlen("dataddsXXXXXX")+1);
if(tmpname == NULL) return -1;
@ -354,7 +356,7 @@ createtempfile1(char* tmppath, char** tmpnamep)
sprintf(spid,"%06d",rno);
strcat(tmpname,spid);
# ifdef WIN32
fd=open(tmpname,O_RDWR|O_BINARY|O_CREAT|O_EXCL|_O_SHORT_LIVED, _S_IREAD|_S_IWRITE);
fd=open(tmpname,O_RDWR|O_BINARY|O_CREAT|O_EXCL|FILE_ATTRIBUTE_TEMPORARY, _S_IREAD|_S_IWRITE);
# else
fd=open(tmpname,O_RDWR|O_CREAT|O_EXCL, S_IRWXU);
# endif

View File

@ -51,7 +51,7 @@ EXTERNC int oclistcontains(OClist*, ocelem);
#define oclistclear(l) oclistsetlength((l),0U)
#define oclistextend(l,len) oclistsetalloc((l),(len)+(l->alloc))
#define oclistcontents(l) ((l)->content)
#define oclistlength(l) ((l)?(l)->length:0U)
#define oclistlength(l) ((l!=NULL)?(l)->length:0U)
#endif /*OCLIST_H*/

View File

@ -32,9 +32,10 @@ oc_loginit(void)
oclogfile = NULL;
oclogstream = NULL;
/* Use environment variables to preset oclogging state*/
if(file != NULL) {
oc_setlogging(1);
oc_logopen(file);
if(file != NULL && strlen(file) > 0) {
if(oc_logopen(file)) {
oc_setlogging(1);
}
}
}
@ -76,6 +77,16 @@ oc_logopen(const char* file)
oclogstream = stderr;
oclogfile = NULL;
ocsystemfile = 1;
} else if(strcmp(file,"stdout") == 0) {
/* use stdout*/
oclogstream = stdout;
oclogfile = NULL;
ocsystemfile = 1;
} else if(strcmp(file,"stderr") == 0) {
/* use stderr*/
oclogstream = stderr;
oclogfile = NULL;
ocsystemfile = 1;
} else {
int fd;
oclogfile = (char*)malloc(strlen(file)+1);
@ -104,6 +115,7 @@ Logging is still enabled.
void
oc_logclose(void)
{
if(!ocloginit) oc_loginit();
if(oclogstream != NULL && !ocsystemfile) {
assert(oclogfile != NULL && oclogstream != NULL);
fclose(oclogstream);
@ -128,6 +140,8 @@ oc_log(int tag, const char* format, ...)
{
va_list args;
char* prefix;
if(!ocloginit) oc_loginit();
if(!oclogging || oclogstream == NULL) return;
switch (tag) {
@ -166,6 +180,7 @@ oc_logtext(int tag, const char* text)
size_t delta = 0;
const char* eol = text;
if(!ocloginit) oc_loginit();
if(!oclogging || oclogstream == NULL) return;
while(*text) {

View File

@ -143,7 +143,7 @@ makeattribute(char* name, OCtype ptype, OClist* values)
static void
marklostattribute(OCnode* att)
{
oc_log(LOGWARN,"Lost attribute: %s",att->name);
oc_log(LOGNOTE,"Lost attribute: %s",att->name);
}
void
@ -202,8 +202,12 @@ ocnodes_free(OClist* nodes)
while(oclistlength(node->attributes) > 0) {
OCattribute* attr = (OCattribute*)oclistpop(node->attributes);
ocfree(attr->name);
#if 0
/* If the attribute type is string, then we need to free them*/
if(attr->etype == OC_String || attr->etype == OC_URL) {
all values are strings now
if(attr->etype == OC_String || attr->etype == OC_URL)
#endif
{
char** strings = (char**)attr->values;
for(j=0;j<attr->nvalues;j++) {ocfree(*strings); strings++;}
}
@ -214,6 +218,7 @@ ocnodes_free(OClist* nodes)
if(node->subnodes != NULL) oclistfree(node->subnodes);
if(node->att.values != NULL) oclistfree(node->att.values);
if(node->attributes != NULL) oclistfree(node->attributes);
if(node->array.sizes != NULL) free(node->array.sizes);
ocfree(node);
}
oclistfree(nodes);
@ -236,9 +241,10 @@ As described there, the algorithm is as follows.
names to get each of those variables.
*/
int
OCerror
ocddsdasmerge(OCstate* state, OCnode* dasroot, OCnode* ddsroot)
{
OCerror stat = OC_NOERR;
OClist* dasglobals = oclistnew();
OClist* dodsglobals = oclistnew(); /* top-level DODS_XXX {...} */
OClist* dasnodes = oclistnew();
@ -247,10 +253,10 @@ ocddsdasmerge(OCstate* state, OCnode* dasroot, OCnode* ddsroot)
unsigned int i,j;
if(dasroot->tree == NULL || dasroot->tree->dxdclass != OCDAS)
return OCTHROW(OC_EINVAL);
{stat = OCTHROW(OC_EINVAL); goto done;}
if(ddsroot->tree == NULL || (ddsroot->tree->dxdclass != OCDDS
&& ddsroot->tree->dxdclass != OCDATADDS))
return OCTHROW(OC_EINVAL);
{stat = OCTHROW(OC_EINVAL); goto done;}
ddsnodes = ddsroot->tree->nodes;
@ -332,12 +338,14 @@ ocddsdasmerge(OCstate* state, OCnode* dasroot, OCnode* ddsroot)
OCnode* das = (OCnode*)oclistget(dodsglobals,i);
mergedods1(ddsroot,das);
}
done:
/* cleanup*/
oclistfree(dasglobals);
oclistfree(dodsglobals);
oclistfree(dasnodes);
oclistfree(varnodes);
return OCTHROW(OC_NOERR);
return OCTHROW(stat);
}
static int

View File

@ -193,7 +193,7 @@ readfile(const char* path, const char* suffix, OCbytes* packet)
stat = OC_NOERR;
for(;;) {
count = read(fd,buf,sizeof(buf));
if(count <= 0)
if(count == 0)
break;
else if(count < 0) {
stat = OC_EIO;

View File

@ -102,7 +102,7 @@ int
ocuriparse(const char* uri0, OCURI** ocurip)
{
OCURI* ocuri = NULL;
char* uri;
char* uri = NULL;
char** pp;
char* p;
char* p1;
@ -173,7 +173,8 @@ ocuriparse(const char* uri0, OCURI** ocurip)
/* locate the end of the host section */
file = strchr(p,'/');
/* Temporarily overwrite the '/' */
*file = '\0';
if(file != NULL)
*file = '\0';
/* extract any user:pwd */
host = p;
@ -189,22 +190,22 @@ ocuriparse(const char* uri0, OCURI** ocurip)
/* extract host and port */
p = host;
port = strchr(p,':');
if(port)
if(port!=NULL)
*port++ = '\0';
/* Locate end of the file */
constraint = strchr(file,'?');
if(constraint)
if(constraint!=NULL)
suffixparams = strchr(constraint,'#');
else
suffixparams = strchr(file,'#');
if(constraint) {
if(constraint != NULL) {
*constraint++ = '\0';
p = constraint;
}
if(suffixparams) {
if(suffixparams != NULL) {
*suffixparams++ = '\0';
p = suffixparams;
}
@ -302,7 +303,7 @@ ocurisetconstraints(OCURI* duri,const char* constraints)
char* select = NULL;
const char* p;
if(duri->constraint == NULL) free(duri->constraint);
if(duri->constraint != NULL) free(duri->constraint);
if(duri->projection != NULL) free(duri->projection);
if(duri->selection != NULL) free(duri->selection);
duri->constraint = NULL;

View File

@ -421,7 +421,7 @@ ocdataddsmsg(OCstate* state, OCtree* tree)
xxdr_setpos(xdrs,0);
/* read the whole thing */
contents = (char*)malloc(len+1);
xxdr_getbytes(xdrs,contents,len);
(void)xxdr_getbytes(xdrs,contents,len);
contents[len] = '\0';
/* Look for error tag */
for(i=0;i<len;i++) {
@ -542,7 +542,7 @@ ocdtmodestring(OCDT mode,int compact)
if(!compact && i > 0) strcat(result,",");
if(fisset(mode,(1<<i))) {
if(compact) *p++ = ms[0];
else strcat(result,ms);
else strncat(result,ms,sizeof(result));
}
}
/* pad compact list out to NMODES in length (+1 for null terminator) */