srcanamdw/appdep/src/appdep_sisfiles.cpp
author noe\swadi
Sat, 09 Jan 2010 10:04:12 +0530
changeset 0 509e4801c378
permissions -rw-r--r--
1. Copyrights changed to EPL 2. Feature updates mentioned in release notes.

/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Handling of sis files 
*
*/


#include "appdep.hpp"

// ----------------------------------------------------------------------------------------------------------
// Note that in C/C++ code \ has been replaced with \\ and " with \".
// ----------------------------------------------------------------------------------------------------------

void DoInitialChecksAndPreparationsForSisFiles()
{
    // specify full location for dumpsis
    _dumpsis_location = _cl_releasedir + DUMPSIS_LOCATION;

    // check if dumpsis can be found
 	if (!FileExists(_dumpsis_location))
	{
		cerr << "ERROR: Unable to find " + _dumpsis_location << ", check -release param" << endl;
		cerr << "Please notice that this feature is available only in Symbian OS 9.x" << endl;
		cerr << "It is possible the user to copy dumpsis.exe from some other release under" << endl;
		cerr << "this release to support this feature." << endl;
		exit(EXIT_DUMPSIS_NOT_FOUND);
	}         

    // insert quotes to the dumpsis location to avoid any problems caused by white spaces
    InsertQuotesToFilePath(_dumpsis_location);

    // parse commandline argument "sisfiles" from sisfile;sisfile;...
    int last_found_semicolon_pos = -1;
    for (unsigned int i=0; i<_cl_sisfiles.length(); i++)
    {   
        // try to find ';' characters 
        string::size_type semicolon_pos = _cl_sisfiles.find(";", i);
        
        if (semicolon_pos == string::npos)
        {
            // could not find the ';' character, append last part of the list
            string sis_file = _cl_sisfiles.substr(last_found_semicolon_pos+1,_cl_sisfiles.length()-last_found_semicolon_pos-1);
            _sisfiles.push_back(sis_file);
            break;
        }
        else
        {
            // found a ';' character, append to the list, but needs to check if there are more
            string sis_file = _cl_sisfiles.substr(last_found_semicolon_pos+1, semicolon_pos-last_found_semicolon_pos-1);
            
            if (sis_file.length() > 0)
                _sisfiles.push_back(sis_file);
            
            last_found_semicolon_pos = semicolon_pos;
            i = last_found_semicolon_pos;
        }    
    }

    // check that all given sisfiles can be found and it is supported
    for (unsigned int i=0; i<_sisfiles.size(); i++)
    { 
        // report an error if the file does not exist
        if (!FileExists(_sisfiles.at(i)))
        {
     		cerr << "ERROR: Unable to find " + _sisfiles.at(i) << ", check -sisfiles parameter" << endl;
    		exit(EXIT_SIS_FILE_NOT_FOUND);           
        }
        
        // open the sis file for reading to check if it is supported    
        ifstream sisf(_sisfiles.at(i).c_str(), ios::binary);
		if (sisf.is_open())
		{
            int c1, c2, c3, c4;
            c1 = sisf.get();
            c2 = sisf.get();
            c3 = sisf.get();
            c4 = sisf.get();
            
            // in valid sis first four bytes of the file are 7A1A2010
            if (c1==0x7A && c2==0x1A && c3==0x20 && c4==0x10)
            {
                //cerr << _sisfiles.at(i) << " is supported" << endl;
            }
            else
            {
                // if starting from offset 8, four next bytes are 19040010, the file is
                // unsupported SIS file used in previous Symbian OS releases.    
                sisf.seekg(8, ios::beg);
                c1 = sisf.get();
                c2 = sisf.get();
                c3 = sisf.get();
                c4 = sisf.get();
                sisf.close();

                if (c1==0x19 && c2==0x04 && c3==0x00 && c4==0x10)
                {
                    cerr << "ERROR: " + _sisfiles.at(i) << " is a pre-Symbian OS 9.x" << endl;
                    cerr << "sisfile which is not supported, check -sisfiles parameter" << endl;
                    exit(EXIT_SIS_FILE_NOT_SUPPORTED); 
                }
                else
                {
                    cerr << "ERROR: " + _sisfiles.at(i) << " is not a valid sis file," << endl;
                    cerr << "check -sisfiles parameter" << endl;
                    exit(EXIT_NOT_SIS_FILE);                     
                }
            }    
            sisf.close();
        }
        else
        {
     		cerr << "ERROR: Cannot open " + _sisfiles.at(i) << " for reading, check -sisfiles parameter" << endl;
    		exit(EXIT_SIS_FILE_CANNOT_OPEN_FOR_READING); 
        }
    }    
}

// ----------------------------------------------------------------------------------------------------------

void AnalyseSisFiles()
{
    // create a new target and set some defaults
    target sis_target;
    sis_target.name = "sis";
    sis_target.cache_dir = _cl_cachedir + sis_target.name + DIR_SEPARATOR;
    sis_target.dep_cache_path = sis_target.cache_dir + CACHE_DEP_FILENAME;

    cerr << "Analysing sis files..." << endl;

    // define path to a temp directory where dumpsis will extract the files    
    const string tempdir = _cl_cachedir + SIS_TEMP_DIR + DIR_SEPARATOR;
    const string tempdir2 = _cl_cachedir + SIS_TEMP_DIR;

    // do analysis for each file
    for (unsigned int i=0; i<_sisfiles.size(); i++)
    { 
        // create the temporary directory
        MkDirAll(tempdir);

        cerr << "Binaries in " << _sisfiles.at(i) << " are:" << endl;
        
        // due to bugginess of a specific version of dumpsis, we need to copy the source file under the temporary directory
        const string new_sis_loc = tempdir + "tempsis.sis";
        
        ifstream src_sis_f(_sisfiles.at(i).c_str(), ios::binary);
        if (src_sis_f.is_open())
		{
            ofstream trgt_sis_f(new_sis_loc.c_str(), ios::binary);
            if (trgt_sis_f.is_open())
    		{
                // read all bytes from source and write to the target
                int c1;

                while(!src_sis_f.eof())
                {
                    c1 = src_sis_f.get();
                    trgt_sis_f.put(c1);
                }
                
                trgt_sis_f.close();            
            
            }
            else
            {
         		cerr << "ERROR: Cannot open " + new_sis_loc << " for writing, check write permissions" << endl;
        		exit(EXIT_TEMP_SIS_FILE_CANNOT_OPEN_FOR_WRITING); 
            }             

            src_sis_f.close();
                        
        }
        else
        {
     		cerr << "ERROR: Cannot open " + _sisfiles.at(i) << " for reading, check -sisfiles parameter" << endl;
    		exit(EXIT_SIS_FILE_CANNOT_OPEN_FOR_READING); 
        }        
        
        

        // execute dumpsis        
        string cmd = _dumpsis_location + " -x -d \"" + tempdir2 + "\" \"" + new_sis_loc + "\" " + CERR_TO_NULL;
        
        vector<string> tempVector;
        ExecuteCommand(cmd, tempVector);
        
       
        // check if pkg file found
        string pkgfile_location = tempdir + "tempsis.pkg";
        
        if (!FileExists(pkgfile_location))
        {
            // try again with an alternative
            pkgfile_location = tempdir + "tempsis.sis.pkg";

            if (!FileExists(pkgfile_location))
            {
         		RemoveDirectoryWithAllFiles(tempdir);
                cerr << "ERROR: Dumpsis failed for " << _sisfiles.at(i) << " since it does not contain a pkg file, check -sisfiles parameter" << endl;
        		exit(EXIT_NO_PKG_FILE_FOUND); 
            }            
        }

        // open the pkg file for reading
        ifstream pkgf(pkgfile_location.c_str(), ios::binary);
		if (pkgf.is_open())
		{
            int c1, c2;
            c1 = pkgf.get();
            c2 = pkgf.get();
            
            // we only support unicode format
            if (c1 == 0xFF && c2 == 0xFE)
            {
                string line;

                 // read more chars
                 while(!pkgf.eof())
                 {
                    c1 = pkgf.get();
                    c2 = pkgf.get();
                    
                 //   if (c1 == 0x0D && c2 == 0x00)  // new line marker #1
                  //  {
                      //  c1 = pkgf.get();
                      //  c2 = pkgf.get();                        

                        if (c1 == 0x0A && c2 == 0x00)  // new line marker #2
                        {
                            // full line is now available, parse it
                                                        
                            boost::regex re1("^\\\"(.+)\\\"-\\\".*\\\\(\\S+)\\\",.*$");
                            boost::cmatch matches1;                
                            if (boost::regex_match(line.c_str(), matches1, re1))
                            {
                                // match found
                                string ms1(matches1[1].first, matches1[1].second); // source name
                                string ms2(matches1[2].first, matches1[2].second); // target name
                                
                                binary_info b_info;
                                b_info.directory = tempdir;
                                b_info.filename = ms1;

                                GetImportTableWithPetran(_petran_location, b_info);
                                
                                // make sure that Petran succeeded for this file since we don't do any file
                                // extension checks when parsering the file
                                if (b_info.binary_format != UNKNOWN)
                                {
                                    // print name of the destination binary
                                    cerr << ms2 << endl;
                                
                                    b_info.directory = "";
                                    b_info.filename = ms2;
    
                                    // get statistics of the file and set the modification time
                                    struct stat stat_p;
                                    stat((tempdir + ms1).c_str(), &stat_p);
                                    b_info.mod_time = stat_p.st_mtime;
                                    
                                    // create a new entry to list of binary files
                                    sis_target.binaries.push_back( b_info );                                      
                                }
                                              
                            }
                            
                            // clear the buffer since we start scanning another line
                            line = "";
                        }                        
                    //}
                    else
                    {
                        char c(c1);  // simple unicode to ascii conversion, just ignore c2
                        line += c;  // append the char to end of the line      
                    }    
                 }       
            }
            else
            {
                pkgf.close();
                RemoveDirectoryWithAllFiles(tempdir);
                cerr << "ERROR: Pkg file " + pkgfile_location << " is not supported, check -sisfiles parameter" << endl;
                exit(EXIT_PKG_FILE_CANNOT_OPEN_FOR_READING); 
            } 
        
        }
        else
        {
      		RemoveDirectoryWithAllFiles(tempdir);
     		cerr << "ERROR: Cannot open " + pkgfile_location << " for reading, check -sisfiles parameter" << endl;
    		exit(EXIT_PKG_FILE_CANNOT_OPEN_FOR_READING); 
        }                

        // close handles and clear any temp files        
        pkgf.close();
        RemoveDirectoryWithAllFiles(tempdir);
    }    

    // make sure that the cache directory exists
    MkDirAll(sis_target.cache_dir); 
        
    // write the dependencies cache of the sis files
    WriteDataToDependenciesCacheFile(sis_target);
    
    // append to targets
    _targets.push_back(sis_target);
    
    cerr << endl;

}

// ----------------------------------------------------------------------------------------------------------