gzip.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: gzip.cc,v 1.2 1998/10/26 07:11:53 jgg Exp $
  4. /* ######################################################################
  5. GZip method - Take a file URI in and decompress it into the target
  6. file.
  7. ##################################################################### */
  8. /*}}}*/
  9. // Include Files /*{{{*/
  10. #include <apt-pkg/fileutl.h>
  11. #include <apt-pkg/error.h>
  12. #include <apt-pkg/configuration.h>
  13. #include <apt-pkg/acquire-worker.h>
  14. #include <strutl.h>
  15. #include <sys/stat.h>
  16. #include <unistd.h>
  17. #include <utime.h>
  18. #include <wait.h>
  19. #include <stdio.h>
  20. /*}}}*/
  21. // Fail - Generate a failure message /*{{{*/
  22. // ---------------------------------------------------------------------
  23. /* */
  24. void Fail(string URI)
  25. {
  26. string Err = "Undetermined Error";
  27. if (_error->empty() == false)
  28. _error->PopMessage(Err);
  29. printf("400 URI Failure\n"
  30. "URI: %s\n"
  31. "Message: %s\n\n",URI.c_str(),Err.c_str());
  32. _error->Discard();
  33. }
  34. /*}}}*/
  35. int main()
  36. {
  37. setlinebuf(stdout);
  38. SetNonBlock(STDIN_FILENO,true);
  39. printf("100 Capabilities\n"
  40. "Version: 1.0\n"
  41. "Pipeline: true\n"
  42. "Send-Config: true\n\n");
  43. vector<string> Messages;
  44. while (1)
  45. {
  46. if (WaitFd(STDIN_FILENO) == false ||
  47. ReadMessages(STDIN_FILENO,Messages) == false)
  48. return 0;
  49. while (Messages.empty() == false)
  50. {
  51. string Message = Messages.front();
  52. Messages.erase(Messages.begin());
  53. // Fetch the message number
  54. char *End;
  55. int Number = strtol(Message.c_str(),&End,10);
  56. if (End == Message.c_str())
  57. {
  58. cerr << "Malformed message!" << endl;
  59. return 100;
  60. }
  61. // 601 configuration message
  62. if (Number == 601)
  63. {
  64. pkgInjectConfiguration(Message,*_config);
  65. continue;
  66. }
  67. // 600 URI Fetch message
  68. if (Number != 600)
  69. continue;
  70. // Grab the URI bit
  71. string URI = LookupTag(Message,"URI");
  72. string Target = LookupTag(Message,"Filename");
  73. // Grab the filename
  74. string::size_type Pos = URI.find(':');
  75. if (Pos == string::npos)
  76. {
  77. _error->Error("Invalid message");
  78. Fail(URI);
  79. continue;
  80. }
  81. string File = string(URI,Pos+1);
  82. // Start the reply message
  83. string Result = "201 URI Done";
  84. Result += "\nURI: " + URI;
  85. Result += "\nFileName: " + Target;
  86. // See if the file exists
  87. FileFd From(File,FileFd::ReadOnly);
  88. FileFd To(Target,FileFd::WriteEmpty);
  89. To.EraseOnFailure();
  90. if (_error->PendingError() == true)
  91. {
  92. Fail(URI);
  93. continue;
  94. }
  95. // Fork gzip
  96. int Process = fork();
  97. if (Process < 0)
  98. {
  99. _error->Errno("fork","Couldn't fork gzip");
  100. Fail(URI);
  101. continue;
  102. }
  103. // The child
  104. if (Process == 0)
  105. {
  106. dup2(From.Fd(),STDIN_FILENO);
  107. dup2(To.Fd(),STDOUT_FILENO);
  108. From.Close();
  109. To.Close();
  110. SetCloseExec(STDIN_FILENO,false);
  111. SetCloseExec(STDOUT_FILENO,false);
  112. const char *Args[3];
  113. Args[0] = _config->Find("Dir::bin::gzip","gzip").c_str();
  114. Args[1] = "-d";
  115. Args[2] = 0;
  116. execvp(Args[0],(char **)Args);
  117. exit(100);
  118. }
  119. From.Close();
  120. // Wait for gzip to finish
  121. int Status;
  122. if (waitpid(Process,&Status,0) != Process)
  123. {
  124. To.OpFail();
  125. _error->Errno("wait","Waiting for gzip failed");
  126. Fail(URI);
  127. continue;
  128. }
  129. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
  130. {
  131. To.OpFail();
  132. _error->Error("gzip failed, perhaps the disk is full or the directory permissions are wrong.");
  133. Fail(URI);
  134. continue;
  135. }
  136. To.Close();
  137. // Transfer the modification times
  138. struct stat Buf;
  139. if (stat(File.c_str(),&Buf) != 0)
  140. {
  141. _error->Errno("stat","Failed to stat");
  142. Fail(URI);
  143. continue;
  144. }
  145. struct utimbuf TimeBuf;
  146. TimeBuf.actime = Buf.st_atime;
  147. TimeBuf.modtime = Buf.st_mtime;
  148. if (utime(Target.c_str(),&TimeBuf) != 0)
  149. {
  150. _error->Errno("utime","Failed to set modification time");
  151. Fail(URI);
  152. continue;
  153. }
  154. // Send the message
  155. Result += "\n\n";
  156. if (write(STDOUT_FILENO,Result.begin(),Result.length()) !=
  157. (signed)Result.length())
  158. return 100;
  159. }
  160. }
  161. return 0;
  162. }