Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h> // Standard Input/Output, czyli standardowe wejście-wyjście.
- #include <string.h> // Operacje na łańcuchach znaków.
- #include <stdlib.h> // Najbardziej podstawowe funkcje - exit(), malloc().
- #include <syslog.h> // Definicje dla rejestrowanie błędów systemu.
- #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> // Znajduje się na prawie każdym systemie zgodnym ze standardem POSIX (Mac OS X, Linux, itd.) i udostępnia różne makra i funkcje niezbędne
- // do tworzenia programów, które muszą korzystać z pewnych usług systemu operacyjnego.
- #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 <sys/stat.h> // Nagłówek określa strukturę danych zwracanych przez funkcje fstat (), lstat (), stat ().
- #include <utime.h> // modyfikacja czasu
- #include <limits.h> // limity systemowe (w celu pobrania PATH_MAX, czyli maksymalna dlugosc sciezki w systemie)
- /* Zmienne globalne, które zostaną wykorzystane gdy użytkownik uruchomi program bez dodatkowych opcji: '-R', '-S', '-P' */
- int sleep_time = 60; // 300 sekund = 5 minut
- int fsiz = 53670912; // 512 MB, nmap/copy
- int sig_check = 0; //`
- //********************************************************** Funkcja wyświetla błąd dla użytkownika, jeżeli źle wprowadził argumenty.
- void arg_err()
- {
- printf("\nBlad! Zle wpisales argumenty!\n");
- printf("\nPrawidlowa, przykladowa forma wywolania: 'sciezka_do_katalogu_zrodlowego' 'sciezka_do_katalogu_docelowego' '-S czas_snu' '-P prog_rozmiaru'\n\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_ISDIR(type.st_mode)) // funkcja S_ISDIR sprawdza czy sciezka jest katalogiem.
- {
- return 1;
- }
- else if(S_ISREG(type.st_mode)) // funkcja S_ISREG sprawdza czy sciezka jest plikiem regularnym.
- {
- return 0;
- }
- else // coś innego
- {
- 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
- // urochomienia demona np: demon.o sciezka_zrodlowa sciezka_docelowa -> ilość = 3
- // arg[] - argumenty programu:
- // arg[0] nazwa programu,
- // arg[1] - ścieżka do katalogu źródłowego,
- // arg[2] - ścieżka do katalogu docelowego,
- // arg[3] - wybranie przez użytkownika opcji [-S], pozwalającej wspianie liczby sekund spania demona,
- // arg[4] - liczba sekund spania demona,
- // arg[5] - Wybieramy, czy chcemy włączyć opcję [-P] - próg dzielący pliki małe od dużych.
- // arg[6] - wpisujemy próg (liczbę bajtów), dzięki któremu wiemy czy użyć kopiowania przy pomocy read/write, czy mmap/write.
- // w chwili błędnego wprowadzenia argumentów zwracane jest -1.
- 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 zaczyna 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ł czas uśpienia demona (w sekundach).
- {
- o_time = 1;
- }
- else if(strcmp(arg[i],"-P") == 0 && o_time != 1) // Jezeli napotkaliśmy na '-P' lub '-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.
- {
- //atoi() - funkcja przekształca ciąg znaków liczb będący typu char w liczbę typu int.
- sleep_time = pom;
- o_time = 2;
- }
- else if((pom = atoi(arg[i])) != 0 && o_size == 1 && o_time != 1) // Ustawiamy próg dzielący pliki małe od dużych podany przez użytkownika.
- {
- fsiz = pom;
- o_size = 2;
- }
- else // Jeżeli żaden z powyższych warunków nie został spełniony, oznacza to, że użytkownik popełnił błąd przy wprowadzaniu argumentów.
- {
- 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;
- struct stat statbuf;
- // otworz plik zrodlowy
- if ((f_source = open (inf, O_RDONLY)) < 0)
- {
- syslog(LOG_ERR, "BLAD: mmapcopy: Nie mozna otworzyc: '%s'",inf);
- return 0;
- }
- if (fstat (f_source,&statbuf) < 0)
- {
- syslog(LOG_ERR, "BLAD: mmapcopy: stat(): '%s'",inf);
- return 0;
- }
- // utworz plik wysjciowy
- if ((f_target = open (outf, O_WRONLY | O_CREAT | O_TRUNC,statbuf.st_mode)) < 0)
- {
- syslog(LOG_ERR, "BLAD: mmapcopy: Nie mozna otworzyc: '%s'",outf);
- return 0;
- }
- if ((src = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, f_source, 0)) == (caddr_t) -1)
- {
- syslog(LOG_ERR, "BLAD: mmapcopy: mmap: '%s'",inf);
- return 0;
- }
- write(f_target,src,statbuf.st_size);
- munmap(src,statbuf.st_size);
- close(f_source);
- return 1;
- }
- void list_copy(char *source,char *target){
- 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 helper_s[PATH_MAX]; // helper do przetrzymywania sciezki do zrodla
- char helper_t[PATH_MAX]; // helper do przetrzymywania sciezki do celu
- if( (dir_s = opendir(source)) ){
- // czytaj ścieżke
- while(file_s = readdir(dir_s)){
- snprintf(helper_s,PATH_MAX,"%s/%s",source,file_s->d_name);
- snprintf(helper_t,PATH_MAX,"%s/%s",target,file_s->d_name);
- stat(helper_s,&stat_s);
- if(file_s->d_type == DT_REG){
- if(stat(helper_t,&stat_t)==0){
- // jesli roznia sie data modyfikacji
- if(stat_t.st_mtime != stat_s.st_mtime){
- // jesli przekroczony zostal prog
- if(fsiz>stat_s.st_size){
- if(copy(helper_s,helper_t)==1){
- syslog(LOG_INFO, "Skopiowano plik(read/write): '%s' do '%s'", helper_s,helper_t);
- }else{
- syslog(LOG_INFO, "Nie skopiowano pliku(read/write): '%s' do '%s'", helper_s,helper_t);
- }
- }
- else{
- if(mmapcopy(helper_s,helper_t)==1){
- syslog(LOG_INFO, "Skopiowano plik (mmap): '%s' do '%s'", helper_s,helper_t);
- }else{
- syslog(LOG_INFO, "Nie skopiowano pliku (mmap): '%s' do '%s'", helper_s,helper_t);
- }
- }
- // zaktualizuj daty modyfikacji
- new_time.modtime = stat_s.st_mtime;
- utime(helper_t,&new_time);
- }
- }else{
- // jesli przekroczony zostal prog
- if(fsiz>stat_s.st_size){
- if(copy(helper_s,helper_t)==1){
- syslog(LOG_INFO, "Skopiowano plik(read/write): '%s' do '%s'", helper_s,helper_t);
- }else{
- syslog(LOG_INFO, "Nie skopiowano pliku(read/write): '%s' do '%s'", helper_s,helper_t);
- }
- }
- else{
- if(mmapcopy(helper_s,helper_t)==1){
- syslog(LOG_INFO, "Skopiowano plik (mmap): '%s' do '%s'", helper_s,helper_t);
- }else{
- syslog(LOG_INFO, "Nie skopiowano pliku (mmap): '%s' do '%s'", helper_s,helper_t);
- }
- }
- // zaktualizuj daty modyfikacji
- new_time.modtime = stat_s.st_mtime;
- utime(helper_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 pozycje niesitniejace w katalogu zrodlowym
- struct dirent *file_t; // 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 * dir_t; // wskaznik na ścieżke
- char helper_s[PATH_MAX]; //maksymalna dlugosc sciezki w linux
- char helper_t[PATH_MAX]; // maksymalna dkugosc sciezki w linux
- if((dir_t = opendir(target))!=0){
- while (file_t = readdir(dir_t)){
- if(strcmp(file_t->d_name,"..") != 0 && strcmp(file_t->d_name,".") != 0){
- snprintf(helper_s,PATH_MAX,"%s/%s",source,file_t->d_name);
- snprintf(helper_t,PATH_MAX,"%s/%s",target,file_t->d_name);
- // jesli istneije taka ścieżka w cel
- if(stat(helper_t,&stat_t)==0){
- if(check_path(stat_t) == 1){
- // jesli istnieje taka ścieżka w zrodlowym
- if(stat(helper_s,&stat_s)==0){
- if(check_path(stat_s)==1){
- delete(helper_s,helper_t);
- }
- else{
- continue;
- }
- }else{
- delete(helper_s,helper_t);
- if(rmdir(helper_t)==0){
- syslog(LOG_INFO, "Usunieto katalog: '%s'", helper_t);
- }else{
- syslog(LOG_ERR, "Niepowodzenie w usunieciu katalogu: '%s'", helper_t);
- }
- }
- }else if(check_path(stat_t)==0){
- // jesli istnieje taka ścieżka w zrodowym
- if(stat(helper_s,&stat_s)==0){
- // i jesli ona jest katalogiem
- if(check_path(stat_s) == 1){
- if(unlink(helper_t)==0){
- syslog(LOG_INFO, "Usunieto plik: '%s'", helper_t);
- }else{
- syslog(LOG_ERR, "Niepowodzenie w usunieciu pliku: '%s'", helper_t);
- }
- }
- }
- // jesli nie istnieje to usun
- else{
- if(unlink(helper_t)==0){
- syslog(LOG_INFO, "Usunieto plik: '%s'", helper_t);
- }else{
- syslog(LOG_ERR, "Niepowodzenie w usunieciu pliku: '%s'", helper_t);
- }
- }
- }else{
- syslog(LOG_ERR, "Blad: nie jest katalogiem ani plikiem: '%s' i '%s'", helper_s,helper_t);
- }
- }else{
- syslog(LOG_ERR, "Ta sciezka nie istnieje '%s'",helper_t);
- }
- }
- }
- }
- else{
- syslog(LOG_ERR, "Blad: blad sciezki: '%s' ", target);
- }
- closedir (dir_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;
- int proces; // przechowuje numer procesu potomnego, aby móc później wyłączyć 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;
- }
- int option=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 demona:\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, pierwszy argument określa nazwę procesu,
- //drugi - 'LOG_PID ' dołącza numer PID,
- //trzeci argument określa typ naszego procesu
- syslog(LOG_INFO, "Synchronizacja folderów została rozpoczeta.\n"); //wysyla informacje do logu systemowego,
- if (setsid() < 0) //setsid() zwraca PID aktualnego procesu
- {
- syslog(LOG_ERR, "Wystąpił błąd przy wysylaniu informacji do logu systemowego\n");
- exit(-1);
- }
- umask(0); //Maska jest wykorzystywana przez funkcję open() do praw dostępu.
- //********************************************************** 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);
- }
- //********************************************************** Ciało naszego demona
- while(1)
- {
- sleep(sleep_time);
- switch(sig_check)
- {
- case 0:
- syslog(LOG_INFO, "Demon wyszedl ze snu po tylu %d sekundach.\n", sleep_time);
- break;
- case 1:
- syslog(LOG_INFO, "Demon zostal obudzony po wykryciu sygnalu SIGURS1.");
- break;
- }
- delete(source,target);
- list_copy(source,target);
- syslog(LOG_INFO,"Demon zapadl w sen zimowy\n");
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement