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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
/* ######################################################################
Directory Stream
This class provides a simple basic extractor that can be used for
a number of purposes.
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
#include <config.h>
#include <apt-pkg/dirstream.h>
#include <apt-pkg/error.h>
#include <cerrno>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <apti18n.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 to write file %s"),
Itm.Name);
// fchmod deals with umask and fchown sets the ownership
if (fchmod(iFd,Itm.Mode) != 0)
{
close(iFd);
return _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
}
if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
{
close(iFd);
return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
}
Fd = iFd;
return true;
}
case Item::HardLink:
case Item::SymbolicLink:
case Item::CharDevice:
case Item::BlockDevice:
case Item::Directory:
{
struct stat Buf;
// check if the dir is already there, if so return true
if (stat(Itm.Name,&Buf) == 0)
{
if(S_ISDIR(Buf.st_mode))
return true;
// something else is there already, return false
return false;
}
// nothing here, create the dir
if(mkdir(Itm.Name,Itm.Mode) < 0)
return false;
return true;
}
case Item::FIFO:
break;
}
return true;
}
/*}}}*/
// DirStream::FinishedFile - Finished processing a file /*{{{*/
// ---------------------------------------------------------------------
/* */
bool pkgDirStream::FinishedFile(Item &Itm,int Fd)
{
if (Fd < 0)
return true;
/* Set the modification times. The only way it can fail is if someone
has futzed with our file, which is intolerable :> */
struct timeval times[2];
times[0].tv_sec = times[1].tv_sec = Itm.MTime;
times[0].tv_usec = times[1].tv_usec = 0;
if (utimes(Itm.Name, times) != 0)
_error->Errno("utimes", "Failed to set modification time for %s",Itm.Name);
if (close(Fd) != 0)
return _error->Errno("close",_("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;
}
/*}}}*/
|