13
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
16
##################################################################### */
23
18
// Include Files /*{{{*/
24
19
#define _BSD_SOURCE
25
#include <apt-pkg/contrib/mmap.h>
26
#include <apt-pkg/contrib/error.h>
20
#include <apt-pkg/mmap.h>
21
#include <apt-pkg/error.h>
28
23
#include <apti18n.h>
144
140
// DynamicMMap::DynamicMMap - Constructor /*{{{*/
145
141
// ---------------------------------------------------------------------
147
DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) :
148
MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace)
143
DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long const &Workspace,
144
unsigned long const &Grow, unsigned long const &Limit) :
145
MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(Workspace),
146
GrowFactor(Grow), Limit(Limit)
150
148
if (_error->PendingError() == true)
167
165
// DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/
168
166
// ---------------------------------------------------------------------
169
/* This is just a fancy malloc really.. */
170
DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
171
MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
167
/* We try here to use mmap to reserve some space - this is much more
168
cooler than the fallback solution to simply allocate a char array
169
and could come in handy later than we are able to grow such an mmap */
170
DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace,
171
unsigned long const &Grow, unsigned long const &Limit) :
172
MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace),
173
GrowFactor(Grow), Limit(Limit)
173
if (_error->PendingError() == true)
176
Base = new unsigned char[WorkSpace];
177
memset(Base,0,WorkSpace);
175
if (_error->PendingError() == true)
178
// disable Moveable if we don't grow
183
// kfreebsd doesn't have mremap, so we use the fallback
184
if ((Flags & Moveable) == Moveable)
188
#ifdef _POSIX_MAPPED_FILES
189
if ((Flags & Fallback) != Fallback) {
190
// Set the permissions.
191
int Prot = PROT_READ;
192
int Map = MAP_PRIVATE | MAP_ANONYMOUS;
193
if ((Flags & ReadOnly) != ReadOnly)
195
if ((Flags & Public) == Public)
196
Map = MAP_SHARED | MAP_ANONYMOUS;
198
// use anonymous mmap() to get the memory
199
Base = (unsigned char*) mmap(0, WorkSpace, Prot, Map, -1, 0);
201
if(Base == MAP_FAILED)
202
_error->Errno("DynamicMMap",_("Couldn't make mmap of %lu bytes"),WorkSpace);
208
// fallback to a static allocated space
209
Base = new unsigned char[WorkSpace];
210
memset(Base,0,WorkSpace);
181
214
// DynamicMMap::~DynamicMMap - Destructor /*{{{*/
204
241
unsigned long Result = iSize;
206
243
Result += Aln - (iSize%Aln);
208
245
iSize = Result + Size;
210
// Just in case error check
211
if (Result + Size > WorkSpace)
247
// try to grow the buffer
248
while(Result + Size > WorkSpace)
213
_error->Error(_("Dynamic MMap ran out of room. Please increase the size "
214
"of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
252
_error->Error(_("Dynamic MMap ran out of room. Please increase the size "
253
"of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
249
287
I->ItemSize = ItemSize;
291
unsigned long Result = 0;
253
292
// Out of space, allocate some more
254
293
if (I->Count == 0)
256
I->Count = 20*1024/ItemSize;
257
I->Start = RawAllocate(I->Count*ItemSize,ItemSize);
295
const unsigned long size = 20*1024;
296
I->Count = size/ItemSize;
297
Result = RawAllocate(size,ItemSize);
298
// Does the allocation failed ?
299
if (Result == 0 && _error->PendingError())
261
unsigned long Result = I->Start;
262
I->Start += ItemSize;
307
I->Start += ItemSize;
263
308
return Result/ItemSize;
269
314
unsigned long DynamicMMap::WriteString(const char *String,
270
315
unsigned long Len)
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. Please increase the size "
277
"of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
281
317
if (Len == (unsigned long)-1)
282
318
Len = strlen(String);
320
unsigned long Result = RawAllocate(Len+1,0);
322
if (Result == 0 && _error->PendingError())
284
325
memcpy((char *)Base + Result,String,Len);
285
326
((char *)Base)[Result + Len] = 0;
330
// DynamicMMap::Grow - Grow the mmap /*{{{*/
331
// ---------------------------------------------------------------------
332
/* This method is a wrapper around different methods to (try to) grow
333
a mmap (or our char[]-fallback). Encounterable environments:
334
1. Moveable + !Fallback + linux -> mremap with MREMAP_MAYMOVE
335
2. Moveable + !Fallback + !linux -> not possible (forbidden by constructor)
336
3. Moveable + Fallback -> realloc
337
4. !Moveable + !Fallback + linux -> mremap alone - which will fail in 99,9%
338
5. !Moveable + !Fallback + !linux -> not possible (forbidden by constructor)
339
6. !Moveable + Fallback -> not possible
340
[ While Moveable and Fallback stands for the equally named flags and
341
"linux" indicates a linux kernel instead of a freebsd kernel. ]
342
So what you can see here is, that a MMAP which want to be growable need
343
to be moveable to have a real chance but that this method will at least try
344
the nearly impossible 4 to grow it before it finally give up: Never say never. */
345
bool DynamicMMap::Grow() {
346
if (Limit != 0 && WorkSpace >= Limit)
347
return _error->Error(_("The size of a MMap has already reached the defined limit of %lu bytes,"
348
"abort the try to grow the MMap."), Limit);
350
unsigned long const newSize = WorkSpace + 1024*1024;
353
Fd->Seek(newSize - 1);
355
Fd->Write(&C,sizeof(C));
357
if ((Flags & Fallback) != Fallback) {
358
#if defined(_POSIX_MAPPED_FILES) && defined(__linux__)
359
#ifdef MREMAP_MAYMOVE
360
if ((Flags & Moveable) == Moveable)
361
Base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE);
364
Base = mremap(Base, WorkSpace, newSize, 0);
366
if(Base == MAP_FAILED)
372
if ((Flags & Moveable) != Moveable)
375
Base = realloc(Base, newSize);