DB: get file list.

This commit is contained in:
2025-11-04 17:57:20 +02:00
parent 4ba740ae39
commit 473ec81b7a
11 changed files with 220 additions and 153 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ void process_client_command(char *line, session *sess, server_data_t *s_d) {
/* UPLOAD */
if (!strcmp(arg_2, "upload")) {
res = file_receive_prepare(sess, line, s_d);
if (!res)
if (!res)
sess->state = OP_UPLOAD;
return;
}
+83 -24
View File
@@ -1,5 +1,6 @@
#include "db.h"
#include "main.h"
#include <endian.h>
#include <libpq-fe.h>
#include <netinet/in.h>
#include <stdint.h>
@@ -150,7 +151,7 @@ int db_save_file(session *s) {
if (PQresultStatus(res) != PGRES_TUPLES_OK && !PQntuples(res))
return exit_query_2(0);
int id = atoi(PQgetvalue(res, 0, 0));
clearRes();
return id;
@@ -161,39 +162,97 @@ int db_save_file(session *s) {
// }
int db_get_files(i_get_files_db *arg) {
const char *paramValues[3];
int paramLengths[3];
int paramFormats[3];
int i, j, nFields;
uint64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start,
uint64_t *full_count) {
fl_t *fl_current;
char query[512];
char sort_by[16] = "id";
char sort_dir[5] = "ASC";
const char *paramValues[2];
int paramLengths[2];
int paramFormats[2];
int i;
uint64_t count;
uint64_t n_limit = htobe64(arg->limit);
uint64_t n_offset = htobe64(arg->offset);
paramValues[0] = arg->sort_by;
paramValues[1] = (char *)&arg->limit;
paramValues[2] = (char *)&arg->offset;
switch (arg->sort_by) {
case NAME:
strcpy(sort_by, "name");
break;
case CREATED_AT:
strcpy(sort_by, "created_at");
break;
case USER_ID:
strcpy(sort_by, "user_id");
break;
case ID: // id is by default
default:
break;
}
paramLengths[0] = strlen(arg->sort_by);
paramLengths[1] = sizeof(arg->limit);
paramLengths[2] = sizeof(arg->offset);
if (arg->sort_direction == DESC) {
strcpy(sort_dir, "DESC");
}
paramFormats[0] = TEXT;
paramValues[0] = (char *)&n_limit;
paramValues[1] = (char *)&n_offset;
paramLengths[0] = sizeof(n_limit);
paramLengths[1] = sizeof(n_offset);
paramFormats[0] = BIN;
paramFormats[1] = BIN;
paramFormats[2] = BIN;
res = PQexecParams(conn, "SELECT * FROM files ORDER BY $1 LIMIT $2 OFFSET $3",
3, NULL, paramValues, paramLengths, paramFormats, TEXT);
sprintf(
query,
"SELECT user_id, name, size, description, permissions, hash, username "
"FROM files JOIN users ON user_id = users.id "
"ORDER BY files.%s %s LIMIT $1 OFFSET $2",
sort_by, sort_dir);
nFields = PQnfields(res);
for (i = 0; i < nFields; i++)
printf("%-15s", PQfname(res, i));
printf("\n\n");
res = PQexecParams(conn, query, 2, NULL, paramValues, paramLengths,
paramFormats, TEXT);
if (PQresultStatus(res) != PGRES_TUPLES_OK && !PQntuples(res))
return exit_query_2(0);
for (i = 0; i < PQntuples(res); i++) {
for (j = 0; j < nFields; j++)
printf("%-15s", PQgetvalue(res, i, j));
printf("\n");
fl_t *l_item = malloc(sizeof(fl_t));
l_item->next = NULL;
l_item->owner_id = atoi(PQgetvalue(res, i, 0));
char *name = PQgetvalue(res, i, 1);
l_item->name = malloc(strlen(name) + 1);
strcpy(l_item->name, name);
l_item->size = atoll(PQgetvalue(res, i, 2));
char *description = PQgetvalue(res, i, 3);
l_item->description = malloc(strlen(description) + 1);
strcpy(l_item->description, description);
l_item->permissions = atoi(PQgetvalue(res, i, 4));
l_item->hash = atoi(PQgetvalue(res, i, 5));
char *owner = PQgetvalue(res, i, 6);
l_item->owner = malloc(strlen(owner) + 1);
strcpy(l_item->owner, owner);
if (*fl_start == NULL) {
*fl_start = l_item;
} else {
fl_current->next = l_item;
}
fl_current = l_item;
}
count = PQntuples(res);
clearRes();
return 0;
res = PQexec(conn, "SELECT COUNT(id) "
"FROM files "); // TODO: finish
if (PQresultStatus(res) != PGRES_TUPLES_OK && !PQntuples(res))
return exit_query_2(0);
*full_count = atoll(PQgetvalue(res, 0, 0));
clearRes();
return count;
}
+15 -7
View File
@@ -1,3 +1,5 @@
#ifndef DB_H
#define DB_H
#include "main.h"
#include <stdint.h>
@@ -21,15 +23,21 @@ typedef struct {
int user_id;
} i_get_file_db;
typedef struct {
int user_id; // TODO: implement
char *name; // TODO: implement
int limit;
int offset;
char sort_by[12];
} i_get_files_db;
enum sort_direction { ASC, DESC };
enum sort_by { ID, NAME, CREATED_AT, USER_ID };
typedef struct {
uint32_t user_id; // TODO: implement
char name[12]; // TODO: implement
uint32_t limit;
uint32_t offset;
enum sort_by sort_by;
enum sort_direction sort_direction;
} i_get_files_db;
int init_db_connection();
int db_user_auth(i_auth_t *credentials, o_auth_t *response);
int db_save_file(session *s);
uint64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start,
uint64_t *full_count);
#endif
+9
View File
@@ -0,0 +1,9 @@
client.o: src/client.c src/client.h src/main.h src/file_p.h src/session.h
db.o: src/db.c src/db.h src/main.h
file_p.o: src/file_p.c src/file_p.h src/main.h src/db.h \
src/libs/murmur3/murmur3.h src/session.h
main.o: src/main.c src/main.h src/server.h src/db.h
server.o: src/server.c src/main.h src/session.h src/user.h
session.o: src/session.c src/session.h src/main.h src/client.h src/db.h \
src/file_p.h src/user.h
user.o: src/user.c src/main.h src/session.h src/db.h
+73 -90
View File
@@ -1,4 +1,5 @@
#include "file_p.h"
#include "db.h"
#include "libs/murmur3/murmur3.h"
#include "main.h"
#include "session.h"
@@ -7,6 +8,7 @@
#include <fcntl.h>
#include <netinet/in.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -23,23 +25,69 @@
char *extract_second_arg(char *);
size_t get_file_size(char *, char *);
void clear_list(fl_t *start) {
if (start) {
fl_t *curr = start;
fl_t *next;
do {
next = curr->next;
free(curr->description);
free(curr->name);
free(curr->owner);
free(curr);
} while ((curr = next) != NULL);
}
}
void file_list(session *sess, server_data_t *s_d) {
// TODO: change of format (rewrite in C++)
char list_end[] = "list_end\n";
fl_t *current;
current = s_d->fl_start;
fl_t *fl_start, *fl_current;
char item_h[256];
i_get_files_db args;
uint64_t page = 1;
uint64_t full_count, count, pages_count;
fl_start = NULL;
fl_current = NULL;
if (sess->fl_start) {
clear_list(fl_start);
sess->fl_start = NULL;
sess->fl_current = NULL;
}
args.limit = 15;
args.offset = 15 * (page - 1);
args.sort_by = ID;
args.sort_direction = ASC;
count = db_get_files_data(&args, &fl_start, &full_count);
char page_info[256];
pages_count = full_count / 15;
if (!pages_count)
pages_count = 1;
sprintf(page_info, "PAGE %lu FROM %lu. COUNT: %lu FROM %lu\n", page,
pages_count, count, full_count);
if (!fl_start)
return;
fl_current = fl_start;
do {
int n_len = strlen(sess->uname);
if (strncmp(current->owner, sess->uname, n_len) && !current->permissions) {
if (strncmp(fl_current->owner, sess->uname, n_len) &&
!fl_current->permissions) {
continue;
}
int h_len = sprintf(item_h, "%s %zu %s", current->name, current->size,
current->owner);
int d_len = strlen(current->description);
int h_len = sprintf(item_h, "%s %zu %s", fl_current->name, fl_current->size,
fl_current->owner);
int d_len = strlen(fl_current->description);
int f_len = h_len + d_len + 2;
char *full_str = malloc(sizeof(char) * f_len);
sprintf(full_str, "%s %s", item_h, current->description);
sprintf(full_str, "%s %s", item_h, fl_current->description);
int i;
for (i = h_len; i < h_len + d_len; i++) {
if (full_str[i] == '\n') {
@@ -48,8 +96,12 @@ void file_list(session *sess, server_data_t *s_d) {
}
write(sess->sd, full_str, f_len - 1); // -1 : do not include \0
free(full_str);
} while ((current = current->next) != NULL);
sess->fl_current = fl_current;
} while ((fl_current = fl_current->next) != NULL);
sess->fl_start = fl_start;
write(sess->sd, list_end, sizeof(list_end));
write(sess->sd, page_info, strlen(page_info));
}
int file_send_prepare(session *sess, char *line, server_data_t *s_d) {
@@ -76,7 +128,6 @@ int file_send_prepare(session *sess, char *line, server_data_t *s_d) {
fsize = lseek(file_d, 0, SEEK_END);
lseek(file_d, 0, SEEK_SET);
sess->file->fd = file_d;
sess->file->size = fsize;
sess->file->rest = fsize;
sess->file->name = malloc(strlen(fname));
@@ -113,6 +164,7 @@ int file_receive_prepare(session *sess, char *line, server_data_t *s_d) {
sscanf(line, "file upload \"%s %zd %d", fname, &fsize, &perm);
sess->file = malloc(sizeof(session_file));
sess->file->name = malloc(sizeof(char) * strlen(fname));
sess->file->path = malloc(sizeof(STORAGE_FOLDER) + 2 + 9);
sess->file->permissions = (char)perm;
sess->file->description = NULL;
strncpy(sess->file->name, fname, strlen(fname) - 1);
@@ -143,12 +195,11 @@ int file_receive_prepare(session *sess, char *line, server_data_t *s_d) {
int file_d;
for (;;) {
MurmurHash3_x86_32(sess->file->name, strlen(sess->file->name),
seed, &sess->file->hash);
MurmurHash3_x86_32(sess->file->name, strlen(sess->file->name), seed,
&sess->file->hash);
extract_names_from_hash(sess->file->hash, hashed_dir_name, hashed_name);
sess->file->path = malloc(sizeof(STORAGE_FOLDER) + 2 + 9);
sprintf(sess->file->path, "%s/%s/%s", STORAGE_FOLDER, hashed_dir_name,
hashed_name);
@@ -163,8 +214,6 @@ int file_receive_prepare(session *sess, char *line, server_data_t *s_d) {
if (file_d == -1) {
if (errno == EEXIST) {
seed++;
free(sess->file->path);
sess->file->path = NULL;
continue;
}
mes_len = sprintf(mes, "Can't create file with such name: \"%s\"\n",
@@ -178,7 +227,7 @@ int file_receive_prepare(session *sess, char *line, server_data_t *s_d) {
}
mes_len = sprintf(mes, "accept");
sess->file->fd = file_d;
sess->fd = file_d;
sess->file->size = fsize;
sess->file->rest = fsize;
write(sd, mes, mes_len);
@@ -199,16 +248,17 @@ void clear_file_from_sess(session *s) {
free(sf->description);
sf->description = NULL;
}
if (sf->fd > -1) {
close(sf->fd);
if (s->fd > -1) {
close(s->fd);
s->fd = -1;
}
free(sf);
s->file = NULL;
}
void file_download_upload(session *sess, enum f_actions f_action) {
int source_d = f_action == F_DOWNLOAD ? sess->file->fd : sess->sd;
int dest_d = f_action == F_DOWNLOAD ? sess->sd : sess->file->fd;
void file_load(session *sess, enum f_actions f_action) {
int source_d = f_action == F_DOWNLOAD ? sess->fd : sess->sd;
int dest_d = f_action == F_DOWNLOAD ? sess->sd : sess->fd;
char buf[INBUFSIZE];
int rlen = read(source_d, buf, INBUFSIZE);
if (rlen == 0) {
@@ -282,77 +332,10 @@ int file_upload_description(session *sess, char *line, server_data_t *s_d) {
}
char *desc_end = strstr(line, ":END:");
if (desc_end != NULL) {
sess->file->description[strlen(sess->file->description) - 6] = 0; // cut the :END:
sess->file->description[strlen(sess->file->description) - 6] =
0; // cut the :END:
return 1;
}
line = NULL;
}
}
// TODO: синхронизовать c C++
void get_files_descriptions(server_data_t *s_d) {
int fd = open(FILE_DESCRIPTIONS_NAME, O_RDONLY);
if (-1 == fd) {
perror(FILE_DESCRIPTIONS_NAME);
exit(8);
}
int rlen;
char buf[INBUFSIZE] = "";
chdir(STORAGE_FOLDER);
while ((rlen = read(fd, buf, FILEBUFSIZE)) > 0) {
char *buf_pos = buf;
char tmp[256];
while (buf_pos[0] != '\0') {
fl_t *fl_item = malloc(sizeof(fl_t));
fl_item->next = NULL;
/* file name */
sscanf(buf_pos, "%s\n", tmp);
buf_pos += strlen(tmp) + 1;
fl_item->name = malloc(sizeof(char) * (strlen(tmp) + 1));
strcpy(fl_item->name, tmp);
/* file owner */
sscanf(buf_pos, "%s\n", tmp);
buf_pos += strlen(tmp) + 1;
fl_item->owner = malloc(sizeof(char) * (strlen(tmp) + 1));
strcpy(fl_item->owner, tmp);
/* file permissions */
sscanf(buf_pos, "%s\n", tmp);
buf_pos += strlen(tmp) + 1;
fl_item->permissions = atoi(tmp);
/* file size */
int fd = open(fl_item->name, O_RDONLY);
if (-1 == fd) {
perror(fl_item->name);
free(fl_item->name);
free(fl_item->owner);
free(fl_item);
buf_pos += strstr(buf_pos, ":END:") + 6 - buf_pos;
continue;
}
fl_item->size = lseek(fd, 0, SEEK_END);
close(fd);
/* file description */
int d_len = strstr(buf_pos, ":END:\n") - buf_pos;
fl_item->description = malloc(d_len + 1);
strncpy(fl_item->description, buf_pos, d_len);
fl_item->description[d_len] = 0;
buf_pos += d_len + 6;
if (s_d->fl_start == NULL) {
s_d->fl_start = fl_item;
s_d->fl_current = fl_item;
} else {
s_d->fl_current->next = fl_item;
s_d->fl_current = fl_item;
}
}
}
close(fd);
chdir("..");
}
+3 -2
View File
@@ -1,14 +1,15 @@
#ifndef FILEP_H
#define FILEP_H
#include "main.h"
void get_files_descriptions(server_data_t *);
void get_files_data(server_data_t *, uint32_t page);
void clear_list(fl_t *start);
void file_list(session *, server_data_t *);
int file_send_prepare(session *, char *, server_data_t *);
enum f_actions {
F_UPLOAD,
F_DOWNLOAD,
};
void file_download_upload(session *sess, enum f_actions);
void file_load(session *sess, enum f_actions);
int file_receive_prepare(session *sess, char *line, server_data_t *s_d);
int file_upload_description(session *sess, char *line, server_data_t *s_d);
int file_save_db(session *sess, server_data_t *s_d);
-4
View File
@@ -1,5 +1,4 @@
#include "main.h"
#include "file_p.h"
#include "server.h"
#include "db.h"
@@ -8,10 +7,7 @@ int main(int argc, char *argv[]) {
server_data_t server_data;
prepare_start(argc, argv);
server_data.welcome_message = get_welcome_mes();
server_data.fl_start = NULL;
server_data.fl_current = NULL;
init_db_connection();
get_files_descriptions(&server_data);
server_data.ls = start_server();
server_main_loop(&server_data);
return 0;
+15 -13
View File
@@ -49,9 +49,19 @@ typedef struct {
size_t size;
size_t rest;
uint32_t hash;
int fd;
} session_file;
typedef struct fl_t {
char *name;
char *description;
char *owner;
char permissions;
uint32_t owner_id;
uint32_t hash;
size_t size;
struct fl_t *next;
} fl_t;
typedef struct session {
unsigned long from_ip;
unsigned short from_port;
@@ -62,22 +72,14 @@ typedef struct session {
char privileges;
char *uname;
uint32_t uid;
int fd;
int sd; /* session descriptor */
session_file *file;
} session;
typedef struct fl_t {
char *name;
char *description;
char *owner;
char permissions;
size_t size;
struct fl_t *next;
} fl_t;
typedef struct server_data_t {
fl_t *fl_start;
fl_t *fl_current;
} session;
typedef struct server_data_t {
char *welcome_message;
int ls;
} server_data_t;
+4 -4
View File
@@ -35,8 +35,8 @@ void server_main_loop(server_data_t *s_d) {
if (i > maxfd)
maxfd = i;
/* active uploads/downloads */
if (connections[i]->file && connections[i]->file->fd > -1) {
int fd = connections[i]->file->fd;
if (connections[i]->fd > -1) {
int fd = connections[i]->fd;
FD_SET(fd, &readfds);
if (fd > maxfd)
maxfd = fd;
@@ -61,8 +61,8 @@ void server_main_loop(server_data_t *s_d) {
/* download/upload file */
if (connections[i] != NULL && (connections[i]->state == OP_UPLOAD ||
connections[i]->state == OP_DOWNLOAD)) {
if (connections[i]->file && connections[i]->file->fd > -1 &&
FD_ISSET(connections[i]->file->fd, &readfds)) {
if (connections[i]->fd > -1 &&
FD_ISSET(connections[i]->fd, &readfds)) {
perform_session_action(connections[i], NULL, s_d);
}
} else if (connections[i] != NULL && FD_ISSET(i, &readfds)) {
+15 -8
View File
@@ -1,9 +1,9 @@
#include "session.h"
#include "client.h"
#include "db.h"
#include "file_p.h"
#include "main.h"
#include "user.h"
#include "db.h"
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
@@ -42,7 +42,10 @@ session *make_new_session(int fd, struct sockaddr_in *from, char *wm) {
sess->reason = NO_REASON;
sess->uname = NULL;
sess->sd = fd;
sess->fd = -1;
sess->file = NULL;
sess->fl_start = NULL;
sess->fl_current = NULL;
session_send_string(sess, wm);
session_send_string(sess, "login> ");
return sess;
@@ -112,10 +115,10 @@ int query_extract_from_buf(session *sess, char **output_line) {
pos++;
memmove(sess->buf, sess->buf + pos, sess->buf_used);
sess->buf[sess->buf_used] = 0;
if (line[pos-2] == '\r') {
line[pos-2] = line[pos-1];
if (line[pos - 2] == '\r') {
line[pos - 2] = line[pos - 1];
pos--;
line[pos-1] = 0;
line[pos - 1] = 0;
}
*output_line = line;
}
@@ -124,7 +127,6 @@ int query_extract_from_buf(session *sess, char **output_line) {
void perform_session_action(session *sess, char *line, server_data_t *s_d) {
int state = sess->state;
int priv;
int res;
/* while (sess->buf_used) { */
switch (state) {
@@ -138,10 +140,10 @@ void perform_session_action(session *sess, char *line, server_data_t *s_d) {
process_client_command(line, sess, s_d);
break;
case OP_DOWNLOAD:
file_download_upload(sess, F_DOWNLOAD);
file_load(sess, F_DOWNLOAD);
break;
case OP_UPLOAD:
file_download_upload(sess, F_UPLOAD);
file_load(sess, F_UPLOAD);
break;
case OP_UPLOAD_DESCRIPTION:
res = file_upload_description(sess, line, s_d);
@@ -161,10 +163,15 @@ void perform_session_action(session *sess, char *line, server_data_t *s_d) {
void close_session(session *connections[], int sd) {
if (connections[sd] != NULL) {
if (connections[sd]->file) clear_file_from_sess(connections[sd]);
if (connections[sd]->file != NULL)
clear_file_from_sess(connections[sd]);
close(sd);
connections[sd]->sd = -1;
free(connections[sd]->uname);
if (connections[sd]->fl_start != NULL) {
fl_t *fl_start = connections[sd]->fl_start;
clear_list(fl_start);
}
free(connections[sd]);
connections[sd] = NULL;
}