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 // DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
276 // ---------------------------------------------------------------------
277 /* Here we go and stat every file that we found and strip dup inodes. */
278 bool pkgCdrom::DropRepeats(vector
<string
> &List
,const char *Name
)
280 bool couldFindAllFiles
= true;
281 // Get a list of all the inodes
282 ino_t
*Inodes
= new ino_t
[List
.size()];
283 for (unsigned int I
= 0; I
!= List
.size(); ++I
)
288 std::vector
<APT::Configuration::Compressor
> const compressor
= APT::Configuration::getCompressors();
289 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressor
.begin();
290 c
!= compressor
.end(); ++c
)
292 std::string filename
= std::string(List
[I
]).append(Name
).append(c
->Extension
);
293 if (stat(filename
.c_str(), &Buf
) != 0)
295 Inodes
[I
] = Buf
.st_ino
;
302 _error
->Errno("stat","Failed to stat %s%s",List
[I
].c_str(), Name
);
303 couldFindAllFiles
= false;
309 for (unsigned int I
= 0; I
!= List
.size(); I
++)
313 for (unsigned int J
= I
+1; J
< List
.size(); J
++)
316 if (Inodes
[J
] == 0 || Inodes
[J
] != Inodes
[I
])
319 // We score the two paths.. and erase one
320 int ScoreA
= Score(List
[I
]);
321 int ScoreB
= Score(List
[J
]);
333 // Wipe erased entries
334 for (unsigned int I
= 0; I
< List
.size();)
336 if (List
[I
].empty() == false)
339 List
.erase(List
.begin()+I
);
342 return couldFindAllFiles
;
345 // ReduceSourceList - Takes the path list and reduces it /*{{{*/
346 // ---------------------------------------------------------------------
347 /* This takes the list of source list expressed entires and collects
348 similar ones to form a single entry for each dist */
349 void pkgCdrom::ReduceSourcelist(string CD
,vector
<string
> &List
)
351 sort(List
.begin(),List
.end());
353 // Collect similar entries
354 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
357 string::size_type Space
= (*I
).find(' ');
358 if (Space
== string::npos
)
360 string::size_type SSpace
= (*I
).find(' ',Space
+ 1);
361 if (SSpace
== string::npos
)
364 string Word1
= string(*I
,Space
,SSpace
-Space
);
365 string Prefix
= string(*I
,0,Space
);
366 for (vector
<string
>::iterator J
= List
.begin(); J
!= I
; ++J
)
369 string::size_type Space2
= (*J
).find(' ');
370 if (Space2
== string::npos
)
372 string::size_type SSpace2
= (*J
).find(' ',Space2
+ 1);
373 if (SSpace2
== string::npos
)
376 if (string(*J
,0,Space2
) != Prefix
)
378 if (string(*J
,Space2
,SSpace2
-Space2
) != Word1
)
381 *J
+= string(*I
,SSpace
);
386 // Wipe erased entries
387 for (unsigned int I
= 0; I
< List
.size();)
389 if (List
[I
].empty() == false)
392 List
.erase(List
.begin()+I
);
396 // WriteDatabase - Write the CDROM Database file /*{{{*/
397 // ---------------------------------------------------------------------
398 /* We rewrite the configuration class associated with the cdrom database. */
399 bool pkgCdrom::WriteDatabase(Configuration
&Cnf
)
401 string DFile
= _config
->FindFile("Dir::State::cdroms");
402 string NewFile
= DFile
+ ".new";
404 unlink(NewFile
.c_str());
405 ofstream
Out(NewFile
.c_str());
407 return _error
->Errno("ofstream::ofstream",
408 "Failed to open %s.new",DFile
.c_str());
410 /* Write out all of the configuration directives by walking the
411 configuration tree */
412 const Configuration::Item
*Top
= Cnf
.Tree(0);
415 // Print the config entry
416 if (Top
->Value
.empty() == false)
417 Out
<< Top
->FullTag() + " \"" << Top
->Value
<< "\";" << endl
;
425 while (Top
!= 0 && Top
->Next
== 0)
433 if (FileExists(DFile
) == true && link(DFile
.c_str(),string(DFile
+ '~').c_str()) != 0)
434 return _error
->Errno("link", "Failed to link %s to %s~", DFile
.c_str(), DFile
.c_str());
435 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
436 return _error
->Errno("rename","Failed to rename %s.new to %s",
437 DFile
.c_str(),DFile
.c_str());
442 // WriteSourceList - Write an updated sourcelist /*{{{*/
443 // ---------------------------------------------------------------------
444 /* This reads the old source list and copies it into the new one. It
445 appends the new CDROM entires just after the first block of comments.
446 This places them first in the file. It also removes any old entries
447 that were the same. */
448 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
450 if (List
.empty() == true)
453 string File
= _config
->FindFile("Dir::Etc::sourcelist");
455 // Open the stream for reading
456 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
459 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
461 string NewFile
= File
+ ".new";
462 unlink(NewFile
.c_str());
463 ofstream
Out(NewFile
.c_str());
465 return _error
->Errno("ofstream::ofstream",
466 "Failed to open %s.new",File
.c_str());
468 // Create a short uri without the path
469 string ShortURI
= "cdrom:[" + Name
+ "]/";
470 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
481 while (F
.eof() == false)
483 F
.getline(Buffer
,sizeof(Buffer
));
485 if (F
.fail() && !F
.eof())
486 return _error
->Error(_("Line %u too long in source list %s."),
487 CurLine
,File
.c_str());
488 _strtabexpand(Buffer
,sizeof(Buffer
));
492 if (Buffer
[0] == '#' || Buffer
[0] == 0)
494 Out
<< Buffer
<< endl
;
500 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
502 string::size_type Space
= (*I
).find(' ');
503 if (Space
== string::npos
)
504 return _error
->Error("Internal error");
505 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
506 " " << string(*I
,Space
+1) << endl
;
514 const char *C
= Buffer
;
515 if (ParseQuoteWord(C
,cType
) == false ||
516 ParseQuoteWord(C
,URI
) == false)
518 Out
<< Buffer
<< endl
;
522 // Emit lines like this one
523 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
524 string(URI
,0,ShortURI
.length()) != ShortURI2
))
526 Out
<< Buffer
<< endl
;
531 // Just in case the file was empty
534 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
536 string::size_type Space
= (*I
).find(' ');
537 if (Space
== string::npos
)
538 return _error
->Error("Internal error");
540 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
541 " " << string(*I
,Space
+1) << endl
;
547 rename(File
.c_str(),string(File
+ '~').c_str());
548 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
549 return _error
->Errno("rename","Failed to rename %s.new to %s",
550 File
.c_str(),File
.c_str());
555 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
560 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
562 CDROM
= SafeGetCWD() + '/' + CDROM
;
567 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
569 log
->Update(msg
.str());
571 if (MountCdrom(CDROM
) == false)
572 return _error
->Error("Failed to mount the cdrom.");
574 // Hash the CD to get an ID
576 log
->Update(_("Identifying.. "));
579 if (IdentCdrom(CDROM
,ident
) == false)
588 ioprintf(msg
, "[%s]\n",ident
.c_str());
589 log
->Update(msg
.str());
593 Configuration Database
;
594 string DFile
= _config
->FindFile("Dir::State::cdroms");
595 if (FileExists(DFile
) == true)
597 if (ReadConfigFile(Database
,DFile
) == false)
598 return _error
->Error("Unable to read the cdrom database %s",
604 ioprintf(msg
, _("Stored label: %s\n"),
605 Database
.Find("CD::"+ident
).c_str());
606 log
->Update(msg
.str());
609 // Unmount and finish
610 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
613 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
620 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
625 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
627 CDROM
= SafeGetCWD() + '/' + CDROM
;
631 log
->SetTotal(STEP_LAST
);
633 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
634 log
->Update(msg
.str(), STEP_PREPARE
);
638 Configuration Database
;
639 string DFile
= _config
->FindFile("Dir::State::cdroms");
640 if (FileExists(DFile
) == true)
642 if (ReadConfigFile(Database
,DFile
) == false)
643 return _error
->Error("Unable to read the cdrom database %s",
647 // Unmount the CD and get the user to put in the one they want
648 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
651 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
656 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
657 if(!log
->ChangeCdrom()) {
663 // Mount the new CDROM
665 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
667 if (MountCdrom(CDROM
) == false)
668 return _error
->Error("Failed to mount the cdrom.");
671 // Hash the CD to get an ID
673 log
->Update(_("Identifying.. "), STEP_IDENT
);
675 if (IdentCdrom(CDROM
,ID
) == false)
683 log
->Update("["+ID
+"]\n");
684 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
687 // Get the CD structure
689 vector
<string
> SourceList
;
690 vector
<string
> SigList
;
691 vector
<string
> TransList
;
692 string StartDir
= SafeGetCWD();
694 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
701 if (chdir(StartDir
.c_str()) != 0)
702 return _error
->Errno("chdir","Unable to change to %s", StartDir
.c_str());
704 if (_config
->FindB("Debug::aptcdrom",false) == true)
706 cout
<< "I found (binary):" << endl
;
707 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
709 cout
<< "I found (source):" << endl
;
710 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
712 cout
<< "I found (Signatures):" << endl
;
713 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
717 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
720 DropBinaryArch(List
);
721 DropRepeats(List
,"Packages");
722 DropRepeats(SourceList
,"Sources");
723 // FIXME: We ignore stat() errors here as we usually have only one of those in use
724 // This has little potencial to drop 'valid' stat() errors as we know that one of these
725 // files need to exist, but it would be better if we would check it here
726 _error
->PushToStack();
727 DropRepeats(SigList
,"Release.gpg");
728 DropRepeats(SigList
,"InRelease");
729 _error
->RevertToStack();
730 DropRepeats(TransList
,"");
733 ioprintf(msg
, _("Found %zu package indexes, %zu source indexes, "
734 "%zu translation indexes and %zu signatures\n"),
735 List
.size(), SourceList
.size(), TransList
.size(),
737 log
->Update(msg
.str(), STEP_SCAN
);
740 if (List
.empty() == true && SourceList
.empty() == true)
742 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
744 return _error
->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc or the wrong architecture?"));
747 // Check if the CD is in the database
749 if (Database
.Exists("CD::" + ID
) == false ||
750 _config
->FindB("APT::CDROM::Rename",false) == true)
752 // Try to use the CDs label if at all possible
753 if (InfoDir
.empty() == false &&
754 FileExists(InfoDir
+ "/info") == true)
756 ifstream
F(string(InfoDir
+ "/info").c_str());
760 if (Name
.empty() == false)
762 // Escape special characters
763 string::iterator J
= Name
.begin();
764 for (; J
!= Name
.end(); ++J
)
765 if (*J
== '"' || *J
== ']' || *J
== '[')
771 ioprintf(msg
, _("Found label '%s'\n"), Name
.c_str());
772 log
->Update(msg
.str());
774 Database
.Set("CD::" + ID
+ "::Label",Name
);
778 if (_config
->FindB("APT::CDROM::Rename",false) == true ||
779 Name
.empty() == true)
783 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
785 return _error
->Error("No disc name found and no way to ask for it");
789 if(!log
->AskCdromName(Name
)) {
793 cout
<< "Name: '" << Name
<< "'" << endl
;
795 if (Name
.empty() == false &&
796 Name
.find('"') == string::npos
&&
797 Name
.find('[') == string::npos
&&
798 Name
.find(']') == string::npos
)
800 log
->Update(_("That is not a valid name, try again.\n"));
805 Name
= Database
.Find("CD::" + ID
);
807 // Escape special characters
808 string::iterator J
= Name
.begin();
809 for (; J
!= Name
.end(); ++J
)
810 if (*J
== '"' || *J
== ']' || *J
== '[')
813 Database
.Set("CD::" + ID
,Name
);
817 ioprintf(msg
, _("This disc is called: \n'%s'\n"), Name
.c_str());
818 log
->Update(msg
.str());
819 log
->Update(_("Copying package lists..."), STEP_COPY
);
821 // take care of the signatures and copy them if they are ok
822 // (we do this before PackageCopy as it modifies "List" and "SourceList")
823 SigVerify SignVerify
;
824 SignVerify
.CopyAndVerify(CDROM
, Name
, SigList
, List
, SourceList
);
826 // Copy the package files to the state directory
829 TranslationsCopy TransCopy
;
830 if (Copy
.CopyPackages(CDROM
,Name
,List
, log
) == false ||
831 SrcCopy
.CopyPackages(CDROM
,Name
,SourceList
, log
) == false ||
832 TransCopy
.CopyTranslations(CDROM
,Name
,TransList
, log
) == false)
835 // reduce the List so that it takes less space in sources.list
836 ReduceSourcelist(CDROM
,List
);
837 ReduceSourcelist(CDROM
,SourceList
);
839 // Write the database and sourcelist
840 if (_config
->FindB("APT::cdrom::NoAct",false) == false)
842 if (WriteDatabase(Database
) == false)
846 log
->Update(_("Writing new source list\n"), STEP_WRITE
);
847 if (WriteSourceList(Name
,List
,false) == false ||
848 WriteSourceList(Name
,SourceList
,true) == false)
852 // Print the sourcelist entries
854 log
->Update(_("Source list entries for this disc are:\n"));
856 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
858 string::size_type Space
= (*I
).find(' ');
859 if (Space
== string::npos
)
861 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
863 return _error
->Error("Internal error");
869 msg
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
870 " " << string(*I
,Space
+1) << endl
;
871 log
->Update(msg
.str());
875 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
877 string::size_type Space
= (*I
).find(' ');
878 if (Space
== string::npos
)
880 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
882 return _error
->Error("Internal error");
887 msg
<< "deb-src cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
888 " " << string(*I
,Space
+1) << endl
;
889 log
->Update(msg
.str());
893 // Unmount and finish
894 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
896 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
903 pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/
904 : libudev_handle(NULL
)
911 pkgUdevCdromDevices::Dlopen() /*{{{*/
914 if(libudev_handle
!= NULL
)
917 // see if we can get libudev
918 void *h
= ::dlopen("libudev.so.0", RTLD_LAZY
);
922 // get the pointers to the udev structs
924 udev_new
= (udev
* (*)(void)) dlsym(h
, "udev_new");
925 udev_enumerate_add_match_property
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_property");
926 udev_enumerate_add_match_sysattr
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_sysattr");
927 udev_enumerate_scan_devices
= (int (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_scan_devices");
928 udev_enumerate_get_list_entry
= (udev_list_entry
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_list_entry");
929 udev_device_new_from_syspath
= (udev_device
* (*)(udev
*, const char*))dlsym(h
, "udev_device_new_from_syspath");
930 udev_enumerate_get_udev
= (udev
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_udev");
931 udev_list_entry_get_name
= (const char* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_name");
932 udev_device_get_devnode
= (const char* (*)(udev_device
*))dlsym(h
, "udev_device_get_devnode");
933 udev_enumerate_new
= (udev_enumerate
* (*)(udev
*))dlsym(h
, "udev_enumerate_new");
934 udev_list_entry_get_next
= (udev_list_entry
* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_next");
935 udev_device_get_property_value
= (const char* (*)(udev_device
*, const char *))dlsym(h
, "udev_device_get_property_value");
941 // convenience interface, this will just call ScanForRemovable
943 pkgUdevCdromDevices::Scan()
945 bool CdromOnly
= _config
->FindB("APT::cdrom::CdromOnly", true);
946 return ScanForRemovable(CdromOnly
);
951 pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly
)
953 vector
<CdromDevice
> cdrom_devices
;
954 struct udev_enumerate
*enumerate
;
955 struct udev_list_entry
*l
, *devices
;
956 struct udev
*udev_ctx
;
958 if(libudev_handle
== NULL
)
959 return cdrom_devices
;
961 udev_ctx
= udev_new();
962 enumerate
= udev_enumerate_new (udev_ctx
);
964 udev_enumerate_add_match_property(enumerate
, "ID_CDROM", "1");
966 udev_enumerate_add_match_sysattr(enumerate
, "removable", "1");
969 udev_enumerate_scan_devices (enumerate
);
970 devices
= udev_enumerate_get_list_entry (enumerate
);
971 for (l
= devices
; l
!= NULL
; l
= udev_list_entry_get_next (l
))
974 struct udev_device
*udevice
;
975 udevice
= udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate
), udev_list_entry_get_name (l
));
978 const char* devnode
= udev_device_get_devnode(udevice
);
980 // try fstab_dir first
982 const char* mp
= udev_device_get_property_value(udevice
, "FSTAB_DIR");
984 mountpath
= string(mp
);
986 mountpath
= FindMountPointForDevice(devnode
);
988 // fill in the struct
989 cdrom
.DeviceName
= string(devnode
);
990 if (mountpath
!= "") {
991 cdrom
.MountPath
= mountpath
;
992 string s
= string(mountpath
);
993 cdrom
.Mounted
= IsMounted(s
);
995 cdrom
.Mounted
= false;
996 cdrom
.MountPath
= "";
998 cdrom_devices
.push_back(cdrom
);
1000 return cdrom_devices
;
1004 pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/
1006 if (libudev_handle
!= NULL
)
1007 dlclose(libudev_handle
);