|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 00021 #include <stdlib.h> 00022 #include <stdio.h> 00023 #include <dirent.h> 00024 #include <string.h> 00025 #include <unistd.h> 00026 #include <errno.h> 00027 #include <sys/types.h> 00028 #include <sys/stat.h> 00029 #include <fcntl.h> 00030 #include <grass/glocale.h> 00031 #include <grass/gis.h> 00032 #include <grass/Vect.h> 00033 #include <grass/dbmi.h> 00034 #include <grass/glocale.h> 00035 00045 int Vect_copy_map_lines(struct Map_info *In, struct Map_info *Out) 00046 { 00047 int i, type, nlines, ret; 00048 struct line_pnts *Points; 00049 struct line_cats *Cats; 00050 00051 Points = Vect_new_line_struct(); 00052 Cats = Vect_new_cats_struct(); 00053 00054 if (Vect_level(In) < 1) 00055 G_fatal_error("Vect_copy_map_lines(): %s", 00056 _("input vector map is not open")); 00057 00058 ret = 0; 00059 /* Note: sometimes is important to copy on level 2 (pseudotopo centroids) 00060 * and sometimes on level 1 if build take too long time */ 00061 if (Vect_level(In) >= 2) { 00062 nlines = Vect_get_num_lines(In); 00063 for (i = 1; i <= nlines; i++) { 00064 if (!Vect_line_alive(In, i)) 00065 continue; 00066 00067 type = Vect_read_line(In, Points, Cats, i); 00068 if (type == -1) { 00069 G_warning(_("Unable to read vector map <%s>"), 00070 Vect_get_full_name(In)); 00071 ret = 1; 00072 break; 00073 } 00074 if (type == 0) 00075 continue; /* dead line */ 00076 00077 Vect_write_line(Out, type, Points, Cats); 00078 } 00079 } 00080 else { /* Level 1 */ 00081 Vect_rewind(In); 00082 while (1) { 00083 type = Vect_read_next_line(In, Points, Cats); 00084 if (type == -1) { 00085 G_warning(_("Unable to read vector map <%s>"), 00086 Vect_get_full_name(In)); 00087 ret = 1; 00088 break; 00089 } 00090 else if (type == -2) { /* EOF */ 00091 break; 00092 } 00093 else if (type == 0) { /* dead line */ 00094 continue; 00095 } 00096 Vect_write_line(Out, type, Points, Cats); 00097 } 00098 } 00099 Vect_destroy_line_struct(Points); 00100 Vect_destroy_cats_struct(Cats); 00101 00102 return ret; 00103 } 00104 00105 /* 00106 \brief Copy file 00107 00108 \param[in] src source file 00109 \param[out] dst destination file 00110 00111 \return 0 OK 00112 \return 1 error 00113 */ 00114 static int copy_file(const char *src, const char *dst) 00115 { 00116 char buf[1024]; 00117 int fd, fd2; 00118 FILE *f2; 00119 int len, len2; 00120 00121 if ((fd = open(src, O_RDONLY)) < 0) 00122 return 1; 00123 00124 /* if((fd2 = open(dst, O_CREAT|O_TRUNC|O_WRONLY)) < 0) */ 00125 if ((f2 = fopen(dst, "w")) == NULL) { 00126 close(fd); 00127 return 1; 00128 } 00129 00130 fd2 = fileno(f2); 00131 00132 while ((len = read(fd, buf, 1024)) > 0) { 00133 while (len && (len2 = write(fd2, buf, len)) >= 0) 00134 len -= len2; 00135 } 00136 00137 close(fd); 00138 /* close(fd2); */ 00139 fclose(f2); 00140 00141 if (len == -1 || len2 == -1) 00142 return 1; 00143 00144 return 0; 00145 } 00146 00159 int 00160 Vect_copy(const char *in, const char *mapset, const char *out) 00161 { 00162 int i, n, ret, type; 00163 struct Map_info In, Out; 00164 struct field_info *Fi, *Fin; 00165 char old_path[GPATH_MAX], new_path[GPATH_MAX], buf[GPATH_MAX]; 00166 struct stat info; 00167 const char *files[] = { GRASS_VECT_FRMT_ELEMENT, GRASS_VECT_COOR_ELEMENT, 00168 GRASS_VECT_HEAD_ELEMENT, GRASS_VECT_HIST_ELEMENT, 00169 GV_TOPO_ELEMENT, GV_SIDX_ELEMENT, GV_CIDX_ELEMENT, 00170 NULL 00171 }; 00172 const char *xmapset; 00173 00174 dbDriver *driver; 00175 00176 G_debug(2, "Copy vector '%s' in '%s' to '%s'", in, mapset, out); 00177 /* check for [A-Za-z][A-Za-z0-9_]* in name */ 00178 if (Vect_legal_filename(out) < 0) 00179 G_fatal_error(_("Vector map name is not SQL compliant")); 00180 00181 xmapset = G_find_vector2(in, mapset); 00182 if (!xmapset) { 00183 G_warning(_("Unable to find vector map <%s> in <%s>"), in, mapset); 00184 return -1; 00185 } 00186 mapset = xmapset; 00187 00188 /* Delete old vector if it exists */ 00189 if (G_find_vector2(out, G_mapset())) { 00190 G_warning(_("Vector map <%s> already exists and will be overwritten"), 00191 out); 00192 ret = Vect_delete(out); 00193 if (ret != 0) { 00194 G_warning(_("Unable to delete vector map <%s>"), out); 00195 return -1; 00196 } 00197 } 00198 00199 /* Copy the directory */ 00200 G__make_mapset_element(GRASS_VECT_DIRECTORY); 00201 sprintf(buf, "%s/%s", GRASS_VECT_DIRECTORY, out); 00202 G__make_mapset_element(buf); 00203 00204 i = 0; 00205 while (files[i]) { 00206 sprintf(buf, "%s/%s", in, files[i]); 00207 G__file_name(old_path, GRASS_VECT_DIRECTORY, buf, mapset); 00208 sprintf(buf, "%s/%s", out, files[i]); 00209 G__file_name(new_path, GRASS_VECT_DIRECTORY, buf, G_mapset()); 00210 00211 if (stat(old_path, &info) == 0) { /* file exists? */ 00212 G_debug(2, "copy %s to %s", old_path, new_path); 00213 if (copy_file(old_path, new_path)) { 00214 G_warning(_("Unable to copy vector map <%s> to <%s>"), 00215 old_path, new_path); 00216 } 00217 } 00218 i++; 00219 } 00220 00221 G__file_name(old_path, GRASS_VECT_DIRECTORY, in, mapset); 00222 G__file_name(new_path, GRASS_VECT_DIRECTORY, out, G_mapset()); 00223 00224 /* Open input */ 00225 Vect_set_open_level(1); 00226 Vect_open_old_head(&In, in, mapset); 00227 00228 if (In.format != GV_FORMAT_NATIVE) { /* Done */ 00229 Vect_close(&In); 00230 return 0; 00231 } 00232 00233 /* Open output */ 00234 Vect_open_update_head(&Out, out, G_mapset()); 00235 00236 /* Copy tables */ 00237 n = Vect_get_num_dblinks(&In); 00238 type = GV_1TABLE; 00239 if (n > 1) 00240 type = GV_MTABLE; 00241 for (i = 0; i < n; i++) { 00242 Fi = Vect_get_dblink(&In, i); 00243 if (Fi == NULL) { 00244 G_warning(_("Database connection not defined for layer %d"), 00245 In.dblnk->field[i].number); 00246 Vect_close(&In); 00247 Vect_close(&Out); 00248 return -1; 00249 } 00250 Fin = Vect_default_field_info(&Out, Fi->number, Fi->name, type); 00251 G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 00252 Fi->driver, Fi->database, Fi->table, Fin->driver, 00253 Fin->database, Fin->table); 00254 Vect_map_add_dblink(&Out, Fi->number, Fi->name, Fin->table, Fi->key, 00255 Fin->database, Fin->driver); 00256 00257 ret = db_copy_table(Fi->driver, Fi->database, Fi->table, 00258 Fin->driver, Vect_subst_var(Fin->database, &Out), 00259 Fin->table); 00260 if (ret == DB_FAILED) { 00261 G_warning(_("Unable to copy table <%s>"), Fin->table); 00262 Vect_close(&In); 00263 Vect_close(&Out); 00264 return -1; 00265 } 00266 00267 driver = 00268 db_start_driver_open_database(Fin->driver, 00269 Vect_subst_var(Fin->database, 00270 &Out)); 00271 if (driver == NULL) { 00272 G_warning(_("Unable to open database <%s> by driver <%s>"), 00273 Fin->database, Fin->driver); 00274 } 00275 else { 00276 if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK) 00277 G_warning(_("Unable to create index for table <%s>, key <%s>"), 00278 Fi->table, Fi->key); 00279 00280 db_close_database_shutdown_driver(driver); 00281 } 00282 } 00283 00284 Vect_close(&In); 00285 Vect_close(&Out); 00286 00287 return 0; 00288 } 00289 00304 int Vect_rename(const char *in, const char *out) 00305 { 00306 int i, n, ret, type; 00307 struct Map_info Map; 00308 struct field_info *Fin, *Fout; 00309 int *fields; 00310 dbDriver *driver; 00311 00312 G_debug(2, "Rename vector '%s' to '%s'", in, out); 00313 /* check for [A-Za-z][A-Za-z0-9_]* in name */ 00314 if (Vect_legal_filename(out) < 0) 00315 G_fatal_error(_("Vector map name is not SQL compliant")); 00316 00317 /* Delete old vector if it exists */ 00318 if (G_find_vector2(out, G_mapset())) { 00319 G_warning(_("Vector map <%s> already exists and will be overwritten"), 00320 out); 00321 Vect_delete(out); 00322 } 00323 00324 /* Move the directory */ 00325 ret = G_rename(GRASS_VECT_DIRECTORY, in, out); 00326 00327 if (ret == 0) { 00328 G_warning(_("Vector map <%s> not found"), in); 00329 return -1; 00330 } 00331 else if (ret == -1) { 00332 G_warning(_("Unable to copy vector map <%s> to <%s>"), in, out); 00333 return -1; 00334 } 00335 00336 /* Rename all tables if the format is native */ 00337 Vect_set_open_level(1); 00338 Vect_open_update_head(&Map, out, G_mapset()); 00339 00340 if (Map.format != GV_FORMAT_NATIVE) { /* Done */ 00341 Vect_close(&Map); 00342 return 0; 00343 } 00344 00345 /* Copy tables */ 00346 n = Vect_get_num_dblinks(&Map); 00347 type = GV_1TABLE; 00348 if (n > 1) 00349 type = GV_MTABLE; 00350 00351 /* Make the list of fields */ 00352 fields = (int *)G_malloc(n * sizeof(int)); 00353 00354 for (i = 0; i < n; i++) { 00355 Fin = Vect_get_dblink(&Map, i); 00356 00357 fields[i] = Fin->number; 00358 } 00359 00360 for (i = 0; i < n; i++) { 00361 G_debug(3, "field[%d] = %d", i, fields[i]); 00362 00363 Fin = Vect_get_field(&Map, fields[i]); 00364 if (Fin == NULL) { 00365 G_warning(_("Database connection not defined for layer %d"), 00366 fields[i]); 00367 Vect_close(&Map); 00368 return -1; 00369 } 00370 00371 Fout = Vect_default_field_info(&Map, Fin->number, Fin->name, type); 00372 G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 00373 Fin->driver, Fin->database, Fin->table, Fout->driver, 00374 Fout->database, Fout->table); 00375 00376 /* TODO: db_rename_table instead of db_copy_table */ 00377 ret = db_copy_table(Fin->driver, Fin->database, Fin->table, 00378 Fout->driver, Vect_subst_var(Fout->database, 00379 &Map), Fout->table); 00380 00381 if (ret == DB_FAILED) { 00382 G_warning(_("Unable to copy table <%s>"), Fin->table); 00383 Vect_close(&Map); 00384 return -1; 00385 } 00386 00387 /* Change the link */ 00388 Vect_map_del_dblink(&Map, Fin->number); 00389 00390 Vect_map_add_dblink(&Map, Fout->number, Fout->name, Fout->table, 00391 Fin->key, Fout->database, Fout->driver); 00392 00393 /* Delete old table */ 00394 ret = db_delete_table(Fin->driver, Fin->database, Fin->table); 00395 if (ret == DB_FAILED) { 00396 G_warning(_("Unable to delete table <%s>"), Fin->table); 00397 Vect_close(&Map); 00398 return -1; 00399 } 00400 00401 driver = 00402 db_start_driver_open_database(Fout->driver, 00403 Vect_subst_var(Fout->database, 00404 &Map)); 00405 if (driver == NULL) { 00406 G_warning(_("Unable to open database <%s> by driver <%s>"), 00407 Fout->database, Fout->driver); 00408 } 00409 else { 00410 if (db_create_index2(driver, Fout->table, Fin->key) != DB_OK) 00411 G_warning(_("Unable to create index for table <%s>, key <%s>"), 00412 Fout->table, Fout->key); 00413 00414 db_close_database_shutdown_driver(driver); 00415 } 00416 } 00417 00418 Vect_close(&Map); 00419 free(fields); 00420 00421 return 0; 00422 } 00423 00432 int Vect_delete(const char *map) 00433 { 00434 int i, n, ret; 00435 struct Map_info Map; 00436 struct field_info *Fi; 00437 char buf[GPATH_MAX]; 00438 DIR *dir; 00439 struct dirent *ent; 00440 const char *tmp; 00441 00442 G_debug(3, "Delete vector '%s'", map); 00443 00444 if (map == NULL || strlen(map) == 0) { 00445 G_warning(_("Invalid vector map name <%s>"), map ? map : "null"); 00446 return -1; 00447 } 00448 00449 sprintf(buf, "%s/%s/%s/%s/%s/%s", G_gisdbase(), G_location(), 00450 G_mapset(), GRASS_VECT_DIRECTORY, map, GRASS_VECT_DBLN_ELEMENT); 00451 00452 G_debug(1, "dbln file: %s", buf); 00453 00454 if (access(buf, F_OK) == 0) { 00455 /* Open input */ 00456 Vect_set_open_level(1); /* Topo not needed */ 00457 ret = Vect_open_old_head(&Map, map, G_mapset()); 00458 if (ret < 1) { 00459 G_warning(_("Unable to open header file for vector map <%s>"), 00460 map); 00461 return -1; 00462 } 00463 00464 /* Delete all tables, NOT external (OGR) */ 00465 if (Map.format == GV_FORMAT_NATIVE) { 00466 00467 n = Vect_get_num_dblinks(&Map); 00468 for (i = 0; i < n; i++) { 00469 Fi = Vect_get_dblink(&Map, i); 00470 if (Fi == NULL) { 00471 G_warning(_("Database connection not defined for layer %d"), 00472 Map.dblnk->field[i].number); 00473 Vect_close(&Map); 00474 return -1; 00475 } 00476 G_debug(3, "Delete drv:db:table '%s:%s:%s'", Fi->driver, 00477 Fi->database, Fi->table); 00478 00479 ret = db_table_exists(Fi->driver, Fi->database, Fi->table); 00480 if (ret == -1) { 00481 G_warning(_("Unable to find table <%s> linked to vector map <%s>"), 00482 Fi->table, map); 00483 Vect_close(&Map); 00484 return -1; 00485 } 00486 00487 if (ret == 1) { 00488 ret = 00489 db_delete_table(Fi->driver, Fi->database, Fi->table); 00490 if (ret == DB_FAILED) { 00491 G_warning(_("Unable to delete table <%s>"), 00492 Fi->table); 00493 Vect_close(&Map); 00494 return -1; 00495 } 00496 } 00497 else { 00498 G_warning(_("Table <%s> linked to vector map <%s> does not exist"), 00499 Fi->table, map); 00500 } 00501 } 00502 } 00503 00504 Vect_close(&Map); 00505 } 00506 00507 /* Delete all files from vector/name directory */ 00508 sprintf(buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map); 00509 G_debug(3, "opendir '%s'", buf); 00510 dir = opendir(buf); 00511 if (dir == NULL) { 00512 G_warning(_("Unable to open directory '%s'"), buf); 00513 return -1; 00514 } 00515 00516 while ((ent = readdir(dir))) { 00517 G_debug(3, "file = '%s'", ent->d_name); 00518 if ((strcmp(ent->d_name, ".") == 0) || 00519 (strcmp(ent->d_name, "..") == 0)) 00520 continue; 00521 sprintf(buf, "%s/%s/vector/%s/%s", G_location_path(), G_mapset(), map, 00522 ent->d_name); 00523 G_debug(3, "delete file '%s'", buf); 00524 ret = remove(buf); 00525 if (ret == -1) { 00526 G_warning(_("Unable to delete file '%s'. Reason: %s"), buf, strerror(errno)); 00527 closedir(dir); 00528 return -1; 00529 } 00530 } 00531 closedir(dir); 00532 00533 /* NFS can create .nfsxxxxxxxx files for those deleted 00534 * -> we have to move the directory to ./tmp before it is deleted */ 00535 sprintf(buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map); 00536 00537 tmp = G_tempfile(); 00538 00539 G_debug(3, "rename '%s' to '%s'", buf, tmp); 00540 ret = rename(buf, tmp); 00541 00542 if (ret == -1) { 00543 G_warning(_("Unable to rename directory '%s' to '%s'. Reason: %s"), buf, tmp, strerror(errno)); 00544 return -1; 00545 } 00546 00547 G_debug(3, "remove directory '%s'", tmp); 00548 /* Warning: remove() fails on Windows */ 00549 ret = rmdir(tmp); 00550 if (ret == -1) { 00551 G_warning(_("Unable to remove directory '%s'. Reason: %s"), tmp, strerror(errno)); 00552 return -1; 00553 } 00554 00555 return 0; 00556 } 00557 00572 int Vect_copy_tables(struct Map_info *In, struct Map_info *Out, int field) 00573 { 00574 int i, n, ret, type; 00575 struct field_info *Fi, *Fin; 00576 dbDriver *driver; 00577 00578 n = Vect_get_num_dblinks(In); 00579 00580 G_debug(2, "Vect_copy_tables(): copying %d tables",n); 00581 00582 type = GV_1TABLE; 00583 if (n > 1) 00584 type = GV_MTABLE; 00585 00586 for (i = 0; i < n; i++) { 00587 Fi = Vect_get_dblink(In, i); 00588 if (Fi == NULL) { 00589 G_warning(_("Database connection not defined for layer %d"), 00590 In->dblnk->field[i].number); 00591 return -1; 00592 } 00593 if (field > 0 && Fi->number != field) 00594 continue; 00595 00596 Fin = Vect_default_field_info(Out, Fi->number, Fi->name, type); 00597 G_debug(2, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 00598 Fi->driver, Fi->database, Fi->table, Fin->driver, 00599 Fin->database, Fin->table); 00600 00601 ret = 00602 Vect_map_add_dblink(Out, Fi->number, Fi->name, Fin->table, 00603 Fi->key, Fin->database, Fin->driver); 00604 if (ret == -1) { 00605 G_warning(_("Unable to add database link for vector map <%s>"), 00606 Out->name); 00607 return -1; 00608 } 00609 00610 ret = db_copy_table(Fi->driver, Fi->database, Fi->table, 00611 Fin->driver, Vect_subst_var(Fin->database, Out), 00612 Fin->table); 00613 if (ret == DB_FAILED) { 00614 G_warning(_("Unable to copy table <%s>"), Fin->table); 00615 return -1; 00616 } 00617 00618 driver = 00619 db_start_driver_open_database(Fin->driver, 00620 Vect_subst_var(Fin->database, Out)); 00621 if (driver == NULL) { 00622 G_warning(_("Unable to open database <%s> by driver <%s>"), 00623 Fin->database, Fin->driver); 00624 } 00625 else { 00626 if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK) 00627 G_warning(_("Unable to create index for table <%s>, key <%s>"), 00628 Fin->table, Fin->key); 00629 00630 db_close_database_shutdown_driver(driver); 00631 } 00632 } 00633 00634 return 0; 00635 } 00636 00650 int 00651 Vect_copy_table(struct Map_info *In, struct Map_info *Out, int field_in, 00652 int field_out, const char *field_name, int type) 00653 { 00654 return Vect_copy_table_by_cats(In, Out, field_in, field_out, field_name, 00655 type, NULL, 0); 00656 } 00657 00673 int 00674 Vect_copy_table_by_cats(struct Map_info *In, struct Map_info *Out, 00675 int field_in, int field_out, const char *field_name, 00676 int type, int *cats, int ncats) 00677 { 00678 int ret; 00679 struct field_info *Fi, *Fin; 00680 const char *name, *key; 00681 00682 G_debug(2, "Vect_copy_table(): field_in = %d field_out = %d", field_in, 00683 field_out); 00684 00685 Fi = Vect_get_field(In, field_in); 00686 if (Fi == NULL) { 00687 G_warning(_("Database connection not defined for layer %d"), 00688 field_in); 00689 return -1; 00690 } 00691 00692 if (field_name != NULL) 00693 name = field_name; 00694 else 00695 name = Fi->name; 00696 00697 Fin = Vect_default_field_info(Out, field_out, name, type); 00698 G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 00699 Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, 00700 Fin->table); 00701 00702 ret = 00703 Vect_map_add_dblink(Out, Fin->number, Fin->name, Fin->table, Fi->key, 00704 Fin->database, Fin->driver); 00705 if (ret == -1) { 00706 G_warning(_("Unable to add database link for vector map <%s>"), 00707 Out->name); 00708 return -1; 00709 } 00710 00711 if (cats) 00712 key = Fi->key; 00713 else 00714 key = NULL; 00715 00716 ret = db_copy_table_by_ints(Fi->driver, Fi->database, Fi->table, 00717 Fin->driver, Vect_subst_var(Fin->database, 00718 Out), Fin->table, 00719 key, cats, ncats); 00720 if (ret == DB_FAILED) { 00721 G_warning(_("Unable to copy table <%s>"), Fin->table); 00722 return -1; 00723 } 00724 00725 return 0; 00726 } 00727 00737 void Vect_set_release_support(struct Map_info *Map) 00738 { 00739 Map->plus.release_support = 1; 00740 } 00741 00752 void Vect_set_category_index_update(struct Map_info *Map) 00753 { 00754 Map->plus.update_cidx = 1; 00755 }