GRASS 8 Programmer's Manual 8.6.0dev(2026)-8843f13794
Loading...
Searching...
No Matches
raster/close.c
Go to the documentation of this file.
1/*!
2 * \file lib/raster/close.c
3 *
4 * \brief Raster Library - Close raster file
5 *
6 * SPDX-FileCopyrightText: 1999-2009 GRASS Development Team
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 *
9 * \author USACERL and many others
10 */
11
12#ifdef _WIN32
13#include <windows.h>
14#endif
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <unistd.h>
20#include <fcntl.h>
21#include <signal.h>
22#include <errno.h>
23
24#include <grass/gis.h>
25#include <grass/raster.h>
26#include <grass/glocale.h>
27
28#include "R.h"
29
30#define FORMAT_FILE "f_format"
31#define QUANT_FILE "f_quant"
32#define NULL_FILE "null"
33/* cmpressed null file */
34#define NULLC_FILE "nullcmpr"
35
36static int close_old(int);
37static int close_new(int, int);
38
39static void sync_and_close(int fd, char *element, char *name)
40{
41 /* from man 2 write:
42 * A successful return from write() does not make any guarantee
43 * that data has been committed to disk. On some filesystems,
44 * including NFS, it does not even guarantee that space has
45 * successfully been reserved for the data. In this case, some
46 * errors might be delayed until a future write(2), fsync(2), or
47 * even close(2). The only way to be sure is to call fsync(2)
48 * after you are done writing all your data.
49 */
50
51#ifndef _WIN32
52 if (fsync(fd)) {
53 G_warning(_("Unable to flush file %s for raster map %s: %s"), element,
55 }
56 /* for MS Windows, try fdopen(int, char *) + fflush(FILE *) + fclose(FILE *)
57 * flcose() closes the underlying file descriptor, thus no need to
58 * call close(fd) afterwards */
59#endif
60 if (close(fd)) {
61 G_warning(_("Unable to close file %s for raster map %s: %s"), element,
63 }
64}
65
66static void write_fp_format(int fd);
67
68/*!
69 * \brief Close a raster map
70 *
71 * The raster map opened on file descriptor <i>fd</i> is
72 * closed. Memory allocated for raster processing is freed. If open
73 * for writing, skeletal support files for the new raster map are
74 * created as well.
75 *
76 * <b>Note:</b> If a module wants to explicitly write support files
77 * (e.g., a specific color table) for a raster map it creates, it must
78 * do so after the raster map is closed. Otherwise the close will
79 * overwrite the support files. See \ref
80 * Raster_Map_Layer_Support_Routines for routines which write raster
81 * support files.
82 *
83 * If the map is a new floating point, move the <tt>.tmp</tt> file
84 * into the <tt>fcell</tt> element, create an empty file in the
85 * <tt>cell</tt> directory; write the floating-point range file; write
86 * a default quantization file quantization file is set here to round
87 * fp numbers (this is a default for now). create an empty category
88 * file, with max cat = max value (for backwards compatibility). Move
89 * the <tt>.tmp</tt> NULL-value bitmap file to the <tt>cell_misc</tt>
90 * directory.
91 *
92 * \param fd file descriptor
93 *
94 * \return void
95 */
96void Rast_close(int fd)
97{
98 struct fileinfo *fcb = &R__.fileinfo[fd];
99
100 if (fd < 0 || fd >= R__.fileinfo_count || fcb->open_mode <= 0)
101 G_fatal_error(_("Invalid descriptor: %d"), fd);
102
103 if (fcb->open_mode == OPEN_OLD)
104 close_old(fd);
105 else
106 close_new(fd, 1);
107}
108
109/*!
110 * \brief Unopen a raster map
111 *
112 * The raster map opened on file descriptor <i>fd</i> is
113 * closed. Memory allocated for raster processing is freed. If open
114 * for writing, the raster map is not created and the temporary file
115 * created when the raster map was opened is removed (see \ref
116 * Creating_and_Opening_New_Raster_Files). This routine is useful when
117 * errors are detected and it is desired to not create the new raster
118 * map. While it is true that the raster map will not be created if
119 * the module exits without closing the file, the temporary file will
120 * not be removed at module exit. GRASS database management will
121 * eventually remove the temporary file, but the file can be quite
122 * large and will take up disk space until GRASS does remove it. Use
123 * this routine as a courtesy to the user.
124 *
125 * \param fd file descriptor
126 *
127 * \return void
128 */
129void Rast_unopen(int fd)
130{
131 struct fileinfo *fcb = &R__.fileinfo[fd];
132
133 if (fd < 0 || fd >= R__.fileinfo_count || fcb->open_mode <= 0)
134 G_fatal_error(_("Invalid descriptor: %d"), fd);
135
136 if (fcb->open_mode == OPEN_OLD)
137 close_old(fd);
138 else
139 close_new(fd, 0);
140}
141
142/*!
143 * \brief Unopen all raster maps
144 *
145 * Unopen all raster maps opened for write. Memory allocated for
146 * raster processing is freed, and the temporary file created when the
147 * raster map was opened is removed (see \ref
148 * Creating_and_Opening_New_Raster_Files). This routine is useful when
149 * errors are detected and it is desired to remove temporary files.
150 *
151 * \return void
152 */
154{
155 int i;
156
157 for (i = 0; i < R__.fileinfo_count; i++) {
158 struct fileinfo *fcb = &R__.fileinfo[i];
159
160 if (fcb->open_mode == OPEN_NEW_COMPRESSED ||
161 fcb->open_mode == OPEN_NEW_UNCOMPRESSED)
162 close_new(i, 0);
163 }
164}
165
166static int close_old(int fd)
167{
168 struct fileinfo *fcb = &R__.fileinfo[fd];
169
170 /* if R__.auto_mask was only allocated for reading map rows to create
171 non-existent null rows, and not for actual mask, free R__.mask_row
172 if(R__.auto_mask <=0)
173 G_free (R__.mask_buf);
174 This is obsolete since now the mask_bus is always allocated
175 */
176
177 if (fcb->gdal)
179 if (fcb->vrt)
180 Rast_close_vrt(fcb->vrt);
181
182 if (fcb->null_bits)
183 G_free(fcb->null_bits);
184 if (fcb->null_row_ptr)
185 G_free(fcb->null_row_ptr);
186 if (fcb->null_fd >= 0)
187 close(fcb->null_fd);
188 fcb->null_fd = -1;
189
190 if (fcb->cellhd.compressed)
191 G_free(fcb->row_ptr);
192 G_free(fcb->col_map);
193 G_free(fcb->mapset);
194 G_free(fcb->data);
195 G_free(fcb->name);
196 if (fcb->reclass_flag)
197 Rast_free_reclass(&fcb->reclass);
198 fcb->open_mode = -1;
199
200 if (fcb->map_type != CELL_TYPE) {
201 Rast_quant_free(&fcb->quant);
202 }
203 if (fcb->data_fd >= 0)
204 close(fcb->data_fd);
205
206 return 1;
207}
208
209static void write_support_files(int fd)
210{
211 struct fileinfo *fcb = &R__.fileinfo[fd];
212 struct Categories cats;
213 struct History hist;
215 char path[GPATH_MAX];
216
217 /* remove color table */
219
220 /* create a history file */
221 Rast_short_history(fcb->name, "raster", &hist);
222 Rast_write_history(fcb->name, &hist);
223
224 /* write the range */
225 if (fcb->map_type == CELL_TYPE) {
226 Rast_write_range(fcb->name, &fcb->range);
228 }
229 /*NOTE: int range for floating point maps is not written out */
230 else { /* if(fcb->map_type != CELL_TYPE) */
231
232 Rast_write_fp_range(fcb->name, &fcb->fp_range);
234 /* this range will be used to add default rule to quant structure */
235 }
236
237 if (fcb->map_type != CELL_TYPE)
238 fcb->cellhd.format = -1;
239 else /* CELL map */
240 fcb->cellhd.format = fcb->nbytes - 1;
241
242 /* write header file */
243 Rast_put_cellhd(fcb->name, &fcb->cellhd);
244
245 /* if map is floating point write the quant rules, otherwise remove f_quant
246 */
247 if (fcb->map_type != CELL_TYPE) {
248 /* DEFAULT RANGE QUANT
249 Rast_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max);
250 if(!Rast_is_d_null_value(&dcell_min) &&
251 !Rast_is_d_null_value(&dcell_max))
252 {
253 Rast_get_range_min_max(&fcb->range, &cell_min, &cell_max);
254 Rast_quant_add_rule(&fcb->quant, dcell_min, dcell_max,
255 cell_min, cell_max);
256 }
257 */
258 Rast_quant_round(&fcb->quant);
259 Rast_write_quant(fcb->name, fcb->mapset, &fcb->quant);
260 }
261 else {
262 /* remove cell_misc/name/f_quant */
263 G_file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name, fcb->mapset);
264 remove(path);
265 }
266
267 /* create empty cats file */
270 cell_max = 0;
271 Rast_init_cats((char *)NULL, &cats);
272 Rast_write_cats(fcb->name, &cats);
273 Rast_free_cats(&cats);
274
275 /* write the histogram */
276 /* only works for integer maps */
277 if ((fcb->map_type == CELL_TYPE) && (fcb->want_histogram)) {
279 Rast_free_cell_stats(&fcb->statf);
280 }
281 else {
283 }
284}
285
286static int close_new_gdal(int fd, int ok)
287{
288 struct fileinfo *fcb = &R__.fileinfo[fd];
289 char path[GPATH_MAX];
290 int stat = 1;
291
292 if (ok) {
293 int cell_fd;
294
295 G_debug(1, "close %s GDAL", fcb->name);
296
297 if (fcb->cur_row < fcb->cellhd.rows) {
298 int row;
299
300 Rast_zero_output_buf(fcb->data, fcb->map_type);
301 for (row = fcb->cur_row; row < fcb->cellhd.rows; row++)
302 Rast_put_row(fd, fcb->data, fcb->map_type);
303 G_free(fcb->data);
304 fcb->data = NULL;
305 }
306
307 /* create path : full null file name */
308 G__make_mapset_element_misc("cell_misc", fcb->name);
309 G_file_name_misc(path, "cell_misc", NULL_FILE, fcb->name, G_mapset());
310 remove(path);
311 G_file_name_misc(path, "cell_misc", NULLC_FILE, fcb->name, G_mapset());
312 remove(path);
313
314 /* write 0-length cell file */
316 G_file_name(path, "cell", fcb->name, fcb->mapset);
317 cell_fd = creat(path, 0666);
318 close(cell_fd);
319
320 if (fcb->map_type != CELL_TYPE) { /* floating point map */
321 write_fp_format(fd);
322
323 /* write 0-length fcell file */
325 G_file_name(path, "fcell", fcb->name, fcb->mapset);
326 cell_fd = creat(path, 0666);
327 close(cell_fd);
328 }
329 else {
330 /* remove fcell/name file */
331 G_file_name(path, "fcell", fcb->name, fcb->mapset);
332 remove(path);
333 /* remove cell_misc/name/f_format */
334 G_file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name,
335 fcb->mapset);
336 remove(path);
337 }
338
339 if (Rast_close_gdal_write_link(fcb->gdal) < 0)
340 stat = -1;
341 }
342 else {
343 remove(fcb->gdal->filename);
345 }
346
347 fcb->open_mode = -1;
348
349 if (fcb->data != NULL)
350 G_free(fcb->data);
351
352 if (ok)
353 write_support_files(fd);
354
355 G_free(fcb->name);
356 G_free(fcb->mapset);
357
358 if (fcb->map_type != CELL_TYPE)
359 Rast_quant_free(&fcb->quant);
360
361 return stat;
362}
363
364static int close_new(int fd, int ok)
365{
366 struct fileinfo *fcb = &R__.fileinfo[fd];
367 int stat;
368 char path[GPATH_MAX];
369 int row;
370 const char *CELL_DIR;
371
372 if (fcb->gdal)
373 return close_new_gdal(fd, ok);
374
375 if (ok) {
376 switch (fcb->open_mode) {
378 G_debug(1, "close %s compressed", fcb->name);
379 break;
381 G_debug(1, "close %s uncompressed", fcb->name);
382 break;
383 }
384
385 if (fcb->cur_row < fcb->cellhd.rows) {
386 Rast_zero_output_buf(fcb->data, fcb->map_type);
387 for (row = fcb->cur_row; row < fcb->cellhd.rows; row++)
388 Rast_put_row(fd, fcb->data, fcb->map_type);
389 G_free(fcb->data);
390 fcb->data = NULL;
391 }
392
393 if (fcb->null_row_ptr) { /* compressed nulls */
394 fcb->null_row_ptr[fcb->cellhd.rows] =
395 lseek(fcb->null_fd, 0L, SEEK_CUR);
396 if (fcb->null_row_ptr[fcb->cellhd.rows] == -1) {
397 int err = errno;
398 G_fatal_error(_("File read/write operation failed: %s (%d)"),
399 strerror(err), err);
400 }
401 Rast__write_null_row_ptrs(fd, fcb->null_fd);
402 }
403
404 if (fcb->null_fd >= 0) {
405 sync_and_close(fcb->null_fd,
406 (fcb->null_row_ptr ? NULLC_FILE : NULL_FILE),
407 fcb->name);
408 }
409 fcb->null_fd = -1;
410
411 /* create path : full null file name */
412 G__make_mapset_element_misc("cell_misc", fcb->name);
413 G_file_name_misc(path, "cell_misc", NULL_FILE, fcb->name, G_mapset());
414 remove(path);
415 G_file_name_misc(path, "cell_misc", NULLC_FILE, fcb->name, G_mapset());
416 remove(path);
417
418 G_file_name_misc(path, "cell_misc",
419 fcb->null_row_ptr ? NULLC_FILE : NULL_FILE, fcb->name,
420 G_mapset());
421
422 if (fcb->null_cur_row > 0) {
423 /* if temporary NULL file exists, write it into cell_misc/name/null
424 */
425 if (rename(fcb->null_temp_name, path)) {
426 G_warning(_("Unable to rename null file '%s' to '%s': %s"),
427 fcb->null_temp_name, path, strerror(errno));
428 stat = -1;
429 }
430 /* if rename() was successful what is left to remove() ? */
431 else {
432 remove(fcb->null_temp_name);
433 }
434 }
435 else {
436 remove(fcb->null_temp_name);
437 remove(path); /* again ? */
438 } /* null_cur_row > 0 */
439
440 if (fcb->open_mode == OPEN_NEW_COMPRESSED) { /* auto compression */
441 fcb->row_ptr[fcb->cellhd.rows] = lseek(fcb->data_fd, 0L, SEEK_CUR);
442 if (fcb->row_ptr[fcb->cellhd.rows] == -1) {
443 int err = errno;
444 G_fatal_error(_("File read/write operation failed: %s (%d)"),
445 strerror(err), err);
446 }
448 }
449
450 if (fcb->map_type != CELL_TYPE) { /* floating point map */
451 int cell_fd;
452
453 write_fp_format(fd);
454
455 /* now write 0-length cell file */
457 cell_fd =
458 creat(G_file_name(path, "cell", fcb->name, fcb->mapset), 0666);
459 close(cell_fd);
460 CELL_DIR = "fcell";
461 }
462 else {
463 /* remove fcell/name file */
464 G_file_name(path, "fcell", fcb->name, fcb->mapset);
465 remove(path);
466 /* remove cell_misc/name/f_format */
467 G_file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name,
468 fcb->mapset);
469 remove(path);
470 CELL_DIR = "cell";
471 }
472 } /* ok */
473 /* NOW CLOSE THE FILE DESCRIPTOR */
474
475 sync_and_close(fcb->data_fd,
476 (fcb->map_type == CELL_TYPE ? "cell" : "fcell"), fcb->name);
477 fcb->open_mode = -1;
478
479 if (fcb->null_fd >= 0) {
480 sync_and_close(fcb->null_fd,
481 (fcb->null_row_ptr ? NULLC_FILE : NULL_FILE), fcb->name);
482 }
483 fcb->null_fd = -1;
484
485 if (fcb->data != NULL)
486 G_free(fcb->data);
487
488 if (fcb->null_temp_name != NULL) {
489 G_free(fcb->null_temp_name);
490 fcb->null_temp_name = NULL;
491 }
492
493 /* if the cell file was written to a temporary file
494 * move this temporary file into the cell file
495 * if the move fails, tell the user, but go ahead and create
496 * the support files
497 */
498 stat = 1;
499 if (ok && (fcb->temp_name != NULL)) {
500 G_file_name(path, CELL_DIR, fcb->name, fcb->mapset);
501 remove(path);
502 if (rename(fcb->temp_name, path)) {
503 G_warning(_("Unable to rename cell file '%s' to '%s': %s"),
504 fcb->temp_name, path, strerror(errno));
505 stat = -1;
506 }
507 /* if rename() was successful what is left to remove() ? */
508 else {
509 remove(fcb->temp_name);
510 }
511 }
512
513 if (fcb->temp_name != NULL) {
514 G_free(fcb->temp_name);
515 }
516
517 if (ok)
518 write_support_files(fd);
519
520 G_free(fcb->name);
521 G_free(fcb->mapset);
522
523 G_free(fcb->null_bits);
524
525 if (fcb->null_row_ptr)
526 G_free(fcb->null_row_ptr);
527
528 if (fcb->map_type != CELL_TYPE)
529 Rast_quant_free(&fcb->quant);
530
531 return stat;
532}
533
535{
536 struct fileinfo *fcb = &R__.fileinfo[fd];
537 char path[GPATH_MAX];
538
539 if (fcb->null_row_ptr) { /* compressed nulls */
540 fcb->null_row_ptr[fcb->cellhd.rows] = lseek(fcb->null_fd, 0L, SEEK_CUR);
541 if (fcb->null_row_ptr[fcb->cellhd.rows] == -1) {
542 int err = errno;
543 G_fatal_error(_("File read/write operation failed: %s (%d)"),
544 strerror(err), err);
545 }
546 Rast__write_null_row_ptrs(fd, fcb->null_fd);
547 G_free(fcb->null_row_ptr);
548 }
549
550 if (fcb->null_fd >= 0)
551 close(fcb->null_fd);
552 fcb->null_fd = -1;
553
554 /* create path : full null file name */
555 G__make_mapset_element_misc("cell_misc", fcb->name);
556 G_file_name_misc(path, "cell_misc", NULL_FILE, fcb->name, G_mapset());
557 remove(path);
558 G_file_name_misc(path, "cell_misc", NULLC_FILE, fcb->name, G_mapset());
559 remove(path);
560
561 G_file_name_misc(path, "cell_misc",
562 fcb->null_row_ptr ? NULLC_FILE : NULL_FILE, fcb->name,
563 G_mapset());
564
565 if (rename(fcb->null_temp_name, path))
566 G_warning(_("Unable to rename null file '%s' to '%s': %s"),
567 fcb->null_temp_name, path, strerror(errno));
568 remove(fcb->null_temp_name);
569
570 G_free(fcb->null_temp_name);
571
572 G_free(fcb->name);
573 G_free(fcb->mapset);
574
575 G_free(fcb->null_bits);
576
577 fcb->open_mode = -1;
578}
579
580/* returns 0 on success, 1 on failure */
581static void write_fp_format(int fd)
582{
583 struct fileinfo *fcb = &R__.fileinfo[fd];
584 struct Key_Value *format_kv;
585 char path[GPATH_MAX];
586
587 if (fcb->map_type == CELL_TYPE) {
588 G_warning(_("unable to write f_format file for CELL maps"));
589 return;
590 }
592 if (fcb->map_type == FCELL_TYPE)
593 G_set_key_value("type", "float", format_kv);
594 else
595 G_set_key_value("type", "double", format_kv);
596
597 G_set_key_value("byte_order", "xdr", format_kv);
598
599 if (fcb->open_mode == OPEN_NEW_COMPRESSED)
600 G_set_key_value("lzw_compression_bits", "-1", format_kv);
601
602 G__make_mapset_element_misc("cell_misc", fcb->name);
603 G_file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset);
605
607}
#define OPEN_NEW_COMPRESSED
Definition R.h:106
#define OPEN_NEW_UNCOMPRESSED
Definition R.h:107
#define OPEN_OLD
Definition R.h:105
#define NULL
Definition ccmath.h:32
AMI_err name(char **stream_name)
Definition ami_stream.h:426
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
int G__make_mapset_element_misc(const char *, const char *)
Create misc element in the current mapset.
Definition mapset_msc.c:259
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
char * G_file_name_misc(char *, const char *, const char *, const char *, const char *)
Builds full path names to GIS misc data files.
Definition file_name.c:99
int G_make_mapset_object_group(const char *)
Create directory for group of elements of a given type.
Definition mapset_msc.c:73
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition file_name.c:59
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
Definition key_value1.c:102
void G_set_key_value(const char *, const char *, struct Key_Value *)
Set value for given key.
Definition key_value1.c:37
struct Key_Value * G_create_key_value(void)
Allocate and initialize Key_Value structure.
Definition key_value1.c:21
void G_write_key_value_file(const char *, const struct Key_Value *)
Write key/value pairs to file.
Definition key_value3.c:26
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:31
void Rast_put_cellhd(const char *, struct Cell_head *)
Writes the raster file header.
Definition put_cellhd.c:26
void Rast_free_cats(struct Categories *)
Free category structure memory.
void Rast_construct_default_range(struct Range *)
Construct default range.
void Rast_write_histogram_cs(const char *, struct Cell_stats *)
Writes the histogram based on cell statistics to file.
Definition histogram.c:108
void Rast_quant_round(struct Quant *)
Sets the quant rules to perform simple rounding on floats.
Definition quant.c:228
void Rast_close_gdal_link(struct GDAL_link *)
Close existing GDAL link.
Definition gdal.c:378
void Rast_quant_free(struct Quant *)
Resets and frees allocated memory.
Definition quant.c:53
void Rast_write_cats(const char *, struct Categories *)
Write raster category file.
void Rast_free_reclass(struct Reclass *)
Free Reclass structure.
Definition reclass.c:197
void Rast_free_cell_stats(struct Cell_stats *)
Free cell stats structure.
Definition cell_stats.c:380
int Rast__write_row_ptrs(int)
void Rast_remove_histogram(const char *)
Removes the histogram.
Definition histogram.c:329
void Rast_write_history(const char *, struct History *)
Write raster history file.
void Rast_init_cats(const char *, struct Categories *)
Initialize category structure.
int Rast_close_gdal_write_link(struct GDAL_link *)
Close existing GDAL link and write out data.
Definition gdal.c:393
int Rast__write_null_row_ptrs(int, int)
void Rast_write_range(const char *, const struct Range *)
Write raster range file.
void Rast__remove_fp_range(const char *)
Remove floating-point range.
void Rast_get_range_min_max(const struct Range *, CELL *, CELL *)
Get range min and max.
void Rast_close_vrt(struct R_vrt *)
Definition vrt.c:148
void Rast_put_row(int, const void *, RASTER_MAP_TYPE)
Writes the next row for cell/fcell/dcell file.
void Rast_short_history(const char *, const char *, struct History *)
Initialize history structure.
#define Rast_is_c_null_value(cellVal)
int Rast_remove_colors(const char *, const char *)
Remove color table of raster map.
void Rast_write_quant(const char *, const char *, const struct Quant *)
Writes the quant rule table for the raster map.
Definition quant_rw.c:147
void Rast_zero_output_buf(void *, RASTER_MAP_TYPE)
Definition zero_cell.c:36
void Rast_write_fp_range(const char *, const struct FPRange *)
Write raster range file (floating-point)
Header file for msvc/fcntl.c.
#define creat
Definition fcntl.h:33
#define GPATH_MAX
Definition gis.h:196
int CELL
Definition gis.h:631
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
#define NULL_FILE
void Rast__close_null(int fd)
void Rast_close(int fd)
Close a raster map.
void Rast__unopen_all(void)
Unopen all raster maps.
#define NULLC_FILE
void Rast_unopen(int fd)
Unopen a raster map.
#define QUANT_FILE
#define FORMAT_FILE
#define FCELL_TYPE
Definition raster.h:12
#define CELL_TYPE
Definition raster.h:11
Raster history info (metadata)
Definition raster.h:172
Definition R.h:86
struct fileinfo * fileinfo
Definition R.h:100
int fileinfo_count
Definition R.h:99
Definition R.h:48
Definition path.h:15
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
#define close
Definition unistd.h:8