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 _config
->Dump(Out
, NULL
, "%f \"%v\";\n", false);
416 if (FileExists(DFile
) == true && link(DFile
.c_str(),string(DFile
+ '~').c_str()) != 0)
417 return _error
->Errno("link", "Failed to link %s to %s~", DFile
.c_str(), DFile
.c_str());
418 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
419 return _error
->Errno("rename","Failed to rename %s.new to %s",
420 DFile
.c_str(),DFile
.c_str());
425 // WriteSourceList - Write an updated sourcelist /*{{{*/
426 // ---------------------------------------------------------------------
427 /* This reads the old source list and copies it into the new one. It
428 appends the new CDROM entires just after the first block of comments.
429 This places them first in the file. It also removes any old entries
430 that were the same. */
431 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
433 if (List
.empty() == true)
436 string File
= _config
->FindFile("Dir::Etc::sourcelist");
438 // Open the stream for reading
439 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
442 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
444 string NewFile
= File
+ ".new";
445 unlink(NewFile
.c_str());
446 ofstream
Out(NewFile
.c_str());
448 return _error
->Errno("ofstream::ofstream",
449 "Failed to open %s.new",File
.c_str());
451 // Create a short uri without the path
452 string ShortURI
= "cdrom:[" + Name
+ "]/";
453 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
464 while (F
.eof() == false)
466 F
.getline(Buffer
,sizeof(Buffer
));
468 if (F
.fail() && !F
.eof())
469 return _error
->Error(_("Line %u too long in source list %s."),
470 CurLine
,File
.c_str());
471 _strtabexpand(Buffer
,sizeof(Buffer
));
475 if (Buffer
[0] == '#' || Buffer
[0] == 0)
477 Out
<< Buffer
<< endl
;
483 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
485 string::size_type Space
= (*I
).find(' ');
486 if (Space
== string::npos
)
487 return _error
->Error("Internal error");
488 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
489 " " << string(*I
,Space
+1) << endl
;
497 const char *C
= Buffer
;
498 if (ParseQuoteWord(C
,cType
) == false ||
499 ParseQuoteWord(C
,URI
) == false)
501 Out
<< Buffer
<< endl
;
505 // Emit lines like this one
506 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
507 string(URI
,0,ShortURI
.length()) != ShortURI2
))
509 Out
<< Buffer
<< endl
;
514 // Just in case the file was empty
517 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
519 string::size_type Space
= (*I
).find(' ');
520 if (Space
== string::npos
)
521 return _error
->Error("Internal error");
523 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
524 " " << string(*I
,Space
+1) << endl
;
530 rename(File
.c_str(),string(File
+ '~').c_str());
531 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
532 return _error
->Errno("rename","Failed to rename %s.new to %s",
533 File
.c_str(),File
.c_str());
538 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
543 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
545 CDROM
= SafeGetCWD() + '/' + CDROM
;
550 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
552 log
->Update(msg
.str());
554 if (MountCdrom(CDROM
) == false)
555 return _error
->Error("Failed to mount the cdrom.");
557 // Hash the CD to get an ID
559 log
->Update(_("Identifying.. "));
562 if (IdentCdrom(CDROM
,ident
) == false)
571 ioprintf(msg
, "[%s]\n",ident
.c_str());
572 log
->Update(msg
.str());
576 Configuration Database
;
577 string DFile
= _config
->FindFile("Dir::State::cdroms");
578 if (FileExists(DFile
) == true)
580 if (ReadConfigFile(Database
,DFile
) == false)
581 return _error
->Error("Unable to read the cdrom database %s",
587 ioprintf(msg
, _("Stored label: %s\n"),
588 Database
.Find("CD::"+ident
).c_str());
589 log
->Update(msg
.str());
592 // Unmount and finish
593 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
596 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
603 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
608 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
610 CDROM
= SafeGetCWD() + '/' + CDROM
;
614 log
->SetTotal(STEP_LAST
);
616 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
617 log
->Update(msg
.str(), STEP_PREPARE
);
621 Configuration Database
;
622 string DFile
= _config
->FindFile("Dir::State::cdroms");
623 if (FileExists(DFile
) == true)
625 if (ReadConfigFile(Database
,DFile
) == false)
626 return _error
->Error("Unable to read the cdrom database %s",
630 // Unmount the CD and get the user to put in the one they want
631 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
634 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
639 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
640 if(!log
->ChangeCdrom()) {
646 // Mount the new CDROM
648 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
650 if (MountCdrom(CDROM
) == false)
651 return _error
->Error("Failed to mount the cdrom.");
654 // Hash the CD to get an ID
656 log
->Update(_("Identifying.. "), STEP_IDENT
);
658 if (IdentCdrom(CDROM
,ID
) == false)
666 log
->Update("["+ID
+"]\n");
667 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
670 // Get the CD structure
672 vector
<string
> SourceList
;
673 vector
<string
> SigList
;
674 vector
<string
> TransList
;
675 string StartDir
= SafeGetCWD();
677 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
684 if (chdir(StartDir
.c_str()) != 0)
685 return _error
->Errno("chdir","Unable to change to %s", StartDir
.c_str());
687 if (_config
->FindB("Debug::aptcdrom",false) == true)
689 cout
<< "I found (binary):" << endl
;
690 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
692 cout
<< "I found (source):" << endl
;
693 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
695 cout
<< "I found (Signatures):" << endl
;
696 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
700 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
703 DropBinaryArch(List
);
704 DropRepeats(List
,"Packages");
705 DropRepeats(SourceList
,"Sources");
706 // FIXME: We ignore stat() errors here as we usually have only one of those in use
707 // This has little potencial to drop 'valid' stat() errors as we know that one of these
708 // files need to exist, but it would be better if we would check it here
709 _error
->PushToStack();
710 DropRepeats(SigList
,"Release.gpg");
711 DropRepeats(SigList
,"InRelease");
712 _error
->RevertToStack();
713 DropRepeats(TransList
,"");
716 ioprintf(msg
, _("Found %zu package indexes, %zu source indexes, "
717 "%zu translation indexes and %zu signatures\n"),
718 List
.size(), SourceList
.size(), TransList
.size(),
720 log
->Update(msg
.str(), STEP_SCAN
);
723 if (List
.empty() == true && SourceList
.empty() == true)
725 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
727 return _error
->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc or the wrong architecture?"));
730 // Check if the CD is in the database
732 if (Database
.Exists("CD::" + ID
) == false ||
733 _config
->FindB("APT::CDROM::Rename",false) == true)
735 // Try to use the CDs label if at all possible
736 if (InfoDir
.empty() == false &&
737 FileExists(InfoDir
+ "/info") == true)
739 ifstream
F(string(InfoDir
+ "/info").c_str());
743 if (Name
.empty() == false)
745 // Escape special characters
746 string::iterator J
= Name
.begin();
747 for (; J
!= Name
.end(); ++J
)
748 if (*J
== '"' || *J
== ']' || *J
== '[')
754 ioprintf(msg
, _("Found label '%s'\n"), Name
.c_str());
755 log
->Update(msg
.str());
757 Database
.Set("CD::" + ID
+ "::Label",Name
);
761 if (_config
->FindB("APT::CDROM::Rename",false) == true ||
762 Name
.empty() == true)
766 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
768 return _error
->Error("No disc name found and no way to ask for it");
772 if(!log
->AskCdromName(Name
)) {
776 cout
<< "Name: '" << Name
<< "'" << endl
;
778 if (Name
.empty() == false &&
779 Name
.find('"') == string::npos
&&
780 Name
.find('[') == string::npos
&&
781 Name
.find(']') == string::npos
)
783 log
->Update(_("That is not a valid name, try again.\n"));
788 Name
= Database
.Find("CD::" + ID
);
790 // Escape special characters
791 string::iterator J
= Name
.begin();
792 for (; J
!= Name
.end(); ++J
)
793 if (*J
== '"' || *J
== ']' || *J
== '[')
796 Database
.Set("CD::" + ID
,Name
);
800 ioprintf(msg
, _("This disc is called: \n'%s'\n"), Name
.c_str());
801 log
->Update(msg
.str());
802 log
->Update(_("Copying package lists..."), STEP_COPY
);
804 // take care of the signatures and copy them if they are ok
805 // (we do this before PackageCopy as it modifies "List" and "SourceList")
806 SigVerify SignVerify
;
807 SignVerify
.CopyAndVerify(CDROM
, Name
, SigList
, List
, SourceList
);
809 // Copy the package files to the state directory
812 TranslationsCopy TransCopy
;
813 if (Copy
.CopyPackages(CDROM
,Name
,List
, log
) == false ||
814 SrcCopy
.CopyPackages(CDROM
,Name
,SourceList
, log
) == false ||
815 TransCopy
.CopyTranslations(CDROM
,Name
,TransList
, log
) == false)
818 // reduce the List so that it takes less space in sources.list
819 ReduceSourcelist(CDROM
,List
);
820 ReduceSourcelist(CDROM
,SourceList
);
822 // Write the database and sourcelist
823 if (_config
->FindB("APT::cdrom::NoAct",false) == false)
825 if (WriteDatabase(Database
) == false)
829 log
->Update(_("Writing new source list\n"), STEP_WRITE
);
830 if (WriteSourceList(Name
,List
,false) == false ||
831 WriteSourceList(Name
,SourceList
,true) == false)
835 // Print the sourcelist entries
837 log
->Update(_("Source list entries for this disc are:\n"));
839 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
841 string::size_type Space
= (*I
).find(' ');
842 if (Space
== string::npos
)
844 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
846 return _error
->Error("Internal error");
852 msg
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
853 " " << string(*I
,Space
+1) << endl
;
854 log
->Update(msg
.str());
858 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
860 string::size_type Space
= (*I
).find(' ');
861 if (Space
== string::npos
)
863 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
865 return _error
->Error("Internal error");
870 msg
<< "deb-src cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
871 " " << string(*I
,Space
+1) << endl
;
872 log
->Update(msg
.str());
876 // Unmount and finish
877 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
879 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
886 pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/
887 : libudev_handle(NULL
)
894 pkgUdevCdromDevices::Dlopen() /*{{{*/
897 if(libudev_handle
!= NULL
)
900 // see if we can get libudev
901 void *h
= ::dlopen("libudev.so.0", RTLD_LAZY
);
905 // get the pointers to the udev structs
907 udev_new
= (udev
* (*)(void)) dlsym(h
, "udev_new");
908 udev_enumerate_add_match_property
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_property");
909 udev_enumerate_add_match_sysattr
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_sysattr");
910 udev_enumerate_scan_devices
= (int (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_scan_devices");
911 udev_enumerate_get_list_entry
= (udev_list_entry
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_list_entry");
912 udev_device_new_from_syspath
= (udev_device
* (*)(udev
*, const char*))dlsym(h
, "udev_device_new_from_syspath");
913 udev_enumerate_get_udev
= (udev
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_udev");
914 udev_list_entry_get_name
= (const char* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_name");
915 udev_device_get_devnode
= (const char* (*)(udev_device
*))dlsym(h
, "udev_device_get_devnode");
916 udev_enumerate_new
= (udev_enumerate
* (*)(udev
*))dlsym(h
, "udev_enumerate_new");
917 udev_list_entry_get_next
= (udev_list_entry
* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_next");
918 udev_device_get_property_value
= (const char* (*)(udev_device
*, const char *))dlsym(h
, "udev_device_get_property_value");
924 // convenience interface, this will just call ScanForRemovable
926 pkgUdevCdromDevices::Scan()
928 bool CdromOnly
= _config
->FindB("APT::cdrom::CdromOnly", true);
929 return ScanForRemovable(CdromOnly
);
934 pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly
)
936 vector
<CdromDevice
> cdrom_devices
;
937 struct udev_enumerate
*enumerate
;
938 struct udev_list_entry
*l
, *devices
;
939 struct udev
*udev_ctx
;
941 if(libudev_handle
== NULL
)
942 return cdrom_devices
;
944 udev_ctx
= udev_new();
945 enumerate
= udev_enumerate_new (udev_ctx
);
947 udev_enumerate_add_match_property(enumerate
, "ID_CDROM", "1");
949 udev_enumerate_add_match_sysattr(enumerate
, "removable", "1");
952 udev_enumerate_scan_devices (enumerate
);
953 devices
= udev_enumerate_get_list_entry (enumerate
);
954 for (l
= devices
; l
!= NULL
; l
= udev_list_entry_get_next (l
))
957 struct udev_device
*udevice
;
958 udevice
= udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate
), udev_list_entry_get_name (l
));
961 const char* devnode
= udev_device_get_devnode(udevice
);
963 // try fstab_dir first
965 const char* mp
= udev_device_get_property_value(udevice
, "FSTAB_DIR");
967 mountpath
= string(mp
);
969 mountpath
= FindMountPointForDevice(devnode
);
971 // fill in the struct
972 cdrom
.DeviceName
= string(devnode
);
973 if (mountpath
!= "") {
974 cdrom
.MountPath
= mountpath
;
975 string s
= string(mountpath
);
976 cdrom
.Mounted
= IsMounted(s
);
978 cdrom
.Mounted
= false;
979 cdrom
.MountPath
= "";
981 cdrom_devices
.push_back(cdrom
);
983 return cdrom_devices
;
987 pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/
989 if (libudev_handle
!= NULL
)
990 dlclose(libudev_handle
);