tools/elf4rom/src/outputfile.cpp
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * This program is free software: you can redistribute it and/or modify
       
     6 * it under the terms of the GNU Lesser General Public License as published by
       
     7 * the Free Software Foundation, either version 3 of the License, or
       
     8 * (at your option) any later version.
       
     9 *
       
    10 * This program is distributed in the hope that it will be useful,
       
    11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13 * GNU Lesser General Public License for more details.
       
    14 * 
       
    15 * You should have received a copy of the GNU Lesser General Public License
       
    16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
       
    17 */
       
    18 
       
    19 #include <sys/types.h>
       
    20 #include <sys/stat.h>
       
    21 #include <fcntl.h>
       
    22 #include <cstdio>
       
    23 #include <cstdlib>
       
    24 #include <unistd.h>
       
    25 #include <cassert>
       
    26 
       
    27 #include "outputfile.h"
       
    28 
       
    29 static const size_t NumReservedFileFragments = 100;
       
    30 
       
    31 OutputFile::OutputFile(PathName aFileName) :
       
    32 	iFileName(aFileName), iOpened(false), iFd(-1), iCurrentOffset(0)
       
    33 {
       
    34 	assert(iFileName.size() != 0);
       
    35 	// reserve space for file fragments
       
    36 	iFileFragments.reserve(NumReservedFileFragments);
       
    37 }
       
    38 
       
    39 OutputFile::~OutputFile(){
       
    40 	iFileFragments.clear();
       
    41 	if (iOpened)
       
    42 		Close();
       
    43 }
       
    44 
       
    45 
       
    46 void OutputFile::Close(){
       
    47 	if (iOpened) {
       
    48 		close(iFd);
       
    49 		iOpened = false;
       
    50 	}
       
    51 }
       
    52 
       
    53 void OutputFile::Flush(){
       
    54 	if (!iOpened)
       
    55 		Open();
       
    56 	if (iFileFragments.size() > 0) {
       
    57 		FragmentList::iterator aFrag = iFileFragments.begin();
       
    58 		FragmentList::iterator end = iFileFragments.end();
       
    59 		while (aFrag != end) {
       
    60 			aFrag->Write(this);
       
    61 			aFrag++;
       
    62 		}
       
    63 		iFileFragments.clear();
       
    64 	}	
       
    65 }
       
    66 
       
    67 void OutputFile::Dump(){
       
    68 	Flush();
       
    69 	Close();
       
    70 }
       
    71 
       
    72 const FileFragment & OutputFile::GetFileFragment(FileFragmentOwner * aOwner){
       
    73 	size_t aSize = aOwner->Size();
       
    74 	FileFragment aFragment(iCurrentOffset, aSize, aOwner);
       
    75 	iFileFragments.push_back(aFragment);
       
    76 	iCurrentOffset += ALIGN4(aSize);
       
    77 	return  iFileFragments.back();
       
    78 }
       
    79 
       
    80 void OutputFile::Open(){
       
    81 	if (!iOpened) {
       
    82 		if ((iFd = open(iFileName.c_str(), O_WRONLY | O_CREAT | O_BINARY | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) {
       
    83 			char msg[1000];
       
    84 			sprintf(msg, "Output file %s", iFileName.c_str());
       
    85 			perror(msg);
       
    86 			exit(EXIT_FAILURE);
       
    87 		}
       
    88 		iOpened = true;
       
    89 	}
       
    90 }
       
    91 
       
    92 void OutputFile::Write(size_t aOffset, size_t aSize, char * aData){
       
    93 	assert(((aSize==0) && (aData==NULL)) || ((aSize>0) && (aData!=NULL)));
       
    94 	if (aSize == 0) return;
       
    95 	char msg[1000];
       
    96 #ifndef USE_PWRITE
       
    97 	if (lseek(iFd, aOffset, SEEK_SET) != (int)aOffset) {
       
    98 		sprintf(msg, "Failed to seek to offset %d in output file %s", aOffset, iFileName.c_str());
       
    99 		goto error;
       
   100 	}
       
   101 	for (size_t n = 0; n < aSize;) {
       
   102 		if ((int)(n += write(iFd, aData+n, aSize - n)) == -1) {
       
   103 			sprintf(msg, "Failed to write to output file %s", iFileName.c_str());
       
   104 			goto error;			
       
   105 		}
       
   106 	}
       
   107 #else
       
   108 	for (size_t n = 0; n < aSize;) {
       
   109 		if ((n += pwrite(iFd, aData+n, aSize - n, aOffset + n)) == -1) {
       
   110 			sprintf(msg, "Failed to write to output file %s", iFileName.c_str());
       
   111 			goto error;			
       
   112 		}
       
   113 	}	
       
   114 #endif
       
   115 	return;
       
   116 	
       
   117 error:
       
   118 		perror(msg);
       
   119 // should we close the file and delete it??		
       
   120 #ifdef DELETE_OUTPUT_ON_ERROR
       
   121 		Close();
       
   122 		unlink(iFileName);
       
   123 #endif
       
   124 		exit(EXIT_FAILURE);
       
   125 }