acquire-method.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: acquire-method.cc,v 1.9 1998/11/29 01:24:15 jgg Exp $
  4. /* ######################################################################
  5. Acquire Method
  6. ##################################################################### */
  7. /*}}}*/
  8. // Include Files /*{{{*/
  9. #ifdef __GNUG__
  10. #pragma implementation "apt-pkg/acquire-method.h"
  11. #endif
  12. #include <apt-pkg/acquire-method.h>
  13. #include <apt-pkg/error.h>
  14. #include <apt-pkg/configuration.h>
  15. #include <strutl.h>
  16. #include <apt-pkg/fileutl.h>
  17. #include <stdio.h>
  18. /*}}}*/
  19. // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
  20. // ---------------------------------------------------------------------
  21. /* This constructs the initialization text */
  22. pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
  23. {
  24. char S[300] = "";
  25. char *End = S;
  26. strcat(End,"100 Capabilities\n");
  27. sprintf(End+strlen(End),"Version: %s\n",Ver);
  28. if ((Flags & SingleInstance) == SingleInstance)
  29. strcat(End,"Single-Instance: true\n");
  30. if ((Flags & Pipeline) == Pipeline)
  31. strcat(End,"Pipeline: true\n");
  32. if ((Flags & SendConfig) == SendConfig)
  33. strcat(End,"Send-Config: true\n");
  34. if ((Flags & LocalOnly) == LocalOnly)
  35. strcat(End,"Local-Only: true\n");
  36. strcat(End,"\n");
  37. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  38. exit(100);
  39. SetNonBlock(STDIN_FILENO,true);
  40. Queue = 0;
  41. }
  42. /*}}}*/
  43. // AcqMethod::Fail - A fetch has failed /*{{{*/
  44. // ---------------------------------------------------------------------
  45. /* */
  46. void pkgAcqMethod::Fail(bool Transient)
  47. {
  48. string Err = "Undetermined Error";
  49. if (_error->empty() == false)
  50. _error->PopMessage(Err);
  51. _error->Discard();
  52. Fail(Err,Transient);
  53. }
  54. /*}}}*/
  55. // AcqMethod::Fail - A fetch has failed /*{{{*/
  56. // ---------------------------------------------------------------------
  57. /* */
  58. void pkgAcqMethod::Fail(string Err,bool Transient)
  59. {
  60. char S[1024];
  61. if (Queue != 0)
  62. {
  63. snprintf(S,sizeof(S),"400 URI Failure\nURI: %s\n"
  64. "Message: %s\n",Queue->Uri.c_str(),Err.c_str());
  65. // Dequeue
  66. FetchItem *Tmp = Queue;
  67. Queue = Queue->Next;
  68. delete Tmp;
  69. }
  70. else
  71. snprintf(S,sizeof(S),"400 URI Failure\nURI: <UNKNOWN>\n"
  72. "Message: %s\n",Err.c_str());
  73. // Set the transient flag
  74. if (Transient == true)
  75. strcat(S,"Transient-Failure: true\n\n");
  76. else
  77. strcat(S,"\n");
  78. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  79. exit(100);
  80. }
  81. /*}}}*/
  82. // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
  83. // ---------------------------------------------------------------------
  84. /* */
  85. void pkgAcqMethod::URIStart(FetchResult &Res)
  86. {
  87. if (Queue == 0)
  88. abort();
  89. char S[1024] = "";
  90. char *End = S;
  91. End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",Queue->Uri.c_str());
  92. if (Res.Size != 0)
  93. End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
  94. if (Res.LastModified != 0)
  95. End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
  96. TimeRFC1123(Res.LastModified).c_str());
  97. if (Res.ResumePoint != 0)
  98. End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
  99. Res.ResumePoint);
  100. strcat(End,"\n");
  101. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  102. exit(100);
  103. }
  104. /*}}}*/
  105. // AcqMethod::URIDone - A URI is finished /*{{{*/
  106. // ---------------------------------------------------------------------
  107. /* */
  108. void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
  109. {
  110. if (Queue == 0)
  111. abort();
  112. char S[1024] = "";
  113. char *End = S;
  114. End += snprintf(S,sizeof(S),"201 URI Done\nURI: %s\n",Queue->Uri.c_str());
  115. if (Res.Filename.empty() == false)
  116. End += snprintf(End,sizeof(S) - (End - S),"Filename: %s\n",Res.Filename.c_str());
  117. if (Res.Size != 0)
  118. End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
  119. if (Res.LastModified != 0)
  120. End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
  121. TimeRFC1123(Res.LastModified).c_str());
  122. if (Res.MD5Sum.empty() == false)
  123. End += snprintf(End,sizeof(S) - (End - S),"MD5Sum: %s\n",Res.MD5Sum.c_str());
  124. if (Res.ResumePoint != 0)
  125. End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
  126. Res.ResumePoint);
  127. if (Res.IMSHit == true)
  128. strcat(End,"IMS-Hit: true\n");
  129. End = S + strlen(S);
  130. if (Alt != 0)
  131. {
  132. if (Alt->Filename.empty() == false)
  133. End += snprintf(End,sizeof(S) - (End - S),"Alt-Filename: %s\n",Alt->Filename.c_str());
  134. if (Alt->Size != 0)
  135. End += snprintf(End,sizeof(S) - (End - S),"Alt-Size: %u\n",Alt->Size);
  136. if (Alt->LastModified != 0)
  137. End += snprintf(End,sizeof(S) - (End - S),"Alt-Last-Modified: %s\n",
  138. TimeRFC1123(Alt->LastModified).c_str());
  139. if (Alt->MD5Sum.empty() == false)
  140. End += snprintf(End,sizeof(S) - (End - S),"Alt-MD5Sum: %s\n",
  141. Alt->MD5Sum.c_str());
  142. if (Alt->IMSHit == true)
  143. strcat(End,"Alt-IMS-Hit: true\n");
  144. }
  145. strcat(End,"\n");
  146. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  147. exit(100);
  148. // Dequeue
  149. FetchItem *Tmp = Queue;
  150. Queue = Queue->Next;
  151. delete Tmp;
  152. }
  153. /*}}}*/
  154. // AcqMethod::Configuration - Handle the configuration message /*{{{*/
  155. // ---------------------------------------------------------------------
  156. /* This parses each configuration entry and puts it into the _config
  157. Configuration class. */
  158. bool pkgAcqMethod::Configuration(string Message)
  159. {
  160. ::Configuration &Cnf = *_config;
  161. const char *I = Message.begin();
  162. unsigned int Length = strlen("Config-Item");
  163. for (; I + Length < Message.end(); I++)
  164. {
  165. // Not a config item
  166. if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
  167. continue;
  168. I += Length + 1;
  169. for (; I < Message.end() && *I == ' '; I++);
  170. const char *Equals = I;
  171. for (; Equals < Message.end() && *Equals != '='; Equals++);
  172. const char *End = Equals;
  173. for (; End < Message.end() && *End != '\n'; End++);
  174. if (End == Equals)
  175. return false;
  176. Cnf.Set(string(I,Equals-I),string(Equals+1,End-Equals-1));
  177. I = End;
  178. }
  179. return true;
  180. }
  181. /*}}}*/
  182. // AcqMethod::Run - Run the message engine /*{{{*/
  183. // ---------------------------------------------------------------------
  184. /* */
  185. int pkgAcqMethod::Run(bool Single)
  186. {
  187. while (1)
  188. {
  189. // Block if the message queue is empty
  190. if (Messages.empty() == true)
  191. {
  192. if (Single == false)
  193. if (WaitFd(STDIN_FILENO) == false)
  194. return 0;
  195. if (ReadMessages(STDIN_FILENO,Messages) == false)
  196. return 0;
  197. }
  198. // Single mode exits if the message queue is empty
  199. if (Single == true && Messages.empty() == true)
  200. return 0;
  201. string Message = Messages.front();
  202. Messages.erase(Messages.begin());
  203. // Fetch the message number
  204. char *End;
  205. int Number = strtol(Message.c_str(),&End,10);
  206. if (End == Message.c_str())
  207. {
  208. cerr << "Malformed message!" << endl;
  209. return 100;
  210. }
  211. switch (Number)
  212. {
  213. case 601:
  214. if (Configuration(Message) == false)
  215. return 100;
  216. break;
  217. case 600:
  218. {
  219. FetchItem *Tmp = new FetchItem;
  220. Tmp->Uri = LookupTag(Message,"URI");
  221. Tmp->DestFile = LookupTag(Message,"FileName");
  222. if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false)
  223. Tmp->LastModified = 0;
  224. Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
  225. Tmp->Next = 0;
  226. // Append it to the list
  227. FetchItem **I = &Queue;
  228. for (; *I != 0; I = &(*I)->Next);
  229. *I = Tmp;
  230. // Notify that this item is to be fetched.
  231. if (Fetch(Tmp) == false)
  232. Fail();
  233. break;
  234. }
  235. }
  236. }
  237. return 0;
  238. }
  239. /*}}}*/
  240. // AcqMethod::Log - Send a log message /*{{{*/
  241. // ---------------------------------------------------------------------
  242. /* */
  243. void pkgAcqMethod::Log(const char *Format,...)
  244. {
  245. string CurrentURI = "<UNKNOWN>";
  246. if (Queue != 0)
  247. CurrentURI = Queue->Uri;
  248. va_list args;
  249. va_start(args,Format);
  250. // sprintf the description
  251. char S[1024];
  252. unsigned int Len = snprintf(S,sizeof(S),"101 Log\nURI: %s\n"
  253. "Message: ",CurrentURI.c_str());
  254. vsnprintf(S+Len,sizeof(S)-Len,Format,args);
  255. strcat(S,"\n\n");
  256. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  257. exit(100);
  258. }
  259. /*}}}*/
  260. // AcqMethod::Status - Send a status message /*{{{*/
  261. // ---------------------------------------------------------------------
  262. /* */
  263. void pkgAcqMethod::Status(const char *Format,...)
  264. {
  265. string CurrentURI = "<UNKNOWN>";
  266. if (Queue != 0)
  267. CurrentURI = Queue->Uri;
  268. va_list args;
  269. va_start(args,Format);
  270. // sprintf the description
  271. char S[1024];
  272. unsigned int Len = snprintf(S,sizeof(S),"102 Status\nURI: %s\n"
  273. "Message: ",CurrentURI.c_str());
  274. vsnprintf(S+Len,sizeof(S)-Len,Format,args);
  275. strcat(S,"\n\n");
  276. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  277. exit(100);
  278. }
  279. /*}}}*/
  280. // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
  281. // ---------------------------------------------------------------------
  282. /* */
  283. pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
  284. IMSHit(false), Size(0), ResumePoint(0)
  285. {
  286. }
  287. /*}}}*/