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 string Component
= string(*I
,SSpace
);
367 for (vector
<string
>::iterator J
= List
.begin(); J
!= I
; ++J
)
370 string::size_type Space2
= (*J
).find(' ');
371 if (Space2
== string::npos
)
373 string::size_type SSpace2
= (*J
).find(' ',Space2
+ 1);
374 if (SSpace2
== string::npos
)
377 if (string(*J
,0,Space2
) != Prefix
)
379 if (string(*J
,Space2
,SSpace2
-Space2
) != Word1
)
382 string Component2
= string(*J
, SSpace2
) + " ";
383 if (Component2
.find(Component
+ " ") == std::string::npos
)
389 // Wipe erased entries
390 for (unsigned int I
= 0; I
< List
.size();)
392 if (List
[I
].empty() == false)
395 List
.erase(List
.begin()+I
);
399 // WriteDatabase - Write the CDROM Database file /*{{{*/
400 // ---------------------------------------------------------------------
401 /* We rewrite the configuration class associated with the cdrom database. */
402 bool pkgCdrom::WriteDatabase(Configuration
&Cnf
)
404 string DFile
= _config
->FindFile("Dir::State::cdroms");
405 string NewFile
= DFile
+ ".new";
407 unlink(NewFile
.c_str());
408 ofstream
Out(NewFile
.c_str());
410 return _error
->Errno("ofstream::ofstream",
411 "Failed to open %s.new",DFile
.c_str());
413 /* Write out all of the configuration directives by walking the
414 configuration tree */
415 Cnf
.Dump(Out
, NULL
, "%f \"%v\";\n", false);
419 if (FileExists(DFile
) == true)
420 rename(DFile
.c_str(), string(DFile
+ '~').c_str());
421 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
422 return _error
->Errno("rename","Failed to rename %s.new to %s",
423 DFile
.c_str(),DFile
.c_str());
428 // WriteSourceList - Write an updated sourcelist /*{{{*/
429 // ---------------------------------------------------------------------
430 /* This reads the old source list and copies it into the new one. It
431 appends the new CDROM entires just after the first block of comments.
432 This places them first in the file. It also removes any old entries
433 that were the same. */
434 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
436 if (List
.empty() == true)
439 string File
= _config
->FindFile("Dir::Etc::sourcelist");
441 // Open the stream for reading
442 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
445 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
447 string NewFile
= File
+ ".new";
448 unlink(NewFile
.c_str());
449 ofstream
Out(NewFile
.c_str());
451 return _error
->Errno("ofstream::ofstream",
452 "Failed to open %s.new",File
.c_str());
454 // Create a short uri without the path
455 string ShortURI
= "cdrom:[" + Name
+ "]/";
456 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
467 while (F
.eof() == false)
469 F
.getline(Buffer
,sizeof(Buffer
));
471 if (F
.fail() && !F
.eof())
472 return _error
->Error(_("Line %u too long in source list %s."),
473 CurLine
,File
.c_str());
474 _strtabexpand(Buffer
,sizeof(Buffer
));
478 if (Buffer
[0] == '#' || Buffer
[0] == 0)
480 Out
<< Buffer
<< endl
;
486 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
488 string::size_type Space
= (*I
).find(' ');
489 if (Space
== string::npos
)
490 return _error
->Error("Internal error");
491 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
492 " " << string(*I
,Space
+1) << endl
;
500 const char *C
= Buffer
;
501 if (ParseQuoteWord(C
,cType
) == false ||
502 ParseQuoteWord(C
,URI
) == false)
504 Out
<< Buffer
<< endl
;
508 // Emit lines like this one
509 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
510 string(URI
,0,ShortURI
.length()) != ShortURI2
))
512 Out
<< Buffer
<< endl
;
517 // Just in case the file was empty
520 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
522 string::size_type Space
= (*I
).find(' ');
523 if (Space
== string::npos
)
524 return _error
->Error("Internal error");
526 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
527 " " << string(*I
,Space
+1) << endl
;
533 rename(File
.c_str(),string(File
+ '~').c_str());
534 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
535 return _error
->Errno("rename","Failed to rename %s.new to %s",
536 File
.c_str(),File
.c_str());
541 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
546 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
548 CDROM
= SafeGetCWD() + '/' + CDROM
;
553 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
555 log
->Update(msg
.str());
557 if (MountCdrom(CDROM
) == false)
558 return _error
->Error("Failed to mount the cdrom.");
560 // Hash the CD to get an ID
562 log
->Update(_("Identifying.. "));
565 if (IdentCdrom(CDROM
,ident
) == false)
574 ioprintf(msg
, "[%s]\n",ident
.c_str());
575 log
->Update(msg
.str());
579 Configuration Database
;
580 string DFile
= _config
->FindFile("Dir::State::cdroms");
581 if (FileExists(DFile
) == true)
583 if (ReadConfigFile(Database
,DFile
) == false)
584 return _error
->Error("Unable to read the cdrom database %s",
590 ioprintf(msg
, _("Stored label: %s\n"),
591 Database
.Find("CD::"+ident
).c_str());
592 log
->Update(msg
.str());
595 // Unmount and finish
596 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
599 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
606 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
611 string CDROM
= _config
->FindDir("Acquire::cdrom::mount");
613 CDROM
= SafeGetCWD() + '/' + CDROM
;
617 log
->SetTotal(STEP_LAST
);
619 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
620 log
->Update(msg
.str(), STEP_PREPARE
);
624 Configuration Database
;
625 string DFile
= _config
->FindFile("Dir::State::cdroms");
626 if (FileExists(DFile
) == true)
628 if (ReadConfigFile(Database
,DFile
) == false)
629 return _error
->Error("Unable to read the cdrom database %s",
633 // Unmount the CD and get the user to put in the one they want
634 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
637 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
642 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
643 if(!log
->ChangeCdrom()) {
649 // Mount the new CDROM
651 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
653 if (MountCdrom(CDROM
) == false)
654 return _error
->Error("Failed to mount the cdrom.");
657 // Hash the CD to get an ID
659 log
->Update(_("Identifying.. "), STEP_IDENT
);
661 if (IdentCdrom(CDROM
,ID
) == false)
669 log
->Update("["+ID
+"]\n");
670 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
673 // Get the CD structure
675 vector
<string
> SourceList
;
676 vector
<string
> SigList
;
677 vector
<string
> TransList
;
678 string StartDir
= SafeGetCWD();
680 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
687 if (chdir(StartDir
.c_str()) != 0)
688 return _error
->Errno("chdir","Unable to change to %s", StartDir
.c_str());
690 if (_config
->FindB("Debug::aptcdrom",false) == true)
692 cout
<< "I found (binary):" << endl
;
693 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); ++I
)
695 cout
<< "I found (source):" << endl
;
696 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); ++I
)
698 cout
<< "I found (Signatures):" << endl
;
699 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); ++I
)
703 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
706 DropBinaryArch(List
);
707 DropRepeats(List
,"Packages");
708 DropRepeats(SourceList
,"Sources");
709 // FIXME: We ignore stat() errors here as we usually have only one of those in use
710 // This has little potencial to drop 'valid' stat() errors as we know that one of these
711 // files need to exist, but it would be better if we would check it here
712 _error
->PushToStack();
713 DropRepeats(SigList
,"Release.gpg");
714 DropRepeats(SigList
,"InRelease");
715 _error
->RevertToStack();
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
);