X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/a76a584e46e53dea1aeaf98735079833b08472d2..99158c43616f0c09dc1810ce9913090acd02311e:/apt-pkg/contrib/mmap.cc diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index e395e6cc7..4d5fcf71e 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -13,18 +13,9 @@ libc6 generates warnings -- which should be errors, g++ isn't properly strict. - The configure test notes that some OS's have broken private mmap's - so on those OS's we can't use mmap. This means we have to use - configure to test mmap and can't rely on the POSIX - _POSIX_MAPPED_FILES test. - ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#ifdef __GNUG__ -#pragma implementation "apt-pkg/mmap.h" -#endif - #define _BSD_SOURCE #include #include @@ -35,6 +26,9 @@ #include #include #include +#include + +#include /*}}}*/ // MMap::MMap - Constructor /*{{{*/ @@ -119,7 +113,7 @@ bool MMap::Sync() #ifdef _POSIX_SYNCHRONIZED_IO if ((Flags & ReadOnly) != ReadOnly) - if (msync((char *)Base,iSize,MS_SYNC) != 0) + if (msync((char *)Base,iSize,MS_SYNC) < 0) return _error->Errno("msync","Unable to write mmap"); #endif return true; @@ -136,7 +130,7 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop) #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) + if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0) return _error->Errno("msync","Unable to write mmap"); #endif return true; @@ -146,7 +140,7 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop) // DynamicMMap::DynamicMMap - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) : +DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) : MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace) { if (_error->PendingError() == true) @@ -168,15 +162,34 @@ DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) /*}}}*/ // DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/ // --------------------------------------------------------------------- -/* This is just a fancy malloc really.. */ +/* We try here to use mmap to reserve some space - this is much more + cooler than the fallback solution to simply allocate a char array + and could come in handy later than we are able to grow such an mmap */ DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) : MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace) { if (_error->PendingError() == true) return; - + +#ifdef _POSIX_MAPPED_FILES + // Set the permissions. + int Prot = PROT_READ; + int Map = MAP_PRIVATE | MAP_ANONYMOUS; + if ((Flags & ReadOnly) != ReadOnly) + Prot |= PROT_WRITE; + if ((Flags & Public) == Public) + Map = MAP_SHARED | MAP_ANONYMOUS; + + // use anonymous mmap() to get the memory + Base = (unsigned char*) mmap(0, WorkSpace, Prot, Map, -1, 0); + + if(Base == MAP_FAILED) + _error->Errno("DynamicMMap",_("Couldn't make mmap of %lu bytes"),WorkSpace); +#else + // fallback to a static allocated space Base = new unsigned char[WorkSpace]; memset(Base,0,WorkSpace); +#endif iSize = 0; } /*}}}*/ @@ -187,14 +200,19 @@ DynamicMMap::~DynamicMMap() { if (Fd == 0) { +#ifdef _POSIX_MAPPED_FILES + munmap(Base, WorkSpace); +#else delete [] (unsigned char *)Base; +#endif return; } unsigned long EndOfFile = iSize; iSize = WorkSpace; Close(false); - ftruncate(Fd->Fd(),EndOfFile); + if(ftruncate(Fd->Fd(),EndOfFile) < 0) + _error->Errno("ftruncate", _("Failed to truncate file")); } /*}}}*/ // DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/ @@ -205,16 +223,19 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln) unsigned long Result = iSize; if (Aln != 0) Result += Aln - (iSize%Aln); - + iSize = Result + Size; - - // Just in case error check - if (Result + Size > WorkSpace) + + // try to grow the buffer + while(Result + Size > WorkSpace) { - _error->Error("Dynamic MMap ran out of room"); - return 0; + if(!Grow()) + { + _error->Error(_("Dynamic MMap ran out of room. Please increase the size " + "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace); + return 0; + } } - return Result; } /*}}}*/ @@ -223,7 +244,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln) /* This allocates an Item of size ItemSize so that it is aligned to its size in the file. */ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) -{ +{ // Look for a matching pool entry Pool *I; Pool *Empty = 0; @@ -234,7 +255,6 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) if (I->ItemSize == ItemSize) break; } - // No pool is allocated, use an unallocated one if (I == Pools + PoolCount) { @@ -249,17 +269,24 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) I->ItemSize = ItemSize; I->Count = 0; } - + + unsigned long Result = 0; // Out of space, allocate some more if (I->Count == 0) { - I->Count = 20*1024/ItemSize; - I->Start = RawAllocate(I->Count*ItemSize,ItemSize); - } + const unsigned long size = 20*1024; + I->Count = size/ItemSize; + Result = RawAllocate(size,ItemSize); + // Does the allocation failed ? + if (Result == 0 && _error->PendingError()) + return 0; + I->Start = Result; + } + else + Result = I->Start; I->Count--; - unsigned long Result = I->Start; - I->Start += ItemSize; + I->Start += ItemSize; return Result/ItemSize; } /*}}}*/ @@ -269,19 +296,45 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) unsigned long DynamicMMap::WriteString(const char *String, unsigned long Len) { - unsigned long Result = iSize; - // Just in case error check - if (Result + Len > WorkSpace) - { - _error->Error("Dynamic MMap ran out of room"); - return 0; - } - if (Len == (unsigned long)-1) Len = strlen(String); - iSize += Len + 1; + + unsigned long Result = RawAllocate(Len+1,0); + + if (Result == 0 && _error->PendingError()) + return 0; + memcpy((char *)Base + Result,String,Len); ((char *)Base)[Result + Len] = 0; return Result; } /*}}}*/ +// DynamicMMap::Grow - Grow the mmap /*{{{*/ +// --------------------------------------------------------------------- +/* This method will try to grow the mmap we currently use. This doesn't + work most of the time because we can't move the mmap around in the + memory for now as this would require to adjust quite a lot of pointers + but why we should not at least try to grow it before we give up? */ +bool DynamicMMap::Grow() +{ +#if defined(_POSIX_MAPPED_FILES) && defined(__linux__) + unsigned long newSize = WorkSpace + 1024*1024; + + if(Fd != 0) + { + Fd->Seek(newSize - 1); + char C = 0; + Fd->Write(&C,sizeof(C)); + } + + Base = mremap(Base, WorkSpace, newSize, 0); + if(Base == MAP_FAILED) + return false; + + WorkSpace = newSize; + return true; +#else + return false; +#endif +} + /*}}}*/