summaryrefslogtreecommitdiff
path: root/apt-inst/dirstream.cc
blob: 41dbf44034bb85a24417179f441508b4dc9536fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// -*- mode: cpp; mode: fold -*-
// Description								/*{{{*/
// $Id: dirstream.cc,v 1.2 2001/02/20 07:03:16 jgg Exp $
/* ######################################################################

   Directory Stream 
   
   This class provides a simple basic extractor that can be used for
   a number of purposes.
   
   ##################################################################### */
									/*}}}*/
// Include Files							/*{{{*/
#ifdef __GNUG__
#pragma implementation "apt-pkg/dirstream.h"
#endif

#include <apt-pkg/dirstream.h>
#include <apt-pkg/error.h>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <utime.h>
#include <unistd.h>
									/*}}}*/

// DirStream::DoItem - Process an item					/*{{{*/
// ---------------------------------------------------------------------
/* This is a very simple extractor, it does not deal with things like
   overwriting directories with files and so on. */
bool pkgDirStream::DoItem(Item &Itm,int &Fd)
{
   switch (Itm.Type)
   {
      case Item::File:
      {
	 /* Open the output file, NDELAY is used to prevent this from 
	    blowing up on device special files.. */
	 int iFd = open(Itm.Name,O_NDELAY|O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,
		       Itm.Mode);
	 if (iFd < 0)
	    return _error->Errno("open","Failed write file %s",
				 Itm.Name);
	 
	 // fchmod deals with umask and fchown sets the ownership
	 if (fchmod(iFd,Itm.Mode) != 0)
	    return _error->Errno("fchmod","Failed write file %s",
				 Itm.Name);
	 if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
	    return _error->Errno("fchown","Failed write file %s",
				 Itm.Name);
	 Fd = iFd;
	 return true;
      }
      
      case Item::HardLink:
      case Item::SymbolicLink:
      case Item::CharDevice:
      case Item::BlockDevice:
      case Item::Directory:
      case Item::FIFO:
      break;
   }
   
   return true;
}
									/*}}}*/
// DirStream::FinishedFile - Finished processing a file			/*{{{*/
// ---------------------------------------------------------------------
/* */
bool pkgDirStream::FinishedFile(Item &Itm,int Fd)
{
   if (Fd < 0)
      return true;
   
   if (close(Fd) != 0)
      return _error->Errno("close","Failed to close file %s",Itm.Name);

   /* Set the modification times. The only way it can fail is if someone
      has futzed with our file, which is intolerable :> */
   struct utimbuf Time;
   Time.actime = Itm.MTime;
   Time.modtime = Itm.MTime;
   if (utime(Itm.Name,&Time) != 0)
      _error->Errno("utime","Failed to close file %s",Itm.Name);
   
   return true;   
}
									/*}}}*/
// DirStream::Fail - Failed processing a file				/*{{{*/
// ---------------------------------------------------------------------
/* */
bool pkgDirStream::Fail(Item &Itm,int Fd)
{
   if (Fd < 0)
      return true;
   
   close(Fd);
   return false;
}
									/*}}}*/