2016年4月1日 星期五

Copy file without system call

Copy File Method

前言


在C語言中,開發再Embedded system我的前輩們都會一直說盡量可以不要再C裡面使用system call,因為用了可能會出現一些hang住的可能[這之後會在其他文章裡面提及跟介紹]。


那這次文章只是因為我常常需要copy file從A到B處,但是寫C一定不會想要做一堆code去呈現跟達成這個功能。 只是記錄一下,想讓自己知道要怎麼寫copy的功能。



實作


那如果是傻傻的不太會寫程式初出茅廬的工程師來說。可能會怎麼做呢? 沒有任何偏見!! 只是覺得大家應該都會直接call system call。

int main()
{
    ...
    ...
    system("cp file.txt /mnt/auto/CF/test.txt");
    return 0;
}

那如果我想要用C standard library去做呢?
目前提供最有可能的應該是rename的function,其實就很類似於mv的動作,將A檔名改為B檔名。
int main()
{
    ...
    ...
    rename("file.txt", "/mnt/auto/CF/test.txt");
    return 0;
}

那大家有發現有什麼問題嗎????

你直接拿去compile之後,執行就會知道其實無法正常搬檔案。
因為rename的error return code會跟你說~

Error: Invalid Cross-Device link

原因是Hard link的關係,我是實際上要將某個檔案搬移到另外一個file system 上,但是假若真的要做到這件事情,在hard link的定義上就是不存在的。

意思就是Rename同等於Hard link的定義動作。

有人提供的copy file function

Ref:http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c

#include 
#include 
#include 

int cp(const char *to, const char *from)
{
    int fd_to, fd_from;
    char buf[4096];
    ssize_t nread;
    int saved_errno;

    fd_from = open(from, O_RDONLY);
    if (fd_from < 0)
        return -1;

    fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
    if (fd_to < 0)
        goto out_error;

    while (nread = read(fd_from, buf, sizeof buf), nread > 0)
    {
        char *out_ptr = buf;
        ssize_t nwritten;

        do {
            nwritten = write(fd_to, out_ptr, nread);

            if (nwritten >= 0)
            {
                nread -= nwritten;
                out_ptr += nwritten;
            }
            else if (errno != EINTR)
            {
                goto out_error;
            }
        } while (nread > 0);
    }

    if (nread == 0)
    {
        if (close(fd_to) < 0)
        {
            fd_to = -1;
            goto out_error;
        }
        close(fd_from);

        /* Success! */
        return 0;
    }

  out_error:
    saved_errno = errno;

    close(fd_from);
    if (fd_to >= 0)
        close(fd_to);

    errno = saved_errno;
    return -1;
}




1 則留言: