mirror of the now-defunct rocklinux.org
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.

316 lines
8.2 KiB

  1. /* Copyright 2001 Red Hat, Inc. */
  2. /* Michael Fulbright msf@redhat.com */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <unistd.h>
  8. #include <fcntl.h>
  9. #include <string.h>
  10. #include "md5.h"
  11. #include "libcheckisomd5.h"
  12. #define APPDATA_OFFSET 883
  13. #define SIZE_OFFSET 84
  14. #define MAX(x, y) ((x > y) ? x : y)
  15. #define MIN(x, y) ((x < y) ? x : y)
  16. /* finds primary volume descriptor and returns info from it */
  17. /* mediasum must be a preallocated buffer at least 33 bytes long */
  18. static int parsepvd(int isofd, char *mediasum, int *skipsectors, long long *isosize, int *supported) {
  19. unsigned char buf[2048];
  20. unsigned char buf2[512];
  21. unsigned char tmpbuf[512];
  22. int skipfnd, md5fnd, supportedfnd;
  23. unsigned int loc;
  24. long long offset;
  25. unsigned char *p;
  26. *supported = 0;
  27. if (lseek(isofd, (off_t)(16L * 2048L), SEEK_SET) == -1)
  28. return ((long long)-1);
  29. offset = (16L * 2048L);
  30. for (;1;) {
  31. if (read(isofd, buf, 2048) <=0)
  32. return ((long long)-1);
  33. if (buf[0] == 1)
  34. /* found primary volume descriptor */
  35. break;
  36. else if (buf[0] == 255)
  37. /* hit end and didn't find primary volume descriptor */
  38. return ((long long)-1);
  39. offset += 2048L;
  40. }
  41. /* read out md5sum */
  42. memcpy(buf2, buf + APPDATA_OFFSET, 512);
  43. buf2[511] = '\0';
  44. md5fnd = 0;
  45. skipfnd = 0;
  46. supportedfnd = 0;
  47. loc = 0;
  48. while (loc < 512) {
  49. if (!strncmp((char *)buf2 + loc, "ISO MD5SUM = ", 13)) {
  50. /* make sure we dont walk off end */
  51. if ((loc + 32) > 511)
  52. return -1;
  53. memcpy(mediasum, buf2 + loc + 13, 32);
  54. mediasum[32] = '\0';
  55. md5fnd = 1;
  56. loc += 45;
  57. for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++);
  58. } else if (!strncmp((char *)buf2 + loc, "SKIPSECTORS = ", 14)) {
  59. char *errptr;
  60. /* make sure we dont walk off end */
  61. if ((loc + 14) > 511)
  62. return -1;
  63. loc = loc + 14;
  64. for (p=tmpbuf; buf2[loc] != ';' && loc < 512; p++, loc++)
  65. *p = buf2[loc];
  66. *p = '\0';
  67. *skipsectors = strtol((char *)tmpbuf, &errptr, 10);
  68. if (errptr && *errptr) {
  69. return -1;
  70. } else {
  71. skipfnd = 1;
  72. }
  73. for (p=buf2+loc; *p != ';' && loc < 512; p++, loc++);
  74. } else if (!strncmp((char *)buf2 + loc, "RHLISOSTATUS=1", 14)) {
  75. *supported = 1;
  76. supportedfnd = 1;
  77. } else if (!strncmp((char *)buf2 + loc, "RHLISOSTATUS=0", 14)) {
  78. *supported = 0;
  79. supportedfnd = 1;
  80. } else {
  81. loc++;
  82. }
  83. if ((skipfnd & md5fnd) & supportedfnd)
  84. break;
  85. }
  86. if (!(skipfnd & md5fnd))
  87. return -1;
  88. /* get isosize */
  89. *isosize = (buf[SIZE_OFFSET]*0x1000000+buf[SIZE_OFFSET+1]*0x10000 +
  90. buf[SIZE_OFFSET+2]*0x100 + buf[SIZE_OFFSET+3]) * 2048LL;
  91. return offset;
  92. }
  93. /* returns -1 if no checksum encoded in media, 0 if no match, 1 if match */
  94. /* mediasum is the sum encoded in media, computedsum is one we compute */
  95. /* both strings must be pre-allocated at least 33 chars in length */
  96. static int checkmd5sum(int isofd, char *mediasum, char *computedsum, int quiet) {
  97. int nread;
  98. int i;
  99. int appdata_start_offset, appdata_end_offset;
  100. int nattempt;
  101. int skipsectors;
  102. int supported;
  103. unsigned int bufsize = 32768;
  104. unsigned char md5sum[16];
  105. unsigned int len;
  106. unsigned char *buf;
  107. long long isosize, offset, pvd_offset, apoff;
  108. MD5_CTX md5ctx;
  109. if ((pvd_offset = parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported)) < 0)
  110. return -1;
  111. /* printf("Mediasum = %s\n",mediasum); */
  112. /* rewind, compute md5sum */
  113. lseek(isofd, 0L, SEEK_SET);
  114. MD5_Init(&md5ctx);
  115. offset = 0;
  116. apoff = pvd_offset + APPDATA_OFFSET;
  117. buf = malloc(bufsize * sizeof(unsigned char));
  118. if (!quiet) {
  119. printf("Percent complete: %05.1f%%", (100.0*offset)/(isosize-skipsectors*2048.0));
  120. fflush(stdout);
  121. }
  122. while (offset < isosize - skipsectors*2048) {
  123. nattempt = MIN(isosize - skipsectors*2048 - offset, bufsize);
  124. /* printf("%lld %lld %lld %d\n", offset, isosize, isosize-SKIPSECTORS*2048, nattempt); */
  125. nread = read(isofd, buf, nattempt);
  126. if (nread <= 0)
  127. break;
  128. /* overwrite md5sum we implanted with original data */
  129. if (offset < apoff && offset+nread >= apoff) {
  130. appdata_start_offset = apoff - offset;
  131. appdata_end_offset = MIN(appdata_start_offset+MIN(nread, 512),
  132. offset + nread - apoff);
  133. len = appdata_end_offset - appdata_start_offset;
  134. memset(buf+appdata_start_offset, ' ', len);
  135. } else if (offset >= apoff && offset+nread < apoff + 512) {
  136. appdata_start_offset = 0;
  137. appdata_end_offset = nread;
  138. len = appdata_end_offset - appdata_start_offset;
  139. memset(buf+appdata_start_offset, ' ', len);
  140. } else if (offset < apoff + 512 && offset+nread >= apoff + 512) {
  141. appdata_start_offset = 0;
  142. appdata_end_offset = apoff + 512 - offset;
  143. len = appdata_end_offset - appdata_start_offset;
  144. memset(buf+appdata_start_offset, ' ', len);
  145. }
  146. MD5_Update(&md5ctx, buf, nread);
  147. offset = offset + nread;
  148. /* XXX: print only once every few 100ms, in order not to overload a serial console. -stefanp */
  149. if (!quiet) {
  150. printf("\b\b\b\b\b\b%05.1f%%", (100.0*offset)/(isosize-skipsectors*2048.0));
  151. fflush(stdout);
  152. }
  153. }
  154. if (!quiet) {
  155. printf("\b\b\b\b\b\b%05.1f%%\n", (100.0*offset)/(isosize-skipsectors*2048.0));
  156. }
  157. sleep(1);
  158. free(buf);
  159. MD5_Final(md5sum, &md5ctx);
  160. *computedsum = '\0';
  161. for (i=0; i<16; i++) {
  162. char tmpstr[4];
  163. snprintf (tmpstr, 4, "%02x", md5sum[i]);
  164. strcat(computedsum, tmpstr);
  165. }
  166. /* printf("mediasum, computedsum = %s %s\n", mediasum, computedsum); */
  167. if (strcmp(mediasum, computedsum))
  168. return 0;
  169. else
  170. return 1;
  171. }
  172. #if 0
  173. static void readCB(void *co, long long pos) {
  174. struct progressCBdata *data = co;
  175. static int tick = 0;
  176. char tickmark[2] = "-";
  177. char * ticks = "-\\|/";
  178. newtScaleSet(data->scale, pos);
  179. tick++;
  180. if (tick > 399) tick = 0;
  181. *tickmark = ticks[tick / 100];
  182. newtLabelSetText(data->label, tickmark);
  183. newtRefresh();
  184. }
  185. #endif
  186. static int doMediaCheck(int isofd, char *mediasum, char *computedsum, long long *isosize, int *supported, int quiet) {
  187. int rc;
  188. int skipsectors;
  189. if (parsepvd(isofd, mediasum, &skipsectors, isosize, supported) < 0) {
  190. fprintf(stderr, "Unable to read the disc checksum from the "
  191. "primary volume descriptor.\nThis probably "
  192. "means the disc was created without adding the "
  193. "checksum.\n");
  194. return -1;
  195. }
  196. rc = checkmd5sum(isofd, mediasum, computedsum, quiet);
  197. return rc;
  198. }
  199. int mediaCheckFile(char *file, int quiet) {
  200. int isofd;
  201. int rc;
  202. char *result;
  203. unsigned char mediasum[33], computedsum[33];
  204. long long isosize;
  205. int supported;
  206. isofd = open(file, O_RDONLY);
  207. if (isofd < 0) {
  208. fprintf(stderr, "Unable to find install image %s\n", file);
  209. return -1;
  210. }
  211. rc = doMediaCheck(isofd, (char *)mediasum, (char *)computedsum, &isosize, &supported, quiet);
  212. close(isofd);
  213. /* printf("isosize = %lld\n", isosize);
  214. printf("%s\n%s\n", mediasum, computedsum);*/
  215. /* if (!quiet)
  216. fprintf(stderr, "The supported flag value is %d\n", supported);*/
  217. if (rc == 0)
  218. result = "FAIL.\n\nIt is not recommended to use this media.";
  219. else if (rc > 0)
  220. result = "PASS.\n\nIt is OK to install from this media.";
  221. else
  222. result = "NA.\n\nNo checksum information available, unable to verify media.";
  223. if (!quiet)
  224. fprintf(stderr, "The media check is complete, the "
  225. "result is: %s\n", result);
  226. return rc;
  227. }
  228. void printMD5SUM(char *file) {
  229. int isofd;
  230. char mediasum[64];
  231. long long isosize;
  232. int supported;
  233. int skipsectors;
  234. isofd = open(file, O_RDONLY);
  235. if (isofd < 0) {
  236. fprintf(stderr, "%s: Unable to find install image.\n", file);
  237. exit(1);
  238. }
  239. if (parsepvd(isofd, mediasum, &skipsectors, &isosize, &supported) < 0) {
  240. fprintf(stderr, "%s: Could not get pvd data", file);
  241. fprintf(stderr, "\nUnable to read the disc checksum from the "
  242. "primary volume descriptor.\nThis probably "
  243. "means the disc was created without adding the "
  244. "checksum.");
  245. exit(1);
  246. }
  247. close(isofd);
  248. printf("%s: %s\n", file, mediasum);
  249. }