bool tr_sys_path_get_info(char const* path, int flags, tr_sys_path_info* info, tr_error** error) { TR_ASSERT(path != NULL); TR_ASSERT(info != NULL); bool ret = false; wchar_t* wide_path = path_to_native_path(path); if ((flags & TR_SYS_PATH_NO_FOLLOW) == 0) { HANDLE handle = INVALID_HANDLE_VALUE; if (wide_path != NULL) { handle = CreateFileW(wide_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (handle != INVALID_HANDLE_VALUE) { tr_error* my_error = NULL; ret = tr_sys_file_get_info(handle, info, &my_error); if (!ret) { tr_error_propagate(error, &my_error); } CloseHandle(handle); } else { set_system_error(error, GetLastError()); } } else { WIN32_FILE_ATTRIBUTE_DATA attributes; if (wide_path != NULL) { ret = GetFileAttributesExW(wide_path, GetFileExInfoStandard, &attributes); } if (ret) { stat_to_sys_path_info(attributes.dwFileAttributes, attributes.nFileSizeLow, attributes.nFileSizeHigh, &attributes.ftLastWriteTime, info); } else { set_system_error(error, GetLastError()); } } tr_free(wide_path); return ret; }
static int test_get_info (void) { char * const test_dir = create_test_dir (__FUNCTION__); tr_sys_path_info info; tr_sys_file_t fd; tr_error * err = NULL; char * path1, * path2; time_t t; path1 = tr_buildPath (test_dir, "a", NULL); path2 = tr_buildPath (test_dir, "b", NULL); /* Can't get info of non-existent file/directory */ check (!tr_sys_path_get_info (path1, 0, &info, &err)); check (err != NULL); tr_error_clear (&err); t = time (NULL); libtest_create_file_with_string_contents (path1, "test"); /* Good file info */ clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); /* Good file info (by handle) */ fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL); clear_path_info (&info); check (tr_sys_file_get_info (fd, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_file_close (fd, NULL); tr_sys_path_remove (path1, NULL); /* Good directory info */ t = time (NULL); tr_sys_dir_create (path1, 0, 0777, NULL); clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type); check (info.size != (uint64_t) -1); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_path_remove (path1, NULL); if (create_symlink (path1, path2, false)) { /* Can't get info of non-existent file/directory */ check (!tr_sys_path_get_info (path1, 0, &info, &err)); check (err != NULL); tr_error_clear (&err); t = time (NULL); libtest_create_file_with_string_contents (path2, "test"); /* Good file info */ clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); /* Good file info (by handle) */ fd = tr_sys_file_open (path1, TR_SYS_FILE_READ, 0, NULL); clear_path_info (&info); check (tr_sys_file_get_info (fd, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_FILE, info.type); check_int_eq (4, info.size); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_file_close (fd, NULL); tr_sys_path_remove (path2, NULL); /* Good directory info */ t = time (NULL); tr_sys_dir_create (path2, 0, 0777, NULL); clear_path_info (&info); check (tr_sys_path_get_info (path1, 0, &info, &err)); check (err == NULL); check_int_eq (TR_SYS_PATH_IS_DIRECTORY, info.type); check (info.size != (uint64_t) -1); check (info.last_modified_at >= t && info.last_modified_at <= time (NULL)); tr_sys_path_remove (path2, NULL); tr_sys_path_remove (path1, NULL); } else { fprintf (stderr, "WARNING: [%s] unable to run symlink tests\n", __FUNCTION__); } tr_free (path2); tr_free (path1); tr_free (test_dir); return 0; }