]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/mmap.cc
* apt-pkg/deb/dpkgpm.cc:
[apt.git] / apt-pkg / contrib / mmap.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
0db4a45b 3// $Id: mmap.cc,v 1.22 2001/05/27 05:19:30 jgg Exp $
578bfd0a
AL
4/* ######################################################################
5
6 MMap Class - Provides 'real' mmap or a faked mmap using read().
7
8 MMap cover class.
9
10 Some broken versions of glibc2 (libc6) have a broken definition
11 of mmap that accepts a char * -- all other systems (and libc5) use
12 void *. We can't safely do anything here that would be portable, so
13 libc6 generates warnings -- which should be errors, g++ isn't properly
14 strict.
15
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.
20
21 ##################################################################### */
22 /*}}}*/
23// Include Files /*{{{*/
24#define _BSD_SOURCE
094a497d
AL
25#include <apt-pkg/mmap.h>
26#include <apt-pkg/error.h>
578bfd0a 27
b2e465d6
AL
28#include <apti18n.h>
29
578bfd0a
AL
30#include <sys/mman.h>
31#include <sys/stat.h>
578bfd0a
AL
32#include <unistd.h>
33#include <fcntl.h>
34 /*}}}*/
35
36// MMap::MMap - Constructor /*{{{*/
37// ---------------------------------------------------------------------
38/* */
2d11135a 39MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
578bfd0a
AL
40 Base(0)
41{
42 if ((Flags & NoImmMap) != NoImmMap)
2d11135a
AL
43 Map(F);
44}
45 /*}}}*/
46// MMap::MMap - Constructor /*{{{*/
47// ---------------------------------------------------------------------
48/* */
49MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0),
50 Base(0)
51{
578bfd0a
AL
52}
53 /*}}}*/
54// MMap::~MMap - Destructor /*{{{*/
55// ---------------------------------------------------------------------
56/* */
57MMap::~MMap()
58{
2d11135a 59 Close();
578bfd0a
AL
60}
61 /*}}}*/
62// MMap::Map - Perform the mapping /*{{{*/
63// ---------------------------------------------------------------------
64/* */
2d11135a 65bool MMap::Map(FileFd &Fd)
578bfd0a
AL
66{
67 iSize = Fd.Size();
68
69 // Set the permissions.
70 int Prot = PROT_READ;
71 int Map = MAP_SHARED;
72 if ((Flags & ReadOnly) != ReadOnly)
73 Prot |= PROT_WRITE;
74 if ((Flags & Public) != Public)
75 Map = MAP_PRIVATE;
76
b35d2f5f 77 if (iSize == 0)
b2e465d6 78 return _error->Error(_("Can't mmap an empty file"));
b35d2f5f 79
578bfd0a
AL
80 // Map it.
81 Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
82 if (Base == (void *)-1)
b2e465d6 83 return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"),iSize);
578bfd0a
AL
84
85 return true;
86}
87 /*}}}*/
88// MMap::Close - Close the map /*{{{*/
89// ---------------------------------------------------------------------
90/* */
2d11135a 91bool MMap::Close(bool DoSync)
578bfd0a 92{
2d11135a 93 if ((Flags & UnMapped) == UnMapped || Base == 0 || iSize == 0)
578bfd0a 94 return true;
2d11135a 95
1164783d
AL
96 if (DoSync == true)
97 Sync();
578bfd0a
AL
98
99 if (munmap((char *)Base,iSize) != 0)
100 _error->Warning("Unable to munmap");
101
102 iSize = 0;
b2e465d6 103 Base = 0;
578bfd0a
AL
104 return true;
105}
106 /*}}}*/
107// MMap::Sync - Syncronize the map with the disk /*{{{*/
108// ---------------------------------------------------------------------
0149949b
AL
109/* This is done in syncronous mode - the docs indicate that this will
110 not return till all IO is complete */
578bfd0a
AL
111bool MMap::Sync()
112{
2d11135a
AL
113 if ((Flags & UnMapped) == UnMapped)
114 return true;
115
de3c15ea 116#ifdef _POSIX_SYNCHRONIZED_IO
1164783d 117 if ((Flags & ReadOnly) != ReadOnly)
578bfd0a 118 if (msync((char *)Base,iSize,MS_SYNC) != 0)
4b1b89c5 119 return _error->Errno("msync","Unable to write mmap");
de3c15ea 120#endif
578bfd0a
AL
121 return true;
122}
123 /*}}}*/
124// MMap::Sync - Syncronize a section of the file to disk /*{{{*/
125// ---------------------------------------------------------------------
126/* */
127bool MMap::Sync(unsigned long Start,unsigned long Stop)
128{
2d11135a
AL
129 if ((Flags & UnMapped) == UnMapped)
130 return true;
131
35c22def
AL
132#ifdef _POSIX_SYNCHRONIZED_IO
133 unsigned long PSize = sysconf(_SC_PAGESIZE);
1164783d 134 if ((Flags & ReadOnly) != ReadOnly)
35c22def 135 if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) != 0)
4b1b89c5 136 return _error->Errno("msync","Unable to write mmap");
de3c15ea 137#endif
578bfd0a
AL
138 return true;
139}
140 /*}}}*/
141
142// DynamicMMap::DynamicMMap - Constructor /*{{{*/
143// ---------------------------------------------------------------------
144/* */
8e06abb2 145DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) :
2d11135a 146 MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace)
578bfd0a 147{
d38b7b3d
AL
148 if (_error->PendingError() == true)
149 return;
150
2d11135a 151 unsigned long EndOfFile = Fd->Size();
b2e465d6
AL
152 if (EndOfFile > WorkSpace)
153 WorkSpace = EndOfFile;
ea92d036 154 else if(WorkSpace > 0)
b2e465d6 155 {
ea92d036 156 Fd->Seek(WorkSpace - 1);
b2e465d6
AL
157 char C = 0;
158 Fd->Write(&C,sizeof(C));
159 }
160
2d11135a 161 Map(F);
578bfd0a
AL
162 iSize = EndOfFile;
163}
164 /*}}}*/
2d11135a
AL
165// DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/
166// ---------------------------------------------------------------------
167/* This is just a fancy malloc really.. */
168DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
169 MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
170{
171 if (_error->PendingError() == true)
172 return;
173
174 Base = new unsigned char[WorkSpace];
0db4a45b 175 memset(Base,0,WorkSpace);
2d11135a
AL
176 iSize = 0;
177}
178 /*}}}*/
578bfd0a
AL
179// DynamicMMap::~DynamicMMap - Destructor /*{{{*/
180// ---------------------------------------------------------------------
181/* We truncate the file to the size of the memory data set */
182DynamicMMap::~DynamicMMap()
183{
2d11135a
AL
184 if (Fd == 0)
185 {
186 delete [] (unsigned char *)Base;
187 return;
188 }
189
578bfd0a 190 unsigned long EndOfFile = iSize;
1164783d 191 iSize = WorkSpace;
2d11135a
AL
192 Close(false);
193 ftruncate(Fd->Fd(),EndOfFile);
578bfd0a
AL
194}
195 /*}}}*/
196// DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/
197// ---------------------------------------------------------------------
f55a958f
AL
198/* This allocates a block of memory aligned to the given size */
199unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
578bfd0a
AL
200{
201 unsigned long Result = iSize;
f55a958f
AL
202 if (Aln != 0)
203 Result += Aln - (iSize%Aln);
204
205 iSize = Result + Size;
578bfd0a
AL
206
207 // Just in case error check
e5eebd12 208 if (Result + Size > WorkSpace)
578bfd0a
AL
209 {
210 _error->Error("Dynamic MMap ran out of room");
211 return 0;
212 }
470773ca 213
578bfd0a
AL
214 return Result;
215}
216 /*}}}*/
217// DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/
218// ---------------------------------------------------------------------
219/* This allocates an Item of size ItemSize so that it is aligned to its
220 size in the file. */
221unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
222{
223 // Look for a matching pool entry
224 Pool *I;
225 Pool *Empty = 0;
226 for (I = Pools; I != Pools + PoolCount; I++)
227 {
228 if (I->ItemSize == 0)
229 Empty = I;
230 if (I->ItemSize == ItemSize)
231 break;
232 }
233
234 // No pool is allocated, use an unallocated one
235 if (I == Pools + PoolCount)
236 {
237 // Woops, we ran out, the calling code should allocate more.
238 if (Empty == 0)
239 {
240 _error->Error("Ran out of allocation pools");
241 return 0;
242 }
243
244 I = Empty;
245 I->ItemSize = ItemSize;
246 I->Count = 0;
247 }
248
249 // Out of space, allocate some more
250 if (I->Count == 0)
251 {
252 I->Count = 20*1024/ItemSize;
f55a958f 253 I->Start = RawAllocate(I->Count*ItemSize,ItemSize);
578bfd0a 254 }
f55a958f 255
578bfd0a
AL
256 I->Count--;
257 unsigned long Result = I->Start;
470773ca 258 I->Start += ItemSize;
578bfd0a
AL
259 return Result/ItemSize;
260}
261 /*}}}*/
262// DynamicMMap::WriteString - Write a string to the file /*{{{*/
263// ---------------------------------------------------------------------
264/* Strings are not aligned to anything */
265unsigned long DynamicMMap::WriteString(const char *String,
266 unsigned long Len)
267{
268 unsigned long Result = iSize;
269 // Just in case error check
470773ca 270 if (Result + Len > WorkSpace)
578bfd0a
AL
271 {
272 _error->Error("Dynamic MMap ran out of room");
273 return 0;
274 }
275
6e52073f 276 if (Len == (unsigned long)-1)
578bfd0a
AL
277 Len = strlen(String);
278 iSize += Len + 1;
279 memcpy((char *)Base + Result,String,Len);
280 ((char *)Base)[Result + Len] = 0;
281 return Result;
282}
283 /*}}}*/