From aabbdbf64cf831035d9700c36762ca2319a10779 Mon Sep 17 00:00:00 2001 From: Dennis Heimbigner Date: Fri, 17 Jun 2022 14:35:12 -0600 Subject: [PATCH 1/3] 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. --- CMakeLists.txt | 2 +- RELEASE_NOTES.md | 2 +- configure.ac | 1 + include/ncrc.h | 4 +- include/netcdf.h | 8 ++ libdispatch/ddispatch.c | 1 - libdispatch/dhttp.c | 19 +++ libdispatch/drc.c | 295 ++++++++++++++++++++++++++++------------ libsrc4/nc4internal.c | 9 +- nc_test4/tst_dims3.c | 4 +- nc_test4/tst_vars3.c | 4 +- ncdump/CMakeLists.txt | 7 + ncdump/Makefile.am | 5 +- ncdump/ref_rcapi.txt | 7 + ncdump/test_rcmerge.sh | 42 ++++-- ncdump/tst_rcapi.c | 92 +++++++++++++ ncdump/tst_rcmerge.c | 29 ++-- 17 files changed, 407 insertions(+), 124 deletions(-) create mode 100644 ncdump/ref_rcapi.txt create mode 100755 ncdump/tst_rcapi.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bf8641bec..78c17e3232 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7693bc9bea..181a8a7048 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -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). diff --git a/configure.ac b/configure.ac index 1ed1325458..b8c28ff6b6 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/include/ncrc.h b/include/ncrc.h index c2ed2b041b..81d62fdffd 100644 --- a/include/ncrc.h +++ b/include/ncrc.h @@ -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); diff --git a/include/netcdf.h b/include/netcdf.h index e55f774563..a4b69071dd 100644 --- a/include/netcdf.h +++ b/include/netcdf.h @@ -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 diff --git a/libdispatch/ddispatch.c b/libdispatch/ddispatch.c index 156208a99f..c4cc56d5bd 100644 --- a/libdispatch/ddispatch.c +++ b/libdispatch/ddispatch.c @@ -95,7 +95,6 @@ NCDISPATCH_initialize(void) NCpathcanonical(home,&globalstate->home); nullfree(home); } -fprintf(stderr,">>> HOME=|%s|\n",globalstate->home); fflush(stderr); /* Capture $CWD */ { diff --git a/libdispatch/dhttp.c b/libdispatch/dhttp.c index 250ddab171..6b707969f1 100644 --- a/libdispatch/dhttp.c +++ b/libdispatch/dhttp.c @@ -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; diff --git a/libdispatch/drc.c b/libdispatch/drc.c index e427eb8a79..d924f58e61 100644 --- a/libdispatch/drc.c +++ b/libdispatch/drc.c @@ -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,10 +69,62 @@ static const char* rcfilenames[] = {".ncrc", ".daprc", ".dodsrc",NULL}; /* Read these files */ static const char* awsconfigfiles[] = {".aws/credentials",".aws/config",NULL}; +static int NCRCinitialized = 0; + /**************************************************/ -/* External Entry Points */ +/* User API */ -static int NCRCinitialized = 0; +/** +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 */ /* Initialize defaults and load: @@ -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 @@ -133,15 +190,22 @@ NC_rcclear(NCRCinfo* info) } static void -rcfreeentries(NClist* rc) +rcfreeentry(NCRCentry* t) { - int i; - for(i=0;ihost); + nullfree(t->urlpath); nullfree(t->key); nullfree(t->value); free(t); +} + +static void +rcfreeentries(NClist* rc) +{ + int i; + for(i=0;ircinfo->rchome; dirnames[1] = globalstate->cwd; @@ -214,15 +277,15 @@ NC_rcload(void) } /** - * 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;ihost == NULL) continue; - nclistpush(rc,ti); + nclistpush(tmprc,ti); } /* pass 2 pull entries without host*/ for(i=0;ihost != NULL) continue; + nclistpush(tmprc,ti); + } + /* Move tmp to rc */ + nclistsetlength(rc,0); + for(i=0;ihost); 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 : ""), + (entry->urlpath != NULL ? entry->urlpath : ""), entry->key,entry->value); #endif - entry = NULL; } +#ifdef DRCDEBUG + fprintf(stderr,"reorder.path=%s\n",filepath); +#endif rcorder(rc); done: @@ -481,46 +551,83 @@ rccompile(const char* path) } /** - * (Internal) Locate a entry by property key and host+port (may be null or ""). +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 struct NCRCentry* -rclocate(const char* key, const char* hostport, const char* path) +static int +rclocatepos(const char* key, const char* hostport, const char* urlpath) { - int i,found; + int i; NCglobalstate* globalstate = NC_getglobalstate(); - NClist* rc = globalstate->rcinfo->entries; + struct NCRCinfo* info = globalstate->rcinfo; NCRCentry* entry = NULL; + NCRCentry candidate; + NClist* rc = info->entries; - if(globalstate->rcinfo->ignore) - return NULL; + if(info->ignore) return -1; - if(key == NULL || rc == NULL) return NULL; - if(hostport == NULL) hostport = ""; + candidate.key = (char*)key; + candidate.value = (char*)NULL; + candidate.host = (char*)hostport; + candidate.urlpath = (char*)urlpath; - for(found=0,i=0;ihost == 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;} + if(rcequal(entry,&candidate)) return i; } - return (found?entry:NULL); + 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* urlpath) +{ + int pos; + NCglobalstate* globalstate = NC_getglobalstate(); + struct NCRCinfo* info = globalstate->rcinfo; + + 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 @@ rcsearch(const char* prefix, const char* rcname, char** pathp) } 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; } diff --git a/libsrc4/nc4internal.c b/libsrc4/nc4internal.c index 878be8c765..b96291dc0b 100644 --- a/libsrc4/nc4internal.c +++ b/libsrc4/nc4internal.c @@ -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; } diff --git a/nc_test4/tst_dims3.c b/nc_test4/tst_dims3.c index 6132328d2a..ac12faac1c 100644 --- a/nc_test4/tst_dims3.c +++ b/nc_test4/tst_dims3.c @@ -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}; diff --git a/nc_test4/tst_vars3.c b/nc_test4/tst_vars3.c index 1b5a7ce793..1758789662 100644 --- a/nc_test4/tst_vars3.c +++ b/nc_test4/tst_vars3.c @@ -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; } diff --git a/ncdump/CMakeLists.txt b/ncdump/CMakeLists.txt index 056810f3c9..7e53c13a22 100644 --- a/ncdump/CMakeLists.txt +++ b/ncdump/CMakeLists.txt @@ -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) diff --git a/ncdump/Makefile.am b/ncdump/Makefile.am index bcce244b54..3f958b1597 100644 --- a/ncdump/Makefile.am +++ b/ncdump/Makefile.am @@ -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. diff --git a/ncdump/ref_rcapi.txt b/ncdump/ref_rcapi.txt new file mode 100644 index 0000000000..9faf226041 --- /dev/null +++ b/ncdump/ref_rcapi.txt @@ -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 diff --git a/ncdump/test_rcmerge.sh b/ncdump/test_rcmerge.sh index d1668a17cb..51020d82e9 100755 --- a/ncdump/test_rcmerge.sh +++ b/ncdump/test_rcmerge.sh @@ -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 diff --git a/ncdump/tst_rcapi.c b/ncdump/tst_rcapi.c new file mode 100755 index 0000000000..620b4cbbc1 --- /dev/null +++ b/ncdump/tst_rcapi.c @@ -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 +#include +#include + +#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("\n"); + exit(0); + } + for(i=0;ihost != 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; +} diff --git a/ncdump/tst_rcmerge.c b/ncdump/tst_rcmerge.c index daa3c7bbba..047b3ebe05 100644 --- a/ncdump/tst_rcmerge.c +++ b/ncdump/tst_rcmerge.c @@ -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; } From 2445d779a3b5817b2cc5538553f0c23915e684a9 Mon Sep 17 00:00:00 2001 From: Dennis Heimbigner Date: Fri, 17 Jun 2022 15:01:03 -0600 Subject: [PATCH 2/3] Update Release Notes --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 181a8a7048..3de6ad7ec7 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -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/????). +* [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). From abba5c383bb590540c6ec4a806236dec54520884 Mon Sep 17 00:00:00 2001 From: Dennis Heimbigner Date: Mon, 20 Jun 2022 14:09:05 -0600 Subject: [PATCH 3/3] Fix errors: 1. I accidentally used ncrc_initialize instead of nc_initialize. 2. Change HTTP.CAINFO to HTTP.SSL.CAINFO --- libdispatch/dhttp.c | 4 ++-- libdispatch/drc.c | 8 +++++--- ncdump/tst_rcapi.c | 6 ++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libdispatch/dhttp.c b/libdispatch/dhttp.c index 6b707969f1..729885163c 100644 --- a/libdispatch/dhttp.c +++ b/libdispatch/dhttp.c @@ -492,9 +492,9 @@ setupconn(NC_HTTP_STATE* state, const char* objecturl) ncuriparse(objecturl,&uri); if(uri == NULL) goto fail; hostport = NC_combinehostport(uri); - value = NC_rclookup("HTTP.CAINFO",hostport,NULL); + value = NC_rclookup("HTTP.SSL.CAINFO",hostport,NULL); if(value == NULL) - value = NC_rclookup("HTTP.CAINFO",NULL,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; diff --git a/libdispatch/drc.c b/libdispatch/drc.c index d924f58e61..7798052ef7 100644 --- a/libdispatch/drc.c +++ b/libdispatch/drc.c @@ -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)) @@ -91,7 +92,8 @@ nc_rc_get(const char* key) NCglobalstate* ncg = NULL; char* value = NULL; - if(!NCRCinitialized) ncrc_initialize(); + 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; @@ -113,9 +115,9 @@ nc_rc_set(const char* key, const char* value) { int stat = NC_NOERR; NCglobalstate* ncg = NULL; - NCRCentry* entry = NULL; - if(!NCRCinitialized) ncrc_initialize(); + 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; diff --git a/ncdump/tst_rcapi.c b/ncdump/tst_rcapi.c index 620b4cbbc1..a7bd0f2393 100755 --- a/ncdump/tst_rcapi.c +++ b/ncdump/tst_rcapi.c @@ -2,7 +2,7 @@ Copyright 2018 University Corporation for Atmospheric Research/Unidata See COPYRIGHT file for conditions of use. - Test HDF5 alignment + Test RC interface Dennis Heimbigner */ @@ -63,7 +63,6 @@ main(int argc, char **argv) char* newvalue; printf("load:\n"); - if ((stat=nc_initialize())) {fprintf(stderr,"***fail\n"); exit(1);} key = "key1"; value = "value1"; @@ -72,6 +71,7 @@ main(int argc, char **argv) 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); @@ -83,10 +83,12 @@ main(int argc, char **argv) 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; }