security/nss/cmd/modutil/install-ds.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "install-ds.h"
michael@0 6 #include <prmem.h>
michael@0 7 #include <plstr.h>
michael@0 8 #include <prprf.h>
michael@0 9 #include <string.h>
michael@0 10
michael@0 11 #define PORT_Strcasecmp PL_strcasecmp
michael@0 12
michael@0 13 #define MODULE_FILE_STRING "ModuleFile"
michael@0 14 #define MODULE_NAME_STRING "ModuleName"
michael@0 15 #define MECH_FLAGS_STRING "DefaultMechanismFlags"
michael@0 16 #define CIPHER_FLAGS_STRING "DefaultCipherFlags"
michael@0 17 #define FILES_STRING "Files"
michael@0 18 #define FORWARD_COMPATIBLE_STRING "ForwardCompatible"
michael@0 19 #define PLATFORMS_STRING "Platforms"
michael@0 20 #define RELATIVE_DIR_STRING "RelativePath"
michael@0 21 #define ABSOLUTE_DIR_STRING "AbsolutePath"
michael@0 22 #define FILE_PERMISSIONS_STRING "FilePermissions"
michael@0 23 #define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform"
michael@0 24 #define EXECUTABLE_STRING "Executable"
michael@0 25
michael@0 26 #define DEFAULT_PERMISSIONS 0777
michael@0 27
michael@0 28 #define PLATFORM_SEPARATOR_CHAR ':'
michael@0 29
michael@0 30 /* Error codes */
michael@0 31 enum {
michael@0 32 BOGUS_RELATIVE_DIR=0,
michael@0 33 BOGUS_ABSOLUTE_DIR,
michael@0 34 BOGUS_FILE_PERMISSIONS,
michael@0 35 NO_RELATIVE_DIR,
michael@0 36 NO_ABSOLUTE_DIR,
michael@0 37 EMPTY_PLATFORM_STRING,
michael@0 38 BOGUS_PLATFORM_STRING,
michael@0 39 REPEAT_MODULE_FILE,
michael@0 40 REPEAT_MODULE_NAME,
michael@0 41 BOGUS_MODULE_FILE,
michael@0 42 BOGUS_MODULE_NAME,
michael@0 43 REPEAT_MECH,
michael@0 44 BOGUS_MECH_FLAGS,
michael@0 45 REPEAT_CIPHER,
michael@0 46 BOGUS_CIPHER_FLAGS,
michael@0 47 REPEAT_FILES,
michael@0 48 REPEAT_EQUIV,
michael@0 49 BOGUS_EQUIV,
michael@0 50 EQUIV_TOO_MUCH_INFO,
michael@0 51 NO_FILES,
michael@0 52 NO_MODULE_FILE,
michael@0 53 NO_MODULE_NAME,
michael@0 54 NO_PLATFORMS,
michael@0 55 EQUIV_LOOP,
michael@0 56 UNKNOWN_MODULE_FILE
michael@0 57 };
michael@0 58
michael@0 59 /* Indexed by the above error codes */
michael@0 60 static const char *errString[] = {
michael@0 61 "%s: Invalid relative directory",
michael@0 62 "%s: Invalid absolute directory",
michael@0 63 "%s: Invalid file permissions",
michael@0 64 "%s: No relative directory specified",
michael@0 65 "%s: No absolute directory specified",
michael@0 66 "Empty string given for platform name",
michael@0 67 "%s: invalid platform string",
michael@0 68 "More than one ModuleFile entry given for platform %s",
michael@0 69 "More than one ModuleName entry given for platform %s",
michael@0 70 "Invalid ModuleFile specification for platform %s",
michael@0 71 "Invalid ModuleName specification for platform %s",
michael@0 72 "More than one DefaultMechanismFlags entry given for platform %s",
michael@0 73 "Invalid DefaultMechanismFlags specification for platform %s",
michael@0 74 "More than one DefaultCipherFlags entry given for platform %s",
michael@0 75 "Invalid DefaultCipherFlags entry given for platform %s",
michael@0 76 "More than one Files entry given for platform %s",
michael@0 77 "More than one EquivalentPlatform entry given for platform %s",
michael@0 78 "Invalid EquivalentPlatform specification for platform %s",
michael@0 79 "Module %s uses an EquivalentPlatform but also specifies its own"
michael@0 80 " information",
michael@0 81 "No Files specification in module %s",
michael@0 82 "No ModuleFile specification in module %s",
michael@0 83 "No ModuleName specification in module %s",
michael@0 84 "No Platforms specification in installer script",
michael@0 85 "Platform %s has an equivalency loop",
michael@0 86 "Module file \"%s\" in platform \"%s\" does not exist"
michael@0 87 };
michael@0 88
michael@0 89 static char* PR_Strdup(const char* str);
michael@0 90
michael@0 91 #define PAD(x) {int i; for(i=0;i<x;i++) printf(" ");}
michael@0 92 #define PADINC 4
michael@0 93
michael@0 94 Pk11Install_File*
michael@0 95 Pk11Install_File_new()
michael@0 96 {
michael@0 97 Pk11Install_File* new_this;
michael@0 98 new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File));
michael@0 99 Pk11Install_File_init(new_this);
michael@0 100 return new_this;
michael@0 101 }
michael@0 102
michael@0 103 void
michael@0 104 Pk11Install_File_init(Pk11Install_File* _this)
michael@0 105 {
michael@0 106 _this->jarPath=NULL;
michael@0 107 _this->relativePath=NULL;
michael@0 108 _this->absolutePath=NULL;
michael@0 109 _this->executable=PR_FALSE;
michael@0 110 _this->permissions=0;
michael@0 111 }
michael@0 112
michael@0 113 /*
michael@0 114 //////////////////////////////////////////////////////////////////////////
michael@0 115 // Method: ~Pk11Install_File
michael@0 116 // Class: Pk11Install_File
michael@0 117 // Notes: Destructor.
michael@0 118 */
michael@0 119 void
michael@0 120 Pk11Install_File_delete(Pk11Install_File* _this)
michael@0 121 {
michael@0 122 Pk11Install_File_Cleanup(_this);
michael@0 123 }
michael@0 124
michael@0 125 /*
michael@0 126 //////////////////////////////////////////////////////////////////////////
michael@0 127 // Method: Cleanup
michael@0 128 // Class: Pk11Install_File
michael@0 129 */
michael@0 130 void
michael@0 131 Pk11Install_File_Cleanup(Pk11Install_File* _this)
michael@0 132 {
michael@0 133 if(_this->jarPath) {
michael@0 134 PR_Free(_this->jarPath);
michael@0 135 _this->jarPath = NULL;
michael@0 136 }
michael@0 137 if(_this->relativePath) {
michael@0 138 PR_Free(_this->relativePath);
michael@0 139 _this->relativePath = NULL;
michael@0 140 }
michael@0 141 if(_this->absolutePath) {
michael@0 142 PR_Free(_this->absolutePath);
michael@0 143 _this->absolutePath = NULL;
michael@0 144 }
michael@0 145
michael@0 146 _this->permissions = 0;
michael@0 147 _this->executable = PR_FALSE;
michael@0 148 }
michael@0 149
michael@0 150 /*
michael@0 151 //////////////////////////////////////////////////////////////////////////
michael@0 152 // Method: Generate
michael@0 153 // Class: Pk11Install_File
michael@0 154 // Notes: Creates a file data structure from a syntax tree.
michael@0 155 // Returns: NULL for success, otherwise an error message.
michael@0 156 */
michael@0 157 char*
michael@0 158 Pk11Install_File_Generate(Pk11Install_File* _this,
michael@0 159 const Pk11Install_Pair *pair)
michael@0 160 {
michael@0 161 Pk11Install_ListIter *iter;
michael@0 162 Pk11Install_Value *val;
michael@0 163 Pk11Install_Pair *subpair;
michael@0 164 Pk11Install_ListIter *subiter;
michael@0 165 Pk11Install_Value *subval;
michael@0 166 char* errStr;
michael@0 167 char *endp;
michael@0 168 PRBool gotPerms;
michael@0 169
michael@0 170 iter=NULL;
michael@0 171 subiter=NULL;
michael@0 172 errStr=NULL;
michael@0 173 gotPerms=PR_FALSE;
michael@0 174
michael@0 175 /* Clear out old values */
michael@0 176 Pk11Install_File_Cleanup(_this);
michael@0 177
michael@0 178 _this->jarPath = PR_Strdup(pair->key);
michael@0 179
michael@0 180 /* Go through all the pairs under this file heading */
michael@0 181 iter = Pk11Install_ListIter_new(pair->list);
michael@0 182 for( ; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
michael@0 183 if(val->type == PAIR_VALUE) {
michael@0 184 subpair = val->pair;
michael@0 185
michael@0 186 /* Relative directory */
michael@0 187 if(!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) {
michael@0 188 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 189 subval = subiter->current;
michael@0 190 if(!subval || (subval->type != STRING_VALUE)){
michael@0 191 errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR],
michael@0 192 _this->jarPath);
michael@0 193 goto loser;
michael@0 194 }
michael@0 195 _this->relativePath = PR_Strdup(subval->string);
michael@0 196 Pk11Install_ListIter_delete(subiter);
michael@0 197 subiter = NULL;
michael@0 198
michael@0 199 /* Absolute directory */
michael@0 200 } else if( !PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) {
michael@0 201 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 202 subval = subiter->current;
michael@0 203 if(!subval || (subval->type != STRING_VALUE)){
michael@0 204 errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR],
michael@0 205 _this->jarPath);
michael@0 206 goto loser;
michael@0 207 }
michael@0 208 _this->absolutePath = PR_Strdup(subval->string);
michael@0 209 Pk11Install_ListIter_delete(subiter);
michael@0 210 subiter = NULL;
michael@0 211
michael@0 212 /* file permissions */
michael@0 213 } else if( !PORT_Strcasecmp(subpair->key,
michael@0 214 FILE_PERMISSIONS_STRING)) {
michael@0 215 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 216 subval = subiter->current;
michael@0 217 if(!subval || (subval->type != STRING_VALUE) ||
michael@0 218 !subval->string || !subval->string[0]){
michael@0 219 errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
michael@0 220 _this->jarPath);
michael@0 221 goto loser;
michael@0 222 }
michael@0 223 _this->permissions = (int) strtol(subval->string, &endp, 8);
michael@0 224 if(*endp != '\0') {
michael@0 225 errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
michael@0 226 _this->jarPath);
michael@0 227 goto loser;
michael@0 228 }
michael@0 229 gotPerms = PR_TRUE;
michael@0 230 Pk11Install_ListIter_delete(subiter);
michael@0 231 subiter = NULL;
michael@0 232 }
michael@0 233 } else {
michael@0 234 if(!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) {
michael@0 235 _this->executable = PR_TRUE;
michael@0 236 }
michael@0 237 }
michael@0 238 }
michael@0 239
michael@0 240 /* Default permission value */
michael@0 241 if(!gotPerms) {
michael@0 242 _this->permissions = DEFAULT_PERMISSIONS;
michael@0 243 }
michael@0 244
michael@0 245 /* Make sure we got all the information */
michael@0 246 if(!_this->relativePath && !_this->absolutePath) {
michael@0 247 errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
michael@0 248 goto loser;
michael@0 249 }
michael@0 250 #if 0
michael@0 251 if(!_this->relativePath ) {
michael@0 252 errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath);
michael@0 253 goto loser;
michael@0 254 }
michael@0 255 if(!_this->absolutePath) {
michael@0 256 errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
michael@0 257 goto loser;
michael@0 258 }
michael@0 259 #endif
michael@0 260
michael@0 261 loser:
michael@0 262 if(iter) {
michael@0 263 Pk11Install_ListIter_delete(iter);
michael@0 264 PR_Free(iter);
michael@0 265 }
michael@0 266 if(subiter) {
michael@0 267 Pk11Install_ListIter_delete(subiter);
michael@0 268 PR_Free(subiter);
michael@0 269 }
michael@0 270 return errStr;
michael@0 271 }
michael@0 272
michael@0 273 /*
michael@0 274 //////////////////////////////////////////////////////////////////////////
michael@0 275 // Method: Print
michael@0 276 // Class: Pk11Install_File
michael@0 277 */
michael@0 278 void
michael@0 279 Pk11Install_File_Print(Pk11Install_File* _this, int pad)
michael@0 280 {
michael@0 281 PAD(pad); printf("jarPath: %s\n",
michael@0 282 _this->jarPath ? _this->jarPath : "<NULL>");
michael@0 283 PAD(pad); printf("relativePath: %s\n",
michael@0 284 _this->relativePath ? _this->relativePath: "<NULL>");
michael@0 285 PAD(pad); printf("absolutePath: %s\n",
michael@0 286 _this->absolutePath ? _this->absolutePath: "<NULL>");
michael@0 287 PAD(pad); printf("permissions: %o\n", _this->permissions);
michael@0 288 }
michael@0 289
michael@0 290 Pk11Install_PlatformName*
michael@0 291 Pk11Install_PlatformName_new()
michael@0 292 {
michael@0 293 Pk11Install_PlatformName* new_this;
michael@0 294 new_this = (Pk11Install_PlatformName*)
michael@0 295 PR_Malloc(sizeof(Pk11Install_PlatformName));
michael@0 296 Pk11Install_PlatformName_init(new_this);
michael@0 297 return new_this;
michael@0 298 }
michael@0 299
michael@0 300 void
michael@0 301 Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this)
michael@0 302 {
michael@0 303 _this->OS = NULL;
michael@0 304 _this->verString = NULL;
michael@0 305 _this->numDigits = 0;
michael@0 306 _this->arch = NULL;
michael@0 307 }
michael@0 308
michael@0 309 /*
michael@0 310 //////////////////////////////////////////////////////////////////////////
michael@0 311 // Method: ~Pk11Install_PlatformName
michael@0 312 // Class: Pk11Install_PlatformName
michael@0 313 */
michael@0 314 void
michael@0 315 Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this)
michael@0 316 {
michael@0 317 Pk11Install_PlatformName_Cleanup(_this);
michael@0 318 }
michael@0 319
michael@0 320 /*
michael@0 321 //////////////////////////////////////////////////////////////////////////
michael@0 322 // Method: Cleanup
michael@0 323 // Class: Pk11Install_PlatformName
michael@0 324 */
michael@0 325 void
michael@0 326 Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this)
michael@0 327 {
michael@0 328 if(_this->OS) {
michael@0 329 PR_Free(_this->OS);
michael@0 330 _this->OS = NULL;
michael@0 331 }
michael@0 332 if(_this->verString) {
michael@0 333 int i;
michael@0 334 for (i=0; i<_this->numDigits; i++) {
michael@0 335 PR_Free(_this->verString[i]);
michael@0 336 }
michael@0 337 PR_Free(_this->verString);
michael@0 338 _this->verString = NULL;
michael@0 339 }
michael@0 340 if(_this->arch) {
michael@0 341 PR_Free(_this->arch);
michael@0 342 _this->arch = NULL;
michael@0 343 }
michael@0 344 _this->numDigits = 0;
michael@0 345 }
michael@0 346
michael@0 347 /*
michael@0 348 //////////////////////////////////////////////////////////////////////////
michael@0 349 // Method: Generate
michael@0 350 // Class: Pk11Install_PlatformName
michael@0 351 // Notes: Extracts the information from a platform string.
michael@0 352 */
michael@0 353 char*
michael@0 354 Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
michael@0 355 const char *str)
michael@0 356 {
michael@0 357 char *errStr;
michael@0 358 char *copy;
michael@0 359 char *end, *start; /* start and end of a section (OS, version, arch)*/
michael@0 360 char *pend, *pstart; /* start and end of one portion of version*/
michael@0 361 char *endp; /* used by strtol*/
michael@0 362 int periods, i;
michael@0 363
michael@0 364 errStr=NULL;
michael@0 365 copy=NULL;
michael@0 366
michael@0 367 if(!str) {
michael@0 368 errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]);
michael@0 369 goto loser;
michael@0 370 }
michael@0 371 copy = PR_Strdup(str);
michael@0 372
michael@0 373 /*
michael@0 374 // Get the OS
michael@0 375 */
michael@0 376 end = strchr(copy, PLATFORM_SEPARATOR_CHAR);
michael@0 377 if(!end || end==copy) {
michael@0 378 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
michael@0 379 goto loser;
michael@0 380 }
michael@0 381 *end = '\0';
michael@0 382
michael@0 383 _this->OS = PR_Strdup(copy);
michael@0 384
michael@0 385 /*
michael@0 386 // Get the digits of the version of form: x.x.x (arbitrary number of digits)
michael@0 387 */
michael@0 388
michael@0 389 start = end+1;
michael@0 390 end = strchr(start, PLATFORM_SEPARATOR_CHAR);
michael@0 391 if(!end) {
michael@0 392 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
michael@0 393 goto loser;
michael@0 394 }
michael@0 395 *end = '\0';
michael@0 396
michael@0 397 if(end!=start) {
michael@0 398 /* Find out how many periods*/
michael@0 399 periods = 0;
michael@0 400 pstart = start;
michael@0 401 while( (pend=strchr(pstart, '.')) ) {
michael@0 402 periods++;
michael@0 403 pstart = pend+1;
michael@0 404 }
michael@0 405 _this->numDigits= 1+ periods;
michael@0 406 _this->verString = (char**)PR_Malloc(sizeof(char*)*_this->numDigits);
michael@0 407
michael@0 408 pstart = start;
michael@0 409 i = 0;
michael@0 410 /* Get the digits before each period*/
michael@0 411 while( (pend=strchr(pstart, '.')) ) {
michael@0 412 if(pend == pstart) {
michael@0 413 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
michael@0 414 goto loser;
michael@0 415 }
michael@0 416 *pend = '\0';
michael@0 417 _this->verString[i] = PR_Strdup(pstart);
michael@0 418 endp = pend;
michael@0 419 if(endp==pstart || (*endp != '\0')) {
michael@0 420 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
michael@0 421 goto loser;
michael@0 422 }
michael@0 423 pstart = pend+1;
michael@0 424 i++;
michael@0 425 }
michael@0 426 /* Last digit comes after the last period*/
michael@0 427 if(*pstart == '\0') {
michael@0 428 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
michael@0 429 goto loser;
michael@0 430 }
michael@0 431 _this->verString[i] = PR_Strdup(pstart);
michael@0 432 /*
michael@0 433 if(endp==pstart || (*endp != '\0')) {
michael@0 434 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
michael@0 435 goto loser;
michael@0 436 }
michael@0 437 */
michael@0 438 } else {
michael@0 439 _this->verString = NULL;
michael@0 440 _this->numDigits = 0;
michael@0 441 }
michael@0 442
michael@0 443 /*
michael@0 444 // Get the architecture
michael@0 445 */
michael@0 446 start = end+1;
michael@0 447 if( strchr(start, PLATFORM_SEPARATOR_CHAR) ) {
michael@0 448 errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
michael@0 449 goto loser;
michael@0 450 }
michael@0 451 _this->arch = PR_Strdup(start);
michael@0 452
michael@0 453 if(copy) {
michael@0 454 PR_Free(copy);
michael@0 455 }
michael@0 456 return NULL;
michael@0 457 loser:
michael@0 458 if(_this->OS) {
michael@0 459 PR_Free(_this->OS);
michael@0 460 _this->OS = NULL;
michael@0 461 }
michael@0 462 if(_this->verString) {
michael@0 463 for (i=0; i<_this->numDigits; i++) {
michael@0 464 PR_Free(_this->verString[i]);
michael@0 465 }
michael@0 466 PR_Free(_this->verString);
michael@0 467 _this->verString = NULL;
michael@0 468 }
michael@0 469 _this->numDigits = 0;
michael@0 470 if(_this->arch) {
michael@0 471 PR_Free(_this->arch);
michael@0 472 _this->arch = NULL;
michael@0 473 }
michael@0 474
michael@0 475 return errStr;
michael@0 476 }
michael@0 477
michael@0 478 /*
michael@0 479 //////////////////////////////////////////////////////////////////////////
michael@0 480 // Method: operator ==
michael@0 481 // Class: Pk11Install_PlatformName
michael@0 482 // Returns: PR_TRUE if the platform have the same OS, arch, and version
michael@0 483 */
michael@0 484 PRBool
michael@0 485 Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
michael@0 486 Pk11Install_PlatformName* cmp)
michael@0 487 {
michael@0 488 int i;
michael@0 489
michael@0 490 if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
michael@0 491 return PR_FALSE;
michael@0 492 }
michael@0 493
michael@0 494 if( PORT_Strcasecmp(_this->OS, cmp->OS) ||
michael@0 495 PORT_Strcasecmp(_this->arch, cmp->arch) ||
michael@0 496 _this->numDigits != cmp->numDigits ) {
michael@0 497 return PR_FALSE;
michael@0 498 }
michael@0 499
michael@0 500 for(i=0; i < _this->numDigits; i++) {
michael@0 501 if(PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) {
michael@0 502 return PR_FALSE;
michael@0 503 }
michael@0 504 }
michael@0 505 return PR_TRUE;
michael@0 506 }
michael@0 507
michael@0 508 /*
michael@0 509 //////////////////////////////////////////////////////////////////////////
michael@0 510 // Method: operator <=
michael@0 511 // Class: Pk11Install_PlatformName
michael@0 512 // Returns: PR_TRUE if the platform have the same OS and arch and a lower
michael@0 513 // or equal release.
michael@0 514 */
michael@0 515 PRBool
michael@0 516 Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
michael@0 517 Pk11Install_PlatformName* cmp)
michael@0 518 {
michael@0 519 return (Pk11Install_PlatformName_equal(_this,cmp) ||
michael@0 520 Pk11Install_PlatformName_lt(_this,cmp)) ? PR_TRUE : PR_FALSE;
michael@0 521 }
michael@0 522
michael@0 523 /*
michael@0 524 //////////////////////////////////////////////////////////////////////////
michael@0 525 // Method: operator <
michael@0 526 // Class: Pk11Install_PlatformName
michael@0 527 // Returns: PR_TRUE if the platform have the same OS and arch and a greater
michael@0 528 // release.
michael@0 529 */
michael@0 530 PRBool
michael@0 531 Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
michael@0 532 Pk11Install_PlatformName* cmp)
michael@0 533 {
michael@0 534 int i, scmp;
michael@0 535
michael@0 536 if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
michael@0 537 return PR_FALSE;
michael@0 538 }
michael@0 539
michael@0 540 if( PORT_Strcasecmp(_this->OS, cmp->OS) ) {
michael@0 541 return PR_FALSE;
michael@0 542 }
michael@0 543 if( PORT_Strcasecmp(_this->arch, cmp->arch) ) {
michael@0 544 return PR_FALSE;
michael@0 545 }
michael@0 546
michael@0 547 for(i=0; (i < _this->numDigits) && (i < cmp->numDigits); i++) {
michael@0 548 scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]);
michael@0 549 if (scmp > 0) {
michael@0 550 return PR_FALSE;
michael@0 551 } else if (scmp < 0) {
michael@0 552 return PR_TRUE;
michael@0 553 }
michael@0 554 }
michael@0 555 /* All the digits they have in common are the same. */
michael@0 556 if(_this->numDigits < cmp->numDigits) {
michael@0 557 return PR_TRUE;
michael@0 558 }
michael@0 559
michael@0 560 return PR_FALSE;
michael@0 561 }
michael@0 562
michael@0 563 /*
michael@0 564 //////////////////////////////////////////////////////////////////////////
michael@0 565 // Method: GetString
michael@0 566 // Class: Pk11Install_PlatformName
michael@0 567 // Returns: String composed of OS, release, and architecture separated
michael@0 568 // by the separator char. Memory is allocated by this function
michael@0 569 // but is the responsibility of the caller to de-allocate.
michael@0 570 */
michael@0 571 char*
michael@0 572 Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this)
michael@0 573 {
michael@0 574 char *ret;
michael@0 575 char *ver;
michael@0 576 char *OS_;
michael@0 577 char *arch_;
michael@0 578
michael@0 579 OS_=NULL;
michael@0 580 arch_=NULL;
michael@0 581
michael@0 582 OS_ = _this->OS ? _this->OS : "";
michael@0 583 arch_ = _this->arch ? _this->arch : "";
michael@0 584
michael@0 585 ver = Pk11Install_PlatformName_GetVerString(_this);
michael@0 586 ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver,
michael@0 587 PLATFORM_SEPARATOR_CHAR, arch_);
michael@0 588
michael@0 589 PR_Free(ver);
michael@0 590
michael@0 591 return ret;
michael@0 592 }
michael@0 593
michael@0 594 /*
michael@0 595 //////////////////////////////////////////////////////////////////////////
michael@0 596 // Method: GetVerString
michael@0 597 // Class: Pk11Install_PlatformName
michael@0 598 // Returns: The version string for this platform, in the form x.x.x with an
michael@0 599 // arbitrary number of digits. Memory allocated by function,
michael@0 600 // must be de-allocated by caller.
michael@0 601 */
michael@0 602 char*
michael@0 603 Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this)
michael@0 604 {
michael@0 605 char *tmp;
michael@0 606 char *ret;
michael@0 607 int i;
michael@0 608 char buf[80];
michael@0 609
michael@0 610 tmp = (char*)PR_Malloc(80*_this->numDigits+1);
michael@0 611 tmp[0] = '\0';
michael@0 612
michael@0 613 for(i=0; i < _this->numDigits-1; i++) {
michael@0 614 sprintf(buf, "%s.", _this->verString[i]);
michael@0 615 strcat(tmp, buf);
michael@0 616 }
michael@0 617 if(i < _this->numDigits) {
michael@0 618 sprintf(buf, "%s", _this->verString[i]);
michael@0 619 strcat(tmp, buf);
michael@0 620 }
michael@0 621
michael@0 622 ret = PR_Strdup(tmp);
michael@0 623 free(tmp);
michael@0 624
michael@0 625 return ret;
michael@0 626 }
michael@0 627
michael@0 628 /*
michael@0 629 //////////////////////////////////////////////////////////////////////////
michael@0 630 // Method: Print
michael@0 631 // Class: Pk11Install_PlatformName
michael@0 632 */
michael@0 633 void
michael@0 634 Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad)
michael@0 635 {
michael@0 636 PAD(pad); printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>");
michael@0 637 PAD(pad); printf("Digits: ");
michael@0 638 if(_this->numDigits == 0) {
michael@0 639 printf("None\n");
michael@0 640 } else {
michael@0 641 printf("%s\n", Pk11Install_PlatformName_GetVerString(_this));
michael@0 642 }
michael@0 643 PAD(pad); printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>");
michael@0 644 }
michael@0 645
michael@0 646 Pk11Install_Platform*
michael@0 647 Pk11Install_Platform_new()
michael@0 648 {
michael@0 649 Pk11Install_Platform* new_this;
michael@0 650 new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform));
michael@0 651 Pk11Install_Platform_init(new_this);
michael@0 652 return new_this;
michael@0 653 }
michael@0 654
michael@0 655 void
michael@0 656 Pk11Install_Platform_init(Pk11Install_Platform* _this)
michael@0 657 {
michael@0 658 Pk11Install_PlatformName_init(&_this->name);
michael@0 659 Pk11Install_PlatformName_init(&_this->equivName);
michael@0 660 _this->equiv = NULL;
michael@0 661 _this->usesEquiv = PR_FALSE;
michael@0 662 _this->moduleFile = NULL;
michael@0 663 _this->moduleName = NULL;
michael@0 664 _this->modFile = -1;
michael@0 665 _this->mechFlags = 0;
michael@0 666 _this->cipherFlags = 0;
michael@0 667 _this->files = NULL;
michael@0 668 _this->numFiles = 0;
michael@0 669 }
michael@0 670
michael@0 671 /*
michael@0 672 //////////////////////////////////////////////////////////////////////////
michael@0 673 // Method: ~Pk11Install_Platform
michael@0 674 // Class: Pk11Install_Platform
michael@0 675 */
michael@0 676 void
michael@0 677 Pk11Install_Platform_delete(Pk11Install_Platform* _this)
michael@0 678 {
michael@0 679 Pk11Install_Platform_Cleanup(_this);
michael@0 680 }
michael@0 681
michael@0 682 /*
michael@0 683 //////////////////////////////////////////////////////////////////////////
michael@0 684 // Method: Cleanup
michael@0 685 // Class: Pk11Install_Platform
michael@0 686 */
michael@0 687 void
michael@0 688 Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this)
michael@0 689 {
michael@0 690 int i;
michael@0 691 if(_this->moduleFile) {
michael@0 692 PR_Free(_this->moduleFile);
michael@0 693 _this->moduleFile = NULL;
michael@0 694 }
michael@0 695 if(_this->moduleName) {
michael@0 696 PR_Free(_this->moduleName);
michael@0 697 _this->moduleName = NULL;
michael@0 698 }
michael@0 699 if(_this->files) {
michael@0 700 for (i=0;i<_this->numFiles;i++) {
michael@0 701 Pk11Install_File_delete(&_this->files[i]);
michael@0 702 }
michael@0 703 PR_Free(_this->files);
michael@0 704 _this->files = NULL;
michael@0 705 }
michael@0 706 _this->equiv = NULL;
michael@0 707 _this->usesEquiv = PR_FALSE;
michael@0 708 _this->modFile = -1;
michael@0 709 _this->numFiles = 0;
michael@0 710 _this->mechFlags = _this->cipherFlags = 0;
michael@0 711 }
michael@0 712
michael@0 713 /*
michael@0 714 //////////////////////////////////////////////////////////////////////////
michael@0 715 // Method: Generate
michael@0 716 // Class: Pk11Install_Platform
michael@0 717 // Notes: Creates a platform data structure from a syntax tree.
michael@0 718 // Returns: NULL for success, otherwise an error message.
michael@0 719 */
michael@0 720 char*
michael@0 721 Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
michael@0 722 const Pk11Install_Pair *pair)
michael@0 723 {
michael@0 724 char* errStr;
michael@0 725 char* endptr;
michael@0 726 char* tmp;
michael@0 727 int i;
michael@0 728 Pk11Install_ListIter *iter;
michael@0 729 Pk11Install_Value *val;
michael@0 730 Pk11Install_Value *subval;
michael@0 731 Pk11Install_Pair *subpair;
michael@0 732 Pk11Install_ListIter *subiter;
michael@0 733 PRBool gotModuleFile, gotModuleName, gotMech,
michael@0 734 gotCipher, gotFiles, gotEquiv;
michael@0 735
michael@0 736 errStr=NULL;
michael@0 737 iter=subiter=NULL;
michael@0 738 val=subval=NULL;
michael@0 739 subpair=NULL;
michael@0 740 gotModuleFile=gotModuleName=gotMech=gotCipher=gotFiles=gotEquiv=PR_FALSE;
michael@0 741 Pk11Install_Platform_Cleanup(_this);
michael@0 742
michael@0 743 errStr = Pk11Install_PlatformName_Generate(&_this->name,pair->key);
michael@0 744 if(errStr) {
michael@0 745 tmp = PR_smprintf("%s: %s", pair->key, errStr);
michael@0 746 PR_smprintf_free(errStr);
michael@0 747 errStr = tmp;
michael@0 748 goto loser;
michael@0 749 }
michael@0 750
michael@0 751 iter = Pk11Install_ListIter_new(pair->list);
michael@0 752 for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
michael@0 753 if(val->type==PAIR_VALUE) {
michael@0 754 subpair = val->pair;
michael@0 755
michael@0 756 if( !PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) {
michael@0 757 if(gotModuleFile) {
michael@0 758 errStr = PR_smprintf(errString[REPEAT_MODULE_FILE],
michael@0 759 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 760 goto loser;
michael@0 761 }
michael@0 762 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 763 subval = subiter->current;
michael@0 764 if(!subval || (subval->type != STRING_VALUE)) {
michael@0 765 errStr = PR_smprintf(errString[BOGUS_MODULE_FILE],
michael@0 766 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 767 goto loser;
michael@0 768 }
michael@0 769 _this->moduleFile = PR_Strdup(subval->string);
michael@0 770 Pk11Install_ListIter_delete(subiter);
michael@0 771 PR_Free(subiter);
michael@0 772 subiter = NULL;
michael@0 773 gotModuleFile = PR_TRUE;
michael@0 774 } else if(!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)){
michael@0 775 if(gotModuleName) {
michael@0 776 errStr = PR_smprintf(errString[REPEAT_MODULE_NAME],
michael@0 777 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 778 goto loser;
michael@0 779 }
michael@0 780 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 781 subval = subiter->current;
michael@0 782 if(!subval || (subval->type != STRING_VALUE)) {
michael@0 783 errStr = PR_smprintf(errString[BOGUS_MODULE_NAME],
michael@0 784 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 785 goto loser;
michael@0 786 }
michael@0 787 _this->moduleName = PR_Strdup(subval->string);
michael@0 788 Pk11Install_ListIter_delete(subiter);
michael@0 789 PR_Free(subiter);
michael@0 790 subiter = NULL;
michael@0 791 gotModuleName = PR_TRUE;
michael@0 792 } else if(!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) {
michael@0 793 endptr=NULL;
michael@0 794
michael@0 795 if(gotMech) {
michael@0 796 errStr = PR_smprintf(errString[REPEAT_MECH],
michael@0 797 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 798 goto loser;
michael@0 799 }
michael@0 800 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 801 subval = subiter->current;
michael@0 802 if(!subval || (subval->type != STRING_VALUE)) {
michael@0 803 errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
michael@0 804 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 805 goto loser;
michael@0 806 }
michael@0 807 _this->mechFlags = strtol(subval->string, &endptr, 0);
michael@0 808 if(*endptr!='\0' || (endptr==subval->string) ) {
michael@0 809 errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
michael@0 810 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 811 goto loser;
michael@0 812 }
michael@0 813 Pk11Install_ListIter_delete(subiter);
michael@0 814 PR_Free(subiter);
michael@0 815 subiter=NULL;
michael@0 816 gotMech = PR_TRUE;
michael@0 817 } else if(!PORT_Strcasecmp(subpair->key,CIPHER_FLAGS_STRING)) {
michael@0 818 endptr=NULL;
michael@0 819
michael@0 820 if(gotCipher) {
michael@0 821 errStr = PR_smprintf(errString[REPEAT_CIPHER],
michael@0 822 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 823 goto loser;
michael@0 824 }
michael@0 825 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 826 subval = subiter->current;
michael@0 827 if(!subval || (subval->type != STRING_VALUE)) {
michael@0 828 errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
michael@0 829 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 830 goto loser;
michael@0 831 }
michael@0 832 _this->cipherFlags = strtol(subval->string, &endptr, 0);
michael@0 833 if(*endptr!='\0' || (endptr==subval->string) ) {
michael@0 834 errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
michael@0 835 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 836 goto loser;
michael@0 837 }
michael@0 838 Pk11Install_ListIter_delete(subiter);
michael@0 839 PR_Free(subiter);
michael@0 840 subiter=NULL;
michael@0 841 gotCipher = PR_TRUE;
michael@0 842 } else if(!PORT_Strcasecmp(subpair->key, FILES_STRING)) {
michael@0 843 if(gotFiles) {
michael@0 844 errStr = PR_smprintf(errString[REPEAT_FILES],
michael@0 845 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 846 goto loser;
michael@0 847 }
michael@0 848 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 849 _this->numFiles = subpair->list->numPairs;
michael@0 850 _this->files = (Pk11Install_File*)
michael@0 851 PR_Malloc(sizeof(Pk11Install_File)*_this->numFiles);
michael@0 852 for(i=0; i < _this->numFiles; i++,
michael@0 853 Pk11Install_ListIter_nextItem(subiter)) {
michael@0 854 Pk11Install_File_init(&_this->files[i]);
michael@0 855 val = subiter->current;
michael@0 856 if(val && (val->type==PAIR_VALUE)) {
michael@0 857 errStr = Pk11Install_File_Generate(&_this->files[i],val->pair);
michael@0 858 if(errStr) {
michael@0 859 tmp = PR_smprintf("%s: %s",
michael@0 860 Pk11Install_PlatformName_GetString(&_this->name),errStr);
michael@0 861 PR_smprintf_free(errStr);
michael@0 862 errStr = tmp;
michael@0 863 goto loser;
michael@0 864 }
michael@0 865 }
michael@0 866 }
michael@0 867 gotFiles = PR_TRUE;
michael@0 868 } else if(!PORT_Strcasecmp(subpair->key,
michael@0 869 EQUIVALENT_PLATFORM_STRING)) {
michael@0 870 if(gotEquiv) {
michael@0 871 errStr = PR_smprintf(errString[REPEAT_EQUIV],
michael@0 872 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 873 goto loser;
michael@0 874 }
michael@0 875 subiter = Pk11Install_ListIter_new(subpair->list);
michael@0 876 subval = subiter->current;
michael@0 877 if(!subval || (subval->type != STRING_VALUE) ) {
michael@0 878 errStr = PR_smprintf(errString[BOGUS_EQUIV],
michael@0 879 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 880 goto loser;
michael@0 881 }
michael@0 882 errStr = Pk11Install_PlatformName_Generate(&_this->equivName,
michael@0 883 subval->string);
michael@0 884 if(errStr) {
michael@0 885 tmp = PR_smprintf("%s: %s",
michael@0 886 Pk11Install_PlatformName_GetString(&_this->name), errStr);
michael@0 887 tmp = PR_smprintf("%s: %s",
michael@0 888 Pk11Install_PlatformName_GetString(&_this->name), errStr);
michael@0 889 PR_smprintf_free(errStr);
michael@0 890 errStr = tmp;
michael@0 891 goto loser;
michael@0 892 }
michael@0 893 _this->usesEquiv = PR_TRUE;
michael@0 894 }
michael@0 895 }
michael@0 896 }
michael@0 897
michael@0 898 /* Make sure we either have an EquivalentPlatform or all the other info */
michael@0 899 if(_this->usesEquiv &&
michael@0 900 (gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) {
michael@0 901 errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO],
michael@0 902 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 903 goto loser;
michael@0 904 }
michael@0 905 if(!gotFiles && !_this->usesEquiv) {
michael@0 906 errStr = PR_smprintf(errString[NO_FILES],
michael@0 907 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 908 goto loser;
michael@0 909 }
michael@0 910 if(!gotModuleFile && !_this->usesEquiv) {
michael@0 911 errStr= PR_smprintf(errString[NO_MODULE_FILE],
michael@0 912 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 913 goto loser;
michael@0 914 }
michael@0 915 if(!gotModuleName && !_this->usesEquiv) {
michael@0 916 errStr = PR_smprintf(errString[NO_MODULE_NAME],
michael@0 917 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 918 goto loser;
michael@0 919 }
michael@0 920
michael@0 921 /* Point the modFile pointer to the correct file */
michael@0 922 if(gotModuleFile) {
michael@0 923 for(i=0; i < _this->numFiles; i++) {
michael@0 924 if(!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath) ) {
michael@0 925 _this->modFile = i;
michael@0 926 break;
michael@0 927 }
michael@0 928 }
michael@0 929 if(_this->modFile==-1) {
michael@0 930 errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE],
michael@0 931 _this->moduleFile,
michael@0 932 Pk11Install_PlatformName_GetString(&_this->name));
michael@0 933 goto loser;
michael@0 934 }
michael@0 935 }
michael@0 936
michael@0 937 loser:
michael@0 938 if(iter) {
michael@0 939 PR_Free(iter);
michael@0 940 }
michael@0 941 if(subiter) {
michael@0 942 PR_Free(subiter);
michael@0 943 }
michael@0 944 return errStr;
michael@0 945 }
michael@0 946
michael@0 947 /*
michael@0 948 //////////////////////////////////////////////////////////////////////////
michael@0 949 // Method: Print
michael@0 950 // Class: Pk11Install_Platform
michael@0 951 */
michael@0 952 void
michael@0 953 Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
michael@0 954 {
michael@0 955 int i;
michael@0 956
michael@0 957 PAD(pad); printf("Name:\n");
michael@0 958 Pk11Install_PlatformName_Print(&_this->name,pad+PADINC);
michael@0 959 PAD(pad); printf("equivName:\n");
michael@0 960 Pk11Install_PlatformName_Print(&_this->equivName,pad+PADINC);
michael@0 961 PAD(pad);
michael@0 962 if(_this->usesEquiv) {
michael@0 963 printf("Uses equiv, which points to:\n");
michael@0 964 Pk11Install_Platform_Print(_this->equiv,pad+PADINC);
michael@0 965 } else {
michael@0 966 printf("Doesn't use equiv\n");
michael@0 967 }
michael@0 968 PAD(pad);
michael@0 969 printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile
michael@0 970 : "<NULL>");
michael@0 971 PAD(pad); printf("mechFlags: %lx\n", _this->mechFlags);
michael@0 972 PAD(pad); printf("cipherFlags: %lx\n", _this->cipherFlags);
michael@0 973 PAD(pad); printf("Files:\n");
michael@0 974 for(i=0; i < _this->numFiles; i++) {
michael@0 975 Pk11Install_File_Print(&_this->files[i],pad+PADINC);
michael@0 976 PAD(pad); printf("--------------------\n");
michael@0 977 }
michael@0 978 }
michael@0 979
michael@0 980 /*
michael@0 981 //////////////////////////////////////////////////////////////////////////
michael@0 982 // Method: Pk11Install_Info
michael@0 983 // Class: Pk11Install_Info
michael@0 984 */
michael@0 985 Pk11Install_Info*
michael@0 986 Pk11Install_Info_new()
michael@0 987 {
michael@0 988 Pk11Install_Info* new_this;
michael@0 989 new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info));
michael@0 990 Pk11Install_Info_init(new_this);
michael@0 991 return new_this;
michael@0 992 }
michael@0 993
michael@0 994 void
michael@0 995 Pk11Install_Info_init(Pk11Install_Info* _this)
michael@0 996 {
michael@0 997 _this->platforms = NULL;
michael@0 998 _this->numPlatforms = 0;
michael@0 999 _this->forwardCompatible = NULL;
michael@0 1000 _this->numForwardCompatible = 0;
michael@0 1001 }
michael@0 1002
michael@0 1003 /*
michael@0 1004 //////////////////////////////////////////////////////////////////////////
michael@0 1005 // Method: ~Pk11Install_Info
michael@0 1006 // Class: Pk11Install_Info
michael@0 1007 */
michael@0 1008 void
michael@0 1009 Pk11Install_Info_delete(Pk11Install_Info* _this)
michael@0 1010 {
michael@0 1011 Pk11Install_Info_Cleanup(_this);
michael@0 1012 }
michael@0 1013
michael@0 1014 /*
michael@0 1015 //////////////////////////////////////////////////////////////////////////
michael@0 1016 // Method: Cleanup
michael@0 1017 // Class: Pk11Install_Info
michael@0 1018 */
michael@0 1019 void
michael@0 1020 Pk11Install_Info_Cleanup(Pk11Install_Info* _this)
michael@0 1021 {
michael@0 1022 int i;
michael@0 1023 if(_this->platforms) {
michael@0 1024 for (i=0;i<_this->numPlatforms;i++) {
michael@0 1025 Pk11Install_Platform_delete(&_this->platforms[i]);
michael@0 1026 }
michael@0 1027 PR_Free(&_this->platforms);
michael@0 1028 _this->platforms = NULL;
michael@0 1029 _this->numPlatforms = 0;
michael@0 1030 }
michael@0 1031
michael@0 1032 if(_this->forwardCompatible) {
michael@0 1033 for (i=0;i<_this->numForwardCompatible;i++) {
michael@0 1034 Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]);
michael@0 1035 }
michael@0 1036 PR_Free(&_this->forwardCompatible);
michael@0 1037 _this->numForwardCompatible = 0;
michael@0 1038 }
michael@0 1039 }
michael@0 1040
michael@0 1041 /*
michael@0 1042 //////////////////////////////////////////////////////////////////////////
michael@0 1043 // Method: Generate
michael@0 1044 // Class: Pk11Install_Info
michael@0 1045 // Takes: Pk11Install_ValueList *list, the top-level list
michael@0 1046 // resulting from parsing an installer file.
michael@0 1047 // Returns: char*, NULL if successful, otherwise an error string.
michael@0 1048 // Caller is responsible for freeing memory.
michael@0 1049 */
michael@0 1050 char*
michael@0 1051 Pk11Install_Info_Generate(Pk11Install_Info* _this,
michael@0 1052 const Pk11Install_ValueList *list)
michael@0 1053 {
michael@0 1054 char *errStr;
michael@0 1055 Pk11Install_ListIter *iter;
michael@0 1056 Pk11Install_Value *val;
michael@0 1057 Pk11Install_Pair *pair;
michael@0 1058 Pk11Install_ListIter *subiter;
michael@0 1059 Pk11Install_Value *subval;
michael@0 1060 Pk11Install_Platform *first, *second;
michael@0 1061 int i, j;
michael@0 1062
michael@0 1063 errStr=NULL;
michael@0 1064 iter=subiter=NULL;
michael@0 1065 Pk11Install_Info_Cleanup(_this);
michael@0 1066
michael@0 1067 iter = Pk11Install_ListIter_new(list);
michael@0 1068 for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
michael@0 1069 if(val->type == PAIR_VALUE) {
michael@0 1070 pair = val->pair;
michael@0 1071
michael@0 1072 if(!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) {
michael@0 1073 subiter = Pk11Install_ListIter_new(pair->list);
michael@0 1074 _this->numForwardCompatible = pair->list->numStrings;
michael@0 1075 _this->forwardCompatible = (Pk11Install_PlatformName*)
michael@0 1076 PR_Malloc(sizeof(Pk11Install_PlatformName)*
michael@0 1077 _this->numForwardCompatible);
michael@0 1078 for(i=0; i < _this->numForwardCompatible; i++,
michael@0 1079 Pk11Install_ListIter_nextItem(subiter)) {
michael@0 1080 subval = subiter->current;
michael@0 1081 if(subval->type == STRING_VALUE) {
michael@0 1082 errStr = Pk11Install_PlatformName_Generate(
michael@0 1083 &_this->forwardCompatible[i], subval->string);
michael@0 1084 if(errStr) {
michael@0 1085 goto loser;
michael@0 1086 }
michael@0 1087 }
michael@0 1088 }
michael@0 1089 Pk11Install_ListIter_delete(subiter);
michael@0 1090 PR_Free(subiter);
michael@0 1091 subiter = NULL;
michael@0 1092 } else if(!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) {
michael@0 1093 subiter = Pk11Install_ListIter_new(pair->list);
michael@0 1094 _this->numPlatforms = pair->list->numPairs;
michael@0 1095 _this->platforms = (Pk11Install_Platform*)
michael@0 1096 PR_Malloc(sizeof(Pk11Install_Platform)*
michael@0 1097 _this->numPlatforms);
michael@0 1098 for(i=0; i < _this->numPlatforms; i++,
michael@0 1099 Pk11Install_ListIter_nextItem(subiter)) {
michael@0 1100 Pk11Install_Platform_init(&_this->platforms[i]);
michael@0 1101 subval = subiter->current;
michael@0 1102 if(subval->type == PAIR_VALUE) {
michael@0 1103 errStr = Pk11Install_Platform_Generate(&_this->platforms[i],subval->pair);
michael@0 1104 if(errStr) {
michael@0 1105 goto loser;
michael@0 1106 }
michael@0 1107 }
michael@0 1108 }
michael@0 1109 Pk11Install_ListIter_delete(subiter);
michael@0 1110 PR_Free(subiter);
michael@0 1111 subiter = NULL;
michael@0 1112 }
michael@0 1113 }
michael@0 1114 }
michael@0 1115
michael@0 1116 if(_this->numPlatforms == 0) {
michael@0 1117 errStr = PR_smprintf(errString[NO_PLATFORMS]);
michael@0 1118 goto loser;
michael@0 1119 }
michael@0 1120
michael@0 1121 /*
michael@0 1122 //
michael@0 1123 // Now process equivalent platforms
michael@0 1124 //
michael@0 1125
michael@0 1126 // First the naive pass
michael@0 1127 */
michael@0 1128 for(i=0; i < _this->numPlatforms; i++) {
michael@0 1129 if(_this->platforms[i].usesEquiv) {
michael@0 1130 _this->platforms[i].equiv = NULL;
michael@0 1131 for(j=0; j < _this->numPlatforms; j++) {
michael@0 1132 if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName,
michael@0 1133 &_this->platforms[j].name)) {
michael@0 1134 if(i==j) {
michael@0 1135 errStr = PR_smprintf(errString[EQUIV_LOOP],
michael@0 1136 Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
michael@0 1137 goto loser;
michael@0 1138 }
michael@0 1139 _this->platforms[i].equiv = &_this->platforms[j];
michael@0 1140 break;
michael@0 1141 }
michael@0 1142 }
michael@0 1143 if(_this->platforms[i].equiv == NULL) {
michael@0 1144 errStr = PR_smprintf(errString[BOGUS_EQUIV],
michael@0 1145 Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
michael@0 1146 goto loser;
michael@0 1147 }
michael@0 1148 }
michael@0 1149 }
michael@0 1150
michael@0 1151 /*
michael@0 1152 // Now the intelligent pass, which will also detect loops.
michael@0 1153 // We will send two pointers through the linked list of equivalent
michael@0 1154 // platforms. Both start with the current node. "first" traverses
michael@0 1155 // two nodes for each iteration. "second" lags behind, only traversing
michael@0 1156 // one node per iteration. Eventually one of two things will happen:
michael@0 1157 // first will hit the end of the list (a platform that doesn't use
michael@0 1158 // an equivalency), or first will equal second if there is a loop.
michael@0 1159 */
michael@0 1160 for(i=0; i < _this->numPlatforms; i++) {
michael@0 1161 if(_this->platforms[i].usesEquiv) {
michael@0 1162 second = _this->platforms[i].equiv;
michael@0 1163 if(!second->usesEquiv) {
michael@0 1164 /* The first link is the terminal node */
michael@0 1165 continue;
michael@0 1166 }
michael@0 1167 first = second->equiv;
michael@0 1168 while(first->usesEquiv) {
michael@0 1169 if(first == second) {
michael@0 1170 errStr = PR_smprintf(errString[EQUIV_LOOP],
michael@0 1171 Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
michael@0 1172 goto loser;
michael@0 1173 }
michael@0 1174 first = first->equiv;
michael@0 1175 if(!first->usesEquiv) {
michael@0 1176 break;
michael@0 1177 }
michael@0 1178 if(first == second) {
michael@0 1179 errStr = PR_smprintf(errString[EQUIV_LOOP],
michael@0 1180 Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
michael@0 1181 goto loser;
michael@0 1182 }
michael@0 1183 second = second->equiv;
michael@0 1184 first = first->equiv;
michael@0 1185 }
michael@0 1186 _this->platforms[i].equiv = first;
michael@0 1187 }
michael@0 1188 }
michael@0 1189
michael@0 1190 loser:
michael@0 1191 if(iter) {
michael@0 1192 Pk11Install_ListIter_delete(iter);
michael@0 1193 PR_Free(iter);
michael@0 1194 iter = NULL;
michael@0 1195 }
michael@0 1196 if(subiter) {
michael@0 1197 Pk11Install_ListIter_delete(subiter);
michael@0 1198 PR_Free(subiter);
michael@0 1199 subiter = NULL;
michael@0 1200 }
michael@0 1201 return errStr;
michael@0 1202 }
michael@0 1203
michael@0 1204 /*
michael@0 1205 //////////////////////////////////////////////////////////////////////////
michael@0 1206 // Method: GetBestPlatform
michael@0 1207 // Class: Pk11Install_Info
michael@0 1208 // Takes: char *myPlatform, the platform we are currently running
michael@0 1209 // on.
michael@0 1210 */
michael@0 1211 Pk11Install_Platform*
michael@0 1212 Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char *myPlatform)
michael@0 1213 {
michael@0 1214 Pk11Install_PlatformName plat;
michael@0 1215 char *errStr;
michael@0 1216 int i, j;
michael@0 1217
michael@0 1218 errStr=NULL;
michael@0 1219
michael@0 1220 Pk11Install_PlatformName_init(&plat);
michael@0 1221 if( (errStr=Pk11Install_PlatformName_Generate(&plat, myPlatform)) ) {
michael@0 1222 PR_smprintf_free(errStr);
michael@0 1223 return NULL;
michael@0 1224 }
michael@0 1225
michael@0 1226 /* First try real platforms */
michael@0 1227 for(i=0; i < _this->numPlatforms; i++) {
michael@0 1228 if(Pk11Install_PlatformName_equal(&_this->platforms[i].name,&plat)) {
michael@0 1229 if(_this->platforms[i].equiv) {
michael@0 1230 return _this->platforms[i].equiv;
michael@0 1231 }
michael@0 1232 else {
michael@0 1233 return &_this->platforms[i];
michael@0 1234 }
michael@0 1235 }
michael@0 1236 }
michael@0 1237
michael@0 1238 /* Now try forward compatible platforms */
michael@0 1239 for(i=0; i < _this->numForwardCompatible; i++) {
michael@0 1240 if(Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i],&plat)) {
michael@0 1241 break;
michael@0 1242 }
michael@0 1243 }
michael@0 1244 if(i == _this->numForwardCompatible) {
michael@0 1245 return NULL;
michael@0 1246 }
michael@0 1247
michael@0 1248 /* Got a forward compatible name, find the actual platform. */
michael@0 1249 for(j=0; j < _this->numPlatforms; j++) {
michael@0 1250 if(Pk11Install_PlatformName_equal(&_this->platforms[j].name,
michael@0 1251 &_this->forwardCompatible[i])) {
michael@0 1252 if(_this->platforms[j].equiv) {
michael@0 1253 return _this->platforms[j].equiv;
michael@0 1254 } else {
michael@0 1255 return &_this->platforms[j];
michael@0 1256 }
michael@0 1257 }
michael@0 1258 }
michael@0 1259
michael@0 1260 return NULL;
michael@0 1261 }
michael@0 1262
michael@0 1263 /*
michael@0 1264 //////////////////////////////////////////////////////////////////////////
michael@0 1265 // Method: Print
michael@0 1266 // Class: Pk11Install_Info
michael@0 1267 */
michael@0 1268 void
michael@0 1269 Pk11Install_Info_Print(Pk11Install_Info* _this, int pad)
michael@0 1270 {
michael@0 1271 int i;
michael@0 1272
michael@0 1273 PAD(pad); printf("Forward Compatible:\n");
michael@0 1274 for(i = 0; i < _this->numForwardCompatible; i++) {
michael@0 1275 Pk11Install_PlatformName_Print(&_this->forwardCompatible[i],pad+PADINC);
michael@0 1276 PAD(pad); printf("-------------------\n");
michael@0 1277 }
michael@0 1278 PAD(pad); printf("Platforms:\n");
michael@0 1279 for( i = 0; i < _this->numPlatforms; i++) {
michael@0 1280 Pk11Install_Platform_Print(&_this->platforms[i],pad+PADINC);
michael@0 1281 PAD(pad); printf("-------------------\n");
michael@0 1282 }
michael@0 1283 }
michael@0 1284
michael@0 1285 /*
michael@0 1286 //////////////////////////////////////////////////////////////////////////
michael@0 1287 */
michael@0 1288 static char*
michael@0 1289 PR_Strdup(const char* str)
michael@0 1290 {
michael@0 1291 char *tmp;
michael@0 1292 tmp = (char*) PR_Malloc((unsigned int)(strlen(str)+1));
michael@0 1293 strcpy(tmp, str);
michael@0 1294 return tmp;
michael@0 1295 }
michael@0 1296
michael@0 1297 /* The global value list, the top of the tree */
michael@0 1298 Pk11Install_ValueList* Pk11Install_valueList=NULL;
michael@0 1299
michael@0 1300 /****************************************************************************/
michael@0 1301 void
michael@0 1302 Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
michael@0 1303 Pk11Install_Value *item)
michael@0 1304 {
michael@0 1305 _this->numItems++;
michael@0 1306 if (item->type == STRING_VALUE) {
michael@0 1307 _this->numStrings++;
michael@0 1308 } else {
michael@0 1309 _this->numPairs++;
michael@0 1310 }
michael@0 1311 item->next = _this->head;
michael@0 1312 _this->head = item;
michael@0 1313 }
michael@0 1314
michael@0 1315 /****************************************************************************/
michael@0 1316 Pk11Install_ListIter*
michael@0 1317 Pk11Install_ListIter_new_default()
michael@0 1318 {
michael@0 1319 Pk11Install_ListIter* new_this;
michael@0 1320 new_this = (Pk11Install_ListIter*)
michael@0 1321 PR_Malloc(sizeof(Pk11Install_ListIter));
michael@0 1322 Pk11Install_ListIter_init(new_this);
michael@0 1323 return new_this;
michael@0 1324 }
michael@0 1325
michael@0 1326 /****************************************************************************/
michael@0 1327 void
michael@0 1328 Pk11Install_ListIter_init(Pk11Install_ListIter* _this)
michael@0 1329 {
michael@0 1330 _this->list = NULL;
michael@0 1331 _this->current = NULL;
michael@0 1332 }
michael@0 1333
michael@0 1334 /****************************************************************************/
michael@0 1335 Pk11Install_ListIter*
michael@0 1336 Pk11Install_ListIter_new(const Pk11Install_ValueList *_list)
michael@0 1337 {
michael@0 1338 Pk11Install_ListIter* new_this;
michael@0 1339 new_this = (Pk11Install_ListIter*)
michael@0 1340 PR_Malloc(sizeof(Pk11Install_ListIter));
michael@0 1341 new_this->list = _list;
michael@0 1342 new_this->current = _list->head;
michael@0 1343 return new_this;
michael@0 1344 }
michael@0 1345
michael@0 1346 /****************************************************************************/
michael@0 1347 void
michael@0 1348 Pk11Install_ListIter_delete(Pk11Install_ListIter* _this)
michael@0 1349 {
michael@0 1350 _this->list=NULL;
michael@0 1351 _this->current=NULL;
michael@0 1352 }
michael@0 1353
michael@0 1354 /****************************************************************************/
michael@0 1355 void
michael@0 1356 Pk11Install_ListIter_reset(Pk11Install_ListIter* _this)
michael@0 1357 {
michael@0 1358 if(_this->list) {
michael@0 1359 _this->current = _this->list->head;
michael@0 1360 }
michael@0 1361 }
michael@0 1362
michael@0 1363 /*************************************************************************/
michael@0 1364 Pk11Install_Value*
michael@0 1365 Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this)
michael@0 1366 {
michael@0 1367 if(_this->current) {
michael@0 1368 _this->current = _this->current->next;
michael@0 1369 }
michael@0 1370
michael@0 1371 return _this->current;
michael@0 1372 }
michael@0 1373
michael@0 1374 /****************************************************************************/
michael@0 1375 Pk11Install_ValueList*
michael@0 1376 Pk11Install_ValueList_new()
michael@0 1377 {
michael@0 1378 Pk11Install_ValueList* new_this;
michael@0 1379 new_this = (Pk11Install_ValueList*)
michael@0 1380 PR_Malloc(sizeof(Pk11Install_ValueList));
michael@0 1381 new_this->numItems = 0;
michael@0 1382 new_this->numPairs = 0;
michael@0 1383 new_this->numStrings = 0;
michael@0 1384 new_this->head = NULL;
michael@0 1385 return new_this;
michael@0 1386 }
michael@0 1387
michael@0 1388 /****************************************************************************/
michael@0 1389 void
michael@0 1390 Pk11Install_ValueList_delete(Pk11Install_ValueList* _this)
michael@0 1391 {
michael@0 1392
michael@0 1393 Pk11Install_Value *tmp;
michael@0 1394 Pk11Install_Value *list;
michael@0 1395 list = _this->head;
michael@0 1396
michael@0 1397 while(list != NULL) {
michael@0 1398 tmp = list;
michael@0 1399 list = list->next;
michael@0 1400 PR_Free(tmp);
michael@0 1401 }
michael@0 1402 PR_Free(_this);
michael@0 1403 }
michael@0 1404
michael@0 1405 /****************************************************************************/
michael@0 1406 Pk11Install_Value*
michael@0 1407 Pk11Install_Value_new_default()
michael@0 1408 {
michael@0 1409 Pk11Install_Value* new_this;
michael@0 1410 new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value));
michael@0 1411 new_this->type = STRING_VALUE;
michael@0 1412 new_this->string = NULL;
michael@0 1413 new_this->pair = NULL;
michael@0 1414 new_this->next = NULL;
michael@0 1415 return new_this;
michael@0 1416 }
michael@0 1417
michael@0 1418 /****************************************************************************/
michael@0 1419 Pk11Install_Value*
michael@0 1420 Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr)
michael@0 1421 {
michael@0 1422 Pk11Install_Value* new_this;
michael@0 1423 new_this = Pk11Install_Value_new_default();
michael@0 1424 new_this->type = _type;
michael@0 1425 if(_type == STRING_VALUE) {
michael@0 1426 new_this->pair = NULL;
michael@0 1427 new_this->string = ptr.string;
michael@0 1428 } else {
michael@0 1429 new_this->string = NULL;
michael@0 1430 new_this->pair = ptr.pair;
michael@0 1431 }
michael@0 1432 return new_this;
michael@0 1433 }
michael@0 1434
michael@0 1435 /****************************************************************************/
michael@0 1436 void
michael@0 1437 Pk11Install_Value_delete(Pk11Install_Value* _this)
michael@0 1438 {
michael@0 1439 if(_this->type == STRING_VALUE) {
michael@0 1440 PR_Free(_this->string);
michael@0 1441 } else {
michael@0 1442 PR_Free(_this->pair);
michael@0 1443 }
michael@0 1444 }
michael@0 1445
michael@0 1446 /****************************************************************************/
michael@0 1447 Pk11Install_Pair*
michael@0 1448 Pk11Install_Pair_new_default()
michael@0 1449 {
michael@0 1450 return Pk11Install_Pair_new(NULL,NULL);
michael@0 1451 }
michael@0 1452
michael@0 1453 /****************************************************************************/
michael@0 1454 Pk11Install_Pair*
michael@0 1455 Pk11Install_Pair_new(char *_key, Pk11Install_ValueList *_list)
michael@0 1456 {
michael@0 1457 Pk11Install_Pair* new_this;
michael@0 1458 new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair));
michael@0 1459 new_this->key = _key;
michael@0 1460 new_this->list = _list;
michael@0 1461 return new_this;
michael@0 1462 }
michael@0 1463
michael@0 1464 /****************************************************************************/
michael@0 1465 void
michael@0 1466 Pk11Install_Pair_delete(Pk11Install_Pair* _this)
michael@0 1467 {
michael@0 1468 PR_Free(_this->key);
michael@0 1469 Pk11Install_ValueList_delete(_this->list);
michael@0 1470 PR_Free(_this->list);
michael@0 1471 }
michael@0 1472
michael@0 1473 /*************************************************************************/
michael@0 1474 void
michael@0 1475 Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad)
michael@0 1476 {
michael@0 1477 while (_this) {
michael@0 1478 /*PAD(pad); printf("**Pair\n");
michael@0 1479 PAD(pad); printf("***Key====\n");*/
michael@0 1480 PAD(pad); printf("%s {\n", _this->key);
michael@0 1481 /*PAD(pad); printf("====\n");*/
michael@0 1482 /*PAD(pad); printf("***ValueList\n");*/
michael@0 1483 Pk11Install_ValueList_Print(_this->list,pad+PADINC);
michael@0 1484 PAD(pad); printf("}\n");
michael@0 1485 }
michael@0 1486 }
michael@0 1487
michael@0 1488 /*************************************************************************/
michael@0 1489 void
michael@0 1490 Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad)
michael@0 1491 {
michael@0 1492 Pk11Install_Value *v;
michael@0 1493
michael@0 1494 /*PAD(pad);printf("**Value List**\n");*/
michael@0 1495 for(v = _this->head; v != NULL; v=v->next) {
michael@0 1496 Pk11Install_Value_Print(v,pad);
michael@0 1497 }
michael@0 1498 }
michael@0 1499
michael@0 1500 /*************************************************************************/
michael@0 1501 void
michael@0 1502 Pk11Install_Value_Print(Pk11Install_Value* _this, int pad)
michael@0 1503 {
michael@0 1504 /*PAD(pad); printf("**Value, type=%s\n",
michael@0 1505 type==STRING_VALUE ? "string" : "pair");*/
michael@0 1506 if(_this->type==STRING_VALUE) {
michael@0 1507 /*PAD(pad+PADINC); printf("====\n");*/
michael@0 1508 PAD(pad); printf("%s\n", _this->string);
michael@0 1509 /*PAD(pad+PADINC); printf("====\n");*/
michael@0 1510 } else {
michael@0 1511 Pk11Install_Pair_Print(_this->pair,pad+PADINC);
michael@0 1512 }
michael@0 1513 }

mercurial