logo

live-bootstrap

Mirror of <https://github.com/fosslinux/live-bootstrap>

simple-patch.c (4816B)


  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "M2libc/bootstrappable.h"
  5. /*
  6. SPDX-FileCopyrightText: 2023 Richard Masters <grick23@gmail.com>
  7. SPDX-License-Identifier: MIT
  8. Simple Patch program.
  9. This program is written in a subset of C called M2, which is from the
  10. stage0-posix bootstrap project.
  11. Example usage:
  12. ./simple-patch file_to_patch before_pattern_file after_pattern_file
  13. */
  14. // function prototypes
  15. void read_file_or_die(char *file_name, char **buffer, int *file_size);
  16. void patch_buffer_or_die(char *patch_file_before_buffer, int patch_file_before_size,
  17. char *before_pattern_buffer, int before_pattern_size,
  18. char *after_pattern_buffer, int after_pattern_size,
  19. char *patch_file_after_buffer);
  20. void writestr_fd(int fd, char *str);
  21. int memsame(char *search_buffer, int search_size,
  22. char *pattern_buffer, int pattern_size);
  23. int main(int argc, char **argv) {
  24. char *patch_file_before_buffer;
  25. int patch_file_before_size;
  26. char *before_pattern_buffer;
  27. int before_pattern_size;
  28. char *after_pattern_buffer;
  29. int after_pattern_size;
  30. int patch_file_after_size;
  31. char *patch_file_after_buffer;
  32. int patch_file_fd;
  33. read_file_or_die(argv[1], &patch_file_before_buffer, &patch_file_before_size);
  34. read_file_or_die(argv[2], &before_pattern_buffer, &before_pattern_size);
  35. read_file_or_die(argv[3], &after_pattern_buffer, &after_pattern_size);
  36. patch_file_after_size = patch_file_before_size - before_pattern_size + after_pattern_size;
  37. patch_file_after_buffer = calloc(patch_file_after_size, sizeof(char));
  38. patch_buffer_or_die(patch_file_before_buffer, patch_file_before_size,
  39. before_pattern_buffer, before_pattern_size,
  40. after_pattern_buffer, after_pattern_size,
  41. patch_file_after_buffer);
  42. patch_file_fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0);
  43. write(patch_file_fd, patch_file_after_buffer, patch_file_after_size);
  44. close(patch_file_fd);
  45. return EXIT_SUCCESS;
  46. }
  47. void read_file_or_die(char *file_name, char **buffer, int *file_size) {
  48. int file_fd;
  49. int num_bytes_read;
  50. file_fd = open(file_name, O_RDONLY, 0);
  51. if (file_fd == -1) {
  52. writestr_fd(2, "Could not open file: ");
  53. writestr_fd(2, file_name);
  54. writestr_fd(2, "\n");
  55. exit(1);
  56. }
  57. // determine file size
  58. *file_size = lseek(file_fd, 0, SEEK_END);
  59. // go back to beginning of file
  60. lseek(file_fd, 0, SEEK_SET);
  61. // alloc a buffer to read the entire file
  62. *buffer = calloc(*file_size, sizeof(char));
  63. // read the entire patch file
  64. num_bytes_read = read(file_fd, *buffer, *file_size);
  65. if (num_bytes_read != *file_size) {
  66. writestr_fd(2, "Could not read file: ");
  67. writestr_fd(2, file_name);
  68. writestr_fd(2, "\n");
  69. exit(1);
  70. }
  71. close(file_fd);
  72. }
  73. void patch_buffer_or_die(char *patch_file_before_buffer, int patch_file_before_size,
  74. char *before_pattern_buffer, int before_pattern_size,
  75. char *after_pattern_buffer, int after_pattern_size,
  76. char *patch_file_after_buffer) {
  77. char *pos = patch_file_before_buffer;
  78. int prefix_len = 0;
  79. // look for the pattern at every offset
  80. while (prefix_len < patch_file_before_size) {
  81. // if we find the pattern, replace it and return
  82. if (memsame(pos, patch_file_before_size - prefix_len, before_pattern_buffer, before_pattern_size)) {
  83. memcpy(patch_file_after_buffer, patch_file_before_buffer, prefix_len);
  84. memcpy(patch_file_after_buffer + prefix_len, after_pattern_buffer, after_pattern_size);
  85. memcpy(patch_file_after_buffer + prefix_len + after_pattern_size,
  86. patch_file_before_buffer + prefix_len + before_pattern_size,
  87. patch_file_before_size - (prefix_len + before_pattern_size));
  88. return;
  89. }
  90. pos = pos + 1;
  91. prefix_len = prefix_len + 1;
  92. }
  93. /* if we don't find the pattern, something is wrong, so exit with error */
  94. exit(1);
  95. }
  96. /*
  97. Write the string to the given file descriptor.
  98. */
  99. void writestr_fd(int fd, char *str) {
  100. write(fd, str, strlen(str));
  101. }
  102. /*
  103. Is the pattern located at the start of the search buffer
  104. (and not exceeding the length of the search buffer)?
  105. */
  106. int memsame(char *search_buffer, int search_size,
  107. char *pattern_buffer, int pattern_size) {
  108. int check_offset = 0;
  109. if (pattern_size > search_size) {
  110. return FALSE;
  111. }
  112. while (check_offset < pattern_size) {
  113. if (search_buffer[check_offset] != pattern_buffer[check_offset]) {
  114. return FALSE;
  115. }
  116. check_offset = check_offset + 1;
  117. }
  118. return TRUE;
  119. }