4 #include<apt-pkg/init.h>
5 #include<apt-pkg/error.h>
6 #include<apt-pkg/cdromutl.h>
7 #include<apt-pkg/strutl.h>
8 #include<apt-pkg/cdrom.h>
9 #include<apt-pkg/aptconfiguration.h>
23 #include "indexcopy.h"
27 // FindPackages - Find the package files on the CDROM /*{{{*/
28 // ---------------------------------------------------------------------
29 /* We look over the cdrom for package files. This is a recursive
30 search that short circuits when it his a package file in the dir.
31 This speeds it up greatly as the majority of the size is in the
33 bool pkgCdrom::FindPackages(string CD
,
35 vector
<string
> &SList
,
36 vector
<string
> &SigList
,
37 vector
<string
> &TransList
,
38 string
&InfoDir
, pkgCdromStatus
*log
,
41 static ino_t Inodes
[9];
44 // if we have a look we "pulse" now
51 if (CD
[CD
.length()-1] != '/')
54 if (chdir(CD
.c_str()) != 0)
55 return _error
->Errno("chdir","Unable to change to %s",CD
.c_str());
57 // Look for a .disk subdirectory
59 if (stat(".disk",&Buf
) == 0)
61 if (InfoDir
.empty() == true)
62 InfoDir
= CD
+ ".disk/";
65 // Don't look into directories that have been marked to ingore.
66 if (stat(".aptignr",&Buf
) == 0)
70 /* Check _first_ for a signature file as apt-cdrom assumes that all files
71 under a Packages/Source file are in control of that file and stops
74 if (stat("Release.gpg",&Buf
) == 0)
76 SigList
.push_back(CD
);
78 /* Aha! We found some package files. We assume that everything under
79 this dir is controlled by those package files so we don't look down
81 if (stat("Packages",&Buf
) == 0 || stat("Packages.gz",&Buf
) == 0)
85 // Continue down if thorough is given
86 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
89 if (stat("Sources.gz",&Buf
) == 0 || stat("Sources",&Buf
) == 0)
93 // Continue down if thorough is given
94 if (_config
->FindB("APT::CDROM::Thorough",false) == false)
98 // see if we find translatin indexes
99 if (stat("i18n",&Buf
) == 0)
102 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
104 if(strstr(Dir
->d_name
,"Translation") != NULL
)
106 if (_config
->FindB("Debug::aptcdrom",false) == true)
107 std::clog
<< "found translations: " << Dir
->d_name
<< "\n";
108 string file
= Dir
->d_name
;
109 if(file
.substr(file
.size()-3,file
.size()) == ".gz")
110 file
= file
.substr(0,file
.size()-3);
111 TransList
.push_back(CD
+"i18n/"+ file
);
120 return _error
->Errno("opendir","Unable to read %s",CD
.c_str());
122 // Run over the directory
123 for (struct dirent
*Dir
= readdir(D
); Dir
!= 0; Dir
= readdir(D
))
126 if (strcmp(Dir
->d_name
,".") == 0 ||
127 strcmp(Dir
->d_name
,"..") == 0 ||
128 //strcmp(Dir->d_name,"source") == 0 ||
129 strcmp(Dir
->d_name
,".disk") == 0 ||
130 strcmp(Dir
->d_name
,"experimental") == 0 ||
131 strcmp(Dir
->d_name
,"binary-all") == 0 ||
132 strcmp(Dir
->d_name
,"debian-installer") == 0)
135 // See if the name is a sub directory
137 if (stat(Dir
->d_name
,&Buf
) != 0)
140 if (S_ISDIR(Buf
.st_mode
) == 0)
144 for (I
= 0; I
!= Depth
; I
++)
145 if (Inodes
[I
] == Buf
.st_ino
)
150 // Store the inodes weve seen
151 Inodes
[Depth
] = Buf
.st_ino
;
154 if (FindPackages(CD
+ Dir
->d_name
,List
,SList
,SigList
,TransList
,InfoDir
,log
,Depth
+1) == false)
157 if (chdir(CD
.c_str()) != 0)
158 return _error
->Errno("chdir","Unable to change to %s",CD
.c_str());
163 return !_error
->PendingError();
166 // Score - We compute a 'score' for a path /*{{{*/
167 // ---------------------------------------------------------------------
168 /* Paths are scored based on how close they come to what I consider
169 normal. That is ones that have 'dist' 'stable' 'testing' will score
170 higher than ones without. */
171 int pkgCdrom::Score(string Path
)
174 if (Path
.find("stable/") != string::npos
)
176 if (Path
.find("/binary-") != string::npos
)
178 if (Path
.find("testing/") != string::npos
)
180 if (Path
.find("unstable/") != string::npos
)
182 if (Path
.find("/dists/") != string::npos
)
184 if (Path
.find("/main/") != string::npos
)
186 if (Path
.find("/contrib/") != string::npos
)
188 if (Path
.find("/non-free/") != string::npos
)
190 if (Path
.find("/non-US/") != string::npos
)
192 if (Path
.find("/source/") != string::npos
)
194 if (Path
.find("/debian/") != string::npos
)
197 // check for symlinks in the patch leading to the actual file
198 // a symlink gets a big penalty
200 string statPath
= flNotFile(Path
);
201 string cdromPath
= _config
->FindDir("Acquire::cdrom::mount","/cdrom/");
202 while(statPath
!= cdromPath
&& statPath
!= "./") {
203 statPath
.resize(statPath
.size()-1); // remove the trailing '/'
204 if (lstat(statPath
.c_str(),&Buf
) == 0) {
205 if(S_ISLNK(Buf
.st_mode
)) {
210 statPath
= flNotFile(statPath
); // descent
216 // DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/
217 // ---------------------------------------------------------------------
218 /* Here we drop everything that is not this machines arch */
219 bool pkgCdrom::DropBinaryArch(vector
<string
> &List
)
222 for (unsigned int I
= 0; I
< List
.size(); I
++)
224 const char *Str
= List
[I
].c_str();
225 const char *Start
, *End
;
226 if ((Start
= strstr(Str
,"/binary-")) == 0)
229 // Between Start and End is the architecture
231 if ((End
= strstr(Start
,"/")) != 0 && Start
!= End
&&
232 APT::Configuration::checkArchitecture(string(Start
, End
)) == true)
233 continue; // okay, architecture is accepted
235 // not accepted -> Erase it
236 List
.erase(List
.begin() + I
);
237 --I
; // the next entry is at the same index after the erase
243 // DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
244 // ---------------------------------------------------------------------
245 /* Here we go and stat every file that we found and strip dup inodes. */
246 bool pkgCdrom::DropRepeats(vector
<string
> &List
,const char *Name
)
248 // Get a list of all the inodes
249 ino_t
*Inodes
= new ino_t
[List
.size()];
250 for (unsigned int I
= 0; I
!= List
.size(); I
++)
253 if (stat((List
[I
] + Name
).c_str(),&Buf
) != 0 &&
254 stat((List
[I
] + Name
+ ".gz").c_str(),&Buf
) != 0)
255 _error
->Errno("stat","Failed to stat %s%s",List
[I
].c_str(),
257 Inodes
[I
] = Buf
.st_ino
;
260 if (_error
->PendingError() == true)
264 for (unsigned int I
= 0; I
!= List
.size(); I
++)
266 for (unsigned int J
= I
+1; J
< List
.size(); J
++)
269 if (Inodes
[J
] != Inodes
[I
])
272 // We score the two paths.. and erase one
273 int ScoreA
= Score(List
[I
]);
274 int ScoreB
= Score(List
[J
]);
286 // Wipe erased entries
287 for (unsigned int I
= 0; I
< List
.size();)
289 if (List
[I
].empty() == false)
292 List
.erase(List
.begin()+I
);
298 // ReduceSourceList - Takes the path list and reduces it /*{{{*/
299 // ---------------------------------------------------------------------
300 /* This takes the list of source list expressed entires and collects
301 similar ones to form a single entry for each dist */
302 void pkgCdrom::ReduceSourcelist(string CD
,vector
<string
> &List
)
304 sort(List
.begin(),List
.end());
306 // Collect similar entries
307 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
310 string::size_type Space
= (*I
).find(' ');
311 if (Space
== string::npos
)
313 string::size_type SSpace
= (*I
).find(' ',Space
+ 1);
314 if (SSpace
== string::npos
)
317 string Word1
= string(*I
,Space
,SSpace
-Space
);
318 string Prefix
= string(*I
,0,Space
);
319 for (vector
<string
>::iterator J
= List
.begin(); J
!= I
; J
++)
322 string::size_type Space2
= (*J
).find(' ');
323 if (Space2
== string::npos
)
325 string::size_type SSpace2
= (*J
).find(' ',Space2
+ 1);
326 if (SSpace2
== string::npos
)
329 if (string(*J
,0,Space2
) != Prefix
)
331 if (string(*J
,Space2
,SSpace2
-Space2
) != Word1
)
334 *J
+= string(*I
,SSpace
);
339 // Wipe erased entries
340 for (unsigned int I
= 0; I
< List
.size();)
342 if (List
[I
].empty() == false)
345 List
.erase(List
.begin()+I
);
349 // WriteDatabase - Write the CDROM Database file /*{{{*/
350 // ---------------------------------------------------------------------
351 /* We rewrite the configuration class associated with the cdrom database. */
352 bool pkgCdrom::WriteDatabase(Configuration
&Cnf
)
354 string DFile
= _config
->FindFile("Dir::State::cdroms");
355 string NewFile
= DFile
+ ".new";
357 unlink(NewFile
.c_str());
358 ofstream
Out(NewFile
.c_str());
360 return _error
->Errno("ofstream::ofstream",
361 "Failed to open %s.new",DFile
.c_str());
363 /* Write out all of the configuration directives by walking the
364 configuration tree */
365 const Configuration::Item
*Top
= Cnf
.Tree(0);
368 // Print the config entry
369 if (Top
->Value
.empty() == false)
370 Out
<< Top
->FullTag() + " \"" << Top
->Value
<< "\";" << endl
;
378 while (Top
!= 0 && Top
->Next
== 0)
386 link(DFile
.c_str(),string(DFile
+ '~').c_str());
387 if (rename(NewFile
.c_str(),DFile
.c_str()) != 0)
388 return _error
->Errno("rename","Failed to rename %s.new to %s",
389 DFile
.c_str(),DFile
.c_str());
394 // WriteSourceList - Write an updated sourcelist /*{{{*/
395 // ---------------------------------------------------------------------
396 /* This reads the old source list and copies it into the new one. It
397 appends the new CDROM entires just after the first block of comments.
398 This places them first in the file. It also removes any old entries
399 that were the same. */
400 bool pkgCdrom::WriteSourceList(string Name
,vector
<string
> &List
,bool Source
)
402 if (List
.size() == 0)
405 string File
= _config
->FindFile("Dir::Etc::sourcelist");
407 // Open the stream for reading
408 ifstream
F((FileExists(File
)?File
.c_str():"/dev/null"),
411 return _error
->Errno("ifstream::ifstream","Opening %s",File
.c_str());
413 string NewFile
= File
+ ".new";
414 unlink(NewFile
.c_str());
415 ofstream
Out(NewFile
.c_str());
417 return _error
->Errno("ofstream::ofstream",
418 "Failed to open %s.new",File
.c_str());
420 // Create a short uri without the path
421 string ShortURI
= "cdrom:[" + Name
+ "]/";
422 string ShortURI2
= "cdrom:" + Name
+ "/"; // For Compatibility
433 while (F
.eof() == false)
435 F
.getline(Buffer
,sizeof(Buffer
));
437 if (F
.fail() && !F
.eof())
438 return _error
->Error(_("Line %u too long in source list %s."),
439 CurLine
,File
.c_str());
440 _strtabexpand(Buffer
,sizeof(Buffer
));
444 if (Buffer
[0] == '#' || Buffer
[0] == 0)
446 Out
<< Buffer
<< endl
;
452 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
454 string::size_type Space
= (*I
).find(' ');
455 if (Space
== string::npos
)
456 return _error
->Error("Internal error");
457 Out
<< Type
<< " cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
458 " " << string(*I
,Space
+1) << endl
;
466 const char *C
= Buffer
;
467 if (ParseQuoteWord(C
,cType
) == false ||
468 ParseQuoteWord(C
,URI
) == false)
470 Out
<< Buffer
<< endl
;
474 // Emit lines like this one
475 if (cType
!= Type
|| (string(URI
,0,ShortURI
.length()) != ShortURI
&&
476 string(URI
,0,ShortURI
.length()) != ShortURI2
))
478 Out
<< Buffer
<< endl
;
483 // Just in case the file was empty
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");
492 Out
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
493 " " << string(*I
,Space
+1) << endl
;
499 rename(File
.c_str(),string(File
+ '~').c_str());
500 if (rename(NewFile
.c_str(),File
.c_str()) != 0)
501 return _error
->Errno("rename","Failed to rename %s.new to %s",
502 File
.c_str(),File
.c_str());
507 bool pkgCdrom::Ident(string
&ident
, pkgCdromStatus
*log
) /*{{{*/
512 string CDROM
= _config
->FindDir("Acquire::cdrom::mount","/cdrom/");
514 CDROM
= SafeGetCWD() + '/' + CDROM
;
518 ioprintf(msg
, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
520 log
->Update(msg
.str());
522 if (MountCdrom(CDROM
) == false)
523 return _error
->Error("Failed to mount the cdrom.");
525 // Hash the CD to get an ID
527 log
->Update(_("Identifying.. "));
530 if (IdentCdrom(CDROM
,ident
) == false)
537 ioprintf(msg
, "[%s]\n",ident
.c_str());
538 log
->Update(msg
.str());
542 Configuration Database
;
543 string DFile
= _config
->FindFile("Dir::State::cdroms");
544 if (FileExists(DFile
) == true)
546 if (ReadConfigFile(Database
,DFile
) == false)
547 return _error
->Error("Unable to read the cdrom database %s",
552 ioprintf(msg
, _("Stored label: %s\n"),
553 Database
.Find("CD::"+ident
).c_str());
554 log
->Update(msg
.str());
557 // Unmount and finish
558 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
559 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
566 bool pkgCdrom::Add(pkgCdromStatus
*log
) /*{{{*/
571 string CDROM
= _config
->FindDir("Acquire::cdrom::mount","/cdrom/");
573 CDROM
= SafeGetCWD() + '/' + CDROM
;
576 log
->SetTotal(STEP_LAST
);
578 ioprintf(msg
, _("Using CD-ROM mount point %s\n"), CDROM
.c_str());
579 log
->Update(msg
.str(), STEP_PREPARE
);
583 Configuration Database
;
584 string DFile
= _config
->FindFile("Dir::State::cdroms");
585 if (FileExists(DFile
) == true)
587 if (ReadConfigFile(Database
,DFile
) == false)
588 return _error
->Error("Unable to read the cdrom database %s",
592 // Unmount the CD and get the user to put in the one they want
593 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
596 log
->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT
);
600 log
->Update(_("Waiting for disc...\n"), STEP_WAIT
);
601 if(!log
->ChangeCdrom()) {
607 // Mount the new CDROM
608 log
->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT
);
609 if (MountCdrom(CDROM
) == false)
610 return _error
->Error("Failed to mount the cdrom.");
613 // Hash the CD to get an ID
615 log
->Update(_("Identifying.. "), STEP_IDENT
);
617 if (IdentCdrom(CDROM
,ID
) == false)
623 log
->Update("["+ID
+"]\n");
626 log
->Update(_("Scanning disc for index files..\n"),STEP_SCAN
);
628 // Get the CD structure
630 vector
<string
> SourceList
;
631 vector
<string
> SigList
;
632 vector
<string
> TransList
;
633 string StartDir
= SafeGetCWD();
635 if (FindPackages(CDROM
,List
,SourceList
, SigList
,TransList
,InfoDir
,log
) == false)
641 chdir(StartDir
.c_str());
643 if (_config
->FindB("Debug::aptcdrom",false) == true)
645 cout
<< "I found (binary):" << endl
;
646 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
648 cout
<< "I found (source):" << endl
;
649 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); I
++)
651 cout
<< "I found (Signatures):" << endl
;
652 for (vector
<string
>::iterator I
= SigList
.begin(); I
!= SigList
.end(); I
++)
656 //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
659 DropBinaryArch(List
);
660 DropRepeats(List
,"Packages");
661 DropRepeats(SourceList
,"Sources");
662 DropRepeats(SigList
,"Release.gpg");
663 DropRepeats(TransList
,"");
666 ioprintf(msg
, _("Found %zu package indexes, %zu source indexes, "
667 "%zu translation indexes and %zu signatures\n"),
668 List
.size(), SourceList
.size(), TransList
.size(),
670 log
->Update(msg
.str(), STEP_SCAN
);
673 if (List
.size() == 0 && SourceList
.size() == 0)
675 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
677 return _error
->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc or the wrong architecture?"));
680 // Check if the CD is in the database
682 if (Database
.Exists("CD::" + ID
) == false ||
683 _config
->FindB("APT::CDROM::Rename",false) == true)
685 // Try to use the CDs label if at all possible
686 if (InfoDir
.empty() == false &&
687 FileExists(InfoDir
+ "/info") == true)
689 ifstream
F(string(InfoDir
+ "/info").c_str());
693 if (Name
.empty() == false)
695 // Escape special characters
696 string::iterator J
= Name
.begin();
697 for (; J
!= Name
.end(); J
++)
698 if (*J
== '"' || *J
== ']' || *J
== '[')
703 ioprintf(msg
, _("Found label '%s'\n"), Name
.c_str());
704 log
->Update(msg
.str());
706 Database
.Set("CD::" + ID
+ "::Label",Name
);
710 if (_config
->FindB("APT::CDROM::Rename",false) == true ||
711 Name
.empty() == true)
715 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
717 return _error
->Error("No disc name found and no way to ask for it");
721 if(!log
->AskCdromName(Name
)) {
725 cout
<< "Name: '" << Name
<< "'" << endl
;
727 if (Name
.empty() == false &&
728 Name
.find('"') == string::npos
&&
729 Name
.find('[') == string::npos
&&
730 Name
.find(']') == string::npos
)
732 log
->Update(_("That is not a valid name, try again.\n"));
737 Name
= Database
.Find("CD::" + ID
);
739 // Escape special characters
740 string::iterator J
= Name
.begin();
741 for (; J
!= Name
.end(); J
++)
742 if (*J
== '"' || *J
== ']' || *J
== '[')
745 Database
.Set("CD::" + ID
,Name
);
748 ioprintf(msg
, _("This disc is called: \n'%s'\n"), Name
.c_str());
749 log
->Update(msg
.str());
752 log
->Update(_("Copying package lists..."), STEP_COPY
);
753 // take care of the signatures and copy them if they are ok
754 // (we do this before PackageCopy as it modifies "List" and "SourceList")
755 SigVerify SignVerify
;
756 SignVerify
.CopyAndVerify(CDROM
, Name
, SigList
, List
, SourceList
);
758 // Copy the package files to the state directory
761 TranslationsCopy TransCopy
;
762 if (Copy
.CopyPackages(CDROM
,Name
,List
, log
) == false ||
763 SrcCopy
.CopyPackages(CDROM
,Name
,SourceList
, log
) == false ||
764 TransCopy
.CopyTranslations(CDROM
,Name
,TransList
, log
) == false)
767 // reduce the List so that it takes less space in sources.list
768 ReduceSourcelist(CDROM
,List
);
769 ReduceSourcelist(CDROM
,SourceList
);
771 // Write the database and sourcelist
772 if (_config
->FindB("APT::cdrom::NoAct",false) == false)
774 if (WriteDatabase(Database
) == false)
778 log
->Update(_("Writing new source list\n"), STEP_WRITE
);
780 if (WriteSourceList(Name
,List
,false) == false ||
781 WriteSourceList(Name
,SourceList
,true) == false)
785 // Print the sourcelist entries
787 log
->Update(_("Source list entries for this disc are:\n"));
789 for (vector
<string
>::iterator I
= List
.begin(); I
!= List
.end(); I
++)
791 string::size_type Space
= (*I
).find(' ');
792 if (Space
== string::npos
)
794 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
796 return _error
->Error("Internal error");
801 msg
<< "deb cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
802 " " << string(*I
,Space
+1) << endl
;
803 log
->Update(msg
.str());
807 for (vector
<string
>::iterator I
= SourceList
.begin(); I
!= SourceList
.end(); I
++)
809 string::size_type Space
= (*I
).find(' ');
810 if (Space
== string::npos
)
812 if (_config
->FindB("APT::CDROM::NoMount",false) == false)
814 return _error
->Error("Internal error");
819 msg
<< "deb-src cdrom:[" << Name
<< "]/" << string(*I
,0,Space
) <<
820 " " << string(*I
,Space
+1) << endl
;
821 log
->Update(msg
.str());
825 // Unmount and finish
826 if (_config
->FindB("APT::CDROM::NoMount",false) == false) {
827 log
->Update(_("Unmounting CD-ROM...\n"), STEP_LAST
);
834 pkgUdevCdromDevices::pkgUdevCdromDevices() /*{{{*/
835 : libudev_handle(NULL
)
842 pkgUdevCdromDevices::Dlopen() /*{{{*/
845 if(libudev_handle
!= NULL
)
848 // see if we can get libudev
849 void *h
= ::dlopen("libudev.so.0", RTLD_LAZY
);
853 // get the pointers to the udev structs
855 udev_new
= (udev
* (*)(void)) dlsym(h
, "udev_new");
856 udev_enumerate_add_match_property
= (int (*)(udev_enumerate
*, const char*, const char*))dlsym(h
, "udev_enumerate_add_match_property");
857 udev_enumerate_scan_devices
= (int (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_scan_devices");
858 udev_enumerate_get_list_entry
= (udev_list_entry
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_list_entry");
859 udev_device_new_from_syspath
= (udev_device
* (*)(udev
*, const char*))dlsym(h
, "udev_device_new_from_syspath");
860 udev_enumerate_get_udev
= (udev
* (*)(udev_enumerate
*))dlsym(h
, "udev_enumerate_get_udev");
861 udev_list_entry_get_name
= (const char* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_name");
862 udev_device_get_devnode
= (const char* (*)(udev_device
*))dlsym(h
, "udev_device_get_devnode");
863 udev_enumerate_new
= (udev_enumerate
* (*)(udev
*))dlsym(h
, "udev_enumerate_new");
864 udev_list_entry_get_next
= (udev_list_entry
* (*)(udev_list_entry
*))dlsym(h
, "udev_list_entry_get_next");
865 udev_device_get_property_value
= (const char* (*)(udev_device
*, const char *))dlsym(h
, "udev_device_get_property_value");
871 pkgUdevCdromDevices::Scan() /*{{{*/
873 vector
<CdromDevice
> cdrom_devices
;
874 struct udev_enumerate
*enumerate
;
875 struct udev_list_entry
*l
, *devices
;
876 struct udev
*udev_ctx
;
878 if(libudev_handle
== NULL
)
879 return cdrom_devices
;
881 udev_ctx
= udev_new();
882 enumerate
= udev_enumerate_new (udev_ctx
);
883 udev_enumerate_add_match_property(enumerate
, "ID_CDROM", "1");
885 udev_enumerate_scan_devices (enumerate
);
886 devices
= udev_enumerate_get_list_entry (enumerate
);
887 for (l
= devices
; l
!= NULL
; l
= udev_list_entry_get_next (l
))
890 struct udev_device
*udevice
;
891 udevice
= udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate
), udev_list_entry_get_name (l
));
894 const char* devnode
= udev_device_get_devnode(udevice
);
895 const char* mountpath
= udev_device_get_property_value(udevice
, "FSTAB_DIR");
897 // fill in the struct
898 cdrom
.DeviceName
= string(devnode
);
900 cdrom
.MountPath
= mountpath
;
901 string s
= string(mountpath
);
902 cdrom
.Mounted
= IsMounted(s
);
904 cdrom
.Mounted
= false;
905 cdrom
.MountPath
= "";
907 cdrom_devices
.push_back(cdrom
);
909 return cdrom_devices
;
913 pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/
915 if (libudev_handle
!= NULL
)
916 dlclose(libudev_handle
);