diff --git a/TODO.md b/TODO.md index defa23a..449415c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,16 +1,15 @@ -# Development plans - -- [ ] Remove file when error while saving the data in DB - ## Tasks - [x] Switch to SQLite -- [ ] Close the DB correctly in any quit case (also by SIGTERM) - process signals through pselect -- [ ] Get rid of unsigned integers +- [x] Close the DB correctly in any quit case (also by SIGTERM) +- [x] Get rid of unsigned integers - [x] Check registration - [x] Auto create a database when one is missing. +# Development plans + +- [ ] Remove file when error while saving the data in DB + ## Features - [x] Database integration diff --git a/src/client.c b/src/client.c index c0b0fc3..10bfbd7 100644 --- a/src/client.c +++ b/src/client.c @@ -17,7 +17,7 @@ void process_client_command(char *line, session *sess, server_data_t *s_d) { char arg_1[32]; char arg_2[32]; - uint32_t res; + int32_t res; i_file_list_t fl_args; fl_args.name = NULL; int32_t ret = 0; diff --git a/src/db/db.h b/src/db/db.h index 9837b2d..a264c75 100644 --- a/src/db/db.h +++ b/src/db/db.h @@ -15,14 +15,14 @@ typedef struct { typedef struct { char privileges; - uint32_t uid; + int32_t uid; } o_auth_t; /* Get file */ typedef struct { - uint32_t id; - uint32_t user_id; + int32_t id; + int32_t user_id; char name[FILE_NAME_LEN]; } i_get_file_db; @@ -30,10 +30,10 @@ enum sort_direction { ASC, DESC }; enum sort_by { ID, NAME, CREATED_AT, USER_ID }; typedef struct { - uint32_t user_id; // TODO: implement + int32_t user_id; // TODO: implement char search_str[FILE_NAME_LEN]; // TODO: implement - uint32_t limit; - uint32_t offset; + int32_t limit; + int32_t offset; enum sort_by sort_by; enum sort_direction sort_direction; } i_get_files_db; @@ -50,8 +50,8 @@ int32_t init_db_connection(); int32_t db_save_file(session *s); int32_t db_user_auth(i_auth_t *credentials, o_auth_t *response); s_file_t *db_get_file(i_get_file_db *arg); -uint64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start, - uint64_t *full_count); +int64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start, + int64_t *full_count); int32_t db_user_create(i_db_user_create *); -int close_connection(void); +int db_close_connection(void); #endif \ No newline at end of file diff --git a/src/db/db_postgresql.c b/src/db/db_postgresql.c index 340375b..a908b6e 100644 --- a/src/db/db_postgresql.c +++ b/src/db/db_postgresql.c @@ -81,7 +81,7 @@ static void processNotice(void *arg, const char *message) { // do nothing } -int close_connection(void) { return 0; }; +int db_close_connection(void) { return 0; }; int init_db_connection() { // TODO: get from external configs @@ -152,7 +152,7 @@ int32_t db_user_create(i_db_user_create *args) { paramLengths[0] = strlen(args->uname); paramLengths[2] = strlen(args->email); - uint32_t ret_value; + int32_t ret_value; string_to_SHA256(args->pass, passHashed); paramValues[1] = passHashed; @@ -205,7 +205,7 @@ int32_t db_save_file(session *s) { char empty_str[] = ""; int32_t uid_n = htonl(s->uid); - uint64_t size_n = htobe64(sf->size); + size_t size_n = htobe64(sf->size); int32_t hash_n = htonl(sf->hash); int32_t perm_n = htonl(sf->permissions); @@ -222,7 +222,7 @@ int32_t db_save_file(session *s) { paramLengths[0] = sizeof(int32_t); paramLengths[1] = strlen(sf->name); - paramLengths[2] = sizeof(uint64_t); + paramLengths[2] = sizeof(int64_t); paramLengths[3] = sizeof(int32_t); if (sf->description != NULL) { paramLengths[4] = strlen(sf->description); @@ -259,7 +259,7 @@ s_file_t *db_get_file(i_get_file_db *arg) { char value[64] = ""; const char *paramValues[1]; char query[512]; - uint32_t q_len = 0; + int32_t q_len = 0; if (arg->id) { strcpy(s_field, "id"); @@ -306,8 +306,8 @@ s_file_t *db_get_file(i_get_file_db *arg) { return sf; } -uint64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start, - uint64_t *full_count) { +int64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start, + int64_t *full_count) { fl_t *fl_current; char query[512]; char sort_by[16] = "id"; @@ -316,9 +316,9 @@ uint64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start, int paramLengths[3]; int paramFormats[3]; int i; - uint64_t count; - uint64_t n_limit = htobe64(arg->limit); - uint64_t n_offset = htobe64(arg->offset); + int64_t count; + int64_t n_limit = htobe64(arg->limit); + int64_t n_offset = htobe64(arg->offset); bool by_name = strlen(arg->search_str) > 0; int32_t params_num = 3; diff --git a/src/db/db_sqlite.c b/src/db/db_sqlite.c index f412038..a9d8729 100644 --- a/src/db/db_sqlite.c +++ b/src/db/db_sqlite.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -32,8 +31,6 @@ enum db_arg_type { db_str, db_int, db_int64, - db_uint, - db_uint64, db_blob, db_size, /* size for subsequent arg */ db_end @@ -41,16 +38,6 @@ enum db_arg_type { typedef enum db_cb_resp (*db_callback)(sqlite3_stmt *stmt, void *resp); -const char message[] = "The program is closing!\n"; - -#define SIG130 130 - -void sigterm_handler(int s) { - signal(SIGINT, sigterm_handler); - write(STDOUT_FILENO, message, sizeof(message) - 1); - /* sqlite3_close_v2(db); */ -} - void print_err(char **err) { if (*err != NULL) { printf("%s\n", *err); @@ -116,7 +103,6 @@ int check_and_create_tables() { } int init_db_connection(void) { - signal(SIGINT, sigterm_handler); int res = sqlite3_open("db.sqlite", &db); char *err = NULL; if (!res) { @@ -126,7 +112,7 @@ int init_db_connection(void) { return 0; } -int close_connection(void) { return sqlite3_close_v2(db); } +int db_close_connection(void) { return sqlite3_close_v2(db); } // === /* BASE FUNCTIONS */ ========================================= @@ -159,12 +145,6 @@ enum db_cb_resp vdb_query(const char *zSql, db_callback callback, void *a_resp, case db_int64: sqlite3_bind_int64(stmt, i + 1, va_arg(va_list, int64_t)); break; - case db_uint: - sqlite3_bind_int(stmt, i + 1, va_arg(va_list, unsigned int)); - break; - case db_uint64: - sqlite3_bind_int64(stmt, i + 1, va_arg(va_list, uint64_t)); - break; case db_blob: if (size > 0) { sqlite3_bind_blob(stmt, i + 1, va_arg(va_list, void *), size, NULL); @@ -442,8 +422,8 @@ enum db_cb_resp db_get_files_count_db(sqlite3_stmt *stmt, void *resp) { return db_success; } -uint64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start, - uint64_t *full_count) { +int64_t db_get_files_data(i_get_files_db *arg, fl_t **fl_start, + int64_t *full_count) { fl_t *fl_current = NULL; char zSql[512]; struct db_get_files_data data = {.fl_current = &fl_current, diff --git a/src/file_p.c b/src/file_p.c index 3762a43..0bfdd62 100644 --- a/src/file_p.c +++ b/src/file_p.c @@ -46,7 +46,7 @@ void file_list(session *sess, server_data_t *s_d, i_file_list_t *f_args) { fl_t *fl_start, *fl_current; char item_h[256]; i_get_files_db args; - uint64_t full_count, count, pages_count; + int32_t full_count, count, pages_count; fl_start = NULL; fl_current = NULL; @@ -125,7 +125,7 @@ int directory_exists(const char *path) { return S_ISDIR(info.st_mode); // true if it is a directory } -void extract_names_from_hash(uint32_t file_hash, char *dirname, char *fname) { +void extract_names_from_hash(int32_t file_hash, char *dirname, char *fname) { char hashed_full_name[9]; sprintf(hashed_full_name, "%08x", file_hash); strncpy(dirname, hashed_full_name, 2); @@ -142,7 +142,7 @@ int32_t file_send_prepare(session *sess, char *line, server_data_t *s_d) { char hashed_dir_name[3]; char hashed_name[7]; char err_mes[256]; - uint32_t mlen; + int32_t mlen; char *name_begin = strchr(line, '[') + 1; char *name_end = strrchr(line, ']'); diff --git a/src/file_p.h b/src/file_p.h index c806ec5..6134e4e 100644 --- a/src/file_p.h +++ b/src/file_p.h @@ -7,8 +7,8 @@ #include void clear_list(fl_t *start); typedef struct { - uint32_t page; - uint32_t limit; + int32_t page; + int32_t limit; char *name; } i_file_list_t; void file_list(session *, server_data_t *, i_file_list_t *l_args); diff --git a/src/libs/murmur3/murmur3.c b/src/libs/murmur3/murmur3.c index fe03d9c..8a13450 100644 --- a/src/libs/murmur3/murmur3.c +++ b/src/libs/murmur3/murmur3.c @@ -18,12 +18,12 @@ #define FORCE_INLINE inline #endif -static FORCE_INLINE uint32_t rotl32 ( uint32_t x, int8_t r ) +static FORCE_INLINE int32_t rotl32 ( int32_t x, int8_t r ) { return (x << r) | (x >> (32 - r)); } -static FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r ) +static FORCE_INLINE int64_t rotl64 ( int64_t x, int8_t r ) { return (x << r) | (x >> (64 - r)); } @@ -42,7 +42,7 @@ static FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r ) //----------------------------------------------------------------------------- // Finalization mix - force all bits of a hash block to avalanche -static FORCE_INLINE uint32_t fmix32 ( uint32_t h ) +static FORCE_INLINE int32_t fmix32 ( int32_t h ) { h ^= h >> 16; h *= 0x85ebca6b; @@ -55,7 +55,7 @@ static FORCE_INLINE uint32_t fmix32 ( uint32_t h ) //---------- -static FORCE_INLINE uint64_t fmix64 ( uint64_t k ) +static FORCE_INLINE int64_t fmix64 ( int64_t k ) { k ^= k >> 33; k *= BIG_CONSTANT(0xff51afd7ed558ccd); @@ -69,25 +69,25 @@ static FORCE_INLINE uint64_t fmix64 ( uint64_t k ) //----------------------------------------------------------------------------- void MurmurHash3_x86_32 ( const void * key, int len, - uint32_t seed, void * out ) + int32_t seed, void * out ) { const uint8_t * data = (const uint8_t*)key; const int nblocks = len / 4; int i; - uint32_t h1 = seed; + int32_t h1 = seed; - uint32_t c1 = 0xcc9e2d51; - uint32_t c2 = 0x1b873593; + int32_t c1 = 0xcc9e2d51; + int32_t c2 = 0x1b873593; //---------- // body - const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); + const int32_t * blocks = (const int32_t *)(data + nblocks*4); for(i = -nblocks; i; i++) { - uint32_t k1 = getblock(blocks,i); + int32_t k1 = getblock(blocks,i); k1 *= c1; k1 = ROTL32(k1,15); @@ -103,7 +103,7 @@ void MurmurHash3_x86_32 ( const void * key, int len, const uint8_t * tail = (const uint8_t*)(data + nblocks*4); - uint32_t k1 = 0; + int32_t k1 = 0; switch(len & 3) { @@ -120,39 +120,39 @@ void MurmurHash3_x86_32 ( const void * key, int len, h1 = fmix32(h1); - *(uint32_t*)out = h1; + *(int32_t*)out = h1; } //----------------------------------------------------------------------------- void MurmurHash3_x86_128 ( const void * key, const int len, - uint32_t seed, void * out ) + int32_t seed, void * out ) { const uint8_t * data = (const uint8_t*)key; const int nblocks = len / 16; int i; - uint32_t h1 = seed; - uint32_t h2 = seed; - uint32_t h3 = seed; - uint32_t h4 = seed; + int32_t h1 = seed; + int32_t h2 = seed; + int32_t h3 = seed; + int32_t h4 = seed; - uint32_t c1 = 0x239b961b; - uint32_t c2 = 0xab0e9789; - uint32_t c3 = 0x38b34ae5; - uint32_t c4 = 0xa1e38b93; + int32_t c1 = 0x239b961b; + int32_t c2 = 0xab0e9789; + int32_t c3 = 0x38b34ae5; + int32_t c4 = 0xa1e38b93; //---------- // body - const uint32_t * blocks = (const uint32_t *)(data + nblocks*16); + const int32_t * blocks = (const int32_t *)(data + nblocks*16); for(i = -nblocks; i; i++) { - uint32_t k1 = getblock(blocks,i*4+0); - uint32_t k2 = getblock(blocks,i*4+1); - uint32_t k3 = getblock(blocks,i*4+2); - uint32_t k4 = getblock(blocks,i*4+3); + int32_t k1 = getblock(blocks,i*4+0); + int32_t k2 = getblock(blocks,i*4+1); + int32_t k3 = getblock(blocks,i*4+2); + int32_t k4 = getblock(blocks,i*4+3); k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; @@ -176,10 +176,10 @@ void MurmurHash3_x86_128 ( const void * key, const int len, const uint8_t * tail = (const uint8_t*)(data + nblocks*16); - uint32_t k1 = 0; - uint32_t k2 = 0; - uint32_t k3 = 0; - uint32_t k4 = 0; + int32_t k1 = 0; + int32_t k2 = 0; + int32_t k3 = 0; + int32_t k4 = 0; switch(len & 15) { @@ -223,36 +223,36 @@ void MurmurHash3_x86_128 ( const void * key, const int len, h1 += h2; h1 += h3; h1 += h4; h2 += h1; h3 += h1; h4 += h1; - ((uint32_t*)out)[0] = h1; - ((uint32_t*)out)[1] = h2; - ((uint32_t*)out)[2] = h3; - ((uint32_t*)out)[3] = h4; + ((int32_t*)out)[0] = h1; + ((int32_t*)out)[1] = h2; + ((int32_t*)out)[2] = h3; + ((int32_t*)out)[3] = h4; } //----------------------------------------------------------------------------- void MurmurHash3_x64_128 ( const void * key, const int len, - const uint32_t seed, void * out ) + const int32_t seed, void * out ) { const uint8_t * data = (const uint8_t*)key; const int nblocks = len / 16; int i; - uint64_t h1 = seed; - uint64_t h2 = seed; + int64_t h1 = seed; + int64_t h2 = seed; - uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5); - uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f); + int64_t c1 = BIG_CONSTANT(0x87c37b91114253d5); + int64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f); //---------- // body - const uint64_t * blocks = (const uint64_t *)(data); + const int64_t * blocks = (const int64_t *)(data); for(i = 0; i < nblocks; i++) { - uint64_t k1 = getblock(blocks,i*2+0); - uint64_t k2 = getblock(blocks,i*2+1); + int64_t k1 = getblock(blocks,i*2+0); + int64_t k2 = getblock(blocks,i*2+1); k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; @@ -268,28 +268,28 @@ void MurmurHash3_x64_128 ( const void * key, const int len, const uint8_t * tail = (const uint8_t*)(data + nblocks*16); - uint64_t k1 = 0; - uint64_t k2 = 0; + int64_t k1 = 0; + int64_t k2 = 0; switch(len & 15) { - case 15: k2 ^= (uint64_t)(tail[14]) << 48; - case 14: k2 ^= (uint64_t)(tail[13]) << 40; - case 13: k2 ^= (uint64_t)(tail[12]) << 32; - case 12: k2 ^= (uint64_t)(tail[11]) << 24; - case 11: k2 ^= (uint64_t)(tail[10]) << 16; - case 10: k2 ^= (uint64_t)(tail[ 9]) << 8; - case 9: k2 ^= (uint64_t)(tail[ 8]) << 0; + case 15: k2 ^= (int64_t)(tail[14]) << 48; + case 14: k2 ^= (int64_t)(tail[13]) << 40; + case 13: k2 ^= (int64_t)(tail[12]) << 32; + case 12: k2 ^= (int64_t)(tail[11]) << 24; + case 11: k2 ^= (int64_t)(tail[10]) << 16; + case 10: k2 ^= (int64_t)(tail[ 9]) << 8; + case 9: k2 ^= (int64_t)(tail[ 8]) << 0; k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; - case 8: k1 ^= (uint64_t)(tail[ 7]) << 56; - case 7: k1 ^= (uint64_t)(tail[ 6]) << 48; - case 6: k1 ^= (uint64_t)(tail[ 5]) << 40; - case 5: k1 ^= (uint64_t)(tail[ 4]) << 32; - case 4: k1 ^= (uint64_t)(tail[ 3]) << 24; - case 3: k1 ^= (uint64_t)(tail[ 2]) << 16; - case 2: k1 ^= (uint64_t)(tail[ 1]) << 8; - case 1: k1 ^= (uint64_t)(tail[ 0]) << 0; + case 8: k1 ^= (int64_t)(tail[ 7]) << 56; + case 7: k1 ^= (int64_t)(tail[ 6]) << 48; + case 6: k1 ^= (int64_t)(tail[ 5]) << 40; + case 5: k1 ^= (int64_t)(tail[ 4]) << 32; + case 4: k1 ^= (int64_t)(tail[ 3]) << 24; + case 3: k1 ^= (int64_t)(tail[ 2]) << 16; + case 2: k1 ^= (int64_t)(tail[ 1]) << 8; + case 1: k1 ^= (int64_t)(tail[ 0]) << 0; k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; }; @@ -307,8 +307,8 @@ void MurmurHash3_x64_128 ( const void * key, const int len, h1 += h2; h2 += h1; - ((uint64_t*)out)[0] = h1; - ((uint64_t*)out)[1] = h2; + ((int64_t*)out)[0] = h1; + ((int64_t*)out)[1] = h2; } //----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/libs/murmur3/murmur3.h b/src/libs/murmur3/murmur3.h index c85395a..0f4bd9d 100644 --- a/src/libs/murmur3/murmur3.h +++ b/src/libs/murmur3/murmur3.h @@ -14,11 +14,11 @@ extern "C" { //----------------------------------------------------------------------------- -void MurmurHash3_x86_32 (const void *key, int len, uint32_t seed, void *out); +void MurmurHash3_x86_32 (const void *key, int len, int32_t seed, void *out); -void MurmurHash3_x86_128(const void *key, int len, uint32_t seed, void *out); +void MurmurHash3_x86_128(const void *key, int len, int32_t seed, void *out); -void MurmurHash3_x64_128(const void *key, int len, uint32_t seed, void *out); +void MurmurHash3_x64_128(const void *key, int len, int32_t seed, void *out); //----------------------------------------------------------------------------- diff --git a/src/main.c b/src/main.c index 071a236..076e2c3 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,6 @@ int main(int argc, char *argv[]) { /* TODO: display server port */ printf("Server is started!\n"); server_main_loop(&server_data); - close_connection(); + db_close_connection(); return 0; } \ No newline at end of file diff --git a/src/main.h b/src/main.h index 3b9595d..6e1dc94 100644 --- a/src/main.h +++ b/src/main.h @@ -54,9 +54,9 @@ typedef struct { char permissions; size_t size; size_t rest; - uint32_t hash; - uint32_t id; - uint32_t owner_id; + int32_t hash; + int32_t id; + int32_t owner_id; } s_file_t; typedef struct fl_t { @@ -64,10 +64,10 @@ typedef struct fl_t { char *description; char *owner; char permissions; - uint32_t owner_id; - uint32_t hash; + int32_t owner_id; + int32_t hash; size_t size; - uint32_t id; + int32_t id; struct fl_t *next; } fl_t; @@ -75,12 +75,12 @@ typedef struct session { unsigned long from_ip; unsigned short from_port; char buf[INBUFSIZE]; - uint32_t buf_used; + int32_t buf_used; enum sess_states state; enum error_reason reason; char privileges; char *uname; - uint32_t uid; + int32_t uid; int32_t fd; int32_t sd; /* session descriptor */ s_file_t *file; diff --git a/src/server.c b/src/server.c index c28da59..ff468fc 100644 --- a/src/server.c +++ b/src/server.c @@ -1,13 +1,15 @@ /* SPDX-License-Identifier: MIT */ /* Copyright (c) 2026 Oleksandr Zhylin */ -#include "main.h" +#include "db.h" #include "file_p.h" +#include "main.h" #include "session.h" #include #include #include #include +#include #include #include #include @@ -16,10 +18,25 @@ #include #include +volatile sig_atomic_t shutdown_requested = 0; +volatile sig_atomic_t signal_received = 0; + +void term_int_handler(int s) { + shutdown_requested = 1; + signal_received = s; +} + void server_main_loop(server_data_t *s_d) { fd_set readfds; int i, sr; + sigset_t mask, orig_mask; + signal(SIGINT, term_int_handler); + signal(SIGTERM, term_int_handler); + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGTERM); + sigprocmask(SIG_BLOCK, &mask, &orig_mask); session *connections[MAX_CONNECTIONS]; for (i = 0; i < MAX_CONNECTIONS; i++) { @@ -48,7 +65,13 @@ void server_main_loop(server_data_t *s_d) { } } - sr = select(maxfd + 1, &readfds, NULL, NULL, NULL); + sr = pselect(maxfd + 1, &readfds, NULL, NULL, NULL, &orig_mask); + + if (shutdown_requested != 0) { + db_close_connection(); + printf("\nStopping the server...\n"); + exit(signal_received); + } if (sr == -1) { perror("select"); diff --git a/src/user.c b/src/user.c index b07796d..505c9af 100644 --- a/src/user.c +++ b/src/user.c @@ -34,7 +34,7 @@ int32_t create_user(session *sess, char *line) { return 0; } -uint32_t process_user_name(char *line, session *sess) { +int32_t process_user_name(char *line, session *sess) { if (!strncmp(line, "exit", sizeof "exit")) { sess->state = ERR; sess->reason = EXIT;