// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: mmap.cc,v 1.2 1998/07/04 05:57:42 jgg Exp $
+// $Id: mmap.cc,v 1.22 2001/05/27 05:19:30 jgg Exp $
/* ######################################################################
MMap Class - Provides 'real' mmap or a faked mmap using read().
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
+#ifdef __GNUG__
+#pragma implementation "apt-pkg/mmap.h"
+#endif
+
#define _BSD_SOURCE
-#include <pkglib/mmap.h>
-#include <pkglib/error.h>
+#include <apt-pkg/mmap.h>
+#include <apt-pkg/error.h>
+
+#include <apti18n.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <sys/user.h>
#include <unistd.h>
#include <fcntl.h>
/*}}}*/
// MMap::MMap - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-MMap::MMap(File &F,unsigned long Flags) : Fd(F), Flags(Flags), iSize(0),
+MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
Base(0)
{
if ((Flags & NoImmMap) != NoImmMap)
- Map();
+ Map(F);
+}
+ /*}}}*/
+// MMap::MMap - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0),
+ Base(0)
+{
}
/*}}}*/
// MMap::~MMap - Destructor /*{{{*/
/* */
MMap::~MMap()
{
- Close(true);
+ Close();
}
/*}}}*/
// MMap::Map - Perform the mapping /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool MMap::Map()
+bool MMap::Map(FileFd &Fd)
{
iSize = Fd.Size();
if ((Flags & Public) != Public)
Map = MAP_PRIVATE;
+ if (iSize == 0)
+ return _error->Error(_("Can't mmap an empty file"));
+
// Map it.
Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
if (Base == (void *)-1)
- return _error->Errno("mmap","Couldn't make mmap of %u bytes",iSize);
+ return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"),iSize);
return true;
}
// MMap::Close - Close the map /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool MMap::Close(bool DoClose)
+bool MMap::Close(bool DoSync)
{
- if (Fd.IsOpen() == false)
+ if ((Flags & UnMapped) == UnMapped || Base == 0 || iSize == 0)
return true;
-
- Sync();
+
+ if (DoSync == true)
+ Sync();
if (munmap((char *)Base,iSize) != 0)
_error->Warning("Unable to munmap");
iSize = 0;
- if (DoClose == true)
- Fd.Close();
+ Base = 0;
return true;
}
/*}}}*/
// MMap::Sync - Syncronize the map with the disk /*{{{*/
// ---------------------------------------------------------------------
-/* */
+/* This is done in syncronous mode - the docs indicate that this will
+ not return till all IO is complete */
bool MMap::Sync()
{
- if ((Flags & ReadOnly) == ReadOnly)
+ if ((Flags & UnMapped) == UnMapped)
+ return true;
+
+#ifdef _POSIX_SYNCHRONIZED_IO
+ if ((Flags & ReadOnly) != ReadOnly)
if (msync((char *)Base,iSize,MS_SYNC) != 0)
- return _error->Error("msync","Unable to write mmap");
+ return _error->Errno("msync","Unable to write mmap");
+#endif
return true;
}
/*}}}*/
/* */
bool MMap::Sync(unsigned long Start,unsigned long Stop)
{
- if ((Flags & ReadOnly) == ReadOnly)
- if (msync((char *)Base+(int)(Start/PAGE_SIZE)*PAGE_SIZE,Stop - Start,MS_SYNC) != 0)
- return _error->Error("msync","Unable to write mmap");
+ if ((Flags & UnMapped) == UnMapped)
+ return true;
+
+#ifdef _POSIX_SYNCHRONIZED_IO
+ unsigned long PSize = sysconf(_SC_PAGESIZE);
+ if ((Flags & ReadOnly) != ReadOnly)
+ if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) != 0)
+ return _error->Errno("msync","Unable to write mmap");
+#endif
return true;
}
/*}}}*/
// DynamicMMap::DynamicMMap - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-DynamicMMap::DynamicMMap(File &F,unsigned long Flags,unsigned long WorkSpace) :
- MMap(F,Flags | NoImmMap), WorkSpace(WorkSpace)
+DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) :
+ MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace)
{
- unsigned long EndOfFile = Fd.Size();
- Fd.Seek(WorkSpace);
- char C = 0;
- Fd.Write(&C,sizeof(C));
- Map();
+ if (_error->PendingError() == true)
+ return;
+
+ unsigned long EndOfFile = Fd->Size();
+ if (EndOfFile > WorkSpace)
+ WorkSpace = EndOfFile;
+ else if(WorkSpace > 0)
+ {
+ Fd->Seek(WorkSpace - 1);
+ char C = 0;
+ Fd->Write(&C,sizeof(C));
+ }
+
+ Map(F);
iSize = EndOfFile;
}
/*}}}*/
+// DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/
+// ---------------------------------------------------------------------
+/* This is just a fancy malloc really.. */
+DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
+ MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
+{
+ if (_error->PendingError() == true)
+ return;
+
+ Base = new unsigned char[WorkSpace];
+ memset(Base,0,WorkSpace);
+ iSize = 0;
+}
+ /*}}}*/
// DynamicMMap::~DynamicMMap - Destructor /*{{{*/
// ---------------------------------------------------------------------
/* We truncate the file to the size of the memory data set */
DynamicMMap::~DynamicMMap()
{
+ if (Fd == 0)
+ {
+ delete [] (unsigned char *)Base;
+ return;
+ }
+
unsigned long EndOfFile = iSize;
+ iSize = WorkSpace;
Close(false);
- ftruncate(Fd.Fd(),EndOfFile);
- Fd.Close();
+ ftruncate(Fd->Fd(),EndOfFile);
}
/*}}}*/
// DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/
iSize = Result + Size;
// Just in case error check
- if (Result > WorkSpace)
+ if (Result + Size > WorkSpace)
{
_error->Error("Dynamic MMap ran out of room");
return 0;
}
+
return Result;
}
/*}}}*/
I->Count--;
unsigned long Result = I->Start;
- I->Start += ItemSize;
+ I->Start += ItemSize;
return Result/ItemSize;
}
/*}}}*/
{
unsigned long Result = iSize;
// Just in case error check
- if (Result > WorkSpace)
+ if (Result + Len > WorkSpace)
{
_error->Error("Dynamic MMap ran out of room");
return 0;
}
- if (Len == 0)
+ if (Len == (unsigned long)-1)
Len = strlen(String);
iSize += Len + 1;
memcpy((char *)Base + Result,String,Len);