Coverage Report

Created: 2025-06-09 07:42

/src/gdal/netcdf-c-4.7.4/libdispatch/dwinpath.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2018, University Corporation for Atmospheric Research
3
 * See netcdf/COPYRIGHT file for copying and redistribution conditions.
4
 */
5
6
#include "config.h"
7
#include <stdlib.h>
8
#include <stdio.h>
9
#include <string.h>
10
#include <assert.h>
11
#include <errno.h>
12
#ifdef HAVE_FCNTL_H
13
#include <fcntl.h>
14
#endif
15
#ifdef HAVE_UNISTD_H
16
#include <unistd.h>
17
#endif
18
#ifdef _MSC_VER
19
#include <io.h>
20
#endif
21
22
#include "ncexternl.h"
23
#include "ncwinpath.h"
24
25
extern char *realpath(const char *path, char *resolved_path);
26
27
#undef PATHFORMAT
28
29
/*
30
Code to provide some path conversion code so that
31
cygwin and (some) mingw paths can be passed to open/fopen
32
for Windows. Other cases will be added as needed.
33
Rules:
34
1. a leading single alpha-character path element (e.g. /D/...)
35
   will be interpreted as a windows drive letter.
36
2. a leading '/cygdrive/X' will be converted to
37
   a drive letter X if X is alpha-char.
38
3. a leading D:/... is treated as a windows drive letter
39
4. a relative path will be converted to an absolute path.
40
5. If any of the above is encountered, then forward slashes
41
   will be converted to backslashes.
42
All other cases are passed thru unchanged
43
*/
44
45
46
/* Define legal windows drive letters */
47
static const char* windrive = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
48
49
static const size_t cdlen = 10; /* strlen("/cygdrive/") */
50
51
static int pathdebug = -1;
52
53
static char* makeabsolute(const char* relpath);
54
55
EXTERNL
56
char* /* caller frees */
57
NCpathcvt(const char* path)
58
0
{
59
0
    char* outpath = NULL; 
60
0
    char* p;
61
0
    char* q;
62
0
    size_t pathlen;
63
64
0
    if(path == NULL) goto done; /* defensive driving */
65
66
    /* Check for path debug env vars */
67
0
    if(pathdebug < 0) {
68
0
  const char* s = getenv("NCPATHDEBUG");
69
0
        pathdebug = (s == NULL ? 0 : 1);
70
0
    }
71
72
0
    pathlen = strlen(path);
73
74
    /* 1. look for MSYS path /D/... */
75
0
    if(pathlen >= 2
76
0
  && (path[0] == '/' || path[0] == '\\')
77
0
  && strchr(windrive,path[1]) != NULL
78
0
  && (path[2] == '/' || path[2] == '\\' || path[2] == '\0')) {
79
  /* Assume this is a mingw path */
80
0
  outpath = (char*)malloc(pathlen+3); /* conservative */
81
0
  if(outpath == NULL) goto done;
82
0
  q = outpath;
83
0
  *q++ = path[1];
84
0
  *q++ = ':';
85
0
  strncpy(q,&path[2],pathlen);
86
0
  if(strlen(outpath) == 2)
87
0
      strcat(outpath,"/");
88
0
  goto slashtrans;
89
0
    }
90
91
    /* 2. Look for leading /cygdrive/D where D is a single-char drive letter */
92
0
    if(pathlen >= (cdlen+1)
93
0
  && memcmp(path,"/cygdrive/",cdlen)==0
94
0
  && strchr(windrive,path[cdlen]) != NULL
95
0
  && (path[cdlen+1] == '/'
96
0
      || path[cdlen+1] == '\\'
97
0
      || path[cdlen+1] == '\0')) {
98
  /* Assume this is a cygwin path */
99
0
  outpath = (char*)malloc(pathlen+1); /* conservative */
100
0
  if(outpath == NULL) goto done;
101
0
  outpath[0] = path[cdlen]; /* drive letter */
102
0
  outpath[1] = ':';
103
0
  strcpy(&outpath[2],&path[cdlen+1]);
104
0
  if(strlen(outpath) == 2)
105
0
      strcat(outpath,"/");
106
0
  goto slashtrans;
107
0
    }
108
109
    /* 3. Look for leading D: where D is a single-char drive letter */
110
0
    if(pathlen >= 2
111
0
  && strchr(windrive,path[0]) != NULL
112
0
  && path[1] == ':'
113
0
  && (path[2] == '\0' || path[2] == '/'  || path[2] == '\\')) {
114
0
  outpath = strdup(path);
115
0
  goto slashtrans;
116
0
    }
117
118
    /* 4. Look for relative path */
119
0
    if(pathlen > 1 && path[0] == '.') {
120
0
  outpath = makeabsolute(path);
121
0
  goto slashtrans;
122
0
    }
123
124
    /* Other: just pass thru */
125
0
    outpath = strdup(path);
126
0
    goto done;
127
128
0
slashtrans:
129
      /* In order to help debugging, and if not using MSC_VER or MINGW,
130
   convert back slashes to forward, else convert forward to back
131
      */
132
0
    p = outpath;
133
    /* In all #1 or #2 cases, translate '/' -> '\\' */
134
0
    for(;*p;p++) {
135
0
  if(*p == '/') {*p = '\\';}
136
0
    }
137
#ifdef PATHFORMAT
138
#ifndef _MSC_VER
139
  p = outpath;
140
        /* Convert '\' back to '/' */
141
        for(;*p;p++) {
142
            if(*p == '\\') {*p = '/';}
143
  }
144
    }
145
#endif /*!_MSC_VER*/
146
#endif /*PATHFORMAT*/
147
148
0
done:
149
0
    if(pathdebug) {
150
0
        fprintf(stderr,"XXXX: inpath=|%s| outpath=|%s|\n",
151
0
            path?path:"NULL",outpath?outpath:"NULL");
152
0
        fflush(stderr);
153
0
    }
154
0
    return outpath;
155
0
}
156
157
static char*
158
makeabsolute(const char* relpath)
159
0
{
160
0
    char* path = NULL;
161
#ifdef _WIN32
162
    path = _fullpath(NULL,relpath,8192);
163
#else
164
0
    path = realpath(relpath, NULL);
165
0
#endif
166
0
    if(path == NULL)
167
0
  path = strdup(relpath);
168
0
    return path;    
169
0
}
170
171
#ifdef WINPATH
172
173
/*
174
Provide wrappers for open and fopen.
175
*/
176
177
EXTERNL
178
FILE*
179
NCfopen(const char* path, const char* flags)
180
{
181
    FILE* f = NULL;
182
    char* cvtname = NCpathcvt(path);
183
    if(cvtname == NULL) return NULL;
184
    f = fopen(cvtname,flags);
185
    free(cvtname);    
186
    return f;
187
}
188
189
EXTERNL
190
int
191
NCopen3(const char* path, int flags, int mode)
192
{
193
    int fd = -1;
194
    char* cvtname = NCpathcvt(path);
195
    if(cvtname == NULL) return -1;
196
    fd = open(cvtname,flags,mode);
197
    free(cvtname);    
198
    return fd;
199
}
200
201
EXTERNL
202
int
203
NCopen2(const char *path, int flags)
204
{
205
    return NCopen3(path,flags,0);
206
}
207
208
/*
209
Provide wrappers for other file system functions
210
*/
211
212
/* Return access applied to path+mode */
213
EXTERNL
214
int
215
NCaccess(const char* path, int mode)
216
{
217
    int status = 0;
218
    char* cvtname = NCpathcvt(path);
219
    if(cvtname == NULL) return -1;
220
#ifdef _MSC_VER
221
    status = _access(cvtname,mode);
222
#else
223
    status = access(cvtname,mode);
224
#endif
225
    free(cvtname);    
226
    return status;
227
}
228
229
EXTERNL
230
int
231
NCremove(const char* path)
232
{
233
    int status = 0;
234
    char* cvtname = NCpathcvt(path);
235
    if(cvtname == NULL) return ENOENT;
236
    status = remove(cvtname);
237
    free(cvtname);    
238
    return status;
239
}
240
241
#endif /*WINPATH*/