반응형

copy_file( )

int copy_file(const char *src_file, const char *dest_file, int overwrite, int copy_attr);

일반적으로 파일을 복사하는 함수를 구현할 때에, 파일의 내용만 복사하고 맙니다. 또한, 이미 파일이 있는 경우에 체크하지 않는 경우도 있습니다. file_copy( ) 함수는 파일의 내용 뿐만 아니라 속성(파일의 접근 권한, 파일에 대한 최종 access 시간, 파일의 최종 변경시간 등)을 함께 복제할 것인지도 선택할 수 있습니다. 또한 파일의 이미 있는 경우는 덮어쓰기를 할 것인지 아니면 보존할 것인지도 선택할 수 있습니다. 그리고 파일을 복사 중에 signal이 발생하여 오류가 발생하더라도 retry를 하여 안정적으로 파일을 복사하도록 구현하였습니다.

 

파라미터

src_file
    - 원본 파일에 대한 상대 Path 또는 절대 Path
dest_file
    - 복사될 파일에 대한 상대 Path 또는 절대 Path
overwrite
    -복사될 파일이 이미 있는 경우 파일을 덮어쓰기(overwrite)를 할 지 
     아니면 오류를 발생시키고 중단할 지를 설정합니다.

 0 : 이미 파일이 있으면 복사하지 말고 오류 발생
 그 외: 이미 파일이 있어도 파일을 overwrite함
copy_attr
    - 원본파일의 속성들을 함께 복사할 지 여부를 설정합니다.
    
 0 : 속성은 복사하지 않고 파일의 시간은 복사시점의 시간으로 설정함
 그 외: 원본 파일의 접근권한 및 파일 시간 정보도 dest_file에 동기화 함

 

RETURN

0
    - 정상적으로 파일이 복제되었습니다.

-1
    - 오류가 발생하였습니다. 상세한 오류 내용은 errno 전역 변수에 설정됩니다. 

 


Source 구현

 

copy_file 소스 구현

#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <utime.h>
#include <errno.h>
#include <fcntl.h>

int copy_file(const char *src_file, const char *dest_file, int overwrite, int copy_attr)
{
    int     src_fd;
    int     dest_fd;
    struct  stat sts;
    char    data_buf[4096];
    int     tmp_errno;
    int     size;
    struct  utimbuf attr;
    
    if((src_fd = open(src_file, O_RDONLY)) == -1) {
        return -1;
    }

    /* 원본 file의 속성을 읽습니다. */
    fstat(src_fd, &sts);

    if(overwrite) { /* 이미 파일이 있으면 overwrite를 하겠다면... */
        dest_fd = open(dest_file, O_WRONLY | O_CREAT | O_TRUNC, sts.st_mode);
    } else {        /* 파일이 있으면, 생성하지 말라고 설정한 경우 */
        dest_fd = open(dest_file, O_WRONLY | O_CREAT | O_EXCL, sts.st_mode);
    }

    if(dest_fd == -1) {
        tmp_errno = errno; 
        close(src_fd);  
        errno = tmp_errno; // close가 초기화한 errno를 복구함
        return -1;
    }

    while(size = read(src_fd, data_buf, 4096)) {
        if(size == -1) {
            if(errno == EINTR) {
                continue;
            }
            tmp_errno = errno;
            close(src_fd);
            close(dest_fd);
            errno = tmp_errno; // close가 초기화한 errno를 복구함
            return -1;
        }

        while(write(dest_fd, data_buf, size) == -1) {
            if(errno == EINTR) {
                /* signal이 발생한 경우에는 재작업 */
                continue;
            } else {
                /* disk가 full났거나 무슨 일이 있음. */
                tmp_errno = errno;
                close(src_fd);
                close(dest_fd);
                errno = tmp_errno; // close가 초기화한 errno를 복구함
            }
        }
    }
    close(src_fd);
    close(dest_fd);
    
    /* 원본 파일의 속성을 복원해야 한다면... */
    if(copy_attr) {
        /* last access 시간, last modify 시간 복구 */
        attr.actime  = sts.st_atime;
        attr.modtime = sts.st_mtime;
        utime(dest_file, &attr);  
        
        /* 원본 파일의 파일 권한을 복원하기 
        * open시에 파일권한을 설정하였지만, 
        * 이미 존재했던 파일은 파일권한이 기존 파일의 권한이므로
        * 파일의 권한도 복구합니다.
        */
        chmod(dest_file, sts.st_mode);
    }
    return 0;
}

 


 

사용 예제

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void help(const char *command)
{
    fprintf(stderr, "%s [-fp] src_file dest_file\n", command);
}

int main(int argc, char *argv[])
{
    int overwrite = 0;
    int attr      = 0;
    int idx       = 0;

    if(argc < 3) {
        help(argv[0]);
        return 1;
    }

    if(argc == 4) {
        if(argv[1][0] == '-') {
            for(idx = 1; idx < strlen(argv[1]); idx++) {
                if(argv[1][idx] == 'f') {
                    overwrite = 1;
                } else if(argv[1][idx] == 'p') {
                    attr      = 1;
                }
            }
        } else {
            help(argv[0]);
            return -1;
        }
    }

    if(copy_file(argv[1], argv[2], overwrite, attr) == -1) {
        fprintf(stderr, "FILE COPY ERROR: %s\n", strerror(errno));
        return 1;
    }
    return 0;
}

 

source download :

copy_file.c
0.00MB

반응형
블로그 이미지

자연&사람

행복한 개발자 programmer since 1995.

,