* imported changes from apt--main
[ntk/apt.git] / methods / cdrom.cc
CommitLineData
f46e7681
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
d77559ac 3// $Id: cdrom.cc,v 1.21 2004/01/07 20:39:38 mdz Exp $
f46e7681
AL
4/* ######################################################################
5
6 CDROM URI method for APT
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
11#include <apt-pkg/acquire-method.h>
12#include <apt-pkg/cdromutl.h>
13#include <apt-pkg/error.h>
14#include <apt-pkg/configuration.h>
15#include <apt-pkg/fileutl.h>
16
17#include <sys/stat.h>
18#include <unistd.h>
076cc664
AL
19
20#include <iostream>
d77559ac 21#include <apti18n.h>
f46e7681
AL
22 /*}}}*/
23
076cc664
AL
24using namespace std;
25
f46e7681
AL
26class CDROMMethod : public pkgAcqMethod
27{
f631d1ba 28 bool DatabaseLoaded;
5b76e7f2 29 ::Configuration Database;
f46e7681 30 string CurrentID;
8e5fc8f5
AL
31 string CDROM;
32 bool Mounted;
f46e7681
AL
33
34 virtual bool Fetch(FetchItem *Itm);
35 string GetID(string Name);
8e5fc8f5 36 virtual void Exit();
f46e7681
AL
37
38 public:
39
40 CDROMMethod();
41};
42
43// CDROMMethod::CDROMethod - Constructor /*{{{*/
44// ---------------------------------------------------------------------
45/* */
459681d3
AL
46CDROMMethod::CDROMMethod() : pkgAcqMethod("1.0",SingleInstance | LocalOnly |
47 SendConfig | NeedsCleanup |
48 Removable),
8e5fc8f5
AL
49 DatabaseLoaded(false),
50 Mounted(false)
f46e7681 51{
f46e7681
AL
52};
53 /*}}}*/
8e5fc8f5
AL
54// CDROMMethod::Exit - Unmount the disc if necessary /*{{{*/
55// ---------------------------------------------------------------------
56/* */
57void CDROMMethod::Exit()
58{
59 if (Mounted == true)
60 UnmountCdrom(CDROM);
61}
62 /*}}}*/
e42eb508 63// CDROMMethod::GetID - Search the database for a matching string /*{{{*/
f46e7681 64// ---------------------------------------------------------------------
e42eb508 65/* */
f46e7681
AL
66string CDROMMethod::GetID(string Name)
67{
e42eb508 68 // Search for an ID
f631d1ba 69 const Configuration::Item *Top = Database.Tree("CD");
b7d9b68e
AL
70 if (Top != 0)
71 Top = Top->Child;
e42eb508 72
f46e7681 73 for (; Top != 0;)
e42eb508 74 {
f46e7681
AL
75 if (Top->Value == Name)
76 return Top->Tag;
e42eb508 77
f46e7681 78 Top = Top->Next;
e42eb508 79 }
f46e7681
AL
80 return string();
81}
82 /*}}}*/
83// CDROMMethod::Fetch - Fetch a file /*{{{*/
84// ---------------------------------------------------------------------
85/* */
86bool CDROMMethod::Fetch(FetchItem *Itm)
87{
88 URI Get = Itm->Uri;
89 string File = Get.Path;
90 FetchResult Res;
34fc0421
AL
91
92 bool Debug = _config->FindB("Debug::Acquire::cdrom",false);
93
f46e7681
AL
94 /* All IMS queries are returned as a hit, CDROMs are readonly so
95 time stamps never change */
96 if (Itm->LastModified != 0)
97 {
98 Res.LastModified = Itm->LastModified;
99 Res.IMSHit = true;
4b1b89c5 100 Res.Filename = File;
f46e7681
AL
101 URIDone(Res);
102 return true;
103 }
e42eb508
AL
104
105 // Load the database
106 if (DatabaseLoaded == false)
107 {
108 // Read the database
109 string DFile = _config->FindFile("Dir::State::cdroms");
110 if (FileExists(DFile) == true)
111 {
112 if (ReadConfigFile(Database,DFile) == false)
dc738e7a 113 return _error->Error(_("Unable to read the cdrom database %s"),
e42eb508
AL
114 DFile.c_str());
115 }
116 DatabaseLoaded = true;
117 }
118
f46e7681 119 // All non IMS queries for package files fail.
e42eb508 120 if (Itm->IndexFile == true || GetID(Get.Host).empty() == true)
f46e7681 121 {
dc738e7a
AL
122 Fail(_("Please use apt-cdrom to make this CD recognized by APT."
123 " apt-get update cannot be used to add new CDs"));
9e0349cc 124 return true;
f46e7681
AL
125 }
126
127 // We already have a CD inserted, but it is the wrong one
e42eb508 128 if (CurrentID.empty() == false && Database.Find("CD::" + CurrentID) != Get.Host)
f46e7681 129 {
dc738e7a 130 Fail(_("Wrong CD"),true);
9e0349cc 131 return true;
f46e7681
AL
132 }
133
8e5fc8f5 134 CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
76d97c26
AL
135 if (CDROM[0] == '.')
136 CDROM= SafeGetCWD() + '/' + CDROM;
f46e7681 137 string NewID;
281daf46 138 while (CurrentID.empty() == true)
f46e7681 139 {
34fc0421 140 bool Hit = false;
f7dd079f 141 Mounted = MountCdrom(CDROM);
34fc0421
AL
142 for (unsigned int Version = 2; Version != 0; Version--)
143 {
144 if (IdentCdrom(CDROM,NewID,Version) == false)
145 return false;
146
147 if (Debug == true)
148 clog << "ID " << Version << " " << NewID << endl;
149
150 // A hit
151 if (Database.Find("CD::" + NewID) == Get.Host)
152 {
153 Hit = true;
154 break;
155 }
156 }
175f08ac
AL
157
158 if (Hit == true)
159 break;
160
4df0b629
AL
161 // I suppose this should prompt somehow?
162 if (UnmountCdrom(CDROM) == false)
dc738e7a 163 return _error->Error(_("Unable to unmount the CD-ROM in %s, it may still be in use."),
4df0b629 164 CDROM.c_str());
018f1533
AL
165 if (MediaFail(Get.Host,CDROM) == false)
166 {
76d97c26 167 CurrentID = "FAIL";
dc738e7a 168 Fail(_("Wrong CD"),true);
9e0349cc 169 return true;
018f1533 170 }
f46e7681
AL
171 }
172
e42eb508
AL
173 // Found a CD
174 Res.Filename = CDROM + File;
175 struct stat Buf;
176 if (stat(Res.Filename.c_str(),&Buf) != 0)
dc738e7a 177 return _error->Error(_("File not found"));
f46e7681 178
281daf46
AL
179 if (NewID.empty() == false)
180 CurrentID = NewID;
e42eb508 181 Res.LastModified = Buf.st_mtime;
e42eb508
AL
182 Res.Size = Buf.st_size;
183 URIDone(Res);
184 return true;
f46e7681
AL
185}
186 /*}}}*/
187
188int main()
189{
b25423f6
MZ
190 setlocale(LC_ALL, "");
191
f46e7681
AL
192 CDROMMethod Mth;
193 return Mth.Run();
194}