1. 程式人生 > >執行緒實現cp-r與ls-l

執行緒實現cp-r與ls-l

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <linux/types.h>
#include <errno.h>
#include <pthread.h>

#define NAME_SIZE 256

struct fnode
{
	struct fnode *next;
	char name[NAME_SIZE];
};

struct fnode *insert_list(struct fnode *temp,struct fnode *head)
{
	if(head==NULL)	//if linklist is empty,for temp is the first one
	{
		head=temp;
		return head;
	}

	if(strcmp(temp->name,head->name)<0) //temp will be insert before first one
	{
		temp->next=head;
		head=temp;
		return head;
	}
	
	struct fnode *next=head->next;
	struct fnode *prev=head;
	while(next!=NULL&& strcmp(temp->name,next->name)>0)
	{
		next=next->next;
		prev=prev->next;
	}
	temp->next=next;
	prev->next=temp;
	return head;
}

output_type_perm(mode_t mode)
{
	char  type[7]={'p','c','d','b','-','l','s'};
	int index=((mode>>12) & 0xF)/2;
	printf("%c",type[index]);

	char *perm[8]={"---","--x","-w-","-wx","r--","r-x","rw-","rwx"};//rwx
	printf("%s",perm[mode>>6 &07]);
	printf("%s",perm[mode>>3 &07]);
	printf("%s",perm[mode>>0 &07]);
}

void output_user_group(uid_t uid,gid_t gid)
{
	struct passwd *user;
	user=getpwuid(uid);
	printf("  %s",user->pw_name);

	struct group *group;
	group=getgrgid(gid);
	printf(" %s",group->gr_name);
}
output_mtime(time_t mytime)
{
	char buf[256];
	memset(buf,'\0',256);
	ctime_r(&mytime,buf);
	buf[strlen(buf)-1]='\0';
	//memcpy(buf,ctime(mytime),strlen(ctime(mytime))-1);
	printf("  %s",buf);
}

void output_info(struct fnode *head)
{
	struct fnode *temp=head;
	while(temp!=NULL)
	{
		struct stat mystat;
		if(-1==stat(temp->name,&mystat))
		{
			perror("stat");exit(EXIT_FAILURE);
		}
		output_type_perm(mystat.st_mode);
		printf("  %4d",mystat.st_nlink);
		output_user_group(mystat.st_uid,mystat.st_gid);
		printf(" %8ld",mystat.st_size);
		output_mtime(mystat.st_mtime);
		printf(" %s\n",temp->name);
		temp=temp->next;
	}

}
void free_list(struct fnode *ptr)
{
	struct fnode *temp=ptr;
	struct fnode *link=ptr;
	while(ptr)
	{
		temp=ptr;
		ptr=ptr->next;
		free(temp);
	}
}


int cp_file(const char *src, const char *dst,mode_t mode)
{
	int fd_src,fd_dst;
	if(-1 == (fd_src =open(src,O_RDONLY)))
	{
		perror("open src");exit(EXIT_FAILURE);
	}
	
	if(-1 == (fd_dst =open(dst,O_WRONLY|O_TRUNC|O_CREAT,mode)))
	{
		perror("open dst");exit(EXIT_FAILURE);
	}
	
	int len=0;
	do
	{
		char buf[1024];
		len=read(fd_src,buf,1024);
		write(fd_dst,buf,len);
	}while(len>0);
	
	close(fd_src);
	close(fd_dst);
}


int cp_dir(const char *src,const char *dst)
{
	DIR *dirp = NULL;
	
	if(NULL== (dirp=opendir(src)))
	{
		perror("opendir");exit(EXIT_FAILURE);
	}	
	
	struct dirent *entp = NULL;
	while ( NULL != (entp =readdir(dirp)))
	{
		if (strcmp(entp->d_name, "..")==0 || strcmp(entp->d_name, ".")==0)	//ignore ./ ../
        {
          continue;
        }
		
		char *name_src =(char *) malloc( strlen(src) + 1 + strlen(entp->d_name) + 1 );
		sprintf(name_src,"%s/%s\0",src,entp->d_name);
		char *name_dst =(char *) malloc( strlen(dst) + 1 + strlen(entp->d_name) + 1 );
		sprintf(name_dst,"%s/%s\0",dst,entp->d_name);

		struct stat stat_src;
		if (stat(name_src, &stat_src) == -1) 
		{
			fprintf(stderr, "%s(%d): stat error(%s)!\n", __FILE__, __LINE__, strerror(errno));
			exit(EXIT_FAILURE);
		}	
	
		if (S_ISREG(stat_src.st_mode))		//regular file
		{
			cp_file(name_src,name_dst,stat_src.st_mode);
			free(name_src);
			free(name_dst);
		}	
		else if ( S_ISDIR( stat_src.st_mode ))
		{		
			if( -1 ==mkdir(name_dst,stat_src.st_mode))
			{
				perror("mkdir1");exit(EXIT_FAILURE);
			}
			cp_dir( name_src, name_dst);		
			free(name_src);
			free(name_dst);
		}
	}
}


void* cp_r(char *argv[])
{
/*	if (argc < 3)
	{
		fprintf(stderr,"usage %s src_dir dst_src\n",argv[0]);exit(EXIT_FAILURE);
	}
*/	
	struct stat stat_src;
	if (stat(argv[1], &stat_src) != 0) 
	{
     		 fprintf(stderr, "%s(%d): stat error(%s)!\n", __FILE__, __LINE__, strerror(errno));
   		 exit(EXIT_FAILURE);
        }	
	
	umask(0000);
	if (S_ISREG(stat_src.st_mode))		//regular file
    {
		struct stat stat_dst;
		if (stat(argv[2], &stat_dst) == -1) 
		{
			if(errno != ENOENT)			//if errno not cause by file/dir not exist
			{
				fprintf(stderr, "%s(%d): stat error(%s)!\n", __FILE__, __LINE__, strerror(errno));
				exit(EXIT_FAILURE);
			}
			else						//if dst_flie not exist.
			{
				cp_file(argv[1],argv[2],stat_src.st_mode);
			}
		}	
		else		//dst file exist.
		{
			if(S_ISDIR(stat_dst.st_mode))	//cp a file to a exist dir
			{				
				char *ptr=(char *)malloc(strlen(argv[2])+1+strlen(argv[1])+1);
				sprintf(ptr,"%s/%s\0",argv[2],argv[1]);			
				cp_file(argv[1],ptr,stat_src.st_mode);
			}
			else						//cp file to a exist file
			{
				printf("file %s exist, do you want overwrite it[y/n]:",argv[2]);
				char ch;
				while(!scanf("%c",&ch))
				{
					getchar();
				}
				if(ch =='Y' || ch == 'y' )
				{
					unlink(argv[2]);
					cp_file(argv[1],argv[2],stat_src.st_mode);	
				}
				else
					return 1;	
			}
		}
    }	
	
	else if (S_ISDIR(stat_src.st_mode))	//  dir
    {
		struct stat stat_dst;                                
		if (stat(argv[2], &stat_dst) == -1) 
		{                                                       printf("TEST1  %s\n",argv[1]);
			if(errno != ENOENT)			//if errno not cause by file/dir not exist
			{
				fprintf(stderr, "%s(%d): stat error(%s)!\n", __FILE__, __LINE__, strerror(errno));
				exit(EXIT_FAILURE);
			}
			else						//file/dir not exist
			{
				errno=0;
				if(-1 == mkdir(argv[2],stat_src.st_mode))
				{
					perror("mkdir2");exit(EXIT_FAILURE);
				}
				char *le = argv[1];                              
				int c = 0;
				for (int i = 0;i < strlen(argv[1]);i++) 
				{
					char l = *(argv[1]+i);
					if (l == '/')	
					{
						c=i;
						break;
					}
				}
				le = le + c + 1; 
				printf("DIR:%s\n",le);
				char *ptr=(char *)malloc(strlen(argv[1])+1+strlen(le)+1);
				sprintf(ptr,"%s/%s\0",argv[2],le);
				if(-1 == mkdir(ptr,stat_src.st_mode))
				{
					printf("mk:%s\n",ptr);perror("mkdir3");exit(EXIT_FAILURE);
				}			
				cp_dir(argv[1],ptr);
				free(ptr);
			}
		}
		else if(S_ISREG(stat_dst.st_mode))		//can't copy a dir to a file
		{
			fprintf(stderr,"can't copy a dir to a file\n");exit(EXIT_FAILURE);
		}
		else								//copy a dir to a exsit dir ,
		{		
			char *le = argv[1];                              
			int c = 0;
			for (int i = 0;i < strlen(argv[1]);i++) 
			{
				char l = *(argv[1]+i);
				if (l == '/')	
				{
					c=i;
					break;
				}
			}
			le = le + c + 1; 
			printf("DIR:%s\n",le);
			char *ptr=(char *)malloc(strlen(argv[1])+1+strlen(le)+1);
			sprintf(ptr,"%s/%s\0",argv[2],le);
			if(-1 == mkdir(ptr,stat_src.st_mode))
			{
				printf("mk:%s\n",ptr);perror("mkdir3");exit(EXIT_FAILURE);
			}			
			cp_dir(argv[1],ptr);
			free(ptr);
		}
	}
	
}	
void* ls_l(char *argv[])
{
	int argc = 2;

	int i;
	for(i=1;i<argc;i++)
	{
		struct fnode *linklist=NULL;

		struct stat stat_info;
		if(stat(argv[i],&stat_info)==-1)
		{
			perror("stat");exit(EXIT_FAILURE);
		}
	
		if (S_ISREG(stat_info.st_mode))		//regular file
		{
			struct fnode *temp=(struct fnode *)malloc(sizeof(struct fnode));
			if(NULL==temp)
			{
				perror("malloc");exit(EXIT_FAILURE);
			}
			temp->next=NULL;
			memset(temp->name,'\0',NAME_SIZE);
			memcpy(temp->name,argv[i],strlen(argv[i]));
			linklist=insert_list(temp,linklist);
			output_info(linklist);  //  output information of the file
		}
		else if(S_ISDIR(stat_info.st_mode))
		{
			char buf[NAME_SIZE];

			getcwd(buf,128);
			
			DIR  *dirp=NULL;
			dirp=opendir(argv[i]);
			if(NULL==dirp)
			{
				perror("opendir");exit(EXIT_FAILURE);
			}

			struct dirent *entp=NULL;

			while(entp=readdir(dirp))
			{
				struct fnode *temp=(struct fnode *)malloc(sizeof(struct fnode));
				char absolute_way[126];
				sprintf(absolute_way,"%s%s\0",argv[1],entp->d_name);
				struct stat stat_inside;
				if(!((strcmp(entp->d_name,".")) && (strcmp(entp->d_name,"..")))) continue;
				if(stat(absolute_way,&stat_inside)==-1)
				{
					perror("stat");printf("\nd_name:%s\n",entp->d_name);exit(EXIT_FAILURE);
				}
				if(NULL==temp)
				{
					perror("malloc");exit(EXIT_FAILURE);
				}
/**************************************************************************************/
				if(S_ISDIR(stat_inside.st_mode))
				{
					int res_1;
					pthread_t cp_thread;
					void *thread_result1;
					char *cp_name = (char*)malloc(156);
					sprintf(cp_name,"%s%s\0",argv[1],entp->d_name);         
					printf("TEST %s\n",entp->d_name);
					char* point[] = {"cp_r",cp_name,"zhangxu",NULL};
					res_1 = pthread_create(&cp_thread,NULL,cp_r,point);     
					if (res_1 != 0)
					{
						perror ("Thread creation failed");
						exit (EXIT_FAILURE);
					}
					
					res_1 = pthread_join(cp_thread, &thread_result1);  
					printf("Waiting for cp_thread to finish...\n");
					if (res_1 != 0)
					{
						perror("Thread join failed");
						exit (EXIT_FAILURE);
					}
					else 
					{
						temp->next=NULL;
						memset(temp->name,'\0',NAME_SIZE);
						memcpy(temp->name,entp->d_name,strlen(entp->d_name));
						linklist=insert_list(temp,linklist);
						free(cp_name);

					}

/*						pid_t pid;
						int status;
						char* pass_argv = argv;
						if ((pid = fork()) == -1)
						{
							perror("fork");
							exit(EXIT_FAILURE);
						}
						else if (pid == 0)
						{
							
							char *cp_name = (char*)malloc(256);
							sprintf(cp_name,"%s%s\0",argv[1],entp->d_name);
							char* point[] = {"cp_r",cp_name,"yourname",NULL};
					//		printf("命令:%s\n",ls_name);
					//		system(ls_name);
					//		int ret = execv("/home/vic/Desktop/cp_r",point);
							int ret = execl("/home/vic/Desktop/cp_r","./cp_r",cp_name,"yourname",NULL);
							if(ret == -1) 
							{
															
							perror("execl error");
							}
							free(cp_name);	
							free(point);
							exit(0);		
	
						}
						else 
						{

							printf("child_pid:%d\n",(waitpid(pid,&status,0)));
							printf("CP RIGHT\n");
							temp->next=NULL;
							memset(temp->name,'\0',NAME_SIZE);
							memcpy(temp->name,entp->d_name,strlen(entp->d_name));
							linklist=insert_list(temp,linklist);
						}
*/
				}

/*********************************************************************************************/
				else 
				{

					temp->next=NULL;
					memset(temp->name,'\0',NAME_SIZE);
					memcpy(temp->name,entp->d_name,strlen(entp->d_name));
					linklist=insert_list(temp,linklist);

				}
			}

			chdir(argv[i]);//change the current dirctory
			close(dirp);
			output_info(linklist);
			chdir(buf);			
		}		
		free_list(linklist);
	}	
	return 1;
}



int main (int argc,char* argv[])
{
	if(argc < 2)
	{
		printf("usage :%s dir_name\n",argv[0]);exit(EXIT_FAILURE);
	}
	int res;
	pthread_t ls_thread;
	void *thread_result;
	res = pthread_create(&ls_thread, NULL, 	ls_l, argv);

	if (res != 0)
	{
		perror ("Thread creation failed");
		exit (EXIT_FAILURE);
	}

	res = pthread_join(ls_thread, &thread_result);
	printf("Waiting for ls_thread to finish...\n");
	if (res != 0)
	{
		perror("Thread join failed");
		exit (EXIT_FAILURE);
	}
	return 1;
}