Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: S-57 Translator
4 : * Purpose: Implements S57FileCollector() function. This function collects
5 : * a list of S-57 data files based on the contents of a directory,
6 : * catalog file, or direct reference to an S-57 file.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Frank Warmerdam
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "s57.h"
34 :
35 : /************************************************************************/
36 : /* S57FileCollector() */
37 : /************************************************************************/
38 :
39 0 : char **S57FileCollector(const char *pszDataset)
40 :
41 : {
42 : /* -------------------------------------------------------------------- */
43 : /* Stat the dataset, and fail if it isn't a file or directory. */
44 : /* -------------------------------------------------------------------- */
45 : VSIStatBuf sStatBuf;
46 0 : if (CPLStat(pszDataset, &sStatBuf))
47 : {
48 0 : CPLError(CE_Failure, CPLE_AppDefined,
49 : "No S-57 files found, %s\nisn't a directory or a file.\n",
50 : pszDataset);
51 :
52 0 : return nullptr;
53 : }
54 :
55 : /* -------------------------------------------------------------------- */
56 : /* We handle directories by scanning for all S-57 data files in */
57 : /* them, but not for catalogs. */
58 : /* -------------------------------------------------------------------- */
59 0 : char **papszRetList = nullptr;
60 :
61 0 : if (VSI_ISDIR(sStatBuf.st_mode))
62 : {
63 0 : char **papszDirFiles = VSIReadDir(pszDataset);
64 0 : DDFModule oModule;
65 :
66 0 : for (int iFile = 0;
67 0 : papszDirFiles != nullptr && papszDirFiles[iFile] != nullptr;
68 : iFile++)
69 : {
70 0 : char *pszFullFile = CPLStrdup(
71 0 : CPLFormFilename(pszDataset, papszDirFiles[iFile], nullptr));
72 :
73 : // Add to list if it is an S-57 _data_ file.
74 0 : if (VSIStat(pszFullFile, &sStatBuf) == 0 &&
75 0 : VSI_ISREG(sStatBuf.st_mode) && oModule.Open(pszFullFile, TRUE))
76 : {
77 0 : if (oModule.FindFieldDefn("DSID") != nullptr)
78 0 : papszRetList = CSLAddString(papszRetList, pszFullFile);
79 : }
80 :
81 0 : CPLFree(pszFullFile);
82 : }
83 :
84 0 : return papszRetList;
85 : }
86 :
87 : /* -------------------------------------------------------------------- */
88 : /* If this is a regular file, but not a catalog just return it. */
89 : /* Note that the caller may still open it and fail. */
90 : /* -------------------------------------------------------------------- */
91 0 : DDFModule oModule;
92 :
93 0 : if (!oModule.Open(pszDataset))
94 : {
95 0 : CPLError(CE_Failure, CPLE_AppDefined,
96 : "The file %s isn't an S-57 data file, or catalog.\n",
97 : pszDataset);
98 :
99 0 : return nullptr;
100 : }
101 :
102 0 : DDFRecord *poRecord = oModule.ReadRecord();
103 0 : if (poRecord == nullptr)
104 0 : return nullptr;
105 :
106 0 : if (poRecord->FindField("CATD") == nullptr ||
107 0 : oModule.FindFieldDefn("CATD")->FindSubfieldDefn("IMPL") == nullptr)
108 : {
109 0 : papszRetList = CSLAddString(papszRetList, pszDataset);
110 0 : return papszRetList;
111 : }
112 :
113 : /* -------------------------------------------------------------------- */
114 : /* We presumably have a catalog. It contains paths to files */
115 : /* that generally lack the ENC_ROOT component. Try to find the */
116 : /* correct name for the ENC_ROOT directory if available and */
117 : /* build a base path for our purposes. */
118 : /* -------------------------------------------------------------------- */
119 0 : char *pszCatDir = CPLStrdup(CPLGetPath(pszDataset));
120 0 : char *pszRootDir = nullptr;
121 :
122 0 : if (CPLStat(CPLFormFilename(pszCatDir, "ENC_ROOT", nullptr), &sStatBuf) ==
123 0 : 0 &&
124 0 : VSI_ISDIR(sStatBuf.st_mode))
125 : {
126 0 : pszRootDir = CPLStrdup(CPLFormFilename(pszCatDir, "ENC_ROOT", nullptr));
127 : }
128 0 : else if (CPLStat(CPLFormFilename(pszCatDir, "enc_root", nullptr),
129 0 : &sStatBuf) == 0 &&
130 0 : VSI_ISDIR(sStatBuf.st_mode))
131 : {
132 0 : pszRootDir = CPLStrdup(CPLFormFilename(pszCatDir, "enc_root", nullptr));
133 : }
134 :
135 0 : if (pszRootDir)
136 0 : CPLDebug("S57", "Found root directory to be %s.", pszRootDir);
137 :
138 : /* -------------------------------------------------------------------- */
139 : /* We have a catalog. Scan it for data files, those with an */
140 : /* IMPL of BIN. Is there be a better way of testing */
141 : /* whether a file is a data file or another catalog file? */
142 : /* -------------------------------------------------------------------- */
143 0 : for (; poRecord != nullptr; poRecord = oModule.ReadRecord())
144 : {
145 0 : if (poRecord->FindField("CATD") != nullptr &&
146 0 : EQUAL(poRecord->GetStringSubfield("CATD", 0, "IMPL", 0), "BIN"))
147 : {
148 : const char *pszFile =
149 0 : poRecord->GetStringSubfield("CATD", 0, "FILE", 0);
150 :
151 : // Often there is an extra ENC_ROOT in the path, try finding
152 : // this file.
153 :
154 : const char *pszWholePath =
155 0 : CPLFormFilename(pszCatDir, pszFile, nullptr);
156 0 : if (CPLStat(pszWholePath, &sStatBuf) != 0 && pszRootDir != nullptr)
157 : {
158 0 : pszWholePath = CPLFormFilename(pszRootDir, pszFile, nullptr);
159 : }
160 :
161 0 : if (CPLStat(pszWholePath, &sStatBuf) != 0)
162 : {
163 0 : CPLError(CE_Warning, CPLE_OpenFailed,
164 : "Can't find file %s from catalog %s.", pszFile,
165 : pszDataset);
166 0 : continue;
167 : }
168 :
169 0 : papszRetList = CSLAddString(papszRetList, pszWholePath);
170 0 : CPLDebug("S57", "Got path %s from CATALOG.", pszWholePath);
171 : }
172 : }
173 :
174 0 : CPLFree(pszCatDir);
175 0 : CPLFree(pszRootDir);
176 :
177 0 : return papszRetList;
178 : }
|