2018-12-07 05:56:42 +08:00
|
|
|
/*! \file
|
|
|
|
|
|
|
|
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
|
|
|
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
|
|
|
|
2015, 2016, 2017, 2018
|
|
|
|
University Corporation for Atmospheric Research/Unidata.
|
|
|
|
|
|
|
|
See \ref copyright file for more info.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2018-10-11 03:32:17 +08:00
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#ifdef HAVE_TIME_H
|
|
|
|
#include <time.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
#include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include "unistd.h"
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
2018-10-12 02:09:42 +08:00
|
|
|
#include <Windows.h>
|
2018-10-11 03:32:17 +08:00
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "netcdf.h"
|
2022-02-09 11:53:30 +08:00
|
|
|
#include "ncpathmgr.h"
|
2018-10-11 03:32:17 +08:00
|
|
|
|
|
|
|
#define CLEANUP
|
|
|
|
|
|
|
|
#ifndef NC_NETCDF3
|
|
|
|
#define NC_NETCDF3 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define FILE3D "file3d.nc"
|
|
|
|
#define FILE3DP "file3dp.nc"
|
|
|
|
#define FILE4D "file4d.nc"
|
|
|
|
#define FILE4DP "file4dp.nc"
|
|
|
|
|
2018-10-12 02:09:42 +08:00
|
|
|
/* Mnemonics */
|
|
|
|
#define RDONLY 1
|
|
|
|
#define RDWRITE 0
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#define RDONLYMODE (_S_IREAD)
|
|
|
|
#define RDWRMODE (_S_IREAD|_S_IWRITE)
|
|
|
|
#define CHMOD _chmod
|
|
|
|
#define SLEEP(x) Sleep((x)*1000)
|
|
|
|
#else
|
|
|
|
#define RDONLYMODE (S_IRUSR|S_IRGRP|S_IROTH)
|
|
|
|
#define RDWRMODE (RDONLY | S_IWUSR)
|
|
|
|
#define CHMOD chmod
|
|
|
|
#define SLEEP(x) sleep(x)
|
|
|
|
#endif
|
|
|
|
|
2018-10-11 03:32:17 +08:00
|
|
|
typedef enum OC { OPEN, CLOSE} OC;
|
|
|
|
|
|
|
|
static int lineno = 0;
|
|
|
|
|
|
|
|
static char*
|
|
|
|
smode(int mode)
|
|
|
|
{
|
|
|
|
static char ms[8192];
|
|
|
|
ms[0] = '\0';
|
|
|
|
if(mode & NC_NETCDF4)
|
|
|
|
strcat(ms,"NC_NETCDF4");
|
|
|
|
else
|
|
|
|
strcat(ms,"NC_NETCDF3");
|
|
|
|
if(mode & NC_DISKLESS)
|
|
|
|
strcat(ms,"|NC_DISKLESS");
|
|
|
|
if(mode & NC_WRITE)
|
|
|
|
strcat(ms,"|NC_WRITE");
|
|
|
|
if(mode & NC_NOCLOBBER)
|
|
|
|
strcat(ms,"|NC_NOCLOBBER");
|
|
|
|
if(mode & NC_INMEMORY)
|
|
|
|
strcat(ms,"|NC_INMEMORY");
|
|
|
|
if(mode & NC_PERSIST)
|
|
|
|
strcat(ms,"|NC_PERSIST");
|
|
|
|
if(mode & NC_MMAP)
|
|
|
|
strcat(ms,"|NC_MMAP");
|
|
|
|
return ms;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return 1 if file was changed else 0 */
|
|
|
|
static time_t
|
|
|
|
getmodified(const char* path)
|
|
|
|
{
|
|
|
|
struct stat attr;
|
|
|
|
stat(path, &attr);
|
|
|
|
return attr.st_mtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-10-12 02:09:42 +08:00
|
|
|
changeaccess(int rdonly)
|
2018-10-11 03:32:17 +08:00
|
|
|
{
|
2018-10-12 02:09:42 +08:00
|
|
|
const char* p3 = FILE3DP; /* Keep Visual Studio happy */
|
|
|
|
const char* p4 = FILE4DP;
|
|
|
|
int mode = (rdonly?RDONLYMODE:RDWRMODE);
|
|
|
|
(void)CHMOD(p3,mode);
|
|
|
|
(void)CHMOD(p4,mode);
|
2018-10-11 03:32:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cleanup()
|
|
|
|
{
|
|
|
|
changeaccess(RDWRITE);
|
|
|
|
/* cleanup */
|
|
|
|
(void)unlink(FILE3DP);
|
|
|
|
(void)unlink(FILE4DP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fail(int ret)
|
|
|
|
{
|
|
|
|
if(ret != NC_NOERR) {
|
|
|
|
fprintf(stderr,"*** Fail: line: %d: (%d) %s\n", lineno, ret, nc_strerror(ret));
|
|
|
|
fflush(stderr);
|
|
|
|
#ifdef CLEANUP
|
|
|
|
cleanup();
|
|
|
|
#endif
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
exists(const char* file)
|
|
|
|
{
|
2022-02-09 11:53:30 +08:00
|
|
|
FILE* f = NCfopen(file, "r");
|
2018-10-11 03:32:17 +08:00
|
|
|
if(f == NULL) fail(NC_EPERM);
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
notexists(const char* file)
|
|
|
|
{
|
2022-02-09 11:53:30 +08:00
|
|
|
FILE* f = NCfopen(file,"r");
|
2018-10-11 03:32:17 +08:00
|
|
|
if(f != NULL) {fclose(f); fail(NC_EEXIST);}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TESTCREATE(file,mode,exist) {lineno=__LINE__; testcreate(file,mode,exist);}
|
|
|
|
#define TESTOPEN(file,mode,rw) {lineno=__LINE__; testopen(file,mode,rw);}
|
|
|
|
|
|
|
|
static void
|
|
|
|
testcreate(const char* file, int mode, int mustexist)
|
|
|
|
{
|
|
|
|
int ret = NC_NOERR;
|
|
|
|
int ncid, dimid;
|
|
|
|
|
|
|
|
printf("test: file=%s mode=%s\n",file,smode(mode)); fflush(stdout);
|
|
|
|
|
|
|
|
if((ret = nc_create(file,mode,&ncid))) fail(ret);
|
|
|
|
if((ret = nc_def_dim(ncid,"dim",5,&dimid))) fail(ret);
|
|
|
|
if((ret = nc_close(ncid))) fail(ret);
|
|
|
|
if(mustexist)
|
|
|
|
exists(file);
|
|
|
|
else
|
|
|
|
notexists(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
testopen(const char* file, int mode, int rdwrite)
|
|
|
|
{
|
|
|
|
int ret = NC_NOERR;
|
|
|
|
int ncid, dimid;
|
|
|
|
size_t len;
|
|
|
|
time_t time1, time2;
|
|
|
|
|
|
|
|
printf("test: file=%s mode=%s\n",file,smode(mode)); fflush(stdout);
|
|
|
|
|
|
|
|
time1 = getmodified(file);
|
2018-10-12 02:09:42 +08:00
|
|
|
SLEEP(1); /* Ensure that if modified, it will be reported */
|
2018-10-11 03:32:17 +08:00
|
|
|
if((ret = nc_open(file,mode,&ncid))) fail(ret);
|
|
|
|
if(rdwrite) {
|
|
|
|
/* Modify */
|
|
|
|
if((ret=nc_redef(ncid))) fail(ret);
|
|
|
|
/* See if dim2 is already defined */
|
|
|
|
ret = nc_inq_dimid(ncid,"dim2",&dimid);
|
|
|
|
if(ret == NC_NOERR) {/* defined */
|
|
|
|
if((ret = nc_def_dim(ncid,"dim3",3,&dimid))) fail(ret);
|
|
|
|
} else if(ret == NC_EBADDIM) { /* not defined */
|
|
|
|
if((ret = nc_def_dim(ncid,"dim2",2,&dimid))) fail(ret);
|
|
|
|
} else
|
|
|
|
fail(ret);
|
|
|
|
if((ret=nc_enddef(ncid))) fail(ret);
|
|
|
|
}
|
|
|
|
if((ret = nc_inq_dimid(ncid,"dim",&dimid))) fail(ret);
|
|
|
|
if((ret = nc_inq_dimlen(ncid,dimid,&len))) fail(ret);
|
|
|
|
ret = nc_close(ncid);
|
|
|
|
if(ret != NC_NOERR && rdwrite) fail(ret);
|
|
|
|
else if(ret == NC_NOERR && !rdwrite) fail(NC_EINVAL);
|
|
|
|
time2 = getmodified(file);
|
|
|
|
if(!rdwrite) {
|
|
|
|
if(time2 != time1) {
|
|
|
|
fprintf(stderr,"file modified: %s\n",file);
|
|
|
|
fail(NC_EACCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main()
|
|
|
|
{
|
|
|
|
changeaccess(RDWRITE);
|
|
|
|
cleanup();
|
|
|
|
|
|
|
|
/* Test various mode combinations */
|
|
|
|
|
|
|
|
/* Create and persist some files using diskless */
|
|
|
|
printf("*** Test create\n"); fflush(stdout);
|
|
|
|
TESTCREATE(FILE3D,NC_NETCDF3|NC_DISKLESS,0); /* Not persisted */
|
|
|
|
TESTCREATE(FILE3DP,NC_NETCDF3|NC_DISKLESS|NC_PERSIST,1); /* persisted */
|
|
|
|
TESTCREATE(FILE4D,NC_NETCDF4|NC_DISKLESS,0); /* Not persisted */
|
|
|
|
TESTCREATE(FILE4DP,NC_NETCDF4|NC_DISKLESS|NC_PERSIST,1); /* persisted */
|
|
|
|
|
|
|
|
/* Of the above persisted files, re-read and modify and re-persist */
|
|
|
|
printf("*** Test open + modify + rdwrite\n"); fflush(stdout);
|
|
|
|
TESTOPEN(FILE3DP,NC_NETCDF3|NC_DISKLESS|NC_PERSIST|NC_WRITE,1); /* re-persist */
|
|
|
|
TESTOPEN(FILE4DP,NC_NETCDF4|NC_DISKLESS|NC_PERSIST|NC_WRITE,1); /* re-persist */
|
|
|
|
|
|
|
|
/* Of the above modified files, re-read and modify but do not re-persist */
|
|
|
|
/* Test open + modify + rdonly; requires NC_DISKLESS*/
|
|
|
|
#if 0
|
2018-12-07 05:56:42 +08:00
|
|
|
/* Fails with hdf5, file must be writeable even if not persisted */
|
2018-10-11 03:32:17 +08:00
|
|
|
changeaccess(RDONLY); /* prevent re-persist */
|
|
|
|
#endif
|
|
|
|
printf("*** Testopen modify + rdonly\n"); fflush(stdout);
|
|
|
|
TESTOPEN(FILE3DP,NC_NETCDF3|NC_DISKLESS|NC_WRITE,1);
|
|
|
|
TESTOPEN(FILE4DP,NC_NETCDF4|NC_DISKLESS|NC_WRITE,1);
|
|
|
|
|
|
|
|
#ifdef CLEANUP
|
|
|
|
cleanup();
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|