1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <gflags/gflags.h>
16 #include <syscall.h>
17
18 #include <fstream>
19 #include <iostream>
20
21 #include "gdal_sapi.sapi.h" // NOLINT(build/include)
22 #include "absl/log/log.h"
23 #include "sandboxed_api/util/fileops.h"
24
25 class GdalSapiSandbox : public GDALSandbox {
26 public:
GdalSapiSandbox(std::string path)27 GdalSapiSandbox(std::string path)
28 : GDALSandbox(), file_path_(std::move(path)) {}
29
ModifyPolicy(sandbox2::PolicyBuilder *)30 std::unique_ptr<sandbox2::Policy> ModifyPolicy(
31 sandbox2::PolicyBuilder*) override {
32 return sandbox2::PolicyBuilder()
33 .AllowDynamicStartup()
34 .AllowRead()
35 .AllowSystemMalloc()
36 .AllowWrite()
37 .AllowExit()
38 .AllowStat()
39 .AllowOpen()
40 .AllowSyscall(__NR_futex)
41 .AllowSyscall(__NR_close)
42 .AllowSyscall(__NR_recvmsg)
43 .AllowSyscall(__NR_getdents64)
44 .AllowSyscall(__NR_lseek)
45 .AllowSyscall(__NR_getpid)
46 .AllowSyscall(__NR_sysinfo)
47 .AllowSyscall(__NR_prlimit64)
48 .AllowSyscall(__NR_ftruncate)
49 .AllowUnlink()
50 .AddFile(file_path_)
51 .BuildOrDie();
52 }
53
54 private:
55 std::string file_path_;
56 };
57
GdalMain(std::string filename)58 absl::Status GdalMain(std::string filename) {
59 // Reading GDALDataset from a (local, specific) file.
60 GdalSapiSandbox sandbox(filename);
61
62 SAPI_RETURN_IF_ERROR(sandbox.Init());
63 GDALApi api(&sandbox);
64
65 sapi::v::CStr s(filename.data());
66
67 SAPI_RETURN_IF_ERROR(api.GDALAllRegister());
68 auto open = api.GDALOpen(s.PtrBoth(), GDALAccess::GA_ReadOnly);
69
70 LOG(INFO) << "Dataset pointer adress: " << open.value() << std::endl;
71 sapi::v::RemotePtr ptr_dataset(open.value());
72
73 LOG(INFO) << ptr_dataset.ToString() << std::endl;
74 if (!open.value()) {
75 return absl::AbortedError("NULL pointer for Dataset.\n");
76 }
77
78 // Printing some general information about the dataset.
79 auto driver = api.GDALGetDatasetDriver(&ptr_dataset);
80 sapi::v::RemotePtr ptr_driver(driver.value());
81
82 auto driver_short_name = api.GDALGetDriverShortName(&ptr_driver);
83 auto driver_long_name = api.GDALGetDriverLongName(&ptr_driver);
84
85 sapi::v::RemotePtr ptr_driver_short_name(driver_short_name.value());
86 sapi::v::RemotePtr ptr_driver_long_name(driver_long_name.value());
87
88 LOG(INFO) << "Driver short name: "
89 << sandbox.GetCString(ptr_driver_short_name).value().c_str();
90 LOG(INFO) << "Driver long name: "
91 << sandbox.GetCString(ptr_driver_long_name).value().c_str();
92
93 // Checking that GetGeoTransform is valid.
94 std::vector<double> adf_geo_transform(6);
95 sapi::v::Array<double> adf_geo_transform_array(&adf_geo_transform[0],
96 adf_geo_transform.size());
97
98 // For this function that returns CPLErr, the error-handling must be done
99 // analyzing the returning object.
100 // Same for GDALReturnsIO from below.
101 CPLErr err;
102 SAPI_ASSIGN_OR_RETURN(
103 err,
104 api.GDALGetGeoTransform(&ptr_dataset, adf_geo_transform_array.PtrBoth()));
105
106 // If GDALGetGeoTransform generates an error.
107 if (err != CE_None) {
108 return absl::InternalError("GDAL rasterization failed.");
109 }
110
111 LOG(INFO) << "Origin = (" << adf_geo_transform[0] << ", "
112 << adf_geo_transform[3] << ")" << std::endl;
113 LOG(INFO) << "Pixel Size = (" << adf_geo_transform[0] << ", "
114 << adf_geo_transform[3] << ")" << std::endl;
115
116 std::vector<int> n_blockX_size(1);
117 std::vector<int> n_blockY_size(1);
118
119 sapi::v::Array<int> nBlockXSizeArray(&n_blockX_size[0], n_blockX_size.size());
120 sapi::v::Array<int> nBlockYSizeArray(&n_blockY_size[0], n_blockY_size.size());
121
122 auto band = api.GDALGetRasterBand(&ptr_dataset, 1);
123 LOG(INFO) << "Band pointer adress: " << band.value() << std::endl;
124 if (!band.value()) {
125 return absl::AbortedError("NULL pointer for Band.\n");
126 }
127
128 sapi::v::RemotePtr ptr_band(band.value());
129 SAPI_RETURN_IF_ERROR(api.GDALGetBlockSize(
130 &ptr_band, nBlockXSizeArray.PtrBoth(), nBlockYSizeArray.PtrBoth()));
131
132 LOG(INFO) << "Block = " << n_blockX_size[0] << " x " << n_blockY_size[0]
133 << std::endl;
134
135 std::vector<int> b_got_min(1);
136 std::vector<int> b_got_max(1);
137
138 sapi::v::Array<int> b_got_min_array(&b_got_min[0], b_got_min.size());
139 sapi::v::Array<int> b_got_max_array(&b_got_max[0], b_got_max.size());
140
141 auto nX_size = api.GDALGetRasterBandXSize(&ptr_band);
142 auto nY_size = api.GDALGetRasterBandYSize(&ptr_band);
143
144 std::vector<int8_t> raster_data(nX_size.value() * nY_size.value(), -1);
145 sapi::v::Array<int8_t> raster_data_array(&raster_data[0], raster_data.size());
146
147 // We will use CPLErr type of returning value, as before with
148 // GDALGetGeoTransorm.
149 SAPI_ASSIGN_OR_RETURN(
150 err, api.GDALRasterIO(&ptr_band, GF_Read, 0, 0, nX_size.value(),
151 nY_size.value(), raster_data_array.PtrBoth(),
152 nX_size.value(), nY_size.value(), GDT_Byte, 0, 0));
153
154 // If GDALRasterIO generates an error.
155 if (err != CE_None) {
156 return absl::InternalError("GDAL rasterization failed.");
157 }
158
159 std::cout << "Raster data info: " << raster_data_array.ToString()
160 << std::endl;
161
162 // To print the data content: `std::cout << raster_data_array.GetData() <<
163 // std::endl;`
164
165 return absl::OkStatus();
166 }
167
main(int argc,char * argv[])168 int main(int argc, char* argv[]) {
169 // The file to be converted should be specified in the first argument while
170 // running the program.
171 if (argc < 2) {
172 std::cout << "You need to provide a file name: ./raster "
173 "your_tiff_file_absolute_path\n"
174 "Example: ./raster /usr/home/username/file.tiff"
175 << std::endl;
176 return EXIT_FAILURE;
177 }
178
179 std::ifstream aux_file;
180 aux_file.open(argv[1]);
181 if (!aux_file.is_open()) {
182 std::cout << "Your file name is not valid.\nUnable to open the file."
183 << std::endl;
184 return EXIT_FAILURE;
185 }
186 std::string filename(argv[1]);
187
188 if (absl::Status status = GdalMain(filename); !status.ok()) {
189 LOG(ERROR) << "Initialization failed: " << status.ToString();
190 return EXIT_FAILURE;
191 }
192
193 return EXIT_SUCCESS;
194 }
195