From 05e066b2ff82dc284da2d06dd697098bd36eeed2 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Tue, 27 Oct 2020 15:18:31 -0700 Subject: [PATCH] Garmin: refactor the code to prepare for MTP support Breaking things into helper function makes it much easier to then support both regular file operations and MTP. This includes some mild whitespace cleanups for consistency. Signed-off-by: Dirk Hohndel --- src/garmin.c | 116 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/src/garmin.c b/src/garmin.c index aba013b..34f36a5 100644 --- a/src/garmin.c +++ b/src/garmin.c @@ -124,54 +124,75 @@ static int name_cmp(const void *a, const void *b) * * Return number of files found. */ -static int get_file_list(dc_device_t *abstract, DIR *dir, struct file_list *files) + +static int +check_filename(dc_device_t *abstract, const char *name) +{ + int len = strlen(name); + const char *explain = NULL; + + DEBUG(abstract->context, " %s", name); + + if (len < 5) + explain = "name too short"; + if (len >= FIT_NAME_SIZE) + explain = "name too long"; + if (strncasecmp(name + len - 4, ".FIT", 4)) + explain = "name lacks FIT suffix"; + + DEBUG(abstract->context, " %s - %s", name, explain ? explain : "adding to list"); + return explain == NULL; +} + +static dc_status_t +make_space(struct file_list *files) +{ + if (files->nr == files->allocated) { + struct fit_name *array; + int n = 3*(files->allocated + 8)/2; + size_t new_size; + + new_size = n * sizeof(array[0]); + array = realloc(files->array, new_size); + if (!array) + return DC_STATUS_NOMEMORY; + + files->array = array; + files->allocated = n; + } + return DC_STATUS_SUCCESS; +} + +static void +add_name(struct file_list *files, const char *name) +{ + /* + * NOTE! This depends on the zero-padding that strncpy does. + * + * strncpy() doesn't just limit the size of the copy, it + * will zero-pad the end of the result buffer. + */ + struct fit_name *entry = files->array + files->nr++; + strncpy(entry->name, name, FIT_NAME_SIZE); + entry->name[FIT_NAME_SIZE] = 0; // ensure it's null-terminated +} + +static dc_status_t +get_file_list(dc_device_t *abstract, DIR *dir, struct file_list *files) { struct dirent *de; - DEBUG (abstract->context, "Iterating over Garmin files"); + DEBUG(abstract->context, "Iterating over Garmin files"); while ((de = readdir(dir)) != NULL) { - int len = strlen(de->d_name); - struct fit_name *entry; - const char *explain = NULL; - - DEBUG (abstract->context, " %s", de->d_name); - - if (len < 5) - explain = "name too short"; - if (len >= FIT_NAME_SIZE) - explain = "name too long"; - if (strncasecmp(de->d_name + len - 4, ".FIT", 4)) - explain = "name lacks FIT suffix"; - - DEBUG (abstract->context, " %s - %s", de->d_name, explain ? explain : "adding to list"); - if (explain) + if (!check_filename(abstract, de->d_name)) continue; - if (files->nr == files->allocated) { - struct fit_name *array; - int n = 3*(files->allocated + 8)/2; - size_t new_size; - - new_size = n * sizeof(array[0]); - array = realloc(files->array, new_size); - if (!array) - return DC_STATUS_NOMEMORY; - - files->array = array; - files->allocated = n; - } - - /* - * NOTE! This depends on the zero-padding that strncpy does. - * - * strncpy() doesn't just limit the size of the copy, it - * will zero-pad the end of the result buffer. - */ - entry = files->array + files->nr++; - strncpy(entry->name, de->d_name, FIT_NAME_SIZE); - entry->name[FIT_NAME_SIZE] = 0; // ensure it's null-terminated + dc_status_t rc = make_space(files); + if (rc != DC_STATUS_SUCCESS) + return rc; + add_name(files, de->d_name); } - DEBUG (abstract->context, "Found %d files", files->nr); + DEBUG(abstract->context, "Found %d files", files->nr); qsort(files->array, files->nr, sizeof(struct fit_name), name_cmp); return DC_STATUS_SUCCESS; @@ -221,10 +242,14 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void dc_parser_t *parser; char pathname[PATH_MAX]; size_t pathlen; - struct file_list files = { 0, 0, NULL }; + struct file_list files = { + 0, // nr + 0, // allocated + NULL, // array of names + }; dc_buffer_t *file; DIR *dir; - int rc; + dc_status_t rc; // Read the directory name from the iostream rc = dc_iostream_read(device->iostream, &pathname, sizeof(pathname)-1, &pathlen); @@ -239,7 +264,6 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void ERROR (abstract->context, "Invalid Garmin base directory '%s'", pathname); return DC_STATUS_IO; } - if (pathlen && pathname[pathlen-1] != '/') pathname[pathlen++] = '/'; strcpy(pathname + pathlen, "Garmin/Activity"); @@ -268,7 +292,7 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void // Found fingerprint, just cut the array short here files.nr = i; - DEBUG (abstract->context, "Ignoring '%s' and older", name); + DEBUG(abstract->context, "Ignoring '%s' and older", name); break; } @@ -322,7 +346,7 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void devinfo_p = NULL; } if (!is_dive) { - DEBUG (abstract->context, "decided %s isn't a dive.", name); + DEBUG(abstract->context, "decided %s isn't a dive.", name); continue; }