summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib/mmap.cc
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2010-04-01 17:18:31 +0200
committerMichael Vogt <michael.vogt@ubuntu.com>2010-04-01 17:18:31 +0200
commit46361a17f0cb6f4f7c46705c5af71b6680cf5b1d (patch)
treee7466e094406d5d195823840cb2d43a371f67bea /apt-pkg/contrib/mmap.cc
parent3b1fffc35f3eb277d92f38c687c270edd1d8550d (diff)
parent436d7eab92bb8f9cc6498acfbf2055e717be6fd0 (diff)
merged from lp:~donkult/apt/sid
Diffstat (limited to 'apt-pkg/contrib/mmap.cc')
-rw-r--r--apt-pkg/contrib/mmap.cc70
1 files changed, 59 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;
}