diff --git a/libdispatch/dinfermodel.c b/libdispatch/dinfermodel.c index c11cd548f..a68e222d8 100644 --- a/libdispatch/dinfermodel.c +++ b/libdispatch/dinfermodel.c @@ -10,12 +10,21 @@ #include "config.h" #include #include +#include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif +#ifndef _WIN32 +#ifdef USE_HDF5 +#include +#endif /* USE_HDF5 */ +#endif /* _WIN32 */ +#ifdef HAVE_SYS_XATTR_H +#include +#endif #include "ncdispatch.h" #include "ncpathmgr.h" @@ -33,12 +42,6 @@ #ifndef nulldup #define nulldup(x) ((x)?strdup(x):(x)) #endif -#ifndef _WIN32 -#ifdef USE_HDF5 -#include -#include -#endif /* USE_HDF5 */ -#endif /* _WIN32 */ #undef DEBUG @@ -234,6 +237,7 @@ static int replacemode(NClist* envv, const char* newval); static void infernext(NClist* current, NClist* next); static int negateone(const char* mode, NClist* modes); static void cleanstringlist(NClist* strs, int caseinsensitive); +static int isdaoscontainer(const char* path); /* If the path looks like a URL, then parse it, reformat it. @@ -851,45 +855,6 @@ NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void NClist* modeargs = nclistnew(); char* sfrag = NULL; const char* modeval = NULL; - - /* Check for a DAOS container */ -#ifndef _WIN32 -#ifdef USE_HDF5 -#if H5_VERSION_GE(1,12,0) - hid_t fapl_id; - if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) goto done; - H5Pset_fapl_sec2(fapl_id); - - htri_t accessible; - accessible = H5Fis_accessible(path, fapl_id); - if(accessible > 0) { - int rc=0; - FILE *fp; - char *cmd; - cmd = (char*)malloc((strlen(path)+28)*sizeof(char)); - strcpy(cmd, "getfattr "); - strcat(cmd, path); - strcat(cmd, " | grep -c '.daos'"); - - if((fp = popen(cmd, "r")) != NULL) { - fscanf(fp, "%d", &rc); - pclose(fp); - } - free(cmd); - if(rc == 1) { - /* Is a DAOS container */ - model->impl = NC_FORMATX_NC4; - model->format = NC_FORMAT_NETCDF4; - if (H5Pclose(fapl_id) < 0) goto done; - goto done; - } - } - if (H5Pclose(fapl_id) < 0) goto done; -#endif -#endif -#endif - - char* abspath = NULL; NClist* tmp = NULL; @@ -1011,15 +976,22 @@ NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void if((stat = NC_omodeinfer(useparallel,omode,model))) goto done; } - /* Phase 9: Infer from file content, if possible; - this has highest precedence, so it may override - previous decisions. Note that we do this last - because we need previously determined model info - to guess if this file is readable. - */ - if(!iscreate && isreadable(uri,model)) { - /* Ok, we need to try to read the file */ - if((stat = check_file_type(path, omode, useparallel, params, model, uri))) goto done; + /* Phase 9: Special case for file stored in DAOS container */ + if(isdaoscontainer(path) == NC_NOERR) { + /* This is a DAOS container, so immediately assume it is HDF5. */ + model->impl = NC_FORMATX_NC_HDF5; + model->format = NC_FORMAT_NETCDF4; + } else { + /* Phase 10: Infer from file content, if possible; + this has highest precedence, so it may override + previous decisions. Note that we do this last + because we need previously determined model info + to guess if this file is readable. + */ + if(!iscreate && isreadable(uri,model)) { + /* Ok, we need to try to read the file */ + if((stat = check_file_type(path, omode, useparallel, params, model, uri))) goto done; + } } /* Need a decision */ @@ -1610,6 +1582,94 @@ done: return check(status); } +/* Return NC_NOERR if path is a DAOS container; return NC_EXXX otherwise */ +static int +isdaoscontainer(const char* path) +{ + int stat = NC_ENOTNC; /* default is that this is not a DAOS container */ +#ifndef _WIN32 +#ifdef USE_HDF5 +#if H5_VERSION_GE(1,12,0) + htri_t accessible; + hid_t fapl_id; + int rc; + /* Check for a DAOS container */ + if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) {stat = NC_EHDFERR; goto done;} + H5Pset_fapl_sec2(fapl_id); + accessible = H5Fis_accessible(path, fapl_id); + H5Pclose(fapl_id); /* Ignore any error */ + rc = 0; + if(accessible > 0) { +#ifdef HAVE_SYS_XATTR_H + ssize_t xlen; +#ifdef __APPLE__ + xlen = listxattr(path, NULL, 0, 0); +#else + xlen = listxattr(path, NULL, 0); +#endif + if(xlen > 0) { + char* xlist = NULL; + char* xvalue = NULL; + char* p; + char* endp; + if((xlist = (char*)calloc(1,(size_t)xlen))==NULL) + {stat = NC_ENOMEM; goto done;} +#ifdef __APPLE__ + (void)listxattr(path, xlist, (size_t)xlen, 0); /* Get xattr names */ +#else + (void)listxattr(path, xlist, (size_t)xlen); /* Get xattr names */ +#endif + p = xlist; endp = p + xlen; /* delimit names */ + /* walk the list of xattr names */ + for(;p < endp;p += (strlen(p)+1)) { + /* The popen version looks for the string ".daos"; + It would be nice if we know whether that occurred + int the xattr's name or it value. + Oh well, we will do the general search */ + /* Look for '.daos' in the key */ + if(strstr(p,".daos") != NULL) {rc = 1; break;} /* success */ + /* Else get the p'th xattr's value size */ +#ifdef __APPLE__ + xlen = getxattr(path, p, NULL, 0, 0, 0); +#else + xlen = getxattr(path, p, NULL, 0); +#endif + if((xvalue = (char*)calloc(1,(size_t)xlen))==NULL) + {stat = NC_ENOMEM; goto done;} + /* Read the value */ +#ifdef __APPLE__ + (void)getxattr(path, p, xvalue, (size_t)xlen, 0, 0); +#else + (void)getxattr(path, p, xvalue, (size_t)xlen); +#endif +fprintf(stderr,"@@@ %s=|%s|\n",p,xvalue); + /* Look for '.daos' in the value */ + if(strstr(xvalue,".daos") != NULL) {rc = 1; break;} /* success */ + } + } +#else /*!HAVE_SYS_XATTR_H*/ + { + FILE *fp; + char cmd[4096]; + memset(cmd,0,sizeof(cmd)); + snprintf(cmd,sizeof(cmd),"getfattr %s | grep -c '.daos'",path); + if((fp = popen(cmd, "r")) != NULL) { + fscanf(fp, "%d", &rc); + pclose(fp); + } + } +#endif /*HAVE_SYS_XATTR_H*/ + } + /* Test for DAOS container */ + stat = (rc == 1 ? NC_NOERR : NC_ENOTNC); +done: +#endif +#endif +#endif + errno = 0; /* reset */ + return stat; +} + #ifdef DEBUG static void printmagic(const char* tag, char* magic, struct MagicFile* f)