1 /*
2 Copyright 2018, UCAR/Unidata
3 See COPYRIGHT file for copying and redistribution conditions.
4
5 This program tests the fix for a large file bug in versions previous
6 to netCDF-4.1.2 for 32-bit platforms, writing to a variable with
7 more than 1 dimension and more than 2**32 values, where the write
8 starts after the first 2**32 elements.
9
10 Russ Rew
11 */
12
13 #include <nc_tests.h>
14 #include "err_macros.h"
15 #include <netcdf.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19
20 #define FILE_NAME "tst_big_var6.nc"
21
22 /* Test with both classic and 64-bit offset files. If netcdf-4 is
23 * included, test with both netCDF-4 format variants also. */
24 #ifdef USE_NETCDF4
25 #define NUM_FORMATS (4)
26 #else
27 #define NUM_FORMATS (2)
28 #endif
29
30 #define NUMDIMS 4 /* rank of variable in tests */
31 #define DIM0 1
32 #define DIM1 2
33 #define DIM2 5000
34 #define DIM3 1000000 /* DIM2*DIM3 > 2**32 */
35 #define FIRST_VAL 65
36 #define SECOND_VAL 90
37 /*
38 * This program tests the fix for a large file bug in versions
39 * previous to netCDF-4.1.2 for 32-bit platforms, writing to a
40 * variable with more than 1 dimension and more than 2**32 values,
41 * where the write starts after the first 2**32 elements. The bug
42 * applies to record variables with more than 2**32 values per record
43 * as well, but that's not tested here.
44 */
45 static int
test_big_var(const char * testfile)46 test_big_var(const char *testfile)
47 {
48 int ncid, varid, dimids[NUMDIMS];
49 size_t start[NUMDIMS] = {0, 0, 0, 0};
50 size_t count[NUMDIMS] = {1, 1, 1, DIM3};
51 short data[DIM3];
52 int j;
53 int nerrs = 0;
54
55 /* Create a file with one big 4D variable. */
56 if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR;
57 if (nc_set_fill(ncid, NC_NOFILL, NULL)) ERR;
58 if (nc_def_dim(ncid, "dim0", DIM0, &dimids[0])) ERR;
59 if (nc_def_dim(ncid, "dim1", DIM1, &dimids[1])) ERR;
60 if (nc_def_dim(ncid, "dim2", DIM2, &dimids[2])) ERR;
61 if (nc_def_dim(ncid, "dim3", DIM3, &dimids[3])) ERR;
62 if (nc_def_var(ncid, "var", NC_SHORT, NUMDIMS, dimids, &varid)) ERR;
63 if (nc_enddef(ncid)) ERR;
64
65 /* write var(0,0,4294,*) as all FIRST_VAL */
66 start[0] = 0;
67 start[1] = 0;
68 start[2] = 4294;
69 for (j = 0; j < DIM3; j++)
70 data[j] = FIRST_VAL;
71 if (nc_put_vara_short(ncid, varid, start, count, &data[0])) ERR;
72
73 /* write var(0,1,0,*) as all 8588 */
74 start[0] = 0;
75 start[1] = 1;
76 start[2] = 0;
77 for (j = 0; j < DIM3; j++)
78 data[j] = SECOND_VAL;
79 if (nc_put_vara_short(ncid, varid, start, count, &data[0])) ERR;
80
81 /* Read and check var(0,0,4294,*) */
82 start[0] = 0;
83 start[1] = 0;
84 start[2] = 4294;
85 if (nc_get_vara_short(ncid, varid, start, count, &data[0])) ERR;
86 for (j = 0; j < DIM3; j++) {
87 if (data[j] != FIRST_VAL ) {
88 printf("error on start[0..2]: %ld,%ld,%ld j: %d, expected %d got %d\n",
89 start[0], start[1], start[2], j, FIRST_VAL, data[j]);
90 ERR;
91 if(nerrs++ > 1)
92 return nerrs;
93 }
94 }
95 if (nc_close(ncid)) ERR;
96 return NC_NOERR;
97 }
98
99 int
main(int argc,char ** argv)100 main(int argc, char **argv) {
101 int i;
102 char testfile[NC_MAX_NAME + 1];
103
104 printf("\n*** Testing multidimensional variable with more than 2**32 values\n");
105 sprintf(testfile, "%s/%s", TEMP_LARGE, FILE_NAME);
106 for (i = NC_FORMAT_CLASSIC; i <= NUM_FORMATS; i++)
107 {
108 printf("*** testing format %d file with short variable with > 2**32 values...", i);
109 nc_set_default_format(i, NULL);
110 if (test_big_var(testfile)) ERR_RET;
111 (void) remove(testfile);
112 SUMMARIZE_ERR;
113 }
114
115 FINAL_RESULTS;
116 }
117