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.

205 lines
4.9 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 <fcntl.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include "md5.h"
  11. #include "libimplantisomd5.h"
  12. #define APPDATA_OFFSET 883
  13. #define SIZE_OFFSET 84
  14. /* number of sectors to ignore at end of iso when computing sum */
  15. #define SKIPSECTORS 15
  16. #define MAX(x, y) ((x > y) ? x : y)
  17. #define MIN(x, y) ((x < y) ? x : y)
  18. /* finds primary volume descriptor and returns info from it */
  19. /* mediasum must be a preallocated buffer at least 33 bytes long */
  20. static int parsepvd(int isofd, char *mediasum, long long *isosize) {
  21. unsigned char buf[2048];
  22. long long offset;
  23. unsigned char *p __attribute__((unused));
  24. if (lseek(isofd, 16*2048, SEEK_SET) == -1)
  25. return ((long long)-1);
  26. offset = (16 * 2048);
  27. for (;1;) {
  28. if (read(isofd, buf, 2048L) == -1)
  29. return ((long long)-1);
  30. if (buf[0] == 1)
  31. /* found primary volume descriptor */
  32. break;
  33. else if (buf[0] == 255)
  34. /* hit end and didn't find primary volume descriptor */
  35. return ((long long)-1);
  36. offset += 2048L;
  37. }
  38. /* read out md5sum */
  39. #if 0
  40. memcpy(mediasum, buf + APPDATA_OFFSET + 13, 32);
  41. mediasum[32] = '\0';
  42. for (p=mediasum; *p; p++)
  43. if (*p != ' ')
  44. break;
  45. /* if the md5sum was all spaces, we didn't find md5sum */
  46. if (!*p)
  47. return -1;
  48. #endif
  49. /* get isosize */
  50. *isosize = (buf[SIZE_OFFSET]*0x1000000+buf[SIZE_OFFSET+1]*0x10000 +
  51. buf[SIZE_OFFSET+2]*0x100 + buf[SIZE_OFFSET+3]) * 2048LL;
  52. return offset;
  53. }
  54. static unsigned int writeAppData(unsigned char *appdata, char *valstr, unsigned int loc) {
  55. if (loc + strlen(valstr) > 511) {
  56. printf("Attempted to write too much appdata, exiting...\n");
  57. exit(-1);
  58. }
  59. memcpy(appdata + loc, valstr, strlen(valstr));
  60. return loc+strlen(valstr);
  61. }
  62. int implantISOFile(char *fname, int supported, int forceit, int quiet, char **errstr) {
  63. int i;
  64. int isofd;
  65. int nread;
  66. int dirty;
  67. int pvd_offset;
  68. long long isosize, total;
  69. unsigned char md5sum[16];
  70. unsigned int loc;
  71. unsigned char buf[2048];
  72. unsigned char orig_appdata[512];
  73. unsigned char new_appdata[512];
  74. unsigned char mediasum[33];
  75. char md5str[40];
  76. MD5_CTX md5ctx;
  77. isofd = open(fname, O_RDWR);
  78. if (isofd < 0) {
  79. *errstr = "Error - Unable to open file %s\n\n";
  80. return -1;
  81. }
  82. pvd_offset = parsepvd(isofd, mediasum, &isosize);
  83. if (pvd_offset < 0) {
  84. *errstr = "Could not find primary volumne!\n\n";
  85. return -1;
  86. }
  87. lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
  88. nread = read(isofd, orig_appdata, 512);
  89. if (!forceit) {
  90. dirty = 0;
  91. for (i=0; i < 512; i++)
  92. if (orig_appdata[i] != ' ')
  93. dirty = 1;
  94. if (dirty) {
  95. *errstr = "Application data has been used - not implanting md5sum!\n";
  96. return -1;
  97. }
  98. } else {
  99. /* write out blanks to erase old app data */
  100. lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
  101. memset(new_appdata, ' ', 512);
  102. i = write(isofd, new_appdata, 512);
  103. if (i<0) {
  104. printf("write failed %d\n", i);
  105. perror("");
  106. }
  107. }
  108. /* now do md5sum */
  109. lseek(isofd, 0L, SEEK_SET);
  110. MD5_Init(&md5ctx);
  111. total = 0;
  112. /* read up to 15 sectors from end, due to problems reading last few */
  113. /* sectors on burned CDs */
  114. while (total < isosize - SKIPSECTORS*2048) {
  115. nread = read(isofd, buf, 2048);
  116. if (nread <= 0)
  117. break;
  118. MD5_Update(&md5ctx, buf, nread);
  119. total = total + nread;
  120. }
  121. MD5_Final(md5sum, &md5ctx);
  122. *md5str = '\0';
  123. for (i=0; i<16; i++) {
  124. char tmpstr[4];
  125. snprintf (tmpstr, 4, "%02x", md5sum[i]);
  126. strcat(md5str, tmpstr);
  127. }
  128. if (!quiet) {
  129. printf("Inserting md5sum into iso image...\n");
  130. printf("md5 = %s\n", md5str);
  131. }
  132. /* memcpy(new_appdata, orig_appdata, 512); */
  133. memset(new_appdata, ' ', 512);
  134. loc = 0;
  135. loc = writeAppData(new_appdata, "ISO MD5SUM = ", loc);
  136. loc = writeAppData(new_appdata, md5str, loc);
  137. loc = writeAppData(new_appdata, ";", loc);
  138. snprintf(buf, sizeof(buf), "SKIPSECTORS = %d", SKIPSECTORS);
  139. loc = writeAppData(new_appdata, buf, loc);
  140. loc = writeAppData(new_appdata, ";", loc);
  141. if (supported) {
  142. if (!quiet)
  143. printf("Setting supported flag to 1\n");
  144. loc = writeAppData(new_appdata, "RHLISOSTATUS=1", loc);
  145. } else {
  146. if (!quiet)
  147. printf("Setting supported flag to 0\n");
  148. loc = writeAppData(new_appdata, "RHLISOSTATUS=0", loc);
  149. }
  150. loc = writeAppData(new_appdata, ";", loc);
  151. loc = writeAppData(new_appdata, "THIS IS NOT THE SAME AS RUNNING MD5SUM ON THIS ISO!!", loc);
  152. i = lseek(isofd, pvd_offset + APPDATA_OFFSET, SEEK_SET);
  153. if (i<0)
  154. printf("seek failed\n");
  155. i = write(isofd, new_appdata, 512);
  156. if (i<0) {
  157. printf("write failed %d\n", i);
  158. perror("");
  159. }
  160. close(isofd);
  161. errstr = NULL;
  162. return 0;
  163. }