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 Fi->table);
00492 Vect_close(&Map);
00493 return -1;
00494 }
00495 }
00496 else {
00497 G_warning(_("Table <%s> linked to vector map <%s> does not exist"),
00498 Fi->table, map);
00499 }
00500 }
00501 }
00502
00503 Vect_close(&Map);
00504 }
00505
00506
00507 sprintf(buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map);
00508 G_debug(3, "opendir '%s'", buf);
00509 dir = opendir(buf);
00510 if (dir == NULL) {
00511 G_warning(_("Unable to open directory '%s'"), buf);
00512 return -1;
00513 }
00514
00515 while ((ent = readdir(dir))) {
00516 G_debug(3, "file = '%s'", ent->d_name);
00517 if ((strcmp(ent->d_name, ".") == 0) ||
00518 (strcmp(ent->d_name, "..") == 0))
00519 continue;
00520 sprintf(buf, "%s/%s/vector/%s/%s", G_location_path(), G_mapset(), map,
00521 ent->d_name);
00522 G_debug(3, "delete file '%s'", buf);
00523 ret = unlink(buf);
00524 if (ret == -1) {
00525 G_warning(_("Unable to delete file '%s'"), buf);
00526 closedir(dir);
00527 return -1;
00528 }
00529 }
00530 closedir(dir);
00531
00532
00533
00534 sprintf(buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map);
00535
00536 tmp = G_tempfile();
00537
00538 G_debug(3, "rename '%s' to '%s'", buf, tmp);
00539 ret = rename(buf, tmp);
00540
00541 if (ret == -1) {
00542 G_warning(_("Unable to rename directory '%s' to '%s'"), buf, tmp);
00543 return -1;
00544 }
00545
00546 G_debug(3, "remove directory '%s'", tmp);
00547
00548 ret = rmdir(tmp);
00549 if (ret == -1) {
00550 G_warning(_("Unable to remove directory '%s'"), tmp);
00551 return -1;
00552 }
00553
00554 return 0;
00555 }
00556
00571 int Vect_copy_tables(struct Map_info *In, struct Map_info *Out, int field)
00572 {
00573 int i, n, ret, type;
00574 struct field_info *Fi, *Fin;
00575 dbDriver *driver;
00576
00577 n = Vect_get_num_dblinks(In);
00578
00579 G_debug(2, "Vect_copy_tables(): copying %d tables",n);
00580
00581 type = GV_1TABLE;
00582 if (n > 1)
00583 type = GV_MTABLE;
00584
00585 for (i = 0; i < n; i++) {
00586 Fi = Vect_get_dblink(In, i);
00587 if (Fi == NULL) {
00588 G_warning(_("Database connection not defined for layer %d"),
00589 In->dblnk->field[i].number);
00590 return -1;
00591 }
00592 if (field > 0 && Fi->number != field)
00593 continue;
00594
00595 Fin = Vect_default_field_info(Out, Fi->number, Fi->name, type);
00596 G_debug(2, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
00597 Fi->driver, Fi->database, Fi->table, Fin->driver,
00598 Fin->database, Fin->table);
00599
00600 ret =
00601 Vect_map_add_dblink(Out, Fi->number, Fi->name, Fin->table,
00602 Fi->key, Fin->database, Fin->driver);
00603 if (ret == -1) {
00604 G_warning(_("Unable to add database link for vector map <%s>"),
00605 Out->name);
00606 return -1;
00607 }
00608
00609 ret = db_copy_table(Fi->driver, Fi->database, Fi->table,
00610 Fin->driver, Vect_subst_var(Fin->database, Out),
00611 Fin->table);
00612 if (ret == DB_FAILED) {
00613 G_warning(_("Unable to copy table <%s>"), Fin->table);
00614 return -1;
00615 }
00616
00617 driver =
00618 db_start_driver_open_database(Fin->driver,
00619 Vect_subst_var(Fin->database, Out));
00620 if (driver == NULL) {
00621 G_warning(_("Unable to open database <%s> by driver <%s>"),
00622 Fin->database, Fin->driver);
00623 }
00624 else {
00625 if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK)
00626 G_warning(_("Unable to create index for table <%s>, key <%s>"),
00627 Fin->table, Fin->key);
00628
00629 db_close_database_shutdown_driver(driver);
00630 }
00631 }
00632
00633 return 0;
00634 }
00635
00649 int
00650 Vect_copy_table(struct Map_info *In, struct Map_info *Out, int field_in,
00651 int field_out, const char *field_name, int type)
00652 {
00653 return Vect_copy_table_by_cats(In, Out, field_in, field_out, field_name,
00654 type, NULL, 0);
00655 }
00656
00672 int
00673 Vect_copy_table_by_cats(struct Map_info *In, struct Map_info *Out,
00674 int field_in, int field_out, const char *field_name,
00675 int type, int *cats, int ncats)
00676 {
00677 int ret;
00678 struct field_info *Fi, *Fin;
00679 const char *name, *key;
00680
00681 G_debug(2, "Vect_copy_table(): field_in = %d field_out = %d", field_in,
00682 field_out);
00683
00684 Fi = Vect_get_field(In, field_in);
00685 if (Fi == NULL) {
00686 G_warning(_("Database connection not defined for layer %d"),
00687 field_in);
00688 return -1;
00689 }
00690
00691 if (field_name != NULL)
00692 name = field_name;
00693 else
00694 name = Fi->name;
00695
00696 Fin = Vect_default_field_info(Out, field_out, name, type);
00697 G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
00698 Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database,
00699 Fin->table);
00700
00701 ret =
00702 Vect_map_add_dblink(Out, Fin->number, Fin->name, Fin->table, Fi->key,
00703 Fin->database, Fin->driver);
00704 if (ret == -1) {
00705 G_warning(_("Unable to add database link for vector map <%s>"),
00706 Out->name);
00707 return -1;
00708 }
00709
00710 if (cats)
00711 key = Fi->key;
00712 else
00713 key = NULL;
00714
00715 ret = db_copy_table_by_ints(Fi->driver, Fi->database, Fi->table,
00716 Fin->driver, Vect_subst_var(Fin->database,
00717 Out), Fin->table,
00718 key, cats, ncats);
00719 if (ret == DB_FAILED) {
00720 G_warning(_("Unable to copy table <%s>"), Fin->table);
00721 return -1;
00722 }
00723
00724 return 0;
00725 }
00726
00736 void Vect_set_release_support(struct Map_info *Map)
00737 {
00738 Map->plus.release_support = 1;
00739 }
00740
00751 void Vect_set_category_index_update(struct Map_info *Map)
00752 {
00753 Map->plus.update_cidx = 1;
00754 }