1
// -*- mode: cpp; mode: fold -*-
3
// $Id: mmap.cc,v 1.22 2001/05/27 05:19:30 jgg Exp $
4
/* ######################################################################
6
MMap Class - Provides 'real' mmap or a faked mmap using read().
10
Some broken versions of glibc2 (libc6) have a broken definition
11
of mmap that accepts a char * -- all other systems (and libc5) use
12
void *. We can't safely do anything here that would be portable, so
13
libc6 generates warnings -- which should be errors, g++ isn't properly
16
The configure test notes that some OS's have broken private mmap's
17
so on those OS's we can't use mmap. This means we have to use
18
configure to test mmap and can't rely on the POSIX
19
_POSIX_MAPPED_FILES test.
21
##################################################################### */
23
// Include Files /*{{{*/
25
#pragma implementation "apt-pkg/mmap.h"
29
#include <apt-pkg/mmap.h>
30
#include <apt-pkg/error.h>
40
// MMap::MMap - Constructor /*{{{*/
41
// ---------------------------------------------------------------------
43
MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
46
if ((Flags & NoImmMap) != NoImmMap)
50
// MMap::MMap - Constructor /*{{{*/
51
// ---------------------------------------------------------------------
53
MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0),
58
// MMap::~MMap - Destructor /*{{{*/
59
// ---------------------------------------------------------------------
66
// MMap::Map - Perform the mapping /*{{{*/
67
// ---------------------------------------------------------------------
69
bool MMap::Map(FileFd &Fd)
73
// Set the permissions.
76
if ((Flags & ReadOnly) != ReadOnly)
78
if ((Flags & Public) != Public)
82
return _error->Error(_("Can't mmap an empty file"));
85
Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
86
if (Base == (void *)-1)
87
return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"),iSize);
92
// MMap::Close - Close the map /*{{{*/
93
// ---------------------------------------------------------------------
95
bool MMap::Close(bool DoSync)
97
if ((Flags & UnMapped) == UnMapped || Base == 0 || iSize == 0)
103
if (munmap((char *)Base,iSize) != 0)
104
_error->Warning("Unable to munmap");
111
// MMap::Sync - Syncronize the map with the disk /*{{{*/
112
// ---------------------------------------------------------------------
113
/* This is done in syncronous mode - the docs indicate that this will
114
not return till all IO is complete */
117
if ((Flags & UnMapped) == UnMapped)
120
#ifdef _POSIX_SYNCHRONIZED_IO
121
if ((Flags & ReadOnly) != ReadOnly)
122
if (msync((char *)Base,iSize,MS_SYNC) != 0)
123
return _error->Errno("msync","Unable to write mmap");
128
// MMap::Sync - Syncronize a section of the file to disk /*{{{*/
129
// ---------------------------------------------------------------------
131
bool MMap::Sync(unsigned long Start,unsigned long Stop)
133
if ((Flags & UnMapped) == UnMapped)
136
#ifdef _POSIX_SYNCHRONIZED_IO
137
unsigned long PSize = sysconf(_SC_PAGESIZE);
138
if ((Flags & ReadOnly) != ReadOnly)
139
if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) != 0)
140
return _error->Errno("msync","Unable to write mmap");
146
// DynamicMMap::DynamicMMap - Constructor /*{{{*/
147
// ---------------------------------------------------------------------
149
DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) :
150
MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace)
152
if (_error->PendingError() == true)
155
unsigned long EndOfFile = Fd->Size();
156
if (EndOfFile > WorkSpace)
157
WorkSpace = EndOfFile;
162
Fd->Write(&C,sizeof(C));
169
// DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/
170
// ---------------------------------------------------------------------
171
/* This is just a fancy malloc really.. */
172
DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
173
MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
175
if (_error->PendingError() == true)
178
Base = new unsigned char[WorkSpace];
179
memset(Base,0,WorkSpace);
183
// DynamicMMap::~DynamicMMap - Destructor /*{{{*/
184
// ---------------------------------------------------------------------
185
/* We truncate the file to the size of the memory data set */
186
DynamicMMap::~DynamicMMap()
190
delete [] (unsigned char *)Base;
194
unsigned long EndOfFile = iSize;
197
ftruncate(Fd->Fd(),EndOfFile);
200
// DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/
201
// ---------------------------------------------------------------------
202
/* This allocates a block of memory aligned to the given size */
203
unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
205
unsigned long Result = iSize;
207
Result += Aln - (iSize%Aln);
209
iSize = Result + Size;
211
// Just in case error check
212
if (Result + Size > WorkSpace)
214
_error->Error("Dynamic MMap ran out of room");
221
// DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/
222
// ---------------------------------------------------------------------
223
/* This allocates an Item of size ItemSize so that it is aligned to its
225
unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
227
// Look for a matching pool entry
230
for (I = Pools; I != Pools + PoolCount; I++)
232
if (I->ItemSize == 0)
234
if (I->ItemSize == ItemSize)
238
// No pool is allocated, use an unallocated one
239
if (I == Pools + PoolCount)
241
// Woops, we ran out, the calling code should allocate more.
244
_error->Error("Ran out of allocation pools");
249
I->ItemSize = ItemSize;
253
// Out of space, allocate some more
256
I->Count = 20*1024/ItemSize;
257
I->Start = RawAllocate(I->Count*ItemSize,ItemSize);
261
unsigned long Result = I->Start;
262
I->Start += ItemSize;
263
return Result/ItemSize;
266
// DynamicMMap::WriteString - Write a string to the file /*{{{*/
267
// ---------------------------------------------------------------------
268
/* Strings are not aligned to anything */
269
unsigned long DynamicMMap::WriteString(const char *String,
272
unsigned long Result = iSize;
273
// Just in case error check
274
if (Result + Len > WorkSpace)
276
_error->Error("Dynamic MMap ran out of room");
280
if (Len == (unsigned long)-1)
281
Len = strlen(String);
283
memcpy((char *)Base + Result,String,Len);
284
((char *)Base)[Result + Len] = 0;