~mvo/apt/dep8

« back to all changes in this revision

Viewing changes to ftparchive/cachedb.cc

  • Committer: Arch Librarian
  • Date: 2004-09-20 16:56:32 UTC
  • Revision ID: Arch-1:apt@arch.ubuntu.com%apt--MAIN--0--patch-614
Join with aliencode
Author: jgg
Date: 2001-02-20 07:03:16 GMT
Join with aliencode

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- mode: cpp; mode: fold -*-
 
2
// Description                                                          /*{{{*/
 
3
// $Id: cachedb.cc,v 1.2 2001/02/20 07:03:18 jgg Exp $
 
4
/* ######################################################################
 
5
 
 
6
   CacheDB
 
7
   
 
8
   Simple uniform interface to a cache database.
 
9
   
 
10
   ##################################################################### */
 
11
                                                                        /*}}}*/
 
12
// Include Files                                                        /*{{{*/
 
13
#ifdef __GNUG__
 
14
#pragma implementation "cachedb.h"
 
15
#endif
 
16
 
 
17
#include "cachedb.h"
 
18
 
 
19
#include <apt-pkg/error.h>
 
20
#include <apt-pkg/md5.h>
 
21
#include <apt-pkg/strutl.h>
 
22
#include <apt-pkg/configuration.h>
 
23
    
 
24
#include <netinet/in.h>       // htonl, etc
 
25
                                                                        /*}}}*/
 
26
 
 
27
// CacheDB::ReadyDB - Ready the DB2                                     /*{{{*/
 
28
// ---------------------------------------------------------------------
 
29
/* This opens the DB2 file for caching package information */
 
30
bool CacheDB::ReadyDB(string DB)
 
31
{
 
32
   ReadOnly = _config->FindB("APT::FTPArchive::ReadOnlyDB",false);
 
33
   
 
34
   // Close the old DB
 
35
   if (Dbp != 0) 
 
36
      Dbp->close(Dbp,0);
 
37
   
 
38
   /* Check if the DB was disabled while running and deal with a 
 
39
      corrupted DB */
 
40
   if (DBFailed() == true)
 
41
   {
 
42
      _error->Warning("DB was corrupted, file renamed to %s.old",DBFile.c_str());
 
43
      rename(DBFile.c_str(),(DBFile+".old").c_str());
 
44
   }
 
45
   
 
46
   DBLoaded = false;
 
47
   Dbp = 0;
 
48
   DBFile = string();
 
49
   
 
50
   if (DB.empty())
 
51
      return true;
 
52
   
 
53
   if ((errno = db_open(DB.c_str(),DB_HASH,
 
54
                        (ReadOnly?DB_RDONLY:DB_CREATE),
 
55
                        0644,0,0,&Dbp)) != 0)
 
56
   {
 
57
      Dbp = 0;
 
58
      return _error->Errno("db_open","Unable to open DB2 file %s",DB.c_str());
 
59
   }
 
60
   
 
61
   DBFile = DB;
 
62
   DBLoaded = true;
 
63
   return true;
 
64
}
 
65
                                                                        /*}}}*/
 
66
// CacheDB::SetFile - Select a file to be working with                  /*{{{*/
 
67
// ---------------------------------------------------------------------
 
68
/* All future actions will be performed against this file */
 
69
bool CacheDB::SetFile(string FileName,struct stat St,FileFd *Fd)
 
70
{
 
71
   delete DebFile;
 
72
   DebFile = 0;
 
73
   this->FileName = FileName;
 
74
   this->Fd = Fd;
 
75
   this->FileStat = St;
 
76
   FileStat = St;   
 
77
   memset(&CurStat,0,sizeof(CurStat));
 
78
   
 
79
   Stats.Bytes += St.st_size;
 
80
   Stats.Packages++;
 
81
   
 
82
   if (DBLoaded == false)
 
83
      return true;
 
84
 
 
85
   InitQuery("st");
 
86
   
 
87
   // Ensure alignment of the returned structure
 
88
   Data.data = &CurStat;
 
89
   Data.ulen = sizeof(CurStat);
 
90
   Data.flags = DB_DBT_USERMEM;
 
91
   // Lookup the stat info and confirm the file is unchanged
 
92
   if (Get() == true)
 
93
   {
 
94
      if (CurStat.st_mtime != htonl(St.st_mtime))
 
95
      {
 
96
         CurStat.st_mtime = htonl(St.st_mtime);
 
97
         CurStat.Flags = 0;
 
98
         _error->Warning("File date has changed %s",FileName.c_str());
 
99
      }      
 
100
   }      
 
101
   else
 
102
   {
 
103
      CurStat.st_mtime = htonl(St.st_mtime);
 
104
      CurStat.Flags = 0;
 
105
   }   
 
106
   CurStat.Flags = ntohl(CurStat.Flags);
 
107
   OldStat = CurStat;
 
108
   return true;
 
109
}
 
110
                                                                        /*}}}*/
 
111
// CacheDB::LoadControl - Load Control information                      /*{{{*/
 
112
// ---------------------------------------------------------------------
 
113
/* */
 
114
bool CacheDB::LoadControl()
 
115
{
 
116
   // Try to read the control information out of the DB.
 
117
   if ((CurStat.Flags & FlControl) == FlControl)
 
118
   {
 
119
      // Lookup the control information
 
120
      InitQuery("cl");
 
121
      if (Get() == true && Control.TakeControl(Data.data,Data.size) == true)
 
122
            return true;
 
123
      CurStat.Flags &= ~FlControl;
 
124
   }
 
125
   
 
126
   // Create a deb instance to read the archive
 
127
   if (DebFile == 0)
 
128
   {
 
129
      DebFile = new debDebFile(*Fd);
 
130
      if (_error->PendingError() == true)
 
131
         return false;
 
132
   }
 
133
   
 
134
   Stats.Misses++;
 
135
   if (Control.Read(*DebFile) == false)
 
136
      return false;
 
137
 
 
138
   if (Control.Control == 0)
 
139
      return _error->Error("Archive has no control record");
 
140
   
 
141
   // Write back the control information
 
142
   InitQuery("cl");
 
143
   if (Put(Control.Control,Control.Length) == true)
 
144
      CurStat.Flags |= FlControl;
 
145
   return true;
 
146
}
 
147
                                                                        /*}}}*/
 
148
// CacheDB::LoadContents - Load the File Listing                        /*{{{*/
 
149
// ---------------------------------------------------------------------
 
150
/* */
 
151
bool CacheDB::LoadContents(bool GenOnly)
 
152
{
 
153
   // Try to read the control information out of the DB.
 
154
   if ((CurStat.Flags & FlContents) == FlContents)
 
155
   {
 
156
      if (GenOnly == true)
 
157
         return true;
 
158
      
 
159
      // Lookup the contents information
 
160
      InitQuery("cn");
 
161
      if (Get() == true)
 
162
      {
 
163
         if (Contents.TakeContents(Data.data,Data.size) == true)
 
164
            return true;
 
165
      }
 
166
      
 
167
      CurStat.Flags &= ~FlContents;
 
168
   }
 
169
   
 
170
   // Create a deb instance to read the archive
 
171
   if (DebFile == 0)
 
172
   {
 
173
      DebFile = new debDebFile(*Fd);
 
174
      if (_error->PendingError() == true)
 
175
         return false;
 
176
   }
 
177
 
 
178
   if (Contents.Read(*DebFile) == false)
 
179
      return false;         
 
180
   
 
181
   // Write back the control information
 
182
   InitQuery("cn");
 
183
   if (Put(Contents.Data,Contents.CurSize) == true)
 
184
      CurStat.Flags |= FlContents;
 
185
   return true;
 
186
}
 
187
                                                                        /*}}}*/
 
188
// CacheDB::GetMD5 - Get the MD5 hash                                   /*{{{*/
 
189
// ---------------------------------------------------------------------
 
190
/* */
 
191
bool CacheDB::GetMD5(string &MD5Res,bool GenOnly)
 
192
{
 
193
   // Try to read the control information out of the DB.
 
194
   if ((CurStat.Flags & FlMD5) == FlMD5)
 
195
   {
 
196
      if (GenOnly == true)
 
197
         return true;
 
198
      
 
199
      InitQuery("m5");
 
200
      if (Get() == true)
 
201
      {
 
202
         MD5Res = string((char *)Data.data,Data.size);
 
203
         return true;
 
204
      }
 
205
      CurStat.Flags &= ~FlMD5;
 
206
   }
 
207
   
 
208
   Stats.MD5Bytes += FileStat.st_size;
 
209
         
 
210
   MD5Summation MD5;
 
211
   if (Fd->Seek(0) == false || MD5.AddFD(Fd->Fd(),FileStat.st_size) == false)
 
212
      return false;
 
213
   
 
214
   MD5Res = MD5.Result();
 
215
   InitQuery("m5");
 
216
   if (Put(MD5Res.begin(),MD5Res.length()) == true)
 
217
      CurStat.Flags |= FlMD5;
 
218
   return true;
 
219
}
 
220
                                                                        /*}}}*/
 
221
// CacheDB::Finish - Write back the cache structure                     /*{{{*/
 
222
// ---------------------------------------------------------------------
 
223
/* */
 
224
bool CacheDB::Finish()
 
225
{
 
226
   // Optimize away some writes.
 
227
   if (CurStat.Flags == OldStat.Flags &&
 
228
       CurStat.st_mtime == OldStat.st_mtime)
 
229
      return true;
 
230
   
 
231
   // Write the stat information
 
232
   CurStat.Flags = htonl(CurStat.Flags);
 
233
   InitQuery("st");
 
234
   Put(&CurStat,sizeof(CurStat));
 
235
   CurStat.Flags = ntohl(CurStat.Flags);
 
236
   return true;
 
237
}
 
238
                                                                        /*}}}*/
 
239
// CacheDB::Clean - Clean the Database                                  /*{{{*/
 
240
// ---------------------------------------------------------------------
 
241
/* Tidy the database by removing files that no longer exist at all. */
 
242
bool CacheDB::Clean()
 
243
{
 
244
   if (DBLoaded == false)
 
245
      return true;
 
246
 
 
247
   /* I'm not sure what VERSION_MINOR should be here.. 2.4.14 certainly
 
248
      needs the lower one and 2.7.7 needs the upper.. */
 
249
#if DB_VERSION_MAJOR >= 2 && DB_VERSION_MINOR >= 7
 
250
   DBC *Cursor;
 
251
   if ((errno = Dbp->cursor(Dbp,0,&Cursor,0)) != 0)
 
252
      return _error->Error("Unable to get a cursor");
 
253
#else
 
254
   DBC *Cursor;
 
255
   if ((errno = Dbp->cursor(Dbp,0,&Cursor)) != 0)
 
256
      return _error->Error("Unable to get a cursor");
 
257
#endif
 
258
   
 
259
   DBT Key;
 
260
   DBT Data;
 
261
   memset(&Key,0,sizeof(Key));
 
262
   memset(&Data,0,sizeof(Data));
 
263
   while ((errno = Cursor->c_get(Cursor,&Key,&Data,DB_NEXT)) == 0)
 
264
   {
 
265
      const char *Colon = (char *)Key.data;
 
266
      for (; Colon != (char *)Key.data+Key.size && *Colon != ':'; Colon++);
 
267
      if ((char *)Key.data+Key.size - Colon > 2)
 
268
      {
 
269
         if (stringcmp((char *)Key.data,Colon,"st") == 0 ||
 
270
             stringcmp((char *)Key.data,Colon,"cn") == 0 ||
 
271
             stringcmp((char *)Key.data,Colon,"m5") == 0 ||
 
272
             stringcmp((char *)Key.data,Colon,"cl") == 0)
 
273
         {
 
274
            if (FileExists(string(Colon+1,(const char *)Key.data+Key.size)) == true)
 
275
                continue;            
 
276
         }
 
277
      }
 
278
      
 
279
      Cursor->c_del(Cursor,0);
 
280
   }
 
281
 
 
282
   return true;
 
283
}
 
284
                                                                        /*}}}*/