C语言仅用系统调用开发patch程序:实现指定字符串替换
Implementing the
patch Program with System Calls Only Got it, let's build this patch program that replaces every occurrence of "allis" in a file with your input string—using nothing but system calls, no standard library functions allowed. Below is a complete, working implementation:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #define SEARCH_STR "allis" #define SEARCH_LEN 5 int main(int argc, char *argv[]) { // Check command line arguments if (argc != 3) { const char *usage = "Usage: ./patch FILENAME REPLACEMENT_STRING\n"; write(STDERR_FILENO, usage, __builtin_strlen(usage)); return 1; } const char *filename = argv[1]; const char *replace_str = argv[2]; int replace_len = __builtin_strlen(replace_str); // Open the file for read/write int fd = open(filename, O_RDWR); if (fd == -1) { const char *err = "Error: Failed to open file\n"; write(STDERR_FILENO, err, __builtin_strlen(err)); return 1; } // Get file size using lseek off_t file_size = lseek(fd, 0, SEEK_END); if (file_size == -1) { const char *err = "Error: Failed to get file size\n"; write(STDERR_FILENO, err, __builtin_strlen(err)); close(fd); return 1; } lseek(fd, 0, SEEK_SET); // Allocate memory using brk (since malloc is standard library) char *buf = (char *)sbrk(0); void *new_brk = sbrk(file_size); if (new_brk == (void *)-1) { const char *err = "Error: Failed to allocate memory\n"; write(STDERR_FILENO, err, __builtin_strlen(err)); close(fd); return 1; } // Read entire file into buffer ssize_t bytes_read = read(fd, buf, file_size); if (bytes_read != file_size) { const char *err = "Error: Failed to read file\n"; write(STDERR_FILENO, err, __builtin_strlen(err)); brk(buf); // Free allocated memory close(fd); return 1; } // Calculate required size for modified buffer int match_count = 0; char *ptr = buf; while (ptr <= buf + file_size - SEARCH_LEN) { int match = 1; for (int i = 0; i < SEARCH_LEN; i++) { if (ptr[i] != SEARCH_STR[i]) { match = 0; break; } } if (match) { match_count++; ptr += SEARCH_LEN; } else { ptr++; } } off_t new_size = file_size + match_count * (replace_len - SEARCH_LEN); void *final_brk = sbrk(new_size - file_size); if (final_brk == (void *)-1) { const char *err = "Error: Failed to allocate memory for modified content\n"; write(STDERR_FILENO, err, __builtin_strlen(err)); brk(buf); close(fd); return 1; } // Perform replacement char *dest = buf; ptr = buf; while (ptr <= buf + file_size - SEARCH_LEN) { int match = 1; for (int i = 0; i < SEARCH_LEN; i++) { if (ptr[i] != SEARCH_STR[i]) { match = 0; break; } } if (match) { // Copy replacement string for (int i = 0; i < replace_len; i++) { dest[i] = replace_str[i]; } dest += replace_len; ptr += SEARCH_LEN; } else { *dest = *ptr; dest++; ptr++; } } // Copy remaining characters (if any) while (ptr < buf + file_size) { *dest = *ptr; dest++; ptr++; } // Truncate file and write modified content if (ftruncate(fd, new_size) == -1) { const char *err = "Error: Failed to truncate file\n"; write(STDERR_FILENO, err, __builtin_strlen(err)); brk(buf); close(fd); return 1; } lseek(fd, 0, SEEK_SET); ssize_t bytes_written = write(fd, buf, new_size); if (bytes_written != new_size) { const char *err = "Error: Failed to write to file\n"; write(STDERR_FILENO, err, __builtin_strlen(err)); brk(buf); close(fd); return 1; } // Cleanup brk(buf); close(fd); return 0; }
Key Details Explained
- Argument Validation: We check if exactly 3 arguments are provided (program name, filename, replacement string). If not, we write a usage message to
STDERR_FILENOsinceprintfis off-limits. - File Handling:
open()opens the file in read-write mode (O_RDWR).lseek()is used to get the file size by moving to the end of the file, then we jump back to the start to read content.ftruncate()adjusts the file size to match our modified content before writing.
- Memory Management: We use
sbrk()andbrk()instead ofmalloc/freeto allocate and release memory—these are system calls, not standard library functions. - Replacement Logic:
- First we count how many times "allis" appears to calculate the size needed for the modified content.
- Then we traverse the buffer, copying non-matching characters directly, and inserting the replacement string whenever we find a match.
- Finally, we write the modified buffer back to the truncated file.
Compilation & Usage
Compile with a C compiler (we use __builtin_strlen which is a GCC built-in to avoid strlen from string.h):
gcc patch.c -o patch
Run it like this:
./patch your_file.txt "your_replacement_string"
内容的提问来源于stack exchange,提问作者Shmuel Niraev
相关产品推荐
相关产品推荐

