diff --git a/src/tbox/platform/windows/directory.c b/src/tbox/platform/windows/directory.c index 0490be247..0e2cc25db 100644 --- a/src/tbox/platform/windows/directory.c +++ b/src/tbox/platform/windows/directory.c @@ -62,6 +62,9 @@ static tb_long_t tb_directory_walk_copy(tb_char_t const* path, tb_file_info_t co tb_size_t size = tuple[1].ul; tb_char_t const* name = path + size; + // the copy flags + tb_size_t flags = tuple[2].ul; + // the dest file path tb_char_t dpath[8192] = {0}; tb_snprintf(dpath, 8192, "%s\\%s", dest, name[0] == '\\'? name + 1 : name); @@ -77,18 +80,33 @@ static tb_long_t tb_directory_walk_copy(tb_char_t const* path, tb_file_info_t co } // copy + tb_bool_t ok = tb_true; + tb_bool_t skip_recursion = tb_false; switch (info->type) { case TB_FILE_TYPE_FILE: - if (!tb_file_copy(path, dpath, TB_FILE_COPY_NONE)) tuple[2].b = tb_false; + ok = tb_file_copy(path, dpath, flags); break; case TB_FILE_TYPE_DIRECTORY: - if (!tb_directory_create(dpath)) tuple[2].b = tb_false; + { + // reserve symlink? + if ((flags & TB_FILE_COPY_LINK) && (info->flags & TB_FILE_FLAG_LINK)) + { + // just copy link and skip recursion + ok = tb_file_copy(path, dpath, TB_FILE_COPY_LINK); + skip_recursion = tb_true; + } + else ok = tb_directory_create(dpath); + } break; default: break; } - return TB_DIRECTORY_WALK_CODE_CONTINUE; + tuple[3].b = ok; + tb_size_t retcode = TB_DIRECTORY_WALK_CODE_CONTINUE; + if (skip_recursion) + retcode |= TB_DIRECTORY_WALK_CODE_SKIP_RECURSION; + return retcode; } static tb_long_t tb_directory_walk_impl(tb_wchar_t const* path, tb_long_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv) { @@ -321,16 +339,13 @@ tb_bool_t tb_directory_copy(tb_char_t const* path, tb_char_t const* dest, tb_siz tb_value_t tuple[3]; tuple[0].cstr = dest; tuple[1].ul = tb_strlen(path); - tuple[2].b = tb_true; + tuple[2].ul = flags; + tuple[3].b = tb_true; tb_directory_walk(path, -1, tb_true, tb_directory_walk_copy, tuple); - // ok? - tb_bool_t ok = tuple[2].b; - // copy empty directory? + tb_bool_t ok = tuple[3].b; if (ok && !tb_file_info(dest, tb_null)) return tb_directory_create(dest); - - // ok? return ok; } diff --git a/src/tbox/platform/windows/file.c b/src/tbox/platform/windows/file.c index c80bc9b16..4ff1cf8fb 100644 --- a/src/tbox/platform/windows/file.c +++ b/src/tbox/platform/windows/file.c @@ -442,10 +442,31 @@ tb_bool_t tb_file_copy(tb_char_t const* path, tb_char_t const* dest, tb_size_t f tb_file_info_t info = {0}; if (flags & TB_FILE_COPY_LINK && tb_file_info(path, &info) && info.flags & TB_FILE_FLAG_LINK) { - if (tb_kernel32()->CopyFileExW) - return (tb_bool_t)tb_kernel32()->CopyFileExW(full0, full1, tb_null, tb_null, FALSE, COPY_FILE_COPY_SYMLINK); - // TODO we should read file content to copy it - // ... + tb_file_mkdir(full1); + if (tb_kernel32()->CopyFileExW && tb_kernel32()->CopyFileExW(full0, full1, tb_null, tb_null, FALSE, COPY_FILE_COPY_SYMLINK)) + return tb_true; + + // we should read file content to copy it + tb_bool_t ok = tb_false; + tb_file_ref_t ifile = tb_file_init(path, TB_FILE_MODE_RW); + tb_file_ref_t ofile = tb_file_init(dest, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC); + if (ifile && ofile) + { + tb_hize_t writ = 0; + tb_hize_t size = tb_file_size(ifile); + while (writ < size) + { + tb_long_t real = tb_file_writf(ofile, ifile, writ, size - writ); + if (real > 0) writ += real; + else break; + } + if (writ == size) ok = tb_true; + } + + // exit file + if (ifile) tb_file_exit(ifile); + if (ofile) tb_file_exit(ofile); + return ok; } // copy it