Skip to content

Commit b991311

Browse files
author
Rosen Nedyalkov
committed
Implement windows native function for getting file size.
* This is required when UNC paths (e.g. \\?\Volume{guid}) are used, otherwise the stat() will fail
1 parent 4d4e46e commit b991311

File tree

1 file changed

+93
-10
lines changed

1 file changed

+93
-10
lines changed

src/ds3.c

Lines changed: 93 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21623,11 +21623,99 @@ size_t ds3_read_from_fd(void* buffer, size_t size, size_t nmemb, void* user_data
2162321623
return read(*(int*)user_data, buffer, size * nmemb);
2162421624
}
2162521625

21626+
static void get_file_size_windows(const char* file_path, uint64_t* file_size) {
21627+
BY_HANDLE_FILE_INFORMATION info;
21628+
HANDLE file_handle;
21629+
char * file_path_windows;
21630+
gunichar2 * file_path_windows_wide;
21631+
BOOL res;
21632+
21633+
file_path_windows = g_strdup(file_path);
21634+
21635+
/* Convert the path slashes to windows */
21636+
for (char * ch = file_path_windows; *ch != '\0'; ++ch) {
21637+
switch(*ch) {
21638+
case '/': *ch = '\\'; break;
21639+
}
21640+
}
21641+
21642+
*file_size = 0;
21643+
21644+
/* Convert the path to UTF16 to use in windows native function */
21645+
file_path_windows_wide = g_utf8_to_utf16(file_path_windows, -1, NULL, NULL, NULL);
21646+
if (file_path_windows_wide == NULL) {
21647+
fprintf(stderr, "error converting file name to wide char '%s'\n", file_path_windows);
21648+
g_free(file_path_windows);
21649+
return;
21650+
}
21651+
21652+
21653+
/* Open the file for attributes read only */
21654+
file_handle = CreateFileW(
21655+
(wchar_t*)file_path_windows_wide,
21656+
FILE_READ_ATTRIBUTES,
21657+
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
21658+
NULL,
21659+
OPEN_EXISTING,
21660+
FILE_ATTRIBUTE_NORMAL,
21661+
NULL);
21662+
g_free(file_path_windows_wide);
21663+
21664+
if (file_handle == INVALID_HANDLE_VALUE) {
21665+
g_free(file_path_windows);
21666+
fprintf(stderr, "error opening file '%s'\n", file_path_windows);
21667+
return;
21668+
}
21669+
21670+
res = GetFileInformationByHandle(file_handle, &info);
21671+
CloseHandle(file_handle);
21672+
21673+
if (!res) {
21674+
fprintf(stderr, "error getting file attributes\n");
21675+
g_free(file_path_windows);
21676+
return;
21677+
}
21678+
21679+
/* If entry is file get the file size */
21680+
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
21681+
ULARGE_INTEGER size;
21682+
size.LowPart = info.nFileSizeLow;
21683+
size.HighPart = info.nFileSizeHigh;
21684+
21685+
*file_size = size.QuadPart;
21686+
} else {
21687+
*file_size = 0;
21688+
}
21689+
21690+
g_free(file_path_windows);
21691+
21692+
return;
21693+
}
21694+
21695+
static void get_file_size_posix(const char* file_path, uint64_t* file_size) {
21696+
struct stat file_info;
21697+
int result;
21698+
21699+
result = stat(file_path, &file_info);
21700+
if (result != 0) {
21701+
fprintf(stderr, "Failed to get file info for '%s' res=%d errno=%d\n", file_path, result, errno);
21702+
*file_size = 0;
21703+
return;
21704+
}
21705+
21706+
if (S_ISDIR(file_info.st_mode)) {
21707+
*file_size = 0;
21708+
} else {
21709+
*file_size = file_info.st_size;
21710+
}
21711+
}
21712+
2162621713
static ds3_bulk_object_response* _ds3_bulk_object_from_file(const char* file_name, const char* base_path) {
2162721714
struct stat file_info;
2162821715
int result;
2162921716
ds3_bulk_object_response* obj = g_new0(ds3_bulk_object_response, 1);
2163021717
char* file_to_stat;
21718+
2163121719
memset(&file_info, 0, sizeof(struct stat));
2163221720

2163321721
if (base_path != NULL) {
@@ -21636,18 +21724,13 @@ static ds3_bulk_object_response* _ds3_bulk_object_from_file(const char* file_nam
2163621724
file_to_stat = g_strdup(file_name);
2163721725
}
2163821726

21639-
result = stat(file_to_stat, &file_info);
21640-
if (result != 0) {
21641-
fprintf(stderr, "Failed to get file info for %s\n", file_name);
21642-
}
21643-
2164421727
obj->name = ds3_str_init(file_name);
2164521728

21646-
if (S_ISDIR(file_info.st_mode)) {
21647-
obj->length = 0;
21648-
} else {
21649-
obj->length = file_info.st_size;
21650-
}
21729+
#ifdef _MSC_VER
21730+
get_file_size_windows(file_to_stat, &obj->length);
21731+
#else
21732+
get_file_size_posix(file_to_stat, &obj->length);
21733+
#endif
2165121734

2165221735
g_free(file_to_stat);
2165321736

0 commit comments

Comments
 (0)