#include #include /* for ftruncate */ #include #include size_t str_length(char *s) { size_t n = 0; while (*s++ != '\0') { n++; } return n; } int str_equal(char *a, char *b) { do { if (*a++ != *b++) { return 0; } } while (*b != '\0'); return 1; } long find_in_file(FILE *f, char *needle) { size_t nlen = str_length(needle); long pos = 0; char *str = malloc(nlen + 1); while (!feof(f) || !ferror(f)) { if (fread(str, 1, nlen, f) != nlen) { break; } str[nlen] = '\0'; //printf("%ld: %s\n", ftell(f), str); if (str_equal(str, needle)) { return pos; } fseek(f, ++pos, SEEK_SET); } free(str); return -1; } void move_char(FILE *f, long src, long dst) { int c; fseek(f, src, SEEK_SET); c = fgetc(f); fseek(f, dst, SEEK_SET); fputc(c, f); } void file_move_contents(FILE *f, long from, long to, long end) { int c; long p, q; if (from < to) { // in case of moving to the right side, // we start from right end and move backwards to the start for (p = end, q = end + to - from; p >= from; p--, q--) { move_char(f, p, q); } } else { // otherwise, we start from the left and move towards // the right for (p = from, q = to; p <= end; p++, q++) { move_char(f, p, q); } } } int main(int argc, char **argv) { FILE *f; int fd; long pos; long olen, nlen, end; if (argc < 4) { printf("Usage: %s [file] [needle] [replacement]\n", argv[0]); printf("Replaces needle in the contents of file with replacement.\n\n"); return 2; } if (argv[2][0] == '\0') { printf("%s: Invalid needle: needle can not be empty.\n", argv[0]); return 3; } f = fopen(argv[1], "r+"); if (f == NULL) { printf("%s: Error: Can not open file `%s` for reading.\n", argv[0], argv[1]); return 1; } pos = find_in_file(f, argv[2]); if (pos == -1) { printf("The string \"%s\" is not found in file `%s`\n", argv[2], argv[1]); } else { printf("The string \"%s\" is found in file `%s` at position %ld\n", argv[2], argv[1], pos); fseek(f, 0L, SEEK_END); end = ftell(f); olen = str_length(argv[2]); nlen = str_length(argv[3]); file_move_contents(f, pos + olen, pos + nlen, end - 1); // write down the replacement in the right place fseek(f, pos, SEEK_SET); fwrite(argv[3], 1, nlen, f); fseek(f, 0L, SEEK_END); end = ftell(f); // truncate the file to the right size fd = fileno(f); ftruncate(fd, end + nlen - olen); } fclose(f); return 0; }