]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/mmap.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: mmap.cc,v 1.22 2001/05/27 05:19:30 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 #include <apt-pkg/mmap.h>
26 #include <apt-pkg/error.h>
36 // MMap::MMap - Constructor /*{{{*/
37 // ---------------------------------------------------------------------
39 MMap::MMap(FileFd
&F
,unsigned long Flags
) : Flags(Flags
), iSize(0),
42 if ((Flags
& NoImmMap
) != NoImmMap
)
46 // MMap::MMap - Constructor /*{{{*/
47 // ---------------------------------------------------------------------
49 MMap::MMap(unsigned long Flags
) : Flags(Flags
), iSize(0),
54 // MMap::~MMap - Destructor /*{{{*/
55 // ---------------------------------------------------------------------
62 // MMap::Map - Perform the mapping /*{{{*/
63 // ---------------------------------------------------------------------
65 bool MMap::Map(FileFd
&Fd
)
69 // Set the permissions.
72 if ((Flags
& ReadOnly
) != ReadOnly
)
74 if ((Flags
& Public
) != Public
)
78 return _error
->Error(_("Can't mmap an empty file"));
81 Base
= mmap(0,iSize
,Prot
,Map
,Fd
.Fd(),0);
82 if (Base
== (void *)-1)
83 return _error
->Errno("mmap",_("Couldn't make mmap of %lu bytes"),iSize
);
88 // MMap::Close - Close the map /*{{{*/
89 // ---------------------------------------------------------------------
91 bool MMap::Close(bool DoSync
)
93 if ((Flags
& UnMapped
) == UnMapped
|| Base
== 0 || iSize
== 0)
99 if (munmap((char *)Base
,iSize
) != 0)
100 _error
->Warning("Unable to munmap");
107 // MMap::Sync - Syncronize the map with the disk /*{{{*/
108 // ---------------------------------------------------------------------
109 /* This is done in syncronous mode - the docs indicate that this will
110 not return till all IO is complete */
113 if ((Flags
& UnMapped
) == UnMapped
)
116 #ifdef _POSIX_SYNCHRONIZED_IO
117 if ((Flags
& ReadOnly
) != ReadOnly
)
118 if (msync((char *)Base
,iSize
,MS_SYNC
) != 0)
119 return _error
->Errno("msync","Unable to write mmap");
124 // MMap::Sync - Syncronize a section of the file to disk /*{{{*/
125 // ---------------------------------------------------------------------
127 bool MMap::Sync(unsigned long Start
,unsigned long Stop
)
129 if ((Flags
& UnMapped
) == UnMapped
)
132 #ifdef _POSIX_SYNCHRONIZED_IO
133 unsigned long PSize
= sysconf(_SC_PAGESIZE
);
134 if ((Flags
& ReadOnly
) != ReadOnly
)
135 if (msync((char *)Base
+(int)(Start
/PSize
)*PSize
,Stop
- Start
,MS_SYNC
) != 0)
136 return _error
->Errno("msync","Unable to write mmap");
142 // DynamicMMap::DynamicMMap - Constructor /*{{{*/
143 // ---------------------------------------------------------------------
145 DynamicMMap::DynamicMMap(FileFd
&F
,unsigned long Flags
,unsigned long WorkSpace
) :
146 MMap(F
,Flags
| NoImmMap
), Fd(&F
), WorkSpace(WorkSpace
)
148 if (_error
->PendingError() == true)
151 unsigned long EndOfFile
= Fd
->Size();
152 if (EndOfFile
> WorkSpace
)
153 WorkSpace
= EndOfFile
;
154 else if(WorkSpace
> 0)
156 Fd
->Seek(WorkSpace
- 1);
158 Fd
->Write(&C
,sizeof(C
));
165 // DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/
166 // ---------------------------------------------------------------------
167 /* This is just a fancy malloc really.. */
168 DynamicMMap::DynamicMMap(unsigned long Flags
,unsigned long WorkSpace
) :
169 MMap(Flags
| NoImmMap
| UnMapped
), Fd(0), WorkSpace(WorkSpace
)
171 if (_error
->PendingError() == true)
174 Base
= new unsigned char[WorkSpace
];
175 memset(Base
,0,WorkSpace
);
179 // DynamicMMap::~DynamicMMap - Destructor /*{{{*/
180 // ---------------------------------------------------------------------
181 /* We truncate the file to the size of the memory data set */
182 DynamicMMap::~DynamicMMap()
186 delete [] (unsigned char *)Base
;
190 unsigned long EndOfFile
= iSize
;
193 ftruncate(Fd
->Fd(),EndOfFile
);
196 // DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/
197 // ---------------------------------------------------------------------
198 /* This allocates a block of memory aligned to the given size */
199 unsigned long DynamicMMap::RawAllocate(unsigned long Size
,unsigned long Aln
)
201 unsigned long Result
= iSize
;
203 Result
+= Aln
- (iSize%Aln
);
205 iSize
= Result
+ Size
;
207 // Just in case error check
208 if (Result
+ Size
> WorkSpace
)
210 _error
->Error("Dynamic MMap ran out of room");
217 // DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/
218 // ---------------------------------------------------------------------
219 /* This allocates an Item of size ItemSize so that it is aligned to its
221 unsigned long DynamicMMap::Allocate(unsigned long ItemSize
)
223 // Look for a matching pool entry
226 for (I
= Pools
; I
!= Pools
+ PoolCount
; I
++)
228 if (I
->ItemSize
== 0)
230 if (I
->ItemSize
== ItemSize
)
234 // No pool is allocated, use an unallocated one
235 if (I
== Pools
+ PoolCount
)
237 // Woops, we ran out, the calling code should allocate more.
240 _error
->Error("Ran out of allocation pools");
245 I
->ItemSize
= ItemSize
;
249 // Out of space, allocate some more
252 I
->Count
= 20*1024/ItemSize
;
253 I
->Start
= RawAllocate(I
->Count
*ItemSize
,ItemSize
);
257 unsigned long Result
= I
->Start
;
258 I
->Start
+= ItemSize
;
259 return Result
/ItemSize
;
262 // DynamicMMap::WriteString - Write a string to the file /*{{{*/
263 // ---------------------------------------------------------------------
264 /* Strings are not aligned to anything */
265 unsigned long DynamicMMap::WriteString(const char *String
,
268 unsigned long Result
= iSize
;
269 // Just in case error check
270 if (Result
+ Len
> WorkSpace
)
272 _error
->Error("Dynamic MMap ran out of room");
276 if (Len
== (unsigned long)-1)
277 Len
= strlen(String
);
279 memcpy((char *)Base
+ Result
,String
,Len
);
280 ((char *)Base
)[Result
+ Len
] = 0;