/** * Open directory iterator for reading the directory content. * * @param dir_path directory path * @return pointer to directory stream. On error, NULL is returned, * and errno is set appropriately. */ WIN_DIR* win_opendir(const char* dir_path) { WIN_DIR* d; wchar_t* wpath; /* append '\*' to the dir_path */ size_t len = strlen(dir_path); char *path = (char*)malloc(len + 3); if(!path) return NULL; /* failed, malloc also set errno = ENOMEM */ strcpy(path, dir_path); strcpy(path + len, "\\*"); d = (WIN_DIR*)malloc(sizeof(WIN_DIR)); if(!d) { free(path); return NULL; } memset(d, 0, sizeof(WIN_DIR)); wpath = c2w(path, 0); d->hFind = (wpath != NULL ? FindFirstFileW(wpath, &d->findFileData) : INVALID_HANDLE_VALUE); free(wpath); if(d->hFind == INVALID_HANDLE_VALUE && GetLastError() != ERROR_ACCESS_DENIED) { wpath = c2w(path, 1); /* try to use secondary codepage */ if(wpath) { d->hFind = FindFirstFileW(wpath, &d->findFileData); free(wpath); } } free(path); if(d->hFind == INVALID_HANDLE_VALUE && GetLastError() == ERROR_ACCESS_DENIED) { free(d); errno = EACCES; return NULL; } set_errno_from_last_file_error(); d->state = (d->hFind == INVALID_HANDLE_VALUE ? -1 : 0); d->dir.d_name = NULL; return d; }
/** * Fill file information in the file_t structure. * * @param file the file information * @return 0 on success, -1 on error */ int file_statw(file_t* file) { WIN32_FILE_ATTRIBUTE_DATA data; /* read file attributes */ if (GetFileAttributesExW(file->wpath, GetFileExInfoStandard, &data)) { uint64_t u; file->size = (((uint64_t)data.nFileSizeHigh) << 32) + data.nFileSizeLow; file->mode &= FILE_OPT_DONT_FREE_PATH; file->mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? FILE_IFDIR : FILE_IFREG); /* the number of 100-nanosecond intervals since January 1, 1601 */ u = (((uint64_t)data.ftLastWriteTime.dwHighDateTime) << 32) + data.ftLastWriteTime.dwLowDateTime; /* convert to second and subtract the epoch difference */ file->mtime = u / 10000000 - 11644473600LL; return 0; } set_errno_from_last_file_error(); return -1; }
/* 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; }