/* * Copyright 2018, University Corporation for Atmospheric Research * See netcdf/COPYRIGHT file for copying and redistribution conditions. */ #include "zincludes.h" #include "ncwinpath.h" /**************************************************/ /* Import the current implementations */ extern NCZMAP_DS_API zmap_nz4; extern NCZMAP_DS_API zmap_nzf; #ifdef ENABLE_S3_SDK extern NCZMAP_DS_API zmap_s3sdk; #endif /**************************************************/ int nczmap_create(NCZM_IMPL impl, const char *path, int mode, size64_t flags, void* parameters, NCZMAP** mapp) { int stat = NC_NOERR; NCZMAP* map = NULL; NCURI* uri = NULL; if(path == NULL || strlen(path) == 0) {stat = NC_EINVAL; goto done;} if(mapp) *mapp = NULL; switch (impl) { case NCZM_NC4: stat = zmap_nz4.create(path, mode, flags, parameters, &map); if(stat) goto done; break; case NCZM_FILE: stat = zmap_nzf.create(path, mode, flags, parameters, &map); if(stat) goto done; break; #ifdef ENABLE_S3_SDK case NCZM_S3: stat = zmap_s3sdk.create(path, mode, flags, parameters, &map); if(stat) goto done; break; #endif default: {stat = NC_ENOTBUILT; goto done;} } if(mapp) *mapp = map; done: ncurifree(uri); return THROW(stat); } int nczmap_open(NCZM_IMPL impl, const char *path, int mode, size64_t flags, void* parameters, NCZMAP** mapp) { int stat = NC_NOERR; NCZMAP* map = NULL; NCURI* uri = NULL; if(path == NULL || strlen(path) == 0) {stat = NC_EINVAL; goto done;} if(mapp) *mapp = NULL; switch (impl) { case NCZM_NC4: stat = zmap_nz4.open(path, mode, flags, parameters, &map); if(stat) goto done; break; case NCZM_FILE: stat = zmap_nzf.open(path, mode, flags, parameters, &map); if(stat) goto done; break; #ifdef ENABLE_S3_SDK case NCZM_S3: stat = zmap_s3sdk.open(path, mode, flags, parameters, &map); if(stat) goto done; break; #endif default: {stat = NC_ENOTBUILT; goto done;} } done: ncurifree(uri); if(!stat) { if(mapp) *mapp = map; } return THROW(stat); } /**************************************************/ /* API Wrapper */ int nczmap_close(NCZMAP* map, int delete) { int stat = NC_NOERR; if(map && map->api) stat = map->api->close(map,delete); return THROW(stat); } int nczmap_exists(NCZMAP* map, const char* key) { return map->api->exists(map, key); } int nczmap_len(NCZMAP* map, const char* key, size64_t* lenp) { return map->api->len(map, key, lenp); } int nczmap_defineobj(NCZMAP* map, const char* key) { return map->api->defineobj(map, key); } int nczmap_read(NCZMAP* map, const char* key, size64_t start, size64_t count, void* content) { return map->api->read(map, key, start, count, content); } int nczmap_write(NCZMAP* map, const char* key, size64_t start, size64_t count, const void* content) { return map->api->write(map, key, start, count, content); } int nczmap_search(NCZMAP* map, const char* prefix, NClist* matches) { return map->api->search(map, prefix, matches); } /**************************************************/ /* Utilities */ int nczm_split(const char* path, NClist* segments) { return nczm_split_delim(path,NCZM_SEP[0],segments); } int nczm_split_delim(const char* path, char delim, NClist* segments) { int stat = NC_NOERR; const char* p = NULL; const char* q = NULL; ptrdiff_t len = 0; char* seg = NULL; if(path == NULL || strlen(path)==0 || segments == NULL) {stat = NC_EINVAL; goto done;} p = path; if(p[0] == delim) p++; for(;*p;) { q = strchr(p,delim); if(q==NULL) q = p + strlen(p); /* point to trailing nul */ len = (q - p); if(len == 0) {stat = NC_EURL; goto done;} if((seg = malloc(len+1)) == NULL) {stat = NC_ENOMEM; goto done;} memcpy(seg,p,len); seg[len] = '\0'; nclistpush(segments,seg); seg = NULL; /* avoid mem errors */ if(*q) p = q+1; else p = q; } done: nullfree(seg); return THROW(stat); } /* concat the the segments with each segment preceded by '/' */ int nczm_join(NClist* segments, char** pathp) { int stat = NC_NOERR; int i; NCbytes* buf = NULL; if(segments == NULL) {stat = NC_EINVAL; goto done;} if((buf = ncbytesnew())==NULL) {stat = NC_ENOMEM; goto done;} if(nclistlength(segments) == 0) ncbytescat(buf,"/"); else for(i=0;i 0 && suffix[0] != NCZM_SEP[0]) ncbytescat(buf,NCZM_SEP); ncbytescat(buf,suffix); if(pathp) *pathp = ncbytesextract(buf); ncbytesfree(buf); return NC_NOERR; } /* A segment is defined as a '/' plus characters following up to the end or upto the next '/' */ int nczm_divide_at(const char* key, int nsegs, char** prefixp, char** suffixp) { int stat = NC_NOERR; char* prefix = NULL; char* suffix = NULL; size_t len, i; ptrdiff_t delta; const char* p; int abssegs = (nsegs >= 0 ?nsegs: -nsegs); int presegs = 0; /* Special case */ if(key == NULL || strlen(key) == 0) goto done; p = (key[0] == '/' ? key+1 : key); /* Count number of segments */ for(len=0;;) { const char* q = strchr(p,'/'); len++; if(q == NULL) break; p = q+1; /* start past leading '/' of next segment */ } if(abssegs > len) {stat = NC_EINVAL; goto done;} /* find split point */ if(nsegs >= 0) {presegs = abssegs;} else {presegs = (len - abssegs);} /* skip past the first presegs segments */ for(p=key,i=0;iurl); return NC_NOERR; } int nczm_isabsolutepath(const char* path) { if(path == NULL) return 0; switch (path[0]) { case '\\': return 1; case '/': return 1; case '\0': break; default: /* Check for windows drive letter */ if(NChasdriveletter(path)) return 1; break; } return 0; } /* Convert forward slash to backslash ( !localize) or vice-versa (localize)*/ int nczm_localize(const char* path, char** localpathp, int localize) { int stat = NC_NOERR; char* localpath = NULL; char* p; int forward = 1; int offset = 0; #ifdef _MSC_VER forward = (localize?0:1); #endif /* If path comes from a url, then it may start with: /x:/... where x is a drive letter. If so, then remove leading / */ if(path[0] == '/' && NChasdriveletter(path+1)) offset = 1; if((localpath = strdup(path+offset))==NULL) return NC_ENOMEM; for(p=localpath;*p;p++) { if(forward && *p == '\\') *p = '/'; else if(!forward && *p == '/') *p = '\\'; } if(localpathp) {*localpathp = localpath; localpath = NULL;} nullfree(localpath); return stat; } /* Convert path0 to be: 1. absolute -- including drive letters 2. forward slashed -- we will convert back to back slash in nczm_fixpath */ int nczm_canonicalpath(const char* path, char** cpathp) { int ret = NC_NOERR; char* cpath = NULL; char* tmp = NULL; if(path == NULL) {cpath = NULL; goto done;} /* Process path to make it be windows compatible */ if((tmp = NCpathcvt(path))==NULL) {ret = NC_ENOMEM; goto done;} /* Fix slashes to be forward for now */ if((ret = nczm_localize(tmp,&cpath,!LOCALIZE))) goto done; if(cpathp) {*cpathp = cpath; cpath = NULL;} done: nullfree(tmp); nullfree(cpath); return THROW(ret); }