You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_FILENO since printf is 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() and brk() instead of malloc/free to allocate and release memory—these are system calls, not standard library functions.
  • Replacement Logic:
    1. First we count how many times "allis" appears to calculate the size needed for the modified content.
    2. Then we traverse the buffer, copying non-matching characters directly, and inserting the replacement string whenever we find a match.
    3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:09:24