seems like working lab2
This commit is contained in:
27
lab_2/Makefile
Normal file
27
lab_2/Makefile
Normal file
@@ -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
|
||||||
96
lab_2/task12.c
Normal file
96
lab_2/task12.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#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 <input.txt> <output.txt> <max_replacements> <library.so>\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;
|
||||||
|
}
|
||||||
93
lab_2/textlib.c
Normal file
93
lab_2/textlib.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user