20 #include "chunkspec.h"
27 #define snprintf _snprintf
34 #define COPY_BUFFER_SIZE (5000000)
35 #define COPY_CHUNKCACHE_PREEMPTION (1.0f)
36 #define SAME_AS_INPUT (-1)
37 #define CHUNK_THRESHOLD (8192)
40 #define NC_CLASSIC_MODEL 0x0100
45 static int option_kind = SAME_AS_INPUT;
46 static int option_deflate_level = -1;
48 static int option_fix_unlimdims = 0;
49 static char* option_chunkspec = 0;
50 static size_t option_copy_buffer_size = COPY_BUFFER_SIZE;
51 static size_t option_chunk_cache_size = CHUNK_CACHE_SIZE;
52 static size_t option_chunk_cache_nelems = CHUNK_CACHE_NELEMS;
53 static int option_read_diskless = 0;
54 static int option_write_diskless = 0;
55 static int option_min_chunk_bytes = CHUNK_THRESHOLD;
58 static int option_nlgrps = 0;
60 static char** option_lgrps = 0;
62 static idnode_t* option_grpids = 0;
63 static bool_t option_grpstruct =
false;
64 static int option_nlvars = 0;
65 static char** option_lvars = 0;
67 static bool_t option_varstruct =
false;
68 static int option_compute_chunkcaches = 0;
74 get_grpid(
int igrp,
int parid,
int *ogrpp) {
81 stat = nc_inq_grp_parent(igrp, &inparid);
84 NC_CHECK(nc_inq_grpname(igrp, grpname));
85 NC_CHECK(nc_inq_grp_ncid(parid, grpname, &ogid));
98 val_size(
int grpid,
int varid) {
102 NC_CHECK(
nc_inq_type(grpid, vartype, NULL, &value_size));
111 nc_inq_parid(
int ncid,
const char *fullname,
int *locidp) {
112 char *parent = strdup(fullname);
118 last_slash = strrchr(parent,
'/');
119 if(last_slash == parent || last_slash == NULL) {
121 parent = strdup(slash);
125 NC_CHECK(nc_inq_grp_full_ncid(ncid, parent, locidp));
133 inq_var_chunksize(
int igrp,
int varid,
size_t* chunksizep) {
145 NC_CHECK(
nc_inq_type(igrp, vartype, NULL, &value_size));
148 chunksizes = (
size_t *) emalloc((ndims + 1) *
sizeof(size_t));
156 for(dim = 0; dim < ndims; dim++) {
157 prod *= chunksizes[dim];
170 inq_var_chunking_params(
int igrp,
int ivarid,
int ogrp,
int ovarid,
171 size_t* chunkcache_sizep,
172 size_t *chunkcache_nelemsp,
173 float * chunkcache_preemptionp)
177 size_t *ichunksizes, *ochunksizes;
179 int icontig = 1, ocontig = 1;
182 size_t prod, iprod, oprod;
184 *chunkcache_nelemsp = CHUNK_CACHE_NELEMS;
185 *chunkcache_sizep = CHUNK_CACHE_SIZE;
186 *chunkcache_preemptionp = COPY_CHUNKCACHE_PREEMPTION;
193 if(icontig == 1 && ocontig == 1) {
194 *chunkcache_nelemsp = 0;
195 *chunkcache_sizep = 0;
196 *chunkcache_preemptionp = 0;
201 NC_CHECK(
nc_inq_type(igrp, vartype, NULL, &value_size));
204 if(icontig == 0 && ocontig == 1) {
205 *chunkcache_nelemsp = 1;
206 *chunkcache_sizep = iprod;
207 *chunkcache_preemptionp = 1.0f;
211 ichunksizes = (
size_t *) emalloc((ndims + 1) *
sizeof(size_t));
215 for(dim = 1; dim < ndims; dim++) {
216 ichunksizes[dim] = dim;
223 ochunksizes = (
size_t *) emalloc((ndims + 1) *
sizeof(size_t));
228 for(dim = 0; dim < ndims; dim++) {
229 nelems += 1 + (ichunksizes[dim] - 1) / ochunksizes[dim];
230 iprod *= ichunksizes[dim];
231 oprod *= ochunksizes[dim];
233 prod = iprod + oprod * (nelems - 1);
234 *chunkcache_nelemsp = nelems;
235 *chunkcache_sizep = prod;
242 static int copy_type(
int igrp,
nc_type typeid,
int ogrp);
249 copy_vlen_type(
int igrp,
nc_type itype,
int ogrp)
260 NC_CHECK(
nc_inq_vlen(igrp, itype, name, &size, &ibasetype));
263 NC_CHECK(
nc_inq_type(igrp, ibasetype, basename, &basesize));
267 NC_CHECK(copy_type(igrp, ibasetype, ogrp));
273 NC_CHECK(
nc_def_vlen(ogrp, name, obasetype, &vlen_type));
282 copy_opaque_type(
int igrp,
nc_type itype,
int ogrp)
299 copy_enum_type(
int igrp,
nc_type itype,
int ogrp)
309 NC_CHECK(
nc_inq_enum(igrp, itype, name, &basetype, &basesize, &nmembers));
310 NC_CHECK(
nc_def_enum(ogrp, basetype, name, &otype));
311 for(i = 0; i < nmembers; i++) {
324 copy_compound_type(
int igrp,
nc_type itype,
int ogrp)
336 for (fid = 0; fid < nfields; fid++) {
347 NC_CHECK(
nc_inq_type(igrp, iftype, ftypename, NULL));
353 fdimsizes = (
int *) emalloc((fndims + 1) *
sizeof(int));
368 copy_type(
int igrp,
nc_type typeid,
int ogrp)
373 NC_CHECK(
nc_inq_user_type(igrp,
typeid, NULL, NULL, NULL, NULL, &type_class));
377 NC_CHECK(copy_vlen_type(igrp,
typeid, ogrp));
380 NC_CHECK(copy_opaque_type(igrp,
typeid, ogrp));
383 NC_CHECK(copy_enum_type(igrp,
typeid, ogrp));
386 NC_CHECK(copy_compound_type(igrp,
typeid, ogrp));
399 copy_groups(
int iroot,
int oroot)
407 NC_CHECK(nc_inq_grps_full(iroot, &numgrps, NULL));
409 grpids = emalloc(numgrps *
sizeof(
int));
410 NC_CHECK(nc_inq_grps_full(iroot, NULL, grpids));
412 for(i = 1; i < numgrps; i++) {
416 int ogid, oparid, iparid;
418 NC_CHECK(nc_inq_grpname(grpids[i], grpname));
419 if (option_grpstruct || group_wanted(grpids[i], option_nlgrps, option_grpids)) {
420 NC_CHECK(nc_inq_grpname_full(grpids[i], &len_name, NULL));
421 grpname_full = emalloc(len_name + 1);
422 NC_CHECK(nc_inq_grpname_full(grpids[i], &len_name, grpname_full));
424 NC_CHECK(nc_inq_parid(iroot, grpname_full, &iparid));
425 if (!option_grpstruct && !group_wanted(iparid, option_nlgrps, option_grpids)
426 && iparid != iroot) {
427 error(
"ERROR: trying to copy a group but not the parent: %s", grpname_full);
433 NC_CHECK(nc_inq_parid(oroot, grpname_full, &oparid));
434 NC_CHECK(nc_inq_grpname(grpids[i], grpname));
436 NC_CHECK(nc_def_grp(oparid, grpname, &ogid));
450 copy_types(
int igrp,
int ogrp)
459 NC_CHECK(nc_inq_typeids(igrp, &ntypes, NULL));
463 NC_CHECK(nc_inq_typeids(igrp, &ntypes, types));
464 for (i = 0; i < ntypes; i++) {
465 NC_CHECK(copy_type(igrp, types[i], ogrp));
471 NC_CHECK(nc_inq_grps(igrp, &numgrps, NULL));
473 grpids = (
int *)emalloc(
sizeof(
int) * numgrps);
474 NC_CHECK(nc_inq_grps(igrp, &numgrps, grpids));
475 for(i = 0; i < numgrps; i++) {
476 if (option_grpstruct || group_wanted(grpids[i], option_nlgrps, option_grpids)) {
481 NC_CHECK(get_grpid(grpids[i], ogrp, &ogid));
482 NC_CHECK(copy_types(grpids[i], ogid));
493 copy_var_specials(
int igrp,
int varid,
int ogrp,
int o_varid)
501 size_t *chunkp = (
size_t *) emalloc(ndims *
sizeof(
size_t));
502 int *dimids = (
int *) emalloc(ndims *
sizeof(
int));
505 size_t csprod = val_size(ogrp, o_varid);
506 int is_unlimited = 0;
510 for(idim = 0; idim < ndims; idim++) {
511 int idimid = dimids[idim];
512 int odimid = dimmap_odimid(idimid);
513 size_t chunksize = chunkspec_size(idimid);
515 chunkp[idim] = chunksize;
517 csprod *= chunkp[idim];
518 if(dimmap_ounlim(odimid))
524 if ((csprod < option_min_chunk_bytes && !is_unlimited) || contig == 1) {
525 NC_CHECK(nc_def_var_chunking(ogrp, o_varid,
NC_CONTIGUOUS, NULL));
527 NC_CHECK(nc_def_var_chunking(ogrp, o_varid,
NC_CHUNKED, chunkp));
535 int shuffle, deflate, deflate_level;
537 if(deflate_level == 0 && deflate == 1)
539 if(option_deflate_level >= 0) {
540 deflate_level = option_deflate_level;
543 if(shuffle==0 && option_shuffle_vars != 0) {
544 shuffle = option_shuffle_vars;
546 if(deflate != 0 || shuffle != 0) {
547 NC_CHECK(nc_def_var_deflate(ogrp, o_varid, shuffle, deflate_level > 0, deflate_level));
553 if(fletcher32 != 0) {
554 NC_CHECK(nc_def_var_fletcher32(ogrp, o_varid, fletcher32));
561 NC_CHECK(nc_def_var_endian(ogrp, o_varid, endianness));
571 set_var_chunked(
int ogrp,
int o_varid)
576 size_t chunk_threshold = CHUNK_THRESHOLD;
578 if(chunkspec_ndims() == 0)
584 int *dimids = (
int *) emalloc(ndims *
sizeof(
int));
588 int is_unlimited = 0;
593 NC_CHECK(
nc_inq_type(ogrp, vartype, NULL, &value_size));
594 varsize = value_size;
600 for(odim = 0; odim < ndims; odim++) {
601 int odimid = dimids[odim];
602 int idimid = dimmap_idimid(odimid);
603 if(dimmap_ounlim(odimid))
606 size_t chunksize = chunkspec_size(idimid);
609 if( (chunksize > 0) || dimmap_ounlim(odimid)) {
617 if(varsize < chunk_threshold && !is_unlimited)
623 size_t *chunkp = (
size_t *) emalloc(ndims *
sizeof(
size_t));
624 for(odim = 0; odim < ndims; odim++) {
625 int odimid = dimids[odim];
626 int idimid = dimmap_idimid(odimid);
627 size_t chunksize = chunkspec_size(idimid);
629 chunkp[odim] = chunksize;
634 NC_CHECK(nc_def_var_chunking(ogrp, o_varid,
NC_CHUNKED, chunkp));
644 set_var_compressed(
int ogrp,
int o_varid)
647 if (option_deflate_level >= 0) {
649 NC_CHECK(nc_def_var_deflate(ogrp, o_varid, option_shuffle_vars, deflate, option_deflate_level));
659 free_var_chunk_cache(
int grp,
int varid)
662 size_t chunk_cache_size = 1;
663 size_t cache_nelems = 1;
664 float cache_preemp = 0;
685 copy_dims(
int igrp,
int ogrp)
705 dimids = (
int *) emalloc((ndims + 1) *
sizeof(int));
706 NC_CHECK(nc_inq_dimids(igrp, NULL, dimids, 0));
709 unlimids = (
int *) emalloc((nunlims + 1) *
sizeof(int));
716 for (dgrp = 0; dgrp < ndims; dgrp++) {
728 idimid = dimids[dgrp];
729 for (uld = 0; uld < nunlims; uld++) {
730 if(idimid == unlimids[uld]) {
737 if(unlimid != -1 && (idimid == unlimid)) {
742 stat =
nc_inq_dim(igrp, idimid, name, &length);
744 error(
"dimension \"%s\" requires 64-bit platform", name);
747 o_is_unlim = i_is_unlim;
748 if(i_is_unlim && !option_fix_unlimdims) {
751 NC_CHECK(
nc_def_dim(ogrp, name, length, &odimid));
755 dimmap_store(idimid, odimid, i_is_unlim, o_is_unlim);
768 copy_atts(
int igrp,
int ivar,
int ogrp,
int ovar)
776 for(iatt = 0; iatt < natts; iatt++) {
779 NC_CHECK(nc_copy_att(igrp, ivar, name, ogrp, ovar));
786 copy_var(
int igrp,
int varid,
int ogrp)
799 idimids = (
int *) emalloc((ndims + 1) *
sizeof(int));
800 NC_CHECK(
nc_inq_var(igrp, varid, name, &
typeid, NULL, idimids, &natts));
808 NC_CHECK(
nc_inq_type(igrp,
typeid, type_name, NULL));
814 odimids = (
int *) emalloc((ndims + 1) *
sizeof(int));
815 for(i = 0; i < ndims; i++) {
816 odimids[i] = dimmap_odimid(idimids[i]);
817 if(odimids[i] == -1) {
818 error(
"Oops, no dimension in output associated with input dimid %d", idimids[i]);
823 NC_CHECK(
nc_def_var(ogrp, name, o_typeid, ndims, odimids, &o_varid));
826 NC_CHECK(copy_atts(igrp, varid, ogrp, o_varid));
837 NC_CHECK(copy_var_specials(igrp, varid, ogrp, o_varid));
840 NC_CHECK(set_var_chunked(ogrp, o_varid));
843 NC_CHECK(set_var_compressed(ogrp, o_varid));
854 copy_vars(
int igrp,
int ogrp)
870 for (iv=0; iv < option_nlvars; iv++) {
871 if(nc_inq_gvarid(igrp, option_lvars[iv], &varid) ==
NC_NOERR)
875 NC_CHECK(nc_inq_nvars(igrp, &nvars));
876 for (varid = 0; varid < nvars; varid++) {
877 if (!option_varstruct && option_nlvars > 0 && ! idmember(vlist, varid))
879 NC_CHECK(copy_var(igrp, varid, ogrp));
889 copy_schema(
int igrp,
int ogrp)
896 NC_CHECK(get_grpid(igrp, ogrp, &ogid));
898 NC_CHECK(copy_dims(igrp, ogid));
900 NC_CHECK(copy_vars(igrp, ogid));
907 stat = nc_inq_grps(igrp, &numgrps, NULL);
908 grpids = (
int *)emalloc((numgrps + 1) *
sizeof(int));
909 NC_CHECK(nc_inq_grps(igrp, &numgrps, grpids));
911 for(i = 0; i < numgrps; i++) {
912 if (option_grpstruct || group_wanted(grpids[i], option_nlgrps, option_grpids)) {
913 NC_CHECK(copy_schema(grpids[i], ogid));
924 inq_nvals(
int igrp,
int varid,
long long *nvalsp) {
932 dimids = (
int *) emalloc((ndims + 1) *
sizeof(int));
934 for(dim = 0; dim < ndims; dim++) {
948 copy_var_data(
int igrp,
int varid,
int ogrp) {
954 static void *buf = 0;
966 NC_CHECK(inq_nvals(igrp, varid, &nvalues));
973 value_size = val_size(igrp, varid);
974 if(value_size > option_copy_buffer_size) {
975 option_copy_buffer_size = value_size;
985 if(option_compute_chunkcaches) {
989 size_t chunkcache_size, chunkcache_nelems;
990 float chunkcache_preemption;
991 NC_CHECK(inq_var_chunking_params(igrp, varid, ogrp, ovarid,
994 &chunkcache_preemption));
998 chunkcache_preemption));
1002 option_chunk_cache_size,
1003 option_chunk_cache_nelems,
1004 COPY_CHUNKCACHE_PREEMPTION));
1011 NC_CHECK(inq_var_chunksize(igrp, varid, &chunksize));
1012 if(chunksize > option_copy_buffer_size) {
1013 option_copy_buffer_size = chunksize;
1018 if(buf && do_realloc) {
1023 buf = emalloc(option_copy_buffer_size);
1024 memset((
void*)buf,0,option_copy_buffer_size);
1028 NC_CHECK(nc_get_iter(igrp, varid, option_copy_buffer_size, &iterp));
1030 start = (
size_t *) emalloc((iterp->rank + 1) *
sizeof(size_t));
1031 count = (
size_t *) emalloc((iterp->rank + 1) *
sizeof(size_t));
1035 while((ntoget = nc_next_iter(iterp, start, count)) > 0) {
1036 NC_CHECK(
nc_get_vara(igrp, varid, start, count, buf));
1037 NC_CHECK(
nc_put_vara(ogrp, ovarid, start, count, buf));
1044 NC_CHECK(
nc_inq_user_type(igrp, vartype, NULL, NULL, NULL, NULL, &vclass));
1059 NC_CHECK(nc_free_iter(iterp));
1067 copy_data(
int igrp,
int ogrp)
1080 idnode_t* vlist = 0;
1088 vlist = newidlist();
1089 for (iv=0; iv < option_nlvars; iv++) {
1090 if(nc_inq_gvarid(igrp, option_lvars[iv], &varid) ==
NC_NOERR)
1091 idadd(vlist, varid);
1096 NC_CHECK(get_grpid(igrp, ogrp, &ogid));
1099 NC_CHECK(nc_inq_nvars(igrp, &nvars));
1101 for (varid = 0; varid < nvars; varid++) {
1102 if (option_nlvars > 0 && ! idmember(vlist, varid))
1104 if (!group_wanted(igrp, option_nlgrps, option_grpids))
1106 NC_CHECK(copy_var_data(igrp, varid, ogid));
1110 stat = nc_inq_grps(igrp, &numgrps, NULL);
1111 grpids = (
int *)emalloc((numgrps + 1) *
sizeof(int));
1112 NC_CHECK(nc_inq_grps(igrp, &numgrps, grpids));
1114 for(i = 0; i < numgrps; i++) {
1115 if (!option_grpstruct && !group_wanted(grpids[i], option_nlgrps, option_grpids))
1117 NC_CHECK(copy_data(grpids[i], ogid));
1131 NC_CHECK(nc_inq_grps(ncid, &numgrps, NULL));
1134 int *grpids = emalloc(numgrps *
sizeof(
int));
1135 NC_CHECK(nc_inq_grps(ncid, &numgrps, grpids));
1136 for(igrp = 0; igrp < numgrps; igrp++) {
1137 ndims += count_dims(grpids[igrp]);
1153 nc3_special_case(
int ncid,
int kind) {
1157 if (recdimid != -1) {
1160 NC_CHECK(nc_inq_nvars(ncid, &nvars));
1161 for (varid = 0; varid < nvars; varid++) {
1167 dimids = (
int *) emalloc((ndims + 1) *
sizeof(int));
1169 dimids0 = dimids[0];
1171 if(dimids0 == recdimid) {
1194 NC_CHECK(nc_inq_nvars(ncid, &nvars));
1196 *fvars = (
int *) emalloc(nvars *
sizeof(
int));
1198 *rvars = (
int *) emalloc(nvars *
sizeof(
int));
1199 for (varid = 0; varid < nvars; varid++) {
1200 if (isrecvar(ncid, varid)) {
1201 (*rvars)[*nr] = varid;
1204 (*fvars)[*nf] = varid;
1213 copy_fixed_size_data(
int igrp,
int ogrp,
size_t nfixed_vars,
int *fixed_varids) {
1216 for (ivar = 0; ivar < nfixed_vars; ivar++) {
1217 int varid = fixed_varids[ivar];
1218 NC_CHECK(copy_var_data(igrp, varid, ogrp));
1227 copy_rec_var_data(
int ncid,
1237 NC_CHECK(
nc_get_vara(ncid, varid, start, count, buf));
1238 NC_CHECK(
nc_put_vara(ogrp, ovarid, start, count, buf));
1244 copy_record_data(
int ncid,
int ogrp,
size_t nrec_vars,
int *rec_varids) {
1255 buf = (
void **) emalloc(nrec_vars *
sizeof(
void *));
1256 rec_ovarids = (
int *) emalloc(nrec_vars *
sizeof(
int));
1257 start = (
size_t **) emalloc(nrec_vars *
sizeof(
size_t*));
1258 count = (
size_t **) emalloc(nrec_vars *
sizeof(
size_t*));
1260 for (ivar = 0; ivar < nrec_vars; ivar++) {
1269 varid = rec_varids[ivar];
1271 dimids = (
int *) emalloc((1 + ndims) *
sizeof(int));
1272 start[ivar] = (
size_t *) emalloc(ndims *
sizeof(
size_t));
1273 count[ivar] = (
size_t *) emalloc(ndims *
sizeof(
size_t));
1275 value_size = val_size(ncid, varid);
1277 for(ii = 1; ii < ndims; ii++) {
1282 start[ivar][ii] = 0;
1283 count[ivar][ii] = dimlen;
1287 buf[ivar] = (
void *) emalloc(nvals * value_size);
1289 NC_CHECK(
nc_inq_varid(ogrp, varname, &rec_ovarids[ivar]));
1295 for(irec = 0; irec < nrecs; irec++) {
1296 for (ivar = 0; ivar < nrec_vars; ivar++) {
1298 varid = rec_varids[ivar];
1299 ovarid = rec_ovarids[ivar];
1300 start[ivar][0] = irec;
1301 NC_CHECK(copy_rec_var_data(ncid, ogrp, irec, varid, ovarid,
1302 start[ivar], count[ivar], buf[ivar]));
1305 for (ivar = 0; ivar < nrec_vars; ivar++) {
1315 for (ivar = 0; ivar < nrec_vars; ivar++) {
1332 copy(
char* infile,
char* outfile)
1336 int inkind, outkind;
1341 if(option_read_diskless) {
1345 NC_CHECK(
nc_open(infile, open_mode, &igrp));
1360 outkind = option_kind;
1361 if (option_kind == SAME_AS_INPUT) {
1365 if (option_deflate_level > 0 ||
1375 if(option_chunkspec) {
1378 NC_CHECK(chunkspec_parse(igrp, option_chunkspec));
1383 if(missing_vars(igrp, option_nlvars, option_lvars))
1384 return EXIT_FAILURE;
1386 if(option_nlgrps > 0) {
1388 error(
"Group list (-g ...) only permitted for netCDF-4 file");
1389 return EXIT_FAILURE;
1392 if(grp_matches(igrp, option_nlgrps, option_lgrps, option_grpids) == 0)
1393 return EXIT_FAILURE;
1396 if(option_write_diskless)
1415 error(
"nccopy built with --disable-netcdf4, can't create netCDF-4 files");
1419 error(
"bad value (%d) for -k option\n", option_kind);
1422 NC_CHECK(
nc_create(outfile, create_mode, &ogrp));
1429 NC_CHECK(copy_groups(igrp, ogrp));
1430 NC_CHECK(copy_types(igrp, ogrp));
1434 ndims = count_dims(igrp);
1435 NC_CHECK(dimmap_init(ndims));
1436 NC_CHECK(copy_schema(igrp, ogrp));
1443 if(nc3_special_case(igrp, inkind)) {
1444 size_t nfixed_vars, nrec_vars;
1447 NC_CHECK(classify_vars(igrp, &nfixed_vars, &fixed_varids, &nrec_vars, &rec_varids));
1448 NC_CHECK(copy_fixed_size_data(igrp, ogrp, nfixed_vars, fixed_varids));
1449 NC_CHECK(copy_record_data(igrp, ogrp, nrec_vars, rec_varids));
1450 }
else if (nc3_special_case(ogrp, outkind)) {
1451 size_t nfixed_vars, nrec_vars;
1455 NC_CHECK(classify_vars(ogrp, &nfixed_vars, &fixed_varids, &nrec_vars, &rec_varids));
1456 NC_CHECK(copy_fixed_size_data(igrp, ogrp, nfixed_vars, fixed_varids));
1457 NC_CHECK(copy_record_data(igrp, ogrp, nrec_vars, rec_varids));
1459 NC_CHECK(copy_data(igrp, ogrp));
1474 double_with_suffix(
char *str) {
1478 dval = strtod(str, &suffix);
1479 if(dval < 0 || errno != 0)
1509 [-k n] specify kind of netCDF format for output file, default same as input\n\
1510 1 classic, 2 64-bit offset, 3 netCDF-4, 4 netCDF-4 classic model\n\
1511 [-d n] set deflation compression level, default same as input (0=none 9=max)\n\
1512 [-s] add shuffle option to deflation compression\n\
1513 [-c chunkspec] specify chunking for dimensions, e.g. \"dim1/N1,dim2/N2,...\"\n\
1514 [-u] convert unlimited dimensions to fixed-size dimensions in output copy\n\
1515 [-w] write whole output file from diskless netCDF on close\n\
1516 [-v var1,...] include data for only listed variables, but definitions for all variables\n\
1517 [-V var1,...] include definitions and data for only listed variables\n\
1518 [-g grp1,...] include data for only variables in listed groups, but all definitions\n\
1519 [-G grp1,...] include definitions and data only for variables in listed groups\n\
1520 [-m n] set size in bytes of copy buffer, default is 5000000 bytes\n\
1521 [-h n] set size in bytes of chunk_cache for chunked variables\n\
1522 [-e n] set number of elements that chunk_cache can hold\n\
1523 [-r] read whole input file into diskless file on open (classic or 64-bit offset format only)\n\
1524 infile name of netCDF input file\n\
1525 outfile name for netCDF output file\n"
1530 error(
"%s [-k n] [-d n] [-s] [-c chunkspec] [-u] [-w] [-[v|V] varlist] [-[g|G] grplist] [-m n] [-h n] [-e n] [-r] infile outfile\n%s",
1837 main(
int argc,
char**argv)
1839 char* inputfile = NULL;
1840 char* outputfile = NULL;
1882 while ((c = getopt(argc, argv,
"k:d:sum:c:h:e:rwxg:G:v:V:")) != -1) {
1898 struct Kvalues* kvalue;
1899 char *kind_name = (
char *) emalloc(strlen(optarg)+1);
1900 (void)strcpy(kind_name, optarg);
1901 for(kvalue=legalkinds;kvalue->name;kvalue++) {
1902 if(strcmp(kind_name,kvalue->name) == 0) {
1903 option_kind = kvalue->kind;
1907 if(kvalue->name == NULL) {
1908 error(
"invalid format: %s", kind_name);
1913 option_deflate_level = strtol(optarg, NULL, 10);
1914 if(option_deflate_level < 0 || option_deflate_level > 9) {
1915 error(
"invalid deflation level: %d", option_deflate_level);
1922 option_fix_unlimdims = 1;
1926 double dval = double_with_suffix(optarg);
1928 error(
"Suffix used for '-m' option value must be K, M, G, T, or P");
1929 option_copy_buffer_size = dval;
1934 double dval = double_with_suffix(optarg);
1936 error(
"Suffix used for '-h' option value must be K, M, G, T, or P");
1937 option_chunk_cache_size = dval;
1942 double dval = double_with_suffix(optarg);
1944 error(
"Suffix used for '-e' option value must be K, M, G, T, or P");
1945 option_chunk_cache_nelems = (long)dval;
1949 option_read_diskless = 1;
1952 option_write_diskless = 1;
1955 option_compute_chunkcaches = 1;
1959 option_chunkspec = strdup(optarg);
1963 make_lgrps (optarg, &option_nlgrps, &option_lgrps, &option_grpids);
1964 option_grpstruct =
true;
1968 make_lgrps (optarg, &option_nlgrps, &option_lgrps, &option_grpids);
1969 option_grpstruct =
false;
1973 make_lvars (optarg, &option_nlvars, &option_lvars);
1974 option_varstruct =
true;
1978 make_lvars (optarg, &option_nlvars, &option_lvars);
1979 option_varstruct =
false;
1989 error(
"one input file and one output file required");
1991 inputfile = argv[0];
1992 outputfile = argv[1];
1994 if(strcmp(inputfile, outputfile) == 0) {
1995 error(
"output would overwrite input");
1998 if(copy(inputfile, outputfile) !=
NC_NOERR)