Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma clang diagnostic push
- #pragma ide diagnostic ignored "hicpp-signed-bitwise"
- #include <utime.h> // modyfikacja czasu
- #include <string.h> // Operacje na łańcuchach znaków.
- #include <stdlib.h> // Najbardziej podstawowe funkcje - exit(), malloc().
- #include <dirent.h> // Udostępnia funkcje, makra, i struktury, które umożliwiają łatwe trawersowanie katalogów.
- #include <signal.h> // Obsługa sygnałów.
- #include <unistd.h>
- #include <limits.h> // limity systemowe
- #include <sys/types.h> // Różne typy danych.
- #include <fcntl.h> // Działanie na plikach i inne operacje.
- #include <sys/mman.h> // Deklaracje zarządzania pamięcią.
- #include <stdio.h> // Standard Input/Output, czyli standardowe wejście-wyjście.
- #include <sys/stat.h> // Nagłówek określa strukturę danych zwracanych przez funkcje fstat, stat
- #include <syslog.h> // Definicje dla rejestrowanie błędów systemu.
- /* Zmienne globalne, które zostaną wykorzystane gdy użytkownik uruchomi program bez dodatkowych opcji: '-S', '-P' */
- int sleep_time = 15;
- int fsiz = 26214400; // 25 MB
- int sig_check = 0;
- //********************************************************** Funkcja wyświetla błąd dla użytkownika, jeżeli źle wprowadził argumenty.
- void arg_err() {
- printf("\nWystapil Blad! Argumenty zostały źle wpisane\n");
- printf("\nPrawidlowe wywolanie: 'sciezka_do_katalogu_zrodlowego' 'sciezka_do_katalogu_docelowego' '-R' '-S' '-P'\n\n"
- "-R - Program skopiuje rowniez katalogi\n"
- "-S - Wpisana wartosc oznacza ilosc sekund po jakich demon wyjdzie z uspienia.\n"
- "-P - Wpisana wartosc okresla prog dzielacy pliki male od duzych.\n\n");
- }
- //********************************************************** Funkcja sprawdza czy napotkaliśmy na katalog, plik lub coś innego.
- int check_path(struct stat type)
- {
- if (S_ISREG(type.st_mode)) // funkcja S_ISREG sprawdza czy sciezka jest plikiem regularnym.
- {
- return 0;
- }
- if (S_ISDIR(type.st_mode)) // funkcja S_ISREG sprawdza czy sciezka jest plikiem regularnym.
- {
- return 1;
- }
- }
- int check_arguments(char *source, char *target, int count, char *arg[]) {
- // argumenty funkcji:
- // source - ścieżka do katalogu źródłowego
- // target - ścieżka do katalogu docelowego
- // count - ilość wywołanych argumentow w trakcie
- int i, pom, o_time = 0, o_size = 0;
- if ((count >= 3) && (count <= 8)) // sprawdzamy czy podana ilość argumentów jest poprawna
- {
- strcpy(source, arg[1]); // kopiujemy do tablicy 'sciezka_zrodlowa' ścieżkę do katalogu źródłowego
- strcpy(target, arg[2]); // kopiujemy do tablicy 'sciezka_docelowa' ścieżkę do katalogu docelowego
- for (i = 3; i < count; i++) // demon musi przyjąc minimalnie 3 argumenty, więc pętla zaSyna się od 3
- {
- if (strcmp(arg[i], "-S") == 0 && o_size !=
- 1) // Jeżeli kolejny argument zaczyna się na '-S' oznacza to, że użytkownik w następnym argumencie podał Sas uśpienia demona (w sekundach).
- {
- o_time = 1;
- } else if (strcmp(arg[i], "-P") == 0 && o_time !=
- 1) // Jezeli napotkaliśmy na '-P' oznacza to, że kolejnym argumentem jest liczba okreslająca próg oddzieląjacy małe od dużych plików.
- {
- o_size = 1;
- } else if ((pom = atoi(arg[i])) != 0 && o_time == 1 &&
- o_size != 1) // Odczytujemy ustawioną przez użytkownika ilość sekund uśpienia demona.
- {
- sleep_time = pom;
- o_time = 2;
- } else if ((pom = atoi(arg[i])) != 0 && o_size == 1 &&
- o_time != 1) // Próg oddziela pliki duże od małych
- {
- fsiz = pom;
- o_size = 2;
- } else {
- arg_err();
- }
- }
- if (o_size == 1 || o_time ==
- 1) // Jeżeli po wystąpieniu '-S' lub'-P' użytkownik nie wprowadził żadnej liczby, zwracany jest błąd.
- {
- arg_err();
- return -1;
- }
- } else // Jeżeli została podana zła liczba argumentów, wyświetl błąd.
- {
- arg_err();
- return -1;
- }
- }
- //********************************************************** Odebranie syngału - SIGURS1, aby natychmiast obudzić demona.
- void signal_handling(int sig_check) {
- syslog(LOG_INFO, "Demon odebral sygnal SIGURS1\n");
- sig_check = 1;
- }
- int copy(char *inf, char *outf) {
- ssize_t output, input;
- struct stat stat_s;
- const int buff = 4096;
- int buffer[buff];
- int f_source, f_target;
- if ((f_source = open(inf, O_RDONLY)) < -1) {
- syslog(LOG_ERR, "BLAD: copy: Nie mozna otworzyc: '%s'", inf);
- return 0;
- }
- if (fstat(f_source, &stat_s) < 0) {
- syslog(LOG_ERR, "BLAD: copy: stat(): '%s'", inf);
- return 0;
- }
- if ((f_target = open(outf, O_WRONLY | O_CREAT | O_TRUNC, stat_s.st_mode)) < 0) {
- syslog(LOG_ERR, "BLAD: copy: Nie mozna otworzyc: '%s'", inf);
- return 0;
- }
- while ((input = read(f_source, &buffer, buff)) != 0) {
- output = write(f_target, &buffer, input);
- }
- close(f_source);
- close(f_target);
- return 1;
- }
- int mmapcopy(char *inf, char *outf) {
- int f_source, f_target;
- char *src, *dst;
- struct stat statbuf;
- // write(f_target, src, statbuf.st_size);
- // munmap(src, statbuf.st_size);
- //
- // close(f_source);
- // close(f_target);
- return 1;
- }
- void list_copy(char *source, char *target) {
- int f_source, f_target;
- char *src, *dst;
- struct stat statbuf;
- struct dirent *file_s; // info o lokacji dla zrodla
- struct stat stat_t; // info o pliku docelowym
- struct stat stat_s; // info o pliku zrodlowym
- DIR *dir_s; // wskaznik na ścieżke
- struct utimbuf new_time; // przetrzymuje nowa date modyfikacji
- char tmp_s[PATH_MAX]; // tmp do przetrzymywania sciezki zrodla
- char tmp_t[PATH_MAX]; // tmp do przetrzymywania sciezki celu
- if ((dir_s = opendir(source))) {
- // czytaj ścieżke
- while (file_s = readdir(dir_s)) {
- snprintf(tmp_s, PATH_MAX, "%s/%s", source, file_s->d_name);
- snprintf(tmp_t, PATH_MAX, "%s/%s", target, file_s->d_name);
- stat(tmp_s, &stat_s);
- if (file_s->d_type == DT_REG) { //
- if (stat(tmp_t, &stat_t) != 0) {
- if (fsiz > stat_s.st_size) {
- if (copy(tmp_s, tmp_t) == 1) {
- syslog(LOG_INFO, "Skopiowano: '%s' do '%s'", tmp_s, tmp_t);
- } else {
- syslog(LOG_INFO, "Nie skopiowano: '%s' do '%s'", tmp_s, tmp_t);
- }
- } else {
- if (mmapcopy(tmp_s, tmp_t) == 1) {
- write(f_target, src, statbuf.st_size);
- munmap(src, statbuf.st_size);
- close(f_source);
- close(f_target);
- syslog(LOG_INFO, "(mmap) Skopiowano plik: '%s' do '%s'", tmp_s, tmp_t);
- } else {
- syslog(LOG_INFO, "(mmap) Nie skopiowano pliku : '%s' do '%s'", tmp_s, tmp_t);
- }
- }
- new_time.modtime = stat_s.st_mtime;
- utime(tmp_t, &new_time);
- }
- }
- }
- } else {
- syslog(LOG_INFO, "Niepowodzenie w otworzeniu sciezki: '%s', '%s'", source, target);
- }
- closedir(dir_s);
- }
- void delete(char *source, char *target) { // usuwa pliki nieistniejace w katalogu zrodlowym
- struct dirent *dest; // info o lokacji dla celu
- struct dirent *file_s; // info o lokacji dla zrodla
- struct stat stat_s; // info o pliku zrodlowym
- struct stat stat_t; // info o pliku docelowym
- DIR *path_t; // wskaznik na ścieżke
- char tmp_s[PATH_MAX]; //maksymalna dlugosc sciezki w linux
- char tmp_t[PATH_MAX]; // maksymalna dkugosc sciezki w linux
- if ((path_t = opendir(target)) != 0) {
- while (dest = readdir(path_t)){
- if (strcmp(dest->d_name, ".") || strcmp(dest->d_name, "..")) {
- snprintf(tmp_s, PATH_MAX, "%s/%s", source, dest->d_name);
- snprintf(tmp_t, PATH_MAX, "%s/%s", target, dest->d_name);
- if (stat(tmp_t, &stat_t) == 0) {
- if (check_path(stat_t) == 0) {
- if (stat(tmp_s, &stat_s) == 0) {
- } else {
- if (unlink(tmp_t) == 0) {
- syslog(LOG_INFO, "Usunieto plik: '%s'", tmp_t);
- } else {
- syslog(LOG_ERR, "Nie udalo sie usunac pliku: '%s'", tmp_t);
- }
- }
- }
- } else {
- syslog(LOG_ERR, "Podana sciezka nie istnieje '%s'", tmp_t);
- }
- }
- }
- }
- else{
- syslog(LOG_ERR, "Blad sciezki: '%s' ", target);
- }
- closedir (path_t);
- }
- int main(int argc, char **argv) {
- char source[PATH_MAX]; // przechowuje ścieżkę do folderu zrodlowego
- char target[PATH_MAX]; // przechowuje ścieżkę do folderu docelowego
- struct stat zrodlowa_status; // przechowuje status pliku/folderu wskazywanego przez source[PATH_MAX]
- struct stat docelowa_status; // przechowuje status pliku/folderu wskazywanego przez target[PATH_MAX]
- struct sigaction new_action, old_action;
- pid_t pid,sid;
- int proces; // przechowuje numer procesu potomnego, aby móc później wyłąSyć demona komendą kill
- //********************************************************** Sprawdzenie podanych argumentów dla demona
- if (check_arguments(source, target, argc, argv) == -1) {
- exit(-1);
- }
- //********************************************************** Sprawdzenie poprawności ścieżek
- if (lstat(source, &zrodlowa_status) !=0) // Funkcja lstat() sprawdza istnienie scieżki o nazwie zapisanej w 'sciezka_zrodlowa' dzięki zmiennej środowiskowej path.
- { // W przypadku sukcesu zwraca 0, a w przypadku błędu -1.
- // W przypadku sukcesu lstat() zwraca status pliku znajdującego się pod 'sciezka_zrodlowa' do zmiennej zrodlowa_status.
- printf("Blad, podana sciezka zrodlowa: '%s' nie istnieje!\n", source);
- exit(-1);
- }
- if (lstat(target, &docelowa_status) != 0) {
- printf("Blad, podana sciezka docelowa: '%s' nie istnieje!\n", target);
- exit(-1);
- }
- //********************************************************** Sprawdzenie czy podane ścieżki są katalogami
- if (check_path(zrodlowa_status) != 1) // Sprawdzamy czy podana scieżka źródłowa jest folderem.
- {
- printf("Blad, podana sciezka zrodlowa: '%s' nie jest katalogiem!\n", source);
- exit(-1);
- }
- if (check_path(docelowa_status) != 1) // Sprawdzamy czy podana ścieżka docelowa jest folderem.
- {
- printf("Blad, podana sciezka docelowa: '%s' nie jest katalogiem!\n", target);
- exit(-1);
- }
- //Proces potomny
- pid = fork(); // Tworzenie procesu potomnego
- if (pid < 0) {
- printf("Blad utworzenia procesu potomnego\n");
- exit(-1);
- }
- // Proces macierzysty
- if (pid > 0) {
- return 0;
- }
- // Proces potomny,
- if (pid == 0) {
- proces = getpid(); // Zmiennej 'proces' przypisujemy numer procesu potomnego, aby zakończyć pracę demona poleceniem 'kill'.
- printf("Demon zostal uruchomiony\n");
- printf("\nArgumenty:\n -S:\t%d Sekund\n -P:\t%d Bajtów\n \n", sleep_time, fsiz);
- printf("Numer procesu: %d\nAby zakonczyc prace demona uzyj polecenia: kill <nr_procesu>\nAby wykorzystac SIGUSR1 uzyj polecenia: kill -s 10 <nr_procesu>\n",
- proces);
- //********************************************************** Inicjalizacja logu systemowego
- openlog("demon", LOG_PID, LOG_DAEMON); //wpis do logu systemowego
- syslog(LOG_INFO, "Demon synchronizujacy zostal uruchomiony.\n"); //wysyla informacje do logu systemowego,
- sid=setsid();
- if (sid < 0) //setsid() zwraca PID aktualnego procesu
- {
- syslog(LOG_ERR, "Wystąpił błąd przy wysylaniu informacji do logu systemowego\n");
- exit(-1);
- }
- umask(0);
- //********************************************************** Inicjalizacja przerwania systemowgo
- new_action.sa_handler = signal_handling;
- sigfillset(&new_action.sa_mask);
- new_action.sa_flags = 0;
- if (sigaction(SIGUSR1, &new_action, &old_action) < 0) {
- syslog(LOG_ERR, "Wystapil blad z obsluga sygnalu SIGUSR1.\n");
- exit(-1);
- }
- while (1) {
- switch (sig_check) {
- case 0:
- syslog(LOG_INFO, "Demon wybudził się po %d sekundach.\n", sleep_time);
- break;
- case 1:
- syslog(LOG_INFO, "Wykryto SIGUSR1- Demon zostaje wybudzony.");
- break;
- }
- delete(source, target);
- list_copy(source, target);
- syslog(LOG_INFO, "Demon wykonał synchronizacje, przechodzi w stan uśpienia\n");
- sleep(sleep_time);
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement