int main(int argc, char *argv[]) { /*Prepare to exit */ signal(SIGINT, exit_signal_handler); // TODO: AteXIT fun! atexit(before_exit); /* Reading configuration */ configure_data(); /* Creating, binding and listening on socket */ struct sockaddr_in sa_server; sa_server.sin_family = AF_INET; sa_server.sin_addr.s_addr = INADDR_ANY; sa_server.sin_port = htons(port); server_socket = socket(AF_INET, SOCK_STREAM, 0); if (bind(server_socket, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0) error("inet bind"); if(listen(server_socket, SOMAXCONN) < 0) error("listen inet"); /* FD set */ fd_set read_set; FD_ZERO(&set); FD_SET(server_socket, &set); fd_hwm = server_socket; struct message message; int new_client; while(is_working) { read_set = set; if (select(fd_hwm + 1, &read_set, NULL, NULL, NULL) < 0) error("select"); for (int fd = 0; fd <= fd_hwm; fd++) { if(FD_ISSET(fd, &read_set)) { /* If this is new connection to accept*/ if (fd == server_socket) { new_client = accept(fd, NULL, 0); FD_SET(new_client, &set); fd_hwm = new_client > fd_hwm ? new_client : fd_hwm; } /* If this client is ready to read from him */ else { recv(fd, &message, sizeof(message), 0); char *file_name = message.file.file_name; char *normalized_name = calloc(strlen(file_name) + strlen(backup_main_path), sizeof(char)); strcpy(normalized_name, backup_main_path); strcat(normalized_name, file_name); if (message.type == NEW_FILE) { time(&last_client_push); receive_file_from_socket(fd, normalized_name, message.file); confirm_received(fd); } else if(message.type == NEW_DIR) { time(&last_client_push); receive_dir_from_socket(fd, normalized_name, message.file); confirm_received(fd); } else if(message.type == PULL_REQUEST) { current_socket = fd; current_time = message.last_update_time; if (difftime(last_client_push, current_time) > FILE_DIFF); ftw(backup_main_path, check_updates, 16); } else if(message.type == DISCONNECT) { FD_CLR(fd, &set); } free(normalized_name); message.type = E; } } } } }
int backup_client(char*ipaddr, int port, char*clientpath) /* Purpose:Backup the path of a specific client. Receive the archives. Store them locally (on me, the server). Params: clientno - client# in g_clientlist[] clientpath - client's path to be backed up Return: result (0=success, nonzero=failure) */ { struct s_server2client_msg_record rec_to_client; int res=0, socket_fd, noof_archives, i, len; char tmp[MAX_STR_LEN+1], outfile[MAX_STR_LEN+1]; FILE*fout; log_it(info, "%s - backup of %s commencing", ipaddr, clientpath); sprintf(outfile, "/var/spool/monitas/%s/%lu.dat", ipaddr, time(NULL)); if (does_file_exist(outfile)) { log_it(error, "Backup storage location '%s' exists already. That should be impossible.", outfile); return(1); } if (make_hole_for_file(outfile)) { res++; log_it(error, "Cannot write archive to spool dir '%s'", outfile); } else if (!(fout=fopen(outfile, "w"))) { res++; log_it(fatal, "Failed to openout temp data file '%s'", outfile); } else { log_it(debug, "Backing up %s - archive=%s", ipaddr, outfile); rec_to_client.msg_type = trigger_backup; strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) { log_it(error, "backup_client - failed to send msg to client"); return(1); } res += receive_file_from_socket(fout, socket_fd); len=read(socket_fd, (char*)&i, sizeof(i)); if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondoarchive"); } else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondoarchive"); } else if (i) { res++; log_it(error, "Client said, mondoarchive returned an error."); } else { log_it(debug, "Client said, mondoarchive returned OK"); } fclose(fout); close(socket_fd); } /* Shuffle older backups off the mortal coil. Leave maximum of 4 backup files in /var/spool/monitas/[ipaddr] */ sprintf(tmp, "find /var/spool/monitas/%s -type f 2> /dev/null | grep -n \"\" | tail -n1 | cut -d':' -f1", ipaddr); noof_archives = atoi(call_program_and_get_last_line_of_output(tmp)); i = noof_archives - 3; if (i>0) { sprintf(tmp, "rm -f `find /var/spool/monitas/%s -type f | sort | head -n%d`", ipaddr, i); call_program_and_log_output(tmp); } /* Return success/failure value */ if (res>0) { log_it(error, "%s - error(s) occurred while backing up %s", ipaddr, clientpath); rec_to_client.msg_type = backup_fail; sprintf(rec_to_client.body, "Failed to backup %s", clientpath); log_it(debug, rec_to_client.body); unlink(outfile); } else { log_it(info, "%s - backed up %s ok", ipaddr, clientpath); rec_to_client.msg_type = backup_ok; sprintf(rec_to_client.body, "%s - backed up ok", clientpath); log_it(debug, rec_to_client.body); } if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) { res++; log_it(error, "Unable to notify %s of backup success/failure", ipaddr); i = find_client_in_clientlist(ipaddr); if (i>=0) { forcibly_logout_client(i); } log_it(info, "I'm assuming the backup was bad because the client cannot be reached."); unlink(outfile); } return(res); }