Back to index

lightning-sunbird  0.9+nobinonly
Deflation.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Samir Gehani <sgehani@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "MacInstallWizard.h"
00041 
00042 
00043 #define STANDALONE 1
00044 #define XP_MAC 1
00045 #include "zipstub.h"
00046 #include "zipfile.h"
00047 #include "nsAppleSingleDecoder.h"
00048 
00049 #include <TextUtils.h>
00050 
00051 static FSSpec        coreFileList[kMaxCoreFiles];
00052 static short  currCoreFile = 0;
00053 
00054 #define SLASHES_2_COLONS(_path)                                                                   \
00055 do {                                                                                                            \
00056        char   *delim;                                                                                           \
00057        long   count = 0, len = strlen(_path);                                              \
00058                                                                                                                        \
00059        while ( (count < len) && ((delim = strchr(_path, '/')) != 0) ) \
00060        {                                                                                                               \
00061               *delim = ':';                                                                              \
00062               count++;                                                                                          \
00063        }                                                                                                               \
00064 } while(0)
00065 
00066 
00067 /*-----------------------------------------------------------*
00068  *   Inflation
00069  *-----------------------------------------------------------*/
00070 OSErr
00071 ExtractCoreFile(short srcVRefNum, long srcDirID, short tgtVRefNum, long tgtDirID)
00072 {
00073        OSErr                err = noErr;
00074        StringPtr            coreFile = 0;
00075        UInt32          endTicks;
00076        short                fullPathLen = 0;
00077        Handle               fullPathH = 0;
00078        Ptr                         fullPathStr = 0;
00079        PRInt32                     rv = 0;
00080        void                 *hZip = 0, *hFind = 0;
00081 
00082        /* if there's a core file... */
00083        HLock(gControls->cfg->coreFile);
00084        if (*gControls->cfg->coreFile != NULL)
00085        {
00086               /* make local copy and unlock handle */
00087               coreFile = CToPascal(*gControls->cfg->coreFile);
00088               if (!coreFile)
00089               {
00090                      err = memFullErr;
00091                      goto cleanup;
00092               }
00093        }
00094        else
00095               return fnfErr;
00096        HUnlock(gControls->cfg->coreFile);
00097        
00098        ERR_CHECK_RET(GetFullPath(srcVRefNum, srcDirID, coreFile, &fullPathLen, &fullPathH), err);
00099        
00100        
00101        /* --- o p e n   a r c h i v e --- */
00102        
00103        /* extract the full path string from the handle so we can NULL terminate */
00104        HLock(fullPathH);
00105        fullPathStr = NewPtrClear(fullPathLen+1);
00106        strncat(fullPathStr, *fullPathH, fullPathLen);
00107        *(fullPathStr+fullPathLen) = '\0';
00108        
00109        rv = ZIP_OpenArchive( fullPathStr, &hZip );
00110        
00111        HUnlock(fullPathH);
00112        if (rv!=ZIP_OK) 
00113               goto cleanup;
00114 
00115        /* initialize the search */
00116        hFind = ZIP_FindInit( hZip, NULL ); /* null to match all files in archive */
00117        
00118        
00119        /* --- i n f l a t e   a l l   f i l e s --- */
00120        
00121        err = InflateFiles(hZip, hFind, tgtVRefNum, tgtDirID);
00122        if (err!=noErr)
00123               goto cleanup; /* XXX review later: this check may be pointless */
00124        
00125        
00126        /* --- c l o s e   a r c h i v e --- */
00127 cleanup:
00128 
00129        //if (hFind)
00130        //     rv = ZIP_FindFree( hFind );
00131 #ifdef MIW_DEBUG
00132               if (rv!=ZIP_OK) SysBeep(10);
00133 #endif
00134        if (hZip)
00135               rv = ZIP_CloseArchive( &hZip );
00136 #ifdef MIW_DEBUG
00137               if (rv!=ZIP_OK) SysBeep(10); 
00138 #endif
00139        if (coreFile)
00140               DisposePtr((Ptr)coreFile);
00141        if (fullPathH)
00142               DisposeHandle(fullPathH);
00143        if (fullPathStr)
00144               DisposePtr(fullPathStr);
00145 
00146     /* pause till frag registry is updated */
00147     endTicks = TickCount() + 60;
00148     while (TickCount() < endTicks)
00149     {
00150         YieldToAnyThread();
00151     }
00152     
00153        return err;
00154 }
00155 
00156 void
00157 WhackDirectories(char *filename)
00158 {
00159        // Level ouot essential files and components to satisfy
00160        // lib loading and dependency resolution issues
00161        
00162        Ptr           componentPathStr     = 0;
00163        Ptr           tempStr                            = 0;
00164        Ptr           finalStr                    = 0;
00165        long   prefixLen                   = 0;
00166        long    skipLen             = 0;
00167        
00168        componentPathStr = NewPtrClear(strlen(filename) + 1);
00169        finalStr              = NewPtrClear(strlen(filename) + 1);
00170        strcpy(componentPathStr, filename);                            // e.g. HD:Target:Essential Files:foo.shlb
00171                                                                                            //   or HD:Target:Components:bar.shlb
00172        LowercaseText(componentPathStr, strlen(componentPathStr), smSystemScript);
00173        if((tempStr = strstr(componentPathStr, "essential files")) != NULL)
00174        {
00175               prefixLen = tempStr - componentPathStr;          // e.g. HD:Target:
00176 
00177               strncpy(finalStr, filename, prefixLen);   // e.g. HD:Target:
00178               skipLen = prefixLen + strlen("essential files") + 1;  // add 1 to skip over extra ':'
00179               strcat(finalStr, filename + skipLen);
00180               strcpy(filename, finalStr);
00181        }
00182        else
00183        if ((tempStr = strstr(componentPathStr, "components")) != NULL)
00184        {
00185               prefixLen = tempStr - componentPathStr;          // e.g. HD:Target:
00186 
00187               strncpy(finalStr, filename, prefixLen);   // e.g. HD:Target:
00188               skipLen = prefixLen + strlen("components") + 1;  // add 1 to skip over extra ':'
00189               strcat(finalStr, filename + skipLen);
00190               strcpy(filename, finalStr);                             // e.g. HD:Target:foo.shlb
00191        }
00192 
00193        if(componentPathStr)
00194               DisposePtr(componentPathStr);
00195        if(finalStr)
00196               DisposePtr(finalStr);
00197 }
00198 
00199 OSErr
00200 InflateFiles(void *hZip, void *hFind, short tgtVRefNum, long tgtDirID)
00201 {
00202        OSErr         err = noErr;
00203        Boolean              bFoundAll = false;
00204        PRInt32              rv = 0;
00205        char          filename[255] = "\0", *lastslash, *leaf, macfilename[255] = "\0";
00206        Handle        fullPathH = 0;
00207        short         fullPathLen = 0;
00208        Ptr                  fullPathStr = 0;
00209        StringPtr     extractedFile = 0;
00210        FSSpec        extractedFSp, outFSp;
00211        
00212        
00213        while (!bFoundAll)
00214        {
00215               /* find next item if one exists */
00216               rv = ZIP_FindNext( hFind, filename, 255 );
00217               if (rv==ZIP_ERR_FNF)
00218               {
00219                      bFoundAll = true;
00220                      break;
00221               }
00222               else if (rv!=ZIP_OK)
00223                      return rv;    
00224               
00225               /* ignore if item is a dir entry */       
00226               lastslash = strrchr(filename, '/');
00227               if (lastslash == (&filename[0] + strlen(filename) - 1)) /* dir entry encountered */
00228                      continue;
00229 
00230               /* grab leaf filename only */
00231               if (lastslash == 0)
00232                      leaf = filename;
00233               else
00234                      leaf = lastslash + 1;
00235               
00236               /* obtain and NULL terminate the full path string */
00237               err = GetFullPath(tgtVRefNum, tgtDirID, "\p", &fullPathLen, &fullPathH); /* get dirpath */
00238               if (err!=noErr)
00239                      return err;
00240 
00241         strcpy(macfilename, filename);        
00242         SLASHES_2_COLONS(macfilename);
00243               HLock(fullPathH);
00244               fullPathStr = NewPtrClear(fullPathLen + strlen(macfilename) + 1);
00245               strncat(fullPathStr, *fullPathH, fullPathLen);
00246               strcat(fullPathStr, macfilename);  /* tack on filename to dirpath */
00247               *(fullPathStr+fullPathLen+strlen(macfilename)) = '\0';
00248               
00249               /* create directories if file is nested in new subdirs */
00250               WhackDirectories(fullPathStr);
00251               err = DirCreateRecursive(fullPathStr);                  
00252               
00253               if (err!=noErr)
00254               {
00255                      if (fullPathStr) 
00256                             DisposePtr((Ptr)fullPathStr);
00257                      if (fullPathH)
00258                      {
00259                             HUnlock(fullPathH);                       
00260                             DisposeHandle(fullPathH);
00261                      }
00262                      continue; /* XXX do we want to do this? */
00263               }
00264               
00265               /* extract the file to its full path destination */
00266               rv = ZIP_ExtractFile( hZip, filename, fullPathStr );
00267               
00268               HUnlock(fullPathH);
00269               if (fullPathH)
00270                      DisposeHandle(fullPathH);
00271               if (rv!=ZIP_OK)
00272               {
00273                      if (fullPathStr)
00274                             DisposePtr((Ptr)fullPathStr);                    
00275                      return rv;
00276               }
00277               
00278               /* AppleSingle decode if need be */
00279               extractedFile = CToPascal(fullPathStr); 
00280               if (extractedFile)
00281               {
00282                      err = FSMakeFSSpec(0, 0, extractedFile, &extractedFSp);
00283                      err = FSMakeFSSpec(0, 0, extractedFile, &outFSp);
00284                      err = AppleSingleDecode(&extractedFSp, &outFSp);
00285                      
00286                      /* delete original file if named different than final file */
00287                      if (!pstrcmp(extractedFSp.name, outFSp.name))
00288                      {
00289                             err = FSpDelete(&extractedFSp);
00290                      }
00291               }
00292                      
00293               /* record for cleanup later */
00294               FSMakeFSSpec(outFSp.vRefNum, outFSp.parID, outFSp.name, &coreFileList[currCoreFile]);
00295               currCoreFile++;
00296               
00297               /* progress bar update (roll the barber poll) */
00298               if (gWPtr)
00299                      IdleControls(gWPtr); 
00300                      
00301               if (extractedFile)
00302                      DisposePtr((Ptr)extractedFile);
00303               if (fullPathStr)
00304                      DisposePtr(fullPathStr);
00305        }
00306         
00307        return err;
00308 }
00309 
00310 OSErr
00311 AppleSingleDecode(FSSpecPtr fd, FSSpecPtr outfd)
00312 {
00313        OSErr  err = noErr;
00314        
00315        // if file is AppleSingled
00316        if (nsAppleSingleDecoder::IsAppleSingleFile(fd))
00317        {
00318               // decode it
00319               nsAppleSingleDecoder decoder(fd, outfd);
00320                      
00321               ERR_CHECK_RET(decoder.Decode(), err);
00322        }
00323        return err;
00324 }
00325 
00326 void
00327 ResolveDirs(char *fname, char *dir)
00328 {
00329        char *delim, *dirpath;
00330        dirpath = fname;
00331        Boolean delimFound = false;
00332        
00333        while( (delim = strchr(dirpath, '/')) != 0)
00334        {
00335               delimFound = true;
00336               *delim = ':';
00337               dirpath = delim;
00338        }
00339        
00340        if (delimFound)
00341        {
00342               strncpy(dir, fname, dirpath-fname);
00343               *(dir + (dirpath-fname)+1) = 0; // NULL terminate
00344        }
00345 }
00346 
00347 OSErr
00348 DirCreateRecursive(char* path)
00349 {
00350        long          count, len=strlen(path), dummyDirID;
00351        char          *delim = '\0', *pathpos = path, *currDir;
00352        OSErr         err = noErr;
00353        StringPtr     pCurrDir;
00354        FSSpec        currDirFSp;
00355        
00356        currDir = (char*) malloc(len+1);
00357        
00358        if ((delim=strchr(pathpos, ':'))!=0)             /* skip first since it's volName */
00359        {
00360               for (count=0; ((count<len)&&( (delim=strchr(pathpos, ':'))!=0) ); count++)
00361               {
00362                      currDir[0] = '\0';
00363                      strncpy(currDir, path, delim-path+1);
00364                      currDir[delim-path+1] = '\0';
00365               
00366                      pCurrDir = CToPascal(currDir);
00367                      if (pCurrDir && *pCurrDir > 0)
00368                      {
00369                             err = FSMakeFSSpec(0, 0, pCurrDir, &currDirFSp);
00370                             if (err == fnfErr)
00371                             {      
00372                                    err = FSpDirCreate(&currDirFSp, smSystemScript, &dummyDirID);
00373                                    if (err!=noErr) 
00374                                    {
00375                                           if (currDir)
00376                                                  free(currDir);
00377                                           if (pCurrDir)
00378                                                  DisposePtr((Ptr)pCurrDir);
00379                                           return err;
00380                                    }
00381                             }
00382                             
00383                             DisposePtr((Ptr)pCurrDir);
00384                             pathpos = delim+1;
00385                      }      
00386               }
00387        }
00388        
00389        if (currDir)
00390               free(currDir);
00391               
00392        return err;
00393 }
00394 
00395 OSErr
00396 ForceMoveFile(short vRefNum, long parID, ConstStr255Param name, long newDirID)
00397 {
00398        OSErr  err = noErr;
00399        FSSpec        tmpFSp;
00400        
00401        err = CatMove(vRefNum, parID, name, newDirID, nil);
00402        if (err == dupFNErr)
00403        {
00404               // handle for stomping over old file
00405               err = FSMakeFSSpec(vRefNum, newDirID, name, &tmpFSp);
00406               err = FSpDelete(&tmpFSp);
00407               err = CatMove(vRefNum, parID, name, newDirID, nil);
00408        }
00409        
00410        return err;          
00411 }
00412 
00413 OSErr
00414 CleanupExtractedFiles(short tgtVRefNum, long tgtDirID)
00415 {
00416        OSErr         err = noErr;
00417        FSSpec        coreDirFSp;
00418        StringPtr     pcoreDir = nil;
00419        short         i = 0;
00420        
00421        HLock(gControls->cfg->coreDir);
00422        if (*gControls->cfg->coreDir != NULL && **gControls->cfg->coreDir != NULL)          
00423        {
00424               // just need to delete the core dir and its contents
00425               
00426               pcoreDir = CToPascal(*gControls->cfg->coreDir);
00427               err = FSMakeFSSpec(tgtVRefNum, tgtDirID, pcoreDir, &coreDirFSp);
00428               if (err == noErr)
00429               {
00430                      err = FSpDelete( &coreDirFSp );
00431               }
00432        
00433               HUnlock(gControls->cfg->coreDir);
00434               goto aurevoir;
00435        }      
00436               
00437        HUnlock(gControls->cfg->coreDir);
00438        
00439        // otherwise iterate through coreFileList deleteing each individually
00440        for (i=0; i<currCoreFile+1; i++)
00441        {
00442               FSpDelete( &coreFileList[i] );
00443        }
00444 
00445 aurevoir:
00446        if (pcoreDir)
00447               DisposePtr((Ptr) pcoreDir); 
00448        return err;
00449 }