cmp.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* cmp.c - Compare two files.
  2. *
  3. * Copyright 2012 Timothy Elliott <tle@holymonkey.com>
  4. *
  5. * See http://opengroup.org/onlinepubs/9699919799/utilities/cmp.html
  6. USE_CMP(NEWTOY(cmp, "<1>4ls(silent)(quiet)n#<1[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
  7. config CMP
  8. bool "cmp"
  9. default y
  10. help
  11. usage: cmp [-ls] [-n LEN] FILE1 [FILE2 [SKIP1 [SKIP2]]]
  12. Compare the contents of files (vs stdin if only one given), optionally
  13. skipping bytes at start.
  14. -l Show all differing bytes
  15. -n LEN Compare at most LEN bytes
  16. -s Silent
  17. */
  18. #define FOR_cmp
  19. #include "toys.h"
  20. GLOBALS(
  21. long n;
  22. int fd;
  23. char *name;
  24. )
  25. // We hijack loopfiles() to open and understand the "-" filename for us.
  26. static void do_cmp(int fd, char *name)
  27. {
  28. int i, len1, len2, min_len, size = sizeof(toybuf)/2;
  29. long byte_no = 1, line_no = 1;
  30. char *buf2 = toybuf+size;
  31. if (toys.optc>(i = 2+!!TT.fd) && lskip(fd, atolx(toys.optargs[i])))
  32. error_exit("EOF on %s", name);
  33. // First time through, cache the data and return.
  34. if (!TT.fd) {
  35. TT.name = name;
  36. // On return the old filehandle is closed, and this assures that even
  37. // if we were called with stdin closed, the new filehandle != 0.
  38. TT.fd = dup(fd);
  39. return;
  40. }
  41. toys.exitval = 0;
  42. for (;!FLAG(n) || TT.n;) {
  43. if (FLAG(n)) TT.n -= size = minof(size, TT.n);
  44. len1 = readall(TT.fd, toybuf, size);
  45. len2 = readall(fd, buf2, size);
  46. min_len = minof(len1, len2);
  47. for (i=0; i<min_len; i++) {
  48. if (toybuf[i] != buf2[i]) {
  49. toys.exitval = 1;
  50. if (FLAG(l)) printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]);
  51. else {
  52. if (!FLAG(s)) printf("%s %s differ: char %ld, line %ld\n",
  53. TT.name, name, byte_no, line_no);
  54. goto out;
  55. }
  56. }
  57. byte_no++;
  58. if (toybuf[i] == '\n') line_no++;
  59. }
  60. if (len1 != len2) {
  61. if (!FLAG(s)) error_msg("EOF on %s", len1 < len2 ? TT.name : name);
  62. else toys.exitval = 1;
  63. break;
  64. }
  65. if (len1 < 1) break;
  66. }
  67. out:
  68. if (CFG_TOYBOX_FREE) close(TT.fd);
  69. xexit();
  70. }
  71. void cmp_main(void)
  72. {
  73. toys.exitval = 2;
  74. loopfiles_rw(toys.optargs, O_CLOEXEC|(WARN_ONLY*!FLAG(s)), 0, do_cmp);
  75. if (toys.optc == 1) do_cmp(0, "-");
  76. }