]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/mmap.cc
Res initialize glitch
[apt.git] / apt-pkg / contrib / mmap.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
0149949b 3// $Id: mmap.cc,v 1.3 1998/07/04 22:32:15 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
25#include <pkglib/mmap.h>
26#include <pkglib/error.h>
27
28#include <sys/mman.h>
29#include <sys/stat.h>
30#include <sys/user.h>
31#include <unistd.h>
32#include <fcntl.h>
33 /*}}}*/
34
35// MMap::MMap - Constructor /*{{{*/
36// ---------------------------------------------------------------------
37/* */
38MMap::MMap(File &F,unsigned long Flags) : Fd(F), Flags(Flags), iSize(0),
39 Base(0)
40{
41 if ((Flags & NoImmMap) != NoImmMap)
42 Map();
43}
44 /*}}}*/
45// MMap::~MMap - Destructor /*{{{*/
46// ---------------------------------------------------------------------
47/* */
48MMap::~MMap()
49{
50 Close(true);
51}
52 /*}}}*/
53// MMap::Map - Perform the mapping /*{{{*/
54// ---------------------------------------------------------------------
55/* */
56bool MMap::Map()
57{
58 iSize = Fd.Size();
59
60 // Set the permissions.
61 int Prot = PROT_READ;
62 int Map = MAP_SHARED;
63 if ((Flags & ReadOnly) != ReadOnly)
64 Prot |= PROT_WRITE;
65 if ((Flags & Public) != Public)
66 Map = MAP_PRIVATE;
67
68 // Map it.
69 Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0);
70 if (Base == (void *)-1)
71 return _error->Errno("mmap","Couldn't make mmap of %u bytes",iSize);
72
73 return true;
74}
75 /*}}}*/
76// MMap::Close - Close the map /*{{{*/
77// ---------------------------------------------------------------------
78/* */
79bool MMap::Close(bool DoClose)
80{
81 if (Fd.IsOpen() == false)
82 return true;
83
84 Sync();
85
86 if (munmap((char *)Base,iSize) != 0)
87 _error->Warning("Unable to munmap");
88
89 iSize = 0;
90 if (DoClose == true)
91 Fd.Close();
92 return true;
93}
94 /*}}}*/
95// MMap::Sync - Syncronize the map with the disk /*{{{*/
96// ---------------------------------------------------------------------
0149949b
AL
97/* This is done in syncronous mode - the docs indicate that this will
98 not return till all IO is complete */
578bfd0a
AL
99bool MMap::Sync()
100{
101 if ((Flags & ReadOnly) == ReadOnly)
102 if (msync((char *)Base,iSize,MS_SYNC) != 0)
103 return _error->Error("msync","Unable to write mmap");
104 return true;
105}
106 /*}}}*/
107// MMap::Sync - Syncronize a section of the file to disk /*{{{*/
108// ---------------------------------------------------------------------
109/* */
110bool MMap::Sync(unsigned long Start,unsigned long Stop)
111{
112 if ((Flags & ReadOnly) == ReadOnly)
113 if (msync((char *)Base+(int)(Start/PAGE_SIZE)*PAGE_SIZE,Stop - Start,MS_SYNC) != 0)
114 return _error->Error("msync","Unable to write mmap");
115 return true;
116}
117 /*}}}*/
118
119// DynamicMMap::DynamicMMap - Constructor /*{{{*/
120// ---------------------------------------------------------------------
121/* */
122DynamicMMap::DynamicMMap(File &F,unsigned long Flags,unsigned long WorkSpace) :
123 MMap(F,Flags | NoImmMap), WorkSpace(WorkSpace)
124{
125 unsigned long EndOfFile = Fd.Size();
126 Fd.Seek(WorkSpace);
127 char C = 0;
128 Fd.Write(&C,sizeof(C));
129 Map();
130 iSize = EndOfFile;
131}
132 /*}}}*/
133// DynamicMMap::~DynamicMMap - Destructor /*{{{*/
134// ---------------------------------------------------------------------
135/* We truncate the file to the size of the memory data set */
136DynamicMMap::~DynamicMMap()
137{
138 unsigned long EndOfFile = iSize;
139 Close(false);
140 ftruncate(Fd.Fd(),EndOfFile);
141 Fd.Close();
142}
143 /*}}}*/
144// DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/
145// ---------------------------------------------------------------------
f55a958f
AL
146/* This allocates a block of memory aligned to the given size */
147unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
578bfd0a
AL
148{
149 unsigned long Result = iSize;
f55a958f
AL
150 if (Aln != 0)
151 Result += Aln - (iSize%Aln);
152
153 iSize = Result + Size;
578bfd0a
AL
154
155 // Just in case error check
156 if (Result > WorkSpace)
157 {
158 _error->Error("Dynamic MMap ran out of room");
159 return 0;
160 }
578bfd0a
AL
161 return Result;
162}
163 /*}}}*/
164// DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/
165// ---------------------------------------------------------------------
166/* This allocates an Item of size ItemSize so that it is aligned to its
167 size in the file. */
168unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
169{
170 // Look for a matching pool entry
171 Pool *I;
172 Pool *Empty = 0;
173 for (I = Pools; I != Pools + PoolCount; I++)
174 {
175 if (I->ItemSize == 0)
176 Empty = I;
177 if (I->ItemSize == ItemSize)
178 break;
179 }
180
181 // No pool is allocated, use an unallocated one
182 if (I == Pools + PoolCount)
183 {
184 // Woops, we ran out, the calling code should allocate more.
185 if (Empty == 0)
186 {
187 _error->Error("Ran out of allocation pools");
188 return 0;
189 }
190
191 I = Empty;
192 I->ItemSize = ItemSize;
193 I->Count = 0;
194 }
195
196 // Out of space, allocate some more
197 if (I->Count == 0)
198 {
199 I->Count = 20*1024/ItemSize;
f55a958f 200 I->Start = RawAllocate(I->Count*ItemSize,ItemSize);
578bfd0a 201 }
f55a958f 202
578bfd0a
AL
203 I->Count--;
204 unsigned long Result = I->Start;
205 I->Start += ItemSize;
206 return Result/ItemSize;
207}
208 /*}}}*/
209// DynamicMMap::WriteString - Write a string to the file /*{{{*/
210// ---------------------------------------------------------------------
211/* Strings are not aligned to anything */
212unsigned long DynamicMMap::WriteString(const char *String,
213 unsigned long Len)
214{
215 unsigned long Result = iSize;
216 // Just in case error check
217 if (Result > WorkSpace)
218 {
219 _error->Error("Dynamic MMap ran out of room");
220 return 0;
221 }
222
223 if (Len == 0)
224 Len = strlen(String);
225 iSize += Len + 1;
226 memcpy((char *)Base + Result,String,Len);
227 ((char *)Base)[Result + Len] = 0;
228 return Result;
229}
230 /*}}}*/