cdrom.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /*
  2. */
  3. #ifdef __GNUG__
  4. #pragma implementation "apt-pkg/cdrom.h"
  5. #endif
  6. #include<apt-pkg/init.h>
  7. #include<apt-pkg/error.h>
  8. #include<apt-pkg/cdromutl.h>
  9. #include<apt-pkg/strutl.h>
  10. #include<apt-pkg/cdrom.h>
  11. #include<sstream>
  12. #include<fstream>
  13. #include<config.h>
  14. #include<apti18n.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <dirent.h>
  18. #include <unistd.h>
  19. #include <stdio.h>
  20. #include "indexcopy.h"
  21. using namespace std;
  22. // FindPackages - Find the package files on the CDROM /*{{{*/
  23. // ---------------------------------------------------------------------
  24. /* We look over the cdrom for package files. This is a recursive
  25. search that short circuits when it his a package file in the dir.
  26. This speeds it up greatly as the majority of the size is in the
  27. binary-* sub dirs. */
  28. bool pkgCdrom::FindPackages(string CD,vector<string> &List,
  29. vector<string> &SList, vector<string> &SigList,
  30. string &InfoDir, pkgCdromStatus *log,
  31. unsigned int Depth)
  32. {
  33. static ino_t Inodes[9];
  34. // if we have a look we "pulse" now
  35. if(log)
  36. log->Update();
  37. if (Depth >= 7)
  38. return true;
  39. if (CD[CD.length()-1] != '/')
  40. CD += '/';
  41. if (chdir(CD.c_str()) != 0)
  42. return _error->Errno("chdir","Unable to change to %s",CD.c_str());
  43. // Look for a .disk subdirectory
  44. struct stat Buf;
  45. if (stat(".disk",&Buf) == 0)
  46. {
  47. if (InfoDir.empty() == true)
  48. InfoDir = CD + ".disk/";
  49. }
  50. // Don't look into directories that have been marked to ingore.
  51. if (stat(".aptignr",&Buf) == 0)
  52. return true;
  53. /* Check _first_ for a signature file as apt-cdrom assumes that all files
  54. under a Packages/Source file are in control of that file and stops
  55. the scanning
  56. */
  57. if (stat("Release.gpg",&Buf) == 0)
  58. {
  59. SigList.push_back(CD);
  60. }
  61. /* Aha! We found some package files. We assume that everything under
  62. this dir is controlled by those package files so we don't look down
  63. anymore */
  64. if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0)
  65. {
  66. List.push_back(CD);
  67. // Continue down if thorough is given
  68. if (_config->FindB("APT::CDROM::Thorough",false) == false)
  69. return true;
  70. }
  71. if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0)
  72. {
  73. SList.push_back(CD);
  74. // Continue down if thorough is given
  75. if (_config->FindB("APT::CDROM::Thorough",false) == false)
  76. return true;
  77. }
  78. DIR *D = opendir(".");
  79. if (D == 0)
  80. return _error->Errno("opendir","Unable to read %s",CD.c_str());
  81. // Run over the directory
  82. for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
  83. {
  84. // Skip some files..
  85. if (strcmp(Dir->d_name,".") == 0 ||
  86. strcmp(Dir->d_name,"..") == 0 ||
  87. //strcmp(Dir->d_name,"source") == 0 ||
  88. strcmp(Dir->d_name,".disk") == 0 ||
  89. strcmp(Dir->d_name,"experimental") == 0 ||
  90. strcmp(Dir->d_name,"binary-all") == 0 ||
  91. strcmp(Dir->d_name,"debian-installer") == 0)
  92. continue;
  93. // See if the name is a sub directory
  94. struct stat Buf;
  95. if (stat(Dir->d_name,&Buf) != 0)
  96. continue;
  97. if (S_ISDIR(Buf.st_mode) == 0)
  98. continue;
  99. unsigned int I;
  100. for (I = 0; I != Depth; I++)
  101. if (Inodes[I] == Buf.st_ino)
  102. break;
  103. if (I != Depth)
  104. continue;
  105. // Store the inodes weve seen
  106. Inodes[Depth] = Buf.st_ino;
  107. // Descend
  108. if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false)
  109. break;
  110. if (chdir(CD.c_str()) != 0)
  111. return _error->Errno("chdir","Unable to change to %s",CD.c_str());
  112. };
  113. closedir(D);
  114. return !_error->PendingError();
  115. }
  116. // Score - We compute a 'score' for a path /*{{{*/
  117. // ---------------------------------------------------------------------
  118. /* Paths are scored based on how close they come to what I consider
  119. normal. That is ones that have 'dist' 'stable' 'testing' will score
  120. higher than ones without. */
  121. int pkgCdrom::Score(string Path)
  122. {
  123. int Res = 0;
  124. if (Path.find("stable/") != string::npos)
  125. Res += 29;
  126. if (Path.find("/binary-") != string::npos)
  127. Res += 20;
  128. if (Path.find("testing/") != string::npos)
  129. Res += 28;
  130. if (Path.find("unstable/") != string::npos)
  131. Res += 27;
  132. if (Path.find("/dists/") != string::npos)
  133. Res += 40;
  134. if (Path.find("/main/") != string::npos)
  135. Res += 20;
  136. if (Path.find("/contrib/") != string::npos)
  137. Res += 20;
  138. if (Path.find("/non-free/") != string::npos)
  139. Res += 20;
  140. if (Path.find("/non-US/") != string::npos)
  141. Res += 20;
  142. if (Path.find("/source/") != string::npos)
  143. Res += 10;
  144. if (Path.find("/debian/") != string::npos)
  145. Res -= 10;
  146. // check for symlinks in the patch leading to the actual file
  147. // a symlink gets a big penalty
  148. struct stat Buf;
  149. string statPath = flNotFile(Path);
  150. string cdromPath = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
  151. while(statPath != cdromPath && statPath != "./") {
  152. statPath.resize(statPath.size()-1); // remove the trailing '/'
  153. if (lstat(statPath.c_str(),&Buf) == 0) {
  154. if(S_ISLNK(Buf.st_mode)) {
  155. Res -= 60;
  156. break;
  157. }
  158. }
  159. statPath = flNotFile(statPath); // descent
  160. }
  161. return Res;
  162. }
  163. /*}}}*/
  164. // DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/
  165. // ---------------------------------------------------------------------
  166. /* Here we drop everything that is not this machines arch */
  167. bool pkgCdrom::DropBinaryArch(vector<string> &List)
  168. {
  169. char S[300];
  170. snprintf(S,sizeof(S),"/binary-%s/",
  171. _config->Find("Apt::Architecture").c_str());
  172. for (unsigned int I = 0; I < List.size(); I++)
  173. {
  174. const char *Str = List[I].c_str();
  175. const char *Res;
  176. if ((Res = strstr(Str,"/binary-")) == 0)
  177. continue;
  178. // Weird, remove it.
  179. if (strlen(Res) < strlen(S))
  180. {
  181. List.erase(List.begin() + I);
  182. I--;
  183. continue;
  184. }
  185. // See if it is our arch
  186. if (stringcmp(Res,Res + strlen(S),S) == 0)
  187. continue;
  188. // Erase it
  189. List.erase(List.begin() + I);
  190. I--;
  191. }
  192. return true;
  193. }
  194. // DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
  195. // ---------------------------------------------------------------------
  196. /* Here we go and stat every file that we found and strip dup inodes. */
  197. bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
  198. {
  199. // Get a list of all the inodes
  200. ino_t *Inodes = new ino_t[List.size()];
  201. for (unsigned int I = 0; I != List.size(); I++)
  202. {
  203. struct stat Buf;
  204. if (stat((List[I] + Name).c_str(),&Buf) != 0 &&
  205. stat((List[I] + Name + ".gz").c_str(),&Buf) != 0)
  206. _error->Errno("stat","Failed to stat %s%s",List[I].c_str(),
  207. Name);
  208. Inodes[I] = Buf.st_ino;
  209. }
  210. if (_error->PendingError() == true)
  211. return false;
  212. // Look for dups
  213. for (unsigned int I = 0; I != List.size(); I++)
  214. {
  215. for (unsigned int J = I+1; J < List.size(); J++)
  216. {
  217. // No match
  218. if (Inodes[J] != Inodes[I])
  219. continue;
  220. // We score the two paths.. and erase one
  221. int ScoreA = Score(List[I]);
  222. int ScoreB = Score(List[J]);
  223. if (ScoreA < ScoreB)
  224. {
  225. List[I] = string();
  226. break;
  227. }
  228. List[J] = string();
  229. }
  230. }
  231. // Wipe erased entries
  232. for (unsigned int I = 0; I < List.size();)
  233. {
  234. if (List[I].empty() == false)
  235. I++;
  236. else
  237. List.erase(List.begin()+I);
  238. }
  239. return true;
  240. }
  241. /*}}}*/
  242. // ReduceSourceList - Takes the path list and reduces it /*{{{*/
  243. // ---------------------------------------------------------------------
  244. /* This takes the list of source list expressed entires and collects
  245. similar ones to form a single entry for each dist */
  246. void pkgCdrom::ReduceSourcelist(string CD,vector<string> &List)
  247. {
  248. sort(List.begin(),List.end());
  249. // Collect similar entries
  250. for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
  251. {
  252. // Find a space..
  253. string::size_type Space = (*I).find(' ');
  254. if (Space == string::npos)
  255. continue;
  256. string::size_type SSpace = (*I).find(' ',Space + 1);
  257. if (SSpace == string::npos)
  258. continue;
  259. string Word1 = string(*I,Space,SSpace-Space);
  260. string Prefix = string(*I,0,Space);
  261. for (vector<string>::iterator J = List.begin(); J != I; J++)
  262. {
  263. // Find a space..
  264. string::size_type Space2 = (*J).find(' ');
  265. if (Space2 == string::npos)
  266. continue;
  267. string::size_type SSpace2 = (*J).find(' ',Space2 + 1);
  268. if (SSpace2 == string::npos)
  269. continue;
  270. if (string(*J,0,Space2) != Prefix)
  271. continue;
  272. if (string(*J,Space2,SSpace2-Space2) != Word1)
  273. continue;
  274. *J += string(*I,SSpace);
  275. *I = string();
  276. }
  277. }
  278. // Wipe erased entries
  279. for (unsigned int I = 0; I < List.size();)
  280. {
  281. if (List[I].empty() == false)
  282. I++;
  283. else
  284. List.erase(List.begin()+I);
  285. }
  286. }
  287. /*}}}*/
  288. // WriteDatabase - Write the CDROM Database file /*{{{*/
  289. // ---------------------------------------------------------------------
  290. /* We rewrite the configuration class associated with the cdrom database. */
  291. bool pkgCdrom::WriteDatabase(Configuration &Cnf)
  292. {
  293. string DFile = _config->FindFile("Dir::State::cdroms");
  294. string NewFile = DFile + ".new";
  295. unlink(NewFile.c_str());
  296. ofstream Out(NewFile.c_str());
  297. if (!Out)
  298. return _error->Errno("ofstream::ofstream",
  299. "Failed to open %s.new",DFile.c_str());
  300. /* Write out all of the configuration directives by walking the
  301. configuration tree */
  302. const Configuration::Item *Top = Cnf.Tree(0);
  303. for (; Top != 0;)
  304. {
  305. // Print the config entry
  306. if (Top->Value.empty() == false)
  307. Out << Top->FullTag() + " \"" << Top->Value << "\";" << endl;
  308. if (Top->Child != 0)
  309. {
  310. Top = Top->Child;
  311. continue;
  312. }
  313. while (Top != 0 && Top->Next == 0)
  314. Top = Top->Parent;
  315. if (Top != 0)
  316. Top = Top->Next;
  317. }
  318. Out.close();
  319. rename(DFile.c_str(),string(DFile + '~').c_str());
  320. if (rename(NewFile.c_str(),DFile.c_str()) != 0)
  321. return _error->Errno("rename","Failed to rename %s.new to %s",
  322. DFile.c_str(),DFile.c_str());
  323. return true;
  324. }
  325. /*}}}*/
  326. // WriteSourceList - Write an updated sourcelist /*{{{*/
  327. // ---------------------------------------------------------------------
  328. /* This reads the old source list and copies it into the new one. It
  329. appends the new CDROM entires just after the first block of comments.
  330. This places them first in the file. It also removes any old entries
  331. that were the same. */
  332. bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
  333. {
  334. if (List.size() == 0)
  335. return true;
  336. string File = _config->FindFile("Dir::Etc::sourcelist");
  337. // Open the stream for reading
  338. ifstream F((FileExists(File)?File.c_str():"/dev/null"),
  339. ios::in );
  340. if (!F != 0)
  341. return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
  342. string NewFile = File + ".new";
  343. unlink(NewFile.c_str());
  344. ofstream Out(NewFile.c_str());
  345. if (!Out)
  346. return _error->Errno("ofstream::ofstream",
  347. "Failed to open %s.new",File.c_str());
  348. // Create a short uri without the path
  349. string ShortURI = "cdrom:[" + Name + "]/";
  350. string ShortURI2 = "cdrom:" + Name + "/"; // For Compatibility
  351. string Type;
  352. if (Source == true)
  353. Type = "deb-src";
  354. else
  355. Type = "deb";
  356. char Buffer[300];
  357. int CurLine = 0;
  358. bool First = true;
  359. while (F.eof() == false)
  360. {
  361. F.getline(Buffer,sizeof(Buffer));
  362. CurLine++;
  363. _strtabexpand(Buffer,sizeof(Buffer));
  364. _strstrip(Buffer);
  365. // Comment or blank
  366. if (Buffer[0] == '#' || Buffer[0] == 0)
  367. {
  368. Out << Buffer << endl;
  369. continue;
  370. }
  371. if (First == true)
  372. {
  373. for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
  374. {
  375. string::size_type Space = (*I).find(' ');
  376. if (Space == string::npos)
  377. return _error->Error("Internal error");
  378. Out << Type << " cdrom:[" << Name << "]/" << string(*I,0,Space) <<
  379. " " << string(*I,Space+1) << endl;
  380. }
  381. }
  382. First = false;
  383. // Grok it
  384. string cType;
  385. string URI;
  386. const char *C = Buffer;
  387. if (ParseQuoteWord(C,cType) == false ||
  388. ParseQuoteWord(C,URI) == false)
  389. {
  390. Out << Buffer << endl;
  391. continue;
  392. }
  393. // Emit lines like this one
  394. if (cType != Type || (string(URI,0,ShortURI.length()) != ShortURI &&
  395. string(URI,0,ShortURI.length()) != ShortURI2))
  396. {
  397. Out << Buffer << endl;
  398. continue;
  399. }
  400. }
  401. // Just in case the file was empty
  402. if (First == true)
  403. {
  404. for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
  405. {
  406. string::size_type Space = (*I).find(' ');
  407. if (Space == string::npos)
  408. return _error->Error("Internal error");
  409. Out << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) <<
  410. " " << string(*I,Space+1) << endl;
  411. }
  412. }
  413. Out.close();
  414. rename(File.c_str(),string(File + '~').c_str());
  415. if (rename(NewFile.c_str(),File.c_str()) != 0)
  416. return _error->Errno("rename","Failed to rename %s.new to %s",
  417. File.c_str(),File.c_str());
  418. return true;
  419. }
  420. bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
  421. {
  422. stringstream msg;
  423. // Startup
  424. string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
  425. if (CDROM[0] == '.')
  426. CDROM= SafeGetCWD() + '/' + CDROM;
  427. if(log) {
  428. msg.str("");
  429. ioprintf(msg, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
  430. CDROM.c_str());
  431. log->Update(msg.str());
  432. }
  433. if (MountCdrom(CDROM) == false)
  434. return _error->Error("Failed to mount the cdrom.");
  435. // Hash the CD to get an ID
  436. if(log)
  437. log->Update(_("Identifying.. "));
  438. if (IdentCdrom(CDROM,ident) == false)
  439. {
  440. ident = "";
  441. return false;
  442. }
  443. msg.str("");
  444. ioprintf(msg, "[%s]\n",ident.c_str());
  445. log->Update(msg.str());
  446. // Read the database
  447. Configuration Database;
  448. string DFile = _config->FindFile("Dir::State::cdroms");
  449. if (FileExists(DFile) == true)
  450. {
  451. if (ReadConfigFile(Database,DFile) == false)
  452. return _error->Error("Unable to read the cdrom database %s",
  453. DFile.c_str());
  454. }
  455. if(log) {
  456. msg.str("");
  457. ioprintf(msg, _("Stored label: %s \n"),
  458. Database.Find("CD::"+ident).c_str());
  459. log->Update(msg.str());
  460. }
  461. return true;
  462. }
  463. bool pkgCdrom::Add(pkgCdromStatus *log)
  464. {
  465. stringstream msg;
  466. // Startup
  467. string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
  468. if (CDROM[0] == '.')
  469. CDROM= SafeGetCWD() + '/' + CDROM;
  470. if(log) {
  471. log->SetTotal(STEP_LAST);
  472. msg.str("");
  473. ioprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str());
  474. log->Update(msg.str(), STEP_PREPARE);
  475. }
  476. // Read the database
  477. Configuration Database;
  478. string DFile = _config->FindFile("Dir::State::cdroms");
  479. if (FileExists(DFile) == true)
  480. {
  481. if (ReadConfigFile(Database,DFile) == false)
  482. return _error->Error("Unable to read the cdrom database %s",
  483. DFile.c_str());
  484. }
  485. // Unmount the CD and get the user to put in the one they want
  486. if (_config->FindB("APT::CDROM::NoMount",false) == false)
  487. {
  488. if(log)
  489. log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT);
  490. UnmountCdrom(CDROM);
  491. if(log) {
  492. log->Update(_("Waiting for disc...\n"), STEP_WAIT);
  493. if(!log->ChangeCdrom()) {
  494. // user aborted
  495. return false;
  496. }
  497. }
  498. // Mount the new CDROM
  499. log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT);
  500. if (MountCdrom(CDROM) == false)
  501. return _error->Error("Failed to mount the cdrom.");
  502. }
  503. // Hash the CD to get an ID
  504. if(log)
  505. log->Update(_("Identifying.. "), STEP_IDENT);
  506. string ID;
  507. if (IdentCdrom(CDROM,ID) == false)
  508. {
  509. log->Update("\n");
  510. return false;
  511. }
  512. if(log)
  513. log->Update("["+ID+"]\n");
  514. if(log)
  515. log->Update(_("Scanning disc for index files..\n"),STEP_SCAN);
  516. // Get the CD structure
  517. vector<string> List;
  518. vector<string> SourceList;
  519. vector<string> SigList;
  520. string StartDir = SafeGetCWD();
  521. string InfoDir;
  522. if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false)
  523. {
  524. log->Update("\n");
  525. return false;
  526. }
  527. chdir(StartDir.c_str());
  528. if (_config->FindB("Debug::aptcdrom",false) == true)
  529. {
  530. cout << "I found (binary):" << endl;
  531. for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
  532. cout << *I << endl;
  533. cout << "I found (source):" << endl;
  534. for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
  535. cout << *I << endl;
  536. cout << "I found (Signatures):" << endl;
  537. for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); I++)
  538. cout << *I << endl;
  539. }
  540. //log->Update(_("Cleaning package lists..."), STEP_CLEAN);
  541. // Fix up the list
  542. DropBinaryArch(List);
  543. DropRepeats(List,"Packages");
  544. DropRepeats(SourceList,"Sources");
  545. DropRepeats(SigList,"Release.gpg");
  546. if(log) {
  547. msg.str("");
  548. ioprintf(msg, _("Found %i package indexes, %i source indexes and "
  549. "%i signatures\n"),
  550. List.size(), SourceList.size(), SigList.size());
  551. log->Update(msg.str(), STEP_SCAN);
  552. }
  553. if (List.size() == 0 && SourceList.size() == 0)
  554. return _error->Error("Unable to locate any package files, perhaps this is not a Debian Disc");
  555. // Check if the CD is in the database
  556. string Name;
  557. if (Database.Exists("CD::" + ID) == false ||
  558. _config->FindB("APT::CDROM::Rename",false) == true)
  559. {
  560. // Try to use the CDs label if at all possible
  561. if (InfoDir.empty() == false &&
  562. FileExists(InfoDir + "/info") == true)
  563. {
  564. ifstream F(string(InfoDir + "/info").c_str());
  565. if (!F == 0)
  566. getline(F,Name);
  567. if (Name.empty() == false)
  568. {
  569. // Escape special characters
  570. string::iterator J = Name.begin();
  571. for (; J != Name.end(); J++)
  572. if (*J == '"' || *J == ']' || *J == '[')
  573. *J = '_';
  574. if(log) {
  575. msg.str("");
  576. ioprintf(msg, "Found label '%s'\n", Name.c_str());
  577. log->Update(msg.str());
  578. }
  579. Database.Set("CD::" + ID + "::Label",Name);
  580. }
  581. }
  582. if (_config->FindB("APT::CDROM::Rename",false) == true ||
  583. Name.empty() == true)
  584. {
  585. if(!log)
  586. return _error->Error("No disc name found and no way to ask for it");
  587. while(true) {
  588. if(!log->AskCdromName(Name)) {
  589. // user canceld
  590. return false;
  591. }
  592. cout << "Name: '" << Name << "'" << endl;
  593. if (Name.empty() == false &&
  594. Name.find('"') == string::npos &&
  595. Name.find('[') == string::npos &&
  596. Name.find(']') == string::npos)
  597. break;
  598. log->Update(_("That is not a valid name, try again.\n"));
  599. }
  600. }
  601. }
  602. else
  603. Name = Database.Find("CD::" + ID);
  604. // Escape special characters
  605. string::iterator J = Name.begin();
  606. for (; J != Name.end(); J++)
  607. if (*J == '"' || *J == ']' || *J == '[')
  608. *J = '_';
  609. Database.Set("CD::" + ID,Name);
  610. if(log) {
  611. msg.str("");
  612. ioprintf(msg, _("This disc is called: \n'%s'\n"), Name.c_str());
  613. log->Update(msg.str());
  614. }
  615. log->Update(_("Copying package lists..."), STEP_COPY);
  616. // take care of the signatures and copy them if they are ok
  617. // (we do this before PackageCopy as it modifies "List" and "SourceList")
  618. SigVerify SignVerify;
  619. SignVerify.CopyAndVerify(CDROM, Name, SigList, List, SourceList);
  620. // Copy the package files to the state directory
  621. PackageCopy Copy;
  622. SourceCopy SrcCopy;
  623. if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
  624. SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false)
  625. return false;
  626. // reduce the List so that it takes less space in sources.list
  627. ReduceSourcelist(CDROM,List);
  628. ReduceSourcelist(CDROM,SourceList);
  629. // Write the database and sourcelist
  630. if (_config->FindB("APT::cdrom::NoAct",false) == false)
  631. {
  632. if (WriteDatabase(Database) == false)
  633. return false;
  634. if(log) {
  635. log->Update(_("Writing new source list\n"), STEP_WRITE);
  636. }
  637. if (WriteSourceList(Name,List,false) == false ||
  638. WriteSourceList(Name,SourceList,true) == false)
  639. return false;
  640. }
  641. // Print the sourcelist entries
  642. if(log)
  643. log->Update(_("Source list entries for this disc are:\n"));
  644. for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
  645. {
  646. string::size_type Space = (*I).find(' ');
  647. if (Space == string::npos)
  648. return _error->Error("Internal error");
  649. if(log) {
  650. msg.str("");
  651. msg << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) <<
  652. " " << string(*I,Space+1) << endl;
  653. log->Update(msg.str());
  654. }
  655. }
  656. for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
  657. {
  658. string::size_type Space = (*I).find(' ');
  659. if (Space == string::npos)
  660. return _error->Error("Internal error");
  661. if(log) {
  662. msg.str("");
  663. msg << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) <<
  664. " " << string(*I,Space+1) << endl;
  665. log->Update(msg.str());
  666. }
  667. }
  668. // Unmount and finish
  669. if (_config->FindB("APT::CDROM::NoMount",false) == false) {
  670. log->Update(_("Unmounting CD-ROM..."), STEP_LAST);
  671. UnmountCdrom(CDROM);
  672. }
  673. return true;
  674. }