squash merge of the feature/apt-binary branch without the changes from experimental
[ntk/apt.git] / cmdline / apt-cdrom.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cdrom.cc,v 1.45 2003/11/19 23:50:51 mdz Exp $
4 /* ######################################################################
5
6 APT CDROM - Tool for handling APT's CDROM database.
7
8 Currently the only option is 'add' which will take the current CD
9 in the drive and add it into the database.
10
11 ##################################################################### */
12 /*}}}*/
13 // Include Files /*{{{*/
14 #include<config.h>
15
16 #include <apt-pkg/cmndline.h>
17 #include <apt-pkg/error.h>
18 #include <apt-pkg/init.h>
19 #include <apt-pkg/fileutl.h>
20 #include <apt-pkg/progress.h>
21 #include <apt-pkg/cdromutl.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/acquire.h>
24 #include <apt-pkg/acquire-item.h>
25 #include <apt-pkg/cdrom.h>
26 #include <apt-pkg/configuration.h>
27 #include <apt-pkg/pkgsystem.h>
28
29 #include <locale.h>
30 #include <iostream>
31 #include <fstream>
32 #include <vector>
33 #include <algorithm>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <dirent.h>
37 #include <unistd.h>
38 #include <stdio.h>
39
40 #include <apt-private/private-cmndline.h>
41
42 #include <apti18n.h>
43 /*}}}*/
44 static const char *W_NO_CDROM_FOUND = \
45 N_("No CD-ROM could be auto-detected or found using "
46 "the default mount point.\n"
47 "You may try the --cdrom option to set the CD-ROM mount point. "
48 "See 'man apt-cdrom' for more "
49 "information about the CD-ROM auto-detection and mount point.");
50
51 using namespace std;
52
53 class pkgCdromTextStatus : public pkgCdromStatus /*{{{*/
54 {
55 protected:
56 OpTextProgress Progress;
57 void Prompt(const char *Text);
58 string PromptLine(const char *Text);
59 bool AskCdromName(string &name);
60
61 public:
62 virtual void Update(string text, int current);
63 virtual bool ChangeCdrom();
64 virtual OpProgress* GetOpProgress();
65 };
66
67 void pkgCdromTextStatus::Prompt(const char *Text)
68 {
69 char C;
70 cout << Text << ' ' << flush;
71 if (read(STDIN_FILENO,&C,1) < 0)
72 _error->Errno("pkgCdromTextStatus::Prompt",
73 "Failed to read from standard input (not a terminal?)");
74 if (C != '\n')
75 cout << endl;
76 }
77
78 string pkgCdromTextStatus::PromptLine(const char *Text)
79 {
80 cout << Text << ':' << endl;
81
82 string Res;
83 getline(cin,Res);
84 return Res;
85 }
86
87 bool pkgCdromTextStatus::AskCdromName(string &name)
88 {
89 cout << _("Please provide a name for this Disc, such as 'Debian 5.0.3 Disk 1'") << flush;
90 name = PromptLine("");
91
92 return true;
93 }
94
95
96 void pkgCdromTextStatus::Update(string text, int current)
97 {
98 if(text.size() > 0)
99 cout << text << flush;
100 }
101
102 bool pkgCdromTextStatus::ChangeCdrom()
103 {
104 Prompt(_("Please insert a Disc in the drive and press enter"));
105 return true;
106 }
107
108 OpProgress* pkgCdromTextStatus::GetOpProgress()
109 {
110 return &Progress;
111 };
112 /*}}}*/
113 // SetupAutoDetect /*{{{*/
114 bool AutoDetectCdrom(pkgUdevCdromDevices &UdevCdroms, unsigned int &i)
115 {
116 bool Debug = _config->FindB("Debug::Acquire::cdrom", false);
117
118 vector<struct CdromDevice> v = UdevCdroms.Scan();
119 if (i >= v.size())
120 return false;
121
122 if (Debug)
123 clog << "Looking at devce " << i
124 << " DeviveName: " << v[i].DeviceName
125 << " IsMounted: '" << v[i].Mounted << "'"
126 << " MountPoint: '" << v[i].MountPath << "'"
127 << endl;
128
129 if (v[i].Mounted)
130 {
131 // set the right options
132 _config->Set("Acquire::cdrom::mount", v[i].MountPath);
133 _config->Set("APT::CDROM::NoMount", true);
134 } else {
135 string AptMountPoint = _config->FindDir("Dir::Media::MountPath");
136 if (!FileExists(AptMountPoint))
137 mkdir(AptMountPoint.c_str(), 0750);
138 if(MountCdrom(AptMountPoint, v[i].DeviceName) == false)
139 _error->Warning(_("Failed to mount '%s' to '%s'"), v[i].DeviceName.c_str(), AptMountPoint.c_str());
140 _config->Set("Acquire::cdrom::mount", AptMountPoint);
141 _config->Set("APT::CDROM::NoMount", true);
142 }
143 i++;
144
145 return true;
146 }
147 /*}}}*/
148 // DoAdd - Add a new CDROM /*{{{*/
149 // ---------------------------------------------------------------------
150 /* This does the main add bit.. We show some status and things. The
151 sequence is to mount/umount the CD, Ident it then scan it for package
152 files and reduce that list. Then we copy over the package files and
153 verify them. Then rewrite the database files */
154 bool DoAdd(CommandLine &)
155 {
156 pkgUdevCdromDevices UdevCdroms;
157 pkgCdromTextStatus log;
158 pkgCdrom cdrom;
159 bool res = true;
160
161 bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true);
162 unsigned int count = 0;
163 if (AutoDetect && UdevCdroms.Dlopen())
164 while (AutoDetectCdrom(UdevCdroms, count))
165 res &= cdrom.Add(&log);
166 if (count == 0) {
167 res = cdrom.Add(&log);
168 if (res == false) {
169 _error->Error("%s", _(W_NO_CDROM_FOUND));
170 }
171 }
172
173 if(res)
174 cout << _("Repeat this process for the rest of the CDs in your set.") << endl;
175
176 return res;
177 }
178 /*}}}*/
179 // DoIdent - Ident a CDROM /*{{{*/
180 // ---------------------------------------------------------------------
181 /* */
182 bool DoIdent(CommandLine &)
183 {
184 pkgUdevCdromDevices UdevCdroms;
185 string ident;
186 pkgCdromTextStatus log;
187 pkgCdrom cdrom;
188 bool res = true;
189
190 bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect");
191
192 unsigned int count = 0;
193 if (AutoDetect && UdevCdroms.Dlopen())
194 while (AutoDetectCdrom(UdevCdroms, count))
195 res &= cdrom.Ident(ident, &log);
196 if (count == 0) {
197 res = cdrom.Ident(ident, &log);
198 if (res == false) {
199 _error->Error("%s", _(W_NO_CDROM_FOUND));
200 }
201 }
202 return res;
203 }
204 /*}}}*/
205 // ShowHelp - Show the help screen /*{{{*/
206 // ---------------------------------------------------------------------
207 /* */
208 bool ShowHelp(CommandLine &)
209 {
210 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION,
211 COMMON_ARCH,__DATE__,__TIME__);
212 if (_config->FindB("version") == true)
213 return true;
214
215 cout <<
216 "Usage: apt-cdrom [options] command\n"
217 "\n"
218 "apt-cdrom is a tool to add CDROM's to APT's source list. The\n"
219 "CDROM mount point and device information is taken from apt.conf\n"
220 "and /etc/fstab.\n"
221 "\n"
222 "Commands:\n"
223 " add - Add a CDROM\n"
224 " ident - Report the identity of a CDROM\n"
225 "\n"
226 "Options:\n"
227 " -h This help text\n"
228 " -d CD-ROM mount point\n"
229 " -r Rename a recognized CD-ROM\n"
230 " -m No mounting\n"
231 " -f Fast mode, don't check package files\n"
232 " -a Thorough scan mode\n"
233 " --no-auto-detect Do not try to auto detect drive and mount point\n"
234 " -c=? Read this configuration file\n"
235 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
236 "See fstab(5)\n";
237 return true;
238 }
239 /*}}}*/
240 int main(int argc,const char *argv[]) /*{{{*/
241 {
242 CommandLine::Dispatch Cmds[] = {
243 {"add",&DoAdd},
244 {"ident",&DoIdent},
245 {"help",&ShowHelp},
246 {0,0}};
247
248 std::vector<CommandLine::Args> Args = getCommandArgs("apt-cdrom", CommandLine::GetCommand(Cmds, argc, argv));
249
250 // Set up gettext support
251 setlocale(LC_ALL,"");
252 textdomain(PACKAGE);
253
254 // Parse the command line and initialize the package library
255 CommandLine CmdL(Args.data(),_config);
256 if (pkgInitConfig(*_config) == false ||
257 CmdL.Parse(argc,argv) == false ||
258 pkgInitSystem(*_config,_system) == false)
259 {
260 _error->DumpErrors();
261 return 100;
262 }
263
264 // See if the help should be shown
265 if (_config->FindB("help") == true || _config->FindB("version") == true ||
266 CmdL.FileSize() == 0)
267 return ShowHelp(CmdL);
268
269 // Deal with stdout not being a tty
270 if (isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
271 _config->Set("quiet","1");
272
273 // Match the operation
274 CmdL.DispatchArg(Cmds);
275
276 // Print any errors or warnings found during parsing
277 bool const Errors = _error->PendingError();
278 if (_config->FindI("quiet",0) > 0)
279 _error->DumpErrors();
280 else
281 _error->DumpErrors(GlobalError::DEBUG);
282 return Errors == true ? 100 : 0;
283 }
284 /*}}}*/