init
This commit is contained in:
commit
bcf96a9ec0
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
test
|
||||
compile_commands.json
|
||||
.vscode
|
||||
.cache
|
||||
48
Makefile
Normal file
48
Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
# Compiler and flags
|
||||
CPPC = gcc
|
||||
COMMON_CPPC_FLAGS = -Wall -Wextra -lm
|
||||
CPPC_FLAGS = $(COMMON_CPPC_FLAGS) -s -O3
|
||||
DEBUG_FLAGS = $(COMMON_CPPC_FLAGS) -ggdb
|
||||
DEBUG_ASANITIZE = $(DEBUG_FLAGS) -fsanitize=address -fno-omit-frame-pointer
|
||||
|
||||
|
||||
SRC_PATH := src
|
||||
OBJ_PATH := build/obj
|
||||
BIN_PATH := build/bin
|
||||
BIN_NAME := pupes-backup-server
|
||||
|
||||
|
||||
SRC_FILES := $(shell find $(SRC_PATH) -name '*.c')
|
||||
OBJ_FILES := $(patsubst $(SRC_PATH)/%.c,$(OBJ_PATH)/%.o,$(SRC_FILES))
|
||||
|
||||
|
||||
all: make-build-dir $(BIN_PATH)/$(BIN_NAME)
|
||||
|
||||
|
||||
debug: CPPC_FLAGS = $(DEBUG_FLAGS)
|
||||
debug: make-build-dir $(BIN_PATH)/$(BIN_NAME)
|
||||
|
||||
asan: CPPC_FLAGS = $(DEBUG_ASANITIZE)
|
||||
asan: make-build-dir $(BIN_PATH)/$(BIN_NAME)
|
||||
|
||||
|
||||
make-build-dir:
|
||||
mkdir -p $(OBJ_PATH)
|
||||
mkdir -p $(BIN_PATH)
|
||||
|
||||
|
||||
$(BIN_PATH)/$(BIN_NAME): $(OBJ_FILES)
|
||||
$(CPPC) $(CPPC_FLAGS) $^ -o $@
|
||||
|
||||
|
||||
$(OBJ_PATH)/%.o: $(SRC_PATH)/%.c
|
||||
$(CPPC) $(CPPC_FLAGS) -c $< -o $@
|
||||
|
||||
|
||||
install:
|
||||
@install -vpm 755 -o root -g root $(BIN_PATH)/$(BIN_NAME) /usr/bin/
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
.PHONY: all clean install debug asan
|
||||
BIN
build/bin/pupes-backup-server
Executable file
BIN
build/bin/pupes-backup-server
Executable file
Binary file not shown.
BIN
build/obj/main.o
Normal file
BIN
build/obj/main.o
Normal file
Binary file not shown.
22
src/color.h
Normal file
22
src/color.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Header guard
|
||||
#ifndef RESET
|
||||
|
||||
#define RESET "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
#define BLUE "\033[34m" /* Blue */
|
||||
#define MAGENTA "\033[35m" /* Magenta */
|
||||
#define CYAN "\033[36m" /* Cyan */
|
||||
#define WHITE "\033[37m" /* White */
|
||||
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
|
||||
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
|
||||
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
|
||||
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
|
||||
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
|
||||
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
|
||||
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
|
||||
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
|
||||
|
||||
#endif
|
||||
138
src/main.c
Normal file
138
src/main.c
Normal file
@ -0,0 +1,138 @@
|
||||
#include <asm-generic/errno-base.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include "color.h"
|
||||
|
||||
#define ALLOWED_IP "192.168.1.213"
|
||||
#define MAX_FILE_SIZE_G 100
|
||||
#define MAX_FILE_SIZE (size_t)MAX_FILE_SIZE_G*1073741824
|
||||
|
||||
#define READ_BUFFER_SIZE 32768 // 256K
|
||||
|
||||
const char* filename_base = "backup";
|
||||
|
||||
int sockfd;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage:\n%s [BACKUP DIRECTORY]\n", argv[0]);
|
||||
return EINVAL;
|
||||
}
|
||||
int client_fd;
|
||||
struct sockaddr_in servaddr, client_addr;
|
||||
socklen_t client_len = sizeof(client_addr);
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd == -1) {
|
||||
perror("socket creation failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printf("Socket created successfully\n");
|
||||
|
||||
int opt = 1;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||
perror("setsockopt failed");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
servaddr.sin_port = htons(15531);
|
||||
|
||||
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
|
||||
perror("socket bind failed");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printf("Socket bound to port 15531\n");
|
||||
|
||||
if (listen(sockfd, 1) != 0) {
|
||||
perror("listen failed");
|
||||
close(sockfd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printf("Listening on port 15531\n");
|
||||
|
||||
while (1) {
|
||||
client_fd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
|
||||
if (client_fd < 0) {
|
||||
perror("accept failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
char client_ip[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, INET_ADDRSTRLEN);
|
||||
|
||||
|
||||
if (strcmp(client_ip, ALLOWED_IP) == 0) {
|
||||
printf("Accepted connection from %s\n", client_ip);
|
||||
const time_t unix_time = time(NULL);
|
||||
|
||||
const uint8_t time_lenght = floor(log10(unix_time)) + 1;
|
||||
|
||||
const size_t path_with_filename_lenght = strlen(argv[1]) + 1 /*'/'*/ + strlen(filename_base) + 1 /*'-'*/ + time_lenght + 1 /*NULL BYTE*/;
|
||||
|
||||
char* full_filename_path = malloc(path_with_filename_lenght);
|
||||
char* moved_ptr;
|
||||
moved_ptr = stpcpy(full_filename_path,argv[1]); //copy directory path
|
||||
moved_ptr[0] = '/';
|
||||
moved_ptr = stpcpy(&moved_ptr[1], filename_base);
|
||||
moved_ptr[0] = '-';
|
||||
sprintf(&moved_ptr[1], "%lu", unix_time); // time + NULL terminator
|
||||
|
||||
int savefile_fd = open(full_filename_path, O_WRONLY | O_CREAT, 0644);
|
||||
|
||||
ssize_t bytes_transferred;
|
||||
size_t receved_this_read_cicle = SIZE_MAX;
|
||||
size_t total_received = 0;
|
||||
char* read_buffer = malloc(READ_BUFFER_SIZE);
|
||||
while (receved_this_read_cicle != 0 && total_received < MAX_FILE_SIZE){
|
||||
receved_this_read_cicle = 0;
|
||||
while ((bytes_transferred = read(client_fd, read_buffer, READ_BUFFER_SIZE - receved_this_read_cicle)) > 0) {
|
||||
if (bytes_transferred == -1) {
|
||||
fprintf(stderr, YELLOW"["RED"CRITICAL"YELLOW"]"RESET" Error: %s, when receving file: %s failed file may be corupted\n", strerror(errno) ,full_filename_path);
|
||||
goto client_cleanup;
|
||||
}
|
||||
receved_this_read_cicle += bytes_transferred;
|
||||
}
|
||||
if (receved_this_read_cicle == 0) {break;}
|
||||
|
||||
total_received += receved_this_read_cicle;
|
||||
|
||||
if (write(savefile_fd, read_buffer, receved_this_read_cicle) == -1) {
|
||||
fprintf(stderr, YELLOW"["RED"CRITICAL"YELLOW"]"RESET" Error: %s, when writing file: %s failed file may be corupted\n", strerror(errno) ,full_filename_path);
|
||||
}}
|
||||
client_cleanup:
|
||||
|
||||
printf("finished handling: %s\n",full_filename_path);
|
||||
free(read_buffer);
|
||||
free(full_filename_path);
|
||||
close(savefile_fd);
|
||||
close(client_fd);
|
||||
} else {
|
||||
printf("Rejected connection from %s\n", client_ip);
|
||||
close(client_fd);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[gnu::destructor]]
|
||||
void program_exit() {
|
||||
shutdown(sockfd, SHUT_RDWR);
|
||||
close(sockfd);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user