GRASS Programmer's Manual  6.4.2(2012)
reg_deps.c
Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003  *            reg_deps.c
00004  *
00005  *  Mon Apr 18 15:19:04 2005
00006  *  Copyright  2005  Benjamin Ducke
00007  ****************************************************************************/
00008 
00009 /*
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00023  */
00024 
00025 #include "globals.h"
00026 
00027 
00028 /*
00029    Reads in the "depends" file and returns a string of comma-separated
00030    extensions, on which this one depends.
00031  */
00032 char *depstr(char *package, char *gisbase)
00033 {
00034     char file[MAXSTR];
00035     char line[MAXSTR];
00036     char *str;
00037     int first;
00038     int error;
00039     FILE *f_deps;
00040 
00041     char short_name[MAXSTR];
00042 
00043     /* check if 'depends' exists and is readable */
00044     sprintf(file, "../depends");
00045     f_deps = fopen(file, "r");
00046     if (f_deps == NULL) {
00047         if (errno == ENOENT) {
00048             /* file does not exist, return an empty string */
00049             return ("");
00050         }
00051         else {
00052             /* sth. strange happened */
00053             print_error(ERR_CHECK_DEPS, "checking for file '%s': %s\n", file,
00054                         strerror(errno));
00055         }
00056     }
00057 
00058     first = 1;
00059     str = malloc(sizeof(char) * MAXSTR);
00060     while (nc_fgets_nb(line, MAXSTR, f_deps) != NULL) {
00061         if (strlen(line) > 0) {
00062             error = sscanf(line, "%s", short_name);
00063             if ((error > 0) && (strcmp("GRASS", short_name))) {
00064                 if (first) {
00065                     strcat(str, "\t");
00066                     strcat(str, short_name);
00067                     first = 0;
00068                 }
00069                 else {
00070                     strcat(str, ",");
00071                     strcat(str, short_name);
00072                 }
00073             }
00074         }
00075     }
00076 
00077     fclose(f_deps);
00078     return (str);
00079 }
00080 
00081 /* 
00082    Reads in GISBASE/etc/extensions.db 
00083    Adds a line to the file GISBASE/etc/extensions.db that contains: 
00084    extension name and version, 'src' or name of binary files.
00085    Adds extension name to the end of every entry mentioned in 'depends' 
00086  */
00087 void register_extension(char *gisbase, char *bins, char *pkg_short_name,
00088                         int pkg_major, int pkg_minor, int pkg_revision)
00089 {
00090     char file[MAXSTR];
00091     char str[MAXSTR];
00092     int n_lines;
00093     int error;
00094     int db_exists;
00095     int must_register;
00096     int copy_thru;
00097     int ext_exists;
00098     FILE *f_in, *f_out;
00099 
00100     char short_name[MAXSTR];
00101     char inst_bins[MAXSTR];
00102     char deps[MAXSTR];
00103     int major, minor, revision;
00104 
00105 
00106     /* check, if extensions.db exists and is readable */
00107     db_exists = 1;
00108     sprintf(file, "%s/etc/extensions.db", gisbase);
00109     f_in = fopen(file, "r");
00110     if (f_in == NULL) {
00111         if (errno == ENOENT) {
00112             /* file does not yet exist */
00113             db_exists = 0;
00114         }
00115         else {
00116             /* sth. strange happened */
00117             fclose(f_in);
00118             print_error(ERR_REGISTER_EXT, "checking for file '%s': %s\n",
00119                         file, strerror(errno));
00120         }
00121     }
00122 
00123     if (db_exists) {
00124         /* create a temporary extensions.db file for write access */
00125         /* TODO: Do not hardcode temp paths */
00126         strcpy(TMPDB, "/tmp/grass.extensions.db.XXXXXX");       /* TMPDB is a global variable */
00127         mkstemp(TMPDB);
00128 
00129         f_out = fopen(TMPDB, "w+");
00130         if (f_out == NULL) {
00131             print_error(ERR_REGISTER_EXT,
00132                         "could not create temp file '%s': %s\n \
00133                                                         Make sure that directory /tmp exists on your system and you have write permission.\n", TMPDB, strerror(errno));
00134         }
00135 
00136         atexit(&exit_db);       /* now need to register an at exit func to remove tmpdb automatically! */
00137 
00138         /* count number of extensions.db registry entries */
00139         n_lines = 0;
00140         must_register = 1;
00141         ext_exists = 0;
00142         while (nc_fgets_nb(str, MAXSTR, f_in) != NULL) {
00143             n_lines++;
00144             copy_thru = 1;
00145             /* read in name and version of registered item */
00146             sscanf(str, "%s\t%i.%i.%i\t%s\t%s", short_name, &major, &minor,
00147                    &revision, inst_bins, deps);
00148             /* check, if extension with same name already exists */
00149             if (!strcmp(short_name, pkg_short_name)) {
00150                 /* an extension with this name is already installed */
00151                 ext_exists = 1;
00152                 /* check if it's version is lower, same or higher */
00153                 error =
00154                     vercmp(major, minor, revision, pkg_major, pkg_minor,
00155                            pkg_revision);
00156                 if ((!FORCE)) {
00157                     /* error, if another version is present! */
00158                     if (error < 0) {
00159                         print_error(ERR_EXISTS_EXT,
00160                                     "Extension '%s' with lower version (%i.%i.%i) already installed. You can use -f to overwrite this version, if you know what you are doing.\n",
00161                                     pkg_short_name, major, minor, revision);
00162                     }
00163                     else {
00164                         print_error(ERR_EXISTS_EXT,
00165                                     "Extension '%s' with same or higher version (%i.%i.%i) already installed. You can use -f to overwrite this version, if you know what you are doing.\n",
00166                                     pkg_short_name, major, minor, revision);
00167                     }
00168                 }
00169                 if (FORCE) {    /* this overrides/implies UPGRADE! */
00170                     if (error == 0) {
00171                         /* if same version installed: just leave everything untouched */
00172                         must_register = 0;
00173                     }
00174                     else {
00175                         /* otherwise, work needs be done! */
00176                         must_register = 1;
00177                         copy_thru = 0;
00178                     }
00179                 }
00180             }
00181 
00182             /* write line to temporary extension file */
00183             if (copy_thru) {    /* just copy thru */
00184                 fprintf(f_out, str);
00185                 fflush(f_out);
00186             }
00187         }
00188 
00189         if (must_register) {
00190             if (!ext_exists) {
00191                 /* register brand new extension */
00192                 sprintf(deps, "%s", depstr(pkg_short_name, gisbase));
00193                 fprintf(f_out, "%s\t%i.%i.%i\t%s\t%s\n", pkg_short_name,
00194                         pkg_major, pkg_minor, pkg_revision, bins, deps);
00195             }
00196             else {
00197                 /* register only new version number and binary source, if appropriate */
00198                 sprintf(deps, "%s", depstr(pkg_short_name, gisbase));
00199                 fprintf(f_out, "%s\t%i.%i.%i\t%s\t%s\n", short_name,
00200                         pkg_major, pkg_minor, pkg_revision, inst_bins, deps);
00201             }
00202         }
00203 
00204         fclose(f_out);
00205         fclose(f_in);
00206     }
00207 
00208     if ((n_lines == 0) || (!db_exists)) {
00209         /* extensions.db file does not yet exist or is empty: just create a new one */
00210         /* TODO: Do not hardcode temp paths */
00211         strcpy(TMPDB, "/tmp/grass.extensions.db.XXXXXX");       /* tmpdir is a global variable */
00212         mkstemp(TMPDB);
00213 
00214         f_out = fopen(TMPDB, "w+");
00215         if (f_out == NULL) {
00216             print_error(ERR_REGISTER_EXT,
00217                         "could not create temp db '%s': %s\n \
00218                                         Make sure that directory /tmp exists on your system and you have write permission.\n", file, strerror(errno));
00219         }
00220         atexit(&exit_db);       /* now need to register an at exit func to remove tmpdb automatically! */
00221 
00222         /* register brand new extension */
00223         sprintf(deps, "%s", depstr(pkg_short_name, gisbase));
00224         fprintf(f_out, "%s\t%i.%i.%i\t%s\t%s\n", pkg_short_name, pkg_major,
00225                 pkg_minor, pkg_revision, bins, deps);
00226         fclose(f_out);
00227         return;
00228     }
00229 }
00230 
00231 
00232 /*
00233    Removes an entry from GISBASE/etc/extensions.db
00234  */
00235 void deregister_extension(char *package, char *pkg_short_name, char *gisbase)
00236 {
00237     char file[MAXSTR];
00238     char str[MAXSTR];
00239     int error;
00240     int db_exists;
00241     int copy_thru;
00242     FILE *f_in, *f_out;
00243     int found_ext;
00244 
00245     char short_name[MAXSTR];
00246     char inst_bins[MAXSTR];
00247     char deps[MAXSTR];
00248     int major, minor, revision;
00249 
00250 
00251     db_exists = 0;
00252     /* check, if extensions.db exists and is readable */
00253     sprintf(file, "%s/etc/extensions.db", gisbase);
00254     f_in = fopen(file, "r");
00255     if (f_in == NULL) {
00256         if ((errno == ENOENT) && (!FORCE)) {
00257             /* file does not yet exist */
00258             fclose(f_in);
00259             print_error(ERR_DEREGISTER_EXT,
00260                         "could not deregister: no extensions installed\n");
00261         }
00262         else {
00263             /* sth. strange happened */
00264             if (!FORCE) {
00265                 fclose(f_in);
00266                 print_error(ERR_DEREGISTER_EXT,
00267                             "checking for file '%s': %s\n", file,
00268                             strerror(errno));
00269             }
00270         }
00271     }
00272     else {
00273         db_exists = 1;
00274     }
00275 
00276     if (db_exists) {
00277         db_exists = 0;
00278         /* create a temporary extensions.db file for write access */
00279         /* TODO: Do not hardcode temp paths */
00280         strcpy(TMPDB, "/tmp/grass.extensions.db.XXXXXX");       /* tmpdir is a global variable */
00281         mkstemp(TMPDB);
00282 
00283         f_out = fopen(TMPDB, "w+");
00284         if ((f_out == NULL) && (!FORCE)) {
00285             print_error(ERR_DEREGISTER_EXT,
00286                         "could not create temp db '%s': %s\n \
00287                                                         Make sure that directory /tmp exists on your system and you have write permission.\n", file, strerror(errno));
00288         }
00289         else {
00290             db_exists = 1;
00291             atexit(&exit_db);   /* now need to register an at exit func to remove tmpdb automatically! */
00292         }
00293     }
00294 
00295     /* if creation of temp db file succeeded: */
00296     if (db_exists) {
00297         /* read every line in extension.db */
00298         found_ext = 0;
00299         while (nc_fgets_nb(str, MAXSTR, f_in) != NULL) {
00300             /* copy thru, if extension name different from current extension's */
00301             error =
00302                 sscanf(str, "%s\t%i.%i.%i\t%s\t%s", short_name, &major,
00303                        &minor, &revision, inst_bins, deps);
00304             if (error > 0) {
00305                 copy_thru = 1;
00306                 if (!strcmp(pkg_short_name, short_name)) {
00307                     copy_thru = 0;
00308                     found_ext = 1;
00309                 }
00310                 if (copy_thru) {
00311                     /* abort, if a dependency on current extension is found */
00312                     if ((strstr(deps, pkg_short_name)) && (!FORCE)) {
00313                         print_error(ERR_DEREGISTER_EXT,
00314                                     "cannot uninstall extension '%s' it is needed by '%s'.\n",
00315                                     pkg_short_name, short_name);
00316                     }
00317                     fprintf(f_out, str);
00318                 }
00319             }
00320         }
00321 
00322         /* was the extension installed at all? */
00323         if (found_ext == 0) {
00324             print_error(ERR_DEREGISTER_EXT,
00325                         "no extension '%s' registered/installed in '%s'.\n",
00326                         pkg_short_name, gisbase);
00327         }
00328         /* mind the right sequence for closing these! */
00329         fclose(f_in);
00330         fclose(f_out);
00331     }
00332 }
00333 
00334 
00335 /*
00336    checks GRASS version number and whether all extensions listed in 'depends'
00337    are satisfied (by analysing GISBASE/etc/extensions.db).
00338    Terminates program, if missing deps; just returns, if "--force" was given.
00339  */
00340 void check_dependencies(char *package, char *gisbase, char *grass_version)
00341 {
00342     char file[MAXSTR];
00343     char str[MAXSTR];
00344     char dbstr[MAXSTR];
00345     int error;
00346     int db_exists;
00347     int satisfied;
00348     FILE *f_deps, *f_db;
00349 
00350     char short_name[MAXSTR];
00351     int major, minor, revision;
00352     char dep_short_name[MAXSTR];
00353     int dep_major, dep_minor, dep_revision;
00354 
00355     if (FORCE) {
00356         return;
00357     }
00358 
00359     /* check if 'depends' exists and is readable */
00360     f_deps = fopen("../depends", "r");
00361     if (f_deps == NULL) {
00362         if (errno == ENOENT) {
00363             /* file does not exist, no need to check for deps */
00364             fprintf(stderr, "\n%s/depends ENOENT\n", package);
00365             return;
00366         }
00367         else {
00368             /* sth. strange happened */
00369             fclose(f_deps);
00370             print_error(ERR_CHECK_DEPS, "checking for file '%s': %s\n", file,
00371                         strerror(errno));
00372         }
00373     }
00374 
00375     db_exists = 1;
00376     /* check if extensions.db exists and is readable */
00377     sprintf(file, "%s/etc/extensions.db", gisbase);
00378     f_db = fopen(file, "r");
00379     if (f_db == NULL) {
00380         if (errno == ENOENT) {
00381             /* file does not exist */
00382             db_exists = 0;
00383         }
00384         else {
00385             /* sth. strange happened */
00386             fclose(f_db);
00387             print_error(ERR_CHECK_DEPS, "checking for file '%s': %s\n", file,
00388                         strerror(errno));
00389         }
00390     }
00391 
00392     satisfied = 0;
00393     while (nc_fgets_nb(str, MAXSTR, f_deps) != NULL) {
00394         /* get first line with dependencies info */
00395         major = 0;
00396         minor = 0;
00397         revision = 0;
00398         dep_major = 0;
00399         dep_minor = 0;
00400         dep_revision = 0;
00401         error =
00402             sscanf(str, "%s\t%i.%i.%i", dep_short_name, &dep_major,
00403                    &dep_minor, &dep_revision);
00404         if (error > 0) {
00405             if (!strcmp(dep_short_name, "GRASS")) {
00406                 /* a GRASS version dependency has been specified */
00407                 sscanf(grass_version, "%i.%i.%i", &major, &minor, &revision);
00408                 if (vercmp
00409                     (major, minor, revision, dep_major, dep_minor,
00410                      dep_revision) < 0) {
00411                     print_error(ERR_MISSING_DEPS,
00412                                 "installed version (%s) of GRASS is too low. Required version is %i.%i.%i\n",
00413                                 grass_version, dep_major, dep_minor,
00414                                 dep_revision);
00415                 }
00416                 satisfied = 1;  /* let's be tolerant */
00417             }
00418             else {
00419                 /* a dependency on some other extension has been specified ... */
00420                 if (db_exists) {        /* ... if no extensions installed yet, it must be unsatisfied! */
00421                     satisfied = 0;
00422                     rewind(f_db);
00423                     while (nc_fgets_nb(dbstr, MAXSTR, f_db) != NULL) {
00424                         major = 0;
00425                         minor = 0;
00426                         revision = 0;
00427                         error =
00428                             sscanf(dbstr, "%s\t%i.%i.%i", short_name, &major,
00429                                    &minor, &revision);
00430                         if (error > 0) {
00431                             if (!strcmp(short_name, dep_short_name)) {
00432                                 /* found an installed extension that satisfies name, now check
00433                                    for version number */
00434                                 if (vercmp
00435                                     (major, minor, revision, dep_major,
00436                                      dep_minor, dep_revision) < 0) {
00437                                     print_error(ERR_MISSING_DEPS,
00438                                                 "installed version %i.%i.%i of required extension '%s' is too low.\n \
00439                                                                                                         Required version is %i.%i.%i\n",
00440                                                 major, minor, revision, dep_short_name, dep_major, dep_minor,
00441                                                 dep_revision);
00442                                 }
00443                                 /* name and version dependencies satisfied */
00444                                 satisfied = 1;
00445                             }
00446                         }
00447                     }
00448                     if (!satisfied) {
00449                         print_error(ERR_MISSING_DEPS,
00450                                     "required extension '%s' not found in '%s'.\n",
00451                                     dep_short_name, gisbase);
00452                     }
00453                 }
00454             }
00455         }
00456     }
00457     if (db_exists) {
00458         fclose(f_db);
00459     }
00460     fclose(f_deps);
00461 
00462 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines