/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc. See the COPYRIGHT file for more information. */ #include "config.h" #ifdef HAVE_UNISTD_H #include #endif #include #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;iarray.rank; for(j=0;jarray.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;iname != NULL) free(att->name); if(att->etype == OC_String || att->etype == OC_URL) { for(j=0;jnvalues;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;isubnodes);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;iarray.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"; } 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 ""; } 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 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; }