GRASS Programmer's Manual 6.4.1(2011)
|
00001 00002 /*********************************************************************** 00003 * 00004 * G_close_cell(fd) 00005 * Closes and does housekeeping on an opened cell file 00006 * 00007 * G_unopen_cell(fd) 00008 * Closes and does housekeeping on an opened cell file 00009 * without creating the cell file 00010 * 00011 * parms: 00012 * int fd open cell file 00013 * 00014 * returns: 00015 * -1 on fail 00016 * 0 on success 00017 * 00018 * note: 00019 * On closing of a cell file that was open for writing, dummy cats 00020 * and history files are created. Histogram and range info are written. 00021 * 00022 **********************************************************************/ 00023 00024 #ifdef __MINGW32__ 00025 # include <windows.h> 00026 #endif 00027 00028 #include <stdio.h> 00029 #include <stdlib.h> 00030 #include <string.h> 00031 #include <unistd.h> 00032 #include <fcntl.h> 00033 #include <signal.h> 00034 #include <grass/gis.h> 00035 #include <grass/glocale.h> 00036 #include "G.h" 00037 00038 #define FORMAT_FILE "f_format" 00039 #define QUANT_FILE "f_quant" 00040 #define NULL_FILE "null" 00041 00042 static int close_old(int); 00043 static int close_new(int, int); 00044 static char CELL_DIR[100]; 00045 00046 00079 int G_close_cell(int fd) 00080 { 00081 struct fileinfo *fcb = &G__.fileinfo[fd]; 00082 00083 if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0) 00084 return -1; 00085 if (fcb->open_mode == OPEN_OLD) 00086 return close_old(fd); 00087 00088 return close_new(fd, 1); 00089 } 00090 00091 00112 int G_unopen_cell(int fd) 00113 { 00114 struct fileinfo *fcb = &G__.fileinfo[fd]; 00115 00116 if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0) 00117 return -1; 00118 if (fcb->open_mode == OPEN_OLD) 00119 return close_old(fd); 00120 else 00121 return close_new(fd, 0); 00122 } 00123 00124 static int close_old(int fd) 00125 { 00126 struct fileinfo *fcb = &G__.fileinfo[fd]; 00127 int i; 00128 00129 /* if G__.auto_mask was only allocated for reading map rows to create 00130 non-existant null rows, and not for actuall mask, free G__.mask_row 00131 if(G__.auto_mask <=0) 00132 G_free (G__.mask_buf); 00133 This is obsolete since now the mask_bus is always allocated 00134 */ 00135 00136 if (fcb->gdal) 00137 G_close_gdal_link(fcb->gdal); 00138 00139 for (i = 0; i < NULL_ROWS_INMEM; i++) 00140 G_free(fcb->NULL_ROWS[i]); 00141 G_free(fcb->null_work_buf); 00142 00143 if (fcb->cellhd.compressed) 00144 G_free(fcb->row_ptr); 00145 G_free(fcb->col_map); 00146 G_free(fcb->mapset); 00147 G_free(fcb->data); 00148 G_free(fcb->name); 00149 if (fcb->reclass_flag) 00150 G_free_reclass(&fcb->reclass); 00151 fcb->open_mode = -1; 00152 00153 if (fcb->map_type != CELL_TYPE) { 00154 G_quant_free(&fcb->quant); 00155 xdr_destroy(&fcb->xdrstream); 00156 } 00157 close(fd); 00158 00159 return 1; 00160 } 00161 00162 static int close_new(int fd, int ok) 00163 { 00164 struct fileinfo *fcb = &G__.fileinfo[fd]; 00165 int stat; 00166 struct Categories cats; 00167 struct History hist; 00168 char path[GPATH_MAX]; 00169 CELL cell_min, cell_max; 00170 int row, i, open_mode; 00171 00172 if (ok) { 00173 switch (fcb->open_mode) { 00174 case OPEN_NEW_COMPRESSED: 00175 G_debug(1, "close %s compressed", fcb->name); 00176 break; 00177 case OPEN_NEW_UNCOMPRESSED: 00178 G_debug(1, "close %s uncompressed", fcb->name); 00179 break; 00180 case OPEN_NEW_RANDOM: 00181 G_debug(1, "close %s random", fcb->name); 00182 break; 00183 } 00184 00185 if (fcb->open_mode != OPEN_NEW_RANDOM && 00186 fcb->cur_row < fcb->cellhd.rows) { 00187 G_zero_raster_buf(fcb->data, fcb->map_type); 00188 for (row = fcb->cur_row; row < fcb->cellhd.rows; row++) 00189 G_put_raster_row(fd, fcb->data, fcb->map_type); 00190 G_free(fcb->data); 00191 fcb->data = NULL; 00192 } 00193 00194 /* create path : full null file name */ 00195 G__make_mapset_element_misc("cell_misc", fcb->name); 00196 G__file_name_misc(path, "cell_misc", NULL_FILE, fcb->name, 00197 G_mapset()); 00198 remove(path); 00199 00200 if (fcb->null_cur_row > 0) { 00201 /* if temporary NULL file exists, write it into cell_misc/name/null */ 00202 int null_fd; 00203 00204 null_fd = G__open_null_write(fd); 00205 if (null_fd <= 0) 00206 return -1; 00207 if (null_fd < 1) 00208 return -1; 00209 00210 /* first finish writing null file */ 00211 /* write out the rows stored in memory */ 00212 for (row = fcb->min_null_row; row < fcb->null_cur_row; row++) 00213 G__write_null_bits(null_fd, 00214 fcb->NULL_ROWS[row - fcb->min_null_row], 00215 row, fcb->cellhd.cols, fd); 00216 00217 /* write missing rows */ 00218 if (fcb->open_mode != OPEN_NEW_RANDOM 00219 && fcb->null_cur_row < fcb->cellhd.rows) { 00220 G__init_null_bits(fcb->null_work_buf, fcb->cellhd.cols); 00221 for (row = fcb->null_cur_row; row < fcb->cellhd.rows; row++) 00222 G__write_null_bits(null_fd, fcb->null_work_buf, row, 00223 fcb->cellhd.cols, fd); 00224 } 00225 close(null_fd); 00226 00227 if (rename(fcb->null_temp_name, path)) { 00228 G_warning(_("closecell: can't move %s\nto null file %s"), 00229 fcb->null_temp_name, path); 00230 stat = -1; 00231 } 00232 else { 00233 remove(fcb->null_temp_name); 00234 } 00235 } 00236 else { 00237 remove(fcb->null_temp_name); 00238 remove(path); 00239 } /* null_cur_row > 0 */ 00240 00241 if (fcb->open_mode == OPEN_NEW_COMPRESSED) { /* auto compression */ 00242 fcb->row_ptr[fcb->cellhd.rows] = lseek(fd, 0L, SEEK_CUR); 00243 G__write_row_ptrs(fd); 00244 } 00245 00246 if (fcb->map_type != CELL_TYPE) { /* floating point map */ 00247 int cell_fd; 00248 00249 if (G__write_fp_format(fd) != 0) { 00250 G_warning(_("Error writing floating point format file for map %s"), 00251 fcb->name); 00252 stat = -1; 00253 } 00254 00255 /* now write 0-length cell file */ 00256 G__make_mapset_element("cell"); 00257 cell_fd = 00258 creat(G__file_name(path, "cell", fcb->name, fcb->mapset), 00259 0666); 00260 close(cell_fd); 00261 strcpy(CELL_DIR, "fcell"); 00262 } 00263 else { 00264 /* remove fcell/name file */ 00265 G__file_name(path, "fcell", fcb->name, fcb->mapset); 00266 remove(path); 00267 /* remove cell_misc/name/f_format */ 00268 G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, 00269 fcb->mapset); 00270 remove(path); 00271 strcpy(CELL_DIR, "cell"); 00272 close(fd); 00273 } 00274 } /* ok */ 00275 /* NOW CLOSE THE FILE DESCRIPTOR */ 00276 00277 close(fd); 00278 /* remember open_mode */ 00279 open_mode = fcb->open_mode; 00280 fcb->open_mode = -1; 00281 00282 if (fcb->data != NULL) 00283 G_free(fcb->data); 00284 00285 if (fcb->null_temp_name != NULL) { 00286 G_free(fcb->null_temp_name); 00287 fcb->null_temp_name = NULL; 00288 } 00289 00290 /* if the cell file was written to a temporary file 00291 * move this temporary file into the cell file 00292 * if the move fails, tell the user, but go ahead and create 00293 * the support files 00294 */ 00295 stat = 1; 00296 if (ok && (fcb->temp_name != NULL)) { 00297 G__file_name(path, CELL_DIR, fcb->name, fcb->mapset); 00298 remove(path); 00299 if (rename(fcb->temp_name, path)) { 00300 G_warning(_("closecell: can't move %s\nto cell file %s"), 00301 fcb->temp_name, path); 00302 stat = -1; 00303 } 00304 else { 00305 remove(fcb->temp_name); 00306 } 00307 } 00308 00309 if (fcb->temp_name != NULL) { 00310 G_free(fcb->temp_name); 00311 } 00312 00313 if (ok) { 00314 /* remove color table */ 00315 G_remove_colors(fcb->name, ""); 00316 00317 /* create a history file */ 00318 G_short_history(fcb->name, "raster", &hist); 00319 G_write_history(fcb->name, &hist); 00320 00321 /* write the range */ 00322 if (fcb->map_type == CELL_TYPE) { 00323 G_write_range(fcb->name, &fcb->range); 00324 G__remove_fp_range(fcb->name); 00325 } 00326 /*NOTE: int range for floating point maps is not written out */ 00327 else { /* if(fcb->map_type != CELL_TYPE) */ 00328 00329 G_write_fp_range(fcb->name, &fcb->fp_range); 00330 G_construct_default_range(&fcb->range); 00331 /* this range will be used to add default rule to quant structure */ 00332 } 00333 00334 if (fcb->map_type != CELL_TYPE) 00335 fcb->cellhd.format = -1; 00336 else /* CELL map */ 00337 fcb->cellhd.format = fcb->nbytes - 1; 00338 00339 /* write header file */ 00340 G_put_cellhd(fcb->name, &fcb->cellhd); 00341 00342 /* if map is floating point write the quant rules, otherwise remove f_quant */ 00343 if (fcb->map_type != CELL_TYPE) { 00344 /* DEFAULT RANGE QUANT 00345 G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max); 00346 if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max)) 00347 { 00348 G_get_range_min_max(&fcb->range, &cell_min, &cell_max); 00349 G_quant_add_rule(&fcb->quant, dcell_min, dcell_max, 00350 cell_min, cell_max); 00351 } 00352 */ 00353 G_quant_round(&fcb->quant); 00354 if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0) 00355 G_warning(_("unable to write quant file!")); 00356 } 00357 else { 00358 /* remove cell_misc/name/f_quant */ 00359 G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name, 00360 fcb->mapset); 00361 remove(path); 00362 } 00363 00364 /* create empty cats file */ 00365 G_get_range_min_max(&fcb->range, &cell_min, &cell_max); 00366 if (G_is_c_null_value(&cell_max)) 00367 cell_max = 0; 00368 G_init_cats(cell_max, (char *)NULL, &cats); 00369 G_write_cats(fcb->name, &cats); 00370 G_free_cats(&cats); 00371 00372 /* write the histogram */ 00373 /* only works for integer maps */ 00374 if ((fcb->map_type == CELL_TYPE) 00375 && (fcb->want_histogram)) { 00376 G_write_histogram_cs(fcb->name, &fcb->statf); 00377 G_free_cell_stats(&fcb->statf); 00378 } 00379 else { 00380 G_remove_histogram(fcb->name); 00381 } 00382 } /* OK */ 00383 00384 G_free(fcb->name); 00385 G_free(fcb->mapset); 00386 00387 for (i = 0; i < NULL_ROWS_INMEM; i++) 00388 G_free(fcb->NULL_ROWS[i]); 00389 G_free(fcb->null_work_buf); 00390 00391 if (fcb->map_type != CELL_TYPE) 00392 G_quant_free(&fcb->quant); 00393 00394 return stat; 00395 } 00396 00397 /* returns 0 on success, 1 on failure */ 00398 int G__write_fp_format(int fd) 00399 { 00400 struct fileinfo *fcb = &G__.fileinfo[fd]; 00401 struct Key_Value *format_kv; 00402 char path[GPATH_MAX]; 00403 int stat; 00404 00405 if (fcb->map_type == CELL_TYPE) { 00406 G_warning(_("unable to write f_format file for CELL maps")); 00407 return 0; 00408 } 00409 format_kv = G_create_key_value(); 00410 if (fcb->map_type == FCELL_TYPE) 00411 G_set_key_value("type", "float", format_kv); 00412 else 00413 G_set_key_value("type", "double", format_kv); 00414 00415 G_set_key_value("byte_order", "xdr", format_kv); 00416 00417 if (fcb->open_mode == OPEN_NEW_COMPRESSED) 00418 G_set_key_value("lzw_compression_bits", "-1", format_kv); 00419 00420 G__make_mapset_element_misc("cell_misc", fcb->name); 00421 G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset); 00422 G_write_key_value_file(path, format_kv, &stat); 00423 00424 G_free_key_value(format_kv); 00425 00426 return stat; 00427 }