aboutsummaryrefslogtreecommitdiff
path: root/src/open_lib.cpp
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-01-09 19:08:27 +0100
committerEven Rouault <even.rouault@spatialys.com>2019-01-09 19:45:21 +0100
commit03b8e99d388013558b1a2ec02a82af4763b26b34 (patch)
tree63c130f29048b391c7873b364637f8dc6267044b /src/open_lib.cpp
parent3cc9336b038118de424d018dd0bdd90e329ad8c1 (diff)
downloadPROJ-03b8e99d388013558b1a2ec02a82af4763b26b34.tar.gz
PROJ-03b8e99d388013558b1a2ec02a82af4763b26b34.zip
PROJ_LIB: support multiple paths supported by colon on Unix and semi-colon on Windows (fixes #1150)
Diffstat (limited to 'src/open_lib.cpp')
-rw-r--r--src/open_lib.cpp192
1 files changed, 107 insertions, 85 deletions
diff --git a/src/open_lib.cpp b/src/open_lib.cpp
index b022b263..510704e9 100644
--- a/src/open_lib.cpp
+++ b/src/open_lib.cpp
@@ -30,12 +30,18 @@
#define PJ_LIB__
+#ifndef FROM_PROJ_CPP
+#define FROM_PROJ_CPP
+#endif
+
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "proj/internal/internal.hpp"
+
#include "proj_internal.h"
static const char * proj_lib_name =
@@ -151,92 +157,73 @@ void pj_set_searchpath ( int count, const char **path )
static PAFile
pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
char* out_full_filename, size_t out_full_filename_size) {
- char fname[MAX_PATH_FILENAME+1];
- const char *sysname = nullptr;
- PAFile fid;
- int n = 0;
+ try {
+ std::string fname;
+ const char *sysname = nullptr;
+ PAFile fid = nullptr;
#ifdef WIN32
- static const char dir_chars[] = "/\\";
+ static const char dir_chars[] = "/\\";
+ const char dirSeparator = ';';
#else
- static const char dir_chars[] = "/";
+ static const char dir_chars[] = "/";
+ const char dirSeparator = ':';
#endif
- if( ctx == nullptr ) {
- ctx = pj_get_default_ctx();
- }
-
- if( out_full_filename != nullptr && out_full_filename_size > 0 )
- out_full_filename[0] = '\0';
-
- /* check if ~/name */
- if (*name == '~' && strchr(dir_chars,name[1]) )
- if ((sysname = getenv("HOME")) != nullptr) {
- if( strlen(sysname) + 1 + strlen(name) + 1 > sizeof(fname) )
- {
- return nullptr;
- }
- (void)strcpy(fname, sysname);
- fname[n = (int)strlen(fname)] = DIR_CHAR;
- fname[++n] = '\0';
- (void)strcpy(fname+n, name + 1);
- sysname = fname;
- } else
- return nullptr;
-
- /* or fixed path: /name, ./name or ../name */
- else if (strchr(dir_chars,*name)
- || (*name == '.' && strchr(dir_chars,name[1]))
- || (!strncmp(name, "..", 2) && strchr(dir_chars,name[2]))
- || (name[1] == ':' && strchr(dir_chars,name[2])) )
- sysname = name;
-
- /* or try to use application provided file finder */
- else if( ctx && ctx->file_finder != nullptr && (sysname = ctx->file_finder( ctx, name, ctx->file_finder_user_data )) != nullptr )
- ;
-
- else if( ctx && ctx->file_finder_legacy != nullptr && (sysname = ctx->file_finder_legacy( name )) != nullptr )
- ;
-
- /* or is environment PROJ_LIB defined */
- else if ((sysname = getenv("PROJ_LIB")) || (sysname = proj_lib_name)) {
- if( strlen(sysname) + 1 + strlen(name) + 1 > sizeof(fname) )
- {
- return nullptr;
+ if( ctx == nullptr ) {
+ ctx = pj_get_default_ctx();
}
- (void)strcpy(fname, sysname);
- fname[n = (int)strlen(fname)] = DIR_CHAR;
- fname[++n] = '\0';
- (void)strcpy(fname+n, name);
- sysname = fname;
- } else /* just try it bare bones */
- sysname = name;
-
- if ((fid = pj_ctx_fopen(ctx, sysname, mode)) != nullptr)
- {
+
if( out_full_filename != nullptr && out_full_filename_size > 0 )
- {
- strncpy(out_full_filename, sysname, out_full_filename_size);
- out_full_filename[out_full_filename_size-1] = '\0';
- }
- errno = 0;
- }
+ out_full_filename[0] = '\0';
+
+ /* check if ~/name */
+ if (*name == '~' && strchr(dir_chars,name[1]) )
+ if ((sysname = getenv("HOME")) != nullptr) {
+ fname = sysname;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
+ } else
+ return nullptr;
- /* If none of those work and we have a search path, try it */
- std::string tmp;
- if (!fid && ctx && !ctx->search_paths.empty() )
- {
- for( const auto& path: ctx->search_paths ) {
- try {
- tmp = path + DIR_CHAR + name;
- sysname = tmp.c_str();
+ /* or fixed path: /name, ./name or ../name */
+ else if (strchr(dir_chars,*name)
+ || (*name == '.' && strchr(dir_chars,name[1]))
+ || (!strncmp(name, "..", 2) && strchr(dir_chars,name[2]))
+ || (name[1] == ':' && strchr(dir_chars,name[2])) )
+ sysname = name;
+
+ /* or try to use application provided file finder */
+ else if( ctx && ctx->file_finder != nullptr && (sysname = ctx->file_finder( ctx, name, ctx->file_finder_user_data )) != nullptr )
+ ;
+
+ else if( ctx && ctx->file_finder_legacy != nullptr && (sysname = ctx->file_finder_legacy( name )) != nullptr )
+ ;
+
+ /* or is environment PROJ_LIB defined */
+ else if ((sysname = getenv("PROJ_LIB")) != nullptr) {
+
+ auto paths = NS_PROJ::internal::split(std::string(sysname), dirSeparator);
+ for( const auto& path: paths ) {
+ fname = path;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
fid = pj_ctx_fopen(ctx, sysname, mode);
- } catch( const std::exception& )
- {
+ if( fid )
+ break;
}
- if( fid )
- break;
- }
- if (fid)
+
+ /* or hardcoded path */
+ } else if ((sysname = proj_lib_name) != nullptr) {
+ fname = sysname;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
+ } else /* just try it bare bones */
+ sysname = name;
+
+ if ( fid != nullptr || (fid = pj_ctx_fopen(ctx, sysname, mode)) != nullptr)
{
if( out_full_filename != nullptr && out_full_filename_size > 0 )
{
@@ -245,17 +232,52 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
}
errno = 0;
}
- }
- if( ctx->last_errno == 0 && errno != 0 )
- pj_ctx_set_errno( ctx, errno );
+ /* If none of those work and we have a search path, try it */
+ if (!fid && ctx && !ctx->search_paths.empty() )
+ {
+ for( const auto& path: ctx->search_paths ) {
+ try {
+ fname = path;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
+ fid = pj_ctx_fopen(ctx, sysname, mode);
+ } catch( const std::exception& )
+ {
+ }
+ if( fid )
+ break;
+ }
+ if (fid)
+ {
+ if( out_full_filename != nullptr && out_full_filename_size > 0 )
+ {
+ strncpy(out_full_filename, sysname, out_full_filename_size);
+ out_full_filename[out_full_filename_size-1] = '\0';
+ }
+ errno = 0;
+ }
+ }
+
+ if( ctx->last_errno == 0 && errno != 0 )
+ pj_ctx_set_errno( ctx, errno );
- pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
- "pj_open_lib(%s): call fopen(%s) - %s",
- name, sysname,
- fid == nullptr ? "failed" : "succeeded" );
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ "pj_open_lib(%s): call fopen(%s) - %s",
+ name, sysname,
+ fid == nullptr ? "failed" : "succeeded" );
- return(fid);
+ return(fid);
+ }
+ catch( const std::exception& ) {
+
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ "pj_open_lib(%s): out of memory",
+ name );
+
+ return nullptr;
+ }
}
/************************************************************************/