@@ -11,16 +11,21 @@ char src_path[MAX_BUFFER_SIZE] = { 0 }; // 타겟 경로
1111char  dst_path [MAX_BUFFER_SIZE ] =  { 0  }; // 동기화 경로 
1212char  swap_path [MAX_BUFFER_SIZE ] =  { 0  }; // 스왑 파일 
1313
14+ // 옵션 
1415bool  option_r  =  false; // R 옵션 
1516bool  option_t  =  false; // T 옵션 
1617bool  option_m  =  false; // M 옵션 
1718bool  is_complete  =  false; // 동기화 완료 확인 
1819
20+ // 디스크럽터 
1921int  in_fd ; // 표준 입력 
2022int  out_fd ; // 표준 출력 
2123int  err_fd ; // 표준 에러 
2224
23- change_file  change_list [BUFFER_SIZE ]; // 변경 목록 
25+ file_node  change_list [BUFFER_SIZE ]; // 변경 목록 
26+ char  * * saved_argv ;
27+ int  saved_argc ;
28+ 2429
2530/** 
2631 * @brief ssu_rsync 메인 함수 
@@ -46,14 +51,16 @@ int main(int argc, char *argv[])
4651	gettimeofday (& begin_t , NULL ); // 측정 시작 
4752
4853	if  (argc  <  3 ) { // 인자 개수가 부족할 경우 
49- 		fprintf ( stderr ,  "ssu_rsync(): Usage: %s [OPTION] <SOURCE> <DESTINATION>\n" ,  argv [0 ]);
54+ 		print_usage ( argv [0 ]);
5055		exit (1 );
5156	}
5257
5358	getcwd (pwd , MAX_BUFFER_SIZE );
5459	signal (SIGUSR1 , swap_handler );
5560	signal (SIGUSR2 , swap_handler );
5661
62+ 	copy_argument (argc , argv );
63+ 5764	for  (int  i  =  1 ; i  <  argc ; i ++ ) {
5865#ifdef  DEBUG 
5966		printf ("ssu_rsync(): argv[%d] = %s\n" , i , argv [i ]);
@@ -138,13 +145,8 @@ int main(int argc, char *argv[])
138145	}
139146
140147	// 파싱 중 에러 발견 
141- 	if  (is_invalid )
142- 		exit (1 );
143- 	else  if  (!is_src ) {
144- 		fprintf (stderr , "ssu_rsync(): <SOURCE> doesn't exist\n" );
145- 		exit (1 );
146- 	} else  if  (!is_dst ) {
147- 		fprintf (stderr , "ssu_rsync(): <DESTINATION> doesn't exist\n" );
148+ 	if  (is_invalid  ||  !is_src  ||  !is_dst ) {
149+ 		print_usage (argv [0 ]);
148150		exit (1 );
149151	}
150152
@@ -169,6 +171,21 @@ int main(int argc, char *argv[])
169171	exit (0 );
170172}
171173
174+ /** 
175+  * @brief 명령행 인자 백업  
176+  * @param argc 인자 개수 
177+  * @param argv 인자 문자열 배열 
178+  */ 
179+ void  copy_argument (int  argc , char  * argv []) // 명령행 인자 백업 
180+ {
181+ 	saved_argc  =  argc ;
182+ 	saved_argv  =  calloc (argc , sizeof (char * ));
183+ 	for (int  i  =  0 ; i  <  saved_argc ; i ++ ) {
184+ 		saved_argv [i ] =  calloc (MAX_BUFFER_SIZE , sizeof (char ));
185+ 		strcpy (saved_argv [i ], argv [i ]);
186+ 	}
187+ }
188+ 172189/** 
173190 * @brief 표준 입출력 전환 
174191 * @param signo 시그널  
@@ -221,6 +238,11 @@ void syncronize(char *src_path, char *dst_path) // 동기화 함수
221238	if  (option_m ) 
222239		change_count  =  write_change_list (dst_list -> child , change_count , DELETE , true); // 삭제 혹은 수정된 파일 확인 
223240
241+ 	//if (option_t) 
242+ 	//	refresh_tar(change_count); 
243+ 	//else 
244+ 	renewal (change_count );
245+ 224246	free_list (src_list );
225247	free_list (dst_list );
226248	is_complete  =  true;
@@ -342,8 +364,8 @@ void compare_list(file_node *src_list, file_node *dst_list) // 파일 목록 트
342364
343365		compare_file (now , dst_list );
344366
345- 		if  (now -> child  !=  NULL )
346- 			compare_list (now -> child , dst_list );
367+ 		if  (now -> child  !=  NULL )
368+ 			compare_list (now -> child , dst_list );
347369
348370		now  =  now -> next ;
349371	}
@@ -398,9 +420,9 @@ bool compare_file(file_node *src_file, file_node *dst_file) // 파일 정보 비
398420			return  true;
399421		}
400422
401- 		if (now -> child  !=  NULL ) // 디렉토리 안에 파일이 존재할 경우 
402- 			if (compare_file (src_file , now -> child )) 
403- 				break ;
423+ 		if (now -> child  !=  NULL ) // 디렉토리 안에 파일이 존재할 경우 
424+ 			if (compare_file (src_file , now -> child )) 
425+ 				break ;
404426
405427		now  =  now -> next ;
406428	}
@@ -462,6 +484,123 @@ int write_change_list(file_node *head, int idx, int status, bool is_first) // 
462484	return  idx ;
463485}
464486
487+ /** 
488+  * @brief 파일 동기화 
489+  * @param count 변경 사항 개수 
490+  */ 
491+ void  renewal (int  count ) // 파일 동기화 
492+ {
493+ 	int  src_fd , dst_fd ;
494+ 	char  path [MAX_BUFFER_SIZE ];
495+ 	char  buf [MAX_BUFFER_SIZE ];
496+ 	struct  stat  statbuf ;
497+ 	struct  utimbuf  attr ;
498+ 	size_t  length ;
499+ 500+ 	for  (int  i  =  0 ; i  <  count ; i ++ ) {
501+ 502+ 		switch  (change_list [i ].status ) {
503+ 			case  DELETE :
504+ 505+ 				lstat (change_list [i ].name , & statbuf );
506+ 				if  (S_ISDIR (statbuf .st_mode ))
507+ 					remove_directory (change_list [i ].name );
508+ 				else 
509+ 					remove (change_list [i ].name );
510+ 				break ;
511+ 512+ 			case  CREATE :
513+ 			case  MODIFY :
514+ 515+ 				memset (path , 0 , MAX_BUFFER_SIZE );
516+ 517+ 				lstat (change_list [i ].name , & statbuf );
518+ 				sprintf (path , "%.*s/%s" , (int )strlen (dst_path ), dst_path , change_list [i ].name  +  strlen (pwd ) +  1 ); // 동기화 파일 경로 생성 
519+ 520+ 				if  (S_ISDIR (statbuf .st_mode )) 
521+ 					mkdir (path , 0755 );
522+ 				else  {
523+ 					if  ((src_fd  =  open (change_list [i ].name , O_RDONLY )) <  0 ) { // 타겟 읽기 전용 열기 
524+ 						fprintf (stderr , "renewal(): open error for %s\n" , change_list [i ].name );
525+ 						break ;
526+ 					}
527+ 528+ 					if  ((dst_fd  =  open (path , O_WRONLY  | O_CREAT  | O_TRUNC , statbuf .st_mode )) <  0 ) { // 동기화 파일 열기 
529+ 						fprintf (stderr , "renewal(): open error for %s\n" , path );
530+ 						break ;
531+ 					}
532+ 533+ 					while  ((length  =  read (src_fd , buf , MAX_BUFFER_SIZE )) >  0 ) // 동기화 파일 쓰기 (새로쓰기 혹은 덮어쓰기) 
534+ 						write (dst_fd , buf , length );
535+ 536+ 					close (src_fd );
537+ 					close (dst_fd );
538+ 				}
539+ 540+ 				// 동기화 파일 속성 및 권한 복원 
541+ 				attr .actime  =  statbuf .st_atime ; 
542+ 				attr .modtime  =  statbuf .st_mtime ;
543+ 				utime (path , & attr );
544+ 				chmod (path , statbuf .st_mode );
545+ 				break ;
546+ 		}
547+ 	}
548+ 549+ 	write_log (count );
550+ }
551+ 552+ /** 
553+  * @brief 로그 파일 작성 
554+  * @param 변경 사항 개수 
555+  */ 
556+ void  write_log (int  count ) // 로그 파일 작성 
557+ {
558+ 	FILE  * fp ;
559+ 	time_t  now_t ;
560+ 	struct  tm  * now_tm ;
561+ 	char  command [MAX_BUFFER_SIZE ];
562+ 563+ 	if  (count  ==  0 ) {
564+ 		fprintf (stderr , "write_log(): up-to-date %s\n" , dst_path );
565+ 		return ;
566+ 	}
567+ 568+ 	if  ((fp  =  fopen (RSYNC_LOG , "r+" )) ==  NULL ) // 로그파일 열기 
569+ 		fp  =  fopen (RSYNC_LOG , "w" ); // 존재하지 않을 경우 생성 
570+ 571+ 	fseek (fp , 0 , SEEK_END ); 
572+ 573+ 	// 헤더 명령행 문자열 생성 
574+ 	strcpy (command , get_file_name (saved_argv [0 ]));
575+ 	for  (int  i  =  1 ; i  <  saved_argc ; i ++ ) {
576+ 		strcat (command , " " );
577+ 		strcat (command , saved_argv [i ]);
578+ 	}
579+ 580+ #ifdef  DEBUG 
581+ 	printf ("write_log(): command = %s\n" , command );
582+ #endif 
583+ 584+ 	// 헤더 시간 생성 
585+ 	time (& now_t );
586+ 	now_tm  =  localtime (& now_t );
587+ 588+ 	fprintf (fp , "[%.24s] %s\n" , asctime (now_tm ), command ); // 헤더 라인 쓰기 
589+ 590+ 	//if(option_p) 
591+ 592+ 	for  (int  i  =  0 ; i  <  count ; i ++ ) // 변경 사항 쓰기 
593+ 		switch  (change_list [i ].status ) {
594+ 			case  DELETE :
595+ 				fprintf (fp , " %s delete\n" , change_list [i ].name  +  strlen (dst_path ) +  1 );
596+ 				break ;
597+ 			case  CREATE :
598+ 			case  MODIFY :
599+ 				fprintf (fp , " %s %dbytes\n" , change_list [i ].name  +  strlen (src_path ) +  1 , change_list [i ].size );
600+ 				break ;
601+ 		}
602+ }
603+ 465604/** 
466605 * @brief 모니터링 파일 목록 메모리 할당 해제 
467606 * @param head 트리의 루트 노드 
@@ -494,15 +633,15 @@ void recovery(int signo) // SIGINT 시그널 처리
494633		if (is_complete ) // 동기화가 완료되었을 경우 
495634			return ;
496635
497- 		sprintf (command , "tar -xvf %.*s " , ( int ) strlen ( swap_path ),  swap_path ); // 복원 명령어 생성(압축 해제) 
636+ 		sprintf (command , "tar -xvf %s.swp " , get_file_name ( dst_path ) ); // 복원 명령어 생성(압축 해제) 
498637#ifdef  DEBUG 
499638		printf ("recovery(): command = %s\n" , command );
500639#endif 
501640		remove_directory (dst_path ); // 기존 동기화 디렉토리 삭제 
502641		kill (getpid (), SIGUSR1 ); // 표준 입출력 닫기 
503642		system (command ); // 복원 명령어 실행 
504643		kill (getpid (), SIGUSR2 );
505- 		remove (swap_path ); // swap 파일 삭제 
644+ 		remove (command + 9 ); // swap 파일 삭제 
506645	}
507646	exit (1 );
508647}
@@ -555,3 +694,12 @@ char *get_file_name(char *path) // 파일명 추출
555694
556695	return  tmp  +  1 ;
557696}
697+ 698+ /** 
699+  * @brief 사용법 출력 
700+  * @param 실행파일 문자열 
701+  */ 
702+ void  print_usage (char  * execute_file ) // 사용법 출력 
703+ {
704+ 	fprintf (stderr , "ssu_rsync(): Usage: %s [OPTION] <SOURCE> <DESTINATION>\n" , execute_file );
705+ }
0 commit comments