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