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 ||
85 stat("Packages.bz2",&Buf
) == 0 || stat("Packages.xz",&Buf
) == 0)
89 // Continue down if thorough is given
90 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
93 if (stat("Sources.xz",&Buf
) == 0 || stat("Sources.bz2",&Buf
) == 0 ||
94 stat("Sources.gz",&Buf
) == 0 || stat("Sources",&Buf
) == 0)
98 // Continue down if thorough is given
99 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
103 // see if we find translatin indexes
104 if (stat("i18n",&Buf
) == 0)
107 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
109 if(strstr(Dir
->d_name
,"Translation") != NULL
)
111 if (_config
->FindB("Debug::aptcdrom",false) == true)
112 std::clog
<< "found translations: " << Dir
->d_name
<< "\n";
113 string file
= Dir
->d_name
;
114 if(file
.substr(file
.size()-3,file
.size()) == ".gz" ||
115 file
.substr(file
.size()-3,file
.size()) == ".xz")
116 file
= file
.substr(0,file
.size()-3);
117 if(file
.substr(file
.size()-4,file
.size()) == ".bz2")
118 file
= file
.substr(0,file
.size()-4);
119 TransList
.push_back(CD
+"i18n/"+ file
);
128 return _error
->Errno("opendir","Unable to read %s",CD
.c_str());
130 // Run over the directory
131 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
134 if (strcmp(Dir
->d_name
,".") == 0 ||
135 strcmp(Dir
->d_name
,"..") == 0 ||
136 //strcmp(Dir->d_name,"source") == 0 ||
137 strcmp(Dir
->d_name
,".disk") == 0 ||
138 strcmp(Dir
->d_name
,"experimental") == 0 ||
139 strcmp(Dir
->d_name
,"binary-all") == 0 ||
140 strcmp(Dir
->d_name
,"debian-installer") == 0)
143 // See if the name is a sub directory
145 if (stat(Dir
->d_name
,&Buf
) != 0)
148 if (S_ISDIR(Buf
.st_mode
) == 0)
152 for (I
= 0; I
!= Depth
; I
++)
153 if (Inodes
[I
] == Buf
.st_ino
)
158 // Store the inodes weve seen
159 Inodes
[Depth
] = Buf
.st_ino
;
162 if (FindPackages(CD
+ Dir
->d_name
,List
,SList
,SigList
,TransList
,InfoDir
,log
,Depth
+1) == false)
165 if (chdir(CD
.c_str()) != 0)
167 _error
->Errno("chdir","Unable to change to %s", CD
.c_str());
175 return !_error
->PendingError();
178 // Score - We compute a 'score' for a path /*{{{*/
179 // ---------------------------------------------------------------------
180 /* Paths are scored based on how close they come to what I consider
181 normal. That is ones that have 'dist' 'stable' 'testing' will score
182 higher than ones without. */
183 int pkgCdrom::Score(string Path
)
186 if (Path
.find("stable/") != string::npos
)
188 if (Path
.find("/binary-") != string::npos
)
190 if (Path
.find("testing/") != string::npos
)
192 if (Path
.find("unstable/") != string::npos
)
194 if (Path
.find("/dists/") != string::npos
)
196 if (Path
.find("/main/") != string::npos
)
198 if (Path
.find("/contrib/") != string::npos
)
200 if (Path
.find("/non-free/") != string::npos
)
202 if (Path
.find("/non-US/") != string::npos
)
204 if (Path
.find("/source/") != string::npos
)
206 if (Path
.find("/debian/") != string::npos
)
209 // check for symlinks in the patch leading to the actual file
210 // a symlink gets a big penalty
212 string statPath
= flNotFile(Path
);
213 string cdromPath
= _config
->FindDir("Acquire::cdrom::mount");
214 while(statPath
!= cdromPath
&& statPath
!= "./") {
215 statPath
.resize(statPath
.size()-1); // remove the trailing '/'
216 if (lstat(statPath
.c_str(),&Buf
) == 0) {
217 if(S_ISLNK(Buf
.st_mode
)) {
222 statPath
= flNotFile(statPath
); // descent
228 // DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/
229 // ---------------------------------------------------------------------
230 /* Here we drop everything that is not this machines arch */
231 bool pkgCdrom::DropBinaryArch(vector
<string
> &List
)
234 for (unsigned int I
= 0; I
< List
.size(); I
++)
236 const char *Str
= List
[I
].c_str();
237 const char *Start
, *End
;
238 if ((Start
= strstr(Str
,"/binary-")) == 0)
241 // Between Start and End is the architecture
243 if ((End
= strstr(Start
,"/")) != 0 && Start
!= End
&&
244 APT::Configuration::checkArchitecture(string(Start
, End
)) == true)
245 continue; // okay, architecture is accepted
247 // not accepted -> Erase it
248 List
.erase(List
.begin() + I
);
249 --I
; // the next entry is at the same index after the erase
255 // DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
256 // ---------------------------------------------------------------------
257 /* Here we go and stat every file that we found and strip dup inodes. */
258 bool pkgCdrom::DropRepeats(vector
<string
> &List
,const char *Name
)
260 // Get a list of all the inodes
261 ino_t
*Inodes
= new ino_t
[List
.size()];
262 for (unsigned int I
= 0; I
!= List
.size(); I
++)
265 if (stat((List
[I
] + Name
).c_str(),&Buf
) != 0 &&
266 stat((List
[I
] + Name
+ ".gz").c_str(),&Buf
) != 0 &&
267 stat((List
[I
] + Name
+ ".bz2").c_str(),&Buf
) != 0 &&
268 stat((List
[I
] + Name
+ ".xz").c_str(),&Buf
) != 0)
269 _error
->Errno("stat","Failed to stat %s%s",List
[I
].c_str(),
271 Inodes
[I
] = Buf
.st_ino
;
274 if (_error
->PendingError() == true) {
280 for (unsigned int I
= 0; I
!= List
.size(); I
++)
282 for (unsigned int J
= I
+1; J
< List
.size(); J
++)
285 if (Inodes
[J
] != Inodes
[I
])
288 // We score the two paths.. and erase one
289 int ScoreA
= Score(List
[I
]);
290 int ScoreB
= Score(List
[J
]);
302 // Wipe erased entries
303 for (unsigned int I
= 0; I
< List
.size();)
305 if (List
[I
].empty() == false)
308 List
.erase(List
.begin()+I
);
314 // ReduceSourceList - Takes the path list and reduces it /*{{{*/
315 // ---------------------------------------------------------------------
316 /* This takes the list of source list expressed entires and collects
317 similar ones to form a single entry for each dist */
318 void pkgCdrom::ReduceSourcelist(string CD
,vector
<string
> &List
)
320 sort(List
.begin(),List
.end());
322 // Collect similar entries
323 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
326 string::size_type Space
= (*I
).find(' ');
327 if (Space
== string::npos
)
329 string::size_type SSpace
= (*I
).find(' ',Space
+ 1);
330 if (SSpace
== string::npos
)
333 string Word1
= string(*I
,Space
,SSpace
-Space
);
334 string Prefix
= string(*I
,0,Space
);
335 for (vector
<string
>::iterator J
= List
.begin(); J
!= I
; ++J
)
338 string::size_type Space2
= (*J
).find(' ');
339 if (Space2
== string::npos
)
341 string::size_type SSpace2
= (*J
).find(' ',Space2
+ 1);
342 if (SSpace2
== string::npos
)
345 if (string(*J
,0,Space2
) != Prefix
)
347 if (string(*J
,Space2
,SSpace2
-Space2
) != Word1
)
350 *J
+= string(*I
,SSpace
);
355 // Wipe erased entries
356 for (unsigned int I
= 0; I
< List
.size();)
358 if (List
[I
].empty() == false)
361 List
.erase(List
.begin()+I
);
365 // WriteDatabase - Write the CDROM Database file /*{{{*/
366 // ---------------------------------------------------------------------
367 /* We rewrite the configuration class associated with the cdrom database. */
368 bool pkgCdrom::WriteDatabase(Configuration
&Cnf
)
370 string DFile
= _config
->FindFile("Dir::State::cdroms");
371 string NewFile
= DFile
+ ".new";
373 unlink(NewFile
.c_str());
374 ofstream
Out(NewFile
.c_str());
376 return _error
->Errno("ofstream::ofstream",
377 "Failed to open %s.new",DFile
.c_str());
379 /* Write out all of the configuration directives by walking the
380 configuration tree */
381 const Configuration::Item
*Top
= Cnf
.Tree(0);
384 // Print the config entry
385 if (Top
->Value
.empty() == false)
386 Out
<< Top
->FullTag() + " \"" << Top
->Value
<< "\";" << endl
;
394 while (Top
!= 0 && Top
->Next
== 0)
402 link(DFile
.c_str(),string(DFile
+ '~').c_str());
403 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
404 return _error
->Errno("rename","Failed to rename %s.new to %s",
405 DFile
.c_str(),DFile
.c_str());
410 // WriteSourceList - Write an updated sourcelist /*{{{*/
411 // ---------------------------------------------------------------------
412 /* This reads the old source list and copies it into the new one. It
413 appends the new CDROM entires just after the first block of comments.
414 This places them first in the file. It also removes any old entries
415 that were the same. */
416 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
418 if (List
.empty() == true)
421 string File
= _config
->FindFile("Dir::Etc::sourcelist");
423 // Open the stream for reading
424 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
427 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
429 string NewFile
= File
+ ".new";
430 unlink(NewFile
.c_str());
431 ofstream
Out(NewFile
.c_str());
433 return _error
->Errno("ofstream::ofstream",
434 "Failed to open %s.new",File
.c_str());
436 // Create a short uri without the path
437 string ShortURI
= "cdrom:[" + Name
+ "]/";
438 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
449 while (F
.eof() == false)
451 F
.getline(Buffer
,sizeof(Buffer
));
453 if (F
.fail() && !F
.eof())
454 return _error
->Error(_("Line %u too long in source list %s."),
455 CurLine
,File
.c_str());
456 _strtabexpand(Buffer
,sizeof(Buffer
));
460 if (Buffer
[0] == '#' || Buffer
[0] == 0)
462 Out
<< Buffer
<< endl
;
468 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
470 string::size_type Space
= (*I
).find(' ');
471 if (Space
== string::npos
)
472 return _error
->Error("Internal error");
473 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
474 " " << string(*I
,Space
+1) << endl
;
482 const char *C
= Buffer
;
483 if (ParseQuoteWord(C
,cType
) == false ||
484 ParseQuoteWord(C
,URI
) == false)
486 Out
<< Buffer
<< endl
;
490 // Emit lines like this one
491 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
492 string(URI
,0,ShortURI
.length()) != ShortURI2
))
494 Out
<< Buffer
<< endl
;
499 // Just in case the file was empty
502 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
504 string::size_type Space
= (*I
).find(' ');
505 if (Space
== string::npos
)
506 return _error
->Error("Internal error");
508 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
509 " " << string(*I
,Space
+1) << endl
;
515 rename(File
.c_str(),string(File
+ '~').c_str());
516 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
517 return _error
->Errno("rename","Failed to rename %s.new to %s",
518 File
.c_str(),File
.c_str());
523 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
528 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
530 CDROM
= SafeGetCWD() + '/' + CDROM
;
535 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
537 log
->Update(msg
.str());
539 if (MountCdrom(CDROM
) == false)
540 return _error
->Error("Failed to mount the cdrom.");
542 // Hash the CD to get an ID
544 log
->Update(_("Identifying.. "));
547 if (IdentCdrom(CDROM
,ident
) == false)
556 ioprintf(msg
, "[%s]\n",ident
.c_str());
557 log
->Update(msg
.str());
561 Configuration Database
;
562 string DFile
= _config
->FindFile("Dir::State::cdroms");
563 if (FileExists(DFile
) == true)
565 if (ReadConfigFile(Database
,DFile
) == false)
566 return _error
->Error("Unable to read the cdrom database %s",
572 ioprintf(msg
, _("Stored label: %s\n"),
573 Database
.Find("CD::"+ident
).c_str());
574 log
->Update(msg
.str());
577 // Unmount and finish
578 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
581 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
588 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
593 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
595 CDROM
= SafeGetCWD() + '/' + CDROM
;
599 log
->SetTotal(STEP_LAST
);
601 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
602 log
->Update(msg
.str(), STEP_PREPARE
);
606 Configuration Database
;
607 string DFile
= _config
->FindFile("Dir::State::cdroms");
608 if (FileExists(DFile
) == true)
610 if (ReadConfigFile(Database
,DFile
) == false)
611 return _error
->Error("Unable to read the cdrom database %s",
615 // Unmount the CD and get the user to put in the one they want
616 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
619 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
624 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
625 if(!log
->ChangeCdrom()) {
631 // Mount the new CDROM
633 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
635 if (MountCdrom(CDROM
) == false)
636 return _error
->Error("Failed to mount the cdrom.");
639 // Hash the CD to get an ID
641 log
->Update(_("Identifying.. "), STEP_IDENT
);
643 if (IdentCdrom(CDROM
,ID
) == false)
651 log
->Update("["+ID
+"]\n");
652 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
655 // Get the CD structure
657 vector
<string
> SourceList
;
658 vector
<string
> SigList
;
659 vector
<string
> TransList
;
660 string StartDir
= SafeGetCWD();
662 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
669 chdir(StartDir
.c_str());
671 if (_config
->FindB("Debug::aptcdrom",false) == true)
673 cout
<< "I found (binary):" << endl
;
674 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
676 cout
<< "I found (source):" << endl
;
677 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
679 cout
<< "I found (Signatures):" << endl
;
680 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
684 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
687 DropBinaryArch(List
);
688 DropRepeats(List
,"Packages");
689 DropRepeats(SourceList
,"Sources");
690 DropRepeats(SigList
,"Release.gpg");
691 DropRepeats(TransList
,"");
694 ioprintf(msg
, _("Found %zu package indexes, %zu source indexes, "
695 "%zu translation indexes and %zu signatures\n"),
696 List
.size(), SourceList
.size(), TransList
.size(),
698 log
->Update(msg
.str(), STEP_SCAN
);
701 if (List
.empty() == true && SourceList
.empty() == true)
703 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
705 return _error
->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc or the wrong architecture?"));
708 // Check if the CD is in the database
710 if (Database
.Exists("CD::" + ID
) == false ||
711 _config
->FindB("APT::CDROM::Rename",false) == true)
713 // Try to use the CDs label if at all possible
714 if (InfoDir
.empty() == false &&
715 FileExists(InfoDir
+ "/info") == true)
717 ifstream
F(string(InfoDir
+ "/info").c_str());
721 if (Name
.empty() == false)
723 // Escape special characters
724 string::iterator J
= Name
.begin();
725 for (; J
!= Name
.end(); ++J
)
726 if (*J
== '"' || *J
== ']' || *J
== '[')
732 ioprintf(msg
, _("Found label '%s'\n"), Name
.c_str());
733 log
->Update(msg
.str());
735 Database
.Set("CD::" + ID
+ "::Label",Name
);
739 if (_config
->FindB("APT::CDROM::Rename",false) == true ||
740 Name
.empty() == true)
744 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
746 return _error
->Error("No disc name found and no way to ask for it");
750 if(!log
->AskCdromName(Name
)) {
754 cout
<< "Name: '" << Name
<< "'" << endl
;
756 if (Name
.empty() == false &&
757 Name
.find('"') == string::npos
&&
758 Name
.find('[') == string::npos
&&
759 Name
.find(']') == string::npos
)
761 log
->Update(_("That is not a valid name, try again.\n"));
766 Name
= Database
.Find("CD::" + ID
);
768 // Escape special characters
769 string::iterator J
= Name
.begin();
770 for (; J
!= Name
.end(); ++J
)
771 if (*J
== '"' || *J
== ']' || *J
== '[')
774 Database
.Set("CD::" + ID
,Name
);
778 ioprintf(msg
, _("This disc is called: \n'%s'\n"), Name
.c_str());
779 log
->Update(msg
.str());
780 log
->Update(_("Copying package lists..."), STEP_COPY
);
782 // take care of the signatures and copy them if they are ok
783 // (we do this before PackageCopy as it modifies "List" and "SourceList")
784 SigVerify SignVerify
;
785 SignVerify
.CopyAndVerify(CDROM
, Name
, SigList
, List
, SourceList
);
787 // Copy the package files to the state directory
790 TranslationsCopy TransCopy
;
791 if (Copy
.CopyPackages(CDROM
,Name
,List
, log
) == false ||
792 SrcCopy
.CopyPackages(CDROM
,Name
,SourceList
, log
) == false ||
793 TransCopy
.CopyTranslations(CDROM
,Name
,TransList
, log
) == false)
796 // reduce the List so that it takes less space in sources.list
797 ReduceSourcelist(CDROM
,List
);
798 ReduceSourcelist(CDROM
,SourceList
);
800 // Write the database and sourcelist
801 if (_config
->FindB("APT::cdrom::NoAct",false) == false)
803 if (WriteDatabase(Database
) == false)
807 log
->Update(_("Writing new source list\n"), STEP_WRITE
);
808 if (WriteSourceList(Name
,List
,false) == false ||
809 WriteSourceList(Name
,SourceList
,true) == false)
813 // Print the sourcelist entries
815 log
->Update(_("Source list entries for this disc are:\n"));
817 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
819 string::size_type Space
= (*I
).find(' ');
820 if (Space
== string::npos
)
822 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
824 return _error
->Error("Internal error");
830 msg
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
831 " " << string(*I
,Space
+1) << endl
;
832 log
->Update(msg
.str());
836 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
838 string::size_type Space
= (*I
).find(' ');
839 if (Space
== string::npos
)
841 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
843 return _error
->Error("Internal error");
848 msg
<< "deb-src cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
849 " " << string(*I
,Space
+1) << endl
;
850 log
->Update(msg
.str());
854 // Unmount and finish
855 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
857 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
864 pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/
865 : libudev_handle(NULL
)
872 pkgUdevCdromDevices::Dlopen() /*{{{*/
875 if(libudev_handle
!= NULL
)
878 // see if we can get libudev
879 void *h
= ::dlopen("libudev.so.0", RTLD_LAZY
);
883 // get the pointers to the udev structs
885 udev_new
= (udev
* (*)(void)) dlsym(h
, "udev_new");
886 udev_enumerate_add_match_property
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_property");
887 udev_enumerate_add_match_sysattr
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_sysattr");
888 udev_enumerate_scan_devices
= (int (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_scan_devices");
889 udev_enumerate_get_list_entry
= (udev_list_entry
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_list_entry");
890 udev_device_new_from_syspath
= (udev_device
* (*)(udev
*, const char*))dlsym(h
, "udev_device_new_from_syspath");
891 udev_enumerate_get_udev
= (udev
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_udev");
892 udev_list_entry_get_name
= (const char* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_name");
893 udev_device_get_devnode
= (const char* (*)(udev_device
*))dlsym(h
, "udev_device_get_devnode");
894 udev_enumerate_new
= (udev_enumerate
* (*)(udev
*))dlsym(h
, "udev_enumerate_new");
895 udev_list_entry_get_next
= (udev_list_entry
* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_next");
896 udev_device_get_property_value
= (const char* (*)(udev_device
*, const char *))dlsym(h
, "udev_device_get_property_value");
902 // convenience interface, this will just call ScanForRemovable
904 pkgUdevCdromDevices::Scan()
906 bool CdromOnly
= _config
->FindB("APT::cdrom::CdromOnly", true);
907 return ScanForRemovable(CdromOnly
);
912 pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly
)
914 vector
<CdromDevice
> cdrom_devices
;
915 struct udev_enumerate
*enumerate
;
916 struct udev_list_entry
*l
, *devices
;
917 struct udev
*udev_ctx
;
919 if(libudev_handle
== NULL
)
920 return cdrom_devices
;
922 udev_ctx
= udev_new();
923 enumerate
= udev_enumerate_new (udev_ctx
);
925 udev_enumerate_add_match_property(enumerate
, "ID_CDROM", "1");
927 udev_enumerate_add_match_sysattr(enumerate
, "removable", "1");
930 udev_enumerate_scan_devices (enumerate
);
931 devices
= udev_enumerate_get_list_entry (enumerate
);
932 for (l
= devices
; l
!= NULL
; l
= udev_list_entry_get_next (l
))
935 struct udev_device
*udevice
;
936 udevice
= udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate
), udev_list_entry_get_name (l
));
939 const char* devnode
= udev_device_get_devnode(udevice
);
941 // try fstab_dir first
943 const char* mp
= udev_device_get_property_value(udevice
, "FSTAB_DIR");
945 mountpath
= string(mp
);
947 mountpath
= FindMountPointForDevice(devnode
);
949 // fill in the struct
950 cdrom
.DeviceName
= string(devnode
);
951 if (mountpath
!= "") {
952 cdrom
.MountPath
= mountpath
;
953 string s
= string(mountpath
);
954 cdrom
.Mounted
= IsMounted(s
);
956 cdrom
.Mounted
= false;
957 cdrom
.MountPath
= "";
959 cdrom_devices
.push_back(cdrom
);
961 return cdrom_devices
;
965 pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/
967 if (libudev_handle
!= NULL
)
968 dlclose(libudev_handle
);