]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/mmap.cc
b5c1320e62207553f070f593c8bea07eda7ebad1
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: mmap.cc,v 1.18 1999/08/28 01:49:07 jgg Exp $
4 /* ######################################################################
6 MMap Class - Provides 'real' mmap or a faked mmap using read().
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
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.
21 ##################################################################### */
23 // Include Files /*{{{*/
25 #pragma implementation "apt-pkg/mmap.h"
29 #include <apt-pkg/mmap.h>
30 #include <apt-pkg/error.h>
38 #undef _POSIX_SYNCHRONIZED_IO
40 // MMap::MMap - Constructor /*{{{*/
41 // ---------------------------------------------------------------------
43 MMap::MMap(FileFd
&F
,unsigned long Flags
) : Flags(Flags
), iSize(0),
46 if ((Flags
& NoImmMap
) != NoImmMap
)
50 // MMap::MMap - Constructor /*{{{*/
51 // ---------------------------------------------------------------------
53 MMap::MMap(unsigned long Flags
) : Flags(Flags
), iSize(0),
58 // MMap::~MMap - Destructor /*{{{*/
59 // ---------------------------------------------------------------------
66 // MMap::Map - Perform the mapping /*{{{*/
67 // ---------------------------------------------------------------------
69 bool MMap::Map(FileFd
&Fd
)
73 // Set the permissions.
76 if ((Flags
& ReadOnly
) != ReadOnly
)
78 if ((Flags
& Public
) != Public
)
82 return _error
->Error("Can't mmap an empty file");
85 Base
= mmap(0,iSize
,Prot
,Map
,Fd
.Fd(),0);
86 if (Base
== (void *)-1)
87 return _error
->Errno("mmap","Couldn't make mmap of %u bytes",iSize
);
92 // MMap::Close - Close the map /*{{{*/
93 // ---------------------------------------------------------------------
95 bool MMap::Close(bool DoSync
)
97 if ((Flags
& UnMapped
) == UnMapped
|| Base
== 0 || iSize
== 0)
103 if (munmap((char *)Base
,iSize
) != 0)
104 _error
->Warning("Unable to munmap");
110 // MMap::Sync - Syncronize the map with the disk /*{{{*/
111 // ---------------------------------------------------------------------
112 /* This is done in syncronous mode - the docs indicate that this will
113 not return till all IO is complete */
116 if ((Flags
& UnMapped
) == UnMapped
)
119 #ifdef _POSIX_SYNCHRONIZED_IO
120 if ((Flags
& ReadOnly
) != ReadOnly
)
121 if (msync((char *)Base
,iSize
,MS_SYNC
) != 0)
122 return _error
->Error("msync","Unable to write mmap");
127 // MMap::Sync - Syncronize a section of the file to disk /*{{{*/
128 // ---------------------------------------------------------------------
130 bool MMap::Sync(unsigned long Start
,unsigned long Stop
)
132 if ((Flags
& UnMapped
) == UnMapped
)
135 #ifdef _POSIX_SYNCHRONIZED_IO
136 unsigned long PSize
= sysconf(_SC_PAGESIZE
);
137 if ((Flags
& ReadOnly
) != ReadOnly
)
138 if (msync((char *)Base
+(int)(Start
/PSize
)*PSize
,Stop
- Start
,MS_SYNC
) != 0)
139 return _error
->Error("msync","Unable to write mmap");
145 // DynamicMMap::DynamicMMap - Constructor /*{{{*/
146 // ---------------------------------------------------------------------
148 DynamicMMap::DynamicMMap(FileFd
&F
,unsigned long Flags
,unsigned long WorkSpace
) :
149 MMap(F
,Flags
| NoImmMap
), Fd(&F
), WorkSpace(WorkSpace
)
151 if (_error
->PendingError() == true)
154 unsigned long EndOfFile
= Fd
->Size();
157 Fd
->Write(&C
,sizeof(C
));
162 // DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/
163 // ---------------------------------------------------------------------
164 /* This is just a fancy malloc really.. */
165 DynamicMMap::DynamicMMap(unsigned long Flags
,unsigned long WorkSpace
) :
166 MMap(Flags
| NoImmMap
| UnMapped
), Fd(0), WorkSpace(WorkSpace
)
168 if (_error
->PendingError() == true)
171 Base
= new unsigned char[WorkSpace
];
175 // DynamicMMap::~DynamicMMap - Destructor /*{{{*/
176 // ---------------------------------------------------------------------
177 /* We truncate the file to the size of the memory data set */
178 DynamicMMap::~DynamicMMap()
182 delete [] (unsigned char *)Base
;
186 unsigned long EndOfFile
= iSize
;
190 ftruncate(Fd
->Fd(),EndOfFile
);
194 // DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/
195 // ---------------------------------------------------------------------
196 /* This allocates a block of memory aligned to the given size */
197 unsigned long DynamicMMap::RawAllocate(unsigned long Size
,unsigned long Aln
)
199 unsigned long Result
= iSize
;
201 Result
+= Aln
- (iSize%Aln
);
203 iSize
= Result
+ Size
;
205 // Just in case error check
206 if (Result
+ Size
> WorkSpace
)
208 _error
->Error("Dynamic MMap ran out of room");
215 // DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/
216 // ---------------------------------------------------------------------
217 /* This allocates an Item of size ItemSize so that it is aligned to its
219 unsigned long DynamicMMap::Allocate(unsigned long ItemSize
)
221 // Look for a matching pool entry
224 for (I
= Pools
; I
!= Pools
+ PoolCount
; I
++)
226 if (I
->ItemSize
== 0)
228 if (I
->ItemSize
== ItemSize
)
232 // No pool is allocated, use an unallocated one
233 if (I
== Pools
+ PoolCount
)
235 // Woops, we ran out, the calling code should allocate more.
238 _error
->Error("Ran out of allocation pools");
243 I
->ItemSize
= ItemSize
;
247 // Out of space, allocate some more
250 I
->Count
= 20*1024/ItemSize
;
251 I
->Start
= RawAllocate(I
->Count
*ItemSize
,ItemSize
);
255 unsigned long Result
= I
->Start
;
256 I
->Start
+= ItemSize
;
257 return Result
/ItemSize
;
260 // DynamicMMap::WriteString - Write a string to the file /*{{{*/
261 // ---------------------------------------------------------------------
262 /* Strings are not aligned to anything */
263 unsigned long DynamicMMap::WriteString(const char *String
,
266 unsigned long Result
= iSize
;
267 // Just in case error check
268 if (Result
+ Len
> WorkSpace
)
270 _error
->Error("Dynamic MMap ran out of room");
274 if (Len
== (unsigned long)-1)
275 Len
= strlen(String
);
277 memcpy((char *)Base
+ Result
,String
,Len
);
278 ((char *)Base
)[Result
+ Len
] = 0;