Make public a limited API for programmatic access to internal .rc tables

re: https://github.com/Unidata/netcdf-c/issues/2337
re: https://github.com/Unidata/netcdf-c/issues/2407

Add two functions to netcdf.h to allow programs to get/set
selected entries into the internal .rc tables. This should fix
the above issues by allowing HTTP.CAINFO to be set to the
certificates directory.  Note that the changes should be
performed as early as possible in the program because some of
the .rc table entries may get cached internally and changing the
entry after that caching occurs may have no effect.

The new signatures are as follows:

1. Get the value of a simple .rc entry of the form "key=value".
Note that caller must free the returned value, which might be NULL.
````
char* nc_rc_get(char* const * key);

@param key table entry key
@return value if .rc table has entry of the form key=value
@return NULL if no such entry is found.
````

2. Insert/Overwrite the specified key=value pair in the .rc table.
````
int nc_rc_set(const char* key, const char* value);

@param key table entry key -- may not be NULL
@param value table entry value -- may not be NULL
@return NC_NOERR if no error
@return NC_EINVAL if error
````

Addendum:

re: https://github.com/Unidata/netcdf-c/issues/2407

Modify dhttp.c to use the .rc entry HTTP.CAINFO if defined.
This commit is contained in:
Dennis Heimbigner 2022-06-17 14:35:12 -06:00
parent 7375f4bfb3
commit aabbdbf64c
17 changed files with 410 additions and 127 deletions

View File

@ -69,7 +69,7 @@ endif()
if(MSVC)
SET(ISMSVC yes)
endif()
if(osname MATCHES "MINGW.*")
if(osname MATCHES "MINGW.*" OR osname MATCHES "MSYS.*")
SET(ISMINGW yes)
SET(MINGW yes)
endif()

View File

@ -7,7 +7,7 @@ This file contains a high-level description of this package's evolution. Release
## 4.9.1 - T.B.D.
* [Enhancement] Provide a simple API to allow user access to the internal .rc file table: supports get/set/overwrite of entries of the form "key=value". See [Github #????](https://github.com/Unidata/netcdf-c/pull/????).
* [Bug Fix] Use env variable USERPROFILE instead of HOME for windows and mingw. See [Github #2405](https://github.com/Unidata/netcdf-c/pull/2405).
* [Bug Fix] Fix the nc_def_var_fletcher32 code in hdf5 to properly test value of the fletcher32 argument. See [Github #2403](https://github.com/Unidata/netcdf-c/pull/2403).

View File

@ -107,6 +107,7 @@ case "`uname`" in
Darwin*) ISOSX=yes;;
WIN*) ISMSVC=yes;;
MINGW*) ISMINGW=yes;;
MSYS*) ISMINGW=yes;;
esac
if test "x$MSYSTEM" != x ; then

View File

@ -28,7 +28,7 @@ and accessing rc files (e.g. .daprc).
typedef struct NCRCentry {
char* host; /* combined host:port */
char* path; /* prefix to match or NULL */
char* urlpath; /* prefix to match or NULL */
char* key;
char* value;
} NCRCentry;
@ -67,7 +67,7 @@ extern "C" {
/* From drc.c */
EXTERNL void ncrc_initialize(void);
EXTERNL int NC_rcfile_insert(const char* key, const char* value, const char* hostport, const char* path);
EXTERNL int NC_rcfile_insert(const char* key, const char* hostport, const char* path, const char* value);
EXTERNL char* NC_rclookup(const char* key, const char* hostport, const char* path);
EXTERNL char* NC_rclookupx(NCURI* uri, const char* key);

View File

@ -2095,6 +2095,14 @@ EXTERNL int nc_initialize(void);
*/
EXTERNL int nc_finalize(void);
/* Programmatic access to the internal .rc table */
/* Get the value corresponding to key | return NULL; caller frees result */
EXTERNL char* nc_rc_get(const char* key);
/* Set/overwrite the value corresponding to key */
EXTERNL int nc_rc_set(const char* key, const char* value);
#if defined(__cplusplus)
}
#endif

View File

@ -95,7 +95,6 @@ NCDISPATCH_initialize(void)
NCpathcanonical(home,&globalstate->home);
nullfree(home);
}
fprintf(stderr,">>> HOME=|%s|\n",globalstate->home); fflush(stderr);
/* Capture $CWD */
{

View File

@ -22,7 +22,9 @@
#include "nclog.h"
#include "ncbytes.h"
#include "nclist.h"
#include "ncuri.h"
#include "nchttp.h"
#include "ncauth.h"
#undef TRACE
@ -482,6 +484,23 @@ setupconn(NC_HTTP_STATE* state, const char* objecturl)
cstat = curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
if (cstat != CURLE_OK) goto fail;
/* Pull some values from .rc tables */
{
NCURI* uri = NULL;
char* hostport = NULL;
char* value = NULL;
ncuriparse(objecturl,&uri);
if(uri == NULL) goto fail;
hostport = NC_combinehostport(uri);
value = NC_rclookup("HTTP.CAINFO",hostport,NULL);
if(value == NULL)
value = NC_rclookup("HTTP.CAINFO",NULL,NULL);
if(value != NULL) {
cstat = CURLERR(curl_easy_setopt(state->curl, CURLOPT_CAINFO, value));
if (cstat != CURLE_OK) goto fail;
}
}
/* Set the method */
if((stat = nc_http_set_method(state,state->request.method))) goto done;

View File

@ -38,8 +38,6 @@ See COPYRIGHT for license information.
#define RTAG ']'
#define LTAG '['
#define TRIMCHARS " \t\r\n"
#undef MEMCHECK
#define MEMCHECK(x) if((x)==NULL) {goto nomem;} else {}
@ -52,9 +50,12 @@ static char* rcreadline(char** nextlinep);
static void rctrim(char* text);
static void rcorder(NClist* rc);
static int rccompile(const char* path);
static struct NCRCentry* rclocate(const char* key, const char* hostport, const char* path);
static int rcequal(NCRCentry* e1, NCRCentry* e2);
static int rclocatepos(const char* key, const char* hostport, const char* urlpath);
static struct NCRCentry* rclocate(const char* key, const char* hostport, const char* urlpath);
static int rcsearch(const char* prefix, const char* rcname, char** pathp);
static void rcfreeentries(NClist* rc);
static void rcfreeentry(NCRCentry* t);
#ifdef DRCDEBUG
static void storedump(char* msg, NClist* entrys);
#endif
@ -68,11 +69,63 @@ static const char* rcfilenames[] = {".ncrc", ".daprc", ".dodsrc",NULL};
/* Read these files */
static const char* awsconfigfiles[] = {".aws/credentials",".aws/config",NULL};
static int NCRCinitialized = 0;
/**************************************************/
/* User API */
/**
The most common case is to get the most general value for a key,
where most general means that the urlpath and hostport are null
So this function returns the value associated with the key
where the .rc entry has the simple form "key=value".
If that entry is not found, then return NULL.
@param key table entry key field
@return value matching the key -- caller frees
@return NULL if no entry of the form key=value exists
*/
char*
nc_rc_get(const char* key)
{
NCglobalstate* ncg = NULL;
char* value = NULL;
if(!NCRCinitialized) ncrc_initialize();
ncg = NC_getglobalstate();
assert(ncg != NULL && ncg->rcinfo != NULL && ncg->rcinfo->entries != NULL);
if(ncg->rcinfo->ignore) return NC_NOERR;
value = NC_rclookup(key,NULL,NULL);
return nulldup(value);
}
/**
Set simple key=value in .rc table.
Will overwrite any existing value.
@param key
@param value
@return NC_NOERR if success
@return NC_EINVAL if fail
*/
int
nc_rc_set(const char* key, const char* value)
{
int stat = NC_NOERR;
NCglobalstate* ncg = NULL;
NCRCentry* entry = NULL;
if(!NCRCinitialized) ncrc_initialize();
ncg = NC_getglobalstate();
assert(ncg != NULL && ncg->rcinfo != NULL && ncg->rcinfo->entries != NULL);
if(ncg->rcinfo->ignore) return NC_NOERR;
stat = NC_rcfile_insert(key,NULL,NULL,value);
return stat;
}
/**************************************************/
/* External Entry Points */
static int NCRCinitialized = 0;
/*
Initialize defaults and load:
* .ncrc
@ -96,13 +149,14 @@ ncrc_initialize(void)
if(NCRCinitialized) return;
NCRCinitialized = 1; /* prevent recursion */
ncg = NC_getglobalstate();
#ifndef NOREAD
/* Load entrys */
if((stat = NC_rcload())) {
nclog(NCLOGWARN,".rc loading failed");
}
/* Load .aws/config */
ncg = NC_getglobalstate();
if((stat = aws_load_credentials(ncg))) {
nclog(NCLOGWARN,"AWS config file not loaded");
}
@ -120,6 +174,9 @@ ncrc_setrchome(void)
if(tmp == NULL || strlen(tmp) == 0)
tmp = ncg->home;
ncg->rcinfo->rchome = strdup(tmp);
#ifdef DRCDEBUG
fprintf(stderr,"ncrc_setrchome: %s\n",ncg->rcinfo->rchome);
#endif
}
void
@ -132,16 +189,23 @@ NC_rcclear(NCRCinfo* info)
freeprofilelist(info->s3profiles);
}
static void
rcfreeentry(NCRCentry* t)
{
nullfree(t->host);
nullfree(t->urlpath);
nullfree(t->key);
nullfree(t->value);
free(t);
}
static void
rcfreeentries(NClist* rc)
{
int i;
for(i=0;i<nclistlength(rc);i++) {
NCRCentry* t = (NCRCentry*)nclistget(rc,i);
nullfree(t->host);
nullfree(t->key);
nullfree(t->value);
free(t);
rcfreeentry(t);
}
nclistfree(rc);
}
@ -182,8 +246,7 @@ NC_rcload(void)
const char* dirnames[3];
const char** dir;
/* Make sure rcinfo.rchome is defined */
/* Make sure rcinfo.rchome is defined */
ncrc_setrchome();
dirnames[0] = globalstate->rcinfo->rchome;
dirnames[1] = globalstate->cwd;
@ -214,15 +277,15 @@ done:
}
/**
* Locate a entry by property key and host+port (may be null|"")
* Locate a entry by property key and host+port (may be null)
* If duplicate keys, first takes precedence.
*/
char*
NC_rclookup(const char* key, const char* hostport, const char* path)
NC_rclookup(const char* key, const char* hostport, const char* urlpath)
{
struct NCRCentry* entry = NULL;
if(!NCRCinitialized) ncrc_initialize();
entry = rclocate(key,hostport,path);
entry = rclocate(key,hostport,urlpath);
return (entry == NULL ? NULL : entry->value);
}
@ -248,8 +311,7 @@ Set the absolute path to use for the rc file.
WARNING: this MUST be called before any other
call in order for this to take effect.
\param[in] rcfile The path to use. If NULL, or "",
then do not use any rcfile.
\param[in] rcfile The path to use. If NULL then do not use any rcfile.
\retval OC_NOERR if the request succeeded.
\retval OC_ERCFILE if the file failed to load
@ -305,25 +367,26 @@ rcreadline(char** nextlinep)
static void
rctrim(char* text)
{
char* p = text;
char* p;
char* q;
size_t len = 0;
int i;
if(text == NULL) return;
if(text == NULL || *text == '\0') return;
/* locate first non-trimchar */
for(;*p;p++) {
if(strchr(TRIMCHARS,*p) == NULL) break; /* hit non-trim char */
}
memmove(text,p,strlen(p)+1);
len = strlen(text);
/* elide upto first non-trimchar */
for(q=text,p=text;*p;p++) {
if(*p != ' ' && *p != '\t' && *p != '\r') {*q++ = *p;}
}
len = strlen(p);
/* locate last non-trimchar */
if(len > 0) {
for(i=(len-1);i>=0;i--) {
if(strchr(TRIMCHARS,text[i]) == NULL) {
text[i+1] = '\0'; /* elide trailing trimchars */
break;
}
p = &text[i];
if(*p != ' ' && *p != '\t' && *p != '\r') {break;}
*p = '\0'; /* elide trailing trimchars */
}
}
}
@ -339,22 +402,22 @@ rcorder(NClist* rc)
NClist* tmprc = NULL;
if(rc == NULL || len == 0) return;
tmprc = nclistnew();
/* Copy rc into tmprc and clear rc */
for(i=0;i<len;i++) {
NCRCentry* ti = nclistget(rc,i);
nclistpush(tmprc,ti);
}
nclistclear(rc);
/* Two passes: 1) pull entries with host */
for(i=0;i<len;i++) {
NCRCentry* ti = nclistget(tmprc,i);
NCRCentry* ti = nclistget(rc,i);
if(ti->host == NULL) continue;
nclistpush(rc,ti);
nclistpush(tmprc,ti);
}
/* pass 2 pull entries without host*/
for(i=0;i<len;i++) {
NCRCentry* ti = nclistget(tmprc,i);
NCRCentry* ti = nclistget(rc,i);
if(ti->host != NULL) continue;
nclistpush(tmprc,ti);
}
/* Move tmp to rc */
nclistsetlength(rc,0);
for(i=0;i<len;i++) {
NCRCentry* ti = nclistget(tmprc,i);
nclistpush(rc,ti);
}
#ifdef DRCDEBUG
@ -365,7 +428,7 @@ rcorder(NClist* rc)
/* Merge a entry store from a file*/
static int
rccompile(const char* path)
rccompile(const char* filepath)
{
int ret = NC_NOERR;
NClist* rc = NULL;
@ -376,8 +439,8 @@ rccompile(const char* path)
NCglobalstate* globalstate = NC_getglobalstate();
char* bucket = NULL;
if((ret=NC_readfile(path,tmp))) {
nclog(NCLOGWARN, "Could not open configuration file: %s",path);
if((ret=NC_readfile(filepath,tmp))) {
nclog(NCLOGWARN, "Could not open configuration file: %s",filepath);
goto done;
}
contents = ncbytesextract(tmp);
@ -394,6 +457,7 @@ rccompile(const char* path)
char* key = NULL;
char* value = NULL;
char* host = NULL;
char* urlpath = NULL;
size_t llen;
NCRCentry* entry;
@ -406,7 +470,7 @@ rccompile(const char* path)
char* url = ++line;
char* rtag = strchr(line,RTAG);
if(rtag == NULL) {
nclog(NCLOGERR, "Malformed [url] in %s entry: %s",path,line);
nclog(NCLOGERR, "Malformed [url] in %s entry: %s",filepath,line);
continue;
}
line = rtag + 1;
@ -414,17 +478,18 @@ rccompile(const char* path)
/* compile the url and pull out the host and protocol */
if(uri) ncurifree(uri);
if(ncuriparse(url,&uri)) {
nclog(NCLOGERR, "Malformed [url] in %s entry: %s",path,line);
nclog(NCLOGERR, "Malformed [url] in %s entry: %s",filepath,line);
continue;
}
{ NCURI* newuri = NULL;
/* Rebuild the url to path format */
/* Rebuild the url to S3 "path" format */
nullfree(bucket);
if((ret = NC_s3urlrebuild(uri,&newuri,&bucket,NULL))) goto done;
ncurifree(uri);
uri = newuri;
newuri = NULL;
}
/* Get the host+port */
ncbytesclear(tmp);
ncbytescat(tmp,uri->host);
if(uri->port != NULL) {
@ -433,8 +498,11 @@ rccompile(const char* path)
}
ncbytesnull(tmp);
host = ncbytesextract(tmp);
if(strlen(host)==0)
if(strlen(host)==0) /* nullify host */
{free(host); host = NULL;}
/* Get the url path part */
urlpath = uri->path;
if(urlpath && strlen(urlpath)==0) urlpath = NULL; /* nullify */
}
/* split off key and value */
key=line;
@ -446,31 +514,33 @@ rccompile(const char* path)
value++;
}
/* See if key already exists */
entry = rclocate(key,host,path);
if(entry != NULL) {
nullfree(entry->host);
nullfree(entry->key);
nullfree(entry->value);
} else {
entry = rclocate(key,host,urlpath);
if(entry == NULL) {
entry = (NCRCentry*)calloc(1,sizeof(NCRCentry));
if(entry == NULL) {ret = NC_ENOMEM; goto done;}
nclistpush(rc,entry);
entry->host = host; host = NULL;
entry->urlpath = nulldup(urlpath);
entry->key = nulldup(key);
rctrim(entry->host);
rctrim(entry->urlpath);
rctrim(entry->key);
}
entry->host = host; host = NULL;
entry->key = nulldup(key);
nullfree(entry->value);
entry->value = nulldup(value);
rctrim(entry->host);
rctrim(entry->key);
rctrim(entry->value);
#ifdef DRCDEBUG
fprintf(stderr,"rc: host=%s key=%s value=%s\n",
fprintf(stderr,"rc: host=%s urlpath=%s key=%s value=%s\n",
(entry->host != NULL ? entry->host : "<null>"),
(entry->urlpath != NULL ? entry->urlpath : "<null>"),
entry->key,entry->value);
#endif
entry = NULL;
}
#ifdef DRCDEBUG
fprintf(stderr,"reorder.path=%s\n",filepath);
#endif
rcorder(rc);
done:
@ -480,47 +550,84 @@ done:
return (ret);
}
/**
Encapsulate equality comparison: return 1|0
*/
static int
rcequal(NCRCentry* e1, NCRCentry* e2)
{
int nulltest;
if(e1->key == NULL || e2->key == NULL) return 0;
if(strcmp(e1->key,e2->key) != 0) return 0;
/* test hostport; take NULL into account*/
nulltest = 0;
if(e1->host == NULL) nulltest |= 1;
if(e2->host == NULL) nulltest |= 2;
switch (nulltest) {
case 0: if(strcmp(e1->host,e2->host) != 0) {return 0;} break;
case 1: return 0;
case 2: return 0;
case 3: break;
default: return 0;
}
/* test urlpath take NULL into account*/
nulltest = 0;
if(e1->urlpath == NULL) nulltest |= 1;
if(e2->urlpath == NULL) nulltest |= 2;
switch (nulltest) {
case 0: if(strcmp(e1->urlpath,e2->urlpath) != 0) {return 0;} break;
case 1: return 0;
case 2: return 0;
case 3: break;
default: return 0;
}
return 1;
}
/**
* (Internal) Locate a entry by property key and host+port (may be null) and urlpath (may be null)
* If duplicate keys, first takes precedence.
*/
static int
rclocatepos(const char* key, const char* hostport, const char* urlpath)
{
int i;
NCglobalstate* globalstate = NC_getglobalstate();
struct NCRCinfo* info = globalstate->rcinfo;
NCRCentry* entry = NULL;
NCRCentry candidate;
NClist* rc = info->entries;
if(info->ignore) return -1;
candidate.key = (char*)key;
candidate.value = (char*)NULL;
candidate.host = (char*)hostport;
candidate.urlpath = (char*)urlpath;
for(i=0;i<nclistlength(rc);i++) {
entry = (NCRCentry*)nclistget(rc,i);
if(rcequal(entry,&candidate)) return i;
}
return -1;
}
/**
* (Internal) Locate a entry by property key and host+port (may be null or "").
* If duplicate keys, first takes precedence.
*/
static struct NCRCentry*
rclocate(const char* key, const char* hostport, const char* path)
rclocate(const char* key, const char* hostport, const char* urlpath)
{
int i,found;
int pos;
NCglobalstate* globalstate = NC_getglobalstate();
NClist* rc = globalstate->rcinfo->entries;
NCRCentry* entry = NULL;
struct NCRCinfo* info = globalstate->rcinfo;
if(globalstate->rcinfo->ignore)
return NULL;
if(key == NULL || rc == NULL) return NULL;
if(hostport == NULL) hostport = "";
for(found=0,i=0;i<nclistlength(rc);i++) {
int t;
size_t hplen;
entry = (NCRCentry*)nclistget(rc,i);
hplen = (entry->host == NULL ? 0 : strlen(entry->host));
if(strcmp(key,entry->key) != 0) continue; /* keys do not match */
/* If the entry entry has no url, then use it
(because we have checked all other cases)*/
if(hplen == 0) {found=1;break;}
/* do hostport match */
t = 0;
if(entry->host != NULL)
t = strcmp(hostport,entry->host);
/* do path prefix match */
if(entry->path != NULL) {
size_t pathlen = strlen(entry->path);
t = strncmp(path,entry->path,pathlen);
}
if(t == 0) {found=1; break;}
}
return (found?entry:NULL);
if(globalstate->rcinfo->ignore) return NULL;
if(key == NULL || info == NULL) return NULL;
pos = rclocatepos(key,hostport,urlpath);
if(pos < 0) return NULL;
return NC_rcfile_ith(info,(size_t)pos);
}
/**
@ -562,7 +669,7 @@ done:
}
int
NC_rcfile_insert(const char* key, const char* value, const char* hostport, const char* path)
NC_rcfile_insert(const char* key, const char* hostport, const char* urlpath, const char* value)
{
int ret = NC_NOERR;
/* See if this key already defined */
@ -571,6 +678,10 @@ NC_rcfile_insert(const char* key, const char* value, const char* hostport, const
NClist* rc = NULL;
if(!NCRCinitialized) ncrc_initialize();
if(key == NULL || value == NULL)
{ret = NC_EINVAL; goto done;}
globalstate = NC_getglobalstate();
rc = globalstate->rcinfo->entries;
@ -579,19 +690,25 @@ NC_rcfile_insert(const char* key, const char* value, const char* hostport, const
globalstate->rcinfo->entries = rc;
if(rc == NULL) {ret = NC_ENOMEM; goto done;}
}
entry = rclocate(key,hostport,path);
entry = rclocate(key,hostport,urlpath);
if(entry == NULL) {
entry = (NCRCentry*)calloc(1,sizeof(NCRCentry));
if(entry == NULL) {ret = NC_ENOMEM; goto done;}
entry->key = strdup(key);
entry->value = NULL;
rctrim(entry->key);
entry->host = (hostport == NULL ? NULL : strdup(hostport));
entry->host = nulldup(hostport);
rctrim(entry->host);
entry->urlpath = nulldup(urlpath);
rctrim(entry->urlpath);
nclistpush(rc,entry);
}
if(entry->value != NULL) free(entry->value);
entry->value = strdup(value);
rctrim(entry->value);
#ifdef DRCDEBUG
storedump("NC_rcfile_insert",rc);
#endif
done:
return ret;
}

View File

@ -2105,8 +2105,12 @@ NC_createglobalstate(void)
nc_globalstate = calloc(1,sizeof(NCglobalstate));
}
/* Initialize struct pointers */
nc_globalstate->rcinfo = (struct NCRCinfo*)calloc(1,sizeof(struct NCRCinfo));
if(nc_globalstate == NULL) return NC_ENOMEM;
if((nc_globalstate->rcinfo = calloc(1,sizeof(struct NCRCinfo)))==NULL)
{stat = NC_ENOMEM; goto done;}
if((nc_globalstate->rcinfo->entries = nclistnew())==NULL)
{stat = NC_ENOMEM; goto done;}
if((nc_globalstate->rcinfo->s3profiles = nclistnew())==NULL)
{stat = NC_ENOMEM; goto done;}
/* Get environment variables */
if(getenv(NCRCENVIGNORE) != NULL)
@ -2119,6 +2123,7 @@ NC_createglobalstate(void)
nc_globalstate->chunkcache.nelems = CHUNK_CACHE_NELEMS; /**< Default chunk cache number of elements. */
nc_globalstate->chunkcache.preemption = CHUNK_CACHE_PREEMPTION; /**< Default chunk cache preemption. */
done:
return stat;
}

View File

@ -397,7 +397,7 @@ main(int argc, char **argv)
/* This test code based on test code from Jeff Whitaker. See
* https://github.com/Unidata/netcdf-c/issues/2357. This is a
* simplified version. */
int i, varid, ncid;
int varid, ncid;
int dimids[NDIM2];
size_t start[NDIM2] = {0, 0}, count[NDIM2] = {DATALEN2, 1}, dimlen;
int data[DATALEN2] = {42, 42};
@ -422,7 +422,7 @@ main(int argc, char **argv)
SUMMARIZE_ERR;
printf("*** testing dimlen with NC_UNLIMITED reopen and rewrite...");
{
int i, varid, ncid;
int varid, ncid;
int dimid;
size_t start[NDIM1] = {0}, count[NDIM1] = {DATALEN2}, dimlen;
int data[DATALEN2] = {42, 42};

View File

@ -418,7 +418,7 @@ main(int argc, char **argv)
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
#ifdef HAVE_H5Z_SZIP
#ifdef HAVE_SZ
printf("**** testing simple szip filter setup...");
{
int ncid;
@ -757,6 +757,6 @@ main(int argc, char **argv)
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
#endif /* HAVE_H5Z_SZIP */
#endif /* HAVE_SZ */
FINAL_RESULTS;
}

View File

@ -105,6 +105,7 @@ IF(ENABLE_TESTS)
ADD_EXECUTABLE(nctrunc nctrunc.c)
if(RCMERGE)
ADD_EXECUTABLE(tst_rcmerge tst_rcmerge.c)
ADD_EXECUTABLE(tst_rcmerge tst_rcapi.c)
endif()
TARGET_LINK_LIBRARIES(rewrite-scalar netcdf)
TARGET_LINK_LIBRARIES(bom netcdf)
@ -112,6 +113,7 @@ endif()
TARGET_LINK_LIBRARIES(nctrunc netcdf)
if(RCMERGE)
TARGET_LINK_LIBRARIES(tst_rcmerge netcdf)
TARGET_LINK_LIBRARIES(tst_rcapi netcdf)
endif()
IF(USE_HDF5)
@ -154,6 +156,11 @@ endif()
SET_TARGET_PROPERTIES(tst_rcmerge PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG
${CMAKE_CURRENT_BINARY_DIR})
SET_TARGET_PROPERTIES(tst_rcmerge PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR})
SET_TARGET_PROPERTIES(tst_rcapi PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR})
SET_TARGET_PROPERTIES(tst_rcapi PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG
${CMAKE_CURRENT_BINARY_DIR})
SET_TARGET_PROPERTIES(tst_rcapi PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR})
endif()
IF(USE_HDF5)

View File

@ -79,7 +79,7 @@ man_MANS = ncdump.1 nccopy.1
if BUILD_TESTSETS
# C programs needed by shell scripts for classic tests.
check_PROGRAMS = rewrite-scalar ref_ctest ref_ctest64 ncdump tst_utf8 \
bom tst_dimsizes nctrunc tst_rcmerge
bom tst_dimsizes nctrunc tst_rcmerge tst_rcapi
# Tests for classic and 64-bit offset files.
TESTS = tst_inttags.sh run_tests.sh tst_64bit.sh ref_ctest \
@ -203,7 +203,8 @@ ref_roman_szip_simple.cdl ref_roman_szip_unlim.cdl ref_tst_perdimspecs.cdl \
test_keywords.sh ref_keyword1.cdl ref_keyword2.cdl ref_keyword3.cdl ref_keyword4.cdl \
ref_tst_nofilters.cdl test_scope.sh \
test_rcmerge.sh ref_rcmerge1.txt ref_rcmerge2.txt ref_rcmerge3.txt \
scope_ancestor_only.cdl scope_ancestor_subgroup.cdl scope_group_only.cdl scope_preorder.cdl
scope_ancestor_only.cdl scope_ancestor_subgroup.cdl scope_group_only.cdl scope_preorder.cdl \
ref_rcapi.txt
# The L512.bin file is file containing exactly 512 bytes each of value 0.
# It is used for creating hdf5 files with varying offsets for testing.

7
ncdump/ref_rcapi.txt Normal file
View File

@ -0,0 +1,7 @@
load:
insert: key=key1 value=value1
insert: before: key1 = (null)
insert: after: key1 = value1
replace: key=key1 value=value2
replace: before: key1 = value1
replace: after: key1 = value2

View File

@ -54,7 +54,8 @@ resetrc() {
rm -fr $HOMERCFILES
rm -f $LOCALRCFILES
unset NCRCENV_RC
rm -f tmpoutput.txt
rm -f tmp_rcmerge.txt
rm -f tmp_rcapi.txt
rm -f allfiles1 allfiles2 allfiles3
}
@ -70,36 +71,40 @@ fi
mergecase1() {
# create everything with different keys to test merge
resetrc
rm -f tmp_rcmerge.txt tmpoutput.txt
rm -f tmp_rcmerge.txt tmp_rcmerge.txt
echo "for r=ncrc daprc dodsrc"
for r in "ncrc" "daprc" "dodsrc"; do
echo "${r}_home=${r}" >> $RCHOME/".${r}";
echo "${r}_local=${r}" >> $WD/".${r}"
done;
union 1
${abs_execdir}/tst_rcmerge |sort > tmpoutput.txt
${abs_execdir}/tst_rcmerge |sort > tmp_rcmerge.txt
# echo ">>merge1"; cat ${abs_srcdir}/ref_rcmerge1.txt;
# echo "====="; cat tmpoutput.txt
diff -b ${abs_srcdir}/ref_rcmerge1.txt tmpoutput.txt
# echo "====="; cat tmp_rcmerge.txt
diff -b ${abs_srcdir}/ref_rcmerge1.txt tmp_rcmerge.txt
}
mergecase2() {
# create with some same keys to test override
resetrc
rm -f tmp_rcmerge.txt tmpoutput.txt
rm -f tmp_rcmerge.txt tmp_rcmerge.txt
echo "Create in $RCHOME"
for r in "ncrc" "daprc" "dodsrc" ; do
echo "${r}=${r}" >> $RCHOME/".${r}";
done;
echo "Create in $WD"
for r in "ncrc" "daprc" "dodsrc" ; do
echo "${r}=${r}" >> $WD/".${r}"
done;
union 2
${abs_execdir}/tst_rcmerge |sort > tmpoutput.txt
diff -b ${abs_srcdir}/ref_rcmerge2.txt tmpoutput.txt
${abs_execdir}/tst_rcmerge |sort > tmp_rcmerge.txt
diff -b ${abs_srcdir}/ref_rcmerge2.txt tmp_rcmerge.txt
}
mergecase3() {
# Test cross file overrides
resetrc
rm -f tmp_rcmerge.txt tmpoutput.txt
rm -f tmp_rcmerge.txt tmp_rcmerge.txt
echo "ncrc=ncrc1" >> $HOME/.ncrc
echo "ncrcx=ncrcx" >> $RCHOME/.ncrc
echo "ncrc=ncrc2" >> $RCHOME/.dodsrc
@ -111,8 +116,18 @@ mergecase3() {
echo "daprc=daprc" >> $WD/.dodsrc
echo "ncrcx=ncrcy" >> $WD/.dodsrc
union 3
${abs_execdir}/tst_rcmerge |sort -d > tmpoutput.txt
diff -b ${abs_srcdir}/ref_rcmerge3.txt tmpoutput.txt
${abs_execdir}/tst_rcmerge |sort -d > tmp_rcmerge.txt
diff -b ${abs_srcdir}/ref_rcmerge3.txt tmp_rcmerge.txt
}
rcapi1() {
resetrc
echo "[http://github.com/a/b/c]ncrc=ncrc1" >> $WD/.ncrc
echo "ncrc=ncrc2" >> $WD/.ncrc
echo "[http://github.com:8080/a/b/c]key0=v0" >> $WD/.ncrc
echo "[http://github.com]key0=v1" >> $WD/.ncrc
${abs_execdir}/tst_rcapi > tmp_rcapi.txt
diff -b ${abs_srcdir}/ref_rcapi.txt ./tmp_rcapi.txt
}
resetrc
@ -120,5 +135,10 @@ resetrc
mergecase1
mergecase2
mergecase3
# Test the .rc api
rcapi1
# Test the .rc api
rcapi1
resetrc

92
ncdump/tst_rcapi.c Executable file
View File

@ -0,0 +1,92 @@
/* This is part of the netCDF package.
Copyright 2018 University Corporation for Atmospheric Research/Unidata
See COPYRIGHT file for conditions of use.
Test HDF5 alignment
Dennis Heimbigner
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "netcdf.h"
#undef DEBUG
#ifndef nullfree
#define nullfree(x) {if((x)!=NULL) free(x);}
#endif
#if 0
static void
printrc(NCglobalstate* ngs)
{
size_t i,nentries = 0;
NCRCinfo* info = NULL;
NCRCentry* entry = NULL;
info = ngs->rcinfo;
if(info->ignore) {
fprintf(stderr,".rc ignored\n");
return;
}
/* Print out the .rc entries */
if((nentries = NC_rcfile_length(info))==0) {
printf("<empty>\n");
exit(0);
}
for(i=0;i<nentries;i++) {
entry = NC_rcfile_ith(info,i);
if(entry == NULL) abort();
if(entry->host != NULL) {
printf("[%s ",entry->host);
if(entry->urlpath != NULL)
printf("/%s] ",entry->urlpath);
printf("]");
}
printf("|%s|->|%s|\n",entry->key,entry->value);
}
}
#endif
int
main(int argc, char **argv)
{
int stat = NC_NOERR;
const char* key;
const char* value;
char* newvalue;
printf("load:\n");
if ((stat=nc_initialize())) {fprintf(stderr,"***fail\n"); exit(1);}
key = "key1";
value = "value1";
printf("insert: key=%s value=%s\n",key, value);
newvalue = nc_rc_get(key);
printf("insert: before: %s = %s\n",key,newvalue);
nullfree(newvalue);
stat = nc_rc_set(key, value);
newvalue = nc_rc_get(key);
printf("insert: after: %s = %s\n",key,newvalue);
nullfree(newvalue);
key = "key1";
value = "value2";
printf("replace: key=%s value=%s\n",key, value);
newvalue = nc_rc_get(key);
printf("replace: before: %s = %s\n",key,newvalue);
nullfree(newvalue);
stat = nc_rc_set(key, value);
newvalue = nc_rc_get(key);
printf("replace: after: %s = %s\n",key,newvalue);
nullfree(newvalue);
nc_finalize();
return 0;
}

View File

@ -5,23 +5,17 @@
#include "ncrc.h"
#include "nc4internal.h"
int
main(int argc, char** argv)
static void
printrc(NCglobalstate* ngs)
{
size_t i,nentries = 0;
NCglobalstate* ngs = NC_getglobalstate();
NCRCinfo* info = NULL;
NCRCentry* entry = NULL;
/* Cause the .rc files to be read and merged */
nc_initialize();
if((ngs = NC_getglobalstate())==NULL) abort();
info = ngs->rcinfo;
if(info->ignore) {
fprintf(stderr,".rc ignored\n");
exit(0);
return;
}
/* Print out the .rc entries */
@ -34,11 +28,24 @@ main(int argc, char** argv)
if(entry == NULL) abort();
if(entry->host != NULL) {
printf("[%s ",entry->host);
if(entry->path != NULL)
printf("/%s] ",entry->path);
if(entry->urlpath != NULL)
printf("/%s] ",entry->urlpath);
printf("]");
}
printf("|%s|->|%s|\n",entry->key,entry->value);
}
}
int
main(int argc, char** argv)
{
NCglobalstate* ngs = NC_getglobalstate();
/* Cause the .rc files to be read and merged */
nc_initialize();
if((ngs = NC_getglobalstate())==NULL) abort();
printrc(ngs);
return 0;
}