Пример #1
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_file_ref_t tb_file_init(tb_char_t const* path, tb_size_t mode)
{
    // check
    tb_assert_and_check_return_val(path, tb_null);

    // the full path
    tb_char_t full[TB_PATH_MAXN];
    path = tb_path_absolute(path, full, TB_PATH_MAXN);
    tb_assert_and_check_return_val(path, tb_null);

    // flags
    tb_size_t flags = 0;
    if (mode & TB_FILE_MODE_RO) flags |= O_RDONLY;
    else if (mode & TB_FILE_MODE_WO) flags |= O_WRONLY;
    else if (mode & TB_FILE_MODE_RW) flags |= O_RDWR;

    if (mode & TB_FILE_MODE_CREAT) flags |= O_CREAT;
    if (mode & TB_FILE_MODE_APPEND) flags |= O_APPEND;
    if (mode & TB_FILE_MODE_TRUNC) flags |= O_TRUNC;

    // dma mode, no cache
#ifdef TB_CONFIG_OS_LINUX
    if (mode & TB_FILE_MODE_DIRECT) flags |= O_DIRECT;
#endif

    // for native aio aicp
#if defined(TB_CONFIG_ASIO_HAVE_NAIO)
    if (mode & TB_FILE_MODE_ASIO) flags |= O_DIRECT;
#endif

    // noblock
    flags |= O_NONBLOCK;

    // modes
    tb_size_t modes = 0;
    if (mode & TB_FILE_MODE_CREAT) 
    {
        // 0644: -rw-r--r-- 
        modes = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    }

    // open it, @note need absolute path
    tb_long_t fd = open(path, flags, modes);
    if (fd < 0 && (mode & TB_FILE_MODE_CREAT))
    {
        // open it again after creating the file directory
        tb_char_t dir[TB_PATH_MAXN];
        if (tb_directory_create(tb_path_directory(path, dir, sizeof(dir))))
            fd = open(path, flags, modes);
    }
 
    // trace
    tb_trace_d("open: %p", tb_fd2file(fd));

    // ok?
    return tb_fd2file(fd);
}
Пример #2
0
tb_bool_t tb_file_copy(tb_char_t const* path, tb_char_t const* dest)
{
    // check
    tb_assert_and_check_return_val(path && dest, tb_false);

#ifdef TB_CONFIG_POSIX_HAVE_COPYFILE

    // the full path
    tb_char_t full0[TB_PATH_MAXN];
    path = tb_path_absolute(path, full0, TB_PATH_MAXN);
    tb_assert_and_check_return_val(path, tb_false);

    // the dest path
    tb_char_t full1[TB_PATH_MAXN];
    dest = tb_path_absolute(dest, full1, TB_PATH_MAXN);
    tb_assert_and_check_return_val(dest, tb_false);

    // attempt to copy it directly
    if (!copyfile(path, dest, 0, COPYFILE_ALL)) return tb_true;
    else
    {
        // attempt to copy it again after creating directory
        tb_char_t dir[TB_PATH_MAXN];
        if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
            return !copyfile(path, dest, 0, COPYFILE_ALL);
    }

    // failed
    return tb_false;
#else
    tb_int_t    ifd = -1;
    tb_int_t    ofd = -1;
    tb_bool_t   ok = tb_false;
    do
    {
        // get the absolute source path
        tb_char_t data[8192];
        path = tb_path_absolute(path, data, sizeof(data));
        tb_assert_and_check_break(path);

        // get stat.st_mode first
#ifdef TB_CONFIG_POSIX_HAVE_STAT64
        struct stat64 st = {0};
        if (stat64(path, &st)) break;
#else
        struct stat st = {0};
        if (stat(path, &st)) break;
#endif

        // open source file
        ifd = open(path, O_RDONLY);
        tb_check_break(ifd >= 0);

        // get the absolute source path
        dest = tb_path_absolute(dest, data, sizeof(data));
        tb_assert_and_check_break(dest);

        // open destinate file and copy file mode
        ofd = open(dest, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
        if (ofd < 0)
        {
            // attempt to open it again after creating directory
            tb_char_t dir[TB_PATH_MAXN];
            if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
                ofd = open(dest, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
        }
        tb_check_break(ofd >= 0);

        // get file size
        tb_hize_t size = tb_file_size(tb_fd2file(ifd));

        // init write size
        tb_hize_t writ = 0; 
       
        // attempt to copy file using `sendfile`
#ifdef TB_CONFIG_POSIX_HAVE_SENDFILE
        while (writ < size)
        {
            off_t seek = writ;
            tb_hong_t real = sendfile(ofd, ifd, &seek, (size_t)(size - writ));
            if (real > 0) writ += real;
            else break;
        }

        /* attempt to copy file directly if sendfile failed 
         *
         * sendfile() supports regular file only after "since Linux 2.6.33".
         */
        if (writ != size) 
        {
            lseek(ifd, 0, SEEK_SET);
            lseek(ofd, 0, SEEK_SET);
        }
        else
        {
            ok = tb_true;
            break;
        }
#endif

        // copy file using `read` and `write`
        writ = 0;
        while (writ < size)
        {
            // read some data
            tb_int_t real = read(ifd, data, (size_t)tb_min(size - writ, sizeof(data)));
            if (real > 0)
            {
                real = write(ofd, data, real);
                if (real > 0) writ += real;
                else break;
            }
            else break;
        }

        // ok?
        ok = (writ == size);

    } while (0);

    // close source file
    if (ifd >= 0) close(ifd);
    ifd = -1;

    // close destinate file
    if (ofd >= 0) close(ofd);
    ofd = -1;

    // ok?
    return ok;
#endif
}