netCDF  4.3.0
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
dfile.c
Go to the documentation of this file.
1 
11 #include "config.h"
12 #include <stdlib.h>
13 #ifdef HAVE_SYS_RESOURCE_H
14 #include <sys/resource.h>
15 #endif
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
18 #endif
19 #ifdef HAVE_SYS_STAT_H
20 #include <sys/stat.h>
21 #endif
22 #ifdef HAVE_FCNTL_H
23 #include <fcntl.h>
24 #endif
25 #include "ncdispatch.h"
26 
27 static int nc_initialized = 0;
28 
66 size_t* NC_coord_zero;
67 size_t* NC_coord_one;
68 
69 static void
70 nc_local_initialize(void)
71 {
72  int i;
73  NC_coord_zero = (size_t*)malloc(sizeof(size_t)*NC_MAX_VAR_DIMS);
74  if(NC_coord_zero == NULL) abort();
75  NC_coord_one = (size_t*)malloc(sizeof(size_t)*NC_MAX_VAR_DIMS);
76  if(NC_coord_one == NULL) abort();
77  for(i=0;i<NC_MAX_VAR_DIMS;i++) {
78  NC_coord_one[i] = 1;
79  NC_coord_zero[i] = 0;
80  }
81 }
82 
83 static int
84 NC_check_file_type(const char *path, int use_parallel, void *mpi_info,
85  int *cdf, int *hdf)
86 {
87  char magic[MAGIC_NUMBER_LEN];
88 
89  *hdf = 0; *cdf = 0;
90 
91  /* Get the 4-byte magic from the beginning of the file. Don't use posix
92  * for parallel, use the MPI functions instead. */
93 #ifdef USE_PARALLEL_MPIO
94 /* Note that this assumes netcdf-4 support is enabled */
95  if (use_parallel)
96  {
97  MPI_File fh;
98  MPI_Status status;
99  int retval;
100  MPI_Comm comm = 0;
101  MPI_Info info = 0;
102 
103  if(mpi_info != NULL) {
104  comm = ((NC_MPI_INFO*)mpi_info)->comm;
105  info = ((NC_MPI_INFO*)mpi_info)->info;
106  }
107  if((retval = MPI_File_open(comm, (char *)path, MPI_MODE_RDONLY,info,
108  &fh)) != MPI_SUCCESS)
109  return NC_EPARINIT;
110  if((retval = MPI_File_read(fh, magic, MAGIC_NUMBER_LEN, MPI_CHAR,
111  &status)) != MPI_SUCCESS)
112  return NC_EPARINIT;
113  if((retval = MPI_File_close(&fh)) != MPI_SUCCESS)
114  return NC_EPARINIT;
115  /* Pretend this is an HDF5 file */
116  *hdf = 5;
117  } else
118 #endif /* USE_PARALLEL */
119  {
120  FILE *fp;
121  int i;
122 #ifdef HAVE_SYS_STAT_H
123  struct stat st;
124 #endif
125 
126  if(path == NULL || strlen(path)==0)
127  return NC_EINVAL;
128 
129  if (!(fp = fopen(path, "r")))
130  return errno;
131 
132 #ifdef HAVE_SYS_STAT_H
133  /* The file must be at least MAGIC_NUMBER_LEN in size,
134  or otherwise the following fread will exhibit unexpected
135  behavior. */
136  if(!(fstat(fileno(fp),&st) == 0))
137  return errno;
138 
139  if(st.st_size < MAGIC_NUMBER_LEN)
140  return NC_ENOTNC;
141 #endif
142 
143 
144  i = fread(magic, MAGIC_NUMBER_LEN, 1, fp);
145  fclose(fp);
146  if(i == 0)
147  return NC_ENOTNC;
148  if(i != 1)
149  return errno;
150 
151  /* Ignore the first byte for HDF */
152  if(magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
153  *hdf = 5;
154  else if(magic[0] == '\016' && magic[1] == '\003'
155  && magic[2] == '\023' && magic[3] == '\001')
156  *hdf = 4;
157  else if(magic[0] == 'C' && magic[1] == 'D' && magic[2] == 'F')
158  {
159  if(magic[3] == '\001')
160  *cdf = 1; /* netcdf classic version 1 */
161  else if(magic[3] == '\002')
162  *cdf = 2; /* netcdf classic version 2 */
163  else
164  return NC_ENOTNC;
165  } else
166  return NC_ENOTNC;
167  }
168  return NC_NOERR;
169 }
170 
367 int
368 nc_create(const char *path, int cmode, int *ncidp)
369 {
370  return nc__create(path,cmode,NC_SIZEHINT_DEFAULT,NULL,ncidp);
371 }
372 
434 int
435 nc__create(const char *path, int cmode, size_t initialsz,
436  size_t *chunksizehintp, int *ncidp)
437 {
438  return NC_create(path, cmode, initialsz, 0,
439  chunksizehintp, 0, NULL, ncidp);
440 
441 }
450 int
451 nc__create_mp(const char *path, int cmode, size_t initialsz,
452  int basepe, size_t *chunksizehintp, int *ncidp)
453 {
454  return NC_create(path, cmode, initialsz, basepe,
455  chunksizehintp, 0, NULL, ncidp);
456 }
457 
569 int
570 nc_open(const char *path, int mode, int *ncidp)
571 {
572  return NC_open(path, mode, 0, NULL, 0, NULL, ncidp);
573 }
574 
626 int
627 nc__open(const char *path, int mode,
628  size_t *chunksizehintp, int *ncidp)
629 {
630  return NC_open(path, mode, 0, chunksizehintp, 0,
631  NULL, ncidp);
632 }
633 
642 int
643 nc__open_mp(const char *path, int mode, int basepe,
644  size_t *chunksizehintp, int *ncidp)
645 {
646  return NC_open(path, mode, basepe, chunksizehintp,
647  0, NULL, ncidp);
648 }
649 
667 int
668 nc_inq_path(int ncid, size_t *pathlen, char *path)
669 {
670  NC* ncp;
671  int stat = NC_NOERR;
672  if ((stat = NC_check_id(ncid, &ncp)))
673  return stat;
674  if(ncp->path == NULL) {
675  if(pathlen) *pathlen = 0;
676  if(path) path[0] = '\0';
677  } else {
678  if (pathlen) *pathlen = strlen(ncp->path);
679  if (path) strcpy(path, ncp->path);
680  }
681  return stat;
682 }
683 
732 int
733 nc_redef(int ncid)
734 {
735  NC* ncp;
736  int stat = NC_check_id(ncid, &ncp);
737  if(stat != NC_NOERR) return stat;
738  return ncp->dispatch->redef(ncid);
739 }
740 
796 int
797 nc_enddef(int ncid)
798 {
799  int status = NC_NOERR;
800  NC *ncp;
801  status = NC_check_id(ncid, &ncp);
802  if(status != NC_NOERR) return status;
803  return ncp->dispatch->_enddef(ncid,0,1,0,1);
804 }
805 
887 int
888 nc__enddef(int ncid, size_t h_minfree, size_t v_align, size_t v_minfree,
889  size_t r_align)
890 {
891  NC* ncp;
892  int stat = NC_check_id(ncid, &ncp);
893  if(stat != NC_NOERR) return stat;
894  return ncp->dispatch->_enddef(ncid,h_minfree,v_align,v_minfree,r_align);
895 }
896 
964 int
965 nc_sync(int ncid)
966 {
967  NC* ncp;
968  int stat = NC_check_id(ncid, &ncp);
969  if(stat != NC_NOERR) return stat;
970  return ncp->dispatch->sync(ncid);
971 }
972 
1015 int
1016 nc_abort(int ncid)
1017 {
1018  NC* ncp;
1019  int stat = NC_check_id(ncid, &ncp);
1020  if(stat != NC_NOERR) return stat;
1021  stat = ncp->dispatch->abort(ncid);
1022  del_from_NCList(ncp);
1023  free_NC(ncp);
1024  return stat;
1025 }
1026 
1067 int
1068 nc_close(int ncid)
1069 {
1070  NC* ncp;
1071  int stat = NC_check_id(ncid, &ncp);
1072  if(stat != NC_NOERR) return stat;
1073  stat = ncp->dispatch->close(ncid);
1074  /* Remove from the nc list */
1075  del_from_NCList(ncp);
1076  free_NC(ncp);
1077  return stat;
1078 }
1079 
1178 int
1179 nc_set_fill(int ncid, int fillmode, int *old_modep)
1180 {
1181  NC* ncp;
1182  int stat = NC_check_id(ncid, &ncp);
1183  if(stat != NC_NOERR) return stat;
1184  return ncp->dispatch->set_fill(ncid,fillmode,old_modep);
1185 }
1186 
1198 int
1199 nc_inq_base_pe(int ncid, int *pe)
1200 {
1201  NC* ncp;
1202  int stat = NC_check_id(ncid, &ncp);
1203  if(stat != NC_NOERR) return stat;
1204  return ncp->dispatch->inq_base_pe(ncid,pe);
1205 }
1206 
1218 int
1219 nc_set_base_pe(int ncid, int pe)
1220 {
1221  NC* ncp;
1222  int stat = NC_check_id(ncid, &ncp);
1223  if(stat != NC_NOERR) return stat;
1224  return ncp->dispatch->set_base_pe(ncid,pe);
1225 }
1226 
1244 int
1245 nc_inq_format(int ncid, int *formatp)
1246 {
1247  NC* ncp;
1248  int stat = NC_check_id(ncid, &ncp);
1249  if(stat != NC_NOERR) return stat;
1250  return ncp->dispatch->inq_format(ncid,formatp);
1251 }
1252 
1297 int
1298 nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
1299 {
1300  NC* ncp;
1301  int stat = NC_check_id(ncid, &ncp);
1302  if(stat != NC_NOERR) return stat;
1303  return ncp->dispatch->inq(ncid,ndimsp,nvarsp,nattsp,unlimdimidp);
1304 }
1305 
1306 int
1307 nc_inq_nvars(int ncid, int *nvarsp)
1308 {
1309  NC* ncp;
1310  int stat = NC_check_id(ncid, &ncp);
1311  if(stat != NC_NOERR) return stat;
1312  return ncp->dispatch->inq(ncid, NULL, nvarsp, NULL, NULL);
1313 }
1314 
1380 int
1381 nc_inq_type(int ncid, nc_type xtype, char *name, size_t *size)
1382 {
1383  NC* ncp;
1384  /* For compatibility, we need to allow inq about
1385  atomic types, even if ncid is ill-defined */
1386  if(xtype <= ATOMICTYPEMAX) {
1387  if(xtype <= NC_NAT) return NC_EBADTYPE;
1388  if(name) strncpy(name,NC_atomictypename(xtype),NC_MAX_NAME);
1389  if(size) *size = NC_atomictypelen(xtype);
1390  return NC_NOERR;
1391  } else {
1392  int stat = NC_check_id(ncid, &ncp);
1393  if(stat != NC_NOERR) return NC_EBADTYPE; /* compatibility */
1394  return ncp->dispatch->inq_type(ncid,xtype,name,size);
1395  }
1396 }
1433 int
1434 NC_create(const char *path, int cmode, size_t initialsz,
1435  int basepe, size_t *chunksizehintp, int useparallel,
1436  void* mpi_info, int *ncidp)
1437 {
1438  int stat = NC_NOERR;
1439  NC* ncp = NULL;
1440  NC_Dispatch* dispatcher = NULL;
1441  /* Need three pieces of information for now */
1442  int model = 0; /* one of the NC_DISPATCH_XXX values */
1443  int isurl = 0; /* dap or cdmremote or neither */
1444  int xcmode = 0; /* for implied cmode flags */
1445 
1446  /* Initialize the dispatch table. The function pointers in the
1447  * dispatch table will depend on how netCDF was built
1448  * (with/without netCDF-4, DAP, CDMREMOTE). */
1449  if(!nc_initialized)
1450  {
1451  if ((stat = NC_initialize()))
1452  return stat;
1453  /* Do local initialization */
1454  nc_local_initialize();
1455  nc_initialized = 1;
1456  }
1457 
1458  if((isurl = NC_testurl(path)))
1459  model = NC_urlmodel(path);
1460 
1461  /* Look to the incoming cmode for hints */
1462  if(model == 0) {
1463  if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF)
1464  model = NC_DISPATCH_NC4;
1465  else if(cmode & NC_CLASSIC_MODEL)
1466  model = NC_DISPATCH_NC3;
1467  }
1468 
1469  if(model == 0) {
1470  /* Check default format */
1471  int format = nc_get_default_format();
1472  switch (format) {
1473 #ifdef USE_NETCDF4
1474  case NC_FORMAT_NETCDF4:
1475  xcmode |= NC_NETCDF4;
1476  model = NC_DISPATCH_NC4;
1477  break;
1479  xcmode |= NC_CLASSIC_MODEL;
1480  model = NC_DISPATCH_NC4;
1481  break;
1482 #endif
1483  case NC_FORMAT_64BIT:
1484  xcmode |= NC_64BIT_OFFSET;
1485  /* fall thru */
1486  case NC_FORMAT_CLASSIC:
1487  default:
1488  model = NC_DISPATCH_NC3;
1489  break;
1490  }
1491  }
1492 
1493  /* Add inferred flags */
1494  cmode |= xcmode;
1495 
1496 #ifdef USE_NETCDF4
1497  if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
1498  return NC_EINVAL;
1499 #endif
1500 
1501  if (!(dispatcher = NC_get_dispatch_override()))
1502  {
1503 
1504  /* Figure out what dispatcher to use */
1505 #ifdef USE_NETCDF4
1506 #ifdef USE_CDMREMOTE
1507  if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
1508  dispatcher = NCCR_dispatch_table;
1509  else
1510 #endif
1511  if(model == (NC_DISPATCH_NC4))
1512  dispatcher = NC4_dispatch_table;
1513  else
1514 #endif /*USE_NETCDF4*/
1515 #ifdef USE_DAP
1516  if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
1517  dispatcher = NCD3_dispatch_table;
1518  else
1519 #endif
1520  if(model == (NC_DISPATCH_NC3))
1521  dispatcher = NC3_dispatch_table;
1522  else
1523  return NC_ENOTNC;
1524  }
1525 
1526  /* Create the NC* instance and insert its dispatcher */
1527  stat = new_NC(dispatcher,path,&ncp);
1528  if(stat) return stat;
1529 
1530  /* Add to list of known open files and define ext_ncid */
1531  add_to_NCList(ncp);
1532 
1533  /* Assume create will fill in remaining ncp fields */
1534  if ((stat = dispatcher->create(path, cmode, initialsz, basepe, chunksizehintp,
1535  useparallel, mpi_info, dispatcher, ncp))) {
1536  del_from_NCList(ncp); /* oh well */
1537  free_NC(ncp);
1538  } else {
1539  if(ncidp)*ncidp = ncp->ext_ncid;
1540  }
1541  return stat;
1542 }
1543 
1559 int
1560 NC_open(const char *path, int cmode,
1561  int basepe, size_t *chunksizehintp,
1562  int useparallel, void* mpi_info,
1563  int *ncidp)
1564 {
1565  int stat = NC_NOERR;
1566  NC* ncp = NULL;
1567  NC_Dispatch* dispatcher = NULL;
1568  /* Need two pieces of information for now */
1569  int model = 0;
1570  int isurl = 0;
1571  int cdfversion = 0;
1572  int hdfversion = 0;
1573 
1574  if(!nc_initialized) {
1575  stat = NC_initialize();
1576  if(stat) return stat;
1577  /* Do local initialization */
1578  nc_local_initialize();
1579  nc_initialized = 1;
1580  }
1581 
1582  isurl = NC_testurl(path);
1583  if(isurl)
1584  model = NC_urlmodel(path);
1585 
1586  if(!isurl) {
1587  /* Look at the file if it exists */
1588  stat = NC_check_file_type(path,useparallel,mpi_info,&cdfversion,&hdfversion);
1589  if(stat == NC_NOERR) {
1590  if(hdfversion != 0) {
1591  model = NC_DISPATCH_NC4;
1592  } else if(cdfversion != 0) {
1593  model = NC_DISPATCH_NC3;
1594  }
1595  } else /* presumably not a netcdf file */
1596  return stat;
1597  }
1598 
1599  /* Look to the incoming cmode for hints */
1600  if(model == 0) {
1601  if(cmode & NC_NETCDF4 || cmode & NC_PNETCDF) model |= NC_DISPATCH_NC4;
1602  }
1603 
1604  if(model == 0) model = NC_DISPATCH_NC3; /* final default */
1605 
1606  /* Force flag consistentcy */
1607  if(model & NC_DISPATCH_NC4)
1608  cmode |= NC_NETCDF4;
1609  else if(model & NC_DISPATCH_NC3) {
1610  cmode &= ~NC_NETCDF4; /* must be netcdf-3 */
1611  if(cdfversion == 2) cmode |= NC_64BIT_OFFSET;
1612  }
1613 
1614  if((cmode & NC_MPIIO && cmode & NC_MPIPOSIX))
1615  return NC_EINVAL;
1616 
1617  /* override overrides any other table choice */
1618  dispatcher = NC_get_dispatch_override();
1619  if(dispatcher != NULL) goto havetable;
1620 
1621  /* Figure out what dispatcher to use */
1622 #if defined(USE_CDMREMOTE)
1623  if(model == (NC_DISPATCH_NC4 | NC_DISPATCH_NCR))
1624  dispatcher = NCCR_dispatch_table;
1625  else
1626 #endif
1627 #if defined(USE_DAP)
1628  if(model == (NC_DISPATCH_NC3 | NC_DISPATCH_NCD))
1629  dispatcher = NCD3_dispatch_table;
1630  else
1631 #endif
1632 #if defined(USE_NETCDF4)
1633  if(model == (NC_DISPATCH_NC4))
1634  dispatcher = NC4_dispatch_table;
1635  else
1636 #endif
1637  if(model == (NC_DISPATCH_NC3))
1638  dispatcher = NC3_dispatch_table;
1639  else
1640  return NC_ENOTNC;
1641 
1642 havetable:
1643 
1644  /* Create the NC* instance and insert its dispatcher */
1645  stat = new_NC(dispatcher,path,&ncp);
1646  if(stat) return stat;
1647 
1648  /* Add to list of known open files */
1649  add_to_NCList(ncp);
1650 
1651  /* Assume open will fill in remaining ncp fields */
1652  stat = dispatcher->open(path, cmode, basepe, chunksizehintp,
1653  useparallel, mpi_info, dispatcher, ncp);
1654  if(stat == NC_NOERR) {
1655  if(ncidp) *ncidp = ncp->ext_ncid;
1656  } else {
1657  del_from_NCList(ncp);
1658  free_NC(ncp);
1659  }
1660  return stat;
1661 }
1662 
1663 /*Provide an internal function for generating pseudo file descriptors
1664  for systems that are not file based (e.g. dap, memio).
1665 */
1666 
1667 /* Static counter for pseudo file descriptors (incremented) */
1668 static int pseudofd = 0;
1669 
1670 /* Create a pseudo file descriptor that does not
1671  overlap real file descriptors
1672 */
1673 int
1674 nc__pseudofd(void)
1675 {
1676  if(pseudofd == 0) {
1677  int maxfd = 32767; /* default */
1678 #ifdef HAVE_GETRLIMIT
1679  struct rlimit rl;
1680  if(getrlimit(RLIMIT_NOFILE,&rl) == 0) {
1681  if(rl.rlim_max != RLIM_INFINITY)
1682  maxfd = rl.rlim_max;
1683  if(rl.rlim_cur != RLIM_INFINITY)
1684  maxfd = rl.rlim_cur;
1685  }
1686  pseudofd = maxfd+1;
1687 #endif
1688  }
1689 
1690  return pseudofd++;
1691 }
1692 
1693 

Generated on Tue Jul 9 2013 19:18:10 for netCDF. NetCDF is a Unidata library.