~jr/ubuntu/oneiric/apt/bzr-get-rename

« back to all changes in this revision

Viewing changes to apt-pkg/cdrom.cc

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2005-03-07 20:08:33 UTC
  • Revision ID: james.westby@ubuntu.com-20050307200833-0lxdgg2cb4oculdv
Tags: 0.6.35
* Merge apt--mvo--0 (incorporates 0.6.34ubuntu1):
  - Implement MaxSize and MaxAge in apt.cron.daily, to prevent the cache
    from growing too large (Ubuntu #6761)
  - some comments about the pkgAcqMetaSig::Custom600Headers() added
  - use gpg --with-colons
  - commented the ftp no_proxy unseting in methods/ftp.cc
  - added support for "Acquire::gpgv::options" in methods/gpgv.cc
* Merge bubulle@debian.org--2005/apt--main--0
  - Make capitalization more consistent
  - Un-fuzzy translations resulting from capitalization changes
  - Italian translation update

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 */
 
3
 
 
4
#ifdef __GNUG__
 
5
#pragma implementation "apt-pkg/cdrom.h"
 
6
#endif
 
7
#include<apt-pkg/init.h>
 
8
#include<apt-pkg/error.h>
 
9
#include<apt-pkg/cdromutl.h>
 
10
#include<apt-pkg/strutl.h>
 
11
#include<apt-pkg/cdrom.h>
 
12
#include<sstream>
 
13
#include<fstream>
 
14
#include<config.h>
 
15
#include<apti18n.h>
 
16
#include <sys/stat.h>
 
17
#include <fcntl.h>
 
18
#include <dirent.h>
 
19
#include <unistd.h>
 
20
#include <stdio.h>
 
21
 
 
22
 
 
23
#include "indexcopy.h"
 
24
 
 
25
using namespace std;
 
26
 
 
27
// FindPackages - Find the package files on the CDROM                   /*{{{*/
 
28
// ---------------------------------------------------------------------
 
29
/* We look over the cdrom for package files. This is a recursive
 
30
   search that short circuits when it his a package file in the dir.
 
31
   This speeds it up greatly as the majority of the size is in the
 
32
   binary-* sub dirs. */
 
33
bool pkgCdrom::FindPackages(string CD,vector<string> &List,
 
34
                            vector<string> &SList, vector<string> &SigList,
 
35
                            string &InfoDir, pkgCdromStatus *log,
 
36
                            unsigned int Depth)
 
37
{
 
38
   static ino_t Inodes[9];
 
39
 
 
40
   // if we have a look we "pulse" now
 
41
   if(log)
 
42
      log->Update();
 
43
 
 
44
   if (Depth >= 7)
 
45
      return true;
 
46
 
 
47
   if (CD[CD.length()-1] != '/')
 
48
      CD += '/';   
 
49
 
 
50
   if (chdir(CD.c_str()) != 0)
 
51
      return _error->Errno("chdir","Unable to change to %s",CD.c_str());
 
52
 
 
53
   // Look for a .disk subdirectory
 
54
   struct stat Buf;
 
55
   if (stat(".disk",&Buf) == 0)
 
56
   {
 
57
      if (InfoDir.empty() == true)
 
58
         InfoDir = CD + ".disk/";
 
59
   }
 
60
 
 
61
   // Don't look into directories that have been marked to ingore.
 
62
   if (stat(".aptignr",&Buf) == 0)
 
63
      return true;
 
64
 
 
65
 
 
66
   /* Check _first_ for a signature file as apt-cdrom assumes that all files
 
67
      under a Packages/Source file are in control of that file and stops 
 
68
      the scanning
 
69
   */
 
70
   if (stat("Release.gpg",&Buf) == 0)
 
71
   {
 
72
      SigList.push_back(CD);
 
73
   }
 
74
   /* Aha! We found some package files. We assume that everything under 
 
75
      this dir is controlled by those package files so we don't look down
 
76
      anymore */
 
77
   if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0)
 
78
   {
 
79
      List.push_back(CD);
 
80
      
 
81
      // Continue down if thorough is given
 
82
      if (_config->FindB("APT::CDROM::Thorough",false) == false)
 
83
         return true;
 
84
   }
 
85
   if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0)
 
86
   {
 
87
      SList.push_back(CD);
 
88
      
 
89
      // Continue down if thorough is given
 
90
      if (_config->FindB("APT::CDROM::Thorough",false) == false)
 
91
         return true;
 
92
   }
 
93
   
 
94
   DIR *D = opendir(".");
 
95
   if (D == 0)
 
96
      return _error->Errno("opendir","Unable to read %s",CD.c_str());
 
97
   
 
98
   // Run over the directory
 
99
   for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
 
100
   {
 
101
      // Skip some files..
 
102
      if (strcmp(Dir->d_name,".") == 0 ||
 
103
          strcmp(Dir->d_name,"..") == 0 ||
 
104
          //strcmp(Dir->d_name,"source") == 0 ||
 
105
          strcmp(Dir->d_name,".disk") == 0 ||
 
106
          strcmp(Dir->d_name,"experimental") == 0 ||
 
107
          strcmp(Dir->d_name,"binary-all") == 0 ||
 
108
          strcmp(Dir->d_name,"debian-installer") == 0)
 
109
         continue;
 
110
 
 
111
      // See if the name is a sub directory
 
112
      struct stat Buf;
 
113
      if (stat(Dir->d_name,&Buf) != 0)
 
114
         continue;      
 
115
      
 
116
      if (S_ISDIR(Buf.st_mode) == 0)
 
117
         continue;
 
118
      
 
119
      unsigned int I;
 
120
      for (I = 0; I != Depth; I++)
 
121
         if (Inodes[I] == Buf.st_ino)
 
122
            break;
 
123
      if (I != Depth)
 
124
         continue;
 
125
      
 
126
      // Store the inodes weve seen
 
127
      Inodes[Depth] = Buf.st_ino;
 
128
 
 
129
      // Descend
 
130
      if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false)
 
131
         break;
 
132
 
 
133
      if (chdir(CD.c_str()) != 0)
 
134
         return _error->Errno("chdir","Unable to change to %s",CD.c_str());
 
135
   };
 
136
 
 
137
   closedir(D);
 
138
   
 
139
   return !_error->PendingError();
 
140
}
 
141
 
 
142
// Score - We compute a 'score' for a path                              /*{{{*/
 
143
// ---------------------------------------------------------------------
 
144
/* Paths are scored based on how close they come to what I consider
 
145
   normal. That is ones that have 'dist' 'stable' 'testing' will score
 
146
   higher than ones without. */
 
147
int pkgCdrom::Score(string Path)
 
148
{
 
149
   int Res = 0;
 
150
   if (Path.find("stable/") != string::npos)
 
151
      Res += 29;
 
152
   if (Path.find("/binary-") != string::npos)
 
153
      Res += 20;
 
154
   if (Path.find("testing/") != string::npos)
 
155
      Res += 28;
 
156
   if (Path.find("unstable/") != string::npos)
 
157
      Res += 27;
 
158
   if (Path.find("/dists/") != string::npos)
 
159
      Res += 40;
 
160
   if (Path.find("/main/") != string::npos)
 
161
      Res += 20;
 
162
   if (Path.find("/contrib/") != string::npos)
 
163
      Res += 20;
 
164
   if (Path.find("/non-free/") != string::npos)
 
165
      Res += 20;
 
166
   if (Path.find("/non-US/") != string::npos)
 
167
      Res += 20;
 
168
   if (Path.find("/source/") != string::npos)
 
169
      Res += 10;
 
170
   if (Path.find("/debian/") != string::npos)
 
171
      Res -= 10;
 
172
 
 
173
   // check for symlinks in the patch leading to the actual file
 
174
   // a symlink gets a big penalty
 
175
   struct stat Buf;
 
176
   string statPath = flNotFile(Path);
 
177
   string cdromPath = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
 
178
   while(statPath != cdromPath && statPath != "./") {
 
179
      statPath.resize(statPath.size()-1);  // remove the trailing '/'
 
180
      if (lstat(statPath.c_str(),&Buf) == 0) {
 
181
        if(S_ISLNK(Buf.st_mode)) {
 
182
           Res -= 60;
 
183
           break;
 
184
        }
 
185
      }
 
186
      statPath = flNotFile(statPath); // descent
 
187
   }
 
188
 
 
189
   return Res;
 
190
}
 
191
 
 
192
                                                                        /*}}}*/
 
193
// DropBinaryArch - Dump dirs with a string like /binary-<foo>/         /*{{{*/
 
194
// ---------------------------------------------------------------------
 
195
/* Here we drop everything that is not this machines arch */
 
196
bool pkgCdrom::DropBinaryArch(vector<string> &List)
 
197
{
 
198
   char S[300];
 
199
   snprintf(S,sizeof(S),"/binary-%s/",
 
200
            _config->Find("Apt::Architecture").c_str());
 
201
   
 
202
   for (unsigned int I = 0; I < List.size(); I++)
 
203
   {
 
204
      const char *Str = List[I].c_str();
 
205
      
 
206
      const char *Res;
 
207
      if ((Res = strstr(Str,"/binary-")) == 0)
 
208
         continue;
 
209
 
 
210
      // Weird, remove it.
 
211
      if (strlen(Res) < strlen(S))
 
212
      {
 
213
         List.erase(List.begin() + I);
 
214
         I--;
 
215
         continue;
 
216
      }
 
217
          
 
218
      // See if it is our arch
 
219
      if (stringcmp(Res,Res + strlen(S),S) == 0)
 
220
         continue;
 
221
      
 
222
      // Erase it
 
223
      List.erase(List.begin() + I);
 
224
      I--;
 
225
   }
 
226
   
 
227
   return true;
 
228
}
 
229
 
 
230
 
 
231
// DropRepeats - Drop repeated files resulting from symlinks            /*{{{*/
 
232
// ---------------------------------------------------------------------
 
233
/* Here we go and stat every file that we found and strip dup inodes. */
 
234
bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
 
235
{
 
236
   // Get a list of all the inodes
 
237
   ino_t *Inodes = new ino_t[List.size()];
 
238
   for (unsigned int I = 0; I != List.size(); I++)
 
239
   {
 
240
      struct stat Buf;
 
241
      if (stat((List[I] + Name).c_str(),&Buf) != 0 &&
 
242
          stat((List[I] + Name + ".gz").c_str(),&Buf) != 0)
 
243
         _error->Errno("stat","Failed to stat %s%s",List[I].c_str(),
 
244
                       Name);
 
245
      Inodes[I] = Buf.st_ino;
 
246
   }
 
247
   
 
248
   if (_error->PendingError() == true)
 
249
      return false;
 
250
   
 
251
   // Look for dups
 
252
   for (unsigned int I = 0; I != List.size(); I++)
 
253
   {
 
254
      for (unsigned int J = I+1; J < List.size(); J++)
 
255
      {
 
256
         // No match
 
257
         if (Inodes[J] != Inodes[I])
 
258
            continue;
 
259
         
 
260
         // We score the two paths.. and erase one
 
261
         int ScoreA = Score(List[I]);
 
262
         int ScoreB = Score(List[J]);
 
263
         if (ScoreA < ScoreB)
 
264
         {
 
265
            List[I] = string();
 
266
            break;
 
267
         }
 
268
         
 
269
         List[J] = string();
 
270
      }
 
271
   }  
 
272
 
 
273
   // Wipe erased entries
 
274
   for (unsigned int I = 0; I < List.size();)
 
275
   {
 
276
      if (List[I].empty() == false)
 
277
         I++;
 
278
      else
 
279
         List.erase(List.begin()+I);
 
280
   }
 
281
   
 
282
   return true;
 
283
}
 
284
                                                                        /*}}}*/
 
285
 
 
286
// ReduceSourceList - Takes the path list and reduces it                /*{{{*/
 
287
// ---------------------------------------------------------------------
 
288
/* This takes the list of source list expressed entires and collects
 
289
   similar ones to form a single entry for each dist */
 
290
void pkgCdrom::ReduceSourcelist(string CD,vector<string> &List)
 
291
{
 
292
   sort(List.begin(),List.end());
 
293
   
 
294
   // Collect similar entries
 
295
   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
 
296
   {
 
297
      // Find a space..
 
298
      string::size_type Space = (*I).find(' ');
 
299
      if (Space == string::npos)
 
300
         continue;
 
301
      string::size_type SSpace = (*I).find(' ',Space + 1);
 
302
      if (SSpace == string::npos)
 
303
         continue;
 
304
 
 
305
      string Word1 = string(*I,Space,SSpace-Space);
 
306
      string Prefix = string(*I,0,Space);
 
307
      for (vector<string>::iterator J = List.begin(); J != I; J++)
 
308
      {
 
309
         // Find a space..
 
310
         string::size_type Space2 = (*J).find(' ');
 
311
         if (Space2 == string::npos)
 
312
            continue;
 
313
         string::size_type SSpace2 = (*J).find(' ',Space2 + 1);
 
314
         if (SSpace2 == string::npos)
 
315
            continue;
 
316
         
 
317
         if (string(*J,0,Space2) != Prefix)
 
318
            continue;
 
319
         if (string(*J,Space2,SSpace2-Space2) != Word1)
 
320
            continue;
 
321
         
 
322
         *J += string(*I,SSpace);
 
323
         *I = string();
 
324
      }
 
325
   }   
 
326
 
 
327
   // Wipe erased entries
 
328
   for (unsigned int I = 0; I < List.size();)
 
329
   {
 
330
      if (List[I].empty() == false)
 
331
         I++;
 
332
      else
 
333
         List.erase(List.begin()+I);
 
334
   }
 
335
}
 
336
                                                                        /*}}}*/
 
337
// WriteDatabase - Write the CDROM Database file                        /*{{{*/
 
338
// ---------------------------------------------------------------------
 
339
/* We rewrite the configuration class associated with the cdrom database. */
 
340
bool pkgCdrom::WriteDatabase(Configuration &Cnf)
 
341
{
 
342
   string DFile = _config->FindFile("Dir::State::cdroms");
 
343
   string NewFile = DFile + ".new";
 
344
   
 
345
   unlink(NewFile.c_str());
 
346
   ofstream Out(NewFile.c_str());
 
347
   if (!Out)
 
348
      return _error->Errno("ofstream::ofstream",
 
349
                           "Failed to open %s.new",DFile.c_str());
 
350
   
 
351
   /* Write out all of the configuration directives by walking the
 
352
      configuration tree */
 
353
   const Configuration::Item *Top = Cnf.Tree(0);
 
354
   for (; Top != 0;)
 
355
   {
 
356
      // Print the config entry
 
357
      if (Top->Value.empty() == false)
 
358
         Out <<  Top->FullTag() + " \"" << Top->Value << "\";" << endl;
 
359
      
 
360
      if (Top->Child != 0)
 
361
      {
 
362
         Top = Top->Child;
 
363
         continue;
 
364
      }
 
365
      
 
366
      while (Top != 0 && Top->Next == 0)
 
367
         Top = Top->Parent;
 
368
      if (Top != 0)
 
369
         Top = Top->Next;
 
370
   }   
 
371
 
 
372
   Out.close();
 
373
   
 
374
   rename(DFile.c_str(),string(DFile + '~').c_str());
 
375
   if (rename(NewFile.c_str(),DFile.c_str()) != 0)
 
376
      return _error->Errno("rename","Failed to rename %s.new to %s",
 
377
                           DFile.c_str(),DFile.c_str());
 
378
 
 
379
   return true;
 
380
}
 
381
                                                                        /*}}}*/
 
382
// WriteSourceList - Write an updated sourcelist                        /*{{{*/
 
383
// ---------------------------------------------------------------------
 
384
/* This reads the old source list and copies it into the new one. It 
 
385
   appends the new CDROM entires just after the first block of comments.
 
386
   This places them first in the file. It also removes any old entries
 
387
   that were the same. */
 
388
bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
 
389
{
 
390
   if (List.size() == 0)
 
391
      return true;
 
392
 
 
393
   string File = _config->FindFile("Dir::Etc::sourcelist");
 
394
 
 
395
   // Open the stream for reading
 
396
   ifstream F((FileExists(File)?File.c_str():"/dev/null"),
 
397
              ios::in );
 
398
   if (!F != 0)
 
399
      return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
 
400
 
 
401
   string NewFile = File + ".new";
 
402
   unlink(NewFile.c_str());
 
403
   ofstream Out(NewFile.c_str());
 
404
   if (!Out)
 
405
      return _error->Errno("ofstream::ofstream",
 
406
                           "Failed to open %s.new",File.c_str());
 
407
 
 
408
   // Create a short uri without the path
 
409
   string ShortURI = "cdrom:[" + Name + "]/";   
 
410
   string ShortURI2 = "cdrom:" + Name + "/";     // For Compatibility
 
411
 
 
412
   string Type;
 
413
   if (Source == true)
 
414
      Type = "deb-src";
 
415
   else
 
416
      Type = "deb";
 
417
   
 
418
   char Buffer[300];
 
419
   int CurLine = 0;
 
420
   bool First = true;
 
421
   while (F.eof() == false)
 
422
   {      
 
423
      F.getline(Buffer,sizeof(Buffer));
 
424
      CurLine++;
 
425
      _strtabexpand(Buffer,sizeof(Buffer));
 
426
      _strstrip(Buffer);
 
427
            
 
428
      // Comment or blank
 
429
      if (Buffer[0] == '#' || Buffer[0] == 0)
 
430
      {
 
431
         Out << Buffer << endl;
 
432
         continue;
 
433
      }
 
434
 
 
435
      if (First == true)
 
436
      {
 
437
         for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
 
438
         {
 
439
            string::size_type Space = (*I).find(' ');
 
440
            if (Space == string::npos)
 
441
               return _error->Error("Internal error");
 
442
            Out << Type << " cdrom:[" << Name << "]/" << string(*I,0,Space) <<
 
443
               " " << string(*I,Space+1) << endl;
 
444
         }
 
445
      }
 
446
      First = false;
 
447
      
 
448
      // Grok it
 
449
      string cType;
 
450
      string URI;
 
451
      const char *C = Buffer;
 
452
      if (ParseQuoteWord(C,cType) == false ||
 
453
          ParseQuoteWord(C,URI) == false)
 
454
      {
 
455
         Out << Buffer << endl;
 
456
         continue;
 
457
      }
 
458
 
 
459
      // Emit lines like this one
 
460
      if (cType != Type || (string(URI,0,ShortURI.length()) != ShortURI &&
 
461
          string(URI,0,ShortURI.length()) != ShortURI2))
 
462
      {
 
463
         Out << Buffer << endl;
 
464
         continue;
 
465
      }      
 
466
   }
 
467
   
 
468
   // Just in case the file was empty
 
469
   if (First == true)
 
470
   {
 
471
      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
 
472
      {
 
473
         string::size_type Space = (*I).find(' ');
 
474
         if (Space == string::npos)
 
475
            return _error->Error("Internal error");
 
476
         
 
477
         Out << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
 
478
            " " << string(*I,Space+1) << endl;
 
479
      }
 
480
   }
 
481
   
 
482
   Out.close();
 
483
 
 
484
   rename(File.c_str(),string(File + '~').c_str());
 
485
   if (rename(NewFile.c_str(),File.c_str()) != 0)
 
486
      return _error->Errno("rename","Failed to rename %s.new to %s",
 
487
                           File.c_str(),File.c_str());
 
488
   
 
489
   return true;
 
490
}
 
491
 
 
492
 
 
493
bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
 
494
{
 
495
   stringstream msg;
 
496
 
 
497
   // Startup
 
498
   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
 
499
   if (CDROM[0] == '.')
 
500
      CDROM= SafeGetCWD() + '/' + CDROM;
 
501
 
 
502
   if(log) {
 
503
      msg.str("");
 
504
      ioprintf(msg, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
 
505
                      CDROM.c_str());
 
506
      log->Update(msg.str());
 
507
   }
 
508
   if (MountCdrom(CDROM) == false)
 
509
      return _error->Error("Failed to mount the cdrom.");
 
510
 
 
511
   // Hash the CD to get an ID
 
512
   if(log) 
 
513
      log->Update(_("Identifying.. "));
 
514
   
 
515
 
 
516
   if (IdentCdrom(CDROM,ident) == false)
 
517
   {
 
518
      ident = "";
 
519
      return false;
 
520
   }
 
521
 
 
522
   msg.str("");
 
523
   ioprintf(msg, "[%s]\n",ident.c_str());
 
524
   log->Update(msg.str());
 
525
 
 
526
 
 
527
   // Read the database
 
528
   Configuration Database;
 
529
   string DFile = _config->FindFile("Dir::State::cdroms");
 
530
   if (FileExists(DFile) == true)
 
531
   {
 
532
      if (ReadConfigFile(Database,DFile) == false)
 
533
         return _error->Error("Unable to read the cdrom database %s",
 
534
                              DFile.c_str());
 
535
   }
 
536
   if(log) {
 
537
      msg.str("");
 
538
      ioprintf(msg, _("Stored label: %s \n"),
 
539
               Database.Find("CD::"+ident).c_str());
 
540
      log->Update(msg.str());
 
541
   }
 
542
   return true;
 
543
}
 
544
 
 
545
 
 
546
bool pkgCdrom::Add(pkgCdromStatus *log)
 
547
{
 
548
   stringstream msg;
 
549
 
 
550
   // Startup
 
551
   string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
 
552
   if (CDROM[0] == '.')
 
553
      CDROM= SafeGetCWD() + '/' + CDROM;
 
554
   
 
555
   if(log) {
 
556
      log->SetTotal(STEP_LAST);
 
557
      msg.str("");
 
558
      ioprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str());
 
559
      log->Update(msg.str(), STEP_PREPARE);
 
560
   }
 
561
 
 
562
   // Read the database
 
563
   Configuration Database;
 
564
   string DFile = _config->FindFile("Dir::State::cdroms");
 
565
   if (FileExists(DFile) == true)
 
566
   {
 
567
      if (ReadConfigFile(Database,DFile) == false)
 
568
         return _error->Error("Unable to read the cdrom database %s",
 
569
                              DFile.c_str());
 
570
   }
 
571
   
 
572
   // Unmount the CD and get the user to put in the one they want
 
573
   if (_config->FindB("APT::CDROM::NoMount",false) == false)
 
574
   {
 
575
      if(log)
 
576
         log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT);
 
577
      UnmountCdrom(CDROM);
 
578
 
 
579
      if(log) {
 
580
         log->Update(_("Waiting for disc...\n"), STEP_WAIT);
 
581
         if(!log->ChangeCdrom()) {
 
582
            // user aborted
 
583
            return false; 
 
584
         }
 
585
      }
 
586
 
 
587
      // Mount the new CDROM
 
588
      log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT);
 
589
      if (MountCdrom(CDROM) == false)
 
590
         return _error->Error("Failed to mount the cdrom.");
 
591
   }
 
592
   
 
593
   // Hash the CD to get an ID
 
594
   if(log)
 
595
      log->Update(_("Identifying.. "), STEP_IDENT);
 
596
   string ID;
 
597
   if (IdentCdrom(CDROM,ID) == false)
 
598
   {
 
599
      log->Update("\n");
 
600
      return false;
 
601
   }
 
602
   if(log) 
 
603
      log->Update("["+ID+"]\n");
 
604
 
 
605
   if(log) 
 
606
      log->Update(_("Scanning disc for index files..\n"),STEP_SCAN);
 
607
   
 
608
   // Get the CD structure
 
609
   vector<string> List;
 
610
   vector<string> SourceList;
 
611
   vector<string> SigList;
 
612
   string StartDir = SafeGetCWD();
 
613
   string InfoDir;
 
614
   if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false)
 
615
   {
 
616
      log->Update("\n");
 
617
      return false;
 
618
   }
 
619
 
 
620
   chdir(StartDir.c_str());
 
621
 
 
622
   if (_config->FindB("Debug::aptcdrom",false) == true)
 
623
   {
 
624
      cout << "I found (binary):" << endl;
 
625
      for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
 
626
         cout << *I << endl;
 
627
      cout << "I found (source):" << endl;
 
628
      for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
 
629
         cout << *I << endl;
 
630
      cout << "I found (Signatures):" << endl;
 
631
      for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); I++)
 
632
         cout << *I << endl;
 
633
   }   
 
634
 
 
635
   //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
 
636
 
 
637
   // Fix up the list
 
638
   DropBinaryArch(List);
 
639
   DropRepeats(List,"Packages");
 
640
   DropRepeats(SourceList,"Sources");
 
641
   DropRepeats(SigList,"Release.gpg");
 
642
   if(log) {
 
643
      msg.str("");
 
644
      ioprintf(msg, _("Found %i package indexes, %i source indexes and "
 
645
                      "%i signatures\n"), 
 
646
               List.size(), SourceList.size(), SigList.size());
 
647
      log->Update(msg.str(), STEP_SCAN);
 
648
   }
 
649
 
 
650
   if (List.size() == 0 && SourceList.size() == 0)
 
651
      return _error->Error("Unable to locate any package files, perhaps this is not a Debian Disc");
 
652
 
 
653
   // Check if the CD is in the database
 
654
   string Name;
 
655
   if (Database.Exists("CD::" + ID) == false ||
 
656
       _config->FindB("APT::CDROM::Rename",false) == true)
 
657
   {
 
658
      // Try to use the CDs label if at all possible
 
659
      if (InfoDir.empty() == false &&
 
660
          FileExists(InfoDir + "/info") == true)
 
661
      {
 
662
         ifstream F(string(InfoDir + "/info").c_str());
 
663
         if (!F == 0)
 
664
            getline(F,Name);
 
665
 
 
666
         if (Name.empty() == false)
 
667
         {
 
668
            // Escape special characters
 
669
            string::iterator J = Name.begin();
 
670
            for (; J != Name.end(); J++)
 
671
               if (*J == '"' || *J == ']' || *J == '[')
 
672
                  *J = '_';
 
673
            
 
674
            if(log) {
 
675
               msg.str("");
 
676
               ioprintf(msg, "Found label '%s'\n", Name.c_str());
 
677
               log->Update(msg.str());
 
678
            }
 
679
            Database.Set("CD::" + ID + "::Label",Name);
 
680
         }       
 
681
      }
 
682
      
 
683
      if (_config->FindB("APT::CDROM::Rename",false) == true ||
 
684
          Name.empty() == true)
 
685
      {
 
686
         if(!log) 
 
687
            return _error->Error("No disc name found and no way to ask for it");
 
688
 
 
689
         while(true) {
 
690
            if(!log->AskCdromName(Name)) {
 
691
               // user canceld
 
692
               return false; 
 
693
            }
 
694
            cout << "Name: '" << Name << "'" << endl;
 
695
 
 
696
            if (Name.empty() == false &&
 
697
                Name.find('"') == string::npos &&
 
698
                Name.find('[') == string::npos &&
 
699
                Name.find(']') == string::npos)
 
700
               break;
 
701
            log->Update(_("That is not a valid name, try again.\n"));
 
702
         }
 
703
      }      
 
704
   }
 
705
   else
 
706
      Name = Database.Find("CD::" + ID);
 
707
 
 
708
   // Escape special characters
 
709
   string::iterator J = Name.begin();
 
710
   for (; J != Name.end(); J++)
 
711
      if (*J == '"' || *J == ']' || *J == '[')
 
712
         *J = '_';
 
713
   
 
714
   Database.Set("CD::" + ID,Name);
 
715
   if(log) {
 
716
      msg.str("");
 
717
      ioprintf(msg, _("This disc is called: \n'%s'\n"), Name.c_str());
 
718
      log->Update(msg.str());
 
719
   }
 
720
 
 
721
   log->Update(_("Copying package lists..."), STEP_COPY);
 
722
   // take care of the signatures and copy them if they are ok
 
723
   // (we do this before PackageCopy as it modifies "List" and "SourceList")
 
724
   SigVerify SignVerify;
 
725
   SignVerify.CopyAndVerify(CDROM, Name, SigList, List, SourceList);
 
726
   
 
727
   // Copy the package files to the state directory
 
728
   PackageCopy Copy;
 
729
   SourceCopy SrcCopy;
 
730
   if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
 
731
       SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false)
 
732
      return false;
 
733
 
 
734
   // reduce the List so that it takes less space in sources.list
 
735
   ReduceSourcelist(CDROM,List);
 
736
   ReduceSourcelist(CDROM,SourceList);
 
737
 
 
738
   // Write the database and sourcelist
 
739
   if (_config->FindB("APT::cdrom::NoAct",false) == false)
 
740
   {
 
741
      if (WriteDatabase(Database) == false)
 
742
         return false;
 
743
      
 
744
      if(log) {
 
745
         log->Update(_("Writing new source list\n"), STEP_WRITE);
 
746
      }
 
747
      if (WriteSourceList(Name,List,false) == false ||
 
748
          WriteSourceList(Name,SourceList,true) == false)
 
749
         return false;
 
750
   }
 
751
 
 
752
   // Print the sourcelist entries
 
753
   if(log) 
 
754
      log->Update(_("Source list entries for this disc are:\n"));
 
755
 
 
756
   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
 
757
   {
 
758
      string::size_type Space = (*I).find(' ');
 
759
      if (Space == string::npos)
 
760
         return _error->Error("Internal error");
 
761
 
 
762
      if(log) {
 
763
         msg.str("");
 
764
         msg << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
 
765
            " " << string(*I,Space+1) << endl;
 
766
         log->Update(msg.str());
 
767
      }
 
768
   }
 
769
 
 
770
   for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
 
771
   {
 
772
      string::size_type Space = (*I).find(' ');
 
773
      if (Space == string::npos)
 
774
         return _error->Error("Internal error");
 
775
 
 
776
      if(log) {
 
777
         msg.str("");
 
778
         msg << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) << 
 
779
            " " << string(*I,Space+1) << endl;
 
780
         log->Update(msg.str());
 
781
      }
 
782
   }
 
783
 
 
784
   
 
785
 
 
786
   // Unmount and finish
 
787
   if (_config->FindB("APT::CDROM::NoMount",false) == false) {
 
788
      log->Update(_("Unmounting CD-ROM..."), STEP_LAST);
 
789
      UnmountCdrom(CDROM);
 
790
   }
 
791
 
 
792
   return true;
 
793
}