From e0d0c21c5339ba09872f6561110c630e1a8cb25c Mon Sep 17 00:00:00 2001 From: pajjilykk Date: Wed, 15 Oct 2025 16:58:23 +0700 Subject: [PATCH] seems like working lab2 --- lab_2/Makefile | 27 ++++++++++++++ lab_2/task12.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ lab_2/textlib.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 lab_2/Makefile create mode 100644 lab_2/task12.c create mode 100644 lab_2/textlib.c diff --git a/lab_2/Makefile b/lab_2/Makefile new file mode 100644 index 0000000..d2e096a --- /dev/null +++ b/lab_2/Makefile @@ -0,0 +1,27 @@ +# Makefile +CC = gcc +CFLAGS = -Wall -Wextra -std=c99 +LDFLAGS = -ldl + +# Цель по умолчанию +all: task12 libtextlib.so + +# Основная программа +task12: task12.c + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) + +# Динамическая библиотека +libtextlib.so: textlib.c + $(CC) $(CFLAGS) -fPIC -shared -o $@ $< + +# Очистка +clean: + rm -f task12 libtextlib.so input.txt output.txt + +# Тест +test: all + echo -e "Hello world\ntest line\nanother" > input.txt + ./task12 input.txt output.txt 5 ./libtextlib.so + cat output.txt + +.PHONY: all clean test diff --git a/lab_2/task12.c b/lab_2/task12.c new file mode 100644 index 0000000..6c51f75 --- /dev/null +++ b/lab_2/task12.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define RBUFSZ 4096 +#define WBUFSZ 4096 + +static void die_perror(const char *what, const char *path, int exit_code) { + int saved = errno; + char msg[512]; + if (path) { + snprintf(msg, sizeof(msg), "%s: %s: %s\n", what, path, strerror(saved)); + } else { + snprintf(msg, sizeof(msg), "%s: %s\n", what, strerror(saved)); + } + (void) write(STDERR_FILENO, msg, strlen(msg)); + _exit(exit_code); +} + +static long long parse_ll(const char *s) { + char *end = NULL; + errno = 0; + long long v = strtoll(s, &end, 10); + if (errno != 0 || end == s || *end != '\0' || v < 0) { + errno = EINVAL; + return -1; + } + return v; +} + +int main(int argc, char *argv[]) { + if (argc != 5) { + const char *usage = + "Usage: lab2_var12 \n" + "Variant 12: Load text processing library dynamically and process file.\n" + "Library should provide 'process_text' function.\n"; + (void) write(STDERR_FILENO, usage, strlen(usage)); + return -1; + } + + const char *in_path = argv[1]; + const char *out_path = argv[2]; + long long cap = parse_ll(argv[3]); + const char *lib_path = argv[4]; + + if (cap < 0) { + die_perror("invalid max_replacements", argv[3], -1); + } + + // Динамически загружаем библиотеку + void *lib_handle = dlopen(lib_path, RTLD_LAZY); + if (!lib_handle) { + const char *error_msg = dlerror(); + char msg[512]; + snprintf(msg, sizeof(msg), "dlopen failed: %s\n", error_msg ? error_msg : "unknown error"); + (void) write(STDERR_FILENO, msg, strlen(msg)); + return -1; + } + + // Получаем указатель на функцию обработки текста + long long (*process_text)(const char*, const char*, long long) = + (long long (*)(const char*, const char*, long long)) dlsym(lib_handle, "process_text"); + + if (!process_text) { + const char *error_msg = dlerror(); + char msg[512]; + snprintf(msg, sizeof(msg), "dlsym failed: %s\n", error_msg ? error_msg : "unknown error"); + (void) write(STDERR_FILENO, msg, strlen(msg)); + dlclose(lib_handle); + return -1; + } + + // Вызываем функцию из библиотеки + long long result = process_text(in_path, out_path, cap); + + if (result < 0) { + die_perror("process_text failed", NULL, -1); + } + + // Закрываем библиотеку + dlclose(lib_handle); + + // Выводим результат + char res[64]; + int m = snprintf(res, sizeof(res), "%lld\n", result); + if (m > 0) { + (void) write(STDOUT_FILENO, res, (size_t) m); + } + + return 0; +} diff --git a/lab_2/textlib.c b/lab_2/textlib.c new file mode 100644 index 0000000..5517654 --- /dev/null +++ b/lab_2/textlib.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include + +#define RBUFSZ 4096 +#define WBUFSZ 4096 + +// Функция обработки текста +long long process_text(const char *in_path, const char *out_path, long long cap) { + int in_fd = open(in_path, O_RDONLY); + if (in_fd < 0) { + return -1; + } + + mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + int out_fd = open(out_path, O_CREAT | O_WRONLY | O_TRUNC, filePerms); + if (out_fd < 0) { + close(in_fd); + return -1; + } + + char rbuf[RBUFSZ]; + char wbuf[WBUFSZ]; + size_t wlen = 0; + + long long total_replacements = 0; + int at_line_start = 1; + unsigned char line_key = 0; + int replacing_enabled = 1; + + for (;;) { + ssize_t n = read(in_fd, rbuf, sizeof(rbuf)); + if (n > 0) { + for (ssize_t i = 0; i < n; i++) { + unsigned char c = (unsigned char) rbuf[i]; + + if (at_line_start) { + line_key = c; + at_line_start = 0; + } + + unsigned char outc = c; + if (c == '\n') { + at_line_start = 1; + } else if (replacing_enabled && c == line_key) { + if (total_replacements < cap) { + outc = ' '; + total_replacements++; + if (total_replacements == cap) { + replacing_enabled = 0; + } + } else { + replacing_enabled = 0; + } + } + + if (wlen == sizeof(wbuf)) { + ssize_t wrote = write(out_fd, wbuf, wlen); + if (wrote < 0 || (size_t) wrote != wlen) { + close(in_fd); + close(out_fd); + return -1; + } + wlen = 0; + } + wbuf[wlen++] = (char) outc; + } + } else if (n == 0) { + if (wlen > 0) { + ssize_t wrote = write(out_fd, wbuf, wlen); + if (wrote < 0 || (size_t) wrote != wlen) { + close(in_fd); + close(out_fd); + return -1; + } + wlen = 0; + } + break; + } else { + close(in_fd); + close(out_fd); + return -1; + } + } + + close(in_fd); + close(out_fd); + + return total_replacements; +}