2222#include <stdio.h>
2323#include <stdlib.h>
2424#include <string.h>
25- #include <dirent.h>
26- #include <sys/types.h>
25+
26+ #ifdef _WIN32
27+ #define WIN32_LEAN_AND_MEAN
28+ #define NOGDI
29+ #include <windows.h>
30+ #include <io.h>
31+ #include <fcntl.h>
32+ #ifndef PATH_MAX
33+ #define PATH_MAX MAX_PATH
34+ #endif
35+ #define dc_open _open
36+ #define dc_read _read
37+ #define dc_close _close
38+ #define DC_O_RDONLY _O_RDONLY
39+ #define DC_O_BINARY _O_BINARY
40+ #else
2741#include <dirent.h>
2842#include <sys/types.h>
2943#include <sys/stat.h>
3044#include <fcntl.h>
3145#include <unistd.h>
46+ #define dc_open open
47+ #define dc_read read
48+ #define dc_close close
49+ #define DC_O_RDONLY O_RDONLY
50+ #ifdef O_BINARY
51+ #define DC_O_BINARY O_BINARY
52+ #else
53+ #define DC_O_BINARY 0
54+ #endif
55+ #endif
3256
57+ #include "platform.h"
3358#include "garmin.h"
3459#include "context-private.h"
3560#include "device-private.h"
@@ -275,6 +300,54 @@ add_name(struct file_list *files, const char *name, unsigned int mtp_id)
275300 entry -> mtp_id = mtp_id ;
276301}
277302
303+ #ifdef _WIN32
304+ static dc_status_t
305+ get_file_list (dc_device_t * abstract , const char * pathname , struct file_list * files )
306+ {
307+ WIN32_FIND_DATAA findData ;
308+ HANDLE hFind ;
309+ char searchPath [PATH_MAX ];
310+
311+ DEBUG (abstract -> context , "Iterating over Garmin files" );
312+
313+ // Create search pattern (pathname\*.fit)
314+ snprintf (searchPath , sizeof (searchPath ), "%s\\*" , pathname );
315+
316+ hFind = FindFirstFileA (searchPath , & findData );
317+ if (hFind == INVALID_HANDLE_VALUE ) {
318+ return DC_STATUS_IO ;
319+ }
320+
321+ do {
322+ // Skip directories
323+ if (findData .dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
324+ continue ;
325+
326+ if (!check_filename (abstract , findData .cFileName ))
327+ continue ;
328+
329+ dc_status_t rc = make_space (files );
330+ if (rc != DC_STATUS_SUCCESS ) {
331+ FindClose (hFind );
332+ return rc ;
333+ }
334+ add_name (files , findData .cFileName , 0 );
335+ } while (FindNextFileA (hFind , & findData ));
336+
337+ if (GetLastError () != ERROR_NO_MORE_FILES ) {
338+ FindClose (hFind );
339+ return DC_STATUS_IO ;
340+ }
341+
342+ FindClose (hFind );
343+
344+ DEBUG (abstract -> context , "Found %d files" , files -> nr );
345+
346+ if (files -> array )
347+ qsort (files -> array , files -> nr , sizeof (struct fit_file ), name_cmp );
348+ return DC_STATUS_SUCCESS ;
349+ }
350+ #else
278351static dc_status_t
279352get_file_list (dc_device_t * abstract , DIR * dir , struct file_list * files )
280353{
@@ -296,6 +369,7 @@ get_file_list(dc_device_t *abstract, DIR *dir, struct file_list *files)
296369 qsort (files -> array , files -> nr , sizeof (struct fit_file ), name_cmp );
297370 return DC_STATUS_SUCCESS ;
298371}
372+ #endif
299373
300374#ifdef HAVE_LIBMTP
301375static unsigned int
@@ -438,18 +512,14 @@ mtp_read_file(garmin_device_t *device, unsigned int file_id, dc_buffer_t *file)
438512}
439513#endif /* HAVE_LIBMTP */
440514
441- #ifndef O_BINARY
442- #define O_BINARY 0
443- #endif
444-
445515static dc_status_t
446516read_file (char * pathname , int pathlen , const char * name , dc_buffer_t * file )
447517{
448518 int fd , rc ;
449519
450520 pathname [pathlen ] = '/' ;
451521 memcpy (pathname + pathlen + 1 , name , FILE_NAME_SIZE );
452- fd = open (pathname , O_RDONLY | O_BINARY );
522+ fd = dc_open (pathname , DC_O_RDONLY | DC_O_BINARY );
453523
454524 if (fd < 0 )
455525 return DC_STATUS_IO ;
@@ -459,7 +529,7 @@ read_file(char *pathname, int pathlen, const char *name, dc_buffer_t *file)
459529 char buffer [4096 ];
460530 int n ;
461531
462- n = read (fd , buffer , sizeof (buffer ));
532+ n = dc_read (fd , buffer , sizeof (buffer ));
463533 if (!n )
464534 break ;
465535 if (n > 0 ) {
@@ -470,7 +540,7 @@ read_file(char *pathname, int pathlen, const char *name, dc_buffer_t *file)
470540 break ;
471541 }
472542
473- close (fd );
543+ dc_close (fd );
474544 return rc ;
475545}
476546
@@ -488,7 +558,9 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void
488558 NULL // array of file names / ids
489559 };
490560 dc_buffer_t * file ;
561+ #ifndef _WIN32
491562 DIR * dir ;
563+ #endif
492564 dc_status_t rc ;
493565
494566 // Read the directory name from the iostream
@@ -526,6 +598,35 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void
526598 } else
527599#endif
528600 { // slight coding style violation to deal with the non-MTP case
601+ #ifdef _WIN32
602+ // On Windows, get_file_list takes the pathname directly
603+ rc = get_file_list (abstract , pathname , & files );
604+ if (rc != DC_STATUS_SUCCESS ) {
605+ if (rc == DC_STATUS_NOMEMORY ) {
606+ free (files .array );
607+ return rc ;
608+ }
609+
610+ free (files .array );
611+ files .nr = 0 ;
612+ files .allocated = 0 ;
613+ files .array = NULL ;
614+
615+ // Try the input path directly
616+ rc = get_file_list (abstract , pathname_input , & files );
617+ if (rc != DC_STATUS_SUCCESS ) {
618+ ERROR (abstract -> context , "Failed to open directory '%s' or '%s'." , pathname , pathname_input );
619+ free (files .array );
620+ return rc ;
621+ }
622+ strcpy (pathname , pathname_input );
623+ pathlen = strlen (pathname );
624+ }
625+ if (!files .nr ) {
626+ free (files .array );
627+ return rc ;
628+ }
629+ #else
529630 dir = opendir (pathname );
530631 if (!dir ) {
531632 dir = opendir (pathname_input );
@@ -543,6 +644,7 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void
543644 free (files .array );
544645 return rc ;
545646 }
647+ #endif
546648 }
547649 // We found at least one file
548650 // Can we find the fingerprint entry?
0 commit comments