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.
 
 
 
 
 
 

119 lines
3.2 KiB

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