Coverage Report

Created: 2026-03-30 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements OGRGPSBabelWriteDataSource class.
5
 * Author:   Even Rouault, <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include <cstring>
14
#include "cpl_conv.h"
15
#include "cpl_string.h"
16
#include "cpl_error.h"
17
#include "cpl_spawn.h"
18
19
#include "ogr_gpsbabel.h"
20
21
/************************************************************************/
22
/*                     OGRGPSBabelWriteDataSource()                     */
23
/************************************************************************/
24
25
0
OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource() = default;
26
27
/************************************************************************/
28
/*                    ~OGRGPSBabelWriteDataSource()                     */
29
/************************************************************************/
30
31
OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
32
33
0
{
34
0
    if (poGPXDS)
35
0
        GDALClose(poGPXDS);
36
37
0
    Convert();
38
39
0
    CPLFree(pszGPSBabelDriverName);
40
0
    CPLFree(pszFilename);
41
0
}
42
43
/************************************************************************/
44
/*                              Convert()                               */
45
/************************************************************************/
46
47
bool OGRGPSBabelWriteDataSource::Convert()
48
0
{
49
0
    int nRet = -1;
50
0
    if (!osTmpFileName.empty() && pszFilename != nullptr &&
51
0
        pszGPSBabelDriverName != nullptr)
52
0
    {
53
0
        if (OGRGPSBabelDataSource::IsSpecialFile(pszFilename))
54
0
        {
55
            /* Special file : don't try to open it */
56
0
            VSILFILE *tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
57
0
            if (tmpfp)
58
0
            {
59
0
                const char *const argv[] = {"gpsbabel",
60
0
                                            "-i",
61
0
                                            "gpx",
62
0
                                            "-f",
63
0
                                            "-",
64
0
                                            "-o",
65
0
                                            pszGPSBabelDriverName,
66
0
                                            "-F",
67
0
                                            pszFilename,
68
0
                                            nullptr};
69
0
                nRet = CPLSpawn(argv, tmpfp, nullptr, TRUE);
70
71
0
                VSIFCloseL(tmpfp);
72
0
                tmpfp = nullptr;
73
0
            }
74
0
        }
75
0
        else
76
0
        {
77
0
            VSILFILE *fp = VSIFOpenL(pszFilename, "wb");
78
0
            if (fp == nullptr)
79
0
            {
80
0
                CPLError(CE_Failure, CPLE_AppDefined, "Cannot open file %s",
81
0
                         pszFilename);
82
0
            }
83
0
            else
84
0
            {
85
0
                VSILFILE *tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
86
0
                if (tmpfp)
87
0
                {
88
0
                    const char *const argv[] = {"gpsbabel",
89
0
                                                "-i",
90
0
                                                "gpx",
91
0
                                                "-f",
92
0
                                                "-",
93
0
                                                "-o",
94
0
                                                pszGPSBabelDriverName,
95
0
                                                "-F",
96
0
                                                "-",
97
0
                                                nullptr};
98
0
                    nRet = CPLSpawn(argv, tmpfp, fp, TRUE);
99
100
0
                    VSIFCloseL(tmpfp);
101
0
                    tmpfp = nullptr;
102
0
                }
103
104
0
                VSIFCloseL(fp);
105
0
                fp = nullptr;
106
0
            }
107
0
        }
108
109
0
        VSIUnlink(osTmpFileName.c_str());
110
0
        osTmpFileName = "";
111
0
    }
112
113
0
    return nRet == 0;
114
0
}
115
116
/************************************************************************/
117
/*                               Create()                               */
118
/************************************************************************/
119
120
int OGRGPSBabelWriteDataSource::Create(const char *pszNameIn,
121
                                       CSLConstList papszOptions)
122
0
{
123
0
    GDALDriver *poGPXDriver =
124
0
        OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
125
0
    if (poGPXDriver == nullptr)
126
0
    {
127
0
        CPLError(CE_Failure, CPLE_AppDefined,
128
0
                 "GPX driver is necessary for GPSBabel write support");
129
0
        return FALSE;
130
0
    }
131
132
0
    if (!STARTS_WITH_CI(pszNameIn, "GPSBABEL:"))
133
0
    {
134
0
        const char *pszOptionGPSBabelDriverName =
135
0
            CSLFetchNameValue(papszOptions, "GPSBABEL_DRIVER");
136
0
        if (pszOptionGPSBabelDriverName != nullptr)
137
0
            pszGPSBabelDriverName = CPLStrdup(pszOptionGPSBabelDriverName);
138
0
        else
139
0
        {
140
0
            CPLError(CE_Failure, CPLE_AppDefined,
141
0
                     "GPSBABEL_DRIVER dataset creation option expected");
142
0
            return FALSE;
143
0
        }
144
145
0
        pszFilename = CPLStrdup(pszNameIn);
146
0
    }
147
0
    else
148
0
    {
149
0
        const char *pszSep = strchr(pszNameIn + 9, ':');
150
0
        if (pszSep == nullptr)
151
0
        {
152
0
            CPLError(CE_Failure, CPLE_AppDefined,
153
0
                     "Wrong syntax. Expected GPSBabel:driver_name[,options]*:"
154
0
                     "file_name");
155
0
            return FALSE;
156
0
        }
157
158
0
        pszGPSBabelDriverName = CPLStrdup(pszNameIn + 9);
159
0
        char *nextColon = strchr(pszGPSBabelDriverName, ':');
160
0
        if (nextColon)
161
0
            *nextColon = 0;
162
163
0
        pszFilename = CPLStrdup(pszSep + 1);
164
0
    }
165
166
    /* A bit of validation to avoid command line injection */
167
0
    if (!OGRGPSBabelDataSource::IsValidDriverName(pszGPSBabelDriverName))
168
0
        return FALSE;
169
170
0
    const char *pszOptionUseTempFile =
171
0
        CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
172
0
    if (pszOptionUseTempFile == nullptr)
173
0
        pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", nullptr);
174
0
    if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
175
0
        osTmpFileName = CPLGenerateTempFilenameSafe(nullptr);
176
0
    else
177
0
        osTmpFileName = VSIMemGenerateHiddenFilename("gpsbabel");
178
179
0
    poGPXDS = poGPXDriver->Create(osTmpFileName.c_str(), 0, 0, 0, GDT_Unknown,
180
0
                                  papszOptions);
181
0
    if (poGPXDS == nullptr)
182
0
        return FALSE;
183
184
0
    return TRUE;
185
0
}
186
187
/************************************************************************/
188
/*                            ICreateLayer()                            */
189
/************************************************************************/
190
191
OGRLayer *OGRGPSBabelWriteDataSource::ICreateLayer(
192
    const char *pszLayerName, const OGRGeomFieldDefn *poGeomFieldDefn,
193
    CSLConstList papszOptions)
194
0
{
195
0
    if (poGPXDS)
196
0
        return poGPXDS->CreateLayer(pszLayerName, poGeomFieldDefn,
197
0
                                    papszOptions);
198
0
    return nullptr;
199
0
}
200
201
/************************************************************************/
202
/*                           TestCapability()                           */
203
/************************************************************************/
204
205
int OGRGPSBabelWriteDataSource::TestCapability(const char *pszCap) const
206
207
0
{
208
0
    if (EQUAL(pszCap, ODsCCreateLayer))
209
0
        return TRUE;
210
211
0
    return FALSE;
212
0
}
213
214
/************************************************************************/
215
/*                              GetLayer()                              */
216
/************************************************************************/
217
218
const OGRLayer *OGRGPSBabelWriteDataSource::GetLayer(int iLayer) const
219
220
0
{
221
0
    if (poGPXDS)
222
0
        return poGPXDS->GetLayer(iLayer);
223
224
0
    return nullptr;
225
0
}
226
227
/************************************************************************/
228
/*                           GetLayerCount()                            */
229
/************************************************************************/
230
231
int OGRGPSBabelWriteDataSource::GetLayerCount() const
232
233
0
{
234
0
    if (poGPXDS)
235
0
        return poGPXDS->GetLayerCount();
236
237
0
    return 0;
238
0
}