A utility for downloading and verifying FreeBSD releases and snapshots
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

357 lines
8.9 KiB

  1. #
  2. # Copyright 2018, 2022 John-Mark Gurney.
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions
  7. # are met:
  8. # 1. Redistributions of source code must retain the above copyright
  9. # notice, this list of conditions and the following disclaimer.
  10. # 2. Redistributions in binary form must reproduce the above copyright
  11. # notice, this list of conditions and the following disclaimer in the
  12. # documentation and/or other materials provided with the distribution.
  13. #
  14. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. # SUCH DAMAGE.
  25. #
  26. # $Id$
  27. #
  28. BEGIN {
  29. vmroot = "https://download.freebsd.org/ftp/snapshots/VM-IMAGES/"
  30. isoroot = "https://download.freebsd.org/ftp/snapshots/ISO-IMAGES/"
  31. bciroot = "https://download.freebsd.org/ftp/snapshots/CI-IMAGES/"
  32. relvmroot = "https://download.freebsd.org/ftp/releases/VM-IMAGES/"
  33. relisoroot = "https://download.freebsd.org/ftp/releases/ISO-IMAGES/"
  34. relbciroot = "https://download.freebsd.org/ftp/releases/CI-IMAGES/"
  35. #print "begin" > "/dev/stderr"
  36. hexdigits["0"] = 0
  37. hexdigits["1"] = 1
  38. hexdigits["2"] = 2
  39. hexdigits["3"] = 3
  40. hexdigits["4"] = 4
  41. hexdigits["5"] = 5
  42. hexdigits["6"] = 6
  43. hexdigits["7"] = 7
  44. hexdigits["8"] = 8
  45. hexdigits["9"] = 9
  46. hexdigits["A"] = 10
  47. hexdigits["B"] = 11
  48. hexdigits["C"] = 12
  49. hexdigits["D"] = 13
  50. hexdigits["E"] = 14
  51. hexdigits["F"] = 15
  52. if (DO_TESTS == 1) {
  53. run_tests()
  54. exit(0)
  55. }
  56. }
  57. function run_tests() {
  58. fromhextests["3D"] = 61
  59. fromhextests["3F"] = 63
  60. for (i in fromhextests) {
  61. if (fromhex(i) != fromhextests[i]) {
  62. printf("ERROR: fromhex failed on %s, expecting %d, got %d.\n", i, fromhextests[i], fromhex(i))
  63. exit(1)
  64. }
  65. }
  66. validrevs[0] = "r369411"
  67. validrevs[1] = "c122cf32f2a"
  68. for (i in validrevs) {
  69. if (!isrev(validrevs[i])) {
  70. print "ERROR: valid rev not valid: " validrevs[i]
  71. exit(1)
  72. }
  73. }
  74. invalidrevs[0] = "asoijw23r"
  75. for (i in invalidrevs) {
  76. if (isrev(invalidrevs[i])) {
  77. print "ERROR: invalid rev valid: " invalidrevs[i]
  78. exit(1)
  79. }
  80. }
  81. }
  82. function fromhex(val) {
  83. r = 0
  84. while (val) {
  85. r = r * 16 + hexdigits[substr(val, 1, 1)]
  86. val = substr(val, 2)
  87. }
  88. return r
  89. }
  90. {
  91. #print "raw " $0 > "/dev/stderr"
  92. }
  93. !MID && tolower($1) == "message-id:" {
  94. MID=$2
  95. sub(".*<", "", MID)
  96. sub(">.*", "", MID)
  97. }
  98. !haveboundary && tolower($1) == "content-type:" && tolower($2) == "multipart/signed;" && check == 0 {
  99. getboundary = 1
  100. next
  101. }
  102. getboundary == 1 {
  103. getboundary = 0
  104. haveboundary = 1
  105. if (substr($2, 1, 9) == "boundary=")
  106. boundary=substr($2, 11, length($2) - 11)
  107. next
  108. }
  109. haveboundary && $1 == ("--" boundary) {
  110. sigbody = 1
  111. bodyheaders = 1
  112. }
  113. !haveboundary && $0 == "-----BEGIN PGP SIGNED MESSAGE-----" {
  114. sigbody = 1
  115. }
  116. # Skip processing till we have the body
  117. !sigbody {
  118. next
  119. }
  120. bodyheaders {
  121. if (tolower($1) == "content-transfer-encoding:" && tolower($2) == "quoted-printable")
  122. quotedprintable = 1
  123. if ($0 == "") {
  124. #print "end of headers " $0 > "/dev/stderr"
  125. bodyheaders = 0
  126. }
  127. next
  128. }
  129. quotedprintable {
  130. #print "orig raw " $0 > "/dev/stderr"
  131. contline = 0
  132. if (substr($0, length($0), 1) == "=") {
  133. contline = 1
  134. $0 = substr($0, 1, length($0) - 1)
  135. }
  136. procline = $0
  137. line = ""
  138. while (1) {
  139. #print "procline " procline > "/dev/stderr"
  140. #print "line " line > "/dev/stderr"
  141. pos = index(procline, "=")
  142. #print "pos " pos > "/dev/stderr"
  143. if (pos == 0) {
  144. line = line procline
  145. break
  146. }
  147. line = line substr(procline, 1, pos - 1) sprintf("%c", fromhex(substr(procline, pos + 1, 2)))
  148. procline = substr(procline, pos + 3)
  149. }
  150. $0 = line
  151. #print " new raw " $0 > "/dev/stderr"
  152. if (contline) {
  153. #print "continuing" > "/dev/stderr"
  154. prevline = prevline $0
  155. next
  156. }
  157. $0 = prevline $0
  158. prevline = ""
  159. #print "mid " MID > "/dev/stderr"
  160. #print "proc raw " $0 > "/dev/stderr"
  161. }
  162. $0 == "== ISO CHECKSUMS ==" ||
  163. $0 == "ISO Image Checksums" {
  164. type = "iso"
  165. }
  166. $0 == "== VM IMAGE CHECKSUMS ==" ||
  167. $0 == "Virtual Machine Disk Image Checksums" {
  168. type = "vm"
  169. }
  170. function isdate(date) {
  171. m = match(date, "[0-9]+")
  172. if (m && RLENGTH == 8)
  173. return 1
  174. return 0
  175. }
  176. function isrev(s) {
  177. if (substr(s, 1, 1) == "r")
  178. return 1
  179. m = match(s, "[0-9a-f]+")
  180. if (m && RLENGTH == 11)
  181. return 1
  182. return 0
  183. }
  184. function isrelease(relpart) {
  185. if (index(relpart, "BETA") == 1 || index(relpart, "RC") == 1 ||
  186. index(relpart, "RELEASE") == 1)
  187. return 1
  188. return 0
  189. }
  190. #FreeBSD-13.0-CURRENT-arm64-aarch64-20200903-c122cf32f2a.qcow2.xz
  191. #FreeBSD-13.0-CURRENT-powerpc-powerpcspe-20181026-r339752-bootonly.iso
  192. #FreeBSD-13.0-CURRENT-sparc64-20181026-r339752-bootonly.iso.asc
  193. #FreeBSD-13.0-CURRENT-arm64-aarch64-PINE64-LTS-20181026-r339752.img.xz
  194. #FreeBSD-13.0-CURRENT-i386-20181026-r339752.vmdk.xz
  195. #FreeBSD-12.1-BETA3-amd64-mini-memstick.img.xz
  196. #FreeBSD-12.1-RC1-amd64-mini-memstick.img.xz
  197. #FreeBSD-12.1-RELEASE-arm64-aarch64.vmdk.xz
  198. #FreeBSD-13.1-RELEASE-riscv-riscv64.vmdk.xz
  199. #FreeBSD-13.1-RELEASE-amd64-BASIC-CI.raw.xz
  200. /.*SHA512 (.*) = [0-9a-f]+/ {
  201. #print "raw " $0 > "/dev/stderr"
  202. # Strip parens
  203. fname = substr($2, 2, length($2) - 2)
  204. split(fname, dotparts, ".")
  205. # recombine around dot in version, strips off ALL extensions (including vm type)
  206. basename = dotparts[1] "." dotparts[2]
  207. cnt = split(basename, parts, "-")
  208. # make arch part, may include additional part
  209. arch = parts[4]
  210. basearch = arch
  211. if (parts[4] == "arm" || parts[4] == "riscv" ||
  212. (parts[4] == "powerpc" && parts[5] == "powerpcspe") ||
  213. (parts[4] == "powerpc" && parts[5] == "powerpc64") ||
  214. parts[4] == "arm64") {
  215. # FreeBSD-11.3-STABLE-arm64-aarch64-20191011-r353406-memstick.img
  216. basearch = parts[5]
  217. arch = parts[4] "-" parts[5]
  218. nextidx = 6
  219. } else {
  220. # FreeBSD-11.3-STABLE-amd64-20191011-r353406.qcow2.xz
  221. nextidx = 5
  222. }
  223. # find date, may be platform first
  224. if (isrelease(parts[3])) {
  225. if (nextidx > cnt) {
  226. # FreeBSD-12.1-BETA3-i386.vhd.xz
  227. platform = "xxx"
  228. } else if (cnt == nextidx) {
  229. # FreeBSD-12.1-RC1-powerpc-powerpcspe-dvd1.iso
  230. platform = parts[nextidx]
  231. nextidx += 1
  232. } else {
  233. # FreeBSD-12.1-BETA3-amd64-mini-memstick.img.xz
  234. platform = parts[nextidx] "-" parts[nextidx + 1]
  235. nextidx += 2
  236. }
  237. date = "xxx"
  238. } else if (isdate(parts[nextidx])) {
  239. # FreeBSD-11.3-STABLE-amd64-20191011-r353406.qcow2.xz
  240. platform = "xxx"
  241. date = parts[nextidx]
  242. nextidx += 1
  243. } else {
  244. # FreeBSD-13.0-CURRENT-arm64-aarch64-PINE64-LTS-20181026-r339752.img.xz
  245. platform = parts[nextidx]
  246. date = parts[nextidx + 1]
  247. if (isdate(date)) {
  248. # FreeBSD-13.0-CURRENT-arm64-aarch64-PINEBOOK-20191011-r353427.img.xz
  249. nextidx += 2
  250. } else {
  251. # FreeBSD-13.0-CURRENT-arm64-aarch64-PINE64-LTS-20181026-r339752.img.xz
  252. date = parts[nextidx + 2]
  253. platform = parts[nextidx] "-" parts[nextidx + 1]
  254. nextidx += 3
  255. }
  256. }
  257. if (nextidx >= cnt)
  258. vers="xxx"
  259. else {
  260. vers=""
  261. sep=""
  262. for (i = nextidx + 1; i <= cnt; i++) {
  263. vers = vers sep parts[i]
  264. sep="-"
  265. }
  266. }
  267. if (isrelease(parts[3])) {
  268. if (platform == "BASIC-CI") {
  269. vers = dotparts[3]
  270. url = relbciroot parts[2] "-" parts[3] "/" basearch "/Latest/" fname
  271. } else if (type == "vm") {
  272. vers = dotparts[3]
  273. url = relvmroot parts[2] "-" parts[3] "/" basearch "/Latest/" fname
  274. } else
  275. url = relisoroot parts[2] "/" fname
  276. } else {
  277. if (platform == "BASIC-CI") {
  278. vers = dotparts[3]
  279. url = bciroot parts[2] "-" parts[3] "/" basearch "/" date "/" fname
  280. } else if (type == "vm") {
  281. vers = dotparts[3]
  282. url = vmroot parts[2] "-" parts[3] "/" basearch "/" date "/" fname
  283. } else
  284. url = isoroot parts[2] "/" fname
  285. }
  286. # if this part doesn't begin w/ r (for svn rev), skip it, we can't parse
  287. # others for now
  288. rev = parts[nextidx]
  289. if (isrelease(parts[3])) {
  290. # FreeBSD-12.1-RC1-amd64-mini-memstick.img.xz
  291. rev = "unspec"
  292. } else if (!isrev(rev)) {
  293. print "invalid rev, skipping: " rev > "/dev/stderr"
  294. #print "raw " $0 > "/dev/stderr"
  295. #printf("%s %s %s %s %s %s %s %s %s %s\n", type, parts[2] "-" parts[3], arch, platform, date, rev, vers, fname, url, MID) > "/dev/stderr"
  296. next
  297. }
  298. # double check that date is valid, if not, skip it
  299. if (date != "xxx" && !isdate(date))
  300. next
  301. printf("%s %s %s %s %s %s %s %s %s %s\n", type, parts[2] "-" parts[3], arch, platform, date, rev, vers, fname, url, MID)
  302. #printf("%s %s %s %s %s %s %s %s %s %s\n", type, parts[2] "-" parts[3], arch, platform, date, rev, vers, fname, url, MID) > "/dev/stderr"
  303. }