static tb_bool_t tb_directory_walk_impl(tb_char_t const* path, tb_bool_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(path && func, tb_false); // last tb_long_t last = tb_strlen(path) - 1; tb_assert_and_check_return_val(last >= 0, tb_false); // done tb_bool_t ok = tb_true; tb_char_t temp[4096] = {0}; DIR* directory = tb_null; if ((directory = opendir(path))) { // walk struct dirent* item = tb_null; while ((item = readdir(directory))) { // check tb_assert_and_check_continue(item->d_reclen); // the item name tb_char_t name[1024] = {0}; tb_strncpy(name, item->d_name, tb_min(item->d_reclen, sizeof(name) - 1)); if (tb_strcmp(name, ".") && tb_strcmp(name, "..")) { // the temp path tb_long_t n = tb_snprintf(temp, 4095, "%s%s%s", path, path[last] == '/'? "" : "/", name); if (n >= 0) temp[n] = '\0'; // the file info tb_file_info_t info = {0}; if (tb_file_info(temp, &info)) { // do callback if (prefix) ok = func(temp, &info, priv); tb_check_break(ok); // walk to the next directory if (info.type == TB_FILE_TYPE_DIRECTORY && recursion) ok = tb_directory_walk_impl(temp, recursion, prefix, func, priv); tb_check_break(ok); // do callback if (!prefix) ok = func(temp, &info, priv); tb_check_break(ok); } } } // exit directory closedir(directory); } // continue ? return ok; }
tb_void_t tb_directory_walk(tb_char_t const* path, tb_bool_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return(path && func); // the full path tb_wchar_t full[TB_PATH_MAXN]; if (tb_path_full_w(path, full, TB_PATH_MAXN)) tb_directory_walk_impl(full, recursion, prefix, func, priv); }
tb_void_t tb_directory_walk(tb_char_t const* path, tb_bool_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return(path && func); // exists? tb_file_info_t info = {0}; if (tb_file_info(path, &info) && info.type == TB_FILE_TYPE_DIRECTORY) tb_directory_walk_impl(path, recursion, prefix, func, priv); else { // the absolute path tb_char_t full[TB_PATH_MAXN]; path = tb_path_absolute(path, full, TB_PATH_MAXN); tb_assert_and_check_return(path); // walk tb_directory_walk_impl(path, recursion, prefix, func, priv); } }
static tb_void_t tb_directory_walk_impl(tb_wchar_t const* path, tb_bool_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return(path && func); // last tb_long_t last = tb_wcslen(path) - 1; tb_assert_and_check_return(last >= 0); // add \*.* tb_wchar_t temp_w[4096] = {0}; tb_char_t temp_a[4096] = {0}; tb_swprintf(temp_w, 4095, L"%s%s*.*", path, path[last] == L'\\'? L"" : L"\\"); // init info WIN32_FIND_DATAW find = {0}; HANDLE directory = INVALID_HANDLE_VALUE; if (INVALID_HANDLE_VALUE != (directory = FindFirstFileW(temp_w, &find))) { // walk do { // check if (tb_wcscmp(find.cFileName, L".") && tb_wcscmp(find.cFileName, L"..")) { // the temp path tb_long_t n = tb_swprintf(temp_w, 4095, L"%s%s%s", path, path[last] == L'\\'? L"" : L"\\", find.cFileName); if (n >= 0 && n < 4096) temp_w[n] = L'\0'; // wtoa temp n = tb_wtoa(temp_a, temp_w, 4095); if (n >= 0 && n < 4096) temp_a[n] = '\0'; // the file info tb_file_info_t info = {0}; if (tb_file_info(temp_a, &info)) { // do callback if (prefix) func(temp_a, &info, priv); // walk to the next directory if (info.type == TB_FILE_TYPE_DIRECTORY && recursion) tb_directory_walk_impl(temp_w, recursion, prefix, func, priv); // do callback if (!prefix) func(temp_a, &info, priv); } } } while (FindNextFileW(directory, &find)); // exit directory FindClose(directory); } }
tb_void_t tb_directory_walk(tb_char_t const* path, tb_long_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv) { // check tb_assert_and_check_return(path && func); // walk it directly if rootdir is relative path tb_file_info_t info = {0}; if (!tb_path_is_absolute(path) && tb_file_info(path, &info) && info.type == TB_FILE_TYPE_DIRECTORY) { tb_wchar_t path_w[TB_PATH_MAXN]; if (tb_atow(path_w, path, tb_arrayn(path_w)) != -1) tb_directory_walk_impl(path_w, recursion, prefix, func, priv); } else { // the absolute path (translate "~/") tb_wchar_t full_w[TB_PATH_MAXN]; if (tb_path_absolute_w(path, full_w, TB_PATH_MAXN)) tb_directory_walk_impl(full_w, recursion, prefix, func, priv); } }
tb_bool_t tb_directory_remove(tb_char_t const* path) { // the absolute 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_false); // walk remove tb_directory_walk_impl(path, tb_true, tb_false, tb_directory_walk_remove, tb_null); // remove it return !remove(path)? tb_true : tb_false; }
tb_bool_t tb_directory_remove(tb_char_t const* path) { // check tb_assert_and_check_return_val(path, tb_false); // the absolute path tb_wchar_t full[TB_PATH_MAXN]; if (!tb_path_absolute_w(path, full, TB_PATH_MAXN)) return tb_false; // walk remove tb_directory_walk_impl(full, -1, tb_false, tb_directory_walk_remove, tb_null); // remove it return RemoveDirectoryW(full)? tb_true : tb_false; }
tb_bool_t tb_directory_copy(tb_char_t const* path, tb_char_t const* dest) { // the absolute 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); // walk copy tb_value_t tuple[3]; tuple[0].cstr = dest; tuple[1].ul = tb_strlen(path); tuple[2].b = tb_true; tb_directory_walk_impl(path, tb_true, tb_true, tb_directory_walk_copy, tuple); // ok? return tuple[2].b; }