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             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;       /* dead line */
00072 
00073             Vect_write_line(Out, type, Points, Cats);
00074         }
00075     }
00076     else {                      /* Level 1 */
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) {      /* EOF */
00087                 break;
00088             }
00089             else if (type == 0) {       /* dead line */
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    \brief Copy file
00103 
00104    \param[in] src source file
00105    \param[out] dst destination file
00106 
00107    \return 0 OK
00108    \return 1 error
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     /* if((fd2 = open(dst, O_CREAT|O_TRUNC|O_WRONLY)) < 0) */
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     /* close(fd2); */
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     /* check for [A-Za-z][A-Za-z0-9_]* in name */
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     /* Delete old vector if it exists */
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     /* Copy the directory */
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) {       /* file exists? */
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     /* Open input */
00221     Vect_set_open_level(1);
00222     Vect_open_old_head(&In, in, mapset);
00223 
00224     if (In.format != GV_FORMAT_NATIVE) {        /* Done */
00225         Vect_close(&In);
00226         return 0;
00227     }
00228 
00229     /* Open output */
00230     Vect_open_update_head(&Out, out, G_mapset());
00231 
00232     /* Copy tables */
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     /* check for [A-Za-z][A-Za-z0-9_]* in name */
00310     if (Vect_legal_filename(out) < 0)
00311         G_fatal_error(_("Vector map name is not SQL compliant"));
00312 
00313     /* Delete old vector if it exists */
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     /* Move the directory */
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     /* Rename all tables if the format is native */
00333     Vect_set_open_level(1);
00334     Vect_open_update_head(&Map, out, G_mapset());
00335 
00336     if (Map.format != GV_FORMAT_NATIVE) {       /* Done */
00337         Vect_close(&Map);
00338         return 0;
00339     }
00340 
00341     /* Copy tables */
00342     n = Vect_get_num_dblinks(&Map);
00343     type = GV_1TABLE;
00344     if (n > 1)
00345         type = GV_MTABLE;
00346 
00347     /* Make the list of fields */
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         /* TODO: db_rename_table instead of db_copy_table */
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         /* Change the link */
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         /* Delete old table */
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         /* Open input */
00452         Vect_set_open_level(1); /* Topo not needed */
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         /* Delete all tables, NOT external (OGR) */
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     /* Delete all files from vector/name directory */
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     /* NFS can create .nfsxxxxxxxx files for those deleted 
00529      *  -> we have to move the directory to ./tmp before it is deleted */
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     /* Warning: remove() fails on Windows */
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 }

Generated on Thu Jul 16 13:21:17 2009 for GRASS Programmer's Manual by  doxygen 1.5.6