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