1 // -*- mode: cpp; mode: fold -*-
3 // $Id: cdrom.cc,v 1.20.2.1 2004/01/16 18:58:50 mdz Exp $
4 /* ######################################################################
6 CDROM URI method for APT
8 ##################################################################### */
10 // Include Files /*{{{*/
13 #include <apt-pkg/cdrom.h>
14 #include <apt-pkg/cdromutl.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/configuration.h>
17 #include <apt-pkg/fileutl.h>
18 #include <apt-pkg/strutl.h>
19 #include <apt-pkg/hashes.h>
21 #include "aptmethod.h"
33 class CDROMMethod
: public aptMethod
38 ::Configuration Database
;
42 pkgUdevCdromDevices UdevCdroms
;
44 bool IsCorrectCD(URI want
, string MountPath
, string
& NewID
);
45 bool AutoDetectAndMount(const URI
, string
&NewID
);
46 virtual bool Fetch(FetchItem
*Itm
) APT_OVERRIDE
;
47 string
GetID(string Name
);
48 virtual void Exit() APT_OVERRIDE
;
55 // CDROMMethod::CDROMethod - Constructor /*{{{*/
56 // ---------------------------------------------------------------------
58 CDROMMethod::CDROMMethod() : aptMethod("cdrom", "1.0",SingleInstance
| LocalOnly
|
59 SendConfig
| NeedsCleanup
|
61 DatabaseLoaded(false),
68 // CDROMMethod::Exit - Unmount the disc if necessary /*{{{*/
69 // ---------------------------------------------------------------------
71 void CDROMMethod::Exit()
73 if (MountedByApt
== true)
77 // CDROMMethod::GetID - Search the database for a matching string /*{{{*/
78 // ---------------------------------------------------------------------
80 string
CDROMMethod::GetID(string Name
)
83 const Configuration::Item
*Top
= Database
.Tree("CD");
89 if (Top
->Value
== Name
)
97 // CDROMMethod::AutoDetectAndMount /*{{{*/
98 // ---------------------------------------------------------------------
99 /* Modifies class varaiable CDROM to the mountpoint */
100 bool CDROMMethod::AutoDetectAndMount(const URI Get
, string
&NewID
)
102 vector
<struct CdromDevice
> v
= UdevCdroms
.Scan();
104 // first check if its mounted somewhere already
105 for (unsigned int i
=0; i
< v
.size(); i
++)
110 clog
<< "Checking mounted cdrom device " << v
[i
].DeviceName
<< endl
;
111 if (IsCorrectCD(Get
, v
[i
].MountPath
, NewID
))
113 CDROM
= v
[i
].MountPath
;
119 // we are not supposed to mount, exit
120 if (_config
->FindB("APT::CDROM::NoMount",false) == true)
123 // check if we have the mount point
124 string AptMountPoint
= _config
->FindDir("Dir::Media::MountPath");
125 if (!FileExists(AptMountPoint
))
126 mkdir(AptMountPoint
.c_str(), 0750);
129 for (unsigned int i
=0; i
< v
.size(); i
++)
133 if(MountCdrom(AptMountPoint
, v
[i
].DeviceName
))
135 if (IsCorrectCD(Get
, AptMountPoint
, NewID
))
138 CDROM
= AptMountPoint
;
141 UnmountCdrom(AptMountPoint
);
150 // CDROMMethod::IsCorrectCD /*{{{*/
151 // ---------------------------------------------------------------------
153 bool CDROMMethod::IsCorrectCD(URI want
, string MountPath
, string
& NewID
)
155 for (unsigned int Version
= 2; Version
!= 0; Version
--)
157 if (IdentCdrom(MountPath
,NewID
,Version
) == false)
161 clog
<< "ID " << Version
<< " " << NewID
<< endl
;
164 if (Database
.Find("CD::" + NewID
) == want
.Host
)
171 // CDROMMethod::Fetch - Fetch a file /*{{{*/
172 // ---------------------------------------------------------------------
174 bool CDROMMethod::Fetch(FetchItem
*Itm
)
179 string File
= Get
.Path
;
180 Debug
= _config
->FindB("Debug::Acquire::cdrom", false);
183 clog
<< "CDROMMethod::Fetch " << Itm
->Uri
<< endl
;
185 /* All IMS queries are returned as a hit, CDROMs are readonly so
186 time stamps never change */
187 if (Itm
->LastModified
!= 0)
189 Res
.LastModified
= Itm
->LastModified
;
191 Res
.Filename
= Itm
->DestFile
;
197 if (DatabaseLoaded
== false)
200 string DFile
= _config
->FindFile("Dir::State::cdroms");
201 if (FileExists(DFile
) == true)
203 if (ReadConfigFile(Database
,DFile
) == false)
204 return _error
->Error(_("Unable to read the cdrom database %s"),
207 DatabaseLoaded
= true;
210 // All non IMS queries for package files fail.
211 if (Itm
->IndexFile
== true || GetID(Get
.Host
).empty() == true)
213 Fail(_("Please use apt-cdrom to make this CD-ROM recognized by APT."
214 " apt-get update cannot be used to add new CD-ROMs"));
218 // We already have a CD inserted, but it is the wrong one
219 if (CurrentID
.empty() == false &&
220 CurrentID
!= "FAIL" &&
221 Database
.Find("CD::" + CurrentID
) != Get
.Host
)
223 Fail(_("Wrong CD-ROM"),true);
227 bool AutoDetect
= _config
->FindB("Acquire::cdrom::AutoDetect", true);
228 CDROM
= _config
->FindDir("Acquire::cdrom::mount");
230 clog
<< "Looking for CDROM at " << CDROM
<< endl
;
233 CDROM
= SafeGetCWD() + '/' + CDROM
;
236 while (CurrentID
.empty() == true)
239 AutoDetectAndMount(Get
, NewID
);
241 if(!IsMounted(CDROM
))
242 MountedByApt
= MountCdrom(CDROM
);
244 if (IsCorrectCD(Get
, CDROM
, NewID
))
247 // I suppose this should prompt somehow?
248 if (_config
->FindB("APT::CDROM::NoMount",false) == false &&
249 UnmountCdrom(CDROM
) == false)
250 return _error
->Error(_("Unable to unmount the CD-ROM in %s, it may still be in use."),
252 if (MediaFail(Get
.Host
,CDROM
) == false)
255 return _error
->Error(_("Disk not found."));
260 Res
.Filename
= CDROM
+ File
;
262 if (stat(Res
.Filename
.c_str(),&Buf
) != 0)
263 return _error
->Error(_("File not found"));
266 if (NewID
.empty() == false)
268 Res
.LastModified
= Buf
.st_mtime
;
269 Res
.Size
= Buf
.st_size
;
271 Hashes
Hash(Itm
->ExpectedHashes
);
272 FileFd
Fd(Res
.Filename
, FileFd::ReadOnly
);
274 Res
.TakeHashes(Hash
);
283 _config
->CndSet("Binary::cdrom::Debug::NoDropPrivs", true);
284 return CDROMMethod().Run();