linux C實現cp功能

來源:互聯網
上載者:User

標籤:linux   c   


一:背景

        看了unix/linux編程實踐,跟著書上代碼實現了普通檔案的拷貝,看到課後習題後需要實現目錄之間的拷貝,因此有了本文,我最初實現cp用了180多行代碼,後來覺得很多地方可以封裝,但是最後居然越封裝越多達到了200多行,今晚果斷再次封裝,修剪了代碼大概170多行,要比課後答案的要簡便點。該cp可以實現普通檔案的拷貝,拷貝到指定目錄下,和目錄直接拷貝等功能。


二:思路

    目錄之間的拷貝我覺得最主要的功能就是path路徑的拼裝,處理好path路徑問題,就很簡單了。例如 /root/a.txt 拷貝到 /tmp下,那麼只要傳入/root/a.txt 和 /tmp/a.txt即可,那麼關鍵就是/tmp和a.txt的拼裝,在拷貝到/tmp/下你也可以先判斷下目標是否有相同檔案存在。若存在可以提示使用者是否覆蓋(這個功能我還沒做)。這裡主要還是字串處理函數用的比較多,還有一個就是函數傳回值得一個痛點(下篇博文介紹下函數傳回值)。


三:實現

    

#include<stdio.h>#include<unistd.h>#include<fcntl.h>#include<unistd.h>#include<stdlib.h>#include<sys/types.h>#include<sys/stat.h>#include<string.h>#include<dirent.h>#include <libgen.h>#define BUFFERSIZE 4096#define COPYMODE 0644char *deal_path(char *,char *);char *deal_path1(char *,struct dirent *);int is_file(char *);char *deal_with(char *,char *);void oops(char *,char *);int exists(char *);void do_cp(char *,char *);int main(int argc,char *argv[]){        char answer[10];        char c;        //設定buf        struct stat filebuf1;        struct stat filebuf2;        struct stat tmpbuf;        char *filename=NULL;        char *filename2=NULL;        struct dirent  *dirname;        DIR *dir_ptr;        //判斷參數                if(argc != 3){                fprintf(stderr,"Usage: %s source destination\n",*argv);                exit(1);        }        //判斷源檔案和目標檔案是否相等        if(strcmp(argv[1],argv[2]) == 0)        {                fprintf(stderr,"No Copy Source File equal Dest File\n");                exit(1);        }        //測試檔案是否可以訪問        if(access(argv[2],F_OK) == 0){                //詢問檔案是否可以覆蓋                printf("Can you ovver the file (y/n):");                scanf("%9s",&answer);                while((c = getchar()) != EOF && c != ‘\n‘);        }        //判斷使用者的輸入        if(*answer != ‘y‘ && *answer != ‘Y‘){                fprintf(stderr,"the dst file exists,don‘t over\n");                exit(1);        }        //判斷目標是否是目錄        stat(argv[2],&filebuf2);        stat(argv[1],&filebuf1);        if(!S_ISDIR(filebuf1.st_mode)){                if(S_ISDIR(filebuf2.st_mode))                        filename = deal_path(argv[2],argv[1]);                else                        filename = argv[2];        //      printf("%s\n",filename);                do_cp(argv[1],filename);                free(filename);             }                     else{                if(S_ISDIR(filebuf2.st_mode))                if((dir_ptr = opendir(argv[1])) == NULL)                        sprintf("stderr","Can‘t open dir %s\n",argv[1]);                else                        while((dirname=readdir(dir_ptr)) != NULL){                                        filename = deal_path(argv[1],dirname->d_name);                                        if(is_file(filename)){                                                filename2 = deal_with(filename,argv[2]);                                                do_cp(filename,filename2);                                                free(filename);                                                free(filename2);                                        }else{                                                free(filename);                                                continue;                                        }                                }                        }                closedir(dir_ptr);        }void do_cp(char *path1,char *path2){        int in_fd,out_fd,n_chars;        char buf[BUFFERSIZE];        if((in_fd = open(path1,O_RDONLY)) == -1)                oops("Cannot open",path1);        if((out_fd = open(path2,O_WRONLY|O_CREAT,COPYMODE)) == -1)                oops("Cannot create",path2);        //開始讀取        while((n_chars = read(in_fd,buf,BUFFERSIZE)) > 0)                if(write(out_fd,buf,n_chars) != n_chars)                oops("Write error to",path2);        //判斷最後是否寫入        if(n_chars == -1)                oops("Read error from,path1","");                        //判斷最後是否寫入        if(n_chars == -1)                oops("Read error from,path1","");        //關閉檔案        if(close(in_fd) == -1||close(out_fd) == -1)                oops("Error closing files","");}void oops(char *s1,char *s2){        fprintf(stderr,"Error:%s ",s1);        perror(s2);        exit(1);}int exists(char *filename){        return access(filename,F_OK);}int is_file(char *filename){        struct stat filebuf;        stat(filename,&filebuf);        if(S_ISREG(filebuf.st_mode))                return 1;        else                return 0;}char *deal_with(char *filename,char *filename2){        char *file=NULL;;        if((file = (char *)malloc(strlen(basename(filename))+strlen(filename2)+3)) == NULL)                perror("malloc error");                        else{                if(filename2[strlen(filename2)-1] == ‘/‘){                        strcpy(file,filename2);                        strcat(file,basename(filename));                }else{                        strcpy(file,filename2);                        strcat(file,"/");                        strcat(file,basename(filename));                     }        }        return file;}char *deal_path(char *file,char *file2){        char *filename=NULL;        if((filename = (char *)malloc(strlen(file)+strlen(file2)+3)) == NULL)                                perror("Malloc erro:");        else{        if(file[strlen(file)-1] == ‘/‘){                        strcpy(filename,file);                        strcat(filename,file2);        }else{                        strcpy(filename,file);                        strcat(filename,"/");                        strcat(filename,file2);                }        }        return filename;}用的最多的還是這個deal_path這個函數,這個函數會判斷/tmp/ /tmp這個的區別,最終會將給出的兩個參數合并成一個檔案路徑建立並寫入要拷貝的內容。

四:總結

    C語言基礎很重要,最近在看C專家編程,C和指標,感觸很深裡面很多C語言的細節我都不知道。還有linux C編程實戰中的關於結構體的位元組對齊我也知之甚少。後期會用部落格記錄相關內容加深自己對這些內容的理解。

本文出自 “專註linux” 部落格,請務必保留此出處http://forlinux.blog.51cto.com/8001278/1530293

linux C實現cp功能

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.