2018-07-17 21:55:27 +08:00
|
|
|
/* Copyright 2003-2018, University Corporation for Atmospheric
|
|
|
|
* Research. See COPYRIGHT file for copying and redistribution
|
|
|
|
* conditions. */
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @internal The netCDF-4 file functions relating to file creation.
|
|
|
|
*
|
|
|
|
* @author Ed Hartnett
|
|
|
|
*/
|
2018-07-17 22:29:47 +08:00
|
|
|
|
2018-07-17 21:55:27 +08:00
|
|
|
#include "config.h"
|
Codify cross-platform file paths
The netcdf-c code has to deal with a variety of platforms:
Windows, OSX, Linux, Cygwin, MSYS, etc. These platforms differ
significantly in the kind of file paths that they accept. So in
order to handle this, I have created a set of replacements for
the most common file system operations such as _open_ or _fopen_
or _access_ to manage the file path differences correctly.
A more limited version of this idea was already implemented via
the ncwinpath.h and dwinpath.c code. So this can be viewed as a
replacement for that code. And in path in many cases, the only
change that was required was to replace '#include <ncwinpath.h>'
with '#include <ncpathmgt.h>' and then replace file operation
calls with the NCxxx equivalent from ncpathmgr.h Note that
recently, the ncwinpath.h was renamed ncpathmgmt.h, so this pull
request should not require dealing with winpath.
The heart of the change is include/ncpathmgmt.h, which provides
alternate operations such as NCfopen or NCaccess and which properly
parse and rebuild path arguments to work for the platform on which
the code is executing. This mostly matters for Windows because of the
way that it uses backslash and drive letters, as compared to *nix*.
One important feature is that the user can do string manipulations
on a file path without having to worry too much about the platform
because the path management code will properly handle most mixed cases.
So one can for example concatenate a path suffix that uses forward
slashes to a Windows path and have it work correctly.
The conversion code is in libdispatch/dpathmgr.c, and the
important function there is NCpathcvt which does the proper
conversions to the local path format.
As a rule, most code should just replace their file operations with
the corresponding NCxxx ones defined in include/ncpathmgmt.h. These
NCxxx functions all call NCpathcvt on their path arguments before
executing the actual file operation.
In some rare cases, the client may need to directly use NCpathcvt,
but this should be avoided as much as possible. If there is a need
for supporting a new file operation not already in ncpathmgmt.h, then
use the code in dpathmgr.c as a template. Also please notify Unidata
so we can include it as a formal part or our supported operations.
Also, if you see an operation in the library that is not using the
NCxxx form, then please submit an issue so we can fix it.
Misc. Changes:
* Clean up the utf8 testing code; it is impossible to get some
tests to work under windows using shell scripts; the args do
not pass as utf8 but as some other encoding.
* Added an extra utf8 test case: test_unicode_path.sh
* Add a true test for HDF5 1.10.6 or later because as noted in
PR https://github.com/Unidata/netcdf-c/pull/1794,
HDF5 changed its Windows file path handling.
2021-03-05 04:41:31 +08:00
|
|
|
#include "netcdf.h"
|
|
|
|
#include "ncpathmgr.h"
|
|
|
|
#include "ncpathmgr.h"
|
2018-07-17 21:55:27 +08:00
|
|
|
#include "hdf5internal.h"
|
|
|
|
|
|
|
|
/* From hdf5file.c. */
|
|
|
|
extern size_t nc4_chunk_cache_size;
|
|
|
|
extern size_t nc4_chunk_cache_nelems;
|
|
|
|
extern float nc4_chunk_cache_preemption;
|
|
|
|
|
|
|
|
/** @internal These flags may not be set for create. */
|
|
|
|
static const int ILLEGAL_CREATE_FLAGS = (NC_NOWRITE|NC_MMAP|NC_64BIT_OFFSET|NC_CDF5);
|
|
|
|
|
|
|
|
/* From nc4mem.c */
|
|
|
|
extern int NC4_create_image_file(NC_FILE_INFO_T* h5, size_t);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal Create a netCDF-4/HDF5 file.
|
|
|
|
*
|
|
|
|
* @param path The file name of the new file.
|
|
|
|
* @param cmode The creation mode flag.
|
2019-07-29 03:52:05 +08:00
|
|
|
* @param initialsz The proposed initial file size (advisory, for
|
|
|
|
* in-memory netCDF-4/HDF5 files only).
|
|
|
|
* @param parameters extra parameter info (like MPI communicator).
|
2019-08-02 23:29:18 +08:00
|
|
|
* @param ncid The already-assigned ncid for this file (aka ext_ncid).
|
2018-07-17 21:55:27 +08:00
|
|
|
*
|
|
|
|
* @return ::NC_NOERR No error.
|
|
|
|
* @return ::NC_EINVAL Invalid input (check cmode).
|
|
|
|
* @return ::NC_EEXIST File exists and NC_NOCLOBBER used.
|
|
|
|
* @return ::NC_EHDFERR HDF5 returned error.
|
|
|
|
* @ingroup netcdf4
|
|
|
|
* @author Ed Hartnett, Dennis Heimbigner
|
|
|
|
*/
|
|
|
|
static int
|
2018-07-17 23:03:19 +08:00
|
|
|
nc4_create_file(const char *path, int cmode, size_t initialsz,
|
2019-08-02 23:29:18 +08:00
|
|
|
void* parameters, int ncid)
|
2018-07-17 21:55:27 +08:00
|
|
|
{
|
2019-02-19 20:17:47 +08:00
|
|
|
hid_t fcpl_id, fapl_id = -1;
|
|
|
|
unsigned flags;
|
|
|
|
FILE *fp;
|
|
|
|
int retval = NC_NOERR;
|
2019-08-02 23:29:18 +08:00
|
|
|
NC_FILE_INFO_T *nc4_info;
|
2019-02-19 20:17:47 +08:00
|
|
|
NC_HDF5_FILE_INFO_T *hdf5_info;
|
|
|
|
NC_HDF5_GRP_INFO_T *hdf5_grp;
|
2018-07-17 21:55:27 +08:00
|
|
|
|
|
|
|
#ifdef USE_PARALLEL4
|
2019-02-19 20:17:47 +08:00
|
|
|
NC_MPI_INFO *mpiinfo = NULL;
|
|
|
|
MPI_Comm comm;
|
|
|
|
MPI_Info info;
|
|
|
|
int comm_duped = 0; /* Whether the MPI Communicator was duplicated */
|
|
|
|
int info_duped = 0; /* Whether the MPI Info object was duplicated */
|
2018-07-17 21:55:27 +08:00
|
|
|
#endif /* !USE_PARALLEL4 */
|
|
|
|
|
2019-08-02 23:29:18 +08:00
|
|
|
assert(path);
|
2019-02-19 20:17:47 +08:00
|
|
|
LOG((3, "%s: path %s mode 0x%x", __func__, path, cmode));
|
|
|
|
|
|
|
|
/* Add necessary structs to hold netcdf-4 file data. */
|
2019-08-03 23:04:58 +08:00
|
|
|
if ((retval = nc4_file_list_add(ncid, path, NC_WRITE | cmode,
|
|
|
|
(void **)&nc4_info)))
|
2019-02-19 20:17:47 +08:00
|
|
|
BAIL(retval);
|
|
|
|
assert(nc4_info && nc4_info->root_grp);
|
|
|
|
nc4_info->root_grp->atts_read = 1;
|
|
|
|
|
|
|
|
/* Add struct to hold HDF5-specific file metadata. */
|
|
|
|
if (!(nc4_info->format_file_info = calloc(1, sizeof(NC_HDF5_FILE_INFO_T))))
|
|
|
|
BAIL(NC_ENOMEM);
|
|
|
|
hdf5_info = (NC_HDF5_FILE_INFO_T *)nc4_info->format_file_info;
|
|
|
|
|
|
|
|
/* Add struct to hold HDF5-specific group info. */
|
|
|
|
if (!(nc4_info->root_grp->format_grp_info = calloc(1, sizeof(NC_HDF5_GRP_INFO_T))))
|
|
|
|
return NC_ENOMEM;
|
|
|
|
hdf5_grp = (NC_HDF5_GRP_INFO_T *)nc4_info->root_grp->format_grp_info;
|
|
|
|
|
|
|
|
nc4_info->mem.inmemory = (cmode & NC_INMEMORY) == NC_INMEMORY;
|
|
|
|
nc4_info->mem.diskless = (cmode & NC_DISKLESS) == NC_DISKLESS;
|
|
|
|
nc4_info->mem.persist = (cmode & NC_PERSIST) == NC_PERSIST;
|
|
|
|
nc4_info->mem.created = 1;
|
|
|
|
nc4_info->mem.initialsize = initialsz;
|
|
|
|
|
|
|
|
/* diskless => !inmemory */
|
|
|
|
if(nc4_info->mem.inmemory && nc4_info->mem.diskless)
|
|
|
|
BAIL(NC_EINTERNAL);
|
|
|
|
|
|
|
|
if(nc4_info->mem.inmemory && parameters)
|
|
|
|
nc4_info->mem.memio = *(NC_memio*)parameters;
|
2018-07-17 21:55:27 +08:00
|
|
|
#ifdef USE_PARALLEL4
|
2019-02-19 20:17:47 +08:00
|
|
|
else if(parameters) {
|
|
|
|
mpiinfo = (NC_MPI_INFO *)parameters;
|
|
|
|
comm = mpiinfo->comm;
|
|
|
|
info = mpiinfo->info;
|
|
|
|
}
|
2018-07-17 21:55:27 +08:00
|
|
|
#endif
|
2019-02-19 20:17:47 +08:00
|
|
|
if(nc4_info->mem.diskless)
|
|
|
|
flags = H5F_ACC_TRUNC;
|
|
|
|
else if(cmode & NC_NOCLOBBER)
|
|
|
|
flags = H5F_ACC_EXCL;
|
|
|
|
else
|
|
|
|
flags = H5F_ACC_TRUNC;
|
|
|
|
|
|
|
|
/* If this file already exists, and NC_NOCLOBBER is specified,
|
|
|
|
return an error (unless diskless|inmemory) */
|
|
|
|
if (!nc4_info->mem.diskless && !nc4_info->mem.inmemory) {
|
Codify cross-platform file paths
The netcdf-c code has to deal with a variety of platforms:
Windows, OSX, Linux, Cygwin, MSYS, etc. These platforms differ
significantly in the kind of file paths that they accept. So in
order to handle this, I have created a set of replacements for
the most common file system operations such as _open_ or _fopen_
or _access_ to manage the file path differences correctly.
A more limited version of this idea was already implemented via
the ncwinpath.h and dwinpath.c code. So this can be viewed as a
replacement for that code. And in path in many cases, the only
change that was required was to replace '#include <ncwinpath.h>'
with '#include <ncpathmgt.h>' and then replace file operation
calls with the NCxxx equivalent from ncpathmgr.h Note that
recently, the ncwinpath.h was renamed ncpathmgmt.h, so this pull
request should not require dealing with winpath.
The heart of the change is include/ncpathmgmt.h, which provides
alternate operations such as NCfopen or NCaccess and which properly
parse and rebuild path arguments to work for the platform on which
the code is executing. This mostly matters for Windows because of the
way that it uses backslash and drive letters, as compared to *nix*.
One important feature is that the user can do string manipulations
on a file path without having to worry too much about the platform
because the path management code will properly handle most mixed cases.
So one can for example concatenate a path suffix that uses forward
slashes to a Windows path and have it work correctly.
The conversion code is in libdispatch/dpathmgr.c, and the
important function there is NCpathcvt which does the proper
conversions to the local path format.
As a rule, most code should just replace their file operations with
the corresponding NCxxx ones defined in include/ncpathmgmt.h. These
NCxxx functions all call NCpathcvt on their path arguments before
executing the actual file operation.
In some rare cases, the client may need to directly use NCpathcvt,
but this should be avoided as much as possible. If there is a need
for supporting a new file operation not already in ncpathmgmt.h, then
use the code in dpathmgr.c as a template. Also please notify Unidata
so we can include it as a formal part or our supported operations.
Also, if you see an operation in the library that is not using the
NCxxx form, then please submit an issue so we can fix it.
Misc. Changes:
* Clean up the utf8 testing code; it is impossible to get some
tests to work under windows using shell scripts; the args do
not pass as utf8 but as some other encoding.
* Added an extra utf8 test case: test_unicode_path.sh
* Add a true test for HDF5 1.10.6 or later because as noted in
PR https://github.com/Unidata/netcdf-c/pull/1794,
HDF5 changed its Windows file path handling.
2021-03-05 04:41:31 +08:00
|
|
|
if ((cmode & NC_NOCLOBBER) && (fp = NCfopen(path, "r"))) {
|
2019-02-19 20:17:47 +08:00
|
|
|
fclose(fp);
|
|
|
|
BAIL(NC_EEXIST);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Need this access plist to control how HDF5 handles open objects
|
2020-09-03 02:02:08 +08:00
|
|
|
* on file close. (Setting H5F_CLOSE_WEAK will cause H5Fclose not to
|
|
|
|
* fail if there are any open objects in the file. This may happen when virtual
|
|
|
|
* datasets are opened). */
|
2019-02-19 20:17:47 +08:00
|
|
|
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
2020-09-03 02:02:08 +08:00
|
|
|
if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_WEAK))
|
2019-02-19 20:17:47 +08:00
|
|
|
BAIL(NC_EHDFERR);
|
2018-07-17 21:55:27 +08:00
|
|
|
|
|
|
|
#ifdef USE_PARALLEL4
|
2019-02-19 20:17:47 +08:00
|
|
|
/* If this is a parallel file create, set up the file creation
|
|
|
|
property list. */
|
|
|
|
if (mpiinfo != NULL) {
|
|
|
|
nc4_info->parallel = NC_TRUE;
|
|
|
|
LOG((4, "creating parallel file with MPI/IO"));
|
|
|
|
if (H5Pset_fapl_mpio(fapl_id, comm, info) < 0)
|
|
|
|
BAIL(NC_EPARINIT);
|
|
|
|
|
|
|
|
/* Keep copies of the MPI Comm & Info objects */
|
|
|
|
if (MPI_SUCCESS != MPI_Comm_dup(comm, &nc4_info->comm))
|
2018-07-17 21:55:27 +08:00
|
|
|
BAIL(NC_EMPI);
|
2019-02-19 20:17:47 +08:00
|
|
|
comm_duped++;
|
|
|
|
if (MPI_INFO_NULL != info)
|
|
|
|
{
|
|
|
|
if (MPI_SUCCESS != MPI_Info_dup(info, &nc4_info->info))
|
|
|
|
BAIL(NC_EMPI);
|
|
|
|
info_duped++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No dup, just copy it. */
|
|
|
|
nc4_info->info = info;
|
|
|
|
}
|
|
|
|
}
|
2018-07-17 21:55:27 +08:00
|
|
|
#endif /* USE_PARALLEL4 */
|
|
|
|
|
2020-05-09 01:00:56 +08:00
|
|
|
/* Only set cache for non-parallel creates. */
|
|
|
|
if (!nc4_info->parallel)
|
|
|
|
{
|
|
|
|
if (H5Pset_cache(fapl_id, 0, nc4_chunk_cache_nelems, nc4_chunk_cache_size,
|
|
|
|
nc4_chunk_cache_preemption) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
|
|
|
LOG((4, "%s: set HDF raw chunk cache to size %d nelems %d preemption %f",
|
|
|
|
__func__, nc4_chunk_cache_size, nc4_chunk_cache_nelems,
|
|
|
|
nc4_chunk_cache_preemption));
|
|
|
|
}
|
|
|
|
|
2018-07-17 21:55:27 +08:00
|
|
|
#if H5_VERSION_GE(1,10,2)
|
2021-01-12 00:36:53 +08:00
|
|
|
/* lib versions 1.10.2 and higher */
|
|
|
|
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_V18, H5F_LIBVER_LATEST) < 0)
|
2018-07-17 21:55:27 +08:00
|
|
|
#else
|
2021-01-12 00:36:53 +08:00
|
|
|
#if H5_VERSION_GE(1,10,0)
|
2021-01-11 23:48:04 +08:00
|
|
|
/* lib versions 1.10.0, 1.10.1 */
|
2021-01-12 00:22:18 +08:00
|
|
|
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_EARLIEST, H5F_LIBVER_LATEST) < 0)
|
2021-01-11 23:48:04 +08:00
|
|
|
#else
|
2021-01-12 00:36:53 +08:00
|
|
|
/* all HDF5 1.8 lib versions */
|
|
|
|
if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
|
2018-07-17 21:55:27 +08:00
|
|
|
#endif
|
|
|
|
#endif
|
2021-01-09 01:15:10 +08:00
|
|
|
BAIL(NC_EHDFERR);
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-02-19 20:17:47 +08:00
|
|
|
/* Create the property list. */
|
|
|
|
if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-02-19 20:17:47 +08:00
|
|
|
/* RJ: this suppose to be FALSE that is defined in H5 private.h as 0 */
|
|
|
|
if (H5Pset_obj_track_times(fcpl_id,0)<0)
|
|
|
|
BAIL(NC_EHDFERR);
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-02-19 20:17:47 +08:00
|
|
|
/* Set latest_format in access propertly list and
|
|
|
|
* H5P_CRT_ORDER_TRACKED in the creation property list. This turns
|
|
|
|
* on HDF5 creation ordering. */
|
|
|
|
if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
|
|
|
|
H5P_CRT_ORDER_INDEXED)) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
|
|
|
if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
|
|
|
|
H5P_CRT_ORDER_INDEXED)) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
2018-07-17 21:55:27 +08:00
|
|
|
|
|
|
|
#ifdef HDF5_HAS_COLL_METADATA_OPS
|
2019-02-19 20:17:47 +08:00
|
|
|
/* If HDF5 supports collective metadata operations, turn them
|
|
|
|
* on. This is only relevant for parallel I/O builds of HDF5. */
|
|
|
|
if (H5Pset_all_coll_metadata_ops(fapl_id, 1) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
|
|
|
if (H5Pset_coll_metadata_write(fapl_id, 1) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
2018-07-17 21:55:27 +08:00
|
|
|
#endif
|
|
|
|
|
2019-02-19 20:17:47 +08:00
|
|
|
if(nc4_info->mem.inmemory) {
|
|
|
|
retval = NC4_create_image_file(nc4_info,initialsz);
|
|
|
|
if(retval)
|
|
|
|
BAIL(retval);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(nc4_info->mem.diskless) {
|
|
|
|
size_t alloc_incr; /* Buffer allocation increment */
|
|
|
|
size_t min_incr = 65536; /* Minimum buffer increment */
|
|
|
|
double buf_prcnt = 0.1f; /* Percentage of buffer size to set as increment */
|
|
|
|
/* set allocation increment to a percentage of the supplied buffer size, or
|
|
|
|
* a pre-defined minimum increment value, whichever is larger
|
|
|
|
*/
|
|
|
|
if ((buf_prcnt * initialsz) > min_incr)
|
|
|
|
alloc_incr = (size_t)(buf_prcnt * initialsz);
|
|
|
|
else
|
|
|
|
alloc_incr = min_incr;
|
|
|
|
/* Configure FAPL to use the core file driver */
|
|
|
|
if (H5Pset_fapl_core(fapl_id, alloc_incr, (nc4_info->mem.persist?1:0)) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
2020-07-12 01:28:47 +08:00
|
|
|
if ((hdf5_info->hdfid = nc4_H5Fcreate(path, flags, fcpl_id, fapl_id)) < 0)
|
2019-02-19 20:17:47 +08:00
|
|
|
BAIL(EACCES);
|
|
|
|
}
|
|
|
|
else /* Normal file */
|
|
|
|
{
|
|
|
|
/* Create the HDF5 file. */
|
2020-07-12 01:28:47 +08:00
|
|
|
if ((hdf5_info->hdfid = nc4_H5Fcreate(path, flags, fcpl_id, fapl_id)) < 0)
|
2019-02-19 20:17:47 +08:00
|
|
|
BAIL(EACCES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Open the root group. */
|
|
|
|
if ((hdf5_grp->hdf_grpid = H5Gopen2(hdf5_info->hdfid, "/", H5P_DEFAULT)) < 0)
|
|
|
|
BAIL(NC_EFILEMETA);
|
|
|
|
|
|
|
|
/* Release the property lists. */
|
|
|
|
if (H5Pclose(fapl_id) < 0 || H5Pclose(fcpl_id) < 0)
|
|
|
|
BAIL(NC_EHDFERR);
|
|
|
|
|
|
|
|
/* Define mode gets turned on automatically on create. */
|
|
|
|
nc4_info->flags |= NC_INDEF;
|
|
|
|
|
|
|
|
/* Save the HDF5 superblock number and set the _NCProperties attribute. */
|
2019-03-10 11:35:57 +08:00
|
|
|
if ((retval = NC4_new_provenance(nc4_info)))
|
2019-02-19 20:17:47 +08:00
|
|
|
BAIL(retval);
|
|
|
|
|
|
|
|
return NC_NOERR;
|
2018-07-17 21:55:27 +08:00
|
|
|
|
|
|
|
exit: /*failure exit*/
|
|
|
|
#ifdef USE_PARALLEL4
|
2019-02-19 20:17:47 +08:00
|
|
|
if (comm_duped) MPI_Comm_free(&nc4_info->comm);
|
|
|
|
if (info_duped) MPI_Info_free(&nc4_info->info);
|
2018-07-17 21:55:27 +08:00
|
|
|
#endif
|
2019-02-19 20:17:47 +08:00
|
|
|
if (fapl_id != H5P_DEFAULT) H5Pclose(fapl_id);
|
|
|
|
if(!nc4_info) return retval;
|
|
|
|
nc4_close_hdf5_file(nc4_info, 1, NULL); /* treat like abort */
|
|
|
|
return retval;
|
2018-07-17 21:55:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal Create a netCDF-4/HDF5 file.
|
|
|
|
*
|
|
|
|
* @param path The file name of the new file.
|
|
|
|
* @param cmode The creation mode flag.
|
|
|
|
* @param initialsz Ignored by this function.
|
|
|
|
* @param basepe Ignored by this function.
|
|
|
|
* @param chunksizehintp Ignored by this function.
|
2018-07-17 23:03:19 +08:00
|
|
|
* @param parameters pointer to struct holding extra data (e.g. for
|
|
|
|
* parallel I/O) layer. Ignored if NULL.
|
2018-07-17 21:55:27 +08:00
|
|
|
* @param dispatch Pointer to the dispatch table for this file.
|
2019-08-02 04:30:20 +08:00
|
|
|
* @param ncid The ncid that has been assigned by the dispatch layer
|
|
|
|
* (aka ext_ncid).
|
2018-07-17 21:55:27 +08:00
|
|
|
*
|
|
|
|
* @return ::NC_NOERR No error.
|
|
|
|
* @return ::NC_EINVAL Invalid input (check cmode).
|
|
|
|
* @ingroup netcdf4
|
|
|
|
* @author Ed Hartnett
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
NC4_create(const char* path, int cmode, size_t initialsz, int basepe,
|
2018-09-23 09:22:34 +08:00
|
|
|
size_t *chunksizehintp, void *parameters,
|
2019-08-02 04:30:20 +08:00
|
|
|
const NC_Dispatch *dispatch, int ncid)
|
2018-07-17 21:55:27 +08:00
|
|
|
{
|
2019-02-19 20:17:47 +08:00
|
|
|
int res;
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-08-02 04:30:20 +08:00
|
|
|
assert(path);
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-02-19 20:17:47 +08:00
|
|
|
LOG((1, "%s: path %s cmode 0x%x parameters %p",
|
|
|
|
__func__, path, cmode, parameters));
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-02-19 20:17:47 +08:00
|
|
|
/* If this is our first file, turn off HDF5 error messages. */
|
|
|
|
if (!nc4_hdf5_initialized)
|
|
|
|
nc4_hdf5_initialize();
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2018-08-07 00:57:19 +08:00
|
|
|
#ifdef LOGGING
|
2019-02-19 20:17:47 +08:00
|
|
|
/* If nc logging level has changed, see if we need to turn on
|
|
|
|
* HDF5's error messages. */
|
|
|
|
hdf5_set_log_level();
|
2018-08-07 00:57:19 +08:00
|
|
|
#endif /* LOGGING */
|
|
|
|
|
2019-07-29 03:43:01 +08:00
|
|
|
/* Check the cmode for validity. Checking parallel against
|
|
|
|
* NC_DISKLESS already done in NC_create(). */
|
2019-08-02 04:30:20 +08:00
|
|
|
if (cmode & ILLEGAL_CREATE_FLAGS)
|
2019-07-29 05:48:25 +08:00
|
|
|
return NC_EINVAL;
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-07-29 03:43:01 +08:00
|
|
|
/* Create the netCDF-4/HDF5 file. */
|
2019-08-02 23:29:18 +08:00
|
|
|
res = nc4_create_file(path, cmode, initialsz, parameters, ncid);
|
2018-07-17 21:55:27 +08:00
|
|
|
|
2019-02-19 20:17:47 +08:00
|
|
|
return res;
|
2018-07-17 21:55:27 +08:00
|
|
|
}
|
2020-07-12 01:28:47 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrapper function for H5Fcreate.
|
|
|
|
* Converts the filename from ANSI to UTF-8 as needed before calling H5Fcreate.
|
|
|
|
*
|
|
|
|
* @param filename The filename encoded ANSI to access.
|
|
|
|
* @param flags File access flags.
|
|
|
|
* @param fcpl_id File creation property list identifier.
|
|
|
|
* @param fapl_id File access property list identifier.
|
|
|
|
* @return A file identifier if succeeded. A negative value if failed.
|
|
|
|
*/
|
Codify cross-platform file paths
The netcdf-c code has to deal with a variety of platforms:
Windows, OSX, Linux, Cygwin, MSYS, etc. These platforms differ
significantly in the kind of file paths that they accept. So in
order to handle this, I have created a set of replacements for
the most common file system operations such as _open_ or _fopen_
or _access_ to manage the file path differences correctly.
A more limited version of this idea was already implemented via
the ncwinpath.h and dwinpath.c code. So this can be viewed as a
replacement for that code. And in path in many cases, the only
change that was required was to replace '#include <ncwinpath.h>'
with '#include <ncpathmgt.h>' and then replace file operation
calls with the NCxxx equivalent from ncpathmgr.h Note that
recently, the ncwinpath.h was renamed ncpathmgmt.h, so this pull
request should not require dealing with winpath.
The heart of the change is include/ncpathmgmt.h, which provides
alternate operations such as NCfopen or NCaccess and which properly
parse and rebuild path arguments to work for the platform on which
the code is executing. This mostly matters for Windows because of the
way that it uses backslash and drive letters, as compared to *nix*.
One important feature is that the user can do string manipulations
on a file path without having to worry too much about the platform
because the path management code will properly handle most mixed cases.
So one can for example concatenate a path suffix that uses forward
slashes to a Windows path and have it work correctly.
The conversion code is in libdispatch/dpathmgr.c, and the
important function there is NCpathcvt which does the proper
conversions to the local path format.
As a rule, most code should just replace their file operations with
the corresponding NCxxx ones defined in include/ncpathmgmt.h. These
NCxxx functions all call NCpathcvt on their path arguments before
executing the actual file operation.
In some rare cases, the client may need to directly use NCpathcvt,
but this should be avoided as much as possible. If there is a need
for supporting a new file operation not already in ncpathmgmt.h, then
use the code in dpathmgr.c as a template. Also please notify Unidata
so we can include it as a formal part or our supported operations.
Also, if you see an operation in the library that is not using the
NCxxx form, then please submit an issue so we can fix it.
Misc. Changes:
* Clean up the utf8 testing code; it is impossible to get some
tests to work under windows using shell scripts; the args do
not pass as utf8 but as some other encoding.
* Added an extra utf8 test case: test_unicode_path.sh
* Add a true test for HDF5 1.10.6 or later because as noted in
PR https://github.com/Unidata/netcdf-c/pull/1794,
HDF5 changed its Windows file path handling.
2021-03-05 04:41:31 +08:00
|
|
|
hid_t
|
|
|
|
nc4_H5Fcreate(const char *filename0, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
|
2020-07-12 01:28:47 +08:00
|
|
|
{
|
|
|
|
hid_t hid;
|
Codify cross-platform file paths
The netcdf-c code has to deal with a variety of platforms:
Windows, OSX, Linux, Cygwin, MSYS, etc. These platforms differ
significantly in the kind of file paths that they accept. So in
order to handle this, I have created a set of replacements for
the most common file system operations such as _open_ or _fopen_
or _access_ to manage the file path differences correctly.
A more limited version of this idea was already implemented via
the ncwinpath.h and dwinpath.c code. So this can be viewed as a
replacement for that code. And in path in many cases, the only
change that was required was to replace '#include <ncwinpath.h>'
with '#include <ncpathmgt.h>' and then replace file operation
calls with the NCxxx equivalent from ncpathmgr.h Note that
recently, the ncwinpath.h was renamed ncpathmgmt.h, so this pull
request should not require dealing with winpath.
The heart of the change is include/ncpathmgmt.h, which provides
alternate operations such as NCfopen or NCaccess and which properly
parse and rebuild path arguments to work for the platform on which
the code is executing. This mostly matters for Windows because of the
way that it uses backslash and drive letters, as compared to *nix*.
One important feature is that the user can do string manipulations
on a file path without having to worry too much about the platform
because the path management code will properly handle most mixed cases.
So one can for example concatenate a path suffix that uses forward
slashes to a Windows path and have it work correctly.
The conversion code is in libdispatch/dpathmgr.c, and the
important function there is NCpathcvt which does the proper
conversions to the local path format.
As a rule, most code should just replace their file operations with
the corresponding NCxxx ones defined in include/ncpathmgmt.h. These
NCxxx functions all call NCpathcvt on their path arguments before
executing the actual file operation.
In some rare cases, the client may need to directly use NCpathcvt,
but this should be avoided as much as possible. If there is a need
for supporting a new file operation not already in ncpathmgmt.h, then
use the code in dpathmgr.c as a template. Also please notify Unidata
so we can include it as a formal part or our supported operations.
Also, if you see an operation in the library that is not using the
NCxxx form, then please submit an issue so we can fix it.
Misc. Changes:
* Clean up the utf8 testing code; it is impossible to get some
tests to work under windows using shell scripts; the args do
not pass as utf8 but as some other encoding.
* Added an extra utf8 test case: test_unicode_path.sh
* Add a true test for HDF5 1.10.6 or later because as noted in
PR https://github.com/Unidata/netcdf-c/pull/1794,
HDF5 changed its Windows file path handling.
2021-03-05 04:41:31 +08:00
|
|
|
char* localname = NULL;
|
|
|
|
char* filename = NULL;
|
2020-07-12 01:28:47 +08:00
|
|
|
|
Codify cross-platform file paths
The netcdf-c code has to deal with a variety of platforms:
Windows, OSX, Linux, Cygwin, MSYS, etc. These platforms differ
significantly in the kind of file paths that they accept. So in
order to handle this, I have created a set of replacements for
the most common file system operations such as _open_ or _fopen_
or _access_ to manage the file path differences correctly.
A more limited version of this idea was already implemented via
the ncwinpath.h and dwinpath.c code. So this can be viewed as a
replacement for that code. And in path in many cases, the only
change that was required was to replace '#include <ncwinpath.h>'
with '#include <ncpathmgt.h>' and then replace file operation
calls with the NCxxx equivalent from ncpathmgr.h Note that
recently, the ncwinpath.h was renamed ncpathmgmt.h, so this pull
request should not require dealing with winpath.
The heart of the change is include/ncpathmgmt.h, which provides
alternate operations such as NCfopen or NCaccess and which properly
parse and rebuild path arguments to work for the platform on which
the code is executing. This mostly matters for Windows because of the
way that it uses backslash and drive letters, as compared to *nix*.
One important feature is that the user can do string manipulations
on a file path without having to worry too much about the platform
because the path management code will properly handle most mixed cases.
So one can for example concatenate a path suffix that uses forward
slashes to a Windows path and have it work correctly.
The conversion code is in libdispatch/dpathmgr.c, and the
important function there is NCpathcvt which does the proper
conversions to the local path format.
As a rule, most code should just replace their file operations with
the corresponding NCxxx ones defined in include/ncpathmgmt.h. These
NCxxx functions all call NCpathcvt on their path arguments before
executing the actual file operation.
In some rare cases, the client may need to directly use NCpathcvt,
but this should be avoided as much as possible. If there is a need
for supporting a new file operation not already in ncpathmgmt.h, then
use the code in dpathmgr.c as a template. Also please notify Unidata
so we can include it as a formal part or our supported operations.
Also, if you see an operation in the library that is not using the
NCxxx form, then please submit an issue so we can fix it.
Misc. Changes:
* Clean up the utf8 testing code; it is impossible to get some
tests to work under windows using shell scripts; the args do
not pass as utf8 but as some other encoding.
* Added an extra utf8 test case: test_unicode_path.sh
* Add a true test for HDF5 1.10.6 or later because as noted in
PR https://github.com/Unidata/netcdf-c/pull/1794,
HDF5 changed its Windows file path handling.
2021-03-05 04:41:31 +08:00
|
|
|
#ifdef HDF5_UTF8_PATHS
|
|
|
|
NCpath2utf8(filename0,&filename);
|
|
|
|
#else
|
|
|
|
filename = strdup(filename0);
|
|
|
|
#endif
|
|
|
|
/* Canonicalize it since we are not opening the file ourselves */
|
|
|
|
if((localname = NCpathcvt(filename))==NULL)
|
|
|
|
{hid = H5I_INVALID_HID; goto done;}
|
|
|
|
hid = H5Fcreate(localname, flags, fcpl_id, fapl_id);
|
|
|
|
done:
|
|
|
|
nullfree(filename);
|
|
|
|
nullfree(localname);
|
2020-07-12 01:28:47 +08:00
|
|
|
return hid;
|
|
|
|
}
|