map.c

Go to the documentation of this file.
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 }