aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2024-03-26 16:43:03 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2024-04-02 18:55:46 -0400
commit9910a30f0c26b3180d46418abad760f86a253aa2 (patch)
tree6c5209b5decbdc4206a90dfb3120ebbe88525d65 /src
parent232763cb702e5b39ec5a051ec41582e42adaef59 (diff)
downloadstasis-9910a30f0c26b3180d46418abad760f86a253aa2.tar.gz
Fix replace_text*() functions
* Now return an error code * Completely rewrote replace_text()
Diffstat (limited to 'src')
-rw-r--r--src/relocation.c106
1 files changed, 76 insertions, 30 deletions
diff --git a/src/relocation.c b/src/relocation.c
index b92af2b..8b18efd 100644
--- a/src/relocation.c
+++ b/src/relocation.c
@@ -10,7 +10,10 @@
* ~~~{.c}
* char *str = (char *)calloc(100, sizeof(char));
* strcpy(str, "This are a test.");
- * replace_text(str, "are", "is");
+ * if (replace_text(str, "are", "is")) {
+ * fprintf(stderr, "string replacement failed\n");
+ * exit(1);
+ * }
* // str is: "This is a test."
* free(str);
* ~~~
@@ -18,64 +21,106 @@
* @param original string to modify
* @param target string value to replace
* @param replacement string value
+ * @return 0 on success, -1 on error
*/
-void replace_text(char *original, const char *target, const char *replacement) {
+int replace_text(char *original, const char *target, const char *replacement) {
char buffer[OMC_BUFSIZ];
- char *tmp = original;
+ char *pos = original;
+ char *match = NULL;
+ size_t original_len = strlen(original);
+ size_t target_len = strlen(target);
+ size_t rep_len = strlen(replacement);
+ size_t buffer_len = 0;
+
+ if (original_len > sizeof(buffer)) {
+ errno = EINVAL;
+ SYSERROR("The original string is larger than buffer: %zu > %zu\n", original_len, sizeof(buffer));
+ return -1;
+ }
memset(buffer, 0, sizeof(buffer));
- while (*tmp != '\0') {
- if (!strncmp(tmp, target, strlen(target))) {
- size_t replen;
- char *stop_at = strchr(tmp, '\n');
- if (stop_at) {
- replen = (stop_at - tmp);
- } else {
- replen = strlen(replacement);
+ if ((match = strstr(pos, target))) {
+ while (*pos != '\0') {
+ // append to buffer the bytes leading up to the match
+ strncat(buffer, pos, match - pos);
+ // position in the string jump ahead to the beginning of the match
+ pos = match;
+
+ // replacement is shorter than the target
+ if (rep_len < target_len) {
+ // shrink the string
+ strcat(buffer, replacement);
+ memmove(pos, pos + target_len, strlen(pos) - target_len);
+ memset(pos + (strlen(pos) - target_len), 0, target_len);
+ } else { // replacement is longer than the target
+ // write the replacement value to the buffer
+ strcat(buffer, replacement);
+ // target consumed. jump to the end of the substring.
+ pos += target_len;
+ }
+ // find more matches
+ if (!(match = strstr(pos, target))) {
+ // no more matches
+ // append whatever remains to the buffer
+ strcat(buffer, pos);
+ // stop
+ break;
}
- strcat(buffer, replacement);
- strcat(buffer, "\n");
- tmp += replen;
- } else {
- strncat(buffer, tmp, 1);
}
- tmp++;
}
+
+ buffer_len = strlen(buffer);
+ if (buffer_len < original_len) {
+ // truncate whatever remains of the original buffer
+ memset(original + buffer_len, 0, original_len - buffer_len);
+ }
+ // replace original with contents of buffer
strcpy(original, buffer);
+ return 0;
}
/**
* Replace `target` with `replacement` in `filename`
*
* ~~~{.c}
- * file_replace_text("/path/to/file.txt, "are", "is");
+ * if (file_replace_text("/path/to/file.txt, "are", "is")) {
+ * fprintf(stderr, "failed to replace strings in file\n");
+ * exit(1);
+ * }
* ~~~
*
* @param filename path to file
* @param target string value to replace
* @param replacement string
+ * @return 0 on success, -1 on error
*/
-void file_replace_text(const char* filename, const char* target, const char* replacement) {
- FILE *fp = fopen(filename, "r");
- if (fp == NULL) {
- fprintf(stderr, "unable to open for reading: %s\n", filename);
- return;
- }
-
+int file_replace_text(const char* filename, const char* target, const char* replacement) {
+ int result;
char buffer[OMC_BUFSIZ];
char tempfilename[] = "tempfileXXXXXX";
- FILE *tfp = fopen(tempfilename, "w");
+ FILE *fp;
+ FILE *tfp;
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "unable to open for reading: %s\n", filename);
+ return -1;
+ }
- if (tfp == NULL) {
- fprintf(stderr, "unable to open temporary fp for writing: %s\n", tempfilename);
+ tfp = fopen(tempfilename, "w");
+ if (!tfp) {
+ SYSERROR("unable to open temporary fp for writing: %s", tempfilename);
fclose(fp);
- return;
+ return -1;
}
// Write modified strings to temporary file
+ result = 0;
while (fgets(buffer, sizeof(buffer), fp)) {
if (strstr(buffer, target)) {
- replace_text(buffer, target, replacement);
+ if (replace_text(buffer, target, replacement)) {
+ result = -1;
+ }
}
fputs(buffer, tfp);
}
@@ -86,4 +131,5 @@ void file_replace_text(const char* filename, const char* target, const char* rep
// Replace original with modified copy
remove(filename);
rename(tempfilename, filename);
+ return result;
} \ No newline at end of file