Advertisement
Guest User

Untitled

a guest
May 22nd, 2019
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.75 KB | None | 0 0
  1. #include <stdio.h> // Standard Input/Output, czyli standardowe wejście-wyjście.
  2. #include <string.h> // Operacje na łańcuchach znaków.
  3. #include <stdlib.h> // Najbardziej podstawowe funkcje - exit(), malloc().
  4. #include <syslog.h> // Definicje dla rejestrowanie błędów systemu.
  5. #include <dirent.h> // Udostępnia funkcje, makra, i struktury, które umożliwiają łatwe trawersowanie katalogów.
  6. #include <signal.h> // Obsługa sygnałów.
  7. #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
  8. // do tworzenia programów, które muszą korzystać z pewnych usług systemu operacyjnego.
  9. #include <sys/types.h> // Różne typy danych.
  10. #include <fcntl.h> // Działanie na plikach i inne operacje.
  11. #include <sys/mman.h> // Deklaracje zarządzania pamięcią.
  12. #include <sys/stat.h> // Nagłówek określa strukturę danych zwracanych przez funkcje fstat (), lstat (), stat ().
  13. #include <utime.h> // modyfikacja czasu
  14. #include <limits.h> // limity systemowe (w celu pobrania PATH_MAX, czyli maksymalna dlugosc sciezki w systemie)
  15.  
  16.  
  17.  
  18. /* Zmienne globalne, które zostaną wykorzystane gdy użytkownik uruchomi program bez dodatkowych opcji: '-R', '-S', '-P' */
  19.  
  20. int sleep_time = 60; // 300 sekund = 5 minut
  21. int fsiz = 53670912; // 512 MB, nmap/copy
  22. int sig_check = 0; //`
  23. //********************************************************** Funkcja wyświetla błąd dla użytkownika, jeżeli źle wprowadził argumenty.
  24.  
  25. void arg_err()
  26. {
  27. printf("\nBlad! Zle wpisales argumenty!\n");
  28. printf("\nPrawidlowa, przykladowa forma wywolania: 'sciezka_do_katalogu_zrodlowego' 'sciezka_do_katalogu_docelowego' '-S czas_snu' '-P prog_rozmiaru'\n\n"
  29.  
  30. "-S - Wpisana wartosc oznacza ilosc sekund po jakich demon wyjdzie z uspienia.\n"
  31. "-P- Wpisana wartosc okresla prog dzielacy pliki male od duzych.\n\n");
  32. }
  33.  
  34. //********************************************************** Funkcja sprawdza czy napotkaliśmy na katalog, plik lub coś innego.
  35.  
  36.  
  37. int check_path(struct stat type)
  38. {
  39. if(S_ISDIR(type.st_mode)) // funkcja S_ISDIR sprawdza czy sciezka jest katalogiem.
  40. {
  41. return 1;
  42. }
  43. else if(S_ISREG(type.st_mode)) // funkcja S_ISREG sprawdza czy sciezka jest plikiem regularnym.
  44. {
  45. return 0;
  46. }
  47. else // coś innego
  48. {
  49. return -1;
  50. }
  51.  
  52. }
  53.  
  54. int check_arguments(char *source, char *target, int count, char *arg[])
  55. {
  56. // argumenty funkcji:
  57. // source - ścieżka do katalogu źródłowego
  58. // target - ścieżka do katalogu docelowego
  59. // count - ilość wywołanych argumentow w trakcie
  60. // urochomienia demona np: demon.o sciezka_zrodlowa sciezka_docelowa -> ilość = 3
  61. // arg[] - argumenty programu:
  62. // arg[0] nazwa programu,
  63. // arg[1] - ścieżka do katalogu źródłowego,
  64. // arg[2] - ścieżka do katalogu docelowego,
  65. // arg[3] - wybranie przez użytkownika opcji [-S], pozwalającej wspianie liczby sekund spania demona,
  66. // arg[4] - liczba sekund spania demona,
  67. // arg[5] - Wybieramy, czy chcemy włączyć opcję [-P] - próg dzielący pliki małe od dużych.
  68. // arg[6] - wpisujemy próg (liczbę bajtów), dzięki któremu wiemy czy użyć kopiowania przy pomocy read/write, czy mmap/write.
  69. // w chwili błędnego wprowadzenia argumentów zwracane jest -1.
  70.  
  71. int i, pom, o_time = 0, o_size = 0;
  72.  
  73. if((count >= 3) && (count <= 8)) // sprawdzamy czy podana ilość argumentów jest poprawna
  74. {
  75.  
  76. strcpy(source, arg[1]); // kopiujemy do tablicy 'sciezka_zrodlowa' ścieżkę do katalogu źródłowego
  77. strcpy(target, arg[2]); // kopiujemy do tablicy 'sciezka_docelowa' ścieżkę do katalogu docelowego
  78.  
  79. for(i = 3 ; i < count ; i++) // demon musi przyjąc minimalnie 3 argumenty, więc pętla zaczyna się od 3
  80. {
  81.  
  82.  
  83. 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).
  84. {
  85. o_time = 1;
  86. }
  87.  
  88. 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.
  89. {
  90. o_size = 1;
  91. }
  92.  
  93. else if((pom = atoi(arg[i])) != 0 && o_time == 1 && o_size != 1 ) // Odczytujemy ustawioną przez użytkownika ilość sekund uśpienia demona.
  94. {
  95. //atoi() - funkcja przekształca ciąg znaków liczb będący typu char w liczbę typu int.
  96. sleep_time = pom;
  97. o_time = 2;
  98. }
  99.  
  100. 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.
  101. {
  102. fsiz = pom;
  103. o_size = 2;
  104. }
  105.  
  106. 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.
  107. {
  108. arg_err();
  109. }
  110. }
  111.  
  112. 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.
  113. {
  114. arg_err();
  115. return -1;
  116. }
  117.  
  118. }
  119. else // Jeżeli została podana zła liczba argumentów, wyświetl błąd.
  120. {
  121. arg_err();
  122. return -1;
  123. }
  124. }
  125.  
  126.  
  127. //********************************************************** Odebranie syngału - SIGURS1, aby natychmiast obudzić demona.
  128.  
  129. void signal_handling(int sig_check)
  130. {
  131. syslog(LOG_INFO, "Demon odebral sygnal SIGURS1\n");
  132. sig_check = 1;
  133. }
  134.  
  135. int copy (char *inf, char * outf){
  136. ssize_t output,input;
  137. struct stat stat_s;
  138. const int buff = 4096;
  139. int buffer[buff];
  140. int f_source,f_target;
  141.  
  142. if((f_source = open(inf,O_RDONLY)) < -1){
  143. syslog(LOG_ERR, "BLAD: copy: Nie mozna otworzyc: '%s'",inf);
  144. return 0;
  145. }
  146.  
  147. if (fstat (f_source,&stat_s) < 0)
  148. {
  149. syslog(LOG_ERR, "BLAD: copy: stat(): '%s'",inf);
  150. return 0;
  151. }
  152.  
  153. if((f_target = open(outf,O_WRONLY | O_CREAT | O_TRUNC,stat_s.st_mode)) < 0){
  154. syslog(LOG_ERR, "BLAD: copy: Nie mozna otworzyc: '%s'",inf);
  155. return 0;
  156. }
  157. while ((input = read(f_source,&buffer,buff)) != 0){
  158. output = write(f_target,&buffer,input);
  159. }
  160. close(f_source);
  161. close(f_target);
  162. return 1;
  163. }
  164. int mmapcopy(char *inf, char * outf){
  165.  
  166. int f_source, f_target;
  167. char *src;
  168. struct stat statbuf;
  169.  
  170.  
  171.  
  172. // otworz plik zrodlowy
  173. if ((f_source = open (inf, O_RDONLY)) < 0)
  174. {
  175. syslog(LOG_ERR, "BLAD: mmapcopy: Nie mozna otworzyc: '%s'",inf);
  176. return 0;
  177. }
  178. if (fstat (f_source,&statbuf) < 0)
  179. {
  180. syslog(LOG_ERR, "BLAD: mmapcopy: stat(): '%s'",inf);
  181. return 0;
  182. }
  183. // utworz plik wysjciowy
  184. if ((f_target = open (outf, O_WRONLY | O_CREAT | O_TRUNC,statbuf.st_mode)) < 0)
  185. {
  186. syslog(LOG_ERR, "BLAD: mmapcopy: Nie mozna otworzyc: '%s'",outf);
  187. return 0;
  188. }
  189.  
  190. if ((src = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, f_source, 0)) == (caddr_t) -1)
  191. {
  192. syslog(LOG_ERR, "BLAD: mmapcopy: mmap: '%s'",inf);
  193. return 0;
  194. }
  195.  
  196. write(f_target,src,statbuf.st_size);
  197. munmap(src,statbuf.st_size);
  198.  
  199. close(f_source);
  200.  
  201. return 1;
  202. }
  203. void list_copy(char *source,char *target){
  204. struct dirent *file_s; // info o lokacji dla zrodla
  205.  
  206. struct stat stat_t; // info o pliku docelowym
  207. struct stat stat_s; // info o pliku zrodlowym
  208. DIR * dir_s; // wskaznik na ścieżke
  209. struct utimbuf new_time; // przetrzymuje nowa date modyfikacji
  210.  
  211. char helper_s[PATH_MAX]; // helper do przetrzymywania sciezki do zrodla
  212. char helper_t[PATH_MAX]; // helper do przetrzymywania sciezki do celu
  213.  
  214.  
  215. if( (dir_s = opendir(source)) ){
  216. // czytaj ścieżke
  217. while(file_s = readdir(dir_s)){
  218. snprintf(helper_s,PATH_MAX,"%s/%s",source,file_s->d_name);
  219. snprintf(helper_t,PATH_MAX,"%s/%s",target,file_s->d_name);
  220.  
  221. stat(helper_s,&stat_s);
  222.  
  223. if(file_s->d_type == DT_REG){
  224. if(stat(helper_t,&stat_t)==0){
  225. // jesli roznia sie data modyfikacji
  226. if(stat_t.st_mtime != stat_s.st_mtime){
  227. // jesli przekroczony zostal prog
  228. if(fsiz>stat_s.st_size){
  229. if(copy(helper_s,helper_t)==1){
  230. syslog(LOG_INFO, "Skopiowano plik(read/write): '%s' do '%s'", helper_s,helper_t);
  231. }else{
  232. syslog(LOG_INFO, "Nie skopiowano pliku(read/write): '%s' do '%s'", helper_s,helper_t);
  233. }
  234. }
  235. else{
  236. if(mmapcopy(helper_s,helper_t)==1){
  237. syslog(LOG_INFO, "Skopiowano plik (mmap): '%s' do '%s'", helper_s,helper_t);
  238. }else{
  239. syslog(LOG_INFO, "Nie skopiowano pliku (mmap): '%s' do '%s'", helper_s,helper_t);
  240. }
  241. }
  242. // zaktualizuj daty modyfikacji
  243. new_time.modtime = stat_s.st_mtime;
  244. utime(helper_t,&new_time);
  245.  
  246. }
  247.  
  248. }else{
  249. // jesli przekroczony zostal prog
  250. if(fsiz>stat_s.st_size){
  251. if(copy(helper_s,helper_t)==1){
  252. syslog(LOG_INFO, "Skopiowano plik(read/write): '%s' do '%s'", helper_s,helper_t);
  253. }else{
  254. syslog(LOG_INFO, "Nie skopiowano pliku(read/write): '%s' do '%s'", helper_s,helper_t);
  255. }
  256. }
  257. else{
  258. if(mmapcopy(helper_s,helper_t)==1){
  259. syslog(LOG_INFO, "Skopiowano plik (mmap): '%s' do '%s'", helper_s,helper_t);
  260. }else{
  261. syslog(LOG_INFO, "Nie skopiowano pliku (mmap): '%s' do '%s'", helper_s,helper_t);
  262. }
  263. }
  264. // zaktualizuj daty modyfikacji
  265. new_time.modtime = stat_s.st_mtime;
  266. utime(helper_t,&new_time);
  267. }
  268. }
  269. }
  270. }else{
  271. syslog(LOG_INFO, "Niepowodzenie w otworzeniu sciezki: '%s', '%s'", source,target);
  272. }
  273.  
  274. closedir(dir_s);
  275. }
  276.  
  277. void delete(char * source, char *target){
  278. // usuwa pozycje niesitniejace w katalogu zrodlowym
  279. struct dirent *file_t; // info o lokacji dla celu
  280. struct dirent *file_s; // info o lokacji dla zrodla
  281. struct stat stat_s; // info o pliku zrodlowym
  282. struct stat stat_t; // info o pliku docelowym
  283. DIR * dir_t; // wskaznik na ścieżke
  284. char helper_s[PATH_MAX]; //maksymalna dlugosc sciezki w linux
  285. char helper_t[PATH_MAX]; // maksymalna dkugosc sciezki w linux
  286. if((dir_t = opendir(target))!=0){
  287. while (file_t = readdir(dir_t)){
  288. if(strcmp(file_t->d_name,"..") != 0 && strcmp(file_t->d_name,".") != 0){
  289. snprintf(helper_s,PATH_MAX,"%s/%s",source,file_t->d_name);
  290. snprintf(helper_t,PATH_MAX,"%s/%s",target,file_t->d_name);
  291. // jesli istneije taka ścieżka w cel
  292. if(stat(helper_t,&stat_t)==0){
  293. if(check_path(stat_t) == 1){
  294. // jesli istnieje taka ścieżka w zrodlowym
  295. if(stat(helper_s,&stat_s)==0){
  296. if(check_path(stat_s)==1){
  297. delete(helper_s,helper_t);
  298. }
  299. else{
  300. continue;
  301. }
  302.  
  303. }else{
  304. delete(helper_s,helper_t);
  305. if(rmdir(helper_t)==0){
  306. syslog(LOG_INFO, "Usunieto katalog: '%s'", helper_t);
  307. }else{
  308. syslog(LOG_ERR, "Niepowodzenie w usunieciu katalogu: '%s'", helper_t);
  309. }
  310. }
  311. }else if(check_path(stat_t)==0){
  312. // jesli istnieje taka ścieżka w zrodowym
  313. if(stat(helper_s,&stat_s)==0){
  314. // i jesli ona jest katalogiem
  315. if(check_path(stat_s) == 1){
  316. if(unlink(helper_t)==0){
  317. syslog(LOG_INFO, "Usunieto plik: '%s'", helper_t);
  318. }else{
  319. syslog(LOG_ERR, "Niepowodzenie w usunieciu pliku: '%s'", helper_t);
  320. }
  321. }
  322. }
  323. // jesli nie istnieje to usun
  324. else{
  325. if(unlink(helper_t)==0){
  326. syslog(LOG_INFO, "Usunieto plik: '%s'", helper_t);
  327. }else{
  328. syslog(LOG_ERR, "Niepowodzenie w usunieciu pliku: '%s'", helper_t);
  329. }
  330. }
  331. }else{
  332. syslog(LOG_ERR, "Blad: nie jest katalogiem ani plikiem: '%s' i '%s'", helper_s,helper_t);
  333. }
  334. }else{
  335. syslog(LOG_ERR, "Ta sciezka nie istnieje '%s'",helper_t);
  336. }
  337. }
  338. }
  339. }
  340. else{
  341. syslog(LOG_ERR, "Blad: blad sciezki: '%s' ", target);
  342. }
  343. closedir (dir_t);
  344. }
  345.  
  346. int main(int argc, char **argv)
  347. {
  348. char source[PATH_MAX]; // przechowuje ścieżkę do folderu zrodlowego
  349. char target[PATH_MAX]; // przechowuje ścieżkę do folderu docelowego
  350.  
  351. struct stat zrodlowa_status; // przechowuje status pliku/folderu wskazywanego przez source[PATH_MAX]
  352. struct stat docelowa_status; // przechowuje status pliku/folderu wskazywanego przez target[PATH_MAX]
  353.  
  354. struct sigaction new_action, old_action;
  355.  
  356. pid_t pid;
  357.  
  358. int proces; // przechowuje numer procesu potomnego, aby móc później wyłączyć demona komendą kill
  359.  
  360.  
  361. //********************************************************** Sprawdzenie podanych argumentów dla demona
  362.  
  363. if(check_arguments(source, target, argc, argv) == -1)
  364. {
  365. exit(-1);
  366. }
  367.  
  368. //********************************************************** Sprawdzenie poprawności ścieżek
  369.  
  370. if(lstat(source, &zrodlowa_status) != 0) // Funkcja lstat() sprawdza istnienie scieżki o nazwie zapisanej w 'sciezka_zrodlowa' dzięki zmiennej środowiskowej path.
  371. { // W przypadku sukcesu zwraca 0, a w przypadku błędu -1.
  372. // W przypadku sukcesu lstat() zwraca status pliku znajdującego się pod 'sciezka_zrodlowa' do zmiennej zrodlowa_status.
  373. printf("Blad, podana sciezka zrodlowa: '%s' nie istnieje!\n", source);
  374. exit(-1);
  375. }
  376.  
  377. if(lstat(target, &docelowa_status) != 0)
  378. {
  379. printf("Blad, podana sciezka docelowa: '%s' nie istnieje!\n", target);
  380. exit(-1);
  381. }
  382.  
  383.  
  384. //********************************************************** Sprawdzenie czy podane ścieżki są katalogami
  385.  
  386.  
  387. if(check_path(zrodlowa_status) != 1) // Sprawdzamy czy podana scieżka źródłowa jest folderem.
  388. {
  389. printf("Blad, podana sciezka zrodlowa: '%s' nie jest katalogiem!\n", source);
  390. exit(-1);
  391. }
  392.  
  393. if(check_path(docelowa_status) != 1) // Sprawdzamy czy podana ścieżka docelowa jest folderem.
  394. {
  395. printf("Blad, podana sciezka docelowa: '%s' nie jest katalogiem!\n", target);
  396. exit(-1);
  397. }
  398.  
  399.  
  400.  
  401. //********************************************************** Proces potomny
  402.  
  403. pid = fork(); // Tworzenie procesu potomnego
  404.  
  405. if(pid < 0)
  406. {
  407. printf("Blad utworzenia procesu potomnego!\n");
  408. exit(-1);
  409. }
  410.  
  411. // Proces macierzysty
  412. if(pid > 0)
  413. {
  414. return 0;
  415. }
  416.  
  417.  
  418.  
  419. int option=0;
  420.  
  421.  
  422. // Proces potomny,
  423. if(pid == 0)
  424. {
  425. proces = getpid(); // Zmiennej 'proces' przypisujemy numer procesu potomnego, aby zakończyć pracę demona poleceniem 'kill'.
  426. printf("Demon zostal uruchomiony\n");
  427. printf("\nArgumenty demona:\n -S:\t%d Sekund\n -P:\t%d Bajtów\n \n", sleep_time, fsiz);
  428. 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);
  429.  
  430. //********************************************************** Inicjalizacja logu systemowego
  431.  
  432. openlog("demon", LOG_PID, LOG_DAEMON); //wpis do logu systemowego, pierwszy argument określa nazwę procesu,
  433. //drugi - 'LOG_PID ' dołącza numer PID,
  434. //trzeci argument określa typ naszego procesu
  435.  
  436. syslog(LOG_INFO, "Synchronizacja folderów została rozpoczeta.\n"); //wysyla informacje do logu systemowego,
  437.  
  438. if (setsid() < 0) //setsid() zwraca PID aktualnego procesu
  439. {
  440. syslog(LOG_ERR, "Wystąpił błąd przy wysylaniu informacji do logu systemowego\n");
  441. exit(-1);
  442. }
  443. umask(0); //Maska jest wykorzystywana przez funkcję open() do praw dostępu.
  444.  
  445.  
  446.  
  447. //********************************************************** Inicjalizacja przerwania systemowgo
  448.  
  449. new_action.sa_handler = signal_handling;
  450. sigfillset(&new_action.sa_mask);
  451. new_action.sa_flags = 0;
  452.  
  453. if(sigaction(SIGUSR1, &new_action, &old_action) < 0)
  454. {
  455. syslog(LOG_ERR, "Wystapil blad z obsluga sygnalu SIGUSR1.\n");
  456. exit(-1);
  457. }
  458.  
  459. //********************************************************** Ciało naszego demona
  460.  
  461.  
  462. while(1)
  463. {
  464. sleep(sleep_time);
  465. switch(sig_check)
  466. {
  467. case 0:
  468. syslog(LOG_INFO, "Demon wyszedl ze snu po tylu %d sekundach.\n", sleep_time);
  469. break;
  470. case 1:
  471. syslog(LOG_INFO, "Demon zostal obudzony po wykryciu sygnalu SIGURS1.");
  472. break;
  473. }
  474.  
  475. delete(source,target);
  476.  
  477. list_copy(source,target);
  478. syslog(LOG_INFO,"Demon zapadl w sen zimowy\n");
  479. }
  480. }
  481. return 0;
  482. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement