Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/netcdf-c-4.7.4/libdispatch/dutil.c
Line
Count
Source
1
/*********************************************************************
2
 *   Copyright 2018, UCAR/Unidata
3
 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4
 *********************************************************************/
5
6
#include "config.h"
7
#include <stdlib.h>
8
#include <string.h>
9
#include <stdio.h>
10
#ifdef HAVE_UNISTD_H
11
#include <unistd.h>
12
#endif
13
#ifdef HAVE_SYS_STAT_H
14
#include <sys/stat.h>
15
#endif
16
#ifdef HAVE_FCNTL_H
17
#include <fcntl.h>
18
#endif
19
#ifdef _MSC_VER
20
#include <io.h>
21
#endif
22
#include "netcdf.h"
23
#include "ncuri.h"
24
#include "ncbytes.h"
25
#include "nclist.h"
26
#include "nclog.h"
27
#include "ncwinpath.h"
28
29
extern int mkstemp(char *template);
30
31
#define NC_MAX_PATH 4096
32
33
#define LBRACKET '['
34
#define RBRACKET ']'
35
36
/**************************************************/
37
/**
38
 * Provide a hidden interface to allow utilities
39
 * to check if a given path name is really an ncdap4 url.
40
 * If no, return null, else return basename of the url
41
 * minus any extension.
42
 */
43
44
int
45
NC__testurl(const char* path, char** basenamep)
46
0
{
47
0
    NCURI* uri;
48
0
    int ok = NC_NOERR;
49
0
    if(ncuriparse(path,&uri))
50
0
  ok = NC_EURL;
51
0
    else {
52
0
  char* slash = (uri->path == NULL ? NULL : strrchr(uri->path, '/'));
53
0
  char* dot;
54
0
  if(slash == NULL) slash = (char*)path; else slash++;
55
0
        slash = nulldup(slash);
56
0
        if(slash == NULL)
57
0
            dot = NULL;
58
0
        else
59
0
            dot = strrchr(slash, '.');
60
0
        if(dot != NULL &&  dot != slash) *dot = '\0';
61
0
        if(basenamep)
62
0
            *basenamep=slash;
63
0
        else if(slash)
64
0
            free(slash);
65
0
    }
66
0
    ncurifree(uri);
67
0
    return ok;
68
0
}
69
70
/* Return 1 if this machine is little endian */
71
int
72
NC_isLittleEndian(void)
73
0
{
74
0
    union {
75
0
        unsigned char bytes[SIZEOF_INT];
76
0
  int i;
77
0
    } u;
78
0
    u.i = 1;
79
0
    return (u.bytes[0] == 1 ? 1 : 0);
80
0
}
81
82
char*
83
NC_backslashEscape(const char* s)
84
0
{
85
0
    const char* p;
86
0
    char* q;
87
0
    size_t len;
88
0
    char* escaped = NULL;
89
90
0
    len = strlen(s);
91
0
    escaped = (char*)malloc(1+(2*len)); /* max is everychar is escaped */
92
0
    if(escaped == NULL) return NULL;
93
0
    for(p=s,q=escaped;*p;p++) {
94
0
        char c = *p;
95
0
        switch (c) {
96
0
  case '\\':
97
0
  case '/':
98
0
  case '.':
99
0
  case '@':
100
0
      *q++ = '\\'; *q++ = '\\';
101
0
      break;
102
0
  default: *q++ = c; break;
103
0
        }
104
0
    }
105
0
    *q = '\0';
106
0
    return escaped;
107
0
}
108
109
char*
110
NC_backslashUnescape(const char* esc)
111
0
{
112
0
    size_t len;
113
0
    char* s;
114
0
    const char* p;
115
0
    char* q;
116
117
0
    if(esc == NULL) return NULL;
118
0
    len = strlen(esc);
119
0
    s = (char*)malloc(len+1);
120
0
    if(s == NULL) return NULL;
121
0
    for(p=esc,q=s;*p;) {
122
0
  switch (*p) {
123
0
  case '\\':
124
0
       p++;
125
       /* fall thru */
126
0
  default: *q++ = *p++; break;
127
0
  }
128
0
    }
129
0
    *q = '\0';
130
0
    return s;
131
0
}
132
133
char*
134
NC_entityescape(const char* s)
135
0
{
136
0
    const char* p;
137
0
    char* q;
138
0
    size_t len;
139
0
    char* escaped = NULL;
140
0
    const char* entity;
141
142
0
    len = strlen(s);
143
0
    escaped = (char*)malloc(1+(6*len)); /* 6 = |&apos;| */
144
0
    if(escaped == NULL) return NULL;
145
0
    for(p=s,q=escaped;*p;p++) {
146
0
  char c = *p;
147
0
  switch (c) {
148
0
  case '&':  entity = "&amp;"; break;
149
0
  case '<':  entity = "&lt;"; break;
150
0
  case '>':  entity = "&gt;"; break;
151
0
  case '"':  entity = "&quot;"; break;
152
0
  case '\'': entity = "&apos;"; break;
153
0
  default  : entity = NULL; break;
154
0
  }
155
0
  if(entity == NULL)
156
0
      *q++ = c;
157
0
  else {
158
0
      len = strlen(entity);
159
0
      memcpy(q,entity,len);
160
0
      q+=len;
161
0
  }
162
0
    }
163
0
    *q = '\0';
164
0
    return escaped;
165
0
}
166
167
/**
168
Wrap mktmp and return the generated path,
169
or null if failed.
170
Base is the base file path. XXXXX is appended
171
to allow mktmp add its unique id.
172
Return the generated path.
173
*/
174
175
char*
176
NC_mktmp(const char* base)
177
0
{
178
0
    int fd;
179
0
    char* cvtpath = NULL;
180
0
    char tmp[NC_MAX_PATH];
181
0
#ifdef HAVE_MKSTEMP
182
0
    mode_t mask;
183
0
#endif
184
185
    /* Make sure that this path conversion has been applied */
186
0
    cvtpath = NCpathcvt(base);
187
0
    strncpy(tmp,cvtpath,sizeof(tmp));
188
0
    nullfree(cvtpath);
189
0
  strncat(tmp, "XXXXXX", sizeof(tmp) - strlen(tmp) - 1);
190
191
0
#ifdef HAVE_MKSTEMP
192
    /* Note Potential problem: old versions of this function
193
       leave the file in mode 0666 instead of 0600 */
194
0
    mask=umask(0077);
195
0
    fd = mkstemp(tmp);
196
0
    (void)umask(mask);
197
#else /* !HAVE_MKSTEMP */
198
    {
199
#ifdef HAVE_MKTEMP
200
#ifdef _MSC_VER
201
        /* Use _mktemp_s */
202
  _mktemp_s(tmp,sizeof(tmp)-1);
203
#else /*!_MSC_VER*/
204
        mktemp(tmp);
205
  tmo[sizeof[tmp]-1] = '\0';
206
#endif
207
#else /* !HAVE_MKTEMP */
208
  /* Need to simulate by using some kind of pseudo-random number */
209
  {
210
      int rno = rand();
211
      char spid[7];
212
      if(rno < 0) rno = -rno;
213
            snprintf(spid,sizeof(spid),"%06d",rno);
214
            strncat(tmp,spid,sizeof(tmp) - strlen(tmp) - 1);
215
  }
216
#endif /* HAVE_MKTEMP */
217
#ifdef _MSC_VER
218
        fd=NCopen3(tmp,O_RDWR|O_BINARY|O_CREAT, _S_IREAD|_S_IWRITE);
219
#else
220
        fd=NCopen3(tmp,O_RDWR|O_CREAT|O_EXCL, S_IRWXU);
221
#endif
222
    }
223
#endif /* !HAVE_MKSTEMP */
224
0
    if(fd < 0) {
225
0
       nclog(NCLOGERR, "Could not create temp file: %s",tmp);
226
0
       return NULL;
227
0
    } else
228
0
  close(fd);
229
0
    return strdup(tmp);
230
0
}
231
232
int
233
NC_readfile(const char* filename, NCbytes* content)
234
0
{
235
0
    int ret = NC_NOERR;
236
0
    FILE* stream = NULL;
237
0
    char part[1024];
238
239
#ifdef _WIN32
240
    stream = NCfopen(filename,"rb");
241
#else
242
0
    stream = NCfopen(filename,"r");
243
0
#endif
244
0
    if(stream == NULL) {ret=errno; goto done;}
245
0
    for(;;) {
246
0
  size_t count = fread(part, 1, sizeof(part), stream);
247
0
  if(count <= 0) break;
248
0
  ncbytesappendn(content,part,count);
249
0
  if(ferror(stream)) {ret = NC_EIO; goto done;}
250
0
  if(feof(stream)) break;
251
0
    }
252
0
    ncbytesnull(content);
253
0
done:
254
0
    if(stream) fclose(stream);
255
0
    return ret;
256
0
}
257
258
int
259
NC_writefile(const char* filename, size_t size, void* content)
260
0
{
261
0
    int ret = NC_NOERR;
262
0
    FILE* stream = NULL;
263
0
    void* p;
264
0
    size_t remain;
265
266
#ifdef _WIN32
267
    stream = NCfopen(filename,"wb");
268
#else
269
0
    stream = NCfopen(filename,"w");
270
0
#endif
271
0
    if(stream == NULL) {ret=errno; goto done;}
272
0
    p = content;
273
0
    remain = size;
274
0
    while(remain > 0) {
275
0
  size_t written = fwrite(p, 1, remain, stream);
276
0
  if(ferror(stream)) {ret = NC_EIO; goto done;}
277
0
  if(feof(stream)) break;
278
0
  remain -= written;
279
0
    }
280
0
done:
281
0
    if(stream) fclose(stream);
282
0
    return ret;
283
0
}
284
285
/*
286
Parse a path as a url and extract the modelist.
287
If the path is not a URL, then return a NULL list.
288
If a URL, but modelist is empty or does not exist,
289
then return empty list.
290
*/
291
int
292
NC_getmodelist(const char* path, NClist** modelistp)
293
0
{
294
0
    int stat=NC_NOERR;
295
0
    NClist* modelist = NULL;
296
0
    NCURI* uri = NULL;
297
0
    const char* modestr = NULL;
298
0
    const char* p = NULL;
299
0
    const char* endp = NULL;
300
301
0
    ncuriparse(path,&uri);
302
0
    if(uri == NULL) goto done; /* not a uri */
303
304
    /* Get the mode= arg from the fragment */
305
0
    modelist = nclistnew();    
306
0
    modestr = ncurilookup(uri,"mode");
307
0
    if(modestr == NULL || strlen(modestr) == 0) goto done;
308
    /* Parse the mode string at the commas or EOL */
309
0
    p = modestr;
310
0
    for(;;) {
311
0
  char* s;
312
0
  ptrdiff_t slen;
313
0
  endp = strchr(p,',');
314
0
  if(endp == NULL) endp = p + strlen(p);
315
0
  slen = (endp - p);
316
0
  if((s = malloc(slen+1)) == NULL) {stat = NC_ENOMEM; goto done;}
317
0
  memcpy(s,p,slen);
318
0
  s[slen] = '\0';
319
0
  nclistpush(modelist,s);
320
0
  if(*endp == '\0') break;
321
0
  p = endp+1;
322
0
    }
323
324
0
done:
325
0
    if(stat == NC_NOERR) {
326
0
  if(modelistp) {*modelistp = modelist; modelist = NULL;}
327
0
    }
328
0
    ncurifree(uri);
329
0
    nclistfree(modelist);
330
0
    return stat;
331
0
}
332
333
/*
334
Check "mode=" list for a path and return 1 if present, 0 otherwise.
335
*/
336
int
337
NC_testmode(const char* path, const char* tag)
338
0
{
339
0
    int stat = NC_NOERR;
340
0
    int found = 0;
341
0
    int i;
342
0
    NClist* modelist = NULL;
343
344
0
    if((stat = NC_getmodelist(path, &modelist))) goto done;
345
0
    for(i=0;i<nclistlength(modelist);i++) {
346
0
  const char* value = nclistget(modelist,i);
347
0
  if(strcasecmp(tag,value)==0) {found = 1; break;}
348
0
    }        
349
    
350
0
done:
351
0
    nclistfreeall(modelist);
352
0
    return found;
353
0
}