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
62 if (stat(".disk",&Buf
) == 0)
64 if (InfoDir
.empty() == true)
65 InfoDir
= CD
+ ".disk/";
68 // Don't look into directories that have been marked to ingore.
69 if (stat(".aptignr",&Buf
) == 0)
73 /* Check _first_ for a signature file as apt-cdrom assumes that all files
74 under a Packages/Source file are in control of that file and stops
77 if (stat("Release.gpg",&Buf
) == 0)
79 SigList
.push_back(CD
);
82 /* Aha! We found some package files. We assume that everything under
83 this dir is controlled by those package files so we don't look down
85 std::vector
<std::string
> types
= APT::Configuration::getCompressionTypes();
87 for (std::vector
<std::string
>::const_iterator t
= types
.begin();
88 t
!= types
.end(); ++t
)
90 std::string filename
= std::string("Packages");
92 filename
.append("."+*t
);
93 if (stat(filename
.c_str(), &Buf
) == 0)
97 // Continue down if thorough is given
98 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
103 for (std::vector
<std::string
>::const_iterator t
= types
.begin();
104 t
!= types
.end(); ++t
)
106 std::string filename
= std::string("Sources");
108 filename
.append("."+*t
);
112 // Continue down if thorough is given
113 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
119 // see if we find translation indices
120 if (stat("i18n",&Buf
) == 0)
123 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
125 if(strstr(Dir
->d_name
,"Translation") != NULL
)
127 if (_config
->FindB("Debug::aptcdrom",false) == true)
128 std::clog
<< "found translations: " << Dir
->d_name
<< "\n";
129 string file
= Dir
->d_name
;
130 for (std::vector
<std::string
>::const_iterator t
= types
.begin();
131 t
!= types
.end(); ++t
)
133 std::string needle
= "." + *t
;
134 if(file
.substr(file
.size()-needle
.size()) == needle
)
135 file
= file
.substr(0, file
.size()-needle
.size());
136 TransList
.push_back(CD
+"i18n/"+ file
);
147 return _error
->Errno("opendir","Unable to read %s",CD
.c_str());
149 // Run over the directory
150 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
153 if (strcmp(Dir
->d_name
,".") == 0 ||
154 strcmp(Dir
->d_name
,"..") == 0 ||
155 //strcmp(Dir->d_name,"source") == 0 ||
156 strcmp(Dir
->d_name
,".disk") == 0 ||
157 strcmp(Dir
->d_name
,"experimental") == 0 ||
158 strcmp(Dir
->d_name
,"binary-all") == 0 ||
159 strcmp(Dir
->d_name
,"debian-installer") == 0)
162 // See if the name is a sub directory
164 if (stat(Dir
->d_name
,&Buf
) != 0)
167 if (S_ISDIR(Buf
.st_mode
) == 0)
171 for (I
= 0; I
!= Depth
; I
++)
172 if (Inodes
[I
] == Buf
.st_ino
)
177 // Store the inodes weve seen
178 Inodes
[Depth
] = Buf
.st_ino
;
181 if (FindPackages(CD
+ Dir
->d_name
,List
,SList
,SigList
,TransList
,InfoDir
,log
,Depth
+1) == false)
184 if (chdir(CD
.c_str()) != 0)
186 _error
->Errno("chdir","Unable to change to %s", CD
.c_str());
194 return !_error
->PendingError();
197 // Score - We compute a 'score' for a path /*{{{*/
198 // ---------------------------------------------------------------------
199 /* Paths are scored based on how close they come to what I consider
200 normal. That is ones that have 'dist' 'stable' 'testing' will score
201 higher than ones without. */
202 int pkgCdrom::Score(string Path
)
205 if (Path
.find("stable/") != string::npos
)
207 if (Path
.find("/binary-") != string::npos
)
209 if (Path
.find("testing/") != string::npos
)
211 if (Path
.find("unstable/") != string::npos
)
213 if (Path
.find("/dists/") != string::npos
)
215 if (Path
.find("/main/") != string::npos
)
217 if (Path
.find("/contrib/") != string::npos
)
219 if (Path
.find("/non-free/") != string::npos
)
221 if (Path
.find("/non-US/") != string::npos
)
223 if (Path
.find("/source/") != string::npos
)
225 if (Path
.find("/debian/") != string::npos
)
228 // check for symlinks in the patch leading to the actual file
229 // a symlink gets a big penalty
231 string statPath
= flNotFile(Path
);
232 string cdromPath
= _config
->FindDir("Acquire::cdrom::mount");
233 while(statPath
!= cdromPath
&& statPath
!= "./") {
234 statPath
.resize(statPath
.size()-1); // remove the trailing '/'
235 if (lstat(statPath
.c_str(),&Buf
) == 0) {
236 if(S_ISLNK(Buf
.st_mode
)) {
241 statPath
= flNotFile(statPath
); // descent
247 // DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/
248 // ---------------------------------------------------------------------
249 /* Here we drop everything that is not this machines arch */
250 bool pkgCdrom::DropBinaryArch(vector
<string
> &List
)
253 for (unsigned int I
= 0; I
< List
.size(); I
++)
255 const char *Str
= List
[I
].c_str();
256 const char *Start
, *End
;
257 if ((Start
= strstr(Str
,"/binary-")) == 0)
260 // Between Start and End is the architecture
262 if ((End
= strstr(Start
,"/")) != 0 && Start
!= End
&&
263 APT::Configuration::checkArchitecture(string(Start
, End
)) == true)
264 continue; // okay, architecture is accepted
266 // not accepted -> Erase it
267 List
.erase(List
.begin() + I
);
268 --I
; // the next entry is at the same index after the erase
274 // DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
275 // ---------------------------------------------------------------------
276 /* Here we go and stat every file that we found and strip dup inodes. */
277 bool pkgCdrom::DropRepeats(vector
<string
> &List
,const char *Name
)
279 // Get a list of all the inodes
280 ino_t
*Inodes
= new ino_t
[List
.size()];
281 for (unsigned int I
= 0; I
!= List
.size(); I
++)
284 std::vector
<std::string
> types
= APT::Configuration::getCompressionTypes();
286 for (std::vector
<std::string
>::const_iterator t
= types
.begin();
287 t
!= types
.end(); ++t
)
289 std::string filename
= List
[I
] + Name
;
291 filename
.append("." + *t
);
292 if (stat(filename
.c_str(), &Buf
) != 0)
293 _error
->Errno("stat","Failed to stat %s%s",List
[I
].c_str(),
295 Inodes
[I
] = Buf
.st_ino
;
299 if (_error
->PendingError() == true) {
305 for (unsigned int I
= 0; I
!= List
.size(); I
++)
307 for (unsigned int J
= I
+1; J
< List
.size(); J
++)
310 if (Inodes
[J
] != Inodes
[I
])
313 // We score the two paths.. and erase one
314 int ScoreA
= Score(List
[I
]);
315 int ScoreB
= Score(List
[J
]);
327 // Wipe erased entries
328 for (unsigned int I
= 0; I
< List
.size();)
330 if (List
[I
].empty() == false)
333 List
.erase(List
.begin()+I
);
339 // ReduceSourceList - Takes the path list and reduces it /*{{{*/
340 // ---------------------------------------------------------------------
341 /* This takes the list of source list expressed entires and collects
342 similar ones to form a single entry for each dist */
343 void pkgCdrom::ReduceSourcelist(string CD
,vector
<string
> &List
)
345 sort(List
.begin(),List
.end());
347 // Collect similar entries
348 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
351 string::size_type Space
= (*I
).find(' ');
352 if (Space
== string::npos
)
354 string::size_type SSpace
= (*I
).find(' ',Space
+ 1);
355 if (SSpace
== string::npos
)
358 string Word1
= string(*I
,Space
,SSpace
-Space
);
359 string Prefix
= string(*I
,0,Space
);
360 for (vector
<string
>::iterator J
= List
.begin(); J
!= I
; ++J
)
363 string::size_type Space2
= (*J
).find(' ');
364 if (Space2
== string::npos
)
366 string::size_type SSpace2
= (*J
).find(' ',Space2
+ 1);
367 if (SSpace2
== string::npos
)
370 if (string(*J
,0,Space2
) != Prefix
)
372 if (string(*J
,Space2
,SSpace2
-Space2
) != Word1
)
375 *J
+= string(*I
,SSpace
);
380 // Wipe erased entries
381 for (unsigned int I
= 0; I
< List
.size();)
383 if (List
[I
].empty() == false)
386 List
.erase(List
.begin()+I
);
390 // WriteDatabase - Write the CDROM Database file /*{{{*/
391 // ---------------------------------------------------------------------
392 /* We rewrite the configuration class associated with the cdrom database. */
393 bool pkgCdrom::WriteDatabase(Configuration
&Cnf
)
395 string DFile
= _config
->FindFile("Dir::State::cdroms");
396 string NewFile
= DFile
+ ".new";
398 unlink(NewFile
.c_str());
399 ofstream
Out(NewFile
.c_str());
401 return _error
->Errno("ofstream::ofstream",
402 "Failed to open %s.new",DFile
.c_str());
404 /* Write out all of the configuration directives by walking the
405 configuration tree */
406 const Configuration::Item
*Top
= Cnf
.Tree(0);
409 // Print the config entry
410 if (Top
->Value
.empty() == false)
411 Out
<< Top
->FullTag() + " \"" << Top
->Value
<< "\";" << endl
;
419 while (Top
!= 0 && Top
->Next
== 0)
427 link(DFile
.c_str(),string(DFile
+ '~').c_str());
428 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
429 return _error
->Errno("rename","Failed to rename %s.new to %s",
430 DFile
.c_str(),DFile
.c_str());
435 // WriteSourceList - Write an updated sourcelist /*{{{*/
436 // ---------------------------------------------------------------------
437 /* This reads the old source list and copies it into the new one. It
438 appends the new CDROM entires just after the first block of comments.
439 This places them first in the file. It also removes any old entries
440 that were the same. */
441 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
443 if (List
.empty() == true)
446 string File
= _config
->FindFile("Dir::Etc::sourcelist");
448 // Open the stream for reading
449 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
452 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
454 string NewFile
= File
+ ".new";
455 unlink(NewFile
.c_str());
456 ofstream
Out(NewFile
.c_str());
458 return _error
->Errno("ofstream::ofstream",
459 "Failed to open %s.new",File
.c_str());
461 // Create a short uri without the path
462 string ShortURI
= "cdrom:[" + Name
+ "]/";
463 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
474 while (F
.eof() == false)
476 F
.getline(Buffer
,sizeof(Buffer
));
478 if (F
.fail() && !F
.eof())
479 return _error
->Error(_("Line %u too long in source list %s."),
480 CurLine
,File
.c_str());
481 _strtabexpand(Buffer
,sizeof(Buffer
));
485 if (Buffer
[0] == '#' || Buffer
[0] == 0)
487 Out
<< Buffer
<< endl
;
493 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
495 string::size_type Space
= (*I
).find(' ');
496 if (Space
== string::npos
)
497 return _error
->Error("Internal error");
498 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
499 " " << string(*I
,Space
+1) << endl
;
507 const char *C
= Buffer
;
508 if (ParseQuoteWord(C
,cType
) == false ||
509 ParseQuoteWord(C
,URI
) == false)
511 Out
<< Buffer
<< endl
;
515 // Emit lines like this one
516 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
517 string(URI
,0,ShortURI
.length()) != ShortURI2
))
519 Out
<< Buffer
<< endl
;
524 // Just in case the file was empty
527 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
529 string::size_type Space
= (*I
).find(' ');
530 if (Space
== string::npos
)
531 return _error
->Error("Internal error");
533 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
534 " " << string(*I
,Space
+1) << endl
;
540 rename(File
.c_str(),string(File
+ '~').c_str());
541 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
542 return _error
->Errno("rename","Failed to rename %s.new to %s",
543 File
.c_str(),File
.c_str());
548 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
553 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
555 CDROM
= SafeGetCWD() + '/' + CDROM
;
560 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
562 log
->Update(msg
.str());
564 if (MountCdrom(CDROM
) == false)
565 return _error
->Error("Failed to mount the cdrom.");
567 // Hash the CD to get an ID
569 log
->Update(_("Identifying.. "));
572 if (IdentCdrom(CDROM
,ident
) == false)
581 ioprintf(msg
, "[%s]\n",ident
.c_str());
582 log
->Update(msg
.str());
586 Configuration Database
;
587 string DFile
= _config
->FindFile("Dir::State::cdroms");
588 if (FileExists(DFile
) == true)
590 if (ReadConfigFile(Database
,DFile
) == false)
591 return _error
->Error("Unable to read the cdrom database %s",
597 ioprintf(msg
, _("Stored label: %s\n"),
598 Database
.Find("CD::"+ident
).c_str());
599 log
->Update(msg
.str());
602 // Unmount and finish
603 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
606 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
613 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
618 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
620 CDROM
= SafeGetCWD() + '/' + CDROM
;
624 log
->SetTotal(STEP_LAST
);
626 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
627 log
->Update(msg
.str(), STEP_PREPARE
);
631 Configuration Database
;
632 string DFile
= _config
->FindFile("Dir::State::cdroms");
633 if (FileExists(DFile
) == true)
635 if (ReadConfigFile(Database
,DFile
) == false)
636 return _error
->Error("Unable to read the cdrom database %s",
640 // Unmount the CD and get the user to put in the one they want
641 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
644 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
649 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
650 if(!log
->ChangeCdrom()) {
656 // Mount the new CDROM
658 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
660 if (MountCdrom(CDROM
) == false)
661 return _error
->Error("Failed to mount the cdrom.");
664 // Hash the CD to get an ID
666 log
->Update(_("Identifying.. "), STEP_IDENT
);
668 if (IdentCdrom(CDROM
,ID
) == false)
676 log
->Update("["+ID
+"]\n");
677 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
680 // Get the CD structure
682 vector
<string
> SourceList
;
683 vector
<string
> SigList
;
684 vector
<string
> TransList
;
685 string StartDir
= SafeGetCWD();
687 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
694 chdir(StartDir
.c_str());
696 if (_config
->FindB("Debug::aptcdrom",false) == true)
698 cout
<< "I found (binary):" << endl
;
699 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
701 cout
<< "I found (source):" << endl
;
702 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
704 cout
<< "I found (Signatures):" << endl
;
705 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
709 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
712 DropBinaryArch(List
);
713 DropRepeats(List
,"Packages");
714 DropRepeats(SourceList
,"Sources");
715 DropRepeats(SigList
,"Release.gpg");
716 DropRepeats(TransList
,"");
719 ioprintf(msg
, _("Found %zu package indexes, %zu source indexes, "
720 "%zu translation indexes and %zu signatures\n"),
721 List
.size(), SourceList
.size(), TransList
.size(),
723 log
->Update(msg
.str(), STEP_SCAN
);
726 if (List
.empty() == true && SourceList
.empty() == true)
728 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
730 return _error
->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc or the wrong architecture?"));
733 // Check if the CD is in the database
735 if (Database
.Exists("CD::" + ID
) == false ||
736 _config
->FindB("APT::CDROM::Rename",false) == true)
738 // Try to use the CDs label if at all possible
739 if (InfoDir
.empty() == false &&
740 FileExists(InfoDir
+ "/info") == true)
742 ifstream
F(string(InfoDir
+ "/info").c_str());
746 if (Name
.empty() == false)
748 // Escape special characters
749 string::iterator J
= Name
.begin();
750 for (; J
!= Name
.end(); ++J
)
751 if (*J
== '"' || *J
== ']' || *J
== '[')
757 ioprintf(msg
, _("Found label '%s'\n"), Name
.c_str());
758 log
->Update(msg
.str());
760 Database
.Set("CD::" + ID
+ "::Label",Name
);
764 if (_config
->FindB("APT::CDROM::Rename",false) == true ||
765 Name
.empty() == true)
769 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
771 return _error
->Error("No disc name found and no way to ask for it");
775 if(!log
->AskCdromName(Name
)) {
779 cout
<< "Name: '" << Name
<< "'" << endl
;
781 if (Name
.empty() == false &&
782 Name
.find('"') == string::npos
&&
783 Name
.find('[') == string::npos
&&
784 Name
.find(']') == string::npos
)
786 log
->Update(_("That is not a valid name, try again.\n"));
791 Name
= Database
.Find("CD::" + ID
);
793 // Escape special characters
794 string::iterator J
= Name
.begin();
795 for (; J
!= Name
.end(); ++J
)
796 if (*J
== '"' || *J
== ']' || *J
== '[')
799 Database
.Set("CD::" + ID
,Name
);
803 ioprintf(msg
, _("This disc is called: \n'%s'\n"), Name
.c_str());
804 log
->Update(msg
.str());
805 log
->Update(_("Copying package lists..."), STEP_COPY
);
807 // take care of the signatures and copy them if they are ok
808 // (we do this before PackageCopy as it modifies "List" and "SourceList")
809 SigVerify SignVerify
;
810 SignVerify
.CopyAndVerify(CDROM
, Name
, SigList
, List
, SourceList
);
812 // Copy the package files to the state directory
815 TranslationsCopy TransCopy
;
816 if (Copy
.CopyPackages(CDROM
,Name
,List
, log
) == false ||
817 SrcCopy
.CopyPackages(CDROM
,Name
,SourceList
, log
) == false ||
818 TransCopy
.CopyTranslations(CDROM
,Name
,TransList
, log
) == false)
821 // reduce the List so that it takes less space in sources.list
822 ReduceSourcelist(CDROM
,List
);
823 ReduceSourcelist(CDROM
,SourceList
);
825 // Write the database and sourcelist
826 if (_config
->FindB("APT::cdrom::NoAct",false) == false)
828 if (WriteDatabase(Database
) == false)
832 log
->Update(_("Writing new source list\n"), STEP_WRITE
);
833 if (WriteSourceList(Name
,List
,false) == false ||
834 WriteSourceList(Name
,SourceList
,true) == false)
838 // Print the sourcelist entries
840 log
->Update(_("Source list entries for this disc are:\n"));
842 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
844 string::size_type Space
= (*I
).find(' ');
845 if (Space
== string::npos
)
847 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
849 return _error
->Error("Internal error");
855 msg
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
856 " " << string(*I
,Space
+1) << endl
;
857 log
->Update(msg
.str());
861 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
863 string::size_type Space
= (*I
).find(' ');
864 if (Space
== string::npos
)
866 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
868 return _error
->Error("Internal error");
873 msg
<< "deb-src cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
874 " " << string(*I
,Space
+1) << endl
;
875 log
->Update(msg
.str());
879 // Unmount and finish
880 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
882 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
889 pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/
890 : libudev_handle(NULL
)
897 pkgUdevCdromDevices::Dlopen() /*{{{*/
900 if(libudev_handle
!= NULL
)
903 // see if we can get libudev
904 void *h
= ::dlopen("libudev.so.0", RTLD_LAZY
);
908 // get the pointers to the udev structs
910 udev_new
= (udev
* (*)(void)) dlsym(h
, "udev_new");
911 udev_enumerate_add_match_property
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_property");
912 udev_enumerate_add_match_sysattr
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_sysattr");
913 udev_enumerate_scan_devices
= (int (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_scan_devices");
914 udev_enumerate_get_list_entry
= (udev_list_entry
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_list_entry");
915 udev_device_new_from_syspath
= (udev_device
* (*)(udev
*, const char*))dlsym(h
, "udev_device_new_from_syspath");
916 udev_enumerate_get_udev
= (udev
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_udev");
917 udev_list_entry_get_name
= (const char* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_name");
918 udev_device_get_devnode
= (const char* (*)(udev_device
*))dlsym(h
, "udev_device_get_devnode");
919 udev_enumerate_new
= (udev_enumerate
* (*)(udev
*))dlsym(h
, "udev_enumerate_new");
920 udev_list_entry_get_next
= (udev_list_entry
* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_next");
921 udev_device_get_property_value
= (const char* (*)(udev_device
*, const char *))dlsym(h
, "udev_device_get_property_value");
927 // convenience interface, this will just call ScanForRemovable
929 pkgUdevCdromDevices::Scan()
931 bool CdromOnly
= _config
->FindB("APT::cdrom::CdromOnly", true);
932 return ScanForRemovable(CdromOnly
);
937 pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly
)
939 vector
<CdromDevice
> cdrom_devices
;
940 struct udev_enumerate
*enumerate
;
941 struct udev_list_entry
*l
, *devices
;
942 struct udev
*udev_ctx
;
944 if(libudev_handle
== NULL
)
945 return cdrom_devices
;
947 udev_ctx
= udev_new();
948 enumerate
= udev_enumerate_new (udev_ctx
);
950 udev_enumerate_add_match_property(enumerate
, "ID_CDROM", "1");
952 udev_enumerate_add_match_sysattr(enumerate
, "removable", "1");
955 udev_enumerate_scan_devices (enumerate
);
956 devices
= udev_enumerate_get_list_entry (enumerate
);
957 for (l
= devices
; l
!= NULL
; l
= udev_list_entry_get_next (l
))
960 struct udev_device
*udevice
;
961 udevice
= udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate
), udev_list_entry_get_name (l
));
964 const char* devnode
= udev_device_get_devnode(udevice
);
966 // try fstab_dir first
968 const char* mp
= udev_device_get_property_value(udevice
, "FSTAB_DIR");
970 mountpath
= string(mp
);
972 mountpath
= FindMountPointForDevice(devnode
);
974 // fill in the struct
975 cdrom
.DeviceName
= string(devnode
);
976 if (mountpath
!= "") {
977 cdrom
.MountPath
= mountpath
;
978 string s
= string(mountpath
);
979 cdrom
.Mounted
= IsMounted(s
);
981 cdrom
.Mounted
= false;
982 cdrom
.MountPath
= "";
984 cdrom_devices
.push_back(cdrom
);
986 return cdrom_devices
;
990 pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/
992 if (libudev_handle
!= NULL
)
993 dlclose(libudev_handle
);