X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/fa64f7b255b6fce2949ccd13a01714a595020534..f932bccbf7f8e8c06cb978e9a9b722d1b583c358:/apt-pkg/contrib/mmap.cc diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index 2d12b6fe9..8fbddbd2f 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -16,17 +16,17 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#define _BSD_SOURCE +#define _DEFAULT_SOURCE #include #include #include #include +#include +#include #include -#include #include -#include #include #include #include @@ -38,9 +38,8 @@ // --------------------------------------------------------------------- /* */ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0), - Base(0), SyncToFd(NULL) + Base(nullptr), SyncToFd(nullptr) { - if ((Flags & NoImmMap) != NoImmMap) Map(F); } /*}}}*/ @@ -48,7 +47,7 @@ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0), // --------------------------------------------------------------------- /* */ MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0), - Base(0), SyncToFd(NULL) + Base(nullptr), SyncToFd(nullptr) { } /*}}}*/ @@ -83,7 +82,9 @@ bool MMap::Map(FileFd &Fd) { if ((Flags & ReadOnly) != ReadOnly) return _error->Error("Compressed file %s can only be mapped readonly", Fd.Name().c_str()); - Base = new unsigned char[iSize]; + Base = malloc(iSize); + if (unlikely(Base == nullptr)) + return _error->Errno("MMap-compressed-malloc", _("Couldn't make mmap of %llu bytes"), iSize); SyncToFd = new FileFd(); if (Fd.Seek(0L) == false || Fd.Read(Base, iSize) == false) return _error->Error("Compressed file %s can't be read into mmap", Fd.Name().c_str()); @@ -91,32 +92,36 @@ bool MMap::Map(FileFd &Fd) } // Map it. - Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0); - if (Base == (void *)-1) + Base = (Flags & Fallback) ? MAP_FAILED : mmap(0,iSize,Prot,Map,Fd.Fd(),0); + if (Base == MAP_FAILED) { - if (errno == ENODEV || errno == EINVAL) + if (errno == ENODEV || errno == EINVAL || (Flags & Fallback)) { // The filesystem doesn't support this particular kind of mmap. // So we allocate a buffer and read the whole file into it. if ((Flags & ReadOnly) == ReadOnly) { // for readonly, we don't need sync, so make it simple - Base = new unsigned char[iSize]; - return Fd.Read(Base, iSize); + Base = malloc(iSize); + if (unlikely(Base == nullptr)) + return _error->Errno("MMap-malloc", _("Couldn't make mmap of %llu bytes"), iSize); + SyncToFd = new FileFd(); + return Fd.Seek(0L) && Fd.Read(Base, iSize); } // FIXME: Writing to compressed fd's ? int const dupped_fd = dup(Fd.Fd()); if (dupped_fd == -1) return _error->Errno("mmap", _("Couldn't duplicate file descriptor %i"), Fd.Fd()); - Base = new unsigned char[iSize]; + Base = malloc(iSize); + if (unlikely(Base == nullptr)) + return _error->Errno("MMap-calloc", _("Couldn't make mmap of %llu bytes"), iSize); SyncToFd = new FileFd (dupped_fd); if (!SyncToFd->Seek(0L) || !SyncToFd->Read(Base, iSize)) return false; } else - return _error->Errno("mmap",_("Couldn't make mmap of %llu bytes"), - iSize); + return _error->Errno("MMap-mmap", _("Couldn't make mmap of %llu bytes"), iSize); } return true; @@ -135,7 +140,7 @@ bool MMap::Close(bool DoSync) if (SyncToFd != NULL) { - delete[] (char *)Base; + free(Base); delete SyncToFd; SyncToFd = NULL; } @@ -155,11 +160,10 @@ bool MMap::Close(bool DoSync) /* This is done in syncronous mode - the docs indicate that this will not return till all IO is complete */ bool MMap::Sync() -{ +{ if ((Flags & UnMapped) == UnMapped) return true; - -#ifdef _POSIX_SYNCHRONIZED_IO + if ((Flags & ReadOnly) != ReadOnly) { if (SyncToFd != NULL) @@ -169,11 +173,12 @@ bool MMap::Sync() } else { +#ifdef _POSIX_SYNCHRONIZED_IO if (msync((char *)Base, iSize, MS_SYNC) < 0) return _error->Errno("msync", _("Unable to synchronize mmap")); +#endif } } -#endif return true; } /*}}}*/ @@ -184,24 +189,25 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop) { if ((Flags & UnMapped) == UnMapped) return true; - -#ifdef _POSIX_SYNCHRONIZED_IO - unsigned long long PSize = sysconf(_SC_PAGESIZE); + if ((Flags & ReadOnly) != ReadOnly) { if (SyncToFd != 0) { - if (!SyncToFd->Seek(0) || + if (!SyncToFd->Seek(Start) || !SyncToFd->Write (((char *)Base)+Start, Stop-Start)) return false; } else { - if (msync((char *)Base+(unsigned long long)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0) +#ifdef _POSIX_SYNCHRONIZED_IO + unsigned long long const PSize = sysconf(_SC_PAGESIZE); + Start = (Start/PSize)*PSize; + if (msync((char *)Base+Start, Stop - Start, MS_SYNC) < 0) return _error->Errno("msync", _("Unable to synchronize mmap")); +#endif } } -#endif return true; } /*}}}*/ @@ -211,12 +217,19 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop) /* */ DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long const &Workspace, unsigned long const &Grow, unsigned long const &Limit) : - MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(Workspace), + MMap(Flags), Fd(&F), WorkSpace(Workspace), GrowFactor(Grow), Limit(Limit) { - if (_error->PendingError() == true) - return; - + // disable Moveable if we don't grow + if (Grow == 0) + this->Flags &= ~Moveable; + +#ifndef __linux__ + // kfreebsd doesn't have mremap, so we use the fallback + if ((this->Flags & Moveable) == Moveable) + this->Flags |= Fallback; +#endif + unsigned long long EndOfFile = Fd->Size(); if (EndOfFile > WorkSpace) WorkSpace = EndOfFile; @@ -238,12 +251,9 @@ DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long const &Work and could come in handy later than we are able to grow such an mmap */ DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace, unsigned long const &Grow, unsigned long const &Limit) : - MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace), + MMap(Flags | UnMapped), Fd(0), WorkSpace(WorkSpace), GrowFactor(Grow), Limit(Limit) { - if (_error->PendingError() == true) - return; - // disable Moveable if we don't grow if (Grow == 0) this->Flags &= ~Moveable; @@ -283,8 +293,7 @@ DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace, } #endif // fallback to a static allocated space - Base = new unsigned char[WorkSpace]; - memset(Base,0,WorkSpace); + Base = calloc(WorkSpace, 1); iSize = 0; } /*}}}*/ @@ -300,7 +309,7 @@ DynamicMMap::~DynamicMMap() #ifdef _POSIX_MAPPED_FILES munmap(Base, WorkSpace); #else - delete [] (unsigned char *)Base; + free(Base); #endif return; } @@ -329,7 +338,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln if(!Grow()) { _error->Fatal(_("Dynamic MMap ran out of room. Please increase the size " - "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace); + "of APT::Cache-Start. Current value: %lu. (man 5 apt.conf)"), WorkSpace); return 0; } } @@ -342,6 +351,12 @@ unsigned long DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln size in the file. */ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) { + if (unlikely(ItemSize == 0)) + { + _error->Fatal("Can't allocate an item of size zero"); + return 0; + } + // Look for a matching pool entry Pool *I; Pool *Empty = 0; @@ -374,12 +389,15 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) const unsigned long size = 20*1024; I->Count = size/ItemSize; Pool* oldPools = Pools; + _error->PushToStack(); Result = RawAllocate(size,ItemSize); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); if (Pools != oldPools) I += Pools - oldPools; // Does the allocation failed ? - if (Result == 0 && _error->PendingError()) + if (Result == 0 && newError) return 0; I->Start = Result; } @@ -393,18 +411,28 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) /*}}}*/ // DynamicMMap::WriteString - Write a string to the file /*{{{*/ // --------------------------------------------------------------------- -/* Strings are not aligned to anything */ +/* Strings are aligned to 16 bytes */ unsigned long DynamicMMap::WriteString(const char *String, unsigned long Len) { if (Len == (unsigned long)-1) Len = strlen(String); - unsigned long const Result = RawAllocate(Len+1,0); + _error->PushToStack(); + unsigned long Result = RawAllocate(Len+1+sizeof(uint16_t),sizeof(uint16_t)); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); - if (Result == 0 && _error->PendingError()) + if (Base == NULL || (Result == 0 && newError)) return 0; + if (Len >= std::numeric_limits::max()) + abort(); + + uint16_t LenToWrite = Len; + memcpy((char *)Base + Result, &LenToWrite, sizeof(LenToWrite)); + Result += + sizeof(LenToWrite); + memcpy((char *)Base + Result,String,Len); ((char *)Base)[Result + Len] = 0; return Result; @@ -464,6 +492,9 @@ bool DynamicMMap::Grow() { Base = realloc(Base, newSize); if (Base == NULL) return false; + else + /* Set new memory to 0 */ + memset((char*)Base + WorkSpace, 0, newSize - WorkSpace); } Pools =(Pool*) Base + poolOffset;