|
7 | 7 | * Copyright 2018 University Corporation for Atmospheric |
8 | 8 | * Research/Unidata. See COPYRIGHT file for more info. |
9 | 9 | */ |
10 | | - |
11 | 10 | #include "config.h" |
12 | 11 | #include <stddef.h> |
13 | 12 | #include <stdlib.h> |
| 13 | +#include <string.h> |
14 | 14 | #ifdef HAVE_UNISTD_H |
15 | 15 | #include <unistd.h> |
16 | 16 | #endif |
17 | 17 | #ifdef HAVE_SYS_TYPES_H |
18 | 18 | #include <sys/types.h> |
19 | 19 | #endif |
| 20 | +#ifndef _WIN32 |
| 21 | +#ifdef USE_HDF5 |
| 22 | +#include <hdf5.h> |
| 23 | +#endif /* USE_HDF5 */ |
| 24 | +#endif /* _WIN32 */ |
| 25 | +#ifdef HAVE_SYS_XATTR_H |
| 26 | +#include <sys/xattr.h> |
| 27 | +#endif |
20 | 28 |
|
21 | 29 | #include "ncdispatch.h" |
22 | 30 | #include "ncpathmgr.h" |
@@ -229,6 +237,7 @@ static int replacemode(NClist* envv, const char* newval); |
229 | 237 | static void infernext(NClist* current, NClist* next); |
230 | 238 | static int negateone(const char* mode, NClist* modes); |
231 | 239 | static void cleanstringlist(NClist* strs, int caseinsensitive); |
| 240 | +static int isdaoscontainer(const char* path); |
232 | 241 |
|
233 | 242 | /* |
234 | 243 | If the path looks like a URL, then parse it, reformat it. |
@@ -848,7 +857,7 @@ NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void |
848 | 857 | const char* modeval = NULL; |
849 | 858 | char* abspath = NULL; |
850 | 859 | NClist* tmp = NULL; |
851 | | - |
| 860 | + |
852 | 861 | /* Phase 1: |
853 | 862 | 1. convert special protocols to http|https |
854 | 863 | 2. begin collecting fragments |
@@ -967,15 +976,22 @@ NC_infermodel(const char* path, int* omodep, int iscreate, int useparallel, void |
967 | 976 | if((stat = NC_omodeinfer(useparallel,omode,model))) goto done; |
968 | 977 | } |
969 | 978 |
|
970 | | - /* Phase 9: Infer from file content, if possible; |
971 | | - this has highest precedence, so it may override |
972 | | - previous decisions. Note that we do this last |
973 | | - because we need previously determined model info |
974 | | - to guess if this file is readable. |
975 | | - */ |
976 | | - if(!iscreate && isreadable(uri,model)) { |
977 | | - /* Ok, we need to try to read the file */ |
978 | | - if((stat = check_file_type(path, omode, useparallel, params, model, uri))) goto done; |
| 979 | + /* Phase 9: Special case for file stored in DAOS container */ |
| 980 | + if(isdaoscontainer(path) == NC_NOERR) { |
| 981 | + /* This is a DAOS container, so immediately assume it is HDF5. */ |
| 982 | + model->impl = NC_FORMATX_NC_HDF5; |
| 983 | + model->format = NC_FORMAT_NETCDF4; |
| 984 | + } else { |
| 985 | + /* Phase 10: Infer from file content, if possible; |
| 986 | + this has highest precedence, so it may override |
| 987 | + previous decisions. Note that we do this last |
| 988 | + because we need previously determined model info |
| 989 | + to guess if this file is readable. |
| 990 | + */ |
| 991 | + if(!iscreate && isreadable(uri,model)) { |
| 992 | + /* Ok, we need to try to read the file */ |
| 993 | + if((stat = check_file_type(path, omode, useparallel, params, model, uri))) goto done; |
| 994 | + } |
979 | 995 | } |
980 | 996 |
|
981 | 997 | /* Need a decision */ |
@@ -1566,6 +1582,100 @@ NC_interpret_magic_number(char* magic, NCmodel* model) |
1566 | 1582 | return check(status); |
1567 | 1583 | } |
1568 | 1584 |
|
| 1585 | +/* Return NC_NOERR if path is a DAOS container; return NC_EXXX otherwise */ |
| 1586 | +static int |
| 1587 | +isdaoscontainer(const char* path) |
| 1588 | +{ |
| 1589 | + int stat = NC_ENOTNC; /* default is that this is not a DAOS container */ |
| 1590 | +#ifndef _WIN32 |
| 1591 | +#ifdef USE_HDF5 |
| 1592 | +#if H5_VERSION_GE(1,12,0) |
| 1593 | + htri_t accessible; |
| 1594 | + hid_t fapl_id; |
| 1595 | + int rc; |
| 1596 | + /* Check for a DAOS container */ |
| 1597 | + if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) {stat = NC_EHDFERR; goto done;} |
| 1598 | + H5Pset_fapl_sec2(fapl_id); |
| 1599 | + accessible = H5Fis_accessible(path, fapl_id); |
| 1600 | + H5Pclose(fapl_id); /* Ignore any error */ |
| 1601 | + rc = 0; |
| 1602 | + if(accessible > 0) { |
| 1603 | +#ifdef HAVE_SYS_XATTR_H |
| 1604 | + ssize_t xlen; |
| 1605 | +#ifdef __APPLE__ |
| 1606 | + xlen = listxattr(path, NULL, 0, 0); |
| 1607 | +#else |
| 1608 | + xlen = listxattr(path, NULL, 0); |
| 1609 | +#endif |
| 1610 | + if(xlen > 0) { |
| 1611 | + char* xlist = NULL; |
| 1612 | + char* xvalue = NULL; |
| 1613 | + char* p; |
| 1614 | + char* endp; |
| 1615 | + if((xlist = (char*)calloc(1,(size_t)xlen))==NULL) |
| 1616 | + {stat = NC_ENOMEM; goto done;} |
| 1617 | +#ifdef __APPLE__ |
| 1618 | + (void)listxattr(path, xlist, (size_t)xlen, 0); /* Get xattr names */ |
| 1619 | +#else |
| 1620 | + (void)listxattr(path, xlist, (size_t)xlen); /* Get xattr names */ |
| 1621 | +#endif |
| 1622 | + p = xlist; endp = p + xlen; /* delimit names */ |
| 1623 | + /* walk the list of xattr names */ |
| 1624 | + for(;p < endp;p += (strlen(p)+1)) { |
| 1625 | + /* The popen version looks for the string ".daos"; |
| 1626 | + It would be nice if we know whether that occurred |
| 1627 | + int the xattr's name or it value. |
| 1628 | + Oh well, we will do the general search */ |
| 1629 | + /* Look for '.daos' in the key */ |
| 1630 | + if(strstr(p,".daos") != NULL) {rc = 1; break;} /* success */ |
| 1631 | + /* Else get the p'th xattr's value size */ |
| 1632 | +#ifdef __APPLE__ |
| 1633 | + xlen = getxattr(path, p, NULL, 0, 0, 0); |
| 1634 | +#else |
| 1635 | + xlen = getxattr(path, p, NULL, 0); |
| 1636 | +#endif |
| 1637 | + if((xvalue = (char*)calloc(1,(size_t)xlen))==NULL) |
| 1638 | + {stat = NC_ENOMEM; goto done;} |
| 1639 | + /* Read the value */ |
| 1640 | +#ifdef __APPLE__ |
| 1641 | + (void)getxattr(path, p, xvalue, (size_t)xlen, 0, 0); |
| 1642 | +#else |
| 1643 | + (void)getxattr(path, p, xvalue, (size_t)xlen); |
| 1644 | +#endif |
| 1645 | +fprintf(stderr,"@@@ %s=|%s|\n",p,xvalue); |
| 1646 | + /* Look for '.daos' in the value */ |
| 1647 | + if(strstr(xvalue,".daos") != NULL) {rc = 1; break;} /* success */ |
| 1648 | + } |
| 1649 | + } |
| 1650 | +#else /*!HAVE_SYS_XATTR_H*/ |
| 1651 | + |
| 1652 | +#ifdef HAVE_GETFATTR |
| 1653 | + { |
| 1654 | + FILE *fp; |
| 1655 | + char cmd[4096]; |
| 1656 | + memset(cmd,0,sizeof(cmd)); |
| 1657 | + snprintf(cmd,sizeof(cmd),"getfattr %s | grep -c '.daos'",path); |
| 1658 | + if((fp = popen(cmd, "r")) != NULL) { |
| 1659 | + fscanf(fp, "%d", &rc); |
| 1660 | + pclose(fp); |
| 1661 | + } |
| 1662 | + } |
| 1663 | +#else /*!HAVE_GETFATTR*/ |
| 1664 | + /* We just can't test for DAOS container.*/ |
| 1665 | + stat = 0; |
| 1666 | +#endif /*HAVE_GETFATTR*/ |
| 1667 | +#endif /*HAVE_SYS_XATTR_H*/ |
| 1668 | + } |
| 1669 | + /* Test for DAOS container */ |
| 1670 | + stat = (rc == 1 ? NC_NOERR : NC_ENOTNC); |
| 1671 | +done: |
| 1672 | +#endif |
| 1673 | +#endif |
| 1674 | +#endif |
| 1675 | + errno = 0; /* reset */ |
| 1676 | + return stat; |
| 1677 | +} |
| 1678 | + |
1569 | 1679 | #ifdef DEBUG |
1570 | 1680 | static void |
1571 | 1681 | printmagic(const char* tag, char* magic, struct MagicFile* f) |
|
0 commit comments