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.
 
 
 
 
 
 

122 lines
3.3 KiB

  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: dirstream.cc,v 1.3.2.1 2004/01/16 18:58:50 mdz Exp $
  4. /* ######################################################################
  5. Directory Stream
  6. This class provides a simple basic extractor that can be used for
  7. a number of purposes.
  8. ##################################################################### */
  9. /*}}}*/
  10. // Include Files /*{{{*/
  11. #include<config.h>
  12. #include <apt-pkg/dirstream.h>
  13. #include <apt-pkg/error.h>
  14. #include <fcntl.h>
  15. #include <sys/stat.h>
  16. #include <sys/types.h>
  17. #include <sys/time.h>
  18. #include <errno.h>
  19. #include <unistd.h>
  20. #include <apti18n.h>
  21. /*}}}*/
  22. // DirStream::DoItem - Process an item /*{{{*/
  23. // ---------------------------------------------------------------------
  24. /* This is a very simple extractor, it does not deal with things like
  25. overwriting directories with files and so on. */
  26. bool pkgDirStream::DoItem(Item &Itm,int &Fd)
  27. {
  28. switch (Itm.Type)
  29. {
  30. case Item::File:
  31. {
  32. /* Open the output file, NDELAY is used to prevent this from
  33. blowing up on device special files.. */
  34. int iFd = open(Itm.Name,O_NDELAY|O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,
  35. Itm.Mode);
  36. if (iFd < 0)
  37. return _error->Errno("open",_("Failed to write file %s"),
  38. Itm.Name);
  39. // fchmod deals with umask and fchown sets the ownership
  40. if (fchmod(iFd,Itm.Mode) != 0)
  41. {
  42. close(iFd);
  43. return _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
  44. }
  45. if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
  46. {
  47. close(iFd);
  48. return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
  49. }
  50. Fd = iFd;
  51. return true;
  52. }
  53. case Item::HardLink:
  54. case Item::SymbolicLink:
  55. case Item::CharDevice:
  56. case Item::BlockDevice:
  57. case Item::Directory:
  58. {
  59. struct stat Buf;
  60. // check if the dir is already there, if so return true
  61. if (stat(Itm.Name,&Buf) == 0)
  62. {
  63. if(S_ISDIR(Buf.st_mode))
  64. return true;
  65. // something else is there already, return false
  66. return false;
  67. }
  68. // nothing here, create the dir
  69. if(mkdir(Itm.Name,Itm.Mode) < 0)
  70. return false;
  71. return true;
  72. break;
  73. }
  74. case Item::FIFO:
  75. break;
  76. }
  77. return true;
  78. }
  79. /*}}}*/
  80. // DirStream::FinishedFile - Finished processing a file /*{{{*/
  81. // ---------------------------------------------------------------------
  82. /* */
  83. bool pkgDirStream::FinishedFile(Item &Itm,int Fd)
  84. {
  85. if (Fd < 0)
  86. return true;
  87. /* Set the modification times. The only way it can fail is if someone
  88. has futzed with our file, which is intolerable :> */
  89. struct timeval times[2];
  90. times[0].tv_sec = times[1].tv_sec = Itm.MTime;
  91. times[0].tv_usec = times[1].tv_usec = 0;
  92. if (utimes(Itm.Name, times) != 0)
  93. _error->Errno("utimes", "Failed to set modification time for %s",Itm.Name);
  94. if (close(Fd) != 0)
  95. return _error->Errno("close",_("Failed to close file %s"),Itm.Name);
  96. return true;
  97. }
  98. /*}}}*/
  99. // DirStream::Fail - Failed processing a file /*{{{*/
  100. // ---------------------------------------------------------------------
  101. /* */
  102. bool pkgDirStream::Fail(Item &Itm,int Fd)
  103. {
  104. if (Fd < 0)
  105. return true;
  106. close(Fd);
  107. return false;
  108. }
  109. /*}}}*/