5 #include<apt-pkg/init.h>
6 #include<apt-pkg/error.h>
7 #include<apt-pkg/cdromutl.h>
8 #include<apt-pkg/strutl.h>
9 #include<apt-pkg/cdrom.h>
10 #include<apt-pkg/aptconfiguration.h>
11 #include<apt-pkg/configuration.h>
12 #include<apt-pkg/fileutl.h>
24 #include "indexcopy.h"
30 // FindPackages - Find the package files on the CDROM /*{{{*/
31 // ---------------------------------------------------------------------
32 /* We look over the cdrom for package files. This is a recursive
33 search that short circuits when it his a package file in the dir.
34 This speeds it up greatly as the majority of the size is in the
36 bool pkgCdrom::FindPackages(string CD
,
38 vector
<string
> &SList
,
39 vector
<string
> &SigList
,
40 vector
<string
> &TransList
,
41 string
&InfoDir
, pkgCdromStatus
*log
,
44 static ino_t Inodes
[9];
47 // if we have a look we "pulse" now
54 if (CD
[CD
.length()-1] != '/')
57 if (chdir(CD
.c_str()) != 0)
58 return _error
->Errno("chdir","Unable to change to %s",CD
.c_str());
60 // Look for a .disk subdirectory
61 if (DirectoryExists(".disk") == true)
63 if (InfoDir
.empty() == true)
64 InfoDir
= CD
+ ".disk/";
67 // Don't look into directories that have been marked to ingore.
68 if (RealFileExists(".aptignr") == true)
71 /* Check _first_ for a signature file as apt-cdrom assumes that all files
72 under a Packages/Source file are in control of that file and stops
75 if (RealFileExists("Release.gpg") == true || RealFileExists("InRelease") == true)
77 SigList
.push_back(CD
);
80 /* Aha! We found some package files. We assume that everything under
81 this dir is controlled by those package files so we don't look down
83 std::vector
<APT::Configuration::Compressor
> const compressor
= APT::Configuration::getCompressors();
84 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressor
.begin();
85 c
!= compressor
.end(); ++c
)
87 if (RealFileExists(std::string("Packages").append(c
->Extension
).c_str()) == false)
90 if (_config
->FindB("Debug::aptcdrom",false) == true)
91 std::clog
<< "Found Packages in " << CD
<< std::endl
;
94 // Continue down if thorough is given
95 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
99 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressor
.begin();
100 c
!= compressor
.end(); ++c
)
102 if (RealFileExists(std::string("Sources").append(c
->Extension
).c_str()) == false)
105 if (_config
->FindB("Debug::aptcdrom",false) == true)
106 std::clog
<< "Found Sources in " << CD
<< std::endl
;
109 // Continue down if thorough is given
110 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
115 // see if we find translation indices
116 if (DirectoryExists("i18n") == true)
119 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
121 if(strncmp(Dir
->d_name
, "Translation-", strlen("Translation-")) != 0)
123 string file
= Dir
->d_name
;
124 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressor
.begin();
125 c
!= compressor
.end(); ++c
)
127 string fileext
= flExtension(file
);
130 else if (fileext
.empty() == false)
131 fileext
= "." + fileext
;
133 if (c
->Extension
== fileext
)
135 if (_config
->FindB("Debug::aptcdrom",false) == true)
136 std::clog
<< "Found translation " << Dir
->d_name
<< " in " << CD
<< "i18n/" << std::endl
;
137 file
.erase(file
.size() - fileext
.size());
138 TransList
.push_back(CD
+ "i18n/" + file
);
148 return _error
->Errno("opendir","Unable to read %s",CD
.c_str());
150 // Run over the directory
151 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
154 if (strcmp(Dir
->d_name
,".") == 0 ||
155 strcmp(Dir
->d_name
,"..") == 0 ||
156 //strcmp(Dir->d_name,"source") == 0 ||
157 strcmp(Dir
->d_name
,".disk") == 0 ||
158 strcmp(Dir
->d_name
,"experimental") == 0 ||
159 strcmp(Dir
->d_name
,"binary-all") == 0 ||
160 strcmp(Dir
->d_name
,"debian-installer") == 0)
163 // See if the name is a sub directory
165 if (stat(Dir
->d_name
,&Buf
) != 0)
168 if (S_ISDIR(Buf
.st_mode
) == 0)
172 for (I
= 0; I
!= Depth
; I
++)
173 if (Inodes
[I
] == Buf
.st_ino
)
178 // Store the inodes weve seen
179 Inodes
[Depth
] = Buf
.st_ino
;
182 if (FindPackages(CD
+ Dir
->d_name
,List
,SList
,SigList
,TransList
,InfoDir
,log
,Depth
+1) == false)
185 if (chdir(CD
.c_str()) != 0)
187 _error
->Errno("chdir","Unable to change to %s", CD
.c_str());
195 return !_error
->PendingError();
198 // Score - We compute a 'score' for a path /*{{{*/
199 // ---------------------------------------------------------------------
200 /* Paths are scored based on how close they come to what I consider
201 normal. That is ones that have 'dist' 'stable' 'testing' will score
202 higher than ones without. */
203 int pkgCdrom::Score(string Path
)
206 if (Path
.find("stable/") != string::npos
)
208 if (Path
.find("/binary-") != string::npos
)
210 if (Path
.find("testing/") != string::npos
)
212 if (Path
.find("unstable/") != string::npos
)
214 if (Path
.find("/dists/") != string::npos
)
216 if (Path
.find("/main/") != string::npos
)
218 if (Path
.find("/contrib/") != string::npos
)
220 if (Path
.find("/non-free/") != string::npos
)
222 if (Path
.find("/non-US/") != string::npos
)
224 if (Path
.find("/source/") != string::npos
)
226 if (Path
.find("/debian/") != string::npos
)
229 // check for symlinks in the patch leading to the actual file
230 // a symlink gets a big penalty
232 string statPath
= flNotFile(Path
);
233 string cdromPath
= _config
->FindDir("Acquire::cdrom::mount");
234 while(statPath
!= cdromPath
&& statPath
!= "./") {
235 statPath
.resize(statPath
.size()-1); // remove the trailing '/'
236 if (lstat(statPath
.c_str(),&Buf
) == 0) {
237 if(S_ISLNK(Buf
.st_mode
)) {
242 statPath
= flNotFile(statPath
); // descent
248 // DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/
249 // ---------------------------------------------------------------------
250 /* Here we drop everything that is not this machines arch */
251 bool pkgCdrom::DropBinaryArch(vector
<string
> &List
)
254 for (unsigned int I
= 0; I
< List
.size(); I
++)
256 const char *Str
= List
[I
].c_str();
257 const char *Start
, *End
;
258 if ((Start
= strstr(Str
,"/binary-")) == 0)
261 // Between Start and End is the architecture
263 if ((End
= strstr(Start
,"/")) != 0 && Start
!= End
&&
264 APT::Configuration::checkArchitecture(string(Start
, End
)) == true)
265 continue; // okay, architecture is accepted
267 // not accepted -> Erase it
268 List
.erase(List
.begin() + I
);
269 --I
; // the next entry is at the same index after the erase
275 // DropTranslation - Dump unwanted Translation-<lang> files /*{{{*/
276 // ---------------------------------------------------------------------
277 /* Here we drop everything that is not configured in Acquire::Languages */
278 bool pkgCdrom::DropTranslation(vector
<string
> &List
)
280 for (unsigned int I
= 0; I
< List
.size(); I
++)
283 if ((Start
= strstr(List
[I
].c_str(), "/Translation-")) == NULL
)
285 Start
+= strlen("/Translation-");
287 if (APT::Configuration::checkLanguage(Start
, true) == true)
290 // not accepted -> Erase it
291 List
.erase(List
.begin() + I
);
292 --I
; // the next entry is at the same index after the erase
298 // DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
299 // ---------------------------------------------------------------------
300 /* Here we go and stat every file that we found and strip dup inodes. */
301 bool pkgCdrom::DropRepeats(vector
<string
> &List
,const char *Name
)
303 bool couldFindAllFiles
= true;
304 // Get a list of all the inodes
305 ino_t
*Inodes
= new ino_t
[List
.size()];
306 for (unsigned int I
= 0; I
!= List
.size(); ++I
)
311 std::vector
<APT::Configuration::Compressor
> const compressor
= APT::Configuration::getCompressors();
312 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressor
.begin();
313 c
!= compressor
.end(); ++c
)
315 std::string filename
= std::string(List
[I
]).append(Name
).append(c
->Extension
);
316 if (stat(filename
.c_str(), &Buf
) != 0)
318 Inodes
[I
] = Buf
.st_ino
;
325 _error
->Errno("stat","Failed to stat %s%s",List
[I
].c_str(), Name
);
326 couldFindAllFiles
= false;
332 for (unsigned int I
= 0; I
!= List
.size(); I
++)
336 for (unsigned int J
= I
+1; J
< List
.size(); J
++)
339 if (Inodes
[J
] == 0 || Inodes
[J
] != Inodes
[I
])
342 // We score the two paths.. and erase one
343 int ScoreA
= Score(List
[I
]);
344 int ScoreB
= Score(List
[J
]);
356 // Wipe erased entries
357 for (unsigned int I
= 0; I
< List
.size();)
359 if (List
[I
].empty() == false)
362 List
.erase(List
.begin()+I
);
365 return couldFindAllFiles
;
368 // ReduceSourceList - Takes the path list and reduces it /*{{{*/
369 // ---------------------------------------------------------------------
370 /* This takes the list of source list expressed entires and collects
371 similar ones to form a single entry for each dist */
372 void pkgCdrom::ReduceSourcelist(string CD
,vector
<string
> &List
)
374 sort(List
.begin(),List
.end());
376 // Collect similar entries
377 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
380 string::size_type Space
= (*I
).find(' ');
381 if (Space
== string::npos
)
383 string::size_type SSpace
= (*I
).find(' ',Space
+ 1);
384 if (SSpace
== string::npos
)
387 string Word1
= string(*I
,Space
,SSpace
-Space
);
388 string Prefix
= string(*I
,0,Space
);
389 string Component
= string(*I
,SSpace
);
390 for (vector
<string
>::iterator J
= List
.begin(); J
!= I
; ++J
)
393 string::size_type Space2
= (*J
).find(' ');
394 if (Space2
== string::npos
)
396 string::size_type SSpace2
= (*J
).find(' ',Space2
+ 1);
397 if (SSpace2
== string::npos
)
400 if (string(*J
,0,Space2
) != Prefix
)
402 if (string(*J
,Space2
,SSpace2
-Space2
) != Word1
)
405 string Component2
= string(*J
, SSpace2
) + " ";
406 if (Component2
.find(Component
+ " ") == std::string::npos
)
412 // Wipe erased entries
413 for (unsigned int I
= 0; I
< List
.size();)
415 if (List
[I
].empty() == false)
418 List
.erase(List
.begin()+I
);
422 // WriteDatabase - Write the CDROM Database file /*{{{*/
423 // ---------------------------------------------------------------------
424 /* We rewrite the configuration class associated with the cdrom database. */
425 bool pkgCdrom::WriteDatabase(Configuration
&Cnf
)
427 string DFile
= _config
->FindFile("Dir::State::cdroms");
428 string NewFile
= DFile
+ ".new";
430 unlink(NewFile
.c_str());
431 ofstream
Out(NewFile
.c_str());
433 return _error
->Errno("ofstream::ofstream",
434 "Failed to open %s.new",DFile
.c_str());
436 /* Write out all of the configuration directives by walking the
437 configuration tree */
438 Cnf
.Dump(Out
, NULL
, "%f \"%v\";\n", false);
442 if (FileExists(DFile
) == true)
443 rename(DFile
.c_str(), string(DFile
+ '~').c_str());
444 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
445 return _error
->Errno("rename","Failed to rename %s.new to %s",
446 DFile
.c_str(),DFile
.c_str());
451 // WriteSourceList - Write an updated sourcelist /*{{{*/
452 // ---------------------------------------------------------------------
453 /* This reads the old source list and copies it into the new one. It
454 appends the new CDROM entires just after the first block of comments.
455 This places them first in the file. It also removes any old entries
456 that were the same. */
457 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
459 if (List
.empty() == true)
462 string File
= _config
->FindFile("Dir::Etc::sourcelist");
464 // Open the stream for reading
465 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
468 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
470 string NewFile
= File
+ ".new";
471 unlink(NewFile
.c_str());
472 ofstream
Out(NewFile
.c_str());
474 return _error
->Errno("ofstream::ofstream",
475 "Failed to open %s.new",File
.c_str());
477 // Create a short uri without the path
478 string ShortURI
= "cdrom:[" + Name
+ "]/";
479 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
490 while (F
.eof() == false)
492 F
.getline(Buffer
,sizeof(Buffer
));
494 if (F
.fail() && !F
.eof())
495 return _error
->Error(_("Line %u too long in source list %s."),
496 CurLine
,File
.c_str());
497 _strtabexpand(Buffer
,sizeof(Buffer
));
501 if (Buffer
[0] == '#' || Buffer
[0] == 0)
503 Out
<< Buffer
<< endl
;
509 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
511 string::size_type Space
= (*I
).find(' ');
512 if (Space
== string::npos
)
513 return _error
->Error("Internal error");
514 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
515 " " << string(*I
,Space
+1) << endl
;
523 const char *C
= Buffer
;
524 if (ParseQuoteWord(C
,cType
) == false ||
525 ParseQuoteWord(C
,URI
) == false)
527 Out
<< Buffer
<< endl
;
531 // Emit lines like this one
532 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
533 string(URI
,0,ShortURI
.length()) != ShortURI2
))
535 Out
<< Buffer
<< endl
;
540 // Just in case the file was empty
543 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
545 string::size_type Space
= (*I
).find(' ');
546 if (Space
== string::npos
)
547 return _error
->Error("Internal error");
549 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
550 " " << string(*I
,Space
+1) << endl
;
556 rename(File
.c_str(),string(File
+ '~').c_str());
557 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
558 return _error
->Errno("rename","Failed to rename %s.new to %s",
559 File
.c_str(),File
.c_str());
564 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
569 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
571 CDROM
= SafeGetCWD() + '/' + CDROM
;
576 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
578 log
->Update(msg
.str());
581 // Unmount the CD and get the user to put in the one they want
582 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
585 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
590 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
591 if(!log
->ChangeCdrom()) {
597 // Mount the new CDROM
599 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
601 if (MountCdrom(CDROM
) == false)
602 return _error
->Error("Failed to mount the cdrom.");
605 // Hash the CD to get an ID
607 log
->Update(_("Identifying.. "));
610 if (IdentCdrom(CDROM
,ident
) == false)
619 ioprintf(msg
, "[%s]\n",ident
.c_str());
620 log
->Update(msg
.str());
624 Configuration Database
;
625 string DFile
= _config
->FindFile("Dir::State::cdroms");
626 if (FileExists(DFile
) == true)
628 if (ReadConfigFile(Database
,DFile
) == false)
629 return _error
->Error("Unable to read the cdrom database %s",
635 ioprintf(msg
, _("Stored label: %s\n"),
636 Database
.Find("CD::"+ident
).c_str());
637 log
->Update(msg
.str());
640 // Unmount and finish
641 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
644 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
651 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
656 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
658 CDROM
= SafeGetCWD() + '/' + CDROM
;
662 log
->SetTotal(STEP_LAST
);
664 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
665 log
->Update(msg
.str(), STEP_PREPARE
);
669 Configuration Database
;
670 string DFile
= _config
->FindFile("Dir::State::cdroms");
671 if (FileExists(DFile
) == true)
673 if (ReadConfigFile(Database
,DFile
) == false)
674 return _error
->Error("Unable to read the cdrom database %s",
678 // Unmount the CD and get the user to put in the one they want
679 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
682 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
687 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
688 if(!log
->ChangeCdrom()) {
694 // Mount the new CDROM
696 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
698 if (MountCdrom(CDROM
) == false)
699 return _error
->Error("Failed to mount the cdrom.");
702 // Hash the CD to get an ID
704 log
->Update(_("Identifying.. "), STEP_IDENT
);
706 if (IdentCdrom(CDROM
,ID
) == false)
714 log
->Update("["+ID
+"]\n");
715 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
718 // Get the CD structure
720 vector
<string
> SourceList
;
721 vector
<string
> SigList
;
722 vector
<string
> TransList
;
723 string StartDir
= SafeGetCWD();
725 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
732 if (chdir(StartDir
.c_str()) != 0)
733 return _error
->Errno("chdir","Unable to change to %s", StartDir
.c_str());
735 if (_config
->FindB("Debug::aptcdrom",false) == true)
737 cout
<< "I found (binary):" << endl
;
738 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
740 cout
<< "I found (source):" << endl
;
741 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
743 cout
<< "I found (Signatures):" << endl
;
744 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
748 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
751 DropBinaryArch(List
);
752 DropRepeats(List
,"Packages");
753 DropRepeats(SourceList
,"Sources");
754 // FIXME: We ignore stat() errors here as we usually have only one of those in use
755 // This has little potencial to drop 'valid' stat() errors as we know that one of these
756 // files need to exist, but it would be better if we would check it here
757 _error
->PushToStack();
758 DropRepeats(SigList
,"Release.gpg");
759 DropRepeats(SigList
,"InRelease");
760 _error
->RevertToStack();
761 DropRepeats(TransList
,"");
762 if (_config
->FindB("APT::CDROM::DropTranslation", true) == true)
763 DropTranslation(TransList
);
766 ioprintf(msg
, _("Found %zu package indexes, %zu source indexes, "
767 "%zu translation indexes and %zu signatures\n"),
768 List
.size(), SourceList
.size(), TransList
.size(),
770 log
->Update(msg
.str(), STEP_SCAN
);
773 if (List
.empty() == true && SourceList
.empty() == true)
775 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
777 return _error
->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc or the wrong architecture?"));
780 // Check if the CD is in the database
782 if (Database
.Exists("CD::" + ID
) == false ||
783 _config
->FindB("APT::CDROM::Rename",false) == true)
785 // Try to use the CDs label if at all possible
786 if (InfoDir
.empty() == false &&
787 FileExists(InfoDir
+ "/info") == true)
789 ifstream
F(string(InfoDir
+ "/info").c_str());
793 if (Name
.empty() == false)
795 // Escape special characters
796 string::iterator J
= Name
.begin();
797 for (; J
!= Name
.end(); ++J
)
798 if (*J
== '"' || *J
== ']' || *J
== '[')
804 ioprintf(msg
, _("Found label '%s'\n"), Name
.c_str());
805 log
->Update(msg
.str());
807 Database
.Set("CD::" + ID
+ "::Label",Name
);
811 if (_config
->FindB("APT::CDROM::Rename",false) == true ||
812 Name
.empty() == true)
816 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
818 return _error
->Error("No disc name found and no way to ask for it");
822 if(!log
->AskCdromName(Name
)) {
826 cout
<< "Name: '" << Name
<< "'" << endl
;
828 if (Name
.empty() == false &&
829 Name
.find('"') == string::npos
&&
830 Name
.find('[') == string::npos
&&
831 Name
.find(']') == string::npos
)
833 log
->Update(_("That is not a valid name, try again.\n"));
838 Name
= Database
.Find("CD::" + ID
);
840 // Escape special characters
841 string::iterator J
= Name
.begin();
842 for (; J
!= Name
.end(); ++J
)
843 if (*J
== '"' || *J
== ']' || *J
== '[')
846 Database
.Set("CD::" + ID
,Name
);
850 ioprintf(msg
, _("This disc is called: \n'%s'\n"), Name
.c_str());
851 log
->Update(msg
.str());
852 log
->Update(_("Copying package lists..."), STEP_COPY
);
855 // check for existence and possibly create state directory for copying
856 string
const listDir
= _config
->FindDir("Dir::State::lists");
857 string
const partialListDir
= listDir
+ "partial/";
858 if (CreateAPTDirectoryIfNeeded(_config
->FindDir("Dir::State"), partialListDir
) == false &&
859 CreateAPTDirectoryIfNeeded(listDir
, partialListDir
) == false)
860 return _error
->Errno("cdrom", _("List directory %spartial is missing."), listDir
.c_str());
862 // take care of the signatures and copy them if they are ok
863 // (we do this before PackageCopy as it modifies "List" and "SourceList")
864 SigVerify SignVerify
;
865 SignVerify
.CopyAndVerify(CDROM
, Name
, SigList
, List
, SourceList
);
867 // Copy the package files to the state directory
870 TranslationsCopy TransCopy
;
871 if (Copy
.CopyPackages(CDROM
,Name
,List
, log
) == false ||
872 SrcCopy
.CopyPackages(CDROM
,Name
,SourceList
, log
) == false ||
873 TransCopy
.CopyTranslations(CDROM
,Name
,TransList
, log
) == false)
876 // reduce the List so that it takes less space in sources.list
877 ReduceSourcelist(CDROM
,List
);
878 ReduceSourcelist(CDROM
,SourceList
);
880 // Write the database and sourcelist
881 if (_config
->FindB("APT::cdrom::NoAct",false) == false)
883 if (WriteDatabase(Database
) == false)
887 log
->Update(_("Writing new source list\n"), STEP_WRITE
);
888 if (WriteSourceList(Name
,List
,false) == false ||
889 WriteSourceList(Name
,SourceList
,true) == false)
893 // Print the sourcelist entries
895 log
->Update(_("Source list entries for this disc are:\n"));
897 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
899 string::size_type Space
= (*I
).find(' ');
900 if (Space
== string::npos
)
902 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
904 return _error
->Error("Internal error");
910 msg
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
911 " " << string(*I
,Space
+1) << endl
;
912 log
->Update(msg
.str());
916 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
918 string::size_type Space
= (*I
).find(' ');
919 if (Space
== string::npos
)
921 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
923 return _error
->Error("Internal error");
928 msg
<< "deb-src cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
929 " " << string(*I
,Space
+1) << endl
;
930 log
->Update(msg
.str());
934 // Unmount and finish
935 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
937 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
944 pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/
945 : libudev_handle(NULL
)
952 pkgUdevCdromDevices::Dlopen() /*{{{*/
955 if(libudev_handle
!= NULL
)
958 // see if we can get libudev
959 void *h
= ::dlopen("libudev.so.0", RTLD_LAZY
);
963 // get the pointers to the udev structs
965 udev_new
= (udev
* (*)(void)) dlsym(h
, "udev_new");
966 udev_enumerate_add_match_property
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_property");
967 udev_enumerate_add_match_sysattr
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_sysattr");
968 udev_enumerate_scan_devices
= (int (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_scan_devices");
969 udev_enumerate_get_list_entry
= (udev_list_entry
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_list_entry");
970 udev_device_new_from_syspath
= (udev_device
* (*)(udev
*, const char*))dlsym(h
, "udev_device_new_from_syspath");
971 udev_enumerate_get_udev
= (udev
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_udev");
972 udev_list_entry_get_name
= (const char* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_name");
973 udev_device_get_devnode
= (const char* (*)(udev_device
*))dlsym(h
, "udev_device_get_devnode");
974 udev_enumerate_new
= (udev_enumerate
* (*)(udev
*))dlsym(h
, "udev_enumerate_new");
975 udev_list_entry_get_next
= (udev_list_entry
* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_next");
976 udev_device_get_property_value
= (const char* (*)(udev_device
*, const char *))dlsym(h
, "udev_device_get_property_value");
982 // convenience interface, this will just call ScanForRemovable
984 pkgUdevCdromDevices::Scan()
986 bool CdromOnly
= _config
->FindB("APT::cdrom::CdromOnly", true);
987 return ScanForRemovable(CdromOnly
);
992 pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly
)
994 vector
<CdromDevice
> cdrom_devices
;
995 struct udev_enumerate
*enumerate
;
996 struct udev_list_entry
*l
, *devices
;
997 struct udev
*udev_ctx
;
999 if(libudev_handle
== NULL
)
1000 return cdrom_devices
;
1002 udev_ctx
= udev_new();
1003 enumerate
= udev_enumerate_new (udev_ctx
);
1005 udev_enumerate_add_match_property(enumerate
, "ID_CDROM", "1");
1007 udev_enumerate_add_match_sysattr(enumerate
, "removable", "1");
1010 udev_enumerate_scan_devices (enumerate
);
1011 devices
= udev_enumerate_get_list_entry (enumerate
);
1012 for (l
= devices
; l
!= NULL
; l
= udev_list_entry_get_next (l
))
1015 struct udev_device
*udevice
;
1016 udevice
= udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate
), udev_list_entry_get_name (l
));
1017 if (udevice
== NULL
)
1019 const char* devnode
= udev_device_get_devnode(udevice
);
1021 // try fstab_dir first
1023 const char* mp
= udev_device_get_property_value(udevice
, "FSTAB_DIR");
1025 mountpath
= string(mp
);
1027 mountpath
= FindMountPointForDevice(devnode
);
1029 // fill in the struct
1030 cdrom
.DeviceName
= string(devnode
);
1031 if (mountpath
!= "") {
1032 cdrom
.MountPath
= mountpath
;
1033 string s
= string(mountpath
);
1034 cdrom
.Mounted
= IsMounted(s
);
1036 cdrom
.Mounted
= false;
1037 cdrom
.MountPath
= "";
1039 cdrom_devices
.push_back(cdrom
);
1041 return cdrom_devices
;
1045 pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/
1047 if (libudev_handle
!= NULL
)
1048 dlclose(libudev_handle
);