#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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); }