Bug Summary

File:s/cmd/modutil/install.c
Warning:line 327, column 5
Value stored to 'ret' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name install.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/modutil -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/modutil -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D NSPR20 -D YY_NO_UNPUT -D YY_NO_INPUT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/sectools -I ../../../dist/private/sectools -I ../../../dist/public/seccmd -I ../../../dist/public/nss -I ../../../dist/public/dbm -I ../../../dist/private/seccmd -I ../../../dist/private/nss -I ../../../dist/private/dbm -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c install.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "install.h"
6#include "install-ds.h"
7#include <prerror.h>
8#include <prlock.h>
9#include <prio.h>
10#include <prmem.h>
11#include <prprf.h>
12#include <prsystem.h>
13#include <prproces.h>
14
15#ifdef XP_UNIX1
16/* for chmod */
17#include <sys/types.h>
18#include <sys/stat.h>
19#endif
20
21/*extern "C" {*/
22#include <jar.h>
23/*}*/
24
25extern /*"C"*/
26 int
27 Pk11Install_AddNewModule(char *moduleName, char *dllPath,
28 unsigned long defaultMechanismFlags,
29 unsigned long cipherEnableFlags);
30extern /*"C"*/
31 short
32 Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out,
33 PRBool query);
34extern /*"C"*/
35 const char *
36 mySECU_ErrorString(PRErrorCode errnum);
37extern int Pk11Install_yyparse();
38
39#define INSTALL_METAINFO_TAG"Pkcs11_install_script" "Pkcs11_install_script"
40#define SCRIPT_TEMP_FILE"pkcs11inst.tmp" "pkcs11inst.tmp"
41#define ROOT_MARKER"%root%" "%root%"
42#define TEMP_MARKER"%temp%" "%temp%"
43#define PRINTF_ROOT_MARKER"%%root%%" "%%root%%"
44#define TEMPORARY_DIRECTORY_NAME"pk11inst.dir" "pk11inst.dir"
45#define JAR_BASE_END((-0x2000) + 300 + 100) (JAR_BASE(-0x2000) + 300 + 100)
46
47static PRLock *errorHandlerLock = NULL((void*)0);
48static Pk11Install_ErrorHandler errorHandler = NULL((void*)0);
49static char *PR_Strdup(const char *str);
50static int rm_dash_r(char *path);
51static int make_dirs(char *path, int file_perms);
52static int dir_perms(int perms);
53
54static Pk11Install_Error DoInstall(JAR *jar, const char *installDir,
55 const char *tempDir, Pk11Install_Platform *platform,
56 PRFileDesc *feedback, PRBool noverify);
57
58static char *errorString[] = {
59 "Operation was successful", /* PK11_INSTALL_NO_ERROR */
60 "Directory \"%s\" does not exist", /* PK11_INSTALL_DIR_DOESNT_EXIST */
61 "File \"%s\" does not exist", /* PK11_INSTALL_FILE_DOESNT_EXIST */
62 "File \"%s\" is not readable", /* PK11_INSTALL_FILE_NOT_READABLE */
63 "%s", /* PK11_INSTALL_ERROR_STRING */
64 "Error in JAR file %s: %s", /* PK11_INSTALL_JAR_ERROR */
65 "No Pkcs11_install_script specified in JAR metainfo file",
66 /* PK11_INSTALL_NO_INSTALLER_SCRIPT */
67 "Could not delete temporary file \"%s\"",
68 /*PK11_INSTALL_DELETE_TEMP_FILE */
69 "Could not open temporary file \"%s\"", /*PK11_INSTALL_OPEN_SCRIPT_FILE*/
70 "%s: %s", /* PK11_INSTALL_SCRIPT_PARSE */
71 "Error in script: %s",
72 "Unable to obtain system platform information",
73 "Installer script has no information about the current platform (%s)",
74 "Relative directory \"%s\" does not contain " PRINTF_ROOT_MARKER"%%root%%",
75 "Module File \"%s\" not found",
76 "Error occurred installing module \"%s\" into database",
77 "Error extracting \"%s\" from JAR file: %s",
78 "Directory \"%s\" is not writeable",
79 "Could not create directory \"%s\"",
80 "Could not remove directory \"%s\"",
81 "Unable to execute \"%s\"",
82 "Unable to wait for process \"%s\"",
83 "\"%s\" returned error code %d",
84 "User aborted operation",
85 "Unspecified error"
86};
87
88enum {
89 INSTALLED_FILE_MSG = 0,
90 INSTALLED_MODULE_MSG,
91 INSTALLER_SCRIPT_NAME,
92 MY_PLATFORM_IS,
93 USING_PLATFORM,
94 PARSED_INSTALL_SCRIPT,
95 EXEC_FILE_MSG,
96 EXEC_SUCCESS,
97 INSTALLATION_COMPLETE_MSG,
98 USER_ABORT
99};
100
101static char *msgStrings[] = {
102 "Installed file %s to %s\n",
103 "Installed module \"%s\" into module database\n",
104 "Using installer script \"%s\"\n",
105 "Current platform is %s\n",
106 "Using installation parameters for platform %s\n",
107 "Successfully parsed installation script\n",
108 "Executing \"%s\"...\n",
109 "\"%s\" executed successfully\n",
110 "\nInstallation completed successfully\n",
111 "\nAborting...\n"
112};
113
114/**************************************************************************
115 * S t r i n g N o d e
116 */
117typedef struct StringNode_str {
118 char *str;
119 struct StringNode_str *next;
120} StringNode;
121
122StringNode *
123StringNode_new()
124{
125 StringNode *new_this;
126 new_this = (StringNode *)PR_Malloc(sizeof(StringNode));
127 PORT_Assert(new_this != NULL)((new_this != ((void*)0))?((void)0):PR_Assert("new_this != NULL"
,"install.c",127))
;
128 new_this->str = NULL((void*)0);
129 new_this->next = NULL((void*)0);
130 return new_this;
131}
132
133void
134StringNode_delete(StringNode *s)
135{
136 if (s->str) {
137 PR_Free(s->str);
138 s->str = NULL((void*)0);
139 }
140}
141
142/*************************************************************************
143 * S t r i n g L i s t
144 */
145typedef struct StringList_str {
146 StringNode *head;
147 StringNode *tail;
148} StringList;
149
150void
151StringList_new(StringList *list)
152{
153 list->head = NULL((void*)0);
154 list->tail = NULL((void*)0);
155}
156
157void
158StringList_delete(StringList *list)
159{
160 StringNode *tmp;
161 while (list->head) {
162 tmp = list->head;
163 list->head = list->head->next;
164 StringNode_delete(tmp);
165 }
166}
167
168void
169StringList_Append(StringList *list, char *str)
170{
171 if (!str) {
172 return;
173 }
174
175 if (!list->tail) {
176 /* This is the first element */
177 list->head = list->tail = StringNode_new();
178 } else {
179 list->tail->next = StringNode_new();
180 list->tail = list->tail->next;
181 }
182
183 list->tail->str = PR_Strdup(str);
184 list->tail->next = NULL((void*)0); /* just to be sure */
185}
186
187/**************************************************************************
188 *
189 * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r
190 *
191 * Sets the error handler to be used by the library. Returns the current
192 * error handler function.
193 */
194Pk11Install_ErrorHandler
195Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler)
196{
197 Pk11Install_ErrorHandler old;
198
199 if (!errorHandlerLock) {
200 errorHandlerLock = PR_NewLock();
201 }
202
203 PR_Lock(errorHandlerLock);
204
205 old = errorHandler;
206 errorHandler = handler;
207
208 PR_Unlock(errorHandlerLock);
209
210 return old;
211}
212
213/**************************************************************************
214 *
215 * P k 1 1 I n s t a l l _ I n i t
216 *
217 * Does initialization that otherwise would be done on the fly. Only
218 * needs to be called by multithreaded apps, before they make any calls
219 * to this library.
220 */
221void
222Pk11Install_Init()
223{
224 if (!errorHandlerLock) {
225 errorHandlerLock = PR_NewLock();
226 }
227}
228
229/**************************************************************************
230 *
231 * P k 1 1 I n s t a l l _ R e l e a s e
232 *
233 * Releases static data structures used by the library. Don't use the
234 * library after calling this, unless you call Pk11Install_Init()
235 * first. This function doesn't have to be called at all unless you're
236 * really anal about freeing memory before your program exits.
237 */
238void
239Pk11Install_Release()
240{
241 if (errorHandlerLock) {
242 PR_Free(errorHandlerLock);
243 errorHandlerLock = NULL((void*)0);
244 }
245}
246
247/*************************************************************************
248 *
249 * e r r o r
250 *
251 * Takes an error code and its arguments, creates the error string,
252 * and sends the string to the handler function if it exists.
253 */
254
255#include <stdarg.h>
256
257static void
258error(PRErrorCode errcode, ...)
259{
260
261 va_list ap;
262 char *errstr;
263 Pk11Install_ErrorHandler handler;
264
265 if (!errorHandlerLock) {
266 errorHandlerLock = PR_NewLock();
267 }
268
269 PR_Lock(errorHandlerLock);
270
271 handler = errorHandler;
272
273 PR_Unlock(errorHandlerLock);
274
275 if (handler) {
276 va_start(ap, errcode)__builtin_va_start(ap, errcode);
277 errstr = PR_vsmprintf(errorString[errcode], ap);
278 handler(errstr);
279 PR_smprintf_free(errstr);
280 va_end(ap)__builtin_va_end(ap);
281 }
282}
283
284/*************************************************************************
285 *
286 * j a r _ c a l l b a c k
287 */
288static int
289jar_callback(int status, JAR *foo, const char *bar, char *pathname,
290 char *errortext)
291{
292 char *string;
293
294 string = PR_smprintf("JAR error %d: %s in file %s\n", status, errortext,
295 pathname);
296 error(PK11_INSTALL_ERROR_STRING, string);
297 PR_smprintf_free(string);
298 return 0;
299}
300
301/*************************************************************************
302 *
303 * P k 1 1 I n s t a l l _ D o I n s t a l l
304 *
305 * jarFile is the path of a JAR in the PKCS #11 module JAR format.
306 * installDir is the directory relative to which files will be
307 * installed.
308 */
309Pk11Install_Error
310Pk11Install_DoInstall(char *jarFile, const char *installDir,
311 const char *tempDir, PRFileDesc *feedback, short force, PRBool noverify)
312{
313 JAR *jar;
314 char *installer;
315 unsigned long installer_len;
316 int status;
317 Pk11Install_Error ret;
318 PRBool made_temp_file;
319 Pk11Install_Info installInfo;
320 Pk11Install_Platform *platform;
321 char *errMsg;
322 char sysname[SYS_INFO_BUFFER_LENGTH256], release[SYS_INFO_BUFFER_LENGTH256],
323 arch[SYS_INFO_BUFFER_LENGTH256];
324 char *myPlatform;
325
326 jar = NULL((void*)0);
327 ret = PK11_INSTALL_UNSPECIFIED;
Value stored to 'ret' is never read
328 made_temp_file = PR_FALSE0;
329 errMsg = NULL((void*)0);
330 Pk11Install_Info_init(&installInfo);
331
332 /*
333 printf("Inside DoInstall, jarFile=%s, installDir=%s, tempDir=%s\n",
334 jarFile, installDir, tempDir);
335 */
336
337 /*
338 * Check out jarFile and installDir for validity
339 */
340 if (PR_Access(installDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
341 error(PK11_INSTALL_DIR_DOESNT_EXIST, installDir);
342 return PK11_INSTALL_DIR_DOESNT_EXIST;
343 }
344 if (!tempDir) {
345 tempDir = ".";
346 }
347 if (PR_Access(tempDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
348 error(PK11_INSTALL_DIR_DOESNT_EXIST, tempDir);
349 return PK11_INSTALL_DIR_DOESNT_EXIST;
350 }
351 if (PR_Access(tempDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
352 error(PK11_INSTALL_DIR_NOT_WRITEABLE, tempDir);
353 return PK11_INSTALL_DIR_NOT_WRITEABLE;
354 }
355 if ((PR_Access(jarFile, PR_ACCESS_EXISTS) != PR_SUCCESS)) {
356 error(PK11_INSTALL_FILE_DOESNT_EXIST, jarFile);
357 return PK11_INSTALL_FILE_DOESNT_EXIST;
358 }
359 if (PR_Access(jarFile, PR_ACCESS_READ_OK) != PR_SUCCESS) {
360 error(PK11_INSTALL_FILE_NOT_READABLE, jarFile);
361 return PK11_INSTALL_FILE_NOT_READABLE;
362 }
363
364 /*
365 * Extract the JAR file
366 */
367 jar = JAR_new();
368 JAR_set_callback(JAR_CB_SIGNAL1, jar, jar_callback);
369
370 if (noverify) {
371 status = JAR_pass_archive_unverified(jar, jarArchGuess, jarFile, "url");
372 } else {
373 status = JAR_pass_archive(jar, jarArchGuess, jarFile, "url");
374 }
375 if ((status < 0) || (jar->valid < 0)) {
376 if (status >= JAR_BASE(-0x2000) + 300 && status <= JAR_BASE_END((-0x2000) + 300 + 100)) {
377 error(PK11_INSTALL_JAR_ERROR, jarFile, JAR_get_error(status));
378 } else {
379 error(PK11_INSTALL_JAR_ERROR, jarFile,
380 mySECU_ErrorString(PORT_GetErrorPORT_GetError_Util()));
381 }
382 ret = PK11_INSTALL_JAR_ERROR;
383 goto loser;
384 }
385 /*printf("passed the archive\n");*/
386
387 /*
388 * Show the user security information, allow them to abort or continue
389 */
390 if (Pk11Install_UserVerifyJar(jar, PR_STDOUTPR_GetSpecialFD(PR_StandardOutput),
391 force ? PR_FALSE0
392 : PR_TRUE1) &&
393 !force) {
394 if (feedback) {
395 PR_fprintf(feedback, msgStrings[USER_ABORT]);
396 }
397 ret = PK11_INSTALL_USER_ABORT;
398 goto loser;
399 }
400
401 /*
402 * Get the name of the installation file
403 */
404 if (JAR_get_metainfo(jar, NULL((void*)0), INSTALL_METAINFO_TAG"Pkcs11_install_script", (void **)&installer,
405 (unsigned long *)&installer_len)) {
406 error(PK11_INSTALL_NO_INSTALLER_SCRIPT);
407 ret = PK11_INSTALL_NO_INSTALLER_SCRIPT;
408 goto loser;
409 }
410 if (feedback) {
411 PR_fprintf(feedback, msgStrings[INSTALLER_SCRIPT_NAME], installer);
412 }
413
414 /*
415 * Extract the installation file
416 */
417 if (PR_Access(SCRIPT_TEMP_FILE"pkcs11inst.tmp", PR_ACCESS_EXISTS) == PR_SUCCESS) {
418 if (PR_Delete(SCRIPT_TEMP_FILE"pkcs11inst.tmp") != PR_SUCCESS) {
419 error(PK11_INSTALL_DELETE_TEMP_FILE, SCRIPT_TEMP_FILE"pkcs11inst.tmp");
420 ret = PK11_INSTALL_DELETE_TEMP_FILE;
421 goto loser;
422 }
423 }
424 if (noverify) {
425 status = JAR_extract(jar, installer, SCRIPT_TEMP_FILE"pkcs11inst.tmp");
426 } else {
427 status = JAR_verified_extract(jar, installer, SCRIPT_TEMP_FILE"pkcs11inst.tmp");
428 }
429 if (status) {
430 if (status >= JAR_BASE(-0x2000) + 300 && status <= JAR_BASE_END((-0x2000) + 300 + 100)) {
431 error(PK11_INSTALL_JAR_EXTRACT, installer, JAR_get_error(status));
432 } else {
433 error(PK11_INSTALL_JAR_EXTRACT, installer,
434 mySECU_ErrorString(PORT_GetErrorPORT_GetError_Util()));
435 }
436 ret = PK11_INSTALL_JAR_EXTRACT;
437 goto loser;
438 } else {
439 made_temp_file = PR_TRUE1;
440 }
441
442 /*
443 * Parse the installation file into a syntax tree
444 */
445 Pk11Install_FD = PR_Open(SCRIPT_TEMP_FILE"pkcs11inst.tmp", PR_RDONLY0x01, 0);
446 if (!Pk11Install_FD) {
447 error(PK11_INSTALL_OPEN_SCRIPT_FILE, SCRIPT_TEMP_FILE"pkcs11inst.tmp");
448 ret = PK11_INSTALL_OPEN_SCRIPT_FILE;
449 goto loser;
450 }
451 if (Pk11Install_yyparse()) {
452 error(PK11_INSTALL_SCRIPT_PARSE, installer,
453 Pk11Install_yyerrstr ? Pk11Install_yyerrstr : "");
454 ret = PK11_INSTALL_SCRIPT_PARSE;
455 goto loser;
456 }
457
458#if 0
459 /* for debugging */
460 Pk11Install_valueList->Print(0);
461#endif
462
463 /*
464 * From the syntax tree, build a semantic structure
465 */
466 errMsg = Pk11Install_Info_Generate(&installInfo, Pk11Install_valueList);
467 if (errMsg) {
468 error(PK11_INSTALL_SEMANTIC, errMsg);
469 ret = PK11_INSTALL_SEMANTIC;
470 goto loser;
471 }
472#if 0
473 installInfo.Print(0);
474#endif
475
476 if (feedback) {
477 PR_fprintf(feedback, msgStrings[PARSED_INSTALL_SCRIPT]);
478 }
479
480 /*
481 * Figure out which platform to use
482 */
483 {
484 sysname[0] = release[0] = arch[0] = '\0';
485
486 if ((PR_GetSystemInfo(PR_SI_SYSNAME, sysname, SYS_INFO_BUFFER_LENGTH256) !=
487 PR_SUCCESS) ||
488 (PR_GetSystemInfo(PR_SI_RELEASE, release, SYS_INFO_BUFFER_LENGTH256) !=
489 PR_SUCCESS) ||
490 (PR_GetSystemInfo(PR_SI_ARCHITECTURE, arch, SYS_INFO_BUFFER_LENGTH256) !=
491 PR_SUCCESS)) {
492 error(PK11_INSTALL_SYSINFO);
493 ret = PK11_INSTALL_SYSINFO;
494 goto loser;
495 }
496 myPlatform = PR_smprintf("%s:%s:%s", sysname, release, arch);
497 platform = Pk11Install_Info_GetBestPlatform(&installInfo, myPlatform);
498 if (!platform) {
499 error(PK11_INSTALL_NO_PLATFORM, myPlatform);
500 PR_smprintf_free(myPlatform);
501 ret = PK11_INSTALL_NO_PLATFORM;
502 goto loser;
503 }
504 if (feedback) {
505 PR_fprintf(feedback, msgStrings[MY_PLATFORM_IS], myPlatform);
506 PR_fprintf(feedback, msgStrings[USING_PLATFORM],
507 Pk11Install_PlatformName_GetString(&platform->name));
508 }
509 PR_smprintf_free(myPlatform);
510 }
511
512 /* Run the install for that platform */
513 ret = DoInstall(jar, installDir, tempDir, platform, feedback, noverify);
514 if (ret) {
515 goto loser;
516 }
517
518 ret = PK11_INSTALL_SUCCESSPK11_INSTALL_NO_ERROR;
519loser:
520 if (Pk11Install_valueList) {
521 Pk11Install_ValueList_delete(Pk11Install_valueList);
522 Pk11Install_valueList = NULL((void*)0);
523 }
524 if (jar) {
525 JAR_destroy(jar);
526 }
527 if (made_temp_file) {
528 PR_Delete(SCRIPT_TEMP_FILE"pkcs11inst.tmp");
529 }
530 if (errMsg) {
531 PR_smprintf_free(errMsg);
532 }
533 return ret;
534}
535
536/*
537/////////////////////////////////////////////////////////////////////////
538// actually run the installation, copying files to and fro
539*/
540static Pk11Install_Error
541DoInstall(JAR *jar, const char *installDir, const char *tempDir,
542 Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify)
543{
544 Pk11Install_File *file;
545 Pk11Install_Error ret;
546 char *modDest;
547 char *cp;
548 int i;
549 int status;
550 char *tempname, *temp;
551 StringList executables;
552 StringNode *execNode;
553 PRProcessAttr *attr;
554 PRProcess *proc;
555 char *argv[2];
556 char *envp[1];
557 int errcode;
558
559 ret = PK11_INSTALL_UNSPECIFIED;
560 modDest = NULL((void*)0);
561 tempname = NULL((void*)0);
562
563 StringList_new(&executables);
564 /*
565 // Create Temporary directory
566 */
567 tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME"pk11inst.dir");
568 if (PR_Access(tempname, PR_ACCESS_EXISTS) == PR_SUCCESS) {
569 /* Left over from previous run? Delete it. */
570 rm_dash_r(tempname);
571 }
572 if (PR_MkDir(tempname, 0700) != PR_SUCCESS) {
573 error(PK11_INSTALL_CREATE_DIR, tempname);
574 ret = PK11_INSTALL_CREATE_DIR;
575 goto loser;
576 }
577
578 /*
579 // Install all the files
580 */
581 for (i = 0; i < platform->numFiles; i++) {
582 char *dest;
583 file = &platform->files[i];
584
585 if (file->relativePath) {
586 PRBool foundMarker = PR_FALSE0;
587 char *reldir = PR_Strdup(file->relativePath);
588
589 if (!reldir) {
590 error(PK11_INSTALL_UNSPECIFIED);
591 goto loser;
592 }
593
594 /* Replace all the markers with the directories for which they stand */
595 while (1) {
596 if ((cp = PL_strcasestr(reldir, ROOT_MARKER"%root%"))) {
597 /* Has a %root% marker */
598 *cp = '\0';
599 temp = PR_smprintf("%s%s%s", reldir, installDir,
600 cp + strlen(ROOT_MARKER"%root%"));
601 PR_Free(reldir);
602 reldir = temp;
603 foundMarker = PR_TRUE1;
604 } else if ((cp = PL_strcasestr(reldir, TEMP_MARKER"%temp%"))) {
605 /* Has a %temp% marker */
606 *cp = '\0';
607 temp = PR_smprintf("%s%s%s", reldir, tempname,
608 cp + strlen(TEMP_MARKER"%temp%"));
609 PR_Free(reldir);
610 reldir = temp;
611 foundMarker = PR_TRUE1;
612 } else {
613 break;
614 }
615 }
616 if (!foundMarker) {
617 /* Has no markers...this isn't really a relative directory */
618 error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath);
619 ret = PK11_INSTALL_BOGUS_REL_DIR;
620 PR_Free(reldir);
621 goto loser;
622 }
623 dest = reldir;
624 } else if (file->absolutePath) {
625 dest = PR_Strdup(file->absolutePath);
626 } else {
627 error(PK11_INSTALL_UNSPECIFIED);
628 goto loser;
629 }
630
631 /* Remember if this is the module file, we'll need to add it later */
632 if (i == platform->modFile) {
633 modDest = PR_Strdup(dest);
634 }
635
636 /* Remember is this is an executable, we'll need to run it later */
637 if (file->executable) {
638 StringList_Append(&executables, dest);
639 /*executables.Append(dest);*/
640 }
641
642 /* Make sure the directory we are targetting exists */
643 if (make_dirs(dest, file->permissions)) {
644 ret = PK11_INSTALL_CREATE_DIR;
645 goto loser;
646 }
647
648 /* Actually extract the file onto the filesystem */
649 if (noverify) {
650 status = JAR_extract(jar, (char *)file->jarPath, dest);
651 } else {
652 status = JAR_verified_extract(jar, (char *)file->jarPath, dest);
653 }
654 if (status) {
655 if (status >= JAR_BASE(-0x2000) + 300 && status <= JAR_BASE_END((-0x2000) + 300 + 100)) {
656 error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
657 JAR_get_error(status));
658 } else {
659 error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
660 mySECU_ErrorString(PORT_GetErrorPORT_GetError_Util()));
661 }
662 ret = PK11_INSTALL_JAR_EXTRACT;
663 goto loser;
664 }
665 if (feedback) {
666 PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG],
667 file->jarPath, dest);
668 }
669
670/* no NSPR command to change permissions? */
671#ifdef XP_UNIX1
672 (void)chmod(dest, file->permissions);
673#endif
674
675 PR_Free(dest);
676 }
677 /* Make sure we found the module file */
678 if (!modDest) {
679 /* Internal problem here, since every platform is supposed to have
680 a module file */
681 error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName);
682 ret = PK11_INSTALL_NO_MOD_FILE;
683 goto loser;
684 }
685
686 /*
687 // Execute any executable files
688 */
689 {
690 argv[1] = NULL((void*)0);
691 envp[0] = NULL((void*)0);
692 for (execNode = executables.head; execNode; execNode = execNode->next) {
693 attr = PR_NewProcessAttr();
694 argv[0] = PR_Strdup(execNode->str);
695
696 /* Announce our intentions */
697 if (feedback) {
698 PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str);
699 }
700
701 /* start the process */
702 if (!(proc = PR_CreateProcess(execNode->str, argv, envp, attr))) {
703 PR_Free(argv[0]);
704 PR_DestroyProcessAttr(attr);
705 error(PK11_INSTALL_EXEC_FILE, execNode->str);
706 ret = PK11_INSTALL_EXEC_FILE;
707 goto loser;
708 }
709
710 /* wait for it to finish */
711 if (PR_WaitProcess(proc, &errcode) != PR_SUCCESS) {
712 PR_Free(argv[0]);
713 PR_DestroyProcessAttr(attr);
714 error(PK11_INSTALL_WAIT_PROCESS, execNode->str);
715 ret = PK11_INSTALL_WAIT_PROCESS;
716 goto loser;
717 }
718
719 /* What happened? */
720 if (errcode) {
721 /* process returned an error */
722 error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode);
723 } else if (feedback) {
724 /* process ran successfully */
725 PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str);
726 }
727
728 PR_Free(argv[0]);
729 PR_DestroyProcessAttr(attr);
730 }
731 }
732
733 /*
734 // Add the module
735 */
736 status = Pk11Install_AddNewModule((char *)platform->moduleName,
737 (char *)modDest, platform->mechFlags, platform->cipherFlags);
738
739 if (status != SECSuccess) {
740 error(PK11_INSTALL_ADD_MODULE, platform->moduleName);
741 ret = PK11_INSTALL_ADD_MODULE;
742 goto loser;
743 }
744 if (feedback) {
745 PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG],
746 platform->moduleName);
747 }
748
749 if (feedback) {
750 PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]);
751 }
752
753 ret = PK11_INSTALL_SUCCESSPK11_INSTALL_NO_ERROR;
754
755loser:
756 if (modDest) {
757 PR_Free(modDest);
758 }
759 if (tempname) {
760 PRFileInfo info;
761 if (PR_GetFileInfo(tempname, &info) == PR_SUCCESS) {
762 if (info.type == PR_FILE_DIRECTORY) {
763 /* Recursively remove temporary directory */
764 if (rm_dash_r(tempname)) {
765 error(PK11_INSTALL_REMOVE_DIR,
766 tempname);
767 ret = PK11_INSTALL_REMOVE_DIR;
768 }
769 }
770 }
771 PR_Free(tempname);
772 }
773 StringList_delete(&executables);
774 return ret;
775}
776
777/*
778//////////////////////////////////////////////////////////////////////////
779*/
780static char *
781PR_Strdup(const char *str)
782{
783 char *tmp = (char *)PR_Malloc(strlen(str) + 1);
784 strcpy(tmp, str);
785 return tmp;
786}
787
788/*
789 * r m _ d a s h _ r
790 *
791 * Remove a file, or a directory recursively.
792 *
793 */
794static int
795rm_dash_r(char *path)
796{
797 PRDir *dir;
798 PRDirEntry *entry;
799 PRFileInfo fileinfo;
800 char filename[240];
801
802 if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
803 /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
804 return -1;
805 }
806 if (fileinfo.type == PR_FILE_DIRECTORY) {
807
808 dir = PR_OpenDir(path);
809 if (!dir) {
810 return -1;
811 }
812
813 /* Recursively delete all entries in the directory */
814 while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL((void*)0)) {
815 snprintf(filename, sizeof(filename), "%s/%s", path, entry->name);
816 if (rm_dash_r(filename)) {
817 PR_CloseDir(dir);
818 return -1;
819 }
820 }
821
822 if (PR_CloseDir(dir) != PR_SUCCESS) {
823 return -1;
824 }
825
826 /* Delete the directory itself */
827 if (PR_RmDir(path) != PR_SUCCESS) {
828 return -1;
829 }
830 } else {
831 if (PR_Delete(path) != PR_SUCCESS) {
832 return -1;
833 }
834 }
835 return 0;
836}
837
838/***************************************************************************
839 *
840 * m a k e _ d i r s
841 *
842 * Ensure that the directory portion of the path exists. This may require
843 * making the directory, and its parent, and its parent's parent, etc.
844 */
845static int
846make_dirs(char *path, int file_perms)
847{
848 char *Path;
849 char *start;
850 char *sep;
851 int ret = 0;
852 PRFileInfo info;
853
854 if (!path) {
855 return 0;
856 }
857
858 Path = PR_Strdup(path);
859 start = strpbrk(Path, "/\\");
860 if (!start) {
861 return 0;
862 }
863 start++; /* start right after first slash */
864
865 /* Each time through the loop add one more directory. */
866 while ((sep = strpbrk(start, "/\\"))) {
867 *sep = '\0';
868
869 if (PR_GetFileInfo(Path, &info) != PR_SUCCESS) {
870 /* No such dir, we have to create it */
871 if (PR_MkDir(Path, dir_perms(file_perms)) != PR_SUCCESS) {
872 error(PK11_INSTALL_CREATE_DIR, Path);
873 ret = PK11_INSTALL_CREATE_DIR;
874 goto loser;
875 }
876 } else {
877 /* something exists by this name, make sure it's a directory */
878 if (info.type != PR_FILE_DIRECTORY) {
879 error(PK11_INSTALL_CREATE_DIR, Path);
880 ret = PK11_INSTALL_CREATE_DIR;
881 goto loser;
882 }
883 }
884
885 /* If this is the lowest directory level, make sure it is writeable */
886 if (!strpbrk(sep + 1, "/\\")) {
887 if (PR_Access(Path, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
888 error(PK11_INSTALL_DIR_NOT_WRITEABLE, Path);
889 ret = PK11_INSTALL_DIR_NOT_WRITEABLE;
890 goto loser;
891 }
892 }
893
894 start = sep + 1; /* start after the next slash */
895 *sep = '/';
896 }
897
898loser:
899 PR_Free(Path);
900 return ret;
901}
902
903/*************************************************************************
904 * d i r _ p e r m s
905 *
906 * Guesses the desired permissions on a directory based on the permissions
907 * of a file that will be stored in it. Give read, write, and
908 * execute to the owner (so we can create the file), read and
909 * execute to anyone who has read permissions on the file, and write
910 * to anyone who has write permissions on the file.
911 */
912static int
913dir_perms(int perms)
914{
915 int ret = 0;
916
917 /* owner */
918 ret |= 0700;
919
920 /* group */
921 if (perms & 0040) {
922 /* read on the file -> read and execute on the directory */
923 ret |= 0050;
924 }
925 if (perms & 0020) {
926 /* write on the file -> write on the directory */
927 ret |= 0020;
928 }
929
930 /* others */
931 if (perms & 0004) {
932 /* read on the file -> read and execute on the directory */
933 ret |= 0005;
934 }
935 if (perms & 0002) {
936 /* write on the file -> write on the directory */
937 ret |= 0002;
938 }
939
940 return ret;
941}