map.c

Go to the documentation of this file.
00001 /*
00002 ****************************************************************************
00003 *
00004 * MODULE:       Vector library 
00005 *               
00006 * AUTHOR(S):    Radim Blazek
00007 *
00008 * PURPOSE:      Higher level functions for reading/writing/manipulating vectors.
00009 *
00010 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00011 *
00012 *               This program is free software under the GNU General Public
00013 *               License (>=v2). Read the file COPYING that comes with GRASS
00014 *               for details.
00015 *
00016 *****************************************************************************/
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <dirent.h>
00020 #include <string.h>
00021 #include <unistd.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <fcntl.h>
00025 #include <grass/glocale.h>
00026 #include <grass/gis.h>
00027 #include <grass/Vect.h>
00028 #include <grass/dbmi.h>
00029 
00036 int 
00037 Vect_copy_map_lines ( struct Map_info *In, struct Map_info *Out )
00038 {
00039     int    i, type, nlines, ret;
00040     struct line_pnts *Points;
00041     struct line_cats *Cats;
00042 
00043     Points = Vect_new_line_struct ();
00044     Cats = Vect_new_cats_struct ();
00045    
00046     if ( Vect_level ( In ) < 1 )
00047         G_fatal_error ("Vect_copy_map_lines(): input vector is not open");
00048     
00049     ret = 0;
00050     /* Note: sometimes is important to copy on level 2 (pseudotopo centroids) 
00051      *       and sometimes on level 1 if build take too long time */
00052     if ( Vect_level ( In ) >= 2 ) { 
00053         nlines = Vect_get_num_lines ( In );
00054         for ( i = 1; i <= nlines; i++ ) {
00055             type =  Vect_read_line (In, Points, Cats, i);
00056             if ( type == -1 ) {
00057                 G_warning ("Cannot read vector file\n" );
00058                 ret = 1;
00059                 break;
00060             } 
00061             if ( type == 0 ) continue; /* dead line */
00062 
00063             Vect_write_line ( Out, type, Points, Cats );
00064         }
00065     } else {  /* Level 1 */
00066         Vect_rewind ( In );
00067         while ( 1 ) {
00068             type =  Vect_read_next_line (In, Points, Cats);
00069             if ( type == -1 ) {
00070                 G_warning ("Cannot read vector file\n" );
00071                 ret = 1;
00072                 break;
00073             } else if ( type == -2 ) { /* EOF */ 
00074                 break;
00075             } else if ( type == 0 ) { /* dead line */
00076                 continue;
00077             }
00078             Vect_write_line ( Out, type, Points, Cats );
00079         }
00080     }
00081     Vect_destroy_line_struct (Points);
00082     Vect_destroy_cats_struct (Cats);
00083 
00084     return ret;
00085 }
00086 
00087 /* Copy file
00088  * returns 0 OK
00089  *         1 error
00090  */
00091 int
00092 copy_file(const char *src, const char *dst)
00093 {
00094     char buf[1024];
00095     int fd, fd2;
00096     FILE *f2; 
00097     unsigned int len, len2;
00098 
00099     if((fd = open(src, O_RDONLY)) < 0) return 1;
00100     
00101     /* if((fd2 = open(dst, O_CREAT|O_TRUNC|O_WRONLY)) < 0) */
00102     if((f2 = fopen(dst, "w")) == NULL)
00103     {
00104         close(fd);
00105         return 1;
00106     }   
00107 
00108     fd2 = fileno(f2);
00109 
00110     while((len = read(fd, buf, 1024)) > 0)
00111     {
00112         while(len && (len2 = write(fd2, buf, len)) >= 0)
00113            len -= len2;
00114     }
00115 
00116     close(fd);
00117     /* close(fd2); */
00118     fclose(f2);
00119 
00120     if ( len == -1 || len2 == -1  ) return 1;
00121 
00122     return 0;
00123 }
00124 
00134 int 
00135 Vect_copy ( char *in, char *mapset, char *out, FILE *msgout )
00136 {
00137     int i, n, ret, type;
00138     struct Map_info In, Out;
00139     struct field_info *Fi, *Fin;
00140     char   old_path[1000], new_path[1000], buf[1000]; 
00141     struct stat info;
00142     char *files[] = { GRASS_VECT_FRMT_ELEMENT, GRASS_VECT_COOR_ELEMENT,
00143                       GRASS_VECT_HEAD_ELEMENT, GRASS_VECT_HIST_ELEMENT,
00144                       GV_TOPO_ELEMENT, GV_SIDX_ELEMENT, GV_CIDX_ELEMENT,
00145                       NULL };
00146       
00147     dbDriver *driver;
00148 
00149     G_debug (2, "Copy vector '%s' in '%s' to '%s'", in, mapset, out );
00150     /* check for [A-Za-z][A-Za-z0-9_]* in name */
00151     if (Vect_legal_filename(out) < 0 )
00152        G_fatal_error ( _("Map name is not SQL compliant.") );
00153 
00154     /* Delete old vector if it exists */
00155     if ( G_find_vector2(out, G_mapset()) ) {
00156         G_warning (_("The vector '%s' already exists and will be overwritten."), out);
00157         ret = Vect_delete ( out );
00158         if ( ret != 0 ) {
00159             G_warning ( "Cannot copy vector" );
00160             return -1;
00161         }
00162     }
00163 
00164     /* Copy the directory */
00165     G__make_mapset_element ( GRASS_VECT_DIRECTORY );
00166     sprintf ( buf, "%s/%s", GRASS_VECT_DIRECTORY, out );
00167     G__make_mapset_element ( buf );
00168 
00169     i = 0;
00170     while ( files[i] )
00171     {
00172         sprintf ( buf, "%s/%s", in, files[i] );
00173         G__file_name (old_path, GRASS_VECT_DIRECTORY, buf, mapset );
00174         sprintf ( buf, "%s/%s", out, files[i] );
00175         G__file_name (new_path, GRASS_VECT_DIRECTORY, buf, G_mapset() );
00176 
00177         if ( stat (old_path, &info) == 0)       /* file exists? */
00178         {
00179            G_debug (2, "copy %s to %s", old_path, new_path );
00180             if ( copy_file ( old_path, new_path ) )
00181             {
00182                 G_warning ( "Cannot copy vector file '%s' to '%s'", old_path, new_path );
00183             }
00184         }
00185         i++;
00186     }
00187 
00188     G__file_name (old_path, GRASS_VECT_DIRECTORY, in, mapset );
00189     G__file_name (new_path, GRASS_VECT_DIRECTORY, out, G_mapset() );
00190 
00191     /* Open input */
00192     Vect_set_open_level (1);
00193     Vect_open_old_head (&In, in, mapset);
00194 
00195     if ( In.format != GV_FORMAT_NATIVE ) { /* Done */
00196         Vect_close ( &In );
00197         return 0;
00198     }
00199     
00200     /* Open output */
00201     Vect_open_update_head ( &Out, out, G_mapset() );
00202 
00203     /* Copy tables */
00204     n = Vect_get_num_dblinks ( &In );
00205     type = GV_1TABLE;
00206     if ( n > 1 ) type = GV_MTABLE;
00207     for ( i = 0; i < n; i++ ) {
00208         Fi = Vect_get_dblink ( &In, i );
00209         if ( Fi == NULL ) {
00210             G_warning ( "Cannot get db link info" );
00211             Vect_close ( &In );
00212             Vect_close ( &Out );
00213             return -1;
00214         }
00215         Fin = Vect_default_field_info ( &Out, Fi->number, Fi->name, type );
00216         G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00217                       Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
00218         Vect_map_add_dblink ( &Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver);
00219         
00220         ret = db_copy_table ( Fi->driver, Fi->database, Fi->table, 
00221                     Fin->driver, Vect_subst_var(Fin->database,&Out), Fin->table );
00222         if ( ret == DB_FAILED ) {
00223             G_warning ( "Cannot copy table" );
00224             Vect_close ( &In );
00225             Vect_close ( &Out );
00226             return -1;
00227         }
00228 
00229         driver = db_start_driver_open_database ( Fin->driver, Vect_subst_var(Fin->database,&Out) );
00230         if ( driver == NULL ) {
00231             G_warning ( "Cannot open database -> create index" );
00232         } else {
00233             if ( db_create_index2(driver, Fin->table, Fi->key ) != DB_OK )
00234                 G_warning ( "Cannot create index" );
00235 
00236             db_close_database_shutdown_driver ( driver );
00237         }
00238     }
00239     
00240     Vect_close ( &In );
00241     Vect_close ( &Out );
00242 
00243     return 0;
00244 }
00245 
00256 int 
00257 Vect_rename ( char *in, char *out, FILE *msgout )
00258 {
00259     int i, n, ret, type;
00260     struct Map_info Map;
00261     struct field_info *Fin, *Fout;
00262     int *fields;
00263     dbDriver *driver;
00264 
00265     G_debug (2, "Rename vector '%s' to '%s'", in, out );
00266     /* check for [A-Za-z][A-Za-z0-9_]* in name */
00267     if (Vect_legal_filename(out) < 0 )
00268        G_fatal_error ( _("Map name is not SQL compliant.") );
00269 
00270     /* Delete old vector if it exists */
00271     if ( G_find_vector2(out, G_mapset()) ) {
00272         G_warning (_("The vector '%s' already exists and will be overwritten."), out);
00273         Vect_delete ( out );
00274     }
00275 
00276     /* Move the directory */
00277     ret = G_rename ( GRASS_VECT_DIRECTORY, in, out );
00278 
00279     if ( ret == 0 ) {
00280         G_warning (_("Input vector '%s' not found"), in );
00281         return -1;
00282     } else if ( ret == -1 ) {
00283         G_warning (_("Cannot copy vector '%s' to '%s'"), in, out );
00284         return -1;
00285     }
00286 
00287     /* Rename all tables if the format is native */
00288     Vect_set_open_level (1);
00289     Vect_open_update_head ( &Map, out, G_mapset() );
00290 
00291     if ( Map.format != GV_FORMAT_NATIVE ) { /* Done */
00292         Vect_close ( &Map );
00293         return 0;
00294     }
00295 
00296     /* Copy tables */
00297     n = Vect_get_num_dblinks ( &Map );
00298     type = GV_1TABLE;
00299     if ( n > 1 ) type = GV_MTABLE;
00300 
00301     /* Make the list of fields */
00302     fields = (int *) G_malloc ( n * sizeof(int) );
00303 
00304     for ( i = 0; i < n; i++ ) {
00305         Fin = Vect_get_dblink ( &Map, i );
00306 
00307         fields[i] = Fin->number;
00308     }
00309     
00310     for ( i = 0; i < n; i++ ) {
00311         G_debug (3, "field[%d] = %d", i, fields[i] );
00312         
00313         Fin = Vect_get_field ( &Map, fields[i] );
00314         if ( Fin == NULL ) {
00315             G_warning ( "Cannot get db link info" );
00316             Vect_close ( &Map );
00317             return -1;
00318         }
00319 
00320         Fout = Vect_default_field_info ( &Map, Fin->number, Fin->name, type );
00321         G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00322                       Fin->driver, Fin->database, Fin->table, Fout->driver, Fout->database, Fout->table );
00323 
00324         /* TODO: db_rename_table instead of db_copy_table */
00325         ret = db_copy_table ( Fin->driver, Fin->database, Fin->table, 
00326                     Fout->driver, Vect_subst_var(Fout->database,&Map), Fout->table );
00327 
00328         if ( ret == DB_FAILED ) {
00329             G_warning ( "Cannot copy table" );
00330             Vect_close ( &Map );
00331             return -1;
00332         }
00333 
00334         /* Change the link */
00335         Vect_map_del_dblink ( &Map, Fin->number );
00336         
00337         Vect_map_add_dblink ( &Map, Fout->number, Fout->name, Fout->table, Fin->key, 
00338                                     Fout->database, Fout->driver);
00339 
00340         /* Delete old table */
00341         ret = db_delete_table ( Fin->driver, Fin->database, Fin->table );
00342         if ( ret == DB_FAILED ) {
00343             G_warning ( "Cannot delete table" );
00344             Vect_close ( &Map );
00345             return -1;
00346         }
00347 
00348         driver = db_start_driver_open_database ( Fout->driver, Vect_subst_var(Fout->database, &Map) );
00349         if ( driver == NULL ) {
00350             G_warning ( "Cannot open database -> create index" );
00351         } else {
00352             if ( db_create_index2(driver, Fout->table, Fin->key ) != DB_OK )
00353                 G_warning ( "Cannot create index" );
00354 
00355             db_close_database_shutdown_driver ( driver );
00356         }
00357     }
00358     
00359     Vect_close ( &Map );
00360     free ( fields );
00361 
00362     return 0;
00363 }
00364 
00371 int 
00372 Vect_delete ( char *map )
00373 {
00374     int i, n, ret;
00375     struct Map_info Map;
00376     struct field_info *Fi;
00377     char   buf[5000];
00378     DIR    *dir;
00379     struct dirent *ent; 
00380     char *tmp;
00381 
00382     G_debug (3, "Delete vector '%s'", map );
00383 
00384     G_chop ( map );
00385 
00386     if ( map == NULL || strlen ( map ) == 0 ) {
00387         G_warning ( "Wrong map name '%s'", map );
00388         return -1;
00389     }
00390 
00391     sprintf ( buf, "%s/%s/%s/%s/%s/%s", G_gisdbase(), G_location(), 
00392               G_mapset(), GRASS_VECT_DIRECTORY, map, 
00393               GRASS_VECT_DBLN_ELEMENT );
00394 
00395     G_debug (1, "dbln file: %s", buf);  
00396 
00397     if ( access(buf,F_OK) == 0 )
00398     {
00399         /* Open input */
00400         Vect_set_open_level (1); /* Topo not needed */
00401         ret = Vect_open_old_head (&Map, map, G_mapset());
00402         if ( ret < 1 ) {
00403             G_warning ( "Cannot open vector %s", map );
00404             return -1;
00405         }
00406 
00407         /* Delete all tables, NOT external (OGR) */
00408         if ( Map.format == GV_FORMAT_NATIVE ) {
00409 
00410             n = Vect_get_num_dblinks ( &Map );
00411             for ( i = 0; i < n; i++ ) {
00412                 Fi = Vect_get_dblink ( &Map, i );
00413                 if ( Fi == NULL ) {
00414                     G_warning ( "Cannot get db link info" );
00415                     Vect_close ( &Map );
00416                     return -1;
00417                 }
00418                 G_debug (3, "Delete drv:db:table '%s:%s:%s'", Fi->driver, Fi->database, Fi->table);
00419                 
00420                 ret = db_table_exists ( Fi->driver, Fi->database, Fi->table );
00421                 if ( ret == -1 ) {
00422                     G_warning ( "Cannot get info if table '%s' linked to vector exists.", Fi->table );
00423                     Vect_close ( &Map );
00424                     return -1;
00425                 }
00426                 
00427                 if ( ret == 1 ) {
00428                     ret = db_delete_table ( Fi->driver, Fi->database, Fi->table );
00429                     if ( ret == DB_FAILED ) {
00430                         G_warning ( "Cannot delete table" );
00431                         Vect_close ( &Map );
00432                         return -1;
00433                     }
00434                 } else {
00435                     G_warning ( "Table '%s' linked to vector did not exist.", Fi->table );
00436                 }
00437             }
00438         }
00439             
00440         Vect_close ( &Map );
00441     }
00442 
00443     /* Delete all files from vector/name directory */
00444     sprintf ( buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map );
00445     G_debug (3, "opendir '%s'", buf ); 
00446     dir = opendir( buf );
00447     if (dir == NULL) {
00448         G_warning ( "Cannot open directory '%s'", buf );
00449         return -1;
00450     }
00451 
00452     while ( (ent = readdir (dir)) ) {
00453         G_debug (3, "file = '%s'", ent->d_name );
00454         if ( (strcmp (ent->d_name, ".") == 0) || (strcmp (ent->d_name, "..") == 0) ) continue;
00455         sprintf ( buf, "%s/%s/vector/%s/%s", G_location_path(), G_mapset(), map, ent->d_name );
00456         G_debug (3, "delete file '%s'", buf );
00457         ret = unlink ( buf );
00458         if ( ret == -1 ) { 
00459             G_warning ( "Cannot delete file '%s'", buf );
00460             closedir (dir);
00461             return -1;
00462         }
00463     }
00464     closedir (dir);
00465 
00466     /* NFS can create .nfsxxxxxxxx files for those deleted 
00467      *  -> we have to move the directory to ./tmp before it is deleted */
00468     sprintf ( buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map );
00469 
00470     tmp = G_tempfile();
00471 
00472     G_debug (3, "rename '%s' to '%s'", buf, tmp );
00473     ret = rename ( buf, tmp );
00474 
00475     if ( ret == -1 ) {
00476         G_warning ( "Cannot rename directory '%s' to '%s'", buf, tmp );
00477         return -1;
00478     }
00479 
00480     G_debug (3, "remove directory '%s'", tmp );
00481     /* Warning: remove() fails on Windows */
00482     ret = rmdir ( tmp );
00483     if ( ret == -1 ) { 
00484         G_warning ( "Cannot remove directory '%s'", tmp );
00485         return -1;
00486     }
00487 
00488     return 0;
00489 }
00490 
00497 int 
00498 Vect_copy_tables ( struct Map_info *In, struct Map_info *Out, int field )
00499 {
00500     int i, n, ret, type;
00501     struct field_info *Fi, *Fin;
00502     dbDriver *driver;
00503 
00504     G_debug (2, "Vect_copy_tables()");
00505 
00506     n = Vect_get_num_dblinks ( In );
00507     type = GV_1TABLE;
00508     if ( n > 1 ) type = GV_MTABLE;
00509 
00510     for ( i = 0; i < n; i++ ) {
00511         Fi = Vect_get_dblink ( In, i );
00512         if ( Fi == NULL ) {
00513             G_warning ( "Cannot get db link info" );
00514             return -1;
00515         }
00516         if ( field > 0 && Fi->number != field ) continue;
00517 
00518         Fin = Vect_default_field_info ( Out, Fi->number, Fi->name, type );
00519         G_debug (2, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00520                       Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
00521         
00522         ret = Vect_map_add_dblink ( Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver);
00523         if ( ret == -1 ) {
00524             G_warning ( "Cannot add database link" );
00525             return -1;
00526         }
00527         
00528         ret = db_copy_table ( Fi->driver, Fi->database, Fi->table, 
00529                     Fin->driver, Vect_subst_var(Fin->database,Out), Fin->table );
00530         if ( ret == DB_FAILED ) {
00531             G_warning ( "Cannot copy table" );
00532             return -1;
00533         }
00534 
00535         driver = db_start_driver_open_database ( Fin->driver, Vect_subst_var(Fin->database,Out) );
00536         if ( driver == NULL ) {
00537             G_warning ( "Cannot open database -> create index" );
00538         } else {
00539             if ( db_create_index2(driver, Fin->table, Fi->key ) != DB_OK )
00540                 G_warning ( "Cannot create index" );
00541 
00542             db_close_database_shutdown_driver ( driver );
00543         }
00544     }
00545 
00546     return 0;
00547 }
00548 
00561 int 
00562 Vect_copy_table ( struct Map_info *In, struct Map_info *Out, int field_in, 
00563                    int field_out,  char *field_name, int type )
00564 {
00565     return Vect_copy_table_by_cats ( In, Out, field_in, field_out, field_name, type, NULL, 0); 
00566 }
00567 
00582 int 
00583 Vect_copy_table_by_cats ( struct Map_info *In, struct Map_info *Out, int field_in, 
00584                    int field_out,  char *field_name, int type, int *cats, int ncats )
00585 {
00586     int    ret;
00587     struct field_info *Fi, *Fin;
00588     char   *name, *key;
00589 
00590     G_debug (2, "Vect_copy_table(): field_in = %d field_out = %d", field_in, field_out);
00591 
00592     Fi = Vect_get_field ( In, field_in );
00593     if ( Fi == NULL ) {
00594         G_warning ( "Cannot get db link info" );
00595         return -1;
00596     }
00597 
00598     if ( field_name != NULL ) name = field_name;
00599     else name = Fi->name;
00600     
00601     Fin = Vect_default_field_info ( Out, field_out, name, type );
00602     G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'", 
00603                   Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
00604     
00605     ret = Vect_map_add_dblink ( Out, Fin->number, Fin->name, Fin->table, Fi->key, Fin->database, Fin->driver);
00606     if ( ret == -1 ) {
00607         G_warning ( "Cannot add database link" );
00608         return -1;
00609     }
00610     
00611     if ( cats ) 
00612         key = Fi->key;
00613     else 
00614         key = NULL;
00615     
00616     ret = db_copy_table_by_ints ( Fi->driver, Fi->database, Fi->table, 
00617                 Fin->driver, Vect_subst_var(Fin->database,Out), Fin->table, key, cats, ncats );
00618     if ( ret == DB_FAILED ) {
00619         G_warning ( "Cannot copy table" );
00620         return -1;
00621     }
00622 
00623     return 0;
00624 }
00625 
00631 void
00632 Vect_set_release_support ( struct Map_info * Map )
00633 {
00634     Map->plus.release_support = 1;
00635 }
00636 
00644 void
00645 Vect_set_category_index_update ( struct Map_info * Map )
00646 {
00647     Map->plus.update_cidx = 1;
00648 }
00649 

Generated on Sun Apr 6 17:32:44 2008 for GRASS by  doxygen 1.5.5