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
);
81 /* Aha! We found some package files. We assume that everything under
82 this dir is controlled by those package files so we don't look down
84 if (stat("Packages",&Buf
) == 0 || stat("Packages.gz",&Buf
) == 0)
88 // Continue down if thorough is given
89 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
92 if (stat("Sources.gz",&Buf
) == 0 || stat("Sources",&Buf
) == 0)
96 // Continue down if thorough is given
97 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
101 // see if we find translatin indexes
102 if (stat("i18n",&Buf
) == 0)
105 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
107 if(strstr(Dir
->d_name
,"Translation") != NULL
)
109 if (_config
->FindB("Debug::aptcdrom",false) == true)
110 std::clog
<< "found translations: " << Dir
->d_name
<< "\n";
111 string file
= Dir
->d_name
;
112 if(file
.substr(file
.size()-3,file
.size()) == ".gz")
113 file
= file
.substr(0,file
.size()-3);
114 TransList
.push_back(CD
+"i18n/"+ file
);
123 return _error
->Errno("opendir","Unable to read %s",CD
.c_str());
125 // Run over the directory
126 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
129 if (strcmp(Dir
->d_name
,".") == 0 ||
130 strcmp(Dir
->d_name
,"..") == 0 ||
131 //strcmp(Dir->d_name,"source") == 0 ||
132 strcmp(Dir
->d_name
,".disk") == 0 ||
133 strcmp(Dir
->d_name
,"experimental") == 0 ||
134 strcmp(Dir
->d_name
,"binary-all") == 0 ||
135 strcmp(Dir
->d_name
,"debian-installer") == 0)
138 // See if the name is a sub directory
140 if (stat(Dir
->d_name
,&Buf
) != 0)
143 if (S_ISDIR(Buf
.st_mode
) == 0)
147 for (I
= 0; I
!= Depth
; I
++)
148 if (Inodes
[I
] == Buf
.st_ino
)
153 // Store the inodes weve seen
154 Inodes
[Depth
] = Buf
.st_ino
;
157 if (FindPackages(CD
+ Dir
->d_name
,List
,SList
,SigList
,TransList
,InfoDir
,log
,Depth
+1) == false)
160 if (chdir(CD
.c_str()) != 0)
162 _error
->Errno("chdir","Unable to change to %s", CD
.c_str());
170 return !_error
->PendingError();
173 // Score - We compute a 'score' for a path /*{{{*/
174 // ---------------------------------------------------------------------
175 /* Paths are scored based on how close they come to what I consider
176 normal. That is ones that have 'dist' 'stable' 'testing' will score
177 higher than ones without. */
178 int pkgCdrom::Score(string Path
)
181 if (Path
.find("stable/") != string::npos
)
183 if (Path
.find("/binary-") != string::npos
)
185 if (Path
.find("testing/") != string::npos
)
187 if (Path
.find("unstable/") != string::npos
)
189 if (Path
.find("/dists/") != string::npos
)
191 if (Path
.find("/main/") != string::npos
)
193 if (Path
.find("/contrib/") != string::npos
)
195 if (Path
.find("/non-free/") != string::npos
)
197 if (Path
.find("/non-US/") != string::npos
)
199 if (Path
.find("/source/") != string::npos
)
201 if (Path
.find("/debian/") != string::npos
)
204 // check for symlinks in the patch leading to the actual file
205 // a symlink gets a big penalty
207 string statPath
= flNotFile(Path
);
208 string cdromPath
= _config
->FindDir("Acquire::cdrom::mount");
209 while(statPath
!= cdromPath
&& statPath
!= "./") {
210 statPath
.resize(statPath
.size()-1); // remove the trailing '/'
211 if (lstat(statPath
.c_str(),&Buf
) == 0) {
212 if(S_ISLNK(Buf
.st_mode
)) {
217 statPath
= flNotFile(statPath
); // descent
223 // DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/
224 // ---------------------------------------------------------------------
225 /* Here we drop everything that is not this machines arch */
226 bool pkgCdrom::DropBinaryArch(vector
<string
> &List
)
229 for (unsigned int I
= 0; I
< List
.size(); I
++)
231 const char *Str
= List
[I
].c_str();
232 const char *Start
, *End
;
233 if ((Start
= strstr(Str
,"/binary-")) == 0)
236 // Between Start and End is the architecture
238 if ((End
= strstr(Start
,"/")) != 0 && Start
!= End
&&
239 APT::Configuration::checkArchitecture(string(Start
, End
)) == true)
240 continue; // okay, architecture is accepted
242 // not accepted -> Erase it
243 List
.erase(List
.begin() + I
);
244 --I
; // the next entry is at the same index after the erase
250 // DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
251 // ---------------------------------------------------------------------
252 /* Here we go and stat every file that we found and strip dup inodes. */
253 bool pkgCdrom::DropRepeats(vector
<string
> &List
,const char *Name
)
255 // Get a list of all the inodes
256 ino_t
*Inodes
= new ino_t
[List
.size()];
257 for (unsigned int I
= 0; I
!= List
.size(); I
++)
260 if (stat((List
[I
] + Name
).c_str(),&Buf
) != 0 &&
261 stat((List
[I
] + Name
+ ".gz").c_str(),&Buf
) != 0)
262 _error
->Errno("stat","Failed to stat %s%s",List
[I
].c_str(),
264 Inodes
[I
] = Buf
.st_ino
;
267 if (_error
->PendingError() == true) {
273 for (unsigned int I
= 0; I
!= List
.size(); I
++)
275 for (unsigned int J
= I
+1; J
< List
.size(); J
++)
278 if (Inodes
[J
] != Inodes
[I
])
281 // We score the two paths.. and erase one
282 int ScoreA
= Score(List
[I
]);
283 int ScoreB
= Score(List
[J
]);
295 // Wipe erased entries
296 for (unsigned int I
= 0; I
< List
.size();)
298 if (List
[I
].empty() == false)
301 List
.erase(List
.begin()+I
);
307 // ReduceSourceList - Takes the path list and reduces it /*{{{*/
308 // ---------------------------------------------------------------------
309 /* This takes the list of source list expressed entires and collects
310 similar ones to form a single entry for each dist */
311 void pkgCdrom::ReduceSourcelist(string CD
,vector
<string
> &List
)
313 sort(List
.begin(),List
.end());
315 // Collect similar entries
316 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
319 string::size_type Space
= (*I
).find(' ');
320 if (Space
== string::npos
)
322 string::size_type SSpace
= (*I
).find(' ',Space
+ 1);
323 if (SSpace
== string::npos
)
326 string Word1
= string(*I
,Space
,SSpace
-Space
);
327 string Prefix
= string(*I
,0,Space
);
328 for (vector
<string
>::iterator J
= List
.begin(); J
!= I
; ++J
)
331 string::size_type Space2
= (*J
).find(' ');
332 if (Space2
== string::npos
)
334 string::size_type SSpace2
= (*J
).find(' ',Space2
+ 1);
335 if (SSpace2
== string::npos
)
338 if (string(*J
,0,Space2
) != Prefix
)
340 if (string(*J
,Space2
,SSpace2
-Space2
) != Word1
)
343 *J
+= string(*I
,SSpace
);
348 // Wipe erased entries
349 for (unsigned int I
= 0; I
< List
.size();)
351 if (List
[I
].empty() == false)
354 List
.erase(List
.begin()+I
);
358 // WriteDatabase - Write the CDROM Database file /*{{{*/
359 // ---------------------------------------------------------------------
360 /* We rewrite the configuration class associated with the cdrom database. */
361 bool pkgCdrom::WriteDatabase(Configuration
&Cnf
)
363 string DFile
= _config
->FindFile("Dir::State::cdroms");
364 string NewFile
= DFile
+ ".new";
366 unlink(NewFile
.c_str());
367 ofstream
Out(NewFile
.c_str());
369 return _error
->Errno("ofstream::ofstream",
370 "Failed to open %s.new",DFile
.c_str());
372 /* Write out all of the configuration directives by walking the
373 configuration tree */
374 const Configuration::Item
*Top
= Cnf
.Tree(0);
377 // Print the config entry
378 if (Top
->Value
.empty() == false)
379 Out
<< Top
->FullTag() + " \"" << Top
->Value
<< "\";" << endl
;
387 while (Top
!= 0 && Top
->Next
== 0)
395 link(DFile
.c_str(),string(DFile
+ '~').c_str());
396 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
397 return _error
->Errno("rename","Failed to rename %s.new to %s",
398 DFile
.c_str(),DFile
.c_str());
403 // WriteSourceList - Write an updated sourcelist /*{{{*/
404 // ---------------------------------------------------------------------
405 /* This reads the old source list and copies it into the new one. It
406 appends the new CDROM entires just after the first block of comments.
407 This places them first in the file. It also removes any old entries
408 that were the same. */
409 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
411 if (List
.empty() == true)
414 string File
= _config
->FindFile("Dir::Etc::sourcelist");
416 // Open the stream for reading
417 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
420 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
422 string NewFile
= File
+ ".new";
423 unlink(NewFile
.c_str());
424 ofstream
Out(NewFile
.c_str());
426 return _error
->Errno("ofstream::ofstream",
427 "Failed to open %s.new",File
.c_str());
429 // Create a short uri without the path
430 string ShortURI
= "cdrom:[" + Name
+ "]/";
431 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
442 while (F
.eof() == false)
444 F
.getline(Buffer
,sizeof(Buffer
));
446 if (F
.fail() && !F
.eof())
447 return _error
->Error(_("Line %u too long in source list %s."),
448 CurLine
,File
.c_str());
449 _strtabexpand(Buffer
,sizeof(Buffer
));
453 if (Buffer
[0] == '#' || Buffer
[0] == 0)
455 Out
<< Buffer
<< endl
;
461 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
463 string::size_type Space
= (*I
).find(' ');
464 if (Space
== string::npos
)
465 return _error
->Error("Internal error");
466 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
467 " " << string(*I
,Space
+1) << endl
;
475 const char *C
= Buffer
;
476 if (ParseQuoteWord(C
,cType
) == false ||
477 ParseQuoteWord(C
,URI
) == false)
479 Out
<< Buffer
<< endl
;
483 // Emit lines like this one
484 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
485 string(URI
,0,ShortURI
.length()) != ShortURI2
))
487 Out
<< Buffer
<< endl
;
492 // Just in case the file was empty
495 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
497 string::size_type Space
= (*I
).find(' ');
498 if (Space
== string::npos
)
499 return _error
->Error("Internal error");
501 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
502 " " << string(*I
,Space
+1) << endl
;
508 rename(File
.c_str(),string(File
+ '~').c_str());
509 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
510 return _error
->Errno("rename","Failed to rename %s.new to %s",
511 File
.c_str(),File
.c_str());
516 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
521 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
523 CDROM
= SafeGetCWD() + '/' + CDROM
;
528 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
530 log
->Update(msg
.str());
532 if (MountCdrom(CDROM
) == false)
533 return _error
->Error("Failed to mount the cdrom.");
535 // Hash the CD to get an ID
537 log
->Update(_("Identifying.. "));
540 if (IdentCdrom(CDROM
,ident
) == false)
549 ioprintf(msg
, "[%s]\n",ident
.c_str());
550 log
->Update(msg
.str());
554 Configuration Database
;
555 string DFile
= _config
->FindFile("Dir::State::cdroms");
556 if (FileExists(DFile
) == true)
558 if (ReadConfigFile(Database
,DFile
) == false)
559 return _error
->Error("Unable to read the cdrom database %s",
565 ioprintf(msg
, _("Stored label: %s\n"),
566 Database
.Find("CD::"+ident
).c_str());
567 log
->Update(msg
.str());
570 // Unmount and finish
571 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
574 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
581 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
586 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
588 CDROM
= SafeGetCWD() + '/' + CDROM
;
592 log
->SetTotal(STEP_LAST
);
594 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
595 log
->Update(msg
.str(), STEP_PREPARE
);
599 Configuration Database
;
600 string DFile
= _config
->FindFile("Dir::State::cdroms");
601 if (FileExists(DFile
) == true)
603 if (ReadConfigFile(Database
,DFile
) == false)
604 return _error
->Error("Unable to read the cdrom database %s",
608 // Unmount the CD and get the user to put in the one they want
609 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
612 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
617 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
618 if(!log
->ChangeCdrom()) {
624 // Mount the new CDROM
626 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
628 if (MountCdrom(CDROM
) == false)
629 return _error
->Error("Failed to mount the cdrom.");
632 // Hash the CD to get an ID
634 log
->Update(_("Identifying.. "), STEP_IDENT
);
636 if (IdentCdrom(CDROM
,ID
) == false)
644 log
->Update("["+ID
+"]\n");
645 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
648 // Get the CD structure
650 vector
<string
> SourceList
;
651 vector
<string
> SigList
;
652 vector
<string
> TransList
;
653 string StartDir
= SafeGetCWD();
655 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
662 chdir(StartDir
.c_str());
664 if (_config
->FindB("Debug::aptcdrom",false) == true)
666 cout
<< "I found (binary):" << endl
;
667 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
669 cout
<< "I found (source):" << endl
;
670 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
672 cout
<< "I found (Signatures):" << endl
;
673 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
677 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
680 DropBinaryArch(List
);
681 DropRepeats(List
,"Packages");
682 DropRepeats(SourceList
,"Sources");
683 DropRepeats(SigList
,"Release.gpg");
684 DropRepeats(TransList
,"");
687 ioprintf(msg
, _("Found %zu package indexes, %zu source indexes, "
688 "%zu translation indexes and %zu signatures\n"),
689 List
.size(), SourceList
.size(), TransList
.size(),
691 log
->Update(msg
.str(), STEP_SCAN
);
694 if (List
.empty() == true && SourceList
.empty() == true)
696 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
698 return _error
->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc or the wrong architecture?"));
701 // Check if the CD is in the database
703 if (Database
.Exists("CD::" + ID
) == false ||
704 _config
->FindB("APT::CDROM::Rename",false) == true)
706 // Try to use the CDs label if at all possible
707 if (InfoDir
.empty() == false &&
708 FileExists(InfoDir
+ "/info") == true)
710 ifstream
F(string(InfoDir
+ "/info").c_str());
714 if (Name
.empty() == false)
716 // Escape special characters
717 string::iterator J
= Name
.begin();
718 for (; J
!= Name
.end(); ++J
)
719 if (*J
== '"' || *J
== ']' || *J
== '[')
725 ioprintf(msg
, _("Found label '%s'\n"), Name
.c_str());
726 log
->Update(msg
.str());
728 Database
.Set("CD::" + ID
+ "::Label",Name
);
732 if (_config
->FindB("APT::CDROM::Rename",false) == true ||
733 Name
.empty() == true)
737 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
739 return _error
->Error("No disc name found and no way to ask for it");
743 if(!log
->AskCdromName(Name
)) {
747 cout
<< "Name: '" << Name
<< "'" << endl
;
749 if (Name
.empty() == false &&
750 Name
.find('"') == string::npos
&&
751 Name
.find('[') == string::npos
&&
752 Name
.find(']') == string::npos
)
754 log
->Update(_("That is not a valid name, try again.\n"));
759 Name
= Database
.Find("CD::" + ID
);
761 // Escape special characters
762 string::iterator J
= Name
.begin();
763 for (; J
!= Name
.end(); ++J
)
764 if (*J
== '"' || *J
== ']' || *J
== '[')
767 Database
.Set("CD::" + ID
,Name
);
771 ioprintf(msg
, _("This disc is called: \n'%s'\n"), Name
.c_str());
772 log
->Update(msg
.str());
773 log
->Update(_("Copying package lists..."), STEP_COPY
);
775 // take care of the signatures and copy them if they are ok
776 // (we do this before PackageCopy as it modifies "List" and "SourceList")
777 SigVerify SignVerify
;
778 SignVerify
.CopyAndVerify(CDROM
, Name
, SigList
, List
, SourceList
);
780 // Copy the package files to the state directory
783 TranslationsCopy TransCopy
;
784 if (Copy
.CopyPackages(CDROM
,Name
,List
, log
) == false ||
785 SrcCopy
.CopyPackages(CDROM
,Name
,SourceList
, log
) == false ||
786 TransCopy
.CopyTranslations(CDROM
,Name
,TransList
, log
) == false)
789 // reduce the List so that it takes less space in sources.list
790 ReduceSourcelist(CDROM
,List
);
791 ReduceSourcelist(CDROM
,SourceList
);
793 // Write the database and sourcelist
794 if (_config
->FindB("APT::cdrom::NoAct",false) == false)
796 if (WriteDatabase(Database
) == false)
800 log
->Update(_("Writing new source list\n"), STEP_WRITE
);
801 if (WriteSourceList(Name
,List
,false) == false ||
802 WriteSourceList(Name
,SourceList
,true) == false)
806 // Print the sourcelist entries
808 log
->Update(_("Source list entries for this disc are:\n"));
810 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
812 string::size_type Space
= (*I
).find(' ');
813 if (Space
== string::npos
)
815 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
817 return _error
->Error("Internal error");
823 msg
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
824 " " << string(*I
,Space
+1) << endl
;
825 log
->Update(msg
.str());
829 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
831 string::size_type Space
= (*I
).find(' ');
832 if (Space
== string::npos
)
834 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
836 return _error
->Error("Internal error");
841 msg
<< "deb-src cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
842 " " << string(*I
,Space
+1) << endl
;
843 log
->Update(msg
.str());
847 // Unmount and finish
848 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
850 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
857 pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/
858 : libudev_handle(NULL
)
865 pkgUdevCdromDevices::Dlopen() /*{{{*/
868 if(libudev_handle
!= NULL
)
871 // see if we can get libudev
872 void *h
= ::dlopen("libudev.so.0", RTLD_LAZY
);
876 // get the pointers to the udev structs
878 udev_new
= (udev
* (*)(void)) dlsym(h
, "udev_new");
879 udev_enumerate_add_match_property
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_property");
880 udev_enumerate_add_match_sysattr
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_sysattr");
881 udev_enumerate_scan_devices
= (int (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_scan_devices");
882 udev_enumerate_get_list_entry
= (udev_list_entry
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_list_entry");
883 udev_device_new_from_syspath
= (udev_device
* (*)(udev
*, const char*))dlsym(h
, "udev_device_new_from_syspath");
884 udev_enumerate_get_udev
= (udev
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_udev");
885 udev_list_entry_get_name
= (const char* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_name");
886 udev_device_get_devnode
= (const char* (*)(udev_device
*))dlsym(h
, "udev_device_get_devnode");
887 udev_enumerate_new
= (udev_enumerate
* (*)(udev
*))dlsym(h
, "udev_enumerate_new");
888 udev_list_entry_get_next
= (udev_list_entry
* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_next");
889 udev_device_get_property_value
= (const char* (*)(udev_device
*, const char *))dlsym(h
, "udev_device_get_property_value");
895 // convenience interface, this will just call ScanForRemovable
897 pkgUdevCdromDevices::Scan()
899 bool CdromOnly
= _config
->FindB("APT::cdrom::CdromOnly", true);
900 return ScanForRemovable(CdromOnly
);
905 pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly
)
907 vector
<CdromDevice
> cdrom_devices
;
908 struct udev_enumerate
*enumerate
;
909 struct udev_list_entry
*l
, *devices
;
910 struct udev
*udev_ctx
;
912 if(libudev_handle
== NULL
)
913 return cdrom_devices
;
915 udev_ctx
= udev_new();
916 enumerate
= udev_enumerate_new (udev_ctx
);
918 udev_enumerate_add_match_property(enumerate
, "ID_CDROM", "1");
920 udev_enumerate_add_match_sysattr(enumerate
, "removable", "1");
923 udev_enumerate_scan_devices (enumerate
);
924 devices
= udev_enumerate_get_list_entry (enumerate
);
925 for (l
= devices
; l
!= NULL
; l
= udev_list_entry_get_next (l
))
928 struct udev_device
*udevice
;
929 udevice
= udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate
), udev_list_entry_get_name (l
));
932 const char* devnode
= udev_device_get_devnode(udevice
);
934 // try fstab_dir first
936 const char* mp
= udev_device_get_property_value(udevice
, "FSTAB_DIR");
938 mountpath
= string(mp
);
940 mountpath
= FindMountPointForDevice(devnode
);
942 // fill in the struct
943 cdrom
.DeviceName
= string(devnode
);
944 if (mountpath
!= "") {
945 cdrom
.MountPath
= mountpath
;
946 string s
= string(mountpath
);
947 cdrom
.Mounted
= IsMounted(s
);
949 cdrom
.Mounted
= false;
950 cdrom
.MountPath
= "";
952 cdrom_devices
.push_back(cdrom
);
954 return cdrom_devices
;
958 pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/
960 if (libudev_handle
!= NULL
)
961 dlclose(libudev_handle
);