]>
Commit | Line | Data |
---|---|---|
1 | #include <config.h> | |
2 | ||
3 | #include <apt-pkg/error.h> | |
4 | #include <apt-pkg/fileutl.h> | |
5 | #include <apt-pkg/aptconfiguration.h> | |
6 | ||
7 | #include <string> | |
8 | #include <vector> | |
9 | #include <stdlib.h> | |
10 | #include <sys/stat.h> | |
11 | #include <string.h> | |
12 | ||
13 | #include "assert.h" | |
14 | ||
15 | static void assertStringEquals(char const * const expect, char const * const got, unsigned long const line) { | |
16 | if (strncmp(expect, got, strlen(expect)) == 0) | |
17 | return; | |
18 | OutputAssertEqual(expect, "==", got, line); | |
19 | } | |
20 | #define strequals(x,y) assertStringEquals(x, y, __LINE__) | |
21 | ||
22 | static bool | |
23 | TestFileFd(mode_t const a_umask, mode_t const ExpectedFilePermission, unsigned int const filemode, APT::Configuration::Compressor const &compressor) | |
24 | { | |
25 | FileFd f; | |
26 | struct stat buf; | |
27 | static const char* fname = "apt-filefd-test.txt"; | |
28 | if (FileExists(fname) == true) | |
29 | equals(unlink(fname), 0); | |
30 | ||
31 | umask(a_umask); | |
32 | equals(f.Open(fname, filemode, compressor), true); | |
33 | equals(f.IsOpen(), true); | |
34 | equals(f.Failed(), false); | |
35 | equals(umask(a_umask), a_umask); | |
36 | ||
37 | std::string test = "This is a test!\n"; | |
38 | equals(f.Write(test.c_str(), test.size()), true); | |
39 | equals(f.IsOpen(), true); | |
40 | equals(f.Failed(), false); | |
41 | ||
42 | f.Close(); | |
43 | equals(f.IsOpen(), false); | |
44 | equals(f.Failed(), false); | |
45 | ||
46 | equals(f.Open(fname, FileFd::ReadOnly, compressor), true); | |
47 | equals(f.IsOpen(), true); | |
48 | equals(f.Failed(), false); | |
49 | equals(f.Eof(), false); | |
50 | equalsNot(f.FileSize(), 0); | |
51 | equals(f.Failed(), false); | |
52 | equalsNot(f.ModificationTime(), 0); | |
53 | equals(f.Failed(), false); | |
54 | ||
55 | // ensure the memory is as predictably messed up | |
56 | # define APT_INIT_READBACK \ | |
57 | char readback[20]; \ | |
58 | memset(readback, 'D', sizeof(readback)/sizeof(readback[0])); \ | |
59 | readback[19] = '\0'; | |
60 | { | |
61 | APT_INIT_READBACK | |
62 | char const * const expect = "This"; | |
63 | equals(f.Read(readback, strlen(expect)), true); | |
64 | equals(f.Failed(), false); | |
65 | equals(f.Eof(), false); | |
66 | strequals(expect, readback); | |
67 | equals(strlen(expect), f.Tell()); | |
68 | } | |
69 | { | |
70 | APT_INIT_READBACK | |
71 | char const * const expect = "test!\n"; | |
72 | equals(f.Skip((test.size() - f.Tell()) - strlen(expect)), true); | |
73 | equals(f.Read(readback, strlen(expect)), true); | |
74 | equals(f.Failed(), false); | |
75 | equals(f.Eof(), false); | |
76 | strequals(expect, readback); | |
77 | equals(test.size(), f.Tell()); | |
78 | } | |
79 | { | |
80 | APT_INIT_READBACK | |
81 | equals(f.Seek(0), true); | |
82 | equals(f.Eof(), false); | |
83 | equals(f.Read(readback, 20, true), true); | |
84 | equals(f.Failed(), false); | |
85 | equals(f.Eof(), true); | |
86 | strequals(test.c_str(), readback); | |
87 | equals(f.Size(), f.Tell()); | |
88 | } | |
89 | { | |
90 | APT_INIT_READBACK | |
91 | equals(f.Seek(0), true); | |
92 | equals(f.Eof(), false); | |
93 | equals(f.Read(readback, test.size(), true), true); | |
94 | equals(f.Failed(), false); | |
95 | equals(f.Eof(), false); | |
96 | strequals(test.c_str(), readback); | |
97 | equals(f.Size(), f.Tell()); | |
98 | } | |
99 | { | |
100 | APT_INIT_READBACK | |
101 | equals(f.Seek(0), true); | |
102 | equals(f.Eof(), false); | |
103 | unsigned long long actual; | |
104 | equals(f.Read(readback, 20, &actual), true); | |
105 | equals(f.Failed(), false); | |
106 | equals(f.Eof(), true); | |
107 | equals(test.size(), actual); | |
108 | strequals(test.c_str(), readback); | |
109 | equals(f.Size(), f.Tell()); | |
110 | } | |
111 | { | |
112 | APT_INIT_READBACK | |
113 | equals(f.Seek(0), true); | |
114 | equals(f.Eof(), false); | |
115 | f.ReadLine(readback, 20); | |
116 | equals(f.Failed(), false); | |
117 | equals(f.Eof(), false); | |
118 | equals(test, readback); | |
119 | equals(f.Size(), f.Tell()); | |
120 | } | |
121 | { | |
122 | APT_INIT_READBACK | |
123 | equals(f.Seek(0), true); | |
124 | equals(f.Eof(), false); | |
125 | char const * const expect = "This"; | |
126 | f.ReadLine(readback, strlen(expect) + 1); | |
127 | equals(f.Failed(), false); | |
128 | equals(f.Eof(), false); | |
129 | strequals(expect, readback); | |
130 | equals(strlen(expect), f.Tell()); | |
131 | } | |
132 | #undef APT_INIT_READBACK | |
133 | ||
134 | f.Close(); | |
135 | equals(f.IsOpen(), false); | |
136 | equals(f.Failed(), false); | |
137 | ||
138 | // regression test for permission bug LP: #1304657 | |
139 | if (stat(fname, &buf) < 0) | |
140 | { | |
141 | _error->Errno("stat", "failed to stat"); | |
142 | return false; | |
143 | } | |
144 | equals(unlink(fname), 0); | |
145 | equals(buf.st_mode & 0777, ExpectedFilePermission); | |
146 | return true; | |
147 | } | |
148 | ||
149 | static bool TestFileFd(unsigned int const filemode) | |
150 | { | |
151 | std::vector<APT::Configuration::Compressor> compressors = APT::Configuration::getCompressors(); | |
152 | ||
153 | // testing the (un)compress via pipe, as the 'real' compressors are usually built in via libraries | |
154 | compressors.push_back(APT::Configuration::Compressor("rev", ".reversed", "rev", NULL, NULL, 42)); | |
155 | //compressors.push_back(APT::Configuration::Compressor("cat", ".ident", "cat", NULL, NULL, 42)); | |
156 | ||
157 | for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressors.begin(); c != compressors.end(); ++c) | |
158 | { | |
159 | if ((filemode & FileFd::ReadWrite) == FileFd::ReadWrite && | |
160 | (c->Name.empty() != true && c->Binary.empty() != true)) | |
161 | continue; | |
162 | if (TestFileFd(0002, 0664, filemode, *c) == false || | |
163 | TestFileFd(0022, 0644, filemode, *c) == false || | |
164 | TestFileFd(0077, 0600, filemode, *c) == false || | |
165 | TestFileFd(0026, 0640, filemode, *c) == false) | |
166 | { | |
167 | _error->DumpErrors(); | |
168 | return false; | |
169 | } | |
170 | } | |
171 | return true; | |
172 | } | |
173 | ||
174 | int main(int const argc, char const * const * const argv) | |
175 | { | |
176 | std::string startdir; | |
177 | if (argc > 1 && DirectoryExists(argv[1]) == true) { | |
178 | startdir = SafeGetCWD(); | |
179 | equals(chdir(argv[1]), 0); | |
180 | } | |
181 | if (TestFileFd(FileFd::WriteOnly | FileFd::Create) == false || | |
182 | TestFileFd(FileFd::WriteOnly | FileFd::Create | FileFd::Empty) == false || | |
183 | TestFileFd(FileFd::WriteOnly | FileFd::Create | FileFd::Exclusive) == false || | |
184 | TestFileFd(FileFd::WriteOnly | FileFd::Atomic) == false || | |
185 | TestFileFd(FileFd::WriteOnly | FileFd::Create | FileFd::Atomic) == false || | |
186 | // short-hands for ReadWrite with these modes | |
187 | TestFileFd(FileFd::WriteEmpty) == false || | |
188 | TestFileFd(FileFd::WriteAny) == false || | |
189 | TestFileFd(FileFd::WriteTemp) == false || | |
190 | TestFileFd(FileFd::WriteAtomic) == false) | |
191 | { | |
192 | return 1; | |
193 | } | |
194 | if (startdir.empty() == false) | |
195 | equals(chdir(startdir.c_str()), 0); | |
196 | ||
197 | std::vector<std::string> files; | |
198 | // normal match | |
199 | files = Glob("*.lst"); | |
200 | if (files.size() != 1) | |
201 | { | |
202 | _error->DumpErrors(); | |
203 | return 1; | |
204 | } | |
205 | ||
206 | // not there | |
207 | files = Glob("xxxyyyzzz"); | |
208 | if (files.size() != 0 || _error->PendingError()) | |
209 | { | |
210 | _error->DumpErrors(); | |
211 | return 1; | |
212 | } | |
213 | ||
214 | // many matches (number is a bit random) | |
215 | files = Glob("*.cc"); | |
216 | if (files.size() < 10) | |
217 | { | |
218 | _error->DumpErrors(); | |
219 | return 1; | |
220 | } | |
221 | ||
222 | // GetTempDir() | |
223 | unsetenv("TMPDIR"); | |
224 | equals(GetTempDir(), "/tmp"); | |
225 | ||
226 | setenv("TMPDIR", "", 1); | |
227 | equals(GetTempDir(), "/tmp"); | |
228 | ||
229 | setenv("TMPDIR", "/not-there-no-really-not", 1); | |
230 | equals(GetTempDir(), "/tmp"); | |
231 | ||
232 | setenv("TMPDIR", "/usr", 1); | |
233 | equals(GetTempDir(), "/usr"); | |
234 | ||
235 | return 0; | |
236 | } |