GRASS Programmer's Manual
6.4.2(2012)
|
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 }