/** * Expand wildcards in the given filepath and store results into vector. * If no wildcards are found then just the filepath is stored. * Note: only wildcards in the last filename of the path are expanded. * * @param vect the vector to receive wide-strings with file paths * @param filepath the filepath to process */ void expand_wildcards(vector_t* vect, wchar_t* filepath) { int added = 0; size_t len = wcslen(filepath); size_t index = wcscspn(filepath, L"*?"); /* if a wildcard has been found without a directory separator after it */ if(index < len && wcscspn(filepath + index, L"/\\") >= (len - index)) { wchar_t* parent; WIN32_FIND_DATAW d; HANDLE h; /* find directory separator */ for(; index > 0 && !IS_PATH_SEPARATOR(filepath[index]); index--); parent = (IS_PATH_SEPARATOR(filepath[index]) ? filepath : 0); h = FindFirstFileW(filepath, &d); if(INVALID_HANDLE_VALUE != h) { do { wchar_t* wpath; char* cstr; int failed; if((0 == wcscmp(d.cFileName, L".")) || (0 == wcscmp(d.cFileName, L".."))) continue; if(NULL == (wpath = make_pathw(parent, index + 1, d.cFileName))) continue; cstr = wchar_to_cstr(wpath, WIN_DEFAULT_ENCODING, &failed); /* note: just quietly skip unconvertible file names */ if(!cstr || failed) { free(cstr); free(wpath); continue; } rsh_vector_add_ptr(vect, cstr); added++; } while(FindNextFileW(h, &d)); FindClose(h); } } if(added == 0) { wchar_t* wpath = make_pathw(0, 0, filepath); char* cstr = w2c(wpath); if(cstr) rsh_vector_add_ptr(vect, cstr); } }
/** * Open a directory for reading its content. * For simplicity the function supposes that dir_path points to an * existing directory and doesn't check for this error. * The Unicode version of the function. * * @param dir_path directory path * @return pointer to directory iterator */ WIN_DIR* win_wopendir(const wchar_t* dir_path) { WIN_DIR* d; /* append '\*' to the dir_path */ wchar_t *wpath = make_pathw(dir_path, (size_t)-1, L"*"); d = (WIN_DIR*)rsh_malloc(sizeof(WIN_DIR)); d->hFind = FindFirstFileW(wpath, &d->findFileData); free(wpath); if(d->hFind == INVALID_HANDLE_VALUE && GetLastError() == ERROR_ACCESS_DENIED) { free(d); errno = EACCES; return NULL; } /* note: we suppose if INVALID_HANDLE_VALUE was returned, then the file listing is empty */ d->state = (d->hFind == INVALID_HANDLE_VALUE ? -1 : 0); d->dir.d_name = NULL; return d; }
/* allocate and fill the file_search_data */ file_search_data* create_file_search_data(rsh_tchar** paths, size_t count, int max_depth) { size_t i; file_search_data* data = (file_search_data*)rsh_malloc(sizeof(file_search_data)); memset(data, 0, sizeof(file_search_data)); rsh_blocks_vector_init(&data->root_files); data->max_depth = max_depth; #ifdef _WIN32 /* expand wildcards and fill the root_files */ for (i = 0; i < count; i++) { int added = 0; size_t length, index; wchar_t* path = paths[i]; wchar_t* p = wcschr(path, L'\0') - 1; /* strip trailing '\','/' symbols (if not preceded by ':') */ for (; p > path && IS_PATH_SEPARATOR_W(*p) && p[-1] != L':'; p--) *p = 0; /* Expand a wildcard in the current file path and store results into data->root_files. * If a wildcard is not found then just the file path is stored. * NB, only wildcards in the last filename of the path are expanded. */ length = p - path + 1; index = wcscspn(path, L"*?"); if (index < length && wcscspn(path + index, L"/\\") >= (length - index)) { /* a wildcard is found without a directory separator after it */ wchar_t* parent; WIN32_FIND_DATAW d; HANDLE handle; /* find a directory separator before the file name */ for (; index > 0 && !IS_PATH_SEPARATOR(path[index]); index--); parent = (IS_PATH_SEPARATOR(path[index]) ? path : 0); handle = FindFirstFileW(path, &d); if (INVALID_HANDLE_VALUE != handle) { do { file_t file; int failed; if (IS_CURRENT_OR_PARENT_DIRW(d.cFileName)) continue; memset(&file, 0, sizeof(file)); file.wpath = make_pathw(parent, index + 1, d.cFileName); if (!file.wpath) continue; /* skip directories if not in recursive mode */ if (data->max_depth == 0 && (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue; /* convert file name */ file.path = wchar_to_cstr(file.wpath, WIN_DEFAULT_ENCODING, &failed); if (!failed) { failed = (file_statw(&file) < 0); } /* quietly skip unconvertible file names */ if (!file.path || failed) { if (failed) { data->errors_count++; } free(file.path); free(file.wpath); continue; } /* fill the file information */ file.mode |= FILE_IFROOT; add_root_file(data, &file); added++; } while (FindNextFileW(handle, &d)); FindClose(handle); } else { /* report error on the specified wildcard */ char * cpath = wchar_to_cstr(path, WIN_DEFAULT_ENCODING, NULL); set_errno_from_last_file_error(); log_file_error(cpath); free(cpath); data->errors_count++; } } else { int failed; file_t file; memset(&file, 0, sizeof(file)); /* if filepath is a dash string "-" */ if ((path[0] == L'-' && path[1] == L'\0')) { file.mode = FILE_IFSTDIN; file.path = rsh_strdup("(stdin)"); } else { file.path = wchar_to_cstr(path, WIN_DEFAULT_ENCODING, &failed); if (failed) { log_error(_("Can't convert the path to local encoding: %s\n"), file.path); free(file.path); data->errors_count++; continue; } file.wpath = path; if (file_statw(&file) < 0) { log_file_error(file.path); free(file.path); data->errors_count++; continue; } } /* mark the file as obtained from the command line */ file.mode |= FILE_IFROOT; file.wpath = rsh_wcsdup(path); add_root_file(data, &file); } } /* for */ #else /* copy file paths */ for (i = 0; i < count; i++) { file_t file; file_init(&file, paths[i], 0); if (IS_DASH_STR(file.path)) { file.mode = FILE_IFSTDIN; } else if (file_stat2(&file, USE_LSTAT) < 0) { log_file_error(file.path); file_cleanup(&file); data->errors_count++; continue; } file.mode |= FILE_IFROOT; add_root_file(data, &file); } #endif return data; }