diff options
author | onefang | 2019-12-23 13:01:05 +1000 |
---|---|---|
committer | onefang | 2019-12-23 13:01:05 +1000 |
commit | 5e8b0adf2a39debac8354fd98ca7d5b729580ff7 (patch) | |
tree | 73b9c3666a89bbf52adb714c712209a09d48deb0 | |
parent | Move the declaration of the APT.tests table to where APT.protocols is. (diff) | |
download | apt-panopticon-5e8b0adf2a39debac8354fd98ca7d5b729580ff7.zip apt-panopticon-5e8b0adf2a39debac8354fd98ca7d5b729580ff7.tar.gz apt-panopticon-5e8b0adf2a39debac8354fd98ca7d5b729580ff7.tar.bz2 apt-panopticon-5e8b0adf2a39debac8354fd98ca7d5b729580ff7.tar.xz |
Major refactor, especially of the downloading and processing code.
Make the code more readable, less scattered.
Use a coroutine to multitask better.
Plugable functions for parsing the download results, and figuring out
what to download next.
Track timeouts at a finer level.
Dig for IPs in the forked apt-panopticons, not all at once at the
beginning.
Various cleanups and tweaks.
-rw-r--r-- | apt-panopticommon.lua | 56 | ||||
-rwxr-xr-x | apt-panopticon-report-RRD.lua | 1 | ||||
-rwxr-xr-x | apt-panopticon-report-email-web.lua | 31 | ||||
-rwxr-xr-x | apt-panopticon-update-data.lua | 2 | ||||
-rwxr-xr-x | apt-panopticon.lua | 680 |
5 files changed, 471 insertions, 299 deletions
diff --git a/apt-panopticommon.lua b/apt-panopticommon.lua index 8d6de05..4b0be8b 100644 --- a/apt-panopticommon.lua +++ b/apt-panopticommon.lua | |||
@@ -53,7 +53,19 @@ APT.options = | |||
53 | { | 53 | { |
54 | typ = "number", | 54 | typ = "number", |
55 | help = "", | 55 | help = "", |
56 | value = 15, | 56 | value = 5, |
57 | }, | ||
58 | timeouts = | ||
59 | { | ||
60 | typ = "number", | ||
61 | help = "", | ||
62 | value = 3, | ||
63 | }, | ||
64 | retries = | ||
65 | { | ||
66 | typ = "number", | ||
67 | help = "", | ||
68 | value = 3, | ||
57 | }, | 69 | }, |
58 | reports = | 70 | reports = |
59 | { | 71 | { |
@@ -290,14 +302,16 @@ local log = function(v, t, s, prot, test, host) | |||
290 | t = t .. "(" .. x .. ")" | 302 | t = t .. "(" .. x .. ")" |
291 | if "" ~= prot then | 303 | if "" ~= prot then |
292 | if "" == test then | 304 | if "" == test then |
293 | if nil == APT.results[prot] then APT.results[prot] = {errors = 0; warnings = 0} end | 305 | if nil == APT.results[prot] then APT.results[prot] = {errors = 0; warnings = 0; timeouts = 0} end |
294 | if v == 0 then APT.results[prot].errors = APT.results[prot].errors + 1 end | 306 | if v == 0 then APT.results[prot].errors = APT.results[prot].errors + 1 end |
295 | if v == 1 then APT.results[prot].warnings = APT.results[prot].warnings + 1 end | 307 | if v == 1 then APT.results[prot].warnings = APT.results[prot].warnings + 1 end |
308 | if v == 2 then APT.results[prot].timeouts = APT.results[prot].timeouts + 1 end | ||
296 | else | 309 | else |
297 | if nil == APT.results[prot] then APT.results[prot] = {errors = 0; warnings = 0} end | 310 | if nil == APT.results[prot] then APT.results[prot] = {errors = 0; warnings = 0; timeouts = 0} end |
298 | if nil == APT.results[prot][test] then APT.results[prot][test] = {errors = 0; warnings = 0} end | 311 | if nil == APT.results[prot][test] then APT.results[prot][test] = {errors = 0; warnings = 0; timeouts = 0} end |
299 | if v == 0 then APT.results[prot][test].errors = APT.results[prot][test].errors + 1 end | 312 | if v == 0 then APT.results[prot][test].errors = APT.results[prot][test].errors + 1 end |
300 | if v == 1 then APT.results[prot][test].warnings = APT.results[prot][test].warnings + 1 end | 313 | if v == 1 then APT.results[prot][test].warnings = APT.results[prot][test].warnings + 1 end |
314 | if v == 2 then APT.results[prot][test].timeouts = APT.results[prot][test].timeouts + 1 end | ||
301 | end | 315 | end |
302 | end | 316 | end |
303 | end | 317 | end |
@@ -311,8 +325,9 @@ local log = function(v, t, s, prot, test, host) | |||
311 | if -1 == v then colour = "fuchsia" end -- CRITICAL | 325 | if -1 == v then colour = "fuchsia" end -- CRITICAL |
312 | if 0 == v then colour = "red " end -- ERROR | 326 | if 0 == v then colour = "red " end -- ERROR |
313 | if 1 == v then colour = "yellow " end -- WARNING | 327 | if 1 == v then colour = "yellow " end -- WARNING |
314 | if 2 == v then colour = "white " end -- INFO | 328 | if 2 == v then colour = "blue " end -- TIMEOUT |
315 | if 3 == v then colour = "gray " end -- DEBUG | 329 | if 3 == v then colour = "white " end -- INFO |
330 | if 4 == v then colour = "gray " end -- DEBUG | ||
316 | APT.logFile:write(os.date() .. " <font color='" .. colour .. "'><b>" .. t .. "</b></font>: " .. s .. "</br>\n") | 331 | APT.logFile:write(os.date() .. " <font color='" .. colour .. "'><b>" .. t .. "</b></font>: " .. s .. "</br>\n") |
317 | else | 332 | else |
318 | APT.logFile:write(os.date() .. " " .. t .. ": " .. s .. "\n") | 333 | APT.logFile:write(os.date() .. " " .. t .. ": " .. s .. "\n") |
@@ -320,13 +335,15 @@ local log = function(v, t, s, prot, test, host) | |||
320 | APT.logFile:flush() | 335 | APT.logFile:flush() |
321 | end | 336 | end |
322 | end | 337 | end |
323 | APT.D = function(s) log(3, "DEBUG ", s) end | 338 | APT.D = function(s) log(4, "DEBUG ", s) end |
324 | APT.I = function(s) log(2, "INFO ", s) end | 339 | APT.I = function(s) log(3, "INFO ", s) end |
340 | APT.T = function(s, p, t, h) log(2, "TIMEOUT ", s, p, t, h) end | ||
325 | APT.W = function(s, p, t, h) log(1, "WARNING ", s, p, t, h) end | 341 | APT.W = function(s, p, t, h) log(1, "WARNING ", s, p, t, h) end |
326 | APT.E = function(s, p, t, h) log(0, "ERROR ", s, p, t, h) end | 342 | APT.E = function(s, p, t, h) log(0, "ERROR ", s, p, t, h) end |
327 | APT.C = function(s) log(-1, "CRITICAL", s) end | 343 | APT.C = function(s) log(-1, "CRITICAL", s) end |
328 | local D = APT.D | 344 | local D = APT.D |
329 | local I = APT.I | 345 | local I = APT.I |
346 | local T = APT.T | ||
330 | local W = APT.W | 347 | local W = APT.W |
331 | local E = APT.E | 348 | local E = APT.E |
332 | local C = APT.C | 349 | local C = APT.C |
@@ -380,7 +397,7 @@ APT.checkFile = function(f) | |||
380 | if nil == h then return false else h:close(); return true end | 397 | if nil == h then return false else h:close(); return true end |
381 | end | 398 | end |
382 | 399 | ||
383 | APT.plurals = function(e, w) | 400 | APT.plurals = function(e, w, t) |
384 | local result = "" | 401 | local result = "" |
385 | if 1 == e then | 402 | if 1 == e then |
386 | result = e .. " error" | 403 | result = e .. " error" |
@@ -397,18 +414,29 @@ APT.plurals = function(e, w) | |||
397 | end | 414 | end |
398 | if ("" ~= result) and APT.html then result = "<font color='yellow'><b>" .. result .. "</b></font>" end | 415 | if ("" ~= result) and APT.html then result = "<font color='yellow'><b>" .. result .. "</b></font>" end |
399 | end | 416 | end |
417 | if 0 < t then | ||
418 | if (0 < e) or (0 < w) then result = result .. ", " end | ||
419 | if 1 == t then | ||
420 | result = result .. t .. " timeout" | ||
421 | else | ||
422 | result = result .. t .. " timeouts" | ||
423 | end | ||
424 | if ("" ~= result) and APT.html then result = "<font color='blue'><b>" .. result .. "</b></font>" end | ||
425 | end | ||
400 | if "" ~= result then result = " (" .. result .. ")" end | 426 | if "" ~= result then result = " (" .. result .. ")" end |
401 | return result | 427 | return result |
402 | end | 428 | end |
403 | 429 | ||
404 | APT.padResults = function(results) | 430 | APT.padResults = function(results) |
431 | local c = 0 | ||
432 | if nil == results then results = {}; c = 999 end | ||
405 | for k, v in pairs(APT.protocols) do | 433 | for k, v in pairs(APT.protocols) do |
406 | tests = results[v] | 434 | tests = results[v] |
407 | if nil == tests then tests = {errors = 0; warnings = 0} end | 435 | if nil == tests then tests = {errors = c; warnings = c; timeouts = c} end |
408 | if nil == tests.Integrity then tests.Integrity = {errors = 0; warnings = 0} end | 436 | if nil == tests.Integrity then tests.Integrity = {errors = c; warnings = c; timeouts = c} end |
409 | if nil == tests.Protocol then tests.Protocol = {errors = 0; warnings = 0} end | 437 | if nil == tests.Protocol then tests.Protocol = {errors = c; warnings = c; timeouts = c} end |
410 | if nil == tests.Updated then tests.Updated = {errors = 0; warnings = 0} end | 438 | if nil == tests.Updated then tests.Updated = {errors = c; warnings = c; timeouts = c} end |
411 | if nil == tests.URLSanity then tests.URLSanity = {errors = 0; warnings = 0} end | 439 | if nil == tests.URLSanity then tests.URLSanity = {errors = c; warnings = c; timeouts = c} end |
412 | results[v] = tests | 440 | results[v] = tests |
413 | end | 441 | end |
414 | if nil == results.timeout then results.timeout = false end | 442 | if nil == results.timeout then results.timeout = false end |
diff --git a/apt-panopticon-report-RRD.lua b/apt-panopticon-report-RRD.lua index dfe21d2..e703659 100755 --- a/apt-panopticon-report-RRD.lua +++ b/apt-panopticon-report-RRD.lua | |||
@@ -3,6 +3,7 @@ | |||
3 | local APT = require 'apt-panopticommon' | 3 | local APT = require 'apt-panopticommon' |
4 | local D = APT.D | 4 | local D = APT.D |
5 | local I = APT.I | 5 | local I = APT.I |
6 | local T = APT.T | ||
6 | local W = APT.W | 7 | local W = APT.W |
7 | local E = APT.E | 8 | local E = APT.E |
8 | local C = APT.C | 9 | local C = APT.C |
diff --git a/apt-panopticon-report-email-web.lua b/apt-panopticon-report-email-web.lua index 8a5404a..c52b6c0 100755 --- a/apt-panopticon-report-email-web.lua +++ b/apt-panopticon-report-email-web.lua | |||
@@ -3,6 +3,7 @@ | |||
3 | local APT = require 'apt-panopticommon' | 3 | local APT = require 'apt-panopticommon' |
4 | local D = APT.D | 4 | local D = APT.D |
5 | local I = APT.I | 5 | local I = APT.I |
6 | local T = APT.T | ||
6 | local W = APT.W | 7 | local W = APT.W |
7 | local E = APT.E | 8 | local E = APT.E |
8 | local C = APT.C | 9 | local C = APT.C |
@@ -47,16 +48,19 @@ local status = function(host, results, typ) | |||
47 | local result = "" | 48 | local result = "" |
48 | local e = 0 | 49 | local e = 0 |
49 | local w = 0 | 50 | local w = 0 |
51 | local t = 0 | ||
50 | local s = nil ~= APT.mirrors[host].Protocols[typ] | 52 | local s = nil ~= APT.mirrors[host].Protocols[typ] |
51 | local to = results.timeout | 53 | local to = results.timeout |
52 | if not APT.search(APT.protocols, typ) then s = true end | 54 | if not APT.search(APT.protocols, typ) then s = true end |
53 | if nil ~= results[typ] then | 55 | if nil ~= results[typ] then |
54 | e = results[typ].errors | 56 | e = results[typ].errors |
55 | w = results[typ].warnings | 57 | w = results[typ].warnings |
58 | t = results[typ].timeouts | ||
56 | for k, v in pairs(results[typ]) do | 59 | for k, v in pairs(results[typ]) do |
57 | if "table" == type(v) then | 60 | if "table" == type(v) then |
58 | if 0 <= v.errors then e = e + v.errors else to = true end | 61 | if 0 <= v.errors then e = e + v.errors else to = true end |
59 | if 0 <= v.warnings then w = w + v.warnings else to = true end | 62 | if 0 <= v.warnings then w = w + v.warnings else to = true end |
63 | if 0 <= v.timeouts then t = t + v.timeouts else to = true end | ||
60 | end | 64 | end |
61 | end | 65 | end |
62 | else | 66 | else |
@@ -67,6 +71,7 @@ local status = function(host, results, typ) | |||
67 | if typ == i then | 71 | if typ == i then |
68 | if 0 <= u.errors then e = e + u.errors end | 72 | if 0 <= u.errors then e = e + u.errors end |
69 | if 0 <= u.warnings then w = w + u.warnings end | 73 | if 0 <= u.warnings then w = w + u.warnings end |
74 | if 0 <= u.timeouts then t = t + u.timeouts end | ||
70 | end | 75 | end |
71 | end | 76 | end |
72 | end | 77 | end |
@@ -99,6 +104,21 @@ local status = function(host, results, typ) | |||
99 | else | 104 | else |
100 | faulty = faulty .. host .. " (" .. typ .. ")\n" | 105 | faulty = faulty .. host .. " (" .. typ .. ")\n" |
101 | end | 106 | end |
107 | elseif 0 < t then | ||
108 | result = "[timeout" | ||
109 | if not s then result = result .. "*" end | ||
110 | if APT.html then | ||
111 | if s then | ||
112 | result = "[<font color='blue'><b>timeout</b></font>" | ||
113 | else | ||
114 | result = "[<font color='darkblue'><b>timeout*</b></font>" | ||
115 | end | ||
116 | end | ||
117 | if APT.html then | ||
118 | faulty = faulty .. host .. " (" .. typ .. ")<br>\n" | ||
119 | else | ||
120 | faulty = faulty .. host .. " (" .. typ .. ")\n" | ||
121 | end | ||
102 | else | 122 | else |
103 | result = "[OK" | 123 | result = "[OK" |
104 | if not s then result = result .. "*" end | 124 | if not s then result = result .. "*" end |
@@ -110,7 +130,7 @@ local status = function(host, results, typ) | |||
110 | end | 130 | end |
111 | end | 131 | end |
112 | end | 132 | end |
113 | return result .. APT.plurals(e, w) .. "]" | 133 | return result .. APT.plurals(e, w, t) .. "]" |
114 | end | 134 | end |
115 | 135 | ||
116 | local m = {} | 136 | local m = {} |
@@ -125,9 +145,11 @@ local logCount = function(domain, ip) | |||
125 | if nil ~= rfile then | 145 | if nil ~= rfile then |
126 | local errors = 0 | 146 | local errors = 0 |
127 | local warnings = 0 | 147 | local warnings = 0 |
148 | local timeouts = 0 | ||
128 | for l in rfile:lines() do | 149 | for l in rfile:lines() do |
129 | if nil ~= l:match("><b>ERROR ") then errors = errors + 1 end | 150 | if nil ~= l:match("><b>ERROR ") then errors = errors + 1 end |
130 | if nil ~= l:match("><b>WARNING ") then warnings = warnings + 1 end | 151 | if nil ~= l:match("><b>WARNING ") then warnings = warnings + 1 end |
152 | if nil ~= l:match("><b>TIMEOUT ") then timeouts = timeouts + 1 end | ||
131 | end | 153 | end |
132 | rfile:close() | 154 | rfile:close() |
133 | if APT.html then | 155 | if APT.html then |
@@ -137,7 +159,7 @@ local logCount = function(domain, ip) | |||
137 | log = "<a href='" .. nm .. "'>" .. ip .. "</a>" | 159 | log = "<a href='" .. nm .. "'>" .. ip .. "</a>" |
138 | end | 160 | end |
139 | end | 161 | end |
140 | log = log .. APT.plurals(errors, warnings) | 162 | log = log .. APT.plurals(errors, warnings, timeouts) |
141 | end | 163 | end |
142 | return log | 164 | return log |
143 | end | 165 | end |
@@ -303,8 +325,11 @@ if nil == web then C("opening mirrors file - " .. e) else | |||
303 | " means the tested thing is supported for that mirror.</p>\n" .. | 325 | " means the tested thing is supported for that mirror.</p>\n" .. |
304 | "<p>[<font color='darkred'><b>FAILED*</b></font>] or [<font color='darkgreen'><b>OK*</b></font>]" .. | 326 | "<p>[<font color='darkred'><b>FAILED*</b></font>] or [<font color='darkgreen'><b>OK*</b></font>]" .. |
305 | " means the tested thing is unsupported for that mirror, but might have been tested anyway.</p>\n" .. | 327 | " means the tested thing is unsupported for that mirror, but might have been tested anyway.</p>\n" .. |
328 | "<p>[<font color='blue'><b>timeout</b></font>] or [<font color='darkblue'><b>timeout</b></font>]" .. | ||
329 | " means the mirror had some timeouts, and tests where not yet aborted. The darker colour means unsupported by the mirror, but tested anyway.</p>" .. | ||
306 | "<p>[<font color='blue'><b>TIMEOUT</b></font>] or [<font color='darkblue'><b>TIMEOUT</b></font>]" .. | 330 | "<p>[<font color='blue'><b>TIMEOUT</b></font>] or [<font color='darkblue'><b>TIMEOUT</b></font>]" .. |
307 | " means the server had too many timeouts, and tests where aborted, so there is no result for this test.</p>" .. | 331 | " means the mirror had too many timeouts, and tests where aborted, so there is no result for this test.</p>" .. |
332 | "<p>NOTE: timeouts may be due to a problem on the testing computer.</p>" .. | ||
308 | "<p>The DNS round robin (DNS-RR) column shows the IPs for that mirror, or [<font color='grey'><b>no</b></font>] if it isn't part of the DNS-RR. " .. | 333 | "<p>The DNS round robin (DNS-RR) column shows the IPs for that mirror, or [<font color='grey'><b>no</b></font>] if it isn't part of the DNS-RR. " .. |
309 | "The IPs link to the testing log for that IP accessed via the DNS-RR. " .. | 334 | "The IPs link to the testing log for that IP accessed via the DNS-RR. " .. |
310 | "deb.devuan.org is the DNS-RR itself, so it doesn't get tested directly.</p>\n" .. | 335 | "deb.devuan.org is the DNS-RR itself, so it doesn't get tested directly.</p>\n" .. |
diff --git a/apt-panopticon-update-data.lua b/apt-panopticon-update-data.lua index 98c909a..8adad4d 100755 --- a/apt-panopticon-update-data.lua +++ b/apt-panopticon-update-data.lua | |||
@@ -3,7 +3,9 @@ | |||
3 | local APT = require 'apt-panopticommon' | 3 | local APT = require 'apt-panopticommon' |
4 | local D = APT.D | 4 | local D = APT.D |
5 | local I = APT.I | 5 | local I = APT.I |
6 | local T = APT.T | ||
6 | local W = APT.W | 7 | local W = APT.W |
8 | local E = APT.E | ||
7 | local C = APT.C | 9 | local C = APT.C |
8 | local arg, sendArgs = APT.parseArgs({...}) | 10 | local arg, sendArgs = APT.parseArgs({...}) |
9 | 11 | ||
diff --git a/apt-panopticon.lua b/apt-panopticon.lua index 6bec6a1..4e4be94 100755 --- a/apt-panopticon.lua +++ b/apt-panopticon.lua | |||
@@ -5,6 +5,7 @@ local now = os.time() | |||
5 | local APT = require 'apt-panopticommon' | 5 | local APT = require 'apt-panopticommon' |
6 | local D = APT.D | 6 | local D = APT.D |
7 | local I = APT.I | 7 | local I = APT.I |
8 | local T = APT.T | ||
8 | local W = APT.W | 9 | local W = APT.W |
9 | local E = APT.E | 10 | local E = APT.E |
10 | local C = APT.C | 11 | local C = APT.C |
@@ -23,14 +24,14 @@ local releases = {"jessie", "ascii", "beowulf", "ceres"} | |||
23 | local releaseFiles = | 24 | local releaseFiles = |
24 | { | 25 | { |
25 | -- Release file. | 26 | -- Release file. |
26 | "/Release", -- 3.7 MB | 27 | "Release", -- 3.7 MB |
27 | "/Release.gpg", -- | 28 | "Release.gpg", -- |
28 | -- "/InRelease", -- 3.7 MB | 29 | -- "InRelease", -- 3.7 MB |
29 | -- "/main/binary-all/Packages.xz", -- 2.6 GB for all that changed recently. | 30 | -- "main/binary-all/Packages.xz", -- 2.6 GB for all that changed recently. |
30 | -- Contents files. -- 3.3 GB | 31 | -- Contents files. -- 3.3 GB |
31 | -- "/main/Contents-all.xz", | 32 | -- "main/Contents-all.xz", |
32 | -- "/main/Contents-amd64.xz", | 33 | -- "main/Contents-amd64.xz", |
33 | -- "/main/Contents-arm64.xz", | 34 | -- "main/Contents-arm64.xz", |
34 | -- "-security/main/Contents-all.xz", | 35 | -- "-security/main/Contents-all.xz", |
35 | -- "-security/main/Contents-amd64.xz", | 36 | -- "-security/main/Contents-amd64.xz", |
36 | -- "-security/main/Contents-arm64.xz", | 37 | -- "-security/main/Contents-arm64.xz", |
@@ -160,6 +161,7 @@ local url = require 'socket.url' | |||
160 | 161 | ||
161 | 162 | ||
162 | local ip = "" | 163 | local ip = "" |
164 | local cor = nil | ||
163 | 165 | ||
164 | 166 | ||
165 | local repoExists = function (r) | 167 | local repoExists = function (r) |
@@ -197,6 +199,7 @@ gatherIPs = function (host) | |||
197 | end | 199 | end |
198 | until nil == IPs | 200 | until nil == IPs |
199 | end | 201 | end |
202 | return IP[host] | ||
200 | end | 203 | end |
201 | 204 | ||
202 | -- Returns FTP directory listing | 205 | -- Returns FTP directory listing |
@@ -229,7 +232,7 @@ checkHEAD = function (host, URL, r, retry, sanity) | |||
229 | E("too many timeouts! " .. check .. " " .. host .. " -> " .. URL, PU.scheme, "", host) | 232 | E("too many timeouts! " .. check .. " " .. host .. " -> " .. URL, PU.scheme, "", host) |
230 | return | 233 | return |
231 | end | 234 | end |
232 | if 4 <= (totalTimeouts) then | 235 | if APT.options.timeouts.value <= (totalTimeouts) then |
233 | E("Way too many timeouts!", PU.scheme, "", host) | 236 | E("Way too many timeouts!", PU.scheme, "", host) |
234 | return | 237 | return |
235 | end | 238 | end |
@@ -237,7 +240,7 @@ checkHEAD = function (host, URL, r, retry, sanity) | |||
237 | E("too many redirects! " .. check .. " " .. host .. " -> " .. URL, PU.scheme, "", host) | 240 | E("too many redirects! " .. check .. " " .. host .. " -> " .. URL, PU.scheme, "", host) |
238 | return | 241 | return |
239 | end | 242 | end |
240 | if 4 <= retry then | 243 | if APT.options.retries.value <= retry then |
241 | E("too many retries! " .. check .. " " .. host .. " -> " .. URL, PU.scheme, "", host) | 244 | E("too many retries! " .. check .. " " .. host .. " -> " .. URL, PU.scheme, "", host) |
242 | return | 245 | return |
243 | end | 246 | end |
@@ -343,6 +346,8 @@ checkHEAD = function (host, URL, r, retry, sanity) | |||
343 | Still duplicates a tiny bit, but much less than the previous find based method. | 346 | Still duplicates a tiny bit, but much less than the previous find based method. |
344 | TODO - maybe we can switch to using flock like we do with the other curl calls? | 347 | TODO - maybe we can switch to using flock like we do with the other curl calls? |
345 | ]] | 348 | ]] |
349 | C('Commented out code being called in checkHEAD() for redirects that should no longer happen!') | ||
350 | --[[ | ||
346 | local file = pu.host .. "://" .. pu.path | 351 | local file = pu.host .. "://" .. pu.path |
347 | local f = io.popen(string.format('if [ ! -f results/%s.check ] ; then touch results/%s.check; echo -n "check"; fi', file:gsub("/", "_"), file:gsub("/", "_") )):read("*a") | 352 | local f = io.popen(string.format('if [ ! -f results/%s.check ] ; then touch results/%s.check; echo -n "check"; fi', file:gsub("/", "_"), file:gsub("/", "_") )):read("*a") |
348 | if (nil == f) or ("check" == f) then | 353 | if (nil == f) or ("check" == f) then |
@@ -351,28 +356,27 @@ TODO - maybe we can switch to using flock like we do with the other curl calls? | |||
351 | else | 356 | else |
352 | D(" Already checking " .. file) | 357 | D(" Already checking " .. file) |
353 | end | 358 | end |
359 | ]] | ||
354 | end | 360 | end |
355 | end | 361 | end |
356 | end | 362 | end |
357 | end | 363 | end |
358 | 364 | ||
359 | local checkTimeouts = function(host, scheme, URL) | 365 | local checkTimeouts = function(host, scheme, URL) |
360 | if APT.testing(scheme) then | 366 | totalTimeouts = totalTimeouts + timeouts; timeouts = 0 |
361 | totalTimeouts = totalTimeouts + timeouts; timeouts = 0 | 367 | checkHEAD(host, scheme .. "://" .. URL) |
362 | checkHEAD(host, scheme .. "://" .. URL) | ||
363 | if 4 <= (totalTimeouts) then | ||
364 | E("Way too many timeouts!", scheme, "", host) | ||
365 | return true | ||
366 | end | ||
367 | end | ||
368 | if APT.testing("URLSanity") then | 368 | if APT.testing("URLSanity") then |
369 | URL = URL:gsub("merged/", "merged///") | 369 | URL = URL:gsub("merged/", "merged///") |
370 | totalTimeouts = totalTimeouts + timeouts; timeouts = 0 | ||
371 | checkHEAD(host, scheme .. "://" .. URL, 0, 0, true) | 370 | checkHEAD(host, scheme .. "://" .. URL, 0, 0, true) |
372 | if 4 <= (totalTimeouts) then | 371 | end |
373 | E("Way too many timeouts!", scheme, "URLSanity", host) | 372 | if nil ~= cor then |
374 | return true | 373 | D('*>* About to resume coroutine after checkHEAD(' .. host .. ' , ' .. scheme .. ' :// ' .. URL .. ')') |
375 | end | 374 | local ok, message = coroutine.resume(cor) |
375 | if not ok then cor = nil; print(message) end | ||
376 | end | ||
377 | if APT.options.timeouts.value <= (totalTimeouts) then | ||
378 | E("Way too many timeouts!", scheme, "URLSanity", host) | ||
379 | return true | ||
376 | end | 380 | end |
377 | return false | 381 | return false |
378 | end | 382 | end |
@@ -387,19 +391,18 @@ local checkFiles = function (host, ip, path, file) | |||
387 | if checkTimeouts(host, "https", ip .. path .. "/" .. file) then return end | 391 | if checkTimeouts(host, "https", ip .. path .. "/" .. file) then return end |
388 | else | 392 | else |
389 | I(" Checking IP " .. host .. " -> " .. ip .. " " .. path) | 393 | I(" Checking IP " .. host .. " -> " .. ip .. " " .. path) |
390 | for i, s in pairs(referenceDevs) do | ||
391 | if checkTimeouts(host, "http", ip .. path .. "/" .. s) then return end | ||
392 | if checkTimeouts(host, "https", ip .. path .. "/" .. s) then return end | ||
393 | end | ||
394 | |||
395 | for i, s in pairs(releases) do | 394 | for i, s in pairs(releases) do |
396 | for j, k in pairs(releaseFiles) do | 395 | for j, k in pairs(releaseFiles) do |
397 | if repoExists(s .. k) then | 396 | if repoExists(s .. k) then |
398 | if checkTimeouts(host, "http", ip .. path .. "/merged/dists/" .. s .. k) then return end | 397 | if checkTimeouts(host, "http", ip .. path .. "/merged/dists/" .. s .. '/' .. k) then return end |
399 | if checkTimeouts(host, "https", ip .. path .. "/merged/dists/" .. s .. k) then return end | 398 | if checkTimeouts(host, "https", ip .. path .. "/merged/dists/" .. s .. '/' .. k) then return end |
400 | end | 399 | end |
401 | end | 400 | end |
402 | end | 401 | end |
402 | for i, s in pairs(referenceDevs) do | ||
403 | if checkTimeouts(host, "http", ip .. path .. "/" .. s) then return end | ||
404 | if checkTimeouts(host, "https", ip .. path .. "/" .. s) then return end | ||
405 | end | ||
403 | end | 406 | end |
404 | end | 407 | end |
405 | 408 | ||
@@ -421,127 +424,51 @@ checkHost = function (orig, host, path, ip, file) | |||
421 | D("checkHost " .. orig .. "" .. file) | 424 | D("checkHost " .. orig .. "" .. file) |
422 | if APT.testing("IPv4") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " -o " .. orig .. path .. " " .. file) end | 425 | if APT.testing("IPv4") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " -o " .. orig .. path .. " " .. file) end |
423 | else D("checkHost " .. orig .. " -> " .. host) end | 426 | else D("checkHost " .. orig .. " -> " .. host) end |
424 | local h = APT.mirrors[ph.host] | ||
425 | if nil == h then return end | ||
426 | for k, v in pairs(h.IPs) do | ||
427 | if "table" == type(v) then | ||
428 | for k1, v1 in pairs(v) do | ||
429 | if v1 == "A" then | ||
430 | if APT.testing("IPv4") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. orig .. path .. " " .. k1 .. " " .. file) end | ||
431 | elseif v1 == "AAAA" then | ||
432 | if APT.testing("IPv6") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. orig .. path .. " " .. k1 .. " " .. file) end | ||
433 | end | ||
434 | end | ||
435 | else | ||
436 | if v == "A" then | ||
437 | if APT.testing("IPv4") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. orig .. path .. " " .. k .. " " .. file) end | ||
438 | elseif v == "AAAA" then | ||
439 | if APT.testing("IPv6") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. orig .. path .. " " .. k .. " " .. file) end | ||
440 | end | ||
441 | end | ||
442 | end | ||
443 | end | 427 | end |
444 | end | 428 | end |
445 | 429 | ||
446 | 430 | ||
447 | local addDownload = function(host, URL, f, r, k) | 431 | local addDownload = function(host, URL, f, r, k) |
448 | local file = k:match(".*/([%w%.%+%-_]*)$") -- Get the filename. | 432 | local file = k:match(".*/([%w%.%+%-_]*)$") -- Get the filename. |
449 | if APT.checkFile("results/" .. host .. "/merged/dists/" .. r .. k) then | 433 | if APT.checkFile("results/" .. host .. "/merged/dists/" .. r .. '/' .. k) then |
450 | -- Curls "check timestamp and overwrite file" stuff sucks. | 434 | -- Curls "check timestamp and overwrite file" stuff sucks. |
451 | -- -R means the destination file gets the timestamp of the remote file. | 435 | -- -R means the destination file gets the timestamp of the remote file. |
452 | -- Can only do ONE timestamp check per command. | 436 | -- Can only do ONE timestamp check per command. |
453 | -- This doesn't work either. All downloads get all these headers. Pffft | 437 | -- This doesn't work either. All downloads get all these headers. Pffft |
454 | -- local status, ts = APT.execute('TZ="GMT" ls -l --time-style="+%a, %d %b %Y %T %Z" results/' .. host .. "/merged/dists/" .. r .. k .. ' | cut -d " " -f 6-11') | 438 | -- local status, ts = APT.execute('TZ="GMT" ls -l --time-style="+%a, %d %b %Y %T %Z" results/' .. host .. "/merged/dists/" .. r .. '/' .. k .. ' | cut -d " " -f 6-11') |
455 | -- f:write('header "If-Modified-Since: ' .. ts:sub(2, -2) .. '"\n') | 439 | -- f:write('header "If-Modified-Since: ' .. ts:sub(2, -2) .. '"\n') |
456 | -- Curl will DELETE the existing file if the timestamp fails to download a new one, unless we change directory first, | 440 | -- Curl will DELETE the existing file if the timestamp fails to download a new one, unless we change directory first, |
457 | -- which wont work with multiple files in multiple directories. WTF? | 441 | -- which wont work with multiple files in multiple directories. WTF? |
458 | os.execute(" mv results/" .. host .. "/merged/dists/" .. r .. k .. | 442 | os.execute(" mv results/" .. host .. "/merged/dists/" .. r .. '/' .. k .. |
459 | " results/" .. host .. "/merged/dists/" .. r .. k .. ".old") | 443 | " results/" .. host .. "/merged/dists/" .. r .. '/' .. k .. ".old") |
460 | end | 444 | end |
461 | 445 | ||
462 | D('Downloading http://' .. host .. URL .. '/merged/dists/' .. r .. k) | 446 | D('Downloading http://' .. host .. URL .. '/merged/dists/' .. r .. '/' .. k) |
463 | f:write('url "' .. 'http://' .. host .. URL .. '/merged/dists/' .. r .. k .. '"\n') | 447 | f:write('url "' .. 'http://' .. host .. URL .. '/merged/dists/' .. r .. '/' .. k .. '"\n') |
464 | f:write('output "results/' .. host .. '/merged/dists/' .. r .. k .. '"\n') | 448 | f:write('output "results/' .. host .. '/merged/dists/' .. r .. '/' .. k .. '"\n') |
465 | end | 449 | end |
466 | 450 | ||
467 | local postDownload = function(host, r, k) | 451 | local postDownload = function(host, r, k) |
468 | local file = k:match(".*/([%w%.%+%-_]*)$") -- Get the filename. | 452 | local file = k:match(".*/([%w%.%+%-_]*)$") -- Get the filename. |
469 | local dir = k:sub(1, 0 - (#file + 1)) | 453 | if nil == file then file = k end |
470 | os.execute("if [ -f results/" .. host .. "/merged/dists/" .. r .. k .. ".old ]" .. | 454 | os.execute("if [ -f results/" .. host .. "/merged/dists/" .. r .. '/' .. k .. ".old ]" .. |
471 | " && [ ! -f results/" .. host .. "/merged/dists/" .. r .. k .. " ]; then cp -a" .. | 455 | " && [ ! -f results/" .. host .. "/merged/dists/" .. r .. '/' .. k .. " ]; then cp -a" .. |
472 | " results/" .. host .. "/merged/dists/" .. r .. k .. ".old" .. | 456 | " results/" .. host .. "/merged/dists/" .. r .. '/' .. k .. ".old" .. |
473 | " results/" .. host .. "/merged/dists/" .. r .. k .. "; fi") | 457 | " results/" .. host .. "/merged/dists/" .. r .. '/' .. k .. "; fi") |
474 | if ".gz" == k:sub(-3, -1) then APT.execute("ionice -c3 nice -n 19 gzip -dfk results/" .. host .. "/merged/dists/" .. r .. k) end | 458 | if APT.checkFile('results/' .. host .. '/merged/dists/' .. r .. '/' .. k) then |
475 | if ".xz" == k:sub(-3, -1) then APT.execute("ionice -c3 nice -n 19 xz -dfk results/" .. host .. "/merged/dists/" .. r .. k .. " 2>/dev/null") end | 459 | if ".gz" == k:sub(-3, -1) then APT.execute("ionice -c3 nice -n 19 gzip -dfk results/" .. host .. "/merged/dists/" .. r .. '/' .. k) end |
476 | if APT.testing("Integrity") then | 460 | if ".xz" == k:sub(-3, -1) then APT.execute("ionice -c3 nice -n 19 xz -dfk results/" .. host .. "/merged/dists/" .. r .. '/' .. k .. " 2>/dev/null") end |
477 | if ".gpg" == k:sub(-4, -1) then | ||
478 | local status, out = APT.execute("gpgv --keyring /usr/share/keyrings/devuan-keyring.gpg results/" .. host .. "/merged/dists/" .. r .. k .. | ||
479 | " results/" .. host .. "/merged/dists/" .. r .. k:sub(1, -5) .. " 2>/dev/null") | ||
480 | if "0" ~= status then E("GPG check failed - " .. host .. "/merged/dists/" .. r .. k, "http", "Integrity", host) end | ||
481 | os.execute('rm results/' .. host .. '/merged/dists/' .. r .. k) | ||
482 | end | ||
483 | -- TODO - should check the PGP sig of InRelease as well. | ||
484 | end | ||
485 | if APT.testing("Integrity") or APT.testing("Updated") then | ||
486 | if "Packages." == file:sub(1, 9) then | ||
487 | -- TODO - compare the SHA256 sums in pkgmaster's Release for both the packed and unpacked versions. | ||
488 | -- Also note that this might get only a partial download due to maxtime. | ||
489 | if APT.options.referenceSite.value == host then | ||
490 | local Pp, e = io.open('results/' .. host .. '/merged/dists/'.. r .. dir .. 'Packages.parsed', "w+") | ||
491 | if nil == Pp then W('opening results/' .. host .. '/merged/dists/'.. r .. dir .. 'Packages.parsed' .. ' file - ' .. e) else | ||
492 | local pp = {} | ||
493 | for l in io.lines('results/' .. host .. '/merged/dists/'.. r .. dir .. 'Packages') do | ||
494 | if "Package: " == l:sub(1, 9) then | ||
495 | if 0 ~= #pp then | ||
496 | for i = 1, 5 do | ||
497 | if nil == pp[i] then print(host .. " " .. r .. " " .. dir .. " " .. i) else Pp:write(pp[i] .. " | ") end | ||
498 | end | ||
499 | Pp:write("\n") | ||
500 | end | ||
501 | pp = {} | ||
502 | pp[1] = l:sub(10, -1) | ||
503 | elseif "Version: " == l:sub(1, 9) then | ||
504 | pp[2] = l:sub(10, -1) | ||
505 | elseif "Filename: " == l:sub(1, 10) then | ||
506 | pp[3] = l:sub(11, -1) | ||
507 | elseif "Size: " == l:sub(1, 6) then | ||
508 | pp[4] = l:sub(7, -1) | ||
509 | elseif "SHA256: " == l:sub(1, 8) then | ||
510 | pp[5] = l:sub(9, -1) | ||
511 | end | ||
512 | end | ||
513 | Pp:close() | ||
514 | os.execute('sort results/' .. host .. '/merged/dists/'.. r .. dir .. 'Packages.parsed >results/' .. host .. '/merged/dists/'.. r .. dir .. 'Packages_parsed-sorted') | ||
515 | if APT.checkFile('Packages/' .. r .. dir .. 'Packages_parsed-sorted') then | ||
516 | os.execute('diff -U 0 Packages/' .. r .. dir .. 'Packages_parsed-sorted ' .. | ||
517 | 'results/pkgmaster.devuan.org/merged/dists/' .. r .. dir .. 'Packages_parsed-sorted ' .. | ||
518 | ' | grep -E "^-" | grep -Ev "^\\+\\+\\+|^---" >>results/OLD_PACKAGES_' .. r .. '.txt') | ||
519 | os.execute('diff -U 0 Packages/' .. r .. dir .. 'Packages_parsed-sorted ' .. | ||
520 | 'results/pkgmaster.devuan.org/merged/dists/' .. r .. dir .. 'Packages_parsed-sorted ' .. | ||
521 | ' | grep -E "^\\+" | grep -Ev "^\\+\\+\\+|^---" >>results/NEW_Packages_' .. r .. '.txt') | ||
522 | -- Find the smallest new package for each release. | ||
523 | os.execute('sort -b -k 9,9 -n results/NEW_Packages_' .. r .. '.txt >results/NEW_Packages_' .. r .. '.sorted.txt') | ||
524 | os.execute('grep -s " | pool/DEBIAN/" results/NEW_Packages_' .. r .. '.sorted.txt 2>/dev/null | head -n 1 >results/NEW_Packages_' .. r .. '.test.tmp') | ||
525 | os.execute('grep -s " | pool/DEBIAN-SECURITY/" results/NEW_Packages_' .. r .. '.sorted.txt 2>/dev/null | head -n 1 >>results/NEW_Packages_' .. r .. '.test.tmp') | ||
526 | os.execute('grep -s " | pool/DEVUAN/" results/NEW_Packages_' .. r .. '.sorted.txt 2>/dev/null | head -n 1 >>results/NEW_Packages_' .. r .. '.test.tmp') | ||
527 | os.execute('mv results/NEW_Packages_' .. r .. '.test.tmp results/NEW_Packages_' .. r .. '.test.txt') | ||
528 | else | ||
529 | C("Can't find file Packages/" .. r .. dir .. "Packages_parsed-sorted") | ||
530 | end | ||
531 | os.execute('mkdir -p Packages/' .. r .. dir) | ||
532 | os.execute('mv -f results/pkgmaster.devuan.org/merged/dists/' .. r .. dir .. 'Packages_parsed-sorted Packages/' .. r .. dir .. 'Packages_parsed-sorted') | ||
533 | end | ||
534 | else | ||
535 | while not APT.checkFile('results/NEW_Packages_' .. r .. '.test.txt') do os.execute('sleep 10') end | ||
536 | end | ||
537 | os.execute('rm -f results/' .. host .. '/merged/dists/' .. r .. dir .. 'Packages 2>/dev/null') | ||
538 | os.execute('rm -f results/' .. host .. '/merged/dists/' .. r .. dir .. 'Packages.* 2>/dev/null') | ||
539 | end | ||
540 | end | 461 | end |
541 | end | 462 | end |
542 | 463 | ||
543 | local downloadLock = "flock -n results/curl-" | 464 | local downloadLock = "flock -n results/curl-" |
544 | local download = "curl --connect-timeout " .. APT.options.timeout.value .. " --create-dirs -f -L --max-time " .. APT.options.maxtime.value .. " -z 'results/stamp.old' -v -R " | 465 | local download = "curl" .. |
466 | " --connect-timeout " .. APT.options.timeout.value .. | ||
467 | " --create-dirs -f -L" .. | ||
468 | " --fail-early" .. | ||
469 | " --max-time " .. APT.options.maxtime.value .. | ||
470 | " --retry " .. APT.options.retries.value .. | ||
471 | " -R -v -z 'results/stamp.old' " | ||
545 | local downloads = function(host, URL, meta, release, list) | 472 | local downloads = function(host, URL, meta, release, list) |
546 | if nil == URL then URL = "" end | 473 | if nil == URL then URL = "" end |
547 | local lock = meta .. "-" .. host .. ".log" | 474 | local lock = meta .. "-" .. host .. ".log" |
@@ -600,6 +527,7 @@ local validateURL = function(m) | |||
600 | m.BaseURL = p.authority .. p.path | 527 | m.BaseURL = p.authority .. p.path |
601 | return m | 528 | return m |
602 | end | 529 | end |
530 | |||
603 | local getMirrors = function () | 531 | local getMirrors = function () |
604 | local mirrors = {} | 532 | local mirrors = {} |
605 | local host = "" | 533 | local host = "" |
@@ -621,8 +549,6 @@ local getMirrors = function () | |||
621 | end | 549 | end |
622 | host = d | 550 | host = d |
623 | m[t] = d | 551 | m[t] = d |
624 | gatherIPs(host) | ||
625 | m["IPs"] = IP[host] | ||
626 | elseif "Protocols" == t then | 552 | elseif "Protocols" == t then |
627 | local prot = {} | 553 | local prot = {} |
628 | for w in d:gmatch("(%w+)") do | 554 | for w in d:gmatch("(%w+)") do |
@@ -643,19 +569,305 @@ local getMirrors = function () | |||
643 | end | 569 | end |
644 | end | 570 | end |
645 | if APT.testing("DNSRR") then | 571 | if APT.testing("DNSRR") then |
646 | mirrors[APT.options.roundRobin.value] = { ["Protocols"] = { ["http"] = true; ["https"] = true; }; ["FQDN"] = 'deb.devuan.org'; ["Active"] = 'yes'; ["BaseURL"] = 'deb.devuan.org'; } | 572 | mirrors[APT.options.roundRobin.value] = { ["Protocols"] = { ["http"] = true; ["https"] = true; }; |
647 | gatherIPs(APT.options.roundRobin.value) | 573 | ["FQDN"] = APT.options.roundRobin.value; ["Active"] = 'yes'; ["BaseURL"] = APT.options.roundRobin.value; } |
648 | mirrors[APT.options.roundRobin.value].IPs = IP[APT.options.roundRobin.value] | ||
649 | end | ||
650 | local file, e = io.open("results/mirrors.lua", "w+") | ||
651 | if nil == file then C("opening mirrors file - " .. e) else | ||
652 | file:write(APT.dumpTable(mirrors, "", "mirrors") .. "\nreturn mirrors\n") | ||
653 | file:close() | ||
654 | end | 574 | end |
655 | return mirrors | 575 | return mirrors |
656 | end | 576 | end |
657 | 577 | ||
658 | 578 | ||
579 | local postParse = function(host, list) | ||
580 | if APT.options.referenceSite.value == host then | ||
581 | if nil ~= list then | ||
582 | local sem = 'results/NEW_' .. list.out .. '_%s.txt' | ||
583 | for i, n in pairs(releases) do | ||
584 | local f = sem:format(n) | ||
585 | if APT.checkFile(f .. '.tmp') then | ||
586 | os.execute('mv ' .. f .. '.tmp ' .. f) | ||
587 | else | ||
588 | os.execute('touch ' .. f) | ||
589 | end | ||
590 | end | ||
591 | end | ||
592 | end | ||
593 | end | ||
594 | |||
595 | local parseDebs = function(host) | ||
596 | for i, n in pairs(releases) do | ||
597 | local inFile = 'results/NEW_debs_' .. n .. '.txt' | ||
598 | local nfile, e = io.open(inFile, "r") | ||
599 | if nil == nfile then W("opening " .. inFile .. " file - " .. e) else | ||
600 | for l in nfile:lines() do | ||
601 | local v, p, sz, sha = l:match(' | (.+) | (pool/.+%.deb) | (%d.+) | (%x.+) |') | ||
602 | if nil ~= p then | ||
603 | if APT.checkFile('results/' .. host .. "/merged/" .. p) then | ||
604 | local status, fsz = APT.execute('ls -l results/' .. host .. "/merged/" .. p .. ' | cut -d " " -f 5-5') | ||
605 | if APT.testing("Integrity") then | ||
606 | if sz ~= fsz:sub(2, -2) then -- The sub bit is to slice off the EOLs at each end. | ||
607 | E('Package size mismatch - results/' .. host .. "/merged/" .. p .. ' should be ' .. sz .. ', but is ' .. fsz:sub(2, -2) .. '.', 'http', 'Integrity', host) | ||
608 | else | ||
609 | local status, fsha = APT.execute('sha256sum results/' .. host .. "/merged/" .. p .. ' | cut -d " " -f 1') | ||
610 | if sha ~= fsha:sub(2, -2) then E('Package SHA256 sum mismatch - results/' .. host .. "/merged/" .. p, 'http', 'Integrity', host) end | ||
611 | -- TODO - maybe check the PGP key, though packages are mostly not signed. | ||
612 | end | ||
613 | end | ||
614 | if APT.testing("Updated") then | ||
615 | if sz ~= fsz:sub(2, -2) then | ||
616 | E('Package size mismatch - results/' .. host .. "/merged/" .. p, 'http', 'Updated', host) | ||
617 | end | ||
618 | end | ||
619 | os.execute('rm -f results/' .. host .. "/merged/" .. p) | ||
620 | else | ||
621 | E('Failed to download - results/' .. host .. "/merged/" .. p, 'http', 'Updated', host) | ||
622 | end | ||
623 | end | ||
624 | end | ||
625 | end | ||
626 | end | ||
627 | return nil | ||
628 | end | ||
629 | |||
630 | local parsePackages = function(host) | ||
631 | local list = {inf = 'Packages', parser = parseDebs, out = 'debs', files = {}, nextf = ''} | ||
632 | for i, n in pairs(releases) do | ||
633 | local inFile = 'results/NEW_' .. list.inf .. '_' .. n .. '.txt' | ||
634 | local outFile = 'results/NEW_' .. list.out .. '_' .. n .. '.txt' | ||
635 | if APT.options.referenceSite.value == host then | ||
636 | outFile = outFile .. '.tmp' | ||
637 | end | ||
638 | local dFile, e = io.open(inFile, "r") | ||
639 | if nil == dFile then W("opening " .. inFile .. " file - " .. e) else | ||
640 | for l in dFile:lines() do | ||
641 | postDownload(host, n, l) | ||
642 | |||
643 | l = '/' .. l | ||
644 | local file = l:match(".*/([%w%.%+%-_]*)$") -- Get the filename. | ||
645 | local dir = l:sub(1, 0 - (#file + 1)) | ||
646 | |||
647 | if "Packages." == file:sub(1, 9) then | ||
648 | -- TODO - compare the SHA256 sums in pkgmaster's Release for both the packed and unpacked versions. | ||
649 | -- Also note that this might get only a partial download due to maxtime. | ||
650 | if APT.options.referenceSite.value == host then | ||
651 | local Pp, e = io.open('results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages.parsed', "w+") | ||
652 | if nil == Pp then W('opening results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages.parsed' .. ' file - ' .. e) else | ||
653 | local pp = {} | ||
654 | for l in io.lines('results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages') do | ||
655 | if "Package: " == l:sub(1, 9) then | ||
656 | if 0 ~= #pp then | ||
657 | for i = 1, 5 do | ||
658 | if nil == pp[i] then print(host .. " " .. n .. " " .. dir .. " " .. i) else Pp:write(pp[i] .. " | ") end | ||
659 | end | ||
660 | Pp:write("\n") | ||
661 | end | ||
662 | pp = {} | ||
663 | pp[1] = l:sub(10, -1) | ||
664 | elseif "Version: " == l:sub(1, 9) then | ||
665 | pp[2] = l:sub(10, -1) | ||
666 | elseif "Filename: " == l:sub(1, 10) then | ||
667 | pp[3] = l:sub(11, -1) | ||
668 | elseif "Size: " == l:sub(1, 6) then | ||
669 | pp[4] = l:sub(7, -1) | ||
670 | elseif "SHA256: " == l:sub(1, 8) then | ||
671 | pp[5] = l:sub(9, -1) | ||
672 | end | ||
673 | end | ||
674 | Pp:close() | ||
675 | os.execute('sort results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages.parsed >results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages_parsed-sorted') | ||
676 | if APT.checkFile('Packages/' .. n .. dir .. 'Packages_parsed-sorted') then | ||
677 | os.execute('diff -U 0 Packages/' .. n .. dir .. 'Packages_parsed-sorted ' .. | ||
678 | 'results/' .. APT.options.referenceSite.value .. '/merged/dists/' .. n .. dir .. 'Packages_parsed-sorted ' .. | ||
679 | ' | grep -E "^-" | grep -Ev "^\\+\\+\\+|^---" >>results/OLD_' .. list.out .. '_' .. n .. '.txt') | ||
680 | os.execute('diff -U 0 Packages/' .. n .. dir .. 'Packages_parsed-sorted ' .. | ||
681 | 'results/' .. APT.options.referenceSite.value .. '/merged/dists/' .. n .. dir .. 'Packages_parsed-sorted ' .. | ||
682 | ' | grep -E "^\\+" | grep -Ev "^\\+\\+\\+|^---" >>results/NEW_' .. list.out .. '_TMP_' .. n .. '.txt') | ||
683 | else | ||
684 | C("Can't find file Packages/" .. n .. dir .. "Packages_parsed-sorted") | ||
685 | end | ||
686 | os.execute('mkdir -p Packages/' .. n .. dir) | ||
687 | os.execute('mv -f results/' .. APT.options.referenceSite.value .. '/merged/dists/' .. n .. dir .. 'Packages_parsed-sorted Packages/' .. n .. dir .. 'Packages_parsed-sorted') | ||
688 | end | ||
689 | else | ||
690 | end | ||
691 | os.execute('rm -fr results/' .. host .. '/merged/dists/' .. n .. dir .. ' 2>/dev/null') | ||
692 | end | ||
693 | end | ||
694 | |||
695 | if APT.checkFile('results/NEW_' .. list.out .. '_TMP_' .. n .. '.txt') then | ||
696 | -- Sort by size. | ||
697 | os.execute('sort -b -k 9,9 -n results/NEW_' .. list.out .. '_TMP_' .. n .. '.txt >results/NEW_' .. list.out .. '_' .. n .. '.sorted.txt') | ||
698 | os.execute('grep -s " | pool/DEBIAN/" results/NEW_' .. list.out .. '_' .. n .. '.sorted.txt 2>/dev/null | head -n 1 >' .. outFile) | ||
699 | os.execute('grep -s " | pool/DEBIAN-SECURITY/" results/NEW_' .. list.out .. '_' .. n .. '.sorted.txt 2>/dev/null | head -n 1 >>' .. outFile) | ||
700 | os.execute('grep -s " | pool/DEVUAN/" results/NEW_' .. list.out .. '_' .. n .. '.sorted.txt 2>/dev/null | head -n 1 >>' .. outFile) | ||
701 | os.execute('rm -f results/NEW_' .. list.out .. '_TMP_' .. n .. '.txt') | ||
702 | end | ||
703 | |||
704 | end | ||
705 | |||
706 | local nfile, e = io.open(outFile, "r") | ||
707 | if nil ~= nfile then | ||
708 | -- for l in nfile:lines() do | ||
709 | local l = nfile:read('*l') | ||
710 | if nil ~= l then | ||
711 | local p = l:match('(pool/.*%.deb)') | ||
712 | if nil ~= p then | ||
713 | table.insert(list.files, p) | ||
714 | end | ||
715 | end | ||
716 | -- end | ||
717 | end | ||
718 | end | ||
719 | |||
720 | postParse(host, list) | ||
721 | return list | ||
722 | end | ||
723 | |||
724 | local parseRelease = function(host) | ||
725 | local list = {inf = 'Release', parser = parsePackages, out = 'Packages', files = {}, nextf = 'debs'} | ||
726 | for i, n in pairs(releases) do | ||
727 | for l, o in pairs(releaseFiles) do | ||
728 | if repoExists(i .. o) then | ||
729 | postDownload(host, n, o) | ||
730 | if (".gpg" == o:sub(-4, -1)) and (APT.checkFile('results/' .. host .. '/merged/dists/' .. n .. '/' .. o)) then | ||
731 | if APT.testing("Integrity") then | ||
732 | local status, out = APT.execute("gpgv --keyring /usr/share/keyrings/devuan-keyring.gpg results/" .. host .. "/merged/dists/" .. n .. '/' .. o .. | ||
733 | " results/" .. host .. "/merged/dists/" .. n .. '/' .. o:sub(1, -5) .. " 2>/dev/null") | ||
734 | if "0" ~= status then E("GPG check failed - " .. host .. "/merged/dists/" .. n .. '/' .. o, "http", "Integrity", host) end | ||
735 | -- TODO - should check the PGP sig of InRelease as well. | ||
736 | end | ||
737 | os.execute('rm results/' .. host .. '/merged/dists/' .. n .. '/' .. o) | ||
738 | end | ||
739 | end | ||
740 | end | ||
741 | |||
742 | if APT.checkFile('results/' .. host .. '/merged/dists/' .. n .. '/Release') then | ||
743 | os.execute('sort -k 3 results/' .. host .. '/merged/dists/' .. n .. '/Release >results/' .. host .. '/merged/dists/' .. n .. '/Release.SORTED') | ||
744 | local outFile = 'results/NEW_' .. list.out .. '_' .. n .. '.txt' | ||
745 | if APT.checkFile('results_old/' .. APT.options.referenceSite.value .. '/merged/dists/' .. n .. '/Release.SORTED') then | ||
746 | if APT.options.referenceSite.value == host then | ||
747 | outFile = outFile .. '.tmp' | ||
748 | os.execute('diff -U 0 results_old/' .. APT.options.referenceSite.value .. '/merged/dists/' .. n .. '/Release.SORTED ' .. | ||
749 | 'results/' .. APT.options.referenceSite.value .. '/merged/dists/' .. n .. '/Release.SORTED ' .. | ||
750 | '| grep -v "@@" | grep "^+" | grep "Packages.xz$" | cut -c 77- >' .. outFile) | ||
751 | -- TODO - Maybe check the date in Release, though since they are updated daily, is there any point? Perhaps it's for checking amprolla got run? | ||
752 | -- Also check if that date is in the future, apt recently got a check for that, though not sure why. | ||
753 | os.execute('rm -f results/' .. host .. '/merged/dists/' .. n .. '/Release 2>/dev/null; ') | ||
754 | else | ||
755 | -- TODO - compare to the pkgmaster copy. | ||
756 | end | ||
757 | |||
758 | -- TODO - if it's not Integrity and not reference, then just do a HEAD check and compare file times? | ||
759 | if APT.testing("Integrity") or (APT.options.referenceSite.value == host) then | ||
760 | local dfile, e = io.open(outFile, "r") | ||
761 | if nil == dfile then W("opening " .. outFile .. " file - " .. e) else | ||
762 | for l in dfile:lines() do | ||
763 | table.insert(list.files, 'dists/' .. n .. '/' .. l) | ||
764 | end | ||
765 | end | ||
766 | end | ||
767 | end | ||
768 | end | ||
769 | |||
770 | end | ||
771 | postParse(host, list) | ||
772 | return list | ||
773 | end | ||
774 | |||
775 | local parseStart = function(host) | ||
776 | local list = {inf = '', parser = parseRelease, out = 'Release', files = {}, nextf = 'Packages'} | ||
777 | for i, n in pairs(releases) do | ||
778 | local outFile = 'results/NEW_' .. list.out .. '_' .. n .. '.txt' | ||
779 | for l, o in pairs(releaseFiles) do | ||
780 | if repoExists(n .. o) then | ||
781 | if APT.options.referenceSite.value == host then | ||
782 | local dfile, e = io.open(outFile .. '.tmp', "a+") | ||
783 | if nil == dfile then W("opening " .. outFile .. ".tmp file - " .. e) else | ||
784 | dfile:write(o .. '\n') | ||
785 | end | ||
786 | end | ||
787 | table.insert(list.files, 'dists/' .. n .. '/' .. o) | ||
788 | end | ||
789 | end | ||
790 | end | ||
791 | postParse(host, list) | ||
792 | return list | ||
793 | end | ||
794 | |||
795 | local doDownloads = function(host, path, list) | ||
796 | while nil ~= list do | ||
797 | if 0 ~= #(list.files) then | ||
798 | for j, f in pairs(list.files) do | ||
799 | downloads(host, path, list.out, nil, f) | ||
800 | end | ||
801 | downloads(host, path, list.out, nil, '') | ||
802 | --[[ I've seen flock & curl act oddly. Perhaps flock didn't have time to start up? | ||
803 | /var/www/html/apt-panopticon/apt-panopticon/results_2019-12-22-15-00 | ||
804 | |||
805 | Mon Dec 23 01:02:54 2019 DEBUG : forking | ||
806 | |||
807 | ionice -c3 nice -n 19 flock -n results/curl-debs-pkgmaster.devuan.org.log curl --connect-timeout 5 --create-dirs -f -L --fail-early --max-time 300 --retry 3 -R -v -z 'results/stamp.old' --stderr results/curl-debs-pkgmaster.devuan.org.log -K results/curl-debs-pkgmaster.devuan.org.files | ||
808 | |||
809 | |||
810 | Mon Dec 23 01:02:54 2019 DEBUG : 0 flock -n results/curl-debs-pkgmaster.devuan.org.log commands still running. | ||
811 | Mon Dec 23 01:02:54 2019 DEBUG : *>* Resumed coroutine NO LONGER waiting on - 0 < APT.checkExes(flock -n results/curl-debs-pkgmaster.devuan.org.log | ||
812 | Mon Dec 23 01:02:54 2019 DEBUG : *** Doing list.parser() for debs | ||
813 | Mon Dec 23 01:02:54 2019 ERROR (http Updated pkgmaster.devuan.org): Failed to download - results/pkgmaster.devuan.org/merged/pool/DEBIAN/main/a/aptly/aptly_1.3.0+ds1-4_amd64.deb | ||
814 | |||
815 | drwxr-x--- 2 www-data www-data 4096 2019-12-23 01:02:57.000000000 +1000 aptly | ||
816 | -rw-r--r-- 1 www-data www-data 7129 2019-12-23 01:03:54.000000000 +1000 curl-debs-pkgmaster.devuan.org.log | ||
817 | |||
818 | ]] | ||
819 | os.execute('sleep 2') | ||
820 | while 0 < APT.checkExes(downloadLock .. list.out .. "-" .. host .. ".log") do | ||
821 | D('*<* About to yield coroutine while waiting on - 0 < APT.checkExes(' .. downloadLock .. list.out .. '-' .. host .. '.log') | ||
822 | coroutine.yield() | ||
823 | D('*>* Resumed coroutine while waiting on - 0 < APT.checkExes(' .. downloadLock .. list.out .. '-' .. host .. '.log') | ||
824 | end | ||
825 | D('*>* Resumed coroutine NO LONGER waiting on - 0 < APT.checkExes(' .. downloadLock .. list.out .. '-' .. host .. '.log') | ||
826 | |||
827 | local min, max, spd = 999999999999, 0 | ||
828 | if APT.checkFile("results/curl-" .. list.out .. "-" .. host .. ".log") then | ||
829 | for l in io.lines("results/curl-" .. list.out .. "-" .. host .. ".log") do | ||
830 | local speed, crrnt = l:match('^%c *%d+ +%d+k? +%d+ +%d+k? +%d+ +%d+ +(%d+k?) +%d+ +[%d%-]+:[%d%-]+:[%d%-]+ +[%d%-]+:[%d%-]+:[%d%-]+ +[%d%-]+:[%d%-]+:[%d%-]+ +(%d+k?)') | ||
831 | if nil ~= speed then | ||
832 | if 'k' == speed:sub(-1, -1) then speed = speed:sub(1, -2) .. '000' end | ||
833 | if 'k' == crrnt:sub(-1, -1) then crrnt = crrnt:sub(1, -2) .. '000' end | ||
834 | speed = tonumber(speed) | ||
835 | crrnt = tonumber(crrnt) | ||
836 | if speed < min and speed ~= 0 then min = speed end | ||
837 | if speed > max then max = speed end | ||
838 | if crrnt < min and crrnt ~= 0 then min = crrnt end | ||
839 | if crrnt > max then max = crrnt end | ||
840 | end | ||
841 | if l:find('timed out') ~= nil then | ||
842 | E(" TIMEOUT " .. timeouts + 1 .. ', details in curl-' .. list.out .. '-' .. host .. '.log', 'http', '', host) | ||
843 | timeouts = timeouts + 1 | ||
844 | APT.results["timeout"] = true | ||
845 | end | ||
846 | end | ||
847 | end | ||
848 | APT.results["speed"] = {min = min, max = max} | ||
849 | end | ||
850 | |||
851 | if (APT.options.referenceSite.value ~= host) and ('' ~= list.nextf) then | ||
852 | local sem = 'results/NEW_' .. list.nextf .. '_%s.txt' | ||
853 | for i, n in pairs(releases) do | ||
854 | local f = sem:format(n) | ||
855 | while not APT.checkFile(f) do | ||
856 | D('*<* About to yield coroutine while waiting on - not APT.checkFile(' .. f .. ')') | ||
857 | coroutine.yield() | ||
858 | D('*>* Resumed coroutine while waiting on - not APT.checkFile(' .. f .. ')') | ||
859 | end | ||
860 | end | ||
861 | end | ||
862 | D('*** Doing list.parser() for ' .. list.out) | ||
863 | list = list.parser(host) | ||
864 | if APT.options.timeouts.value <= (totalTimeouts) then break end | ||
865 | end | ||
866 | D('*<<* About to end coroutine.') | ||
867 | cor = nil | ||
868 | end | ||
869 | |||
870 | |||
659 | if 0 < #arg then | 871 | if 0 < #arg then |
660 | if "/" == arg[1]:sub(-1, -1) then | 872 | if "/" == arg[1]:sub(-1, -1) then |
661 | W("slash at end of path! " .. arg[1]) | 873 | W("slash at end of path! " .. arg[1]) |
@@ -673,6 +885,8 @@ if 0 < #arg then | |||
673 | end | 885 | end |
674 | end | 886 | end |
675 | 887 | ||
888 | if APT.origin then APT.results["IPs"] = gatherIPs(pu.host) end | ||
889 | |||
676 | if nil ~= arg[2] then | 890 | if nil ~= arg[2] then |
677 | APT.logFile, e = io.open("results/LOG_" .. pu.host .. "_" .. arg[2] .. ".html", "a+") | 891 | APT.logFile, e = io.open("results/LOG_" .. pu.host .. "_" .. arg[2] .. ".html", "a+") |
678 | else | 892 | else |
@@ -681,165 +895,57 @@ if 0 < #arg then | |||
681 | if nil == APT.logFile then C("opening log file - " .. e); return end | 895 | if nil == APT.logFile then C("opening log file - " .. e); return end |
682 | APT.logPre() | 896 | APT.logPre() |
683 | I("Starting tests for " .. arg[1] .. " with these tests - " .. table.concat(APT.options.tests.value, ", ")) | 897 | I("Starting tests for " .. arg[1] .. " with these tests - " .. table.concat(APT.options.tests.value, ", ")) |
684 | APT.mirrors = loadfile("results/mirrors.lua")() | ||
685 | if nil ~= arg[2] then I(" Using IP " .. arg[2]); ip = arg[2] end | 898 | if nil ~= arg[2] then I(" Using IP " .. arg[2]); ip = arg[2] end |
686 | if nil ~= arg[3] then I(" Using file " .. arg[3]); end | 899 | if nil ~= arg[3] then I(" Using file " .. arg[3]); end |
687 | APT.results = APT.padResults(APT.results) | 900 | APT.results = APT.padResults(APT.results) |
901 | |||
688 | if APT.origin then | 902 | if APT.origin then |
903 | |||
904 | local file = arg[3] | ||
905 | if nil == file then file = '' end | ||
906 | local path = pu.path | ||
907 | if nil == path then path = '' end | ||
908 | local ips = APT.results["IPs"] | ||
909 | for k, v in pairs(ips) do | ||
910 | if "table" == type(v) then | ||
911 | for k1, v1 in pairs(v) do | ||
912 | if v1 == "A" then | ||
913 | if APT.testing("IPv4") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. pu.host .. path .. " " .. k1 .. " " .. file) end | ||
914 | elseif v1 == "AAAA" then | ||
915 | if APT.testing("IPv6") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. pu.host .. path .. " " .. k1 .. " " .. file) end | ||
916 | end | ||
917 | end | ||
918 | else | ||
919 | if v == "A" then | ||
920 | if APT.testing("IPv4") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. pu.host .. path .. " " .. k .. " " .. file) end | ||
921 | elseif v == "AAAA" then | ||
922 | if APT.testing("IPv6") then APT.fork("ionice -c3 ./apt-panopticon.lua " .. sendArgs .. " " .. pu.host .. path .. " " .. k .. " " .. file) end | ||
923 | end | ||
924 | end | ||
925 | end | ||
926 | |||
689 | if APT.testing("Integrity") or APT.testing("Updated") then | 927 | if APT.testing("Integrity") or APT.testing("Updated") then |
690 | if APT.origin and (APT.options.roundRobin.value ~= pu.host) then | 928 | if APT.origin and (APT.options.roundRobin.value ~= pu.host) then |
691 | I("Starting file downloads for " .. pu.host) | 929 | I("Starting file downloads for " .. pu.host) |
692 | downloads(pu.host, pu.path, 'Release') | 930 | D('*>* About to create coroutine.') |
931 | cor = coroutine.create(doDownloads) | ||
932 | local ok, message = coroutine.resume(cor, pu.host, pu.path, parseStart(pu.host)) | ||
933 | if not ok then cor = nil; print(message) end | ||
693 | end | 934 | end |
694 | end | 935 | end |
936 | |||
695 | checkFiles(pu.host, pu.host, pu.path); | 937 | checkFiles(pu.host, pu.host, pu.path); |
696 | else | 938 | else |
697 | checkHost(pu.host, pu.host, pu.path, arg[2], arg[3]) | 939 | checkHost(pu.host, pu.host, pu.path, arg[2], arg[3]) |
698 | end | 940 | end |
699 | 941 | ||
700 | if APT.testing("Integrity") or APT.testing("Updated") then | 942 | while nil ~= cor do |
701 | if 4 > (totalTimeouts) then | 943 | os.execute('sleep 10') |
702 | if APT.origin and (APT.options.roundRobin.value ~= pu.host) then | 944 | D('*>* About to resume coroutine before writing results.') |
703 | while 0 < APT.checkExes(downloadLock .. "Release-" .. pu.host .. ".log") do os.execute("sleep 10") end | ||
704 | |||
705 | local fcount = 0 | ||
706 | for i, n in pairs(releases) do | ||
707 | for l, o in pairs(releaseFiles) do | ||
708 | if repoExists(i .. o) then | ||
709 | postDownload(pu.host, n, o) | ||
710 | end | ||
711 | end | ||
712 | |||
713 | if APT.checkFile('results/' .. pu.host .. '/merged/dists/' .. n .. '/Release') then | ||
714 | os.execute('sort -k 3 results/' .. pu.host .. '/merged/dists/' .. n .. '/Release >results/' .. pu.host .. '/merged/dists/' .. n .. '/Release.SORTED') | ||
715 | if APT.checkFile('results_old/pkgmaster.devuan.org/merged/dists/' .. n .. '/Release.SORTED') then | ||
716 | if APT.options.referenceSite.value == pu.host then | ||
717 | os.execute('diff -U 0 results_old/pkgmaster.devuan.org/merged/dists/' .. n .. '/Release.SORTED ' .. | ||
718 | 'results/pkgmaster.devuan.org/merged/dists/' .. n .. '/Release.SORTED ' .. | ||
719 | '| grep -v "@@" | grep "^+" | grep "Packages.xz$" | cut -c 77- >results/NEW_Release_' .. n .. '.tmp') | ||
720 | -- TODO - Maybe check the date in Release, though since they are updated daily, is there any point? Perhaps it's for checking amprolla got run? | ||
721 | os.execute('rm -f results/' .. pu.host .. '/merged/dists/' .. n .. '/Release 2>/dev/null; ' .. | ||
722 | 'mv results/NEW_Release_' .. n .. '.tmp results/NEW_Release_' .. n .. '.txt') | ||
723 | else | ||
724 | -- TODO - compare to the pkgmaster copy. | ||
725 | while not APT.checkFile('results/NEW_Release_' .. n .. '.txt') do os.execute('sleep 10') end | ||
726 | end | ||
727 | |||
728 | local dfile, e = io.open('results/NEW_Release_' .. n .. '.txt', "r") | ||
729 | if nil == dfile then W("opening results/NEW_Release_" .. n .. " file - " .. e) else | ||
730 | local diff = dfile:read("*a") | ||
731 | if "" ~= diff then | ||
732 | downloads(pu.host, pu.path, 'Packages', n, diff) | ||
733 | fcount = fcount + 1 | ||
734 | end | ||
735 | end | ||
736 | end | ||
737 | end | ||
738 | |||
739 | end | ||
740 | |||
741 | if 0 ~= fcount then | ||
742 | downloads(pu.host, pu.path, 'Packages', "", "") | ||
743 | while 0 < APT.checkExes(downloadLock .. "Packages-" .. pu.host .. ".log") do os.execute("sleep 10") end | ||
744 | |||
745 | for i, n in pairs(releases) do | ||
746 | local dfile, e = io.open('results/NEW_Release_' .. n .. '.txt', "r") | ||
747 | if nil == dfile then W("opening results/NEW_Release_" .. n .. ".txt file - " .. e) else | ||
748 | local diff = dfile:read("*a") | ||
749 | for l in diff:gmatch("\n*([^\n]+)\n*") do | ||
750 | postDownload(pu.host, n, "/" .. l) | ||
751 | end | ||
752 | end | ||
753 | if APT.options.referenceSite.value == pu.host then | ||
754 | -- In case it wasn't dealt with already. | ||
755 | os.execute('touch results/NEW_Packages_' .. n .. '.test.txt') | ||
756 | end | ||
757 | end | ||
758 | |||
759 | fcount = 0 | ||
760 | for i, n in pairs(releases) do | ||
761 | local nfile, e = io.open('results/NEW_Packages_' .. n .. '.test.txt', "r") | ||
762 | if nil == nfile then W("opening results/NEW_Packages_" .. n .. ".test.txt file - " .. e) else | ||
763 | for l in nfile:lines() do | ||
764 | local p = l:match('(pool/.*%.deb)') | ||
765 | if nil ~= p then | ||
766 | downloads(pu.host, pu.path, 'package', nil, p) | ||
767 | fcount = fcount + 1 | ||
768 | end | ||
769 | end | ||
770 | end | ||
771 | end | ||
772 | |||
773 | if 0 ~= fcount then | ||
774 | downloads(pu.host, pu.path, 'package', nil, "") | ||
775 | while 0 < APT.checkExes(downloadLock .. "package-" .. pu.host .. ".log") do os.execute("sleep 10") end | ||
776 | for i, n in pairs(releases) do | ||
777 | local nfile, e = io.open('results/NEW_Packages_' .. n .. '.test.txt', "r") | ||
778 | if nil == nfile then W("opening results/NEW_Packages_" .. n .. ".test.txt file - " .. e) else | ||
779 | for l in nfile:lines() do | ||
780 | local v, p, sz, sha = l:match(' | (.+) | (pool/.+%.deb) | (%d.+) | (%x.+) |') | ||
781 | if nil ~= p then | ||
782 | if APT.checkFile('results/' .. pu.host .. "/merged/" .. p) then | ||
783 | local status, fsz = APT.execute('ls -l results/' .. pu.host .. "/merged/" .. p .. ' | cut -d " " -f 5-5') | ||
784 | if APT.testing("Integrity") then | ||
785 | if sz ~= fsz:sub(2, -2) then -- The sub bit is to slice off the EOLs at each end. | ||
786 | E('Package size mismatch - results/' .. pu.host .. "/merged/" .. p .. ' should be ' .. sz .. ', but is ' .. fsz:sub(2, -2) .. '.', 'http', 'Integrity', pu.host) | ||
787 | else | ||
788 | local status, fsha = APT.execute('sha256sum results/' .. pu.host .. "/merged/" .. p .. ' | cut -d " " -f 1') | ||
789 | if sha ~= fsha:sub(2, -2) then E('Package SHA256 sum mismatch - results/' .. pu.host .. "/merged/" .. p, 'http', 'Integrity', pu.host) end | ||
790 | -- TODO - maybe check the PGP key, though packages are mostly not signed. | ||
791 | end | ||
792 | end | ||
793 | if APT.testing("Updated") then | ||
794 | if sz ~= fsz:sub(2, -2) then | ||
795 | E('Package size mismatch - results/' .. pu.host .. "/merged/" .. p, 'http', 'Updated', pu.host) | ||
796 | end | ||
797 | end | ||
798 | else | ||
799 | E('Failed to download - results/' .. pu.host .. "/merged/" .. p, 'http', 'Updated', pu.host) | ||
800 | end | ||
801 | end | ||
802 | end | ||
803 | end | ||
804 | end | ||
805 | end | ||
806 | else | ||
807 | for i, n in pairs(releases) do | ||
808 | os.execute('touch results/NEW_Packages_' .. n .. '.test.txt') | ||
809 | end | ||
810 | end | ||
811 | end | ||
812 | 945 | ||
813 | APT.results["timeout"] = false | 946 | local ok, message = coroutine.resume(cor) |
814 | else | 947 | if not ok then cor = nil; print(message); break end |
815 | APT.results["timeout"] = true | ||
816 | end | ||
817 | end | ||
818 | |||
819 | local min, max, spd = 999999999999, 0 | ||
820 | for i, mt in pairs({'Release', 'Packages', 'package'}) do | ||
821 | if APT.checkFile("results/curl-" .. mt .. "-" .. pu.host .. ".log") then | ||
822 | for l in io.lines("results/curl-" .. mt .. "-" .. pu.host .. ".log") do | ||
823 | local speed, crrnt = l:match('^%c *%d+ +%d+k? +%d+ +%d+k? +%d+ +%d+ +(%d+k?) +%d+ +[%d%-]+:[%d%-]+:[%d%-]+ +[%d%-]+:[%d%-]+:[%d%-]+ +[%d%-]+:[%d%-]+:[%d%-]+ +(%d+k?)') | ||
824 | if nil ~= speed then | ||
825 | if 'k' == speed:sub(-1, -1) then speed = speed:sub(1, -2) .. '000' end | ||
826 | if 'k' == crrnt:sub(-1, -1) then crrnt = crrnt:sub(1, -2) .. '000' end | ||
827 | speed = tonumber(speed) | ||
828 | crrnt = tonumber(crrnt) | ||
829 | if speed < min and speed ~= 0 then min = speed end | ||
830 | if speed > max then max = speed end | ||
831 | if crrnt < min and crrnt ~= 0 then min = crrnt end | ||
832 | if crrnt > max then max = crrnt end | ||
833 | end | ||
834 | if l:find('timed out') ~= nil then | ||
835 | E(" TIMEOUT " .. timeouts + 1 .. ', details in curl-' .. mt .. '-' .. pu.host .. '.log', 'http', '', pu.host) | ||
836 | timeouts = timeouts + 1 | ||
837 | APT.results["timeout"] = true | ||
838 | end | ||
839 | end | ||
840 | end | ||
841 | end | 948 | end |
842 | APT.results["speed"] = {min = min, max = max} | ||
843 | 949 | ||
844 | local f = pu.host | 950 | local f = pu.host |
845 | if "" ~= ip then f = f .. "_" .. ip end | 951 | if "" ~= ip then f = f .. "_" .. ip end |
@@ -891,13 +997,23 @@ else | |||
891 | local pu = url.parse("http://" .. m.BaseURL) | 997 | local pu = url.parse("http://" .. m.BaseURL) |
892 | if APT.options.referenceSite.value ~= pu.host then | 998 | if APT.options.referenceSite.value ~= pu.host then |
893 | checkHost(m.BaseURL) | 999 | checkHost(m.BaseURL) |
894 | APT.checkExes("apt-panopticon.lua " .. sendArgs) | ||
895 | if APT.testing("Integrity") or APT.testing("Updated") then APT.checkExes(downloadLock) end | ||
896 | end | 1000 | end |
897 | end | 1001 | end |
898 | 1002 | ||
899 | while 1 <= APT.checkExes("apt-panopticon.lua " .. sendArgs) do os.execute("sleep 10") end | 1003 | while 1 <= APT.checkExes("apt-panopticon.lua " .. sendArgs) do os.execute("sleep 10") end |
900 | os.execute('rm -f results/*.check; rm STATUS_* 2>/dev/null') | 1004 | os.execute('rm -f results/*.check; rm STATUS_* 2>/dev/null') |
1005 | for k, v in pairs(APT.mirrors) do | ||
1006 | local f = 'results/' .. k .. '.lua' | ||
1007 | if APT.checkFile(f) then | ||
1008 | results = loadfile(f)() | ||
1009 | APT.mirrors[k]['IPs'] = results.IPs | ||
1010 | end | ||
1011 | end | ||
1012 | local file, e = io.open("results/mirrors.lua", "w+") | ||
1013 | if nil == file then C("opening mirrors file - " .. e) else | ||
1014 | file:write(APT.dumpTable(APT.mirrors, "", "mirrors") .. "\nreturn mirrors\n") | ||
1015 | file:close() | ||
1016 | end | ||
901 | 1017 | ||
902 | -- Create the reports. | 1018 | -- Create the reports. |
903 | for n, r in pairs(APT.options.reports.value) do | 1019 | for n, r in pairs(APT.options.reports.value) do |