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