install.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:24k
源码类别:

CA认证

开发平台:

WINDOWS

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