Merge in updated version of the file from Dennis.

This commit is contained in:
Ward Fisher 2024-07-16 09:59:03 -06:00
parent 41f802d1a4
commit e5973deda1

View File

@ -10,12 +10,21 @@
#include "config.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifndef _WIN32
#ifdef USE_HDF5
#include <hdf5.h>
#endif /* USE_HDF5 */
#endif /* _WIN32 */
#ifdef HAVE_SYS_XATTR_H
#include <sys/xattr.h>
#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 <unistd.h>
#include <hdf5.h>
#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)