mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-03-19 17:30:27 +08:00
Merge pull request #2408 from DennisHeimbigner/rcapi.dmh
Make public a limited API for programmatic access to internal .rc tables
This commit is contained in:
commit
a3998aa2f0
@ -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()
|
||||
|
@ -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 #2408](https://github.com/Unidata/netcdf-c/pull/2408).
|
||||
* [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).
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -95,7 +95,6 @@ NCDISPATCH_initialize(void)
|
||||
NCpathcanonical(home,&globalstate->home);
|
||||
nullfree(home);
|
||||
}
|
||||
fprintf(stderr,">>> HOME=|%s|\n",globalstate->home); fflush(stderr);
|
||||
|
||||
/* Capture $CWD */
|
||||
{
|
||||
|
@ -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.SSL.CAINFO",hostport,NULL);
|
||||
if(value == NULL)
|
||||
value = NC_rclookup("HTTP.SSL.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;
|
||||
|
||||
|
@ -23,6 +23,7 @@ See COPYRIGHT for license information.
|
||||
#include "ncauth.h"
|
||||
#include "ncpathmgr.h"
|
||||
#include "nc4internal.h"
|
||||
#include "ncdispatch.h"
|
||||
|
||||
#ifndef nulldup
|
||||
#define nulldup(x) ((x)?strdup(x):(x))
|
||||
@ -38,8 +39,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 +51,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 +70,64 @@ 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(!NC_initialized) nc_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;
|
||||
|
||||
if(!NC_initialized) nc_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 +151,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 +176,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 +191,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 +248,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 +279,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 +313,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 +369,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 +404,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 +430,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 +441,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 +459,7 @@ rccompile(const char* path)
|
||||
char* key = NULL;
|
||||
char* value = NULL;
|
||||
char* host = NULL;
|
||||
char* urlpath = NULL;
|
||||
size_t llen;
|
||||
NCRCentry* entry;
|
||||
|
||||
@ -406,7 +472,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 +480,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 +500,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 +516,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 +552,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 +671,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 +680,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 +692,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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
7
ncdump/ref_rcapi.txt
Normal 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
|
@ -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
|
||||
|
94
ncdump/tst_rcapi.c
Executable file
94
ncdump/tst_rcapi.c
Executable file
@ -0,0 +1,94 @@
|
||||
/* This is part of the netCDF package.
|
||||
Copyright 2018 University Corporation for Atmospheric Research/Unidata
|
||||
See COPYRIGHT file for conditions of use.
|
||||
|
||||
Test RC interface
|
||||
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");
|
||||
|
||||
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);
|
||||
if(stat) {fprintf(stderr,"***Fail: nc_rc_set: %s\n",nc_strerror(stat)); goto done;}
|
||||
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);
|
||||
if(stat) {fprintf(stderr,"***Fail: nc_rc_set: %s\n",nc_strerror(stat)); goto done;}
|
||||
newvalue = nc_rc_get(key);
|
||||
printf("replace: after: %s = %s\n",key,newvalue);
|
||||
nullfree(newvalue);
|
||||
|
||||
done:
|
||||
nc_finalize();
|
||||
return 0;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user