mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-21 08:39:46 +08:00
9380790ea8
re: The current netcdf-c release has some problems with the mingw platform on windows. Mostly they are path issues. Changes to support mingw+msys2: ------------------------------- * Enable option of looking into the windows registry to find the mingw root path. In aid of proper path handling. * Add mingw+msys as a specific platform in configure.ac and move testing of the platform to the front so it is available early. * Handle mingw X libncpoco (dynamic loader) properly even though mingw does not yet support it. * Handle mingw X plugins properly even though mingw does not yet support it. * Alias pwd='pwd -W' to better handle paths in shell scripts. * Plus a number of other minor compile irritations. * Disallow the use of multiple nc_open's on the same file for windows (and mingw) because windows does not seem to handle these properly. Not sure why we did not catch this earlier. * Add mountpoint info to dpathmgr.c to help support mingw. * Cleanup dpathmgr conversions. Known problems: --------------- * I have not been able to get shared libraries to work, so plugins/filters must be disabled. * There is some kind of problem with libcurl that I have not solved, so all uses of libcurl (currently DAP+Byterange) must be disabled. Misc. other fixes: ------------------ * Cleanup the relationship between ENABLE_PLUGINS and various other flags in CMakeLists.txt and configure.ac. * Re-arrange the TESTDIRS order in Makefile.am. * Add pseudo-breakpoint to nclog.[ch] for debugging. * Improve the documentation of the path manager code in ncpathmgr.h * Add better support for relative paths in dpathmgr.c * Default the mode args to NCfopen to include "b" (binary) for windows. * Add optional debugging output in various places. * Make sure that everything builds with plugins disabled. * Fix numerous (s)printf inconsistencies betweenb the format spec and the arguments.
243 lines
8.1 KiB
C
243 lines
8.1 KiB
C
/*
|
|
* Copyright 2018, University Corporation for Atmospheric Research
|
|
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
|
*/
|
|
#ifndef _NCPATHMGR_H_
|
|
#define _NCPATHMGR_H_
|
|
|
|
#include "config.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
#ifdef HAVE_DIRENT_H
|
|
#include <dirent.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_STAT_H
|
|
#include <sys/stat.h>
|
|
#endif
|
|
#ifdef HAVE_FCNTL_H
|
|
#include <fcntl.h>
|
|
#endif
|
|
#include "ncexternl.h"
|
|
|
|
/*
|
|
The path management code attempts to take an arbitrary path and convert
|
|
it to a form acceptable to the current platform.
|
|
Assumptions about Input path:
|
|
1. It is not a URL
|
|
2. It conforms to the format expected by one of the following:
|
|
Linux (/x/y/...),
|
|
Cygwin (/cygdrive/D/...),
|
|
Windows|MINGW (D:\...),
|
|
Windows network path (\\mathworks\...)
|
|
MSYS (/D/...),
|
|
4. It is encoded in the local platform character set. Note that
|
|
for most systems, this is utf-8. But for Windows, the
|
|
encoding is most likely some form of ANSI code page, probably
|
|
the windows 1252 encoding. Note that in any case, the path
|
|
must be representable in the local Code Page.
|
|
|
|
Note that all input paths first have all back slashes (\)
|
|
converted to forward (/), so following rules are in terms of /.
|
|
|
|
Parsing Rules:
|
|
1. A relative path is left as is with no drive letter.
|
|
2. A leading '/cygdrive/D' will be converted to
|
|
drive letter D if D is alpha-char.
|
|
3. A leading D:/... is treated as a windows drive letter
|
|
4. A leading /d/... is treated as a windows drive letter
|
|
if the platform is MSYS2.
|
|
5. A leading // is a windows network path and is converted
|
|
to a drive letter using the fake drive letter "/".
|
|
So '//svc/x/y' translates to '/:/svc/x/y'.
|
|
6. All other cases are assumed to be Unix variants with no drive letter.
|
|
|
|
After parsing, the following pieces of information are kept in a struct.
|
|
a. kind: The inferred path type (e.g. cygwin, unix, etc)
|
|
b. drive: The drive letter if any
|
|
c. path: The path is everything after the drive letter
|
|
|
|
For output, NCpathcvt produces a re-written path that is acceptable
|
|
to the current platform (the one on which the code is running).
|
|
|
|
Additional root mount point information is obtained for Cygwin and MSYS.
|
|
The root mount point is found as follows (in order of precedence):
|
|
1. Registry: get the value of the key named "HKEY_LOCAL_MACHINE/SOFTWARE/Cygwin/setup".
|
|
2. Environment: get the value of MSYS2_PREFIX
|
|
|
|
The re-write rules (unparsing) are given the above three pieces
|
|
of info + the current platform + the root mount point (if any).
|
|
The conversion rules are as follows.
|
|
|
|
Platform | No Input Driv | Input Drive
|
|
----------------------------------------------------
|
|
NCPD_NIX | <path> | /<drive>/path
|
|
NCPD_CYGWIN | /<path> | /cygdrive/<drive>/<path>
|
|
NCPD_WIN | <mountpoint>/<path> | <drive>:<path>
|
|
NCPD_MSYS | <mountpoint>/<path> | <drive>:<path>
|
|
|
|
Notes:
|
|
1. MINGW without MSYS is treated like WIN.
|
|
2. The reason msys and win prefix the mount point is because
|
|
the IO functions are handled directly by Windows, hence
|
|
the conversion must look like a true windows path with a drive.
|
|
*/
|
|
|
|
#ifndef WINPATH
|
|
#if defined _WIN32 || defined __MINGW32__
|
|
#define WINPATH 1
|
|
#endif
|
|
#endif
|
|
|
|
/* Define wrapper constants for use with NCaccess */
|
|
/* Define wrapper constants for use with NCaccess */
|
|
#ifdef _WIN32
|
|
#define ACCESS_MODE_EXISTS 0
|
|
#define ACCESS_MODE_R 4
|
|
#define ACCESS_MODE_W 2
|
|
#define ACCESS_MODE_RW 6
|
|
#ifndef O_RDONLY
|
|
#define O_RDONLY _O_RDONLY
|
|
#define O_RDWR _O_RDWR
|
|
#define O_APPEND _O_APPEND
|
|
#define O_BINARY _O_BINARY
|
|
#define O_CREAT _O_CREAT
|
|
#define O_EXCL _O_EXCL
|
|
#endif
|
|
#else
|
|
#define ACCESS_MODE_EXISTS (F_OK)
|
|
#define ACCESS_MODE_R (R_OK)
|
|
#define ACCESS_MODE_W (W_OK)
|
|
#define ACCESS_MODE_RW (R_OK|W_OK)
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#ifndef S_IFDIR
|
|
#define S_IFDIR _S_IFDIR
|
|
#define S_IFREG _S_IFREG
|
|
#endif
|
|
#ifndef S_ISDIR
|
|
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
|
|
#define S_ISREG(mode) ((mode) & _S_IFREG)
|
|
#endif
|
|
#endif /*_WIN32*/
|
|
|
|
|
|
/*
|
|
WARNING: you should never need to explictly call this function;
|
|
rather it is invoked as part of the wrappers for e.g. NCfopen, etc.
|
|
This function is intended to be Idempotent: f(f(x) == f(x).
|
|
This means it is ok to call it repeatedly with no harm.
|
|
Unless, of course, an error occurs.
|
|
*/
|
|
EXTERNL char* NCpathcvt(const char* path);
|
|
|
|
/**
|
|
It is often convenient to convert a path to some canonical format
|
|
that has some desirable properties:
|
|
1. All backslashes have been converted to forward slash
|
|
2. It can be suffixed or prefixed by simple concatenation
|
|
with a '/' separator. The exception being if the base part
|
|
may be absolute, in which case, suffixing only is allowed;
|
|
the user is responsible for getting this right.
|
|
To this end we choose the cygwin format as our standard canonical form.
|
|
If the path has a windows drive letter, then it is represented
|
|
in the cygwin "/cygdrive/<drive-letter>" form.
|
|
If it is a windows network path, then it starts with "//".
|
|
If it is on *nix* platform, then this sequence will never appear
|
|
and the canonical path will look like a standard *nix* path.
|
|
*/
|
|
EXTERNL int NCpathcanonical(const char* srcpath, char** canonp);
|
|
|
|
EXTERNL int NChasdriveletter(const char* path);
|
|
|
|
EXTERNL int NCisnetworkpath(const char* path);
|
|
|
|
/* Canonicalize and make absolute by prefixing the current working directory */
|
|
EXTERNL char* NCpathabsolute(const char* name);
|
|
|
|
/* Check if this path appears to start with a windows drive letter */
|
|
EXTERNL int NChasdriveletter(const char* path);
|
|
|
|
/* Convert from the local coding (e.g. ANSI) to utf-8;
|
|
note that this can produce unexpected results for Windows
|
|
because it first converts to wide character and then to utf8. */
|
|
EXTERNL int NCpath2utf8(const char* path, char** u8p);
|
|
|
|
/* Wrap various stdio and unistd IO functions.
|
|
It is especially important to use for windows so that
|
|
NCpathcvt (above) is invoked on the path.
|
|
*/
|
|
#if defined(WINPATH)
|
|
/* path converter wrappers*/
|
|
EXTERNL FILE* NCfopen(const char* path, const char* flags);
|
|
EXTERNL int NCopen3(const char* path, int flags, int mode);
|
|
EXTERNL int NCopen2(const char* path, int flags);
|
|
EXTERNL int NCaccess(const char* path, int mode);
|
|
EXTERNL int NCremove(const char* path);
|
|
EXTERNL int NCmkdir(const char* path, int mode);
|
|
EXTERNL int NCrmdir(const char* path);
|
|
EXTERNL char* NCgetcwd(char* cwdbuf, size_t len);
|
|
EXTERNL int NCmkstemp(char* buf);
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
EXTERNL int NCstat(const char* path, struct stat* buf);
|
|
#endif
|
|
#ifdef HAVE_DIRENT_H
|
|
EXTERNL DIR* NCopendir(const char* path);
|
|
EXTERNL int NCclosedir(DIR* ent);
|
|
#endif
|
|
#else /*!WINPATH*/
|
|
#define NCfopen(path,flags) fopen((path),(flags))
|
|
#define NCopen3(path,flags,mode) open((path),(flags),(mode))
|
|
#define NCopen2(path,flags) open((path),(flags))
|
|
#define NCremove(path) remove(path)
|
|
#define NCaccess(path,mode) access(path,mode)
|
|
#define NCmkdir(path,mode) mkdir(path,mode)
|
|
#define NCgetcwd(buf,len) getcwd(buf,len)
|
|
#define NCmkstemp(buf) mkstemp(buf);
|
|
#define NCcwd(buf, len) getcwd(buf,len)
|
|
#define NCrmdir(path) rmdir(path)
|
|
#define NCunlink(path) unlink(path)
|
|
#ifdef HAVE_SYS_STAT_H
|
|
#define NCstat(path,buf) stat(path,buf)
|
|
#endif
|
|
#ifdef HAVE_DIRENT_H
|
|
#define NCopendir(path) opendir(path)
|
|
#define NCclosedir(ent) closedir(ent)
|
|
#endif
|
|
#endif /*!WINPATH*/
|
|
|
|
/* Platform independent */
|
|
#define NCclose(fd) close(fd)
|
|
#define NCfstat(fd,buf) fstat(fd,buf)
|
|
|
|
/**************************************************/
|
|
/* Following definitions are for testing only */
|
|
|
|
/* Possible Kinds Of Output */
|
|
#define NCPD_UNKNOWN 0
|
|
#define NCPD_NIX 1
|
|
#define NCPD_MSYS 2
|
|
#define NCPD_CYGWIN 3
|
|
#define NCPD_WIN 4
|
|
/* #define NCPD_MINGW NCPD_WIN *alias*/
|
|
#define NCPD_REL 6 /* actual kind is unknown */
|
|
|
|
EXTERNL char* NCpathcvt_test(const char* path, int ukind, int udrive);
|
|
EXTERNL int NCgetlocalpathkind(void);
|
|
EXTERNL int NCgetinputpathkind(const char* inpath);
|
|
EXTERNL const char* NCgetkindname(int kind);
|
|
EXTERNL void printutf8hex(const char* s, char* sx);
|
|
EXTERNL int getmountpoint(char*, size_t);
|
|
|
|
/**************************************************/
|
|
/* From dutil.c */
|
|
EXTERNL char* NC_backslashEscape(const char* s);
|
|
EXTERNL char* NC_backslashUnescape(const char* esc);
|
|
EXTERNL char* NC_shellUnescape(const char* esc);
|
|
|
|
#endif /* _NCPATHMGR_H_ */
|