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 <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2020-10-27 15:18:31 -07:00
parent 8df5c15db9
commit 05e066b2ff

View File

@ -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;
}