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..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 #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). 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..729885163c 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.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; diff --git a/libdispatch/drc.c b/libdispatch/drc.c index e427eb8a79..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)) @@ -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,10 +70,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; + /**************************************************/ -/* 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(!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 */ /* Initialize defaults and load: @@ -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 @@ -133,15 +192,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 +279,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 +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;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 +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 : ""), + (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 +553,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 +671,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 +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; } 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..a7bd0f2393 --- /dev/null +++ b/ncdump/tst_rcapi.c @@ -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 +#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"); + + 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; +} 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; }