GRASS Programmer's Manual 6.4.1(2011)
|
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 /* Note: sometimes is important to copy on level 2 (pseudotopo centroids) 00059 * and sometimes on level 1 if build take too long time */ 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; /* dead line */ 00075 00076 Vect_write_line(Out, type, Points, Cats); 00077 } 00078 } 00079 else { /* Level 1 */ 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) { /* EOF */ 00090 break; 00091 } 00092 else if (type == 0) { /* dead line */ 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 \brief Copy file 00106 00107 \param[in] src source file 00108 \param[out] dst destination file 00109 00110 \return 0 OK 00111 \return 1 error 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 /* if((fd2 = open(dst, O_CREAT|O_TRUNC|O_WRONLY)) < 0) */ 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 /* close(fd2); */ 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 /* check for [A-Za-z][A-Za-z0-9_]* in name */ 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 /* Delete old vector if it exists */ 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 /* Copy the directory */ 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) { /* file exists? */ 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 /* Open input */ 00224 Vect_set_open_level(1); 00225 Vect_open_old_head(&In, in, mapset); 00226 00227 if (In.format != GV_FORMAT_NATIVE) { /* Done */ 00228 Vect_close(&In); 00229 return 0; 00230 } 00231 00232 /* Open output */ 00233 Vect_open_update_head(&Out, out, G_mapset()); 00234 00235 /* Copy tables */ 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 /* check for [A-Za-z][A-Za-z0-9_]* in name */ 00313 if (Vect_legal_filename(out) < 0) 00314 G_fatal_error(_("Vector map name is not SQL compliant")); 00315 00316 /* Delete old vector if it exists */ 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 /* Move the directory */ 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 /* Rename all tables if the format is native */ 00336 Vect_set_open_level(1); 00337 Vect_open_update_head(&Map, out, G_mapset()); 00338 00339 if (Map.format != GV_FORMAT_NATIVE) { /* Done */ 00340 Vect_close(&Map); 00341 return 0; 00342 } 00343 00344 /* Copy tables */ 00345 n = Vect_get_num_dblinks(&Map); 00346 type = GV_1TABLE; 00347 if (n > 1) 00348 type = GV_MTABLE; 00349 00350 /* Make the list of fields */ 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 /* TODO: db_rename_table instead of db_copy_table */ 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 /* Change the link */ 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 /* Delete old table */ 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 /* Open input */ 00455 Vect_set_open_level(1); /* Topo not needed */ 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 /* Delete all tables, NOT external (OGR) */ 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 /* Delete all files from vector/name directory */ 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 /* NFS can create .nfsxxxxxxxx files for those deleted 00533 * -> we have to move the directory to ./tmp before it is deleted */ 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 /* Warning: remove() fails on Windows */ 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 }