|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 /*********************************************************************** 00002 * 00003 * G_close_cell(fd) 00004 * Closes and does housekeeping on an opened cell file 00005 * 00006 * G_unopen_cell(fd) 00007 * Closes and does housekeeping on an opened cell file 00008 * without creating the cell file 00009 * 00010 * parms: 00011 * int fd open cell file 00012 * 00013 * returns: 00014 * -1 on fail 00015 * 0 on success 00016 * 00017 * note: 00018 * On closing of a cell file that was open for writing, dummy cats 00019 * and history files are created. Histogram and range info are written. 00020 * 00021 **********************************************************************/ 00022 00023 #ifdef __MINGW32__ 00024 # include <windows.h> 00025 #endif 00026 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 #include <string.h> 00030 #include <unistd.h> 00031 #include <errno.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 00072 int G_close_cell(int fd) 00073 { 00074 struct fileinfo *fcb = &G__.fileinfo[fd]; 00075 00076 if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0) 00077 return -1; 00078 if (fcb->open_mode == OPEN_OLD) 00079 return close_old(fd); 00080 00081 return close_new(fd, 1); 00082 } 00083 00084 00105 int G_unopen_cell(int fd) 00106 { 00107 struct fileinfo *fcb = &G__.fileinfo[fd]; 00108 00109 G_debug(5, "G_unopen_cell()"); 00110 if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0) 00111 return -1; 00112 if (fcb->open_mode == OPEN_OLD) 00113 return close_old(fd); 00114 else 00115 return close_new(fd, 0); 00116 } 00117 00118 static int close_old(int fd) 00119 { 00120 struct fileinfo *fcb = &G__.fileinfo[fd]; 00121 int i; 00122 00123 /* if G__.auto_mask was only allocated for reading map rows to create 00124 non-existant null rows, and not for actuall mask, free G__.mask_row 00125 if(G__.auto_mask <=0) 00126 G_free (G__.mask_buf); 00127 This is obsolete since now the mask_bus is always allocated 00128 */ 00129 00130 if (fcb->gdal) 00131 G_close_gdal_link(fcb->gdal); 00132 00133 for (i = 0; i < NULL_ROWS_INMEM; i++) 00134 G_free(fcb->NULL_ROWS[i]); 00135 G_free(fcb->null_work_buf); 00136 00137 if (fcb->cellhd.compressed) 00138 G_free(fcb->row_ptr); 00139 G_free(fcb->col_map); 00140 G_free(fcb->mapset); 00141 G_free(fcb->data); 00142 G_free(fcb->name); 00143 if (fcb->reclass_flag) 00144 G_free_reclass(&fcb->reclass); 00145 fcb->open_mode = -1; 00146 00147 if (fcb->map_type != CELL_TYPE) { 00148 G_quant_free(&fcb->quant); 00149 xdr_destroy(&fcb->xdrstream); 00150 } 00151 close(fd); 00152 00153 return 1; 00154 } 00155 00156 static int close_new(int fd, int ok) 00157 { 00158 struct fileinfo *fcb = &G__.fileinfo[fd]; 00159 int stat; 00160 struct Categories cats; 00161 struct History hist; 00162 char path[GPATH_MAX]; 00163 CELL cell_min, cell_max; 00164 int row, i, open_mode; 00165 00166 if (ok) { 00167 switch (fcb->open_mode) { 00168 case OPEN_NEW_COMPRESSED: 00169 G_debug(1, "close %s compressed", fcb->name); 00170 break; 00171 case OPEN_NEW_UNCOMPRESSED: 00172 G_debug(1, "close %s uncompressed", fcb->name); 00173 break; 00174 case OPEN_NEW_RANDOM: 00175 G_debug(1, "close %s random", fcb->name); 00176 break; 00177 } 00178 00179 if (fcb->open_mode != OPEN_NEW_RANDOM && 00180 fcb->cur_row < fcb->cellhd.rows) { 00181 G_zero_raster_buf(fcb->data, fcb->map_type); 00182 for (row = fcb->cur_row; row < fcb->cellhd.rows; row++) 00183 G_put_raster_row(fd, fcb->data, fcb->map_type); 00184 G_free(fcb->data); 00185 fcb->data = NULL; 00186 } 00187 00188 /* create path : full null file name */ 00189 G__make_mapset_element_misc("cell_misc", fcb->name); 00190 G__file_name_misc(path, "cell_misc", NULL_FILE, fcb->name, 00191 G_mapset()); 00192 00193 if (access(path, F_OK) == 0) { 00194 if (remove(path) != 0) { 00195 perror(path); 00196 G_warning(_("Unable to delete prior null-cells file")); 00197 } 00198 } 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 if (close(null_fd) != 0) 00226 G_warning(_("Unable to close the null-cells file")); 00227 00228 if (rename(fcb->null_temp_name, path)) { 00229 G_warning(_("closecell: can't move [%s] to null-cells file [%s]"), 00230 fcb->null_temp_name, path); 00231 stat = -1; 00232 } 00233 else { /* if the rename() was successful I'm not sure why there'd be anything left to remove() */ 00234 if (access(fcb->null_temp_name, F_OK) == 0) { 00235 if (remove(fcb->null_temp_name) != 0) 00236 G_warning(_("Unable to delete the temporary null-cells file")); 00237 } 00238 } 00239 } 00240 else { /* no NULL data encountered */ 00241 if (access(fcb->null_temp_name, F_OK) == 0) { 00242 if (remove(fcb->null_temp_name) != 0) 00243 G_warning(_("Unable to delete the empty temporary null-cells file")); 00244 } 00245 if (access(path, F_OK) == 0) { 00246 if (remove(path) != 0) /* duplicate? */ 00247 G_warning(_("Unable to delete the prior null-cells file")); 00248 } 00249 } /* null_cur_row > 0 */ 00250 00251 00252 if (fcb->open_mode == OPEN_NEW_COMPRESSED) { /* auto compression */ 00253 fcb->row_ptr[fcb->cellhd.rows] = lseek(fd, 0L, SEEK_CUR); 00254 G__write_row_ptrs(fd); 00255 } 00256 00257 if (fcb->map_type != CELL_TYPE) { /* floating point map */ 00258 int cell_fd; 00259 00260 if (G__write_fp_format(fd) != 0) { 00261 G_warning(_("Error writing floating point format file for map %s"), 00262 fcb->name); 00263 stat = -1; 00264 } 00265 00266 /* now write 0-length cell file */ 00267 G__make_mapset_element("cell"); 00268 cell_fd = 00269 creat(G__file_name(path, "cell", fcb->name, fcb->mapset), 00270 0666); 00271 if (close(cell_fd) != 0) 00272 G_warning(_("Unable to close the 'cell' file")); 00273 00274 strcpy(CELL_DIR, "fcell"); 00275 } 00276 else { 00277 /* it's a CELL map, so remove fcell/name file if it exists */ 00278 G__file_name(path, "fcell", fcb->name, fcb->mapset); 00279 00280 if (access(path, F_OK) == 0) { 00281 if (remove(path) != 0) 00282 G_warning(_("Unable to delete prior 'fcell' file")); 00283 } 00284 00285 /* remove cell_misc/name/f_format */ 00286 G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, 00287 fcb->mapset); 00288 00289 if (access(path, F_OK) == 0) { 00290 if (remove(path) != 0) 00291 G_warning(_("Unable to delete the prior %s file"), FORMAT_FILE); 00292 } 00293 00294 strcpy(CELL_DIR, "cell"); 00295 } 00296 } /* if(ok) */ 00297 00298 /* NOW CLOSE THE FILE DESCRIPTOR */ 00299 if (close(fd) != 0) 00300 G_warning(_("Unable to close file")); 00301 00302 /* remember open_mode */ 00303 open_mode = fcb->open_mode; 00304 fcb->open_mode = -1; 00305 00306 if (fcb->data != NULL) 00307 G_free(fcb->data); 00308 00309 if (fcb->null_temp_name != NULL) { 00310 G_free(fcb->null_temp_name); 00311 fcb->null_temp_name = NULL; 00312 } 00313 00314 /* if the cell file was written to a temporary file 00315 * move this temporary file into the cell file 00316 * if the move fails, tell the user, but go ahead and create 00317 * the support files 00318 */ 00319 stat = 1; 00320 if (ok && (fcb->temp_name != NULL)) { 00321 G_debug(5, "Moving temporary cell map into main mapset..."); 00322 G__file_name(path, CELL_DIR, fcb->name, fcb->mapset); 00323 00324 if (access(path, F_OK) == 0) { 00325 if (remove(path) != 0) { 00326 perror(path); 00327 G_warning(_("Unable to delete the prior 'cell' file")); 00328 } 00329 } 00330 00331 if (rename(fcb->temp_name, path)) { 00332 G_warning(_("closecell: can't move [%s] to cell file [%s]"), 00333 fcb->temp_name, path); 00334 stat = -1; 00335 } 00336 else { /* if the rename() was successful I'm not sure why there'd be anything left to remove() */ 00337 if (access(fcb->temp_name, F_OK) == 0) { 00338 if (remove(fcb->temp_name) != 0) 00339 G_warning(_("Unable to delete the temporary 'cell' file")); 00340 } 00341 } 00342 } 00343 00344 if (fcb->temp_name != NULL) { 00345 G_free(fcb->temp_name); 00346 } 00347 00348 if (ok) { 00349 /* remove color table */ 00350 G_remove_colors(fcb->name, ""); 00351 00352 /* create a history file */ 00353 G_short_history(fcb->name, "raster", &hist); 00354 G_write_history(fcb->name, &hist); 00355 00356 /* write the range */ 00357 if (fcb->map_type == CELL_TYPE) { 00358 G_write_range(fcb->name, &fcb->range); 00359 G__remove_fp_range(fcb->name); 00360 } 00361 /*NOTE: int range for floating point maps is not written out */ 00362 else { /* if(fcb->map_type != CELL_TYPE) */ 00363 00364 G_write_fp_range(fcb->name, &fcb->fp_range); 00365 G_construct_default_range(&fcb->range); 00366 /* this range will be used to add default rule to quant structure */ 00367 } 00368 00369 if (fcb->map_type != CELL_TYPE) 00370 fcb->cellhd.format = -1; 00371 else /* CELL map */ 00372 fcb->cellhd.format = fcb->nbytes - 1; 00373 00374 /* write header file */ 00375 G_put_cellhd(fcb->name, &fcb->cellhd); 00376 00377 /* if map is floating point write the quant rules, otherwise remove f_quant */ 00378 if (fcb->map_type != CELL_TYPE) { 00379 /* DEFAULT RANGE QUANT 00380 G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max); 00381 if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max)) 00382 { 00383 G_get_range_min_max(&fcb->range, &cell_min, &cell_max); 00384 G_quant_add_rule(&fcb->quant, dcell_min, dcell_max, 00385 cell_min, cell_max); 00386 } 00387 */ 00388 G_quant_round(&fcb->quant); 00389 if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0) 00390 G_warning(_("Unable to write quant file!")); 00391 } 00392 else { 00393 /* remove cell_misc/name/f_quant */ 00394 G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name, 00395 fcb->mapset); 00396 if (access(path, F_OK) == 0) { 00397 if (remove(path) != 0) 00398 G_warning(_("Unable to delete the %s file"), QUANT_FILE); 00399 } 00400 } 00401 00402 /* create empty cats file */ 00403 G_get_range_min_max(&fcb->range, &cell_min, &cell_max); 00404 if (G_is_c_null_value(&cell_max)) 00405 cell_max = 0; 00406 G_init_cats(cell_max, (char *)NULL, &cats); 00407 G_write_cats(fcb->name, &cats); 00408 G_free_cats(&cats); 00409 00410 /* write the histogram */ 00411 /* only works for integer maps */ 00412 if ((fcb->map_type == CELL_TYPE) 00413 && (fcb->want_histogram)) { 00414 G_write_histogram_cs(fcb->name, &fcb->statf); 00415 G_free_cell_stats(&fcb->statf); 00416 } 00417 else { 00418 G_remove_histogram(fcb->name); 00419 } 00420 } /* OK */ 00421 00422 G_free(fcb->name); 00423 G_free(fcb->mapset); 00424 00425 for (i = 0; i < NULL_ROWS_INMEM; i++) 00426 G_free(fcb->NULL_ROWS[i]); 00427 G_free(fcb->null_work_buf); 00428 00429 if (fcb->map_type != CELL_TYPE) 00430 G_quant_free(&fcb->quant); 00431 00432 return stat; 00433 } 00434 00435 /* returns 0 on success, 1 on failure */ 00436 int G__write_fp_format(int fd) 00437 { 00438 struct fileinfo *fcb = &G__.fileinfo[fd]; 00439 struct Key_Value *format_kv; 00440 char path[GPATH_MAX]; 00441 int stat; 00442 00443 if (fcb->map_type == CELL_TYPE) { 00444 G_warning(_("Unable to write f_format file for CELL maps")); 00445 return 0; 00446 } 00447 format_kv = G_create_key_value(); 00448 if (fcb->map_type == FCELL_TYPE) 00449 G_set_key_value("type", "float", format_kv); 00450 else 00451 G_set_key_value("type", "double", format_kv); 00452 00453 G_set_key_value("byte_order", "xdr", format_kv); 00454 00455 if (fcb->open_mode == OPEN_NEW_COMPRESSED) 00456 G_set_key_value("lzw_compression_bits", "-1", format_kv); 00457 00458 G__make_mapset_element_misc("cell_misc", fcb->name); 00459 G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset); 00460 G_write_key_value_file(path, format_kv, &stat); 00461 00462 G_free_key_value(format_kv); 00463 00464 return stat; 00465 }