]>
Commit | Line | Data |
---|---|---|
453b82a3 DK |
1 | #include <config.h> |
2 | ||
488011fa MV |
3 | #include <apt-pkg/error.h> |
4 | #include <apt-pkg/fileutl.h> | |
f7feb041 | 5 | #include <apt-pkg/aptconfiguration.h> |
488011fa | 6 | |
488011fa MV |
7 | #include <string> |
8 | #include <vector> | |
488011fa | 9 | #include <stdlib.h> |
f22b65b4 | 10 | #include <sys/stat.h> |
f7feb041 | 11 | #include <string.h> |
488011fa | 12 | |
453b82a3 | 13 | #include "assert.h" |
488011fa | 14 | |
f7feb041 DK |
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 | ||
f22b65b4 | 22 | static bool |
f7feb041 | 23 | TestFileFd(mode_t const a_umask, mode_t const ExpectedFilePermission, unsigned int const filemode, APT::Configuration::Compressor const &compressor) |
f22b65b4 MV |
24 | { |
25 | FileFd f; | |
26 | struct stat buf; | |
bb93178b DK |
27 | static const char* fname = "apt-filefd-test.txt"; |
28 | if (FileExists(fname) == true) | |
29 | equals(unlink(fname), 0); | |
f22b65b4 MV |
30 | |
31 | umask(a_umask); | |
f7feb041 DK |
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 | ||
bb93178b | 37 | std::string test = "This is a test!\n"; |
f7feb041 DK |
38 | equals(f.Write(test.c_str(), test.size()), true); |
39 | equals(f.IsOpen(), true); | |
40 | equals(f.Failed(), false); | |
41 | ||
f22b65b4 | 42 | f.Close(); |
f7feb041 DK |
43 | equals(f.IsOpen(), false); |
44 | equals(f.Failed(), false); | |
45 | ||
46 | equals(f.Open(fname, FileFd::ReadOnly, compressor), true); | |
f7feb041 DK |
47 | equals(f.IsOpen(), true); |
48 | equals(f.Failed(), false); | |
bb93178b DK |
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); | |
f7feb041 | 54 | |
bb93178b DK |
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'; | |
f7feb041 | 60 | { |
bb93178b | 61 | APT_INIT_READBACK |
f7feb041 DK |
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 | { | |
bb93178b DK |
70 | APT_INIT_READBACK |
71 | char const * const expect = "test!\n"; | |
f7feb041 DK |
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 | } | |
bb93178b DK |
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 | |
f7feb041 DK |
133 | |
134 | f.Close(); | |
135 | equals(f.IsOpen(), false); | |
136 | equals(f.Failed(), false); | |
137 | ||
138 | // regression test for permission bug LP: #1304657 | |
f22b65b4 MV |
139 | if (stat(fname, &buf) < 0) |
140 | { | |
141 | _error->Errno("stat", "failed to stat"); | |
f22b65b4 MV |
142 | return false; |
143 | } | |
bb93178b | 144 | equals(unlink(fname), 0); |
f22b65b4 MV |
145 | equals(buf.st_mode & 0777, ExpectedFilePermission); |
146 | return true; | |
147 | } | |
148 | ||
f7feb041 | 149 | static bool TestFileFd(unsigned int const filemode) |
488011fa | 150 | { |
bb93178b DK |
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 | ||
f7feb041 DK |
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 | } | |
488011fa | 173 | |
bb93178b | 174 | int main(int const argc, char const * const * const argv) |
f7feb041 | 175 | { |
bb93178b DK |
176 | std::string startdir; |
177 | if (argc > 1 && DirectoryExists(argv[1]) == true) { | |
178 | startdir = SafeGetCWD(); | |
179 | equals(chdir(argv[1]), 0); | |
180 | } | |
f7feb041 DK |
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) | |
f22b65b4 MV |
191 | { |
192 | return 1; | |
193 | } | |
bb93178b DK |
194 | if (startdir.empty() == false) |
195 | equals(chdir(startdir.c_str()), 0); | |
f22b65b4 | 196 | |
f7feb041 | 197 | std::vector<std::string> files; |
488011fa MV |
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 | ||
a077861a MV |
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 | ||
488011fa MV |
235 | return 0; |
236 | } |