347 lines
9.6 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <stdarg.h>
  6. #include <errno.h>
  7. #define MAX_LINE 1000
  8. #define MAX_PKGS 100
  9. char *checksum_field=NULL;
  10. static void oom_die(void)
  11. {
  12. fputs("Out of memory!\n", stderr);
  13. exit(1);
  14. }
  15. static char *xvasprintf(const char *fmt, va_list ap) {
  16. char *ret;
  17. if (vasprintf (&ret, fmt, ap) < 0) {
  18. if (errno == ENOMEM)
  19. oom_die();
  20. return NULL;
  21. }
  22. return ret;
  23. }
  24. static char *xasprintf(const char *fmt, ...) {
  25. va_list ap;
  26. char *ret;
  27. va_start(ap, fmt);
  28. ret = xvasprintf(fmt, ap);
  29. va_end(ap);
  30. return ret;
  31. }
  32. static char *fieldcpy(char *dst, char *fld) {
  33. while (*fld && *fld != ':')
  34. fld++;
  35. if (!*(fld++))
  36. return NULL;
  37. while (isspace(*fld)) fld++;
  38. return strcpy(dst, fld);
  39. }
  40. static void outputdeps(char *deps) {
  41. char *pch = deps;
  42. while (1) {
  43. while (isspace(*pch)) pch++;
  44. if (!*pch) break;
  45. while (*pch && *pch != '(' && *pch != '|' && *pch != ','
  46. && !isspace(*pch))
  47. {
  48. fputc(*pch++, stdout);
  49. }
  50. fputc('\n', stdout);
  51. while (*pch && *pch++ != ',') (void)NULL;
  52. }
  53. }
  54. static void dogetdeps(char *pkgsfile, char **in_pkgs, int pkgc) {
  55. char buf[MAX_LINE];
  56. char cur_pkg[MAX_LINE];
  57. char cur_deps[MAX_LINE];
  58. char cur_predeps[MAX_LINE];
  59. char prev_pkg[MAX_LINE];
  60. char *pkgs[MAX_PKGS];
  61. int i;
  62. int skip;
  63. FILE *f;
  64. int output_pkg = -1;
  65. cur_pkg[0] = cur_deps[0] = cur_predeps[0] = prev_pkg[0] = '\0';
  66. for (i = 0; i < pkgc; i++) pkgs[i] = in_pkgs[i];
  67. f = fopen(pkgsfile, "r");
  68. if (f == NULL) {
  69. perror(pkgsfile);
  70. exit(1);
  71. }
  72. skip = 1;
  73. while (fgets(buf, sizeof(buf), f)) {
  74. if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
  75. if (strncasecmp(buf, "Package:", 8) == 0) {
  76. int any = 0;
  77. skip = 1;
  78. fieldcpy(cur_pkg, buf);
  79. if (strcmp(cur_pkg, prev_pkg) != 0) {
  80. if (output_pkg != -1)
  81. pkgs[output_pkg] = NULL;
  82. if (cur_deps[0])
  83. outputdeps(cur_deps);
  84. if (cur_predeps[0])
  85. outputdeps(cur_predeps);
  86. strcpy(prev_pkg, cur_pkg);
  87. }
  88. cur_deps[0] = cur_predeps[0] = '\0';
  89. output_pkg = -1;
  90. for (i = 0; i < pkgc; i++) {
  91. if (!pkgs[i]) continue;
  92. any = 1;
  93. if (strcmp(cur_pkg, pkgs[i]) == 0) {
  94. skip = 0;
  95. output_pkg = i;
  96. break;
  97. }
  98. }
  99. if (!any) break;
  100. } else if (!skip && strncasecmp(buf, "Depends:", 8) == 0)
  101. fieldcpy(cur_deps, buf);
  102. else if (!skip && strncasecmp(buf, "Pre-Depends:", 12) == 0)
  103. fieldcpy(cur_predeps, buf);
  104. }
  105. if (cur_deps[0])
  106. outputdeps(cur_deps);
  107. if (cur_predeps[0])
  108. outputdeps(cur_predeps);
  109. fclose(f);
  110. }
  111. static void dopkgmirrorpkgs(int uniq, char *mirror, char *pkgsfile,
  112. char *fieldname, char **in_pkgs, int pkgc)
  113. {
  114. char buf[MAX_LINE];
  115. char cur_field[MAX_LINE];
  116. char cur_pkg[MAX_LINE];
  117. char cur_ver[MAX_LINE];
  118. char cur_arch[MAX_LINE];
  119. char cur_size[MAX_LINE];
  120. char cur_checksum[MAX_LINE];
  121. char cur_filename[MAX_LINE];
  122. char prev_pkg[MAX_LINE];
  123. char *pkgs[MAX_PKGS];
  124. int i;
  125. FILE *f;
  126. char *output = NULL;
  127. int output_pkg = -1;
  128. cur_field[0] = cur_pkg[0] = cur_ver[0] = cur_arch[0] = cur_filename[0] = prev_pkg[0] = '\0';
  129. for (i = 0; i < pkgc; i++) pkgs[i] = in_pkgs[i];
  130. f = fopen(pkgsfile, "r");
  131. if (f == NULL) {
  132. perror(pkgsfile);
  133. exit(1);
  134. }
  135. while (fgets(buf, sizeof(buf), f)) {
  136. if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
  137. if (strncasecmp(buf, fieldname, strlen(fieldname)) == 0) {
  138. fieldcpy(cur_field, buf);
  139. }
  140. if (strncasecmp(buf, "Package:", 8) == 0) {
  141. fieldcpy(cur_pkg, buf);
  142. if (strcmp(cur_pkg, prev_pkg) != 0) {
  143. if (output)
  144. fputs(output, stdout);
  145. if (uniq && output_pkg != -1)
  146. pkgs[output_pkg] = NULL;
  147. strcpy(prev_pkg, cur_pkg);
  148. }
  149. free(output);
  150. output = NULL;
  151. output_pkg = -1;
  152. } else if (strncasecmp(buf, "Version:", 8) == 0) {
  153. fieldcpy(cur_ver, buf);
  154. } else if (strncasecmp(buf, "Architecture:", 13) == 0) {
  155. fieldcpy(cur_arch, buf);
  156. } else if (strncasecmp(buf, "Size:", 5) == 0) {
  157. fieldcpy(cur_size, buf);
  158. } else if (strncasecmp(buf, checksum_field, strlen(checksum_field)) == 0
  159. && buf[strlen(checksum_field)] == ':') {
  160. fieldcpy(cur_checksum, buf);
  161. } else if (strncasecmp(buf, "Filename:", 9) == 0) {
  162. fieldcpy(cur_filename, buf);
  163. } else if (!*buf) {
  164. int any = 0;
  165. for (i = 0; i < pkgc; i++) {
  166. if (!pkgs[i]) continue;
  167. any = 1;
  168. if (strcmp(cur_field, pkgs[i]) == 0) {
  169. free(output);
  170. output = xasprintf("%s %s %s %s %s %s %s\n", cur_pkg, cur_ver, cur_arch, mirror, cur_filename, cur_checksum, cur_size);
  171. output_pkg = i;
  172. break;
  173. }
  174. }
  175. if (!any) break;
  176. cur_field[0] = '\0';
  177. }
  178. }
  179. if (output)
  180. fputs(output, stdout);
  181. if (uniq && output_pkg != -1)
  182. pkgs[output_pkg] = NULL;
  183. fclose(f);
  184. /* any that weren't found are returned as "pkg -" */
  185. if (uniq) {
  186. for (i = 0; i < pkgc; i++) {
  187. if (pkgs[i]) {
  188. printf("%s -\n", pkgs[i]);
  189. }
  190. }
  191. }
  192. }
  193. static void dopkgstanzas(char *pkgsfile, char **pkgs, int pkgc)
  194. {
  195. char buf[MAX_LINE];
  196. char *accum;
  197. size_t accum_size = 0, accum_alloc = MAX_LINE * 2;
  198. char cur_pkg[MAX_LINE];
  199. FILE *f;
  200. accum = malloc(accum_alloc);
  201. if (!accum)
  202. oom_die();
  203. f = fopen(pkgsfile, "r");
  204. if (f == NULL) {
  205. perror(pkgsfile);
  206. free(accum);
  207. exit(1);
  208. }
  209. while (fgets(buf, sizeof(buf), f)) {
  210. if (*buf) {
  211. size_t len = strlen(buf);
  212. if (accum_size + len + 1 > accum_alloc) {
  213. accum_alloc = (accum_size + len + 1) * 2;
  214. accum = realloc(accum, accum_alloc);
  215. if (!accum)
  216. oom_die();
  217. }
  218. strcpy(accum + accum_size, buf);
  219. accum_size += len;
  220. }
  221. if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
  222. if (strncasecmp(buf, "Package:", 8) == 0) {
  223. fieldcpy(cur_pkg, buf);
  224. } else if (!*buf) {
  225. int i;
  226. for (i = 0; i < pkgc; i++) {
  227. if (!pkgs[i]) continue;
  228. if (strcmp(cur_pkg, pkgs[i]) == 0) {
  229. fputs(accum, stdout);
  230. if (accum[accum_size - 1] != '\n')
  231. fputs("\n\n", stdout);
  232. else if (accum[accum_size - 2] != '\n')
  233. fputc('\n', stdout);
  234. break;
  235. }
  236. }
  237. *accum = '\0';
  238. accum_size = 0;
  239. }
  240. }
  241. fclose(f);
  242. free(accum);
  243. }
  244. static int dotranslatewgetpercent(int low, int high, int end, char *str) {
  245. int ch;
  246. int val, lastval;
  247. /* print out anything that looks like a % on its own line, appropriately
  248. * scaled */
  249. lastval = val = 0;
  250. while ( (ch = getchar()) != EOF ) {
  251. if (isdigit(ch)) {
  252. val *= 10; val += ch - '0';
  253. } else if (ch == '%') {
  254. float f = (float) val / 100.0 * (high - low) + low;
  255. if (str) {
  256. printf("P: %d %d %s\n", (int) f, end, str);
  257. } else {
  258. printf("P: %d %d\n", (int) f, end);
  259. }
  260. lastval = val;
  261. } else {
  262. val = 0;
  263. }
  264. }
  265. return lastval == 100;
  266. }
  267. int main(int argc, char *argv[]) {
  268. checksum_field=getenv("DEBOOTSTRAP_CHECKSUM_FIELD");
  269. if (checksum_field == NULL) {
  270. checksum_field="MD5sum";
  271. }
  272. if ((argc == 6 || argc == 5) && strcmp(argv[1], "WGET%") == 0) {
  273. if (dotranslatewgetpercent(atoi(argv[2]), atoi(argv[3]),
  274. atoi(argv[4]), argc == 6 ? argv[5] : NULL))
  275. {
  276. exit(0);
  277. } else {
  278. exit(1);
  279. }
  280. } else if (argc >= 4 && strcmp(argv[1], "GETDEPS") == 0) {
  281. int i;
  282. for (i = 3; argc - i > MAX_PKGS; i += MAX_PKGS) {
  283. dogetdeps(argv[2], argv+i, MAX_PKGS);
  284. }
  285. dogetdeps(argv[2], argv+i, argc-i);
  286. exit(0);
  287. } else if (argc >= 5 && strcmp(argv[1], "PKGS") == 0) {
  288. int i;
  289. for (i = 4; argc - i > MAX_PKGS; i += MAX_PKGS) {
  290. dopkgmirrorpkgs(1, argv[2], argv[3], "Package:", argv+i, MAX_PKGS);
  291. }
  292. dopkgmirrorpkgs(1, argv[2], argv[3], "Package:", argv+i, argc-i);
  293. exit(0);
  294. } else if (argc >= 6 && strcmp(argv[1], "FIELD") == 0) {
  295. int i;
  296. for (i = 5; argc - i > MAX_PKGS; i += MAX_PKGS) {
  297. dopkgmirrorpkgs(0, argv[3], argv[4], argv[2], argv+i, MAX_PKGS);
  298. }
  299. dopkgmirrorpkgs(0, argv[3], argv[4], argv[2], argv+i, argc-i);
  300. exit(0);
  301. } else if (argc >= 4 && strcmp(argv[1], "STANZAS") == 0) {
  302. int i;
  303. for (i = 3; argc - i > MAX_PKGS; i += MAX_PKGS) {
  304. dopkgstanzas(argv[2], argv+i, MAX_PKGS);
  305. }
  306. dopkgstanzas(argv[2], argv+i, argc-i);
  307. exit(0);
  308. } else {
  309. fprintf(stderr, "usage: %s PKGS mirror packagesfile pkgs..\n", argv[0]);
  310. fprintf(stderr, " or: %s FIELD field mirror packagesfile pkgs..\n",
  311. argv[0]);
  312. fprintf(stderr, " or: %s GETDEPS packagesfile pkgs..\n", argv[0]);
  313. fprintf(stderr, " or: %s STANZAS packagesfile pkgs..\n", argv[0]);
  314. fprintf(stderr, " or: %s WGET%% low high end reason\n", argv[0]);
  315. exit(1);
  316. }
  317. }