const osd_directory_entry *osd_readdir(osd_directory *dir) { // if we've previously allocated a name, free it now if (dir->entry.name != NULL) { free((void *)dir->entry.name); dir->entry.name = NULL; } // if this isn't the first file, do a find next if (!dir->is_first) { if (!FindNextFile(dir->find, &dir->data)) return NULL; } // otherwise, just use the data we already had else dir->is_first = FALSE; // extract the data dir->entry.name = utf8_from_tstring(dir->data.cFileName); dir->entry.type = win_attributes_to_entry_type(dir->data.dwFileAttributes); dir->entry.size = dir->data.nFileSizeLow | ((UINT64) dir->data.nFileSizeHigh << 32); return (dir->entry.name != NULL) ? &dir->entry : NULL; }
osd_directory_entry *osd_stat(const char *path) { osd_directory_entry *result = NULL; TCHAR *t_path; HANDLE find = INVALID_HANDLE_VALUE; WIN32_FIND_DATA find_data; // convert the path to TCHARs t_path = tstring_from_utf8(path); if (t_path == NULL) goto done; // attempt to find the first file find = FindFirstFile(t_path, &find_data); if (find == INVALID_HANDLE_VALUE) goto done; // create an osd_directory_entry; be sure to make sure that the caller can // free all resources by just freeing the resulting osd_directory_entry result = (osd_directory_entry *) malloc(sizeof(*result) + strlen(path) + 1); if (!result) goto done; strcpy(((char *) result) + sizeof(*result), path); result->name = ((char *) result) + sizeof(*result); result->type = win_attributes_to_entry_type(find_data.dwFileAttributes); result->size = find_data.nFileSizeLow | ((UINT64) find_data.nFileSizeHigh << 32); done: if (t_path) osd_free(t_path); return result; }
std::unique_ptr<osd::directory::entry> osd_stat(const std::string &path) { // convert the path to TCHARs std::unique_ptr<TCHAR, void (*)(void *)> const t_path(tstring_from_utf8(path.c_str()), &osd_free); if (!t_path) return nullptr; // is this path a root directory (e.g. - C:)? WIN32_FIND_DATA find_data; std::memset(&find_data, 0, sizeof(find_data)); if (isalpha(path[0]) && (path[1] == ':') && (path[2] == '\0')) { // need to do special logic for root directories if (!GetFileAttributesEx(t_path.get(), GetFileExInfoStandard, &find_data.dwFileAttributes)) find_data.dwFileAttributes = INVALID_FILE_ATTRIBUTES; } else { // attempt to find the first file HANDLE find = FindFirstFileEx(t_path.get(), FindExInfoStandard, &find_data, FindExSearchNameMatch, nullptr, 0); if (find == INVALID_HANDLE_VALUE) return nullptr; FindClose(find); } // create an osd::directory::entry; be sure to make sure that the caller can // free all resources by just freeing the resulting osd::directory::entry osd::directory::entry *result; try { result = reinterpret_cast<osd::directory::entry *>(::operator new(sizeof(*result) + path.length() + 1)); } catch (...) { return nullptr; } new (result) osd::directory::entry; strcpy(((char *) result) + sizeof(*result), path.c_str()); result->name = ((char *) result) + sizeof(*result); result->type = win_attributes_to_entry_type(find_data.dwFileAttributes); result->size = find_data.nFileSizeLow | ((UINT64) find_data.nFileSizeHigh << 32); result->last_modified = win_time_point_from_filetime(&find_data.ftLastWriteTime); return std::unique_ptr<osd::directory::entry>(result); }