]> git.saurik.com Git - apt.git/blame - methods/cdrom.cc
implement generic config fallback for methods
[apt.git] / methods / cdrom.cc
CommitLineData
f46e7681
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b3d44315 3// $Id: cdrom.cc,v 1.20.2.1 2004/01/16 18:58:50 mdz Exp $
f46e7681
AL
4/* ######################################################################
5
6 CDROM URI method for APT
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
ea542140
DK
11#include <config.h>
12
a6418a4b 13#include <apt-pkg/cdrom.h>
f46e7681
AL
14#include <apt-pkg/cdromutl.h>
15#include <apt-pkg/error.h>
16#include <apt-pkg/configuration.h>
17#include <apt-pkg/fileutl.h>
472ff00e 18#include <apt-pkg/strutl.h>
13e8426f 19#include <apt-pkg/hashes.h>
f46e7681 20
8b79c94a
DK
21#include "aptmethod.h"
22
453b82a3
DK
23#include <string>
24#include <vector>
f46e7681 25#include <sys/stat.h>
076cc664
AL
26
27#include <iostream>
d77559ac 28#include <apti18n.h>
f46e7681
AL
29 /*}}}*/
30
076cc664
AL
31using namespace std;
32
8b79c94a 33class CDROMMethod : public aptMethod
f46e7681 34{
f631d1ba 35 bool DatabaseLoaded;
76fe5db7
MV
36 bool Debug;
37
5b76e7f2 38 ::Configuration Database;
f46e7681 39 string CurrentID;
8e5fc8f5 40 string CDROM;
70dbf5f8 41 bool MountedByApt;
76fe5db7 42 pkgUdevCdromDevices UdevCdroms;
8e372e79 43
bf783d90 44 bool IsCorrectCD(URI want, string MountPath, string& NewID);
1c545980 45 bool AutoDetectAndMount(const URI, string &NewID);
3b302846 46 virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
f46e7681 47 string GetID(string Name);
3b302846 48 virtual void Exit() APT_OVERRIDE;
8e372e79 49
f46e7681
AL
50 public:
51
52 CDROMMethod();
53};
54
55// CDROMMethod::CDROMethod - Constructor /*{{{*/
56// ---------------------------------------------------------------------
57/* */
8b79c94a 58CDROMMethod::CDROMMethod() : aptMethod("cdrom", "1.0",SingleInstance | LocalOnly |
459681d3 59 SendConfig | NeedsCleanup |
8b79c94a 60 Removable),
f5a34606
DK
61 DatabaseLoaded(false),
62 Debug(false),
70dbf5f8 63 MountedByApt(false)
f46e7681 64{
76fe5db7 65 UdevCdroms.Dlopen();
d3e8fbb3 66}
f46e7681 67 /*}}}*/
8e5fc8f5
AL
68// CDROMMethod::Exit - Unmount the disc if necessary /*{{{*/
69// ---------------------------------------------------------------------
70/* */
71void CDROMMethod::Exit()
8e372e79
MV
72{
73 if (MountedByApt == true)
8e5fc8f5
AL
74 UnmountCdrom(CDROM);
75}
76 /*}}}*/
e42eb508 77// CDROMMethod::GetID - Search the database for a matching string /*{{{*/
f46e7681 78// ---------------------------------------------------------------------
e42eb508 79/* */
f46e7681
AL
80string CDROMMethod::GetID(string Name)
81{
e42eb508 82 // Search for an ID
f631d1ba 83 const Configuration::Item *Top = Database.Tree("CD");
b7d9b68e
AL
84 if (Top != 0)
85 Top = Top->Child;
e42eb508 86
f46e7681 87 for (; Top != 0;)
e42eb508 88 {
f46e7681
AL
89 if (Top->Value == Name)
90 return Top->Tag;
e42eb508 91
f46e7681 92 Top = Top->Next;
e42eb508 93 }
f46e7681
AL
94 return string();
95}
96 /*}}}*/
76fe5db7
MV
97// CDROMMethod::AutoDetectAndMount /*{{{*/
98// ---------------------------------------------------------------------
99/* Modifies class varaiable CDROM to the mountpoint */
1c545980 100bool CDROMMethod::AutoDetectAndMount(const URI Get, string &NewID)
76fe5db7
MV
101{
102 vector<struct CdromDevice> v = UdevCdroms.Scan();
103
104 // first check if its mounted somewhere already
105 for (unsigned int i=0; i < v.size(); i++)
106 {
107 if (v[i].Mounted)
108 {
109 if (Debug)
110 clog << "Checking mounted cdrom device " << v[i].DeviceName << endl;
bf783d90 111 if (IsCorrectCD(Get, v[i].MountPath, NewID))
76fe5db7
MV
112 {
113 CDROM = v[i].MountPath;
114 return true;
115 }
116 }
117 }
118
119 // we are not supposed to mount, exit
120 if (_config->FindB("APT::CDROM::NoMount",false) == true)
121 return false;
122
123 // check if we have the mount point
ffee221b 124 string AptMountPoint = _config->FindDir("Dir::Media::MountPath");
fb503892 125 if (!FileExists(AptMountPoint))
ffee221b 126 mkdir(AptMountPoint.c_str(), 0750);
a6418a4b 127
76fe5db7
MV
128 // now try mounting
129 for (unsigned int i=0; i < v.size(); i++)
130 {
131 if (!v[i].Mounted)
132 {
fb503892 133 if(MountCdrom(AptMountPoint, v[i].DeviceName))
76fe5db7 134 {
fb503892 135 if (IsCorrectCD(Get, AptMountPoint, NewID))
76fe5db7
MV
136 {
137 MountedByApt = true;
fb503892 138 CDROM = AptMountPoint;
76fe5db7
MV
139 return true;
140 } else {
fb503892 141 UnmountCdrom(AptMountPoint);
76fe5db7
MV
142 }
143 }
144 }
145 }
146
147 return false;
148}
149 /*}}}*/
a6418a4b
MV
150// CDROMMethod::IsCorrectCD /*{{{*/
151// ---------------------------------------------------------------------
152/* */
bf783d90 153bool CDROMMethod::IsCorrectCD(URI want, string MountPath, string& NewID)
a6418a4b 154{
a6418a4b
MV
155 for (unsigned int Version = 2; Version != 0; Version--)
156 {
157 if (IdentCdrom(MountPath,NewID,Version) == false)
158 return false;
159
76fe5db7 160 if (Debug)
a6418a4b
MV
161 clog << "ID " << Version << " " << NewID << endl;
162
163 // A hit
164 if (Database.Find("CD::" + NewID) == want.Host)
165 return true;
166 }
167
168 return false;
169}
170 /*}}}*/
f46e7681
AL
171// CDROMMethod::Fetch - Fetch a file /*{{{*/
172// ---------------------------------------------------------------------
173/* */
174bool CDROMMethod::Fetch(FetchItem *Itm)
175{
76fe5db7
MV
176 FetchResult Res;
177
f46e7681
AL
178 URI Get = Itm->Uri;
179 string File = Get.Path;
30060442 180 Debug = DebugEnabled();
34fc0421 181
49cb36fc
MV
182 if (Debug)
183 clog << "CDROMMethod::Fetch " << Itm->Uri << endl;
34fc0421 184
f46e7681
AL
185 /* All IMS queries are returned as a hit, CDROMs are readonly so
186 time stamps never change */
187 if (Itm->LastModified != 0)
188 {
189 Res.LastModified = Itm->LastModified;
190 Res.IMSHit = true;
2aab5956 191 Res.Filename = Itm->DestFile;
f46e7681
AL
192 URIDone(Res);
193 return true;
194 }
e42eb508
AL
195
196 // Load the database
197 if (DatabaseLoaded == false)
198 {
199 // Read the database
200 string DFile = _config->FindFile("Dir::State::cdroms");
201 if (FileExists(DFile) == true)
202 {
203 if (ReadConfigFile(Database,DFile) == false)
dc738e7a 204 return _error->Error(_("Unable to read the cdrom database %s"),
e42eb508
AL
205 DFile.c_str());
206 }
207 DatabaseLoaded = true;
208 }
209
f46e7681 210 // All non IMS queries for package files fail.
e42eb508 211 if (Itm->IndexFile == true || GetID(Get.Host).empty() == true)
f46e7681 212 {
db0db9fe
CP
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"));
9e0349cc 215 return true;
f46e7681
AL
216 }
217
218 // We already have a CD inserted, but it is the wrong one
49cb36fc
MV
219 if (CurrentID.empty() == false &&
220 CurrentID != "FAIL" &&
221 Database.Find("CD::" + CurrentID) != Get.Host)
f46e7681 222 {
db0db9fe 223 Fail(_("Wrong CD-ROM"),true);
9e0349cc 224 return true;
f46e7681 225 }
a6418a4b 226
30060442 227 bool const AutoDetect = ConfigFindB("AutoDetect", true);
710aba4a 228 CDROM = _config->FindDir("Acquire::cdrom::mount");
49cb36fc
MV
229 if (Debug)
230 clog << "Looking for CDROM at " << CDROM << endl;
a6418a4b 231
49cb36fc
MV
232 if (CDROM[0] == '.')
233 CDROM= SafeGetCWD() + '/' + CDROM;
49cb36fc 234
bf783d90 235 string NewID;
49cb36fc 236 while (CurrentID.empty() == true)
a6418a4b 237 {
ff1e4b06 238 if (AutoDetect)
bf783d90 239 AutoDetectAndMount(Get, NewID);
a6418a4b 240
70dbf5f8
MV
241 if(!IsMounted(CDROM))
242 MountedByApt = MountCdrom(CDROM);
34fc0421 243
bf783d90 244 if (IsCorrectCD(Get, CDROM, NewID))
175f08ac
AL
245 break;
246
4df0b629 247 // I suppose this should prompt somehow?
50959877
MV
248 if (_config->FindB("APT::CDROM::NoMount",false) == false &&
249 UnmountCdrom(CDROM) == false)
dc738e7a 250 return _error->Error(_("Unable to unmount the CD-ROM in %s, it may still be in use."),
4df0b629 251 CDROM.c_str());
018f1533
AL
252 if (MediaFail(Get.Host,CDROM) == false)
253 {
76d97c26 254 CurrentID = "FAIL";
2a749770 255 return _error->Error(_("Disk not found."));
018f1533 256 }
f46e7681
AL
257 }
258
e42eb508
AL
259 // Found a CD
260 Res.Filename = CDROM + File;
261 struct stat Buf;
262 if (stat(Res.Filename.c_str(),&Buf) != 0)
dc738e7a 263 return _error->Error(_("File not found"));
ff86d7df
DK
264
265 URIStart(Res);
281daf46
AL
266 if (NewID.empty() == false)
267 CurrentID = NewID;
e42eb508 268 Res.LastModified = Buf.st_mtime;
e42eb508 269 Res.Size = Buf.st_size;
13e8426f 270
9224ce3d 271 Hashes Hash(Itm->ExpectedHashes);
13e8426f 272 FileFd Fd(Res.Filename, FileFd::ReadOnly);
109eb151 273 Hash.AddFD(Fd);
13e8426f
MV
274 Res.TakeHashes(Hash);
275
e42eb508
AL
276 URIDone(Res);
277 return true;
f46e7681
AL
278}
279 /*}}}*/
280
281int main()
282{
8b79c94a
DK
283 _config->CndSet("Binary::cdrom::Debug::NoDropPrivs", true);
284 return CDROMMethod().Run();
f46e7681 285}