tools/elf4rom/src/outputfile.cpp
changeset 34 92d87f2e53c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/src/outputfile.cpp	Fri Jan 15 09:07:44 2010 +0000
@@ -0,0 +1,125 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+* 
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <cstdio>
+#include <cstdlib>
+#include <unistd.h>
+#include <cassert>
+
+#include "outputfile.h"
+
+static const size_t NumReservedFileFragments = 100;
+
+OutputFile::OutputFile(PathName aFileName) :
+	iFileName(aFileName), iOpened(false), iFd(-1), iCurrentOffset(0)
+{
+	assert(iFileName.size() != 0);
+	// reserve space for file fragments
+	iFileFragments.reserve(NumReservedFileFragments);
+}
+
+OutputFile::~OutputFile(){
+	iFileFragments.clear();
+	if (iOpened)
+		Close();
+}
+
+
+void OutputFile::Close(){
+	if (iOpened) {
+		close(iFd);
+		iOpened = false;
+	}
+}
+
+void OutputFile::Flush(){
+	if (!iOpened)
+		Open();
+	if (iFileFragments.size() > 0) {
+		FragmentList::iterator aFrag = iFileFragments.begin();
+		FragmentList::iterator end = iFileFragments.end();
+		while (aFrag != end) {
+			aFrag->Write(this);
+			aFrag++;
+		}
+		iFileFragments.clear();
+	}	
+}
+
+void OutputFile::Dump(){
+	Flush();
+	Close();
+}
+
+const FileFragment & OutputFile::GetFileFragment(FileFragmentOwner * aOwner){
+	size_t aSize = aOwner->Size();
+	FileFragment aFragment(iCurrentOffset, aSize, aOwner);
+	iFileFragments.push_back(aFragment);
+	iCurrentOffset += ALIGN4(aSize);
+	return  iFileFragments.back();
+}
+
+void OutputFile::Open(){
+	if (!iOpened) {
+		if ((iFd = open(iFileName.c_str(), O_WRONLY | O_CREAT | O_BINARY | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) {
+			char msg[1000];
+			sprintf(msg, "Output file %s", iFileName.c_str());
+			perror(msg);
+			exit(EXIT_FAILURE);
+		}
+		iOpened = true;
+	}
+}
+
+void OutputFile::Write(size_t aOffset, size_t aSize, char * aData){
+	assert(((aSize==0) && (aData==NULL)) || ((aSize>0) && (aData!=NULL)));
+	if (aSize == 0) return;
+	char msg[1000];
+#ifndef USE_PWRITE
+	if (lseek(iFd, aOffset, SEEK_SET) != (int)aOffset) {
+		sprintf(msg, "Failed to seek to offset %d in output file %s", aOffset, iFileName.c_str());
+		goto error;
+	}
+	for (size_t n = 0; n < aSize;) {
+		if ((int)(n += write(iFd, aData+n, aSize - n)) == -1) {
+			sprintf(msg, "Failed to write to output file %s", iFileName.c_str());
+			goto error;			
+		}
+	}
+#else
+	for (size_t n = 0; n < aSize;) {
+		if ((n += pwrite(iFd, aData+n, aSize - n, aOffset + n)) == -1) {
+			sprintf(msg, "Failed to write to output file %s", iFileName.c_str());
+			goto error;			
+		}
+	}	
+#endif
+	return;
+	
+error:
+		perror(msg);
+// should we close the file and delete it??		
+#ifdef DELETE_OUTPUT_ON_ERROR
+		Close();
+		unlink(iFileName);
+#endif
+		exit(EXIT_FAILURE);
+}