First commit
This commit is contained in:
17
src/comment.c
Normal file
17
src/comment.c
Normal 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;
|
||||
}
|
234
src/drivers/unix_fs/unix_fs_driver.c
Normal file
234
src/drivers/unix_fs/unix_fs_driver.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user