You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

206 lines
5.0 KiB

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