First commit

This commit is contained in:
2023-06-15 01:44:02 +03:00
commit 815cfbbcef
8 changed files with 425 additions and 0 deletions

17
src/comment.c Normal file
View File

@@ -0,0 +1,17 @@
#include "comment.h"
#include <stdlib.h>
CommentHeader *
mk_comment_header(int reply_id, time_t creation_time, size_t text_length, char *user_sid, char *user_displayname)
{
CommentHeader *header = malloc(sizeof(CommentHeader));
header->reply_id = reply_id;
header->creation_time = creation_time;
header->text_length = text_length;
header->user_sid = user_sid;
header->user_displayname = user_displayname;
return header;
}

View File

@@ -0,0 +1,234 @@
#define _GNU_SOURCE /* ahh, didn't know asprintf is a GNU extension */
/* TODO: remove this bullshit */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "comment.h"
#include "drivers/unix_fs/unix_fs_driver.h"
#define READ_BUF_SZ 256
int
is_valid_directory(const char *path)
{
struct stat path_stat;
if (stat(path, &path_stat) != 0) {
return 0;
}
return S_ISDIR(path_stat.st_mode);
}
/* TODO: handle errors */
int
serialize_header(int fd, const CommentHeader *header)
{
write(fd, &header->reply_id, sizeof(int));
write(fd, &header->creation_time, sizeof(time_t));
write(fd, &header->text_length, sizeof(size_t));
write(fd, header->user_sid, strlen(header->user_sid) + 1);
write(fd, header->user_displayname, strlen(header->user_displayname) + 1);
return 0;
}
/* TODO: handle errors */
/* header string buffers must be long enough */
int
deserialize_header(int fd, CommentHeader *header)
{
char buf[READ_BUF_SZ], *dst_bufs[2];
int bytes_read;
size_t len, dst_idx, i;
dst_bufs[0] = header->user_sid;
dst_bufs[1] = header->user_displayname;
dst_idx = 0;
read(fd, &header->reply_id, sizeof(int));
read(fd, &header->creation_time, sizeof(time_t));
read(fd, &header->text_length, sizeof(size_t));
while ((bytes_read = read(fd, buf, READ_BUF_SZ))) {
for (; i < bytes_read; ++i) {
if (buf[i] != '\0') {
*(dst_bufs[dst_idx]++) = buf[i];
} else {
dst_idx++;
}
}
}
return 0;
}
int
unix_fs_driver_leave_comment(void *driver_data_ptr, CommentHeader *header, char *text)
{
char *path, *header_file_path, *text_file_path, *id_ctrl_file_path;
FILE *id_ctrl_file;
size_t path_len, text_len;
int max_id;
int retval;
int header_fd, text_fd, id_ctrl_fd;
/* assure safe free calls */
id_ctrl_file_path = header_file_path = text_file_path = NULL;
id_ctrl_file = NULL;
header_fd = text_fd = -1;
path = ((UnixFsDriverData*) driver_data_ptr)->path;
if (!is_valid_directory(path)) {
retval = -EINVAL;
goto defer;
}
path_len = strlen(path);
text_len = strlen(text);
if (asprintf(&id_ctrl_file_path, "%s/%s", path, ID_CTRL_FILE) < 0) {
id_ctrl_file_path = NULL;
retval = -ENOMEM;
goto defer;
}
id_ctrl_file = fopen(id_ctrl_file_path, "r+");
if (!id_ctrl_file) {
retval = -EIO;
goto defer;
}
id_ctrl_fd = fileno(id_ctrl_file);
if (lockf(id_ctrl_fd, F_LOCK, 0) < 0) {
id_ctrl_fd = -1;
retval = -EIO;
goto defer;
}
if (fscanf(id_ctrl_file, "%d", &max_id) != 1) {
max_id = 1;
}
if (asprintf(&header_file_path, HEADER_FILE_FMT, path, max_id) < 0) {
header_file_path = NULL;
retval = -ENOMEM;
goto defer;
}
if (asprintf(&text_file_path, TEXT_FILE_FMT, path, max_id) < 0) {
text_file_path = NULL;
retval = -ENOMEM;
goto defer;
};
header_fd = open(header_file_path, O_RDWR | O_CREAT, 0644);
text_fd = open(text_file_path, O_RDWR | O_CREAT, 0644);
if (header_fd < 0 || text_fd < 0) {
retval = -EINVAL;
goto defer;
}
if (write(text_fd, text, text_len) < text_len) {
retval = -EIO;
goto defer;
}
retval = serialize_header(header_fd, header);
if (retval < 0) {
goto defer;
}
if (!(id_ctrl_file = freopen(id_ctrl_file_path, "w+", id_ctrl_file))) {
retval = -EIO;
goto defer;
}
fprintf(id_ctrl_file, "%d", max_id + 1); /* update id only on success */
retval = max_id + 1;
defer:
if (id_ctrl_fd >= 0) {
if (lockf(id_ctrl_fd, F_ULOCK, 0) < 0) {
fprintf(stderr, "Failed to release id control lock, aborting...\n");
abort();
}
}
if (id_ctrl_file) fclose(id_ctrl_file);
free(id_ctrl_file_path);
free(header_file_path);
free(text_file_path);
if (header_fd >= 0) close(header_fd);
if (text_fd >= 0) close(text_fd);
return retval;
}
int
unix_fs_driver_get_header(void *driver_data_ptr, CommentHeader *header, int id)
{
char *path, *header_file_path;
int fd, retval;
path = ((UnixFsDriverData*) driver_data_ptr)->path;
if (!asprintf(&header_file_path, HEADER_FILE_FMT, path, id)) {
return -ENOMEM;
}
fd = open(header_file_path, O_RDONLY);
if (fd < 0) {
free(header_file_path);
return -EIO;
}
retval = deserialize_header(fd, header);
free(header_file_path);
close(fd);
return retval;
}
int
unix_fs_driver_get_text(void *driver_data_ptr, char *text, int id)
{
char *path, *text_file_path;
int fd, retval;
off_t length;
path = ((UnixFsDriverData*) driver_data_ptr)->path;
if (!asprintf(&text_file_path, TEXT_FILE_FMT, path, id)) {
return -ENOMEM;
}
fd = open(text_file_path, O_RDONLY);
if (fd < 0) {
retval = -EIO;
goto defer;
}
length = lseek(fd, 0, SEEK_END);
if (length < 0) {
retval = -EIO;
goto defer;
}
if (lseek(fd, 0, SEEK_SET) < 0) {
retval = -EIO;
goto defer;
}
if (read(fd, text, length) < length) {
retval = -EIO;
goto defer;
}
text[length] = '\0';
retval = 0;
defer:
free(text_file_path);
if (fd >= 0) close(fd);
return retval;
}