示例#1
0
static int
readfile(char* path, char* suffix, OCbytes* packet)
{
    int stat;
    char buf[1024];
    char filename[1024];
    int count,size,fd;
    /* check for leading file:/// */
    if(strncmp(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 THROW(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 THROW(stat);
}
示例#2
0
/*
    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;
}
static OCerror
createtempfile(OCstate* state, OCtree* tree)
{
    int fd,slen;
    char* name;
    slen = strlen(TMPPATH1);
    if(slen < strlen(TMPPATH2)) slen = strlen(TMPPATH2);
    slen += strlen("datadds") + strlen("XXXXXX");
    name = (char*)ocmalloc(slen+1);
    MEMCHECK(name,OC_ENOMEM);
    fd = createtempfile1(name, TMPPATH1);
    if(fd < 0)
        fd = createtempfile1(name, TMPPATH2);
    if(fd < 0) {
        oc_log(LOGERR,"oc_open: attempt to open tmp file %s failed",name);
        return errno;
    }
    oc_log(LOGNOTE,"oc_open: using tmp file: %s",name);
    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;
}
示例#4
0
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);
}
示例#5
0
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);
}
示例#6
0
static void ocnotify_flush(struct ocnotify_private ocnotify, const char *host)
{
	enum mapistore_error	retval;

	if (ocnotify.flush) {
		retval = mapistore_notification_resolver_delete(&ocnotify.mstore_ctx, ocnotify.username, host);
		if (retval == MAPISTORE_SUCCESS) {
			oc_log(0, "* [OK]   %s resolver entry for user %s deleted", host, ocnotify.username);
		} else {
			oc_log(0, "* [ERR]  %s resolver entry for user %s not deleted", host, ocnotify.username);
		}
	}
}
/*
    Set curl properties for link based on rc files
*/
static void
ocsetcurlproperties(OCstate* state)
{
    CURL* curl = state->curl;
    CURLcode cstat = CURLE_OK;
    int stat = OC_NOERR;

    /* process the triple store wrt to this state */
    if(ocdodsrc_process(state) != OC_NOERR) {
	oc_log(LOGERR,"Malformed .dodsrc");
	goto fail;
    }
    /* Set username+password from .dodsrc */
    stat=ocset_user_password(curl,state->creds.username,
                                  state->creds.password);
    if(stat != OC_NOERR) goto fail;    

    if (occredentials_in_url(state->url.url)) {
	/* this overrides .dodsrc */
        char *result_url = NULL;
        char* userName = NULL;
        char* password = NULL;
        if (ocextract_credentials(state->url.url, &userName, &password, &result_url) != OC_NOERR)
            goto fail;
	dapurlclear(&state->url);
	dapurlparse(result_url,&state->url);
	/* this overrides .dodsrc */
        if(password != NULL && strlen(password) > 0) {
            if(state->creds.password) free(state->creds.password);
            state->creds.password = password;
	}
        if(userName != NULL && strlen(userName) > 0) {
            if(state->creds.username) free(state->creds.username);
            state->creds.username = userName;
	}
    }

    /* Set curl properties */
    if((stat=ocset_curl_flags(curl,state)) != OC_NOERR) goto fail;
    /* Set curl proxy */
    if((stat=ocset_proxy(curl,state)) != OC_NOERR) goto fail;
    /* Set curl ssl */
    if((stat=ocset_ssl(curl,state)) != OC_NOERR) goto fail;

    return;

fail:
    if(cstat != CURLE_OK)
	oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
    return;
}
示例#8
0
static NCerror
cvttype(nc_type etype, char** srcp, char** dstp)
{
    unsigned int typesize = nctypesizeof(etype);
    char* src = *srcp;
    char* dst = *dstp;

    switch (etype) {
    case NC_STRING: case NC_URL: {
	char* ssrc = *(char**)src;	
	*((char**)dst) = nulldup(ssrc);
	srcp += typesize;
	dstp += typesize;
    } break;
    
    default:
	if(typesize == 0) goto fail;
	memcpy((void*)dst,(void*)src,typesize);
	srcp += typesize;
	dstp += typesize;
	break;
    }
    return NC_NOERR;
fail:
    oc_log(OCLOGERR,"cvttype bad value: %s",oc_typetostring(etype));
    return NC_EINVAL;
}
示例#9
0
/* This is called with arguments while the other functions in this file are
 * used with global values read from the.dodsrc file.
 */
int
set_user_password(CURL* curl, const char *userC, const char *passwordC)
{
    CURLcode cstat;
    int iUserPassSize = strlen(userC) + strlen(passwordC) + 2;
    char *userPassword = malloc(sizeof(char) * iUserPassSize);
    if (!userPassword) {
        oc_log(LOGERR,
               "Failed to allocate memory for the username and/or password.\n");
        return OC_ENOMEM;
    }
    strncpy(userPassword, userC, iUserPassSize);
    strncat(userPassword, ":", iUserPassSize);
    strncat(userPassword, passwordC, iUserPassSize);
    cstat = curl_easy_setopt(curl, CURLOPT_USERPWD, userPassword);
    if (cstat != CURLE_OK) {
        free(userPassword);
        return OC_ECURL;
    }

    cstat = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long) CURLAUTH_ANY);
    if (cstat != CURLE_OK) {
        free(userPassword);
        return OC_ECURL;
    }

    free(userPassword);
    return OC_NOERR;
}
示例#10
0
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;
}
示例#11
0
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;
}
示例#12
0
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;
}
示例#13
0
static void ocnotify_newmail(TALLOC_CTX *mem_ctx, struct ocnotify_private ocnotify,
			     uint32_t count, const char **hosts, const char *data)
{
	enum mapistore_error	retval;
	int			sock;
	int			endpoint;
	int			i;
	int			bytes;
	int			timeout;
	int			rc;
	uint8_t			*blob = NULL;
	size_t			msglen;

	if (ocnotify.backend == NULL) {
		oc_log(OC_LOG_ERROR, "No backend specified");
		exit (1);
	}

	retval = mapistore_notification_payload_newmail(mem_ctx, ocnotify.backend, (char *)data, ocnotify.dstfolder,
							ocnotify.sep, &blob, &msglen);
	if (retval != MAPISTORE_SUCCESS) {
		oc_log(OC_LOG_ERROR, "unable to generate newmail payload");
		exit (1);
	}

	sock = nn_socket(AF_SP, NN_PUSH);
	if (sock < 0) {
		oc_log(OC_LOG_FATAL, "unable to create socket");
		exit (1);
	}

	timeout = 200;
	rc = nn_setsockopt(sock, NN_SOL_SOCKET, NN_SNDTIMEO, &timeout, sizeof(timeout));
	if (rc < 0) {
		oc_log(OC_LOG_WARNING, "unable to set timeout on socket send");
	}

	for (i = 0; i < count; i++) {
		endpoint = nn_connect(sock, hosts[i]);
		if (endpoint < 0) {
			oc_log(OC_LOG_ERROR, "unable to connect to %s", hosts[i]);
			ocnotify_flush(ocnotify, hosts[i]);
			continue;
		}
		bytes = nn_send(sock, (char *)blob, msglen, 0);
		if (bytes != msglen) {
			oc_log(OC_LOG_WARNING, "Error sending msg: %d sent but %d expected",
			       bytes, msglen);
		}
		oc_log(OC_LOG_INFO, "message sent to %s", hosts[i]);
		nn_shutdown(sock, endpoint);
	}
}
示例#14
0
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;
}
示例#15
0
文件: occontent.c 项目: U-238/gempak
/* Counting records actually requires walking the xdr packet
   so it is not necessarily cheap*/
size_t
ocrecordcount(OCstate* state, OCcontent* content)
{
    int stat = OC_NOERR;
    size_t count;
    OCnode* node = content->node;
    XDR* xdrs;
    char tmp[BYTES_PER_XDR_UNIT];

    OCASSERT((node != NULL));
    OCASSERT((node->octype == OC_Sequence));
    OCASSERT((content->mode == Recordmode));

    /* If we are using memdata; then use that value */
    if(content->memdata != NULL) {
	return content->memdata->count;
    }

    xdrs = content->tree->data.xdrs;
    OCASSERT((xdrs != NULL));

    /* checkpoint the beginning of this instance*/
    if(!content->xdrpos.valid) {
	content->xdrpos.offset = xdr_getpos(xdrs);
	content->xdrpos.valid = 1;
    }
    /* move to checkpoint position*/
    if(!xdr_setpos(xdrs,content->xdrpos.offset)) return 0;

    for(count=0;;count++) {
        /* pick up the sequence record begin marker*/
        /* extract the tag byte*/
        if(!xdr_opaque(xdrs,tmp,sizeof(tmp))) return 0;
        if(tmp[0] == StartOfoclist) {
            /* skip instance*/
	    stat = ocskipinstance(content->node,xdrs);
            if(stat != OC_NOERR) return 0;
        } else if(tmp[0] == EndOfoclist) {
            break; /* done with the count*/
        } else {
            oc_log(LOGERR,"missing/invalid begin/end record marker\n");
	    return 0;
	}
    }

    /* move back to checkpoint position*/
    if(!xdr_setpos(xdrs,content->xdrpos.offset)) return 0;

    return count;
}
示例#16
0
/* 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:"******"final .dodsrc order:",ocdodsrc->triples,ocdodsrc->ntriples);
}
示例#17
0
static size_t
WriteFileCallback(void* ptr, size_t size, size_t nmemb,	void* data)
{
	size_t count;
	struct Fetchdata* fetchdata;
	fetchdata = (struct Fetchdata*) data;
	count = fwrite(ptr, size, nmemb, fetchdata->stream);
	if (count > 0) {
		fetchdata->size += (count * size);
	}
#ifdef OCPROGRESS
        oc_log(LOGNOTE,"callback: %lu bytes",(unsigned long)(size*nmemb));
#endif
	return count;
}
OCerror
ocopen(OCstate** statep, const char* url)
{
    int stat = OC_NOERR;
    OCstate * state = NULL;
    DAPURL tmpurl;
    CURL* curl = NULL; /* curl handle*/

    memset((void*)&tmpurl,0,sizeof(tmpurl));

    if(!dapurlparse(url,&tmpurl)) {THROWCHK(stat=OC_EBADURL); goto fail;}
    
    stat = occurlopen(&curl);
    if(stat != OC_NOERR) {THROWCHK(stat); goto fail;}

    state = (OCstate*)ocmalloc(sizeof(OCstate)); /* ocmalloc zeros memory*/
    if(state == NULL) {THROWCHK(stat=OC_ENOMEM); goto fail;}

    /* Setup DAP state*/
    state->magic = OCMAGIC;
    state->curl = curl;
    state->trees = oclistnew();
    state->contentlist = NULL;
    state->url = tmpurl;
    state->clientparams = ocparamdecode(state->url.params);
    if(state->clientparams == NULL) {
	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);

    if(statep) *statep = state;
    return THROW(stat);   

fail:
    dapurlclear(&tmpurl);
    if(state != NULL) ocfree(state);
    if(curl != NULL) occurlclose(curl);
    return THROW(stat);
}
示例#19
0
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);
}
示例#20
0
/* 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;
}
示例#21
0
int
set_proxy(CURL* curl, struct OCproxy *pstructProxy)
{
    CURLcode cstat;
    cstat = curl_easy_setopt(curl, CURLOPT_PROXY, pstructProxy->host);
    if (cstat != CURLE_OK)
        return OC_ECURL;

    cstat = curl_easy_setopt(curl, CURLOPT_PROXYPORT, pstructProxy->port);
    if (cstat != CURLE_OK)
        return OC_ECURL;

    if (pstructProxy->user) {
        int userPassSize = strlen(pstructProxy->user) + strlen(
                               pstructProxy->password) + 2;
        char *userPassword = malloc(sizeof(char) * userPassSize);
        if (!userPassword) {
            oc_log(LOGERR, "Out of Memory\n");
            return OC_ENOMEM;
        }
        strncpy(userPassword, pstructProxy->user, userPassSize);
        strncat(userPassword, ":", userPassSize);
        strncat(userPassword, pstructProxy->password, userPassSize);
        cstat = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, userPassword);
        if (cstat != CURLE_OK) {
            free(userPassword);
            return OC_ECURL;
        }

#ifdef CURLOPT_PROXYAUTH
        cstat = curl_easy_setopt(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
        if(cstat != CURLE_OK) goto fail;
#endif
        free(userPassword);
    }

    return OC_NOERR;
}
示例#22
0
int
countrecords(OCnode* node, XDR* xdrs, size_t* nrecordsp)
{
    int stat = OC_NOERR;
    size_t nrecords = 0;
    unsigned int xdroffset;
    if(node->octype != OC_Sequence) return THROW(OC_EINVAL);
    /* checkpoint the xdr position*/
    xdroffset = xdr_getpos(xdrs);
    for(;;) { unsigned int i;
        /* pick up the sequence record begin marker*/
        char tmp[sizeof(unsigned int)];
        /* extract the tag byte*/
        if(!xdr_opaque(xdrs,tmp,sizeof(tmp))) return xdrerror();
        if(tmp[0] == StartOfoclist) {
            /* Walk each member field*/
            for(i=0;i<oclistlength(node->subnodes);i++) {
                OCnode* member = (OCnode*)oclistget(node->subnodes,i);
                stat = ocskip(member,xdrs);
                if(stat != OC_NOERR) break;
            }
	    nrecords++;
        } else if(tmp[0] == EndOfoclist) {
            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(!xdr_setpos(xdrs,xdroffset)) return xdrerror();
    if(nrecordsp != NULL) *nrecordsp = nrecords;
    return THROW(stat);
}
示例#23
0
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);
}
示例#24
0
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 & OCINMEMORY) == 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 { /*inmemory*/
            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 & OCINMEMORY) == 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);
}
示例#25
0
/* Compute the set of prefetched data;
   note that even if caching is off, we will
   still prefetch the small variables.
*/
NCerror
prefetchdata3(NCDAPCOMMON* nccomm)
{
    int i,j;
    NCerror ncstat = NC_NOERR;
    NClist* allvars = nccomm->cdf.varnodes;
    NCconstraint* constraint = nccomm->oc.dapconstraint;
    NClist* vars = nclistnew();
    NCcachenode* cache = NULL;
    NCconstraint* newconstraint = NULL;

    /* Check if we can do constraints */
    if(FLAGSET(nccomm->controls,NCF_UNCONSTRAINABLE)) { /*cannot constrain*/
        /* If we cannot constrain, then pull in everything */
	for(i=0;i<nclistlength(allvars);i++) {
	    nclistpush(vars,nclistget(allvars,i));
	}
    } else { /* can do constraints */
	/* pull in those variables of sufficiently small size */
        for(i=0;i<nclistlength(allvars);i++) {
            CDFnode* var = (CDFnode*)nclistget(allvars,i);
            size_t nelems = 1;
    
	    /* If var is a sequence or under a sequence, then never prefetch */
	    if(var->nctype == NC_Sequence || dapinsequence(var)) continue;

            /* Compute the # of elements in the variable */
            for(j=0;j<nclistlength(var->array.dimensions);j++) {
                CDFnode* dim = (CDFnode*)nclistget(var->array.dimensions,j);
                nelems *= dim->dim.declsize;
	    }
	    if(nelems <= nccomm->cdf.smallsizelimit)
	        nclistpush(vars,(ncelem)var);
	}
    }

    /* If there are no vars, then do nothing */
    if(nclistlength(vars) == 0) {
	nccomm->cdf.cache->prefetch = NULL;
	goto done;
    }

    newconstraint = createncconstraint();
    /* Construct the projections for this set of vars */
    /* Initially, the constraints are same as the merged constraints */
    newconstraint->projections = clonencprojections(constraint->projections);
    restrictprojection34(vars,newconstraint->projections);
    /* similar for selections */
    newconstraint->selections = clonencselections(constraint->selections);

    ncstat = buildcachenode34(nccomm,newconstraint,vars,&cache,1);
    if(ncstat) goto done;
    cache->wholevariable = 1; /* All prefetches are whole variable */

if(FLAGSET(nccomm->controls,NCF_SHOWFETCH)) {
oc_log(OCLOGNOTE,"prefetch.");
}

#ifdef DEBUG
/* Log the set of prefetch variables */
NCbytes* buf = ncbytesnew();
ncbytescat(buf,"prefetch.vars: ");
for(i=0;i<nclistlength(vars);i++) {
CDFnode* var = (CDFnode*)nclistget(vars,i);
ncbytescat(buf," ");
ncbytescat(buf,makesimplepathstring3(var));
}
ncbytescat(buf,"\n");
oc_log(OCLOGNOTE,"%s",ncbytescontents(buf));
ncbytesfree(buf);
#endif

    /* Make cache node be the prefetch node */
    nccomm->cdf.cache->prefetch = cache;

done:
    nclistfree(vars);
    freencconstraint(newconstraint);    
    if(ncstat) freenccachenode(nccomm,cache);
    return THROW(ncstat);
}
示例#26
0
/* Compute the set of prefetched data */
NCerror
prefetchdata4(NCDRNO* drno)
{
    int i,j;
    NCerror ncstat = NC_NOERR;
    NClist* allvars = drno->cdf.varnodes;
    NCconstraint* constraint = &drno->dap.constraint;
    NClist* vars = nclistnew();
    NCcachenode* cache = NULL;
    NCconstraint newconstraint;

    /* If caching is off, and we can do constraints, then
       don't even do prefetch
    */
    if(!FLAGSET(drno,NCF_CACHE) && !FLAGSET(drno,NCF_UNCONSTRAINABLE)) {
	drno->cdf.cache.prefetch = NULL;
	goto done;
    }

    for(i=0;i<nclistlength(allvars);i++) {
	CDFnode* var = (CDFnode*)nclistget(allvars,i);
	size_t nelems = 1;
	/* Compute the # of elements in the variable */
	for(j=0;j<nclistlength(var->array.dimensions);j++) {
	    CDFnode* dim = (CDFnode*)nclistget(var->array.dimensions,j);
	    nelems *= dim->dim.declsize;
	}
	/* If we cannot constrain, then pull in everything */
	if(FLAGSET(drno,NCF_UNCONSTRAINABLE)
           || nelems <= drno->cdf.smallsizelimit)
	    nclistpush(vars,(ncelem)var);
    }

    /* If we cannot constrain, then pull in everything */
    if(FLAGSET(drno,NCF_UNCONSTRAINABLE)) {
	newconstraint.projections = NULL;
	newconstraint.selections= NULL;
    } else { /* Construct the projections for this set of vars */
        /* Construct the projections for this set of vars */
        /* Initially, the constraints are same as the merged constraints */
        newconstraint.projections = cloneprojections(constraint->projections);
        restrictprojection3(drno,vars,newconstraint.projections);
        /* similar for selections */
        newconstraint.selections = cloneselections(constraint->selections);
    }

    ncstat = buildcachenode3(drno,&newconstraint,vars,&cache,0);
    if(ncstat) goto done;

if(FLAGSET(drno,NCF_SHOWFETCH)) {
/* Log the set of prefetch variables */
NCbytes* buf = ncbytesnew();
ncbytescat(buf,"prefetch.vars: ");
for(i=0;i<nclistlength(vars);i++) {
CDFnode* var = (CDFnode*)nclistget(vars,i);
ncbytescat(buf," ");
ncbytescat(buf,makesimplepathstring3(var));
}
ncbytescat(buf,"\n");
oc_log(OCLOGNOTE,ncbytescontents(buf));
ncbytesfree(buf);
}

done:
    if(ncstat) {
	freenccachenode(drno,cache);
    }
    return THROW(ncstat);
}
int
ocinternalinitialize(void)
{
    int stat = OC_NOERR;

    /* Compute if we are same as network order v-a-v xdr */
#ifdef XDRBYTEORDER
    {
        XDR xdrs;
        union {
            char tmp[sizeof(unsigned int)];
            unsigned int i;
        } u;
        int testint = 1;
        xrmem_create(&xdrs, (caddr_t)&u.tmp,sizeof(u.tmp), XDR_ENCODE);
        xdr_int(&xdrs, &testint);   
        oc_network_order = (udub.i == testint?1:0);
        oc_big_endian = oc_network_order;
    }
#else   
    {
        int testint = 0x00000001;
        char *byte = (char *)&testint;
        oc_big_endian = (byte[0] == 0 ? 1 : 0);
        oc_network_order = oc_big_endian;
    }
#endif /*XDRBYTEORDER*/
    {
        /* It turns out that various machines
           store double in different formats.
           This affects the conversion code ocdata.c
           when reconstructing; probably could deduce this
           from oc_big_endian, but not sure.
        */
        XDR xdrs;
	union {
	    double dv;
	    unsigned int i;
	    unsigned int iv[2];
	    char tmp[sizeof(double)];
	} udub;
        double testdub = 18000;
	/* verify double vs int size */
        if(sizeof(double) != (2 * sizeof(unsigned int)))
            ocpanic("|double| != 2*|int|");
        if(sizeof(udub) != sizeof(double))
            ocpanic("|double| != |udub|");
	memset((void*)&udub,0,sizeof(udub));
        xdrmem_create(&xdrs, (caddr_t)&udub.tmp,sizeof(udub.tmp), XDR_ENCODE);
        xdr_double(&xdrs, &testdub);
	udub.iv[0] = ocntoh(udub.iv[0]);
	udub.iv[1] = ocntoh(udub.iv[1]);
	if (udub.dv == testdub)
		oc_invert_xdr_double = 0;
	else { /* swap and try again */
	    unsigned int temp = udub.iv[0];
	    udub.iv[0] = udub.iv[1];
	    udub.iv[1] = temp;
	    if (udub.dv != testdub)
		ocpanic("cannot unpack xdr_double");
	    oc_invert_xdr_double = 1;
	}
    }
    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;
	FILE* f = NULL;
        /* locate the configuration files: . first, then $HOME */
        path = (char*)malloc(strlen("./")+strlen(DODSRC)+1);
	if(path == NULL) return OC_ENOMEM;
        strcpy(path,"./");
        strcat(path,DODSRC);
	/* see if file is readable */
	f = fopen(path,"r");
	if(f == NULL) {
	    /* try $HOME */
            homepath = getenv("HOME");
            if (homepath!= NULL) {
	       if(path != NULL) free(path);
	       path = (char*)malloc(strlen(homepath)+1+strlen(DODSRC)+1);
	       if(path == NULL) return OC_ENOMEM;
	       strcpy(path,homepath);
	       strcat(path,"/");
	       strcat(path,DODSRC);
	       f = fopen(path,"r");
            }
        }
        if(f == NULL) {
	    oc_log(LOGWARN,"Cannot find runtime .dodsrc configuration file");
	} else {
       	    fclose(f);
            if(ocdebug > 1)
		fprintf(stderr, "DODS RC file: %s\n", path);
            if(ocdodsrc_read(path) == 0)
	        oc_log(LOGERR, "Error parsing %s\n",path);
        }
        if(path != NULL) {free(path) ; path = NULL;}
    }
    return THROW(stat);
}
示例#28
0
int
dapmerge3(NCDRNO* drno, CDFnode* ddsroot, OCobject dasroot)
{
    unsigned int i,j;
    NCerror ncerr = NC_NOERR;
    OCerror ocstat = OC_NOERR;
    OCconnection conn = drno->dap.conn;
    unsigned int nsubnodes, nobjects;
    OCobject* dasobjects = NULL;
    NClist* dasglobals = nclistnew();
    NClist* dodsextra = nclistnew();
    NClist* dasnodes = nclistnew();
    NClist* varnodes = nclistnew();
    NClist* allddsnodes = ddsroot->tree->nodes;

    nobjects = oc_inq_nobjects(conn,dasroot);
    dasobjects = oc_inq_objects(conn,dasroot);
    
    /* 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 and DODS_EXTRAs separately*/
    for(i=0;i<nobjects;i++) {
	OCobject das = dasobjects[i];
	OCtype octype;
        char* ocname = NULL;
	int isglobal = 0;
	int hasattributes = 0;
	OCobject* subnodes;

        OCHECK(oc_inq_class(conn,das,&octype));
	if(octype == OC_Attribute) continue; /* ignore these for now*/

        OCHECK(oc_inq_name(conn,das,&ocname));
	OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes));

	isglobal = (ocname == NULL ? 0 : isglobalname3(ocname));

	if(ocname == NULL || isglobal) {
	    nclistpush(dasglobals,(ncelem)das);
	    efree(ocname);
	    continue;
	}
	if(ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) {
	    nclistpush(dodsextra,(ncelem)das);
	    efree(ocname);
	    continue;
	}
	OCHECK(oc_inq_subnodes(conn,das,&subnodes));
	for(j=0;j<nsubnodes;j++) {
	    OCobject subnode = subnodes[j];
	    OCtype ocsubtype;
            OCHECK(oc_inq_class(conn,subnode,&ocsubtype));
	    if(ocsubtype == OC_Attribute) {hasattributes = 1; break;}
	}
	efree(subnodes);
	if(hasattributes) {
	    /* Look for previously collected nodes with same name*/
            for(j=0;j<nclistlength(dasnodes);j++) {
	        OCobject das2 = (OCobject)nclistget(dasnodes,j);
		char* ocname2;
	        OCHECK(oc_inq_name(conn,das2,&ocname2));
		if(ocname2 == NULL || ocname == NULL) goto loop;
		if(strcmp(ocname2,"DODS")==0) goto loop;
	        if(strcmp(ocname,ocname2)==0)
		        oc_log(OCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2);
loop:
		efree(ocname2);
	    }
	    nclistpush(dasnodes,(ncelem)das);
	}
	efree(ocname);
    }

    /* 2. collect all the leaf DDS nodes (of type NC_Primitive)*/
    for(i=0;i<nclistlength(allddsnodes);i++) {
	CDFnode* dds = (CDFnode*)nclistget(allddsnodes,i);
	if(dds->nctype == NC_Primitive) nclistpush(varnodes,(ncelem)dds);
    }

    /* 3. For each das node, lncate 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<nclistlength(dasnodes);i++) {
	OCobject das = (OCobject)nclistget(dasnodes,i);
	char* ocfullname;
	char* ocbasename;
	if(das == OCNULL) continue;
	ocfullname = makeocpathstring3(conn,das,".");
	OCHECK(oc_inq_name(conn,das,&ocbasename));
        for(j=0;j<nclistlength(varnodes);j++) {
	    CDFnode* dds = (CDFnode*)nclistget(varnodes,j);
	    char* ddsfullname = makesimplepathstring3(dds);
	    if(strcmp(ocfullname,ddsfullname)==0
	       || strcmp(ocbasename,ddsfullname)==0
	       || strcmp(ocbasename,dds->name)==0) {
		mergedas1(conn,dds,das);
		/* remove from dasnodes list*/
		nclistset(dasnodes,i,(ncelem)NULL);
	    }
	    efree(ddsfullname);
	}
	efree(ocfullname);
	efree(ocbasename);
    }

    /* 4. Assign globals*/
    for(i=0;i<nclistlength(dasglobals);i++) {
	OCobject das = (OCobject)nclistget(dasglobals,i);
	mergedas1(conn,ddsroot,das);
    }

    /* process DOD_EXTRA */
    if(nclistlength(dodsextra) > 0) dodsextra3(drno,ddsroot,dodsextra);    

done: /* cleanup*/
    efree(dasobjects);
    nclistfree(dasglobals);
    nclistfree(dasnodes);
    nclistfree(dodsextra);
    nclistfree(varnodes);
    if(ocstat != OC_NOERR) ncerr = ocerrtoncerr(ocstat);
    return THROW(ncerr);
}
static int
occompile1(OCstate* state, OCnode* xnode, OCmemdata** memdatap, XDR* xdrs)
{
    unsigned int i,j,xdrcount;
    int stat = OC_NOERR;
    size_t nelements;
    OCmemdata* memdata = NULL;
    OCmemdata* structdata = NULL;
    OClist* records = NULL;
    OCerror ocstat = OC_NOERR;
    OCmemdata** pmem = NULL;


    /* Allocate the space for this memdata chunk */
    switch (xnode->octype) {

    case OC_Dataset:
    case OC_Grid:
    case OC_Structure: {
	if(xnode->array.rank == 0) {
	    ocstat = occompilefields(state,xnode,&memdata,xdrs);
	    if(ocstat != OC_NOERR) goto fail;
	} else { /* rank > 0 */
	    /* Compute the actual index count after projections */
	    nelements = totaldimsize(xnode);
	    if(nelements == 0) return THROW(OC_ENODATA);
	    memdata = makememdata(xnode->octype,OC_NAT,nelements);
	    MEMCHECK(memdata,OC_ENOMEM);
	    memdata->mode = Dimmode;
	    pmem = (OCmemdata**)&memdata->data;
	    /* Consume the leading count field */
	    if(!xdr_u_int(xdrs,&xdrcount)) {stat = OC_EXDR; goto fail;}
	    /* validate the datadds dimensions */
	    if(xdrcount != nelements) {stat=OC_EINVALCOORDS; goto fail;}
            for(i=0;i<nelements;i++) {
		ocstat = occompilefields(state,xnode,&structdata,xdrs);
		if(ocstat != OC_NOERR) {
		    if(ocstat != OC_ENODATA) goto fail;
		    structdata = NULL; /* Leave a hole for this element */
		}
	        pmem[i] = structdata;
	        structdata = NULL;
	    }
	}
    } break;

    case OC_Sequence:{
	/* Since we do not know the # records beforehand,
           use a oclist to collect the record instances.
           Query: this stores by recor (where e.g. original ocapi
           stores by column). How hard would it be to make the
           storage choice conditional on some user defined flag?
        */
	records = oclistnew();
	for(;;) {
            /* pick up the sequence record begin marker*/
            char tmp[sizeof(unsigned int)];
            /* extract the tag byte*/
	    if(!xdr_opaque(xdrs,tmp,sizeof(tmp))) {stat = OC_EXDR; goto fail;}
            if(tmp[0] == StartOfoclist) { /* Walk each member field*/
		ocstat = occompilefields(state,xnode,&structdata,xdrs);
		if(ocstat != OC_NOERR) goto fail;
		oclistpush(records,(ocelem)structdata);
		structdata = NULL;
            } else if(tmp[0] == EndOfoclist) {
                break; /* we are done with the this sequence instance*/
            } else {
		oc_log(LOGERR,"missing/invalid begin/end record marker\n");
                stat = OC_EINVALCOORDS;
		goto fail;
            }
	}
	/* Convert the list to a proper OCmemdata */
	nelements = oclistlength(records);
	memdata = makememdata(xnode->octype,OC_NAT,nelements);
	MEMCHECK(memdata,OC_ENOMEM);
	memdata->mode = Recordmode;
	pmem = (OCmemdata**)&memdata->data;
	for(j=0;j<nelements;j++) {
	    OCmemdata* record = (OCmemdata*)oclistget(records,j);
	    pmem[j] = record;
	}
	oclistfree(records);	    
	records = NULL;
    } break;

    case OC_Primitive:
	ocstat = occompileprim(state,xnode,&memdata,xdrs);
	if(ocstat != OC_NOERR) goto fail;
	break;

    default: OCPANIC1("ocmap: encountered unexpected node type: %x",xnode->octype);
        break;
    }

/*ok:*/
    if(memdatap) *memdatap = memdata;
    return THROW(ocstat);    

fail:
    if(records != NULL) for(i=0;i<oclistlength(records);i++)
	freeocmemdata((OCmemdata*)oclistget(records,i));
    freeocmemdata(memdata);
    freeocmemdata(structdata);
    return THROW(ocstat);
}
OCerror
ocfetch(OCstate* state, const char* constraint, OCdxd kind, 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);

    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:
#ifdef OC_DISK_STORAGE
       /* Create the datadds file immediately
           so that DRNO can reference it*/
        /* Make the tmp file*/
        stat = createtempfile(state,tree);
        if(stat) {THROWCHK(stat); goto unwind;}
        stat = readDATADDS(state,tree);
	if(stat == OC_NOERR) {
            /* Separate the DDS from data and return the dds;
	       will modify packet */
            stat = ocextractdds(state,tree);
	}
#else
        stat = readDATADDS(state,tree);
	if(stat == OC_NOERR) {
            /* Separate the DDS from data*/
            stat = ocextractdds(state,tree);
	    tree->data.xdrdata = ocbytesdup(state->packet);
	}
#endif
	break;
    }
    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 THROW(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) {THROWCHK(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)
	    {THROWCHK(stat=OC_EDAS); goto unwind;}
	break;
    case OCDDS:
        if(root->octype != OC_Dataset)
	    {THROWCHK(stat=OC_EDDS); goto unwind;}
	break;
    case OCDATADDS:
        if(root->octype != OC_Dataset)
	    {THROWCHK(stat=OC_EDATADDS); goto unwind;}
	/* Modify the tree kind */
	tree->dxdclass = OCDATADDS;
	break;
    default: return OC_EINVAL;
    }

    if(kind != OCDAS) {
        /* Process ocnodes to fix various semantic issues*/
        computeocsemantics(tree->nodes);
    }

    /* Process ocnodes to compute name info*/
    computeocfullnames(tree->root);

    if(kind != OCDAS) {
        /* Process ocnodes to compute sizes when uniform in size*/
        ocsetsize(tree->root);
    }

    if(kind == OCDATADDS) {
        tree->data.xdrs = (XDR*)ocmalloc(sizeof(XDR));
        MEMCHECK(tree->data.xdrs,OC_ENOMEM);
#ifdef OC_DISK_STORAGE
        ocxdrstdio_create(tree->data.xdrs,tree->data.file,XDR_DECODE);
#else
	xdrmem_create(tree->data.xdrs,tree->data.xdrdata,tree->data.datasize,XDR_DECODE);
#endif
        if(!xdr_setpos(tree->data.xdrs,tree->data.bod)) return xdrerror();
    }

#ifdef OC_DISK_STORAGE
    if(ocdebug == 0 && tree->data.filename != NULL) {
	unlink(tree->data.filename);
    }
#endif

    /* Put root into the state->trees list */
    oclistpush(state->trees,(ocelem)root);

    if(rootp) *rootp = root;
    return stat;

unwind:
    ocfreetree(tree);
    return THROW(stat);
}