summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/contrib/mmap.cc70
-rw-r--r--apt-pkg/contrib/mmap.h5
-rw-r--r--debian/changelog4
3 files changed, 68 insertions, 11 deletions
diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc
index f440f9489..b3f29032c 100644
--- a/apt-pkg/contrib/mmap.cc
+++ b/apt-pkg/contrib/mmap.cc
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
+#include <errno.h>
#include <cstring>
/*}}}*/
@@ -35,7 +36,7 @@
// ---------------------------------------------------------------------
/* */
MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
- Base(0)
+ Base(0), SyncToFd(NULL)
{
if ((Flags & NoImmMap) != NoImmMap)
Map(F);
@@ -45,7 +46,7 @@ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
// ---------------------------------------------------------------------
/* */
MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0),
- Base(0)
+ Base(0), SyncToFd(NULL)
{
}
/*}}}*/
@@ -78,7 +79,24 @@ bool MMap::Map(FileFd &Fd)
// Map it.
Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
if (Base == (void *)-1)
- return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"),iSize);
+ {
+ if (errno == ENODEV || errno == EINVAL)
+ {
+ // The filesystem doesn't support this particular kind of mmap.
+ // So we allocate a buffer and read the whole file into it.
+ 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];
+ 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 %lu bytes"),
+ iSize);
+ }
return true;
}
@@ -93,10 +111,19 @@ bool MMap::Close(bool DoSync)
if (DoSync == true)
Sync();
-
- if (munmap((char *)Base,iSize) != 0)
- _error->Warning("Unable to munmap");
-
+
+ if (SyncToFd != NULL)
+ {
+ delete[] (char *)Base;
+ delete SyncToFd;
+ SyncToFd = NULL;
+ }
+ else
+ {
+ if (munmap((char *)Base, iSize) != 0)
+ _error->WarningE("mmap", _("Unable to close mmap"));
+ }
+
iSize = 0;
Base = 0;
return true;
@@ -113,8 +140,18 @@ bool MMap::Sync()
#ifdef _POSIX_SYNCHRONIZED_IO
if ((Flags & ReadOnly) != ReadOnly)
- if (msync((char *)Base,iSize,MS_SYNC) < 0)
- return _error->Errno("msync","Unable to write mmap");
+ {
+ if (SyncToFd != NULL)
+ {
+ if (!SyncToFd->Seek(0) || !SyncToFd->Write(Base, iSize))
+ return false;
+ }
+ else
+ {
+ if (msync((char *)Base, iSize, MS_SYNC) < 0)
+ return _error->Errno("msync", _("Unable to synchronize mmap"));
+ }
+ }
#endif
return true;
}
@@ -130,8 +167,19 @@ 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)
- return _error->Errno("msync","Unable to write mmap");
+ {
+ if (SyncToFd != 0)
+ {
+ if (!SyncToFd->Seek(0) ||
+ !SyncToFd->Write (((char *)Base)+Start, Stop-Start))
+ return false;
+ }
+ else
+ {
+ if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0)
+ return _error->Errno("msync", _("Unable to synchronize mmap"));
+ }
+ }
#endif
return true;
}
diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h
index cd2b15ba2..5ca951204 100644
--- a/apt-pkg/contrib/mmap.h
+++ b/apt-pkg/contrib/mmap.h
@@ -44,6 +44,11 @@ class MMap
unsigned long iSize;
void *Base;
+ // In case mmap can not be used, we keep a dup of the file
+ // descriptor that should have been mmaped so that we can write to
+ // the file in Sync().
+ FileFd *SyncToFd;
+
bool Map(FileFd &Fd);
bool Close(bool DoSync = true);
diff --git a/debian/changelog b/debian/changelog
index 9fc481276..39cc70da9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,6 +5,10 @@ apt (0.7.26) UNRELEASED; urgency=low
- don't crash if no arguments are given (Closes: #570962)
* debian/control:
- remove some years old and obsolete Replaces
+ * apt-pkg/contrib/mmap.{h,cc}:
+ - add char[] fallback for filesystems without shared writable
+ mmap() like JFFS2. Thanks to Marius Vollmer for writing
+ and to Loïc Minier for pointing to the patch! (Closes: #314334)
-- David Kalnischkies <kalnischkies@gmail.com> Fri, 19 Feb 2010 21:21:43 +0100