diff --git a/tui/src/dashboard_layout.c b/tui/src/dashboard_layout.c index b5a4390..313f6aa 100644 --- a/tui/src/dashboard_layout.c +++ b/tui/src/dashboard_layout.c @@ -40,15 +40,18 @@ static const TrainlogDashboardTileLayout defaults[TRAINLOG_DASHBOARD_LAYOUT_TILE static int contract_index(const char *id) { size_t index; - for (index = 0U; index < TRAINLOG_DASHBOARD_LAYOUT_TILE_COUNT; ++index) - if (strcmp(id, contracts[index].id) == 0) + for (index = 0U; index < TRAINLOG_DASHBOARD_LAYOUT_TILE_COUNT; ++index) { + if (strcmp(id, contracts[index].id) == 0) { return (int)index; + } + } return -1; } void trainlog_dashboard_layout_default(TrainlogDashboardLayout *layout) { - if (layout == NULL) + if (layout == NULL) { return; + } layout->revision = 0U; (void)memcpy(layout->tiles, defaults, sizeof(defaults)); } @@ -61,25 +64,30 @@ static bool overlap(const TrainlogDashboardTileLayout *a, const TrainlogDashboar bool trainlog_dashboard_layout_validate(const TrainlogDashboardLayout *layout) { bool seen[TRAINLOG_DASHBOARD_LAYOUT_TILE_COUNT] = {false}; size_t index; - if (layout == NULL || layout->revision > TRAINLOG_DASHBOARD_LAYOUT_MAX_REVISION) + if (layout == NULL || layout->revision > TRAINLOG_DASHBOARD_LAYOUT_MAX_REVISION) { return false; + } for (index = 0U; index < TRAINLOG_DASHBOARD_LAYOUT_TILE_COUNT; ++index) { const TrainlogDashboardTileLayout *tile = &layout->tiles[index]; int found = contract_index(tile->id); const TileContract *contract; size_t other; - if (found < 0 || seen[(size_t)found]) + if (found < 0 || seen[(size_t)found]) { return false; + } seen[(size_t)found] = true; contract = &contracts[(size_t)found]; if (tile->y > TRAINLOG_DASHBOARD_LAYOUT_MAX_Y || tile->width < contract->min_width || tile->width > contract->max_width || tile->height < contract->min_height || tile->height > contract->max_height || - tile->x + tile->width > TRAINLOG_DASHBOARD_LAYOUT_COLUMNS) + tile->x + tile->width > TRAINLOG_DASHBOARD_LAYOUT_COLUMNS) { return false; - for (other = index + 1U; other < TRAINLOG_DASHBOARD_LAYOUT_TILE_COUNT; ++other) - if (overlap(tile, &layout->tiles[other])) + } + for (other = index + 1U; other < TRAINLOG_DASHBOARD_LAYOUT_TILE_COUNT; ++other) { + if (overlap(tile, &layout->tiles[other])) { return false; + } + } } return true; } @@ -90,11 +98,13 @@ static bool exact_object(const yyjson_val *value, size_t expected) { static bool read_u16(yyjson_val *value, uint16_t *output) { uint64_t number; - if (!yyjson_is_uint(value)) + if (!yyjson_is_uint(value)) { return false; + } number = yyjson_get_uint(value); - if (number > UINT16_MAX) + if (number > UINT16_MAX) { return false; + } *output = (uint16_t)number; return true; } @@ -111,11 +121,13 @@ trainlog_dashboard_layout_parse(const char *json, size_t size, TrainlogDashboard yyjson_val *tiles; size_t index; if (json == NULL || layout == NULL || size == 0U || - size >= TRAINLOG_DASHBOARD_LAYOUT_JSON_CAPACITY) + size >= TRAINLOG_DASHBOARD_LAYOUT_JSON_CAPACITY) { return TRAINLOG_DASHBOARD_LAYOUT_INVALID; + } document = yyjson_read_opts((char *)json, size, YYJSON_READ_NOFLAG, NULL, &error); - if (document == NULL) + if (document == NULL) { return TRAINLOG_DASHBOARD_LAYOUT_INVALID; + } root = yyjson_doc_get_root(document); if (!exact_object(root, 5U) || !yyjson_equals_str(yyjson_obj_get(root, "format"), "trainlog-dashboard-layout") || @@ -162,14 +174,16 @@ bool trainlog_dashboard_layout_path(char *output, size_t capacity) { const char *base = getenv("XDG_CONFIG_HOME"); const char *home; int length; - if (output == NULL || capacity == 0U) + if (output == NULL || capacity == 0U) { return false; - if (base != NULL && base[0] != '\0') + } + if (base != NULL && base[0] != '\0') { length = snprintf(output, capacity, "%s/trainlog/web/dashboard-layout-v1.json", base); - else { + } else { home = getenv("HOME"); - if (home == NULL || home[0] == '\0') + if (home == NULL || home[0] == '\0') { return false; + } length = snprintf(output, capacity, "%s/.config/trainlog/web/dashboard-layout-v1.json", home); } @@ -181,32 +195,40 @@ static bool ensure_private_directories(const char *path) { char trainlog[4096]; char *last; struct stat status; - if (path == NULL || strlen(path) >= sizeof(web)) + if (path == NULL || strlen(path) >= sizeof(web)) { return false; + } (void)snprintf(web, sizeof(web), "%s", path); last = strrchr(web, '/'); - if (last == NULL) + if (last == NULL) { return false; + } *last = '\0'; (void)snprintf(trainlog, sizeof(trainlog), "%s", web); last = strrchr(trainlog, '/'); - if (last == NULL) + if (last == NULL) { return false; + } *last = '\0'; /* CONTRACT: only the two Trainlog-owned directories are created/chmodded; * an existing symlink or non-directory is never followed. */ { - if (mkdir(trainlog, 0700) != 0 && errno != EEXIST) + if (mkdir(trainlog, 0700) != 0 && errno != EEXIST) { return false; - if (lstat(trainlog, &status) != 0 || !S_ISDIR(status.st_mode)) + } + if (lstat(trainlog, &status) != 0 || !S_ISDIR(status.st_mode)) { return false; - if (chmod(trainlog, 0700) != 0) + } + if (chmod(trainlog, 0700) != 0) { return false; + } } - if (mkdir(web, 0700) != 0 && errno != EEXIST) + if (mkdir(web, 0700) != 0 && errno != EEXIST) { return false; - if (lstat(web, &status) != 0 || !S_ISDIR(status.st_mode)) + } + if (lstat(web, &status) != 0 || !S_ISDIR(status.st_mode)) { return false; + } return chmod(web, 0700) == 0; } @@ -215,19 +237,23 @@ static bool sync_parent(const char *path) { char *slash; int fd; bool ok; - if (strlen(path) >= sizeof(parent)) + if (strlen(path) >= sizeof(parent)) { return false; + } (void)snprintf(parent, sizeof(parent), "%s", path); slash = strrchr(parent, '/'); - if (slash == NULL) + if (slash == NULL) { return false; + } *slash = '\0'; fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); - if (fd < 0) + if (fd < 0) { return false; + } ok = fsync(fd) == 0; - if (close(fd) != 0) + if (close(fd) != 0) { ok = false; + } return ok; } @@ -244,8 +270,9 @@ bool trainlog_dashboard_layout_serialize(const TrainlogDashboardLayout *layout, : source == TRAINLOG_DASHBOARD_LAYOUT_INVALID_PERSISTED ? "invalid_persisted" : "default"; - if (!trainlog_dashboard_layout_validate(layout) || output == NULL || size == NULL) + if (!trainlog_dashboard_layout_validate(layout) || output == NULL || size == NULL) { return false; + } #define APPEND(...) \ do { \ count = snprintf(output + used, capacity - used, __VA_ARGS__); \ @@ -256,8 +283,9 @@ bool trainlog_dashboard_layout_serialize(const TrainlogDashboardLayout *layout, APPEND("{\"format\":\"trainlog-dashboard-layout\",\"version\":1," "\"revision\":%llu,\"columns\":12", (unsigned long long)layout->revision); - if (include_source) + if (include_source) { APPEND(",\"source\":\"%s\"", source_name); + } APPEND(",\"tiles\":["); for (index = 0U; index < TRAINLOG_DASHBOARD_LAYOUT_TILE_COUNT; ++index) { const TrainlogDashboardTileLayout *tile = &layout->tiles[index]; @@ -284,15 +312,17 @@ trainlog_dashboard_layout_load(TrainlogDashboardLayout *layout, ssize_t count; int fd; TrainlogDashboardLayoutResult result; - if (layout == NULL || source == NULL || !trainlog_dashboard_layout_path(path, sizeof(path))) + if (layout == NULL || source == NULL || !trainlog_dashboard_layout_path(path, sizeof(path))) { return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; + } trainlog_dashboard_layout_default(layout); *source = TRAINLOG_DASHBOARD_LAYOUT_DEFAULT; fd = open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK); if (fd < 0) { if (errno == ENOENT || errno == ELOOP) { - if (errno == ELOOP) + if (errno == ELOOP) { *source = TRAINLOG_DASHBOARD_LAYOUT_INVALID_PERSISTED; + } return TRAINLOG_DASHBOARD_LAYOUT_OK; } return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; @@ -312,8 +342,9 @@ trainlog_dashboard_layout_load(TrainlogDashboardLayout *layout, if (result != TRAINLOG_DASHBOARD_LAYOUT_OK) { trainlog_dashboard_layout_default(layout); *source = TRAINLOG_DASHBOARD_LAYOUT_INVALID_PERSISTED; - } else + } else { *source = TRAINLOG_DASHBOARD_LAYOUT_PERSISTED; + } return TRAINLOG_DASHBOARD_LAYOUT_OK; } @@ -321,10 +352,12 @@ static bool write_all(int fd, const char *data, size_t size) { size_t used = 0U; while (used < size) { ssize_t count = write(fd, data + used, size - used); - if (count < 0 && errno == EINTR) + if (count < 0 && errno == EINTR) { continue; - if (count <= 0) + } + if (count <= 0) { return false; + } used += (size_t)count; } return true; @@ -341,26 +374,32 @@ TrainlogDashboardLayoutResult trainlog_dashboard_layout_save(const TrainlogDashb bool ok; if (layout == NULL || saved == NULL || !trainlog_dashboard_layout_validate(layout) || layout->revision != expected_revision || - expected_revision >= TRAINLOG_DASHBOARD_LAYOUT_MAX_REVISION) + expected_revision >= TRAINLOG_DASHBOARD_LAYOUT_MAX_REVISION) { return TRAINLOG_DASHBOARD_LAYOUT_INVALID; - if (trainlog_dashboard_layout_load(¤t, &source) != TRAINLOG_DASHBOARD_LAYOUT_OK) + } + if (trainlog_dashboard_layout_load(¤t, &source) != TRAINLOG_DASHBOARD_LAYOUT_OK) { return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; - if (current.revision != expected_revision) + } + if (current.revision != expected_revision) { return TRAINLOG_DASHBOARD_LAYOUT_CONFLICT; + } *saved = *layout; saved->revision = expected_revision + 1U; if (!trainlog_dashboard_layout_path(path, sizeof(path)) || !ensure_private_directories(path) || !trainlog_dashboard_layout_serialize( saved, TRAINLOG_DASHBOARD_LAYOUT_PERSISTED, false, json, sizeof(json), &size) || - snprintf(temporary, sizeof(temporary), "%s.tmp.XXXXXX", path) >= (int)sizeof(temporary)) + snprintf(temporary, sizeof(temporary), "%s.tmp.XXXXXX", path) >= (int)sizeof(temporary)) { return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; + } fd = mkstemp(temporary); - if (fd < 0) + if (fd < 0) { return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; + } ok = fchmod(fd, 0600) == 0 && fcntl(fd, F_SETFD, FD_CLOEXEC) == 0 && write_all(fd, json, size) && fsync(fd) == 0; - if (close(fd) != 0) + if (close(fd) != 0) { ok = false; + } if (!ok || rename(temporary, path) != 0) { (void)unlink(temporary); return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; @@ -376,12 +415,15 @@ TrainlogDashboardLayoutResult trainlog_dashboard_layout_delete(uint64_t expected TrainlogDashboardLayout current; TrainlogDashboardLayoutSource source; char path[4096]; - if (trainlog_dashboard_layout_load(¤t, &source) != TRAINLOG_DASHBOARD_LAYOUT_OK) + if (trainlog_dashboard_layout_load(¤t, &source) != TRAINLOG_DASHBOARD_LAYOUT_OK) { return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; - if (current.revision != expected_revision) + } + if (current.revision != expected_revision) { return TRAINLOG_DASHBOARD_LAYOUT_CONFLICT; - if (!trainlog_dashboard_layout_path(path, sizeof(path))) + } + if (!trainlog_dashboard_layout_path(path, sizeof(path))) { return TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; + } if (unlink(path) != 0) { return errno == ENOENT ? TRAINLOG_DASHBOARD_LAYOUT_OK : TRAINLOG_DASHBOARD_LAYOUT_IO_ERROR; } diff --git a/tui/src/generation_mtp.c b/tui/src/generation_mtp.c index a397617..600f02b 100644 --- a/tui/src/generation_mtp.c +++ b/tui/src/generation_mtp.c @@ -18,8 +18,9 @@ typedef struct Selection { } Selection; static void diag(char *output, size_t size, const char *value) { - if (output != NULL && size > 0U) + if (output != NULL && size > 0U) { (void)snprintf(output, size, "%s", value); + } } static bool safe_leaf(const char *name) { @@ -50,16 +51,18 @@ static TrainlogStatus one_named(const TrainlogGenerationMtpIo *io, TrainlogMtpEntry entries[TRAINLOG_GENERATION_MTP_MAX_CHILDREN]; size_t count = 0U, index, matches = 0U; TrainlogStatus status = children(io, selection, parent, entries, &count); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; + } for (index = 0U; index < count; ++index) { if (entries[index].folder == folder && strcmp(entries[index].name, name) == 0) { *result = entries[index]; ++matches; } } - if (matches > 1U) + if (matches > 1U) { return TRAINLOG_STATUS_CONFLICT; + } return matches == 1U ? TRAINLOG_STATUS_OK : TRAINLOG_STATUS_NOT_FOUND; } @@ -71,16 +74,19 @@ static bool peer_document_matches(const char *path, const char *expected) { yyjson_val *root, *capabilities, *item; size_t index, maximum; bool manifest = false, acknowledgement = false, valid; - if (fd < 0) + if (fd < 0) { return false; + } count = read(fd, buffer, sizeof(buffer)); (void)close(fd); - if (count <= 0 || (size_t)count >= sizeof(buffer)) + if (count <= 0 || (size_t)count >= sizeof(buffer)) { return false; + } buffer[count] = '\0'; document = yyjson_read(buffer, (size_t)count, YYJSON_READ_NOFLAG); - if (document == NULL) + if (document == NULL) { return false; + } root = yyjson_doc_get_root(document); capabilities = yyjson_obj_get(root, "capabilities"); valid = yyjson_is_obj(root) && yyjson_obj_size(root) == 4U && @@ -95,10 +101,12 @@ static bool peer_document_matches(const char *path, const char *expected) { valid = false; break; } - if (yyjson_equals_str(item, "generation-manifest-v1")) + if (yyjson_equals_str(item, "generation-manifest-v1")) { manifest = true; - if (yyjson_equals_str(item, "generation-ack-v1")) + } + if (yyjson_equals_str(item, "generation-ack-v1")) { acknowledgement = true; + } } } yyjson_doc_free(document); @@ -131,8 +139,9 @@ static TrainlogStatus select_peer(const TrainlogGenerationMtpIo *io, storages, TRAINLOG_GENERATION_MTP_MAX_STORAGES, &storage_count); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { continue; + } for (si = 0U; si < storage_count; ++si) { Selection candidate = { devices[di].bus_number, devices[di].device_number, storages[si].storage_id, 0U}; @@ -140,18 +149,21 @@ static TrainlogStatus select_peer(const TrainlogGenerationMtpIo *io, if (one_named(io, &candidate, UINT32_MAX, "Documents", true, &documents) != TRAINLOG_STATUS_OK || one_named(io, &candidate, documents.item_id, "Trainlog", true, &root) != - TRAINLOG_STATUS_OK) + TRAINLOG_STATUS_OK) { continue; + } candidate.root = root.item_id; if (one_named(io, &candidate, candidate.root, "android-peer-v1.json", false, &peer) != - TRAINLOG_STATUS_OK) + TRAINLOG_STATUS_OK) { continue; + } (void)unlink(peer_path); if (peer.size_bytes > 16384U || io->receive(candidate.bus, candidate.device, peer.item_id, peer_path) != TRAINLOG_STATUS_OK || - !peer_document_matches(peer_path, expected)) + !peer_document_matches(peer_path, expected)) { continue; + } *output = candidate; ++matches; } @@ -169,8 +181,9 @@ static TrainlogStatus select_peer(const TrainlogGenerationMtpIo *io, } static TrainlogStatus mkdir_private(const char *path) { - if (mkdir(path, 0700) == 0 || errno == EEXIST) + if (mkdir(path, 0700) == 0 || errno == EEXIST) { return TRAINLOG_STATUS_OK; + } return TRAINLOG_STATUS_SYSTEM_ERROR; } @@ -184,70 +197,89 @@ static TrainlogStatus pull_folder(const TrainlogGenerationMtpIo *io, TrainlogMtpEntry entries[TRAINLOG_GENERATION_MTP_MAX_CHILDREN]; size_t count = 0U, index; TrainlogStatus status; - if (depth > TRAINLOG_GENERATION_MTP_MAX_DEPTH) + if (depth > TRAINLOG_GENERATION_MTP_MAX_DEPTH) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } status = mkdir_private(local); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; + } status = children(io, selection, parent, entries, &count); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; - if (*objects > TRAINLOG_GENERATION_MTP_MAX_CHILDREN - count) + } + if (*objects > TRAINLOG_GENERATION_MTP_MAX_CHILDREN - count) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } *objects += count; for (index = 0U; index < count; ++index) { char path[1024], temporary[1060]; int written; written = snprintf(path, sizeof(path), "%s/%s", local, entries[index].name); - if (!safe_leaf(entries[index].name) || written < 0 || (size_t)written >= sizeof(path)) + if (!safe_leaf(entries[index].name) || written < 0 || (size_t)written >= sizeof(path)) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } if (entries[index].folder) { status = pull_folder( io, selection, entries[index].item_id, path, depth + 1U, total, objects); } else { struct stat value; if (entries[index].size_bytes > TRAINLOG_GENERATION_MTP_MAX_TOTAL_BYTES || - *total > TRAINLOG_GENERATION_MTP_MAX_TOTAL_BYTES - entries[index].size_bytes) + *total > TRAINLOG_GENERATION_MTP_MAX_TOTAL_BYTES - entries[index].size_bytes) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } *total += entries[index].size_bytes; written = snprintf(temporary, sizeof(temporary), "%s.part.%ld", path, (long)getpid()); - if (written < 0 || (size_t)written >= sizeof(temporary)) + if (written < 0 || (size_t)written >= sizeof(temporary)) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } (void)unlink(temporary); status = io->receive(selection->bus, selection->device, entries[index].item_id, temporary); if (status == TRAINLOG_STATUS_OK && (stat(temporary, &value) != 0 || value.st_size < 0 || (uint64_t)value.st_size != entries[index].size_bytes || - rename(temporary, path) != 0)) + rename(temporary, path) != 0)) { status = TRAINLOG_STATUS_SYSTEM_ERROR; - if (status != TRAINLOG_STATUS_OK) + } + if (status != TRAINLOG_STATUS_OK) { (void)unlink(temporary); + } } - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; + } } return TRAINLOG_STATUS_OK; } static bool same_files(const char *left, const char *right) { - int a = open(left, O_RDONLY | O_CLOEXEC), b = open(right, O_RDONLY | O_CLOEXEC); - char ab[8192], bb[8192]; - ssize_t ac = 0, bc; + int left_fd = open(left, O_RDONLY | O_CLOEXEC); + int right_fd = open(right, O_RDONLY | O_CLOEXEC); + char left_buffer[8192]; + char right_buffer[8192]; + ssize_t left_count = 0; + ssize_t right_count; bool same = true; - if (a < 0 || b < 0) + if (left_fd < 0 || right_fd < 0) { same = false; - while (same && (ac = read(a, ab, sizeof(ab))) > 0) { - bc = read(b, bb, (size_t)ac); - if (bc != ac || memcmp(ab, bb, (size_t)ac) != 0) - same = false; } - if (same && (ac < 0 || read(b, bb, 1U) != 0)) + while (same && (left_count = read(left_fd, left_buffer, sizeof(left_buffer))) > 0) { + right_count = read(right_fd, right_buffer, (size_t)left_count); + if (right_count != left_count || + memcmp(left_buffer, right_buffer, (size_t)left_count) != 0) { + same = false; + } + } + if (same && (left_count < 0 || read(right_fd, right_buffer, 1U) != 0)) { same = false; - if (a >= 0) - (void)close(a); - if (b >= 0) - (void)close(b); + } + if (left_fd >= 0) { + (void)close(left_fd); + } + if (right_fd >= 0) { + (void)close(right_fd); + } return same; } @@ -265,8 +297,9 @@ static TrainlogStatus push_file(const TrainlogGenerationMtpIo *io, (void)snprintf(comparison, sizeof(comparison), "%s.compare.%ld", local, (long)getpid()); (void)unlink(comparison); status = io->receive(selection->bus, selection->device, existing.item_id, comparison); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; + } if (same_files(local, comparison)) { (void)unlink(comparison); return TRAINLOG_STATUS_OK; @@ -281,8 +314,9 @@ static TrainlogStatus push_file(const TrainlogGenerationMtpIo *io, local, temporary_name, &uploaded); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; + } (void)snprintf(comparison, sizeof(comparison), "%s.verify.%ld", local, (long)getpid()); (void)unlink(comparison); status = io->receive(selection->bus, selection->device, uploaded, comparison); @@ -293,16 +327,19 @@ static TrainlogStatus push_file(const TrainlogGenerationMtpIo *io, } (void)unlink(comparison); status = io->remove(selection->bus, selection->device, existing.item_id); - if (status == TRAINLOG_STATUS_OK) + if (status == TRAINLOG_STATUS_OK) { status = io->rename(selection->bus, selection->device, uploaded, name); + } return status; } - if (status != TRAINLOG_STATUS_NOT_FOUND) + if (status != TRAINLOG_STATUS_NOT_FOUND) { return status; + } status = io->send( selection->bus, selection->device, selection->storage, parent, local, name, &uploaded); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; + } (void)snprintf(comparison, sizeof(comparison), "%s.verify.%ld", local, (long)getpid()); (void)unlink(comparison); status = io->receive(selection->bus, selection->device, uploaded, comparison); @@ -324,17 +361,20 @@ static TrainlogStatus push_folder(const TrainlogGenerationMtpIo *io, DIR *directory; struct dirent *entry; TrainlogStatus status = TRAINLOG_STATUS_OK; - if (depth > TRAINLOG_GENERATION_MTP_MAX_DEPTH || (directory = opendir(local)) == NULL) + if (depth > TRAINLOG_GENERATION_MTP_MAX_DEPTH || (directory = opendir(local)) == NULL) { return TRAINLOG_STATUS_SYSTEM_ERROR; + } while ((entry = readdir(directory)) != NULL && status == TRAINLOG_STATUS_OK) { char path[1024]; struct stat value; uint32_t child; bool created; - if (!safe_leaf(entry->d_name) || entry->d_name[0] == '.') + if (!safe_leaf(entry->d_name) || entry->d_name[0] == '.') { continue; - if ((strcmp(entry->d_name, "manifest.json") == 0) != manifests) + } + if ((strcmp(entry->d_name, "manifest.json") == 0) != manifests) { continue; + } int written = snprintf(path, sizeof(path), "%s/%s", local, entry->d_name); if (written < 0 || (size_t)written >= sizeof(path) || lstat(path, &value) != 0 || S_ISLNK(value.st_mode)) { @@ -342,8 +382,9 @@ static TrainlogStatus push_folder(const TrainlogGenerationMtpIo *io, break; } if (S_ISDIR(value.st_mode)) { - if (manifests) + if (manifests) { continue; + } status = io->ensure_folder(selection->bus, selection->device, selection->storage, @@ -351,12 +392,15 @@ static TrainlogStatus push_folder(const TrainlogGenerationMtpIo *io, entry->d_name, &child, &created); - if (status == TRAINLOG_STATUS_OK) + if (status == TRAINLOG_STATUS_OK) { status = push_folder(io, selection, child, path, depth + 1U, false); - if (status == TRAINLOG_STATUS_OK) + } + if (status == TRAINLOG_STATUS_OK) { status = push_folder(io, selection, child, path, depth + 1U, true); - } else if (S_ISREG(value.st_mode)) + } + } else if (S_ISREG(value.st_mode)) { status = push_file(io, selection, parent, path, entry->d_name); + } } (void)closedir(directory); return status; @@ -367,14 +411,16 @@ validate_local_folder(const char *local, unsigned int depth, uint64_t *total, si DIR *directory; struct dirent *entry; TrainlogStatus status = TRAINLOG_STATUS_OK; - if (depth > TRAINLOG_GENERATION_MTP_MAX_DEPTH || (directory = opendir(local)) == NULL) + if (depth > TRAINLOG_GENERATION_MTP_MAX_DEPTH || (directory = opendir(local)) == NULL) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } while ((entry = readdir(directory)) != NULL && status == TRAINLOG_STATUS_OK) { char path[1024]; struct stat value; int written; - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; + } if (!safe_leaf(entry->d_name) || entry->d_name[0] == '.') { status = TRAINLOG_STATUS_INVALID_ARGUMENT; break; @@ -390,16 +436,18 @@ validate_local_folder(const char *local, unsigned int depth, uint64_t *total, si break; } ++*objects; - if (S_ISDIR(value.st_mode)) + if (S_ISDIR(value.st_mode)) { status = validate_local_folder(path, depth + 1U, total, objects); - else if (S_ISREG(value.st_mode)) { + } else if (S_ISREG(value.st_mode)) { if (value.st_size < 0 || - (uint64_t)value.st_size > TRAINLOG_GENERATION_MTP_MAX_TOTAL_BYTES - *total) + (uint64_t)value.st_size > TRAINLOG_GENERATION_MTP_MAX_TOTAL_BYTES - *total) { status = TRAINLOG_STATUS_INVALID_ARGUMENT; - else + } else { *total += (uint64_t)value.st_size; - } else + } + } else { status = TRAINLOG_STATUS_INVALID_ARGUMENT; + } } (void)closedir(directory); return status; @@ -414,13 +462,16 @@ TrainlogStatus trainlog_generation_mtp_pull(const TrainlogGenerationMtpIo *io, uint64_t total = 0U; size_t objects = 0U; TrainlogStatus status; - if (io == NULL || expected == NULL || local == NULL) + if (io == NULL || expected == NULL || local == NULL) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } status = mkdir_private(local); - if (status == TRAINLOG_STATUS_OK) + if (status == TRAINLOG_STATUS_OK) { status = select_peer(io, expected, local, &selection, diagnostic, diagnostic_size); - if (status == TRAINLOG_STATUS_OK) + } + if (status == TRAINLOG_STATUS_OK) { status = pull_folder(io, &selection, selection.root, local, 0U, &total, &objects); + } return status; } @@ -433,26 +484,32 @@ TrainlogStatus trainlog_generation_mtp_push(const TrainlogGenerationMtpIo *io, TrainlogStatus status; uint64_t total = 0U; size_t objects = 0U; - if (io == NULL || expected == NULL || local == NULL) + if (io == NULL || expected == NULL || local == NULL) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } status = validate_local_folder(local, 0U, &total, &objects); - if (status == TRAINLOG_STATUS_OK) + if (status == TRAINLOG_STATUS_OK) { status = select_peer(io, expected, local, &selection, diagnostic, diagnostic_size); - if (status == TRAINLOG_STATUS_OK) + } + if (status == TRAINLOG_STATUS_OK) { status = push_folder(io, &selection, selection.root, local, 0U, false); - if (status == TRAINLOG_STATUS_OK) + } + if (status == TRAINLOG_STATUS_OK) { status = push_folder(io, &selection, selection.root, local, 0U, true); + } return status; } -static const TrainlogGenerationMtpIo production = {trainlog_usb_list_mtp_devices, - trainlog_mtp_list_storages, - trainlog_mtp_list_folder, - trainlog_mtp_ensure_folder, - trainlog_mtp_receive_file, - trainlog_mtp_send_text_file, - trainlog_mtp_delete_object, - trainlog_mtp_rename_object}; +static const TrainlogGenerationMtpIo production = { + .devices = trainlog_usb_list_mtp_devices, + .storages = trainlog_mtp_list_storages, + .children = trainlog_mtp_list_folder, + .ensure_folder = trainlog_mtp_ensure_folder, + .receive = trainlog_mtp_receive_file, + .send = trainlog_mtp_send_text_file, + .remove = trainlog_mtp_delete_object, + .rename = trainlog_mtp_rename_object, +}; const TrainlogGenerationMtpIo *trainlog_generation_mtp_production_io(void) { return &production; } diff --git a/tui/src/json_writer.c b/tui/src/json_writer.c index 766eb02..205d53d 100644 --- a/tui/src/json_writer.c +++ b/tui/src/json_writer.c @@ -7,8 +7,9 @@ static bool append(TrainlogJsonWriter *w, const char *s, size_t n) { if (w == NULL || s == NULL || w->failed || n > w->capacity - (w->size < w->capacity ? w->size : w->capacity) - 1U) { - if (w != NULL) + if (w != NULL) { w->failed = true; + } return false; } (void)memcpy(w->data + w->size, s, n); @@ -17,14 +18,16 @@ static bool append(TrainlogJsonWriter *w, const char *s, size_t n) { return true; } void trainlog_json_init(TrainlogJsonWriter *w, char *data, size_t capacity) { - if (w == NULL) + if (w == NULL) { return; + } w->data = data; w->capacity = capacity; w->size = 0U; w->failed = data == NULL || capacity == 0U; - if (!w->failed) + if (!w->failed) { data[0] = '\0'; + } } bool trainlog_json_raw(TrainlogJsonWriter *w, const char *v) { return v != NULL && append(w, v, strlen(v)); @@ -32,8 +35,9 @@ bool trainlog_json_raw(TrainlogJsonWriter *w, const char *v) { bool trainlog_json_string(TrainlogJsonWriter *w, const char *v) { const unsigned char *p = (const unsigned char *)v; char escape[7]; - if (v == NULL || !append(w, "\"", 1U)) + if (v == NULL || !append(w, "\"", 1U)) { return false; + } while (*p != '\0') { utf8proc_int32_t codepoint; utf8proc_ssize_t sequence = utf8proc_iterate(p, -1, &codepoint); @@ -47,8 +51,9 @@ bool trainlog_json_string(TrainlogJsonWriter *w, const char *v) { if (*p == '\"' || *p == '\\') { escape[0] = '\\'; escape[1] = (char)*p; - if (!append(w, escape, 2U)) + if (!append(w, escape, 2U)) { return false; + } } else if (*p == '\b' || *p == '\f' || *p == '\n' || *p == '\r' || *p == '\t') { const char codes[] = "bfnrt"; const char chars[] = "\b\f\n\r\t"; @@ -57,14 +62,17 @@ bool trainlog_json_string(TrainlogJsonWriter *w, const char *v) { for (i = 0U; i < 5U && chars[i] != (char)*p; ++i) { } escape[1] = codes[i]; - if (!append(w, escape, 2U)) + if (!append(w, escape, 2U)) { return false; + } } else if (*p < 0x20U) { int n = snprintf(escape, sizeof(escape), "\\u%04x", (unsigned int)*p); - if (n != 6 || !append(w, escape, 6U)) + if (n != 6 || !append(w, escape, 6U)) { return false; - } else if (!append(w, (const char *)p, (size_t)sequence)) + } + } else if (!append(w, (const char *)p, (size_t)sequence)) { return false; + } p += (size_t)sequence; } return append(w, "\"", 1U); diff --git a/tui/src/web_dashboard.c b/tui/src/web_dashboard.c index c043d44..b504952 100644 --- a/tui/src/web_dashboard.c +++ b/tui/src/web_dashboard.c @@ -18,23 +18,27 @@ static bool copy_column(sqlite3_stmt *s, int column, char *out, size_t cap) { const unsigned char *text; int bytes; - if (sqlite3_column_type(s, column) != SQLITE_TEXT) + if (sqlite3_column_type(s, column) != SQLITE_TEXT) { return false; + } text = sqlite3_column_text(s, column); bytes = sqlite3_column_bytes(s, column); - if (text == NULL || bytes < 0 || (size_t)bytes >= cap) + if (text == NULL || bytes < 0 || (size_t)bytes >= cap) { return false; + } (void)memcpy(out, text, (size_t)bytes); out[bytes] = '\0'; return true; } static bool read_size(sqlite3_stmt *s, int c, size_t *out) { sqlite3_int64 v; - if (sqlite3_column_type(s, c) != SQLITE_INTEGER) + if (sqlite3_column_type(s, c) != SQLITE_INTEGER) { return false; + } v = sqlite3_column_int64(s, c); - if (v < 0 || (uint64_t)v > (uint64_t)SIZE_MAX) + if (v < 0 || (uint64_t)v > (uint64_t)SIZE_MAX) { return false; + } *out = (size_t)v; return true; } @@ -45,8 +49,9 @@ static bool prepare(TrainlogDatabase *d, const char *sql, sqlite3_stmt **s) { static bool format_generated(int64_t now, char out[TRAINLOG_TIMESTAMP_MAX + 1U]) { time_t value = (time_t)now; struct tm utc; - if ((int64_t)value != now || gmtime_r(&value, &utc) == NULL) + if ((int64_t)value != now || gmtime_r(&value, &utc) == NULL) { return false; + } return strftime(out, TRAINLOG_TIMESTAMP_MAX + 1U, "%Y-%m-%dT%H:%M:%SZ", &utc) > 0U; } static bool format_local_date(time_t value, char out[11]) { @@ -59,8 +64,9 @@ static bool load_user(char out[TRAINLOG_NAME_MAX + 1U]) { char buffer[4096]; int rc = getpwuid_r(geteuid(), &value, buffer, sizeof(buffer), &result); if (rc != 0 || result == NULL || result->pw_name == NULL || result->pw_name[0] == '\0' || - strlen(result->pw_name) > TRAINLOG_NAME_MAX) + strlen(result->pw_name) > TRAINLOG_NAME_MAX) { return false; + } (void)snprintf(out, TRAINLOG_NAME_MAX + 1U, "%s", result->pw_name); return true; } @@ -83,10 +89,12 @@ load_activity(TrainlogDatabase *d, int64_t now, TrainlogWebDashboardSnapshot *ou size_t i; time_t reference = (time_t)now; struct tm current; - if ((int64_t)reference != now) + if ((int64_t)reference != now) { return TRAINLOG_STATUS_DATABASE_ERROR; - if (localtime_r(&reference, ¤t) == NULL) + } + if (localtime_r(&reference, ¤t) == NULL) { return TRAINLOG_STATUS_DATABASE_ERROR; + } out->activity_count = TRAINLOG_WEB_ACTIVITY_DAYS; for (i = 0U; i < TRAINLOG_WEB_ACTIVITY_DAYS; ++i) { struct tm day = current; @@ -94,32 +102,38 @@ load_activity(TrainlogDatabase *d, int64_t now, TrainlogWebDashboardSnapshot *ou day.tm_mday -= (int)(TRAINLOG_WEB_ACTIVITY_DAYS - 1U - i); day.tm_isdst = -1; normalized = mktime(&day); - if (normalized == (time_t)-1 || !format_local_date(normalized, out->activity[i].date)) + if (normalized == (time_t)-1 || !format_local_date(normalized, out->activity[i].date)) { return TRAINLOG_STATUS_DATABASE_ERROR; + } } if (!prepare(d, SQL, &s) || sqlite3_bind_int64(s, 1, now) != SQLITE_OK || - sqlite3_bind_text(s, 2, out->activity[0].date, -1, SQLITE_TRANSIENT) != SQLITE_OK) + sqlite3_bind_text(s, 2, out->activity[0].date, -1, SQLITE_TRANSIENT) != SQLITE_OK) { goto fail; + } while ((step = sqlite3_step(s)) == SQLITE_ROW) { char date[11]; size_t sessions, sets; if (!copy_column(s, 0, date, sizeof(date)) || !read_size(s, 1, &sessions) || - !read_size(s, 2, &sets)) + !read_size(s, 2, &sets)) { goto fail; - for (i = 0U; i < out->activity_count; ++i) + } + for (i = 0U; i < out->activity_count; ++i) { if (strcmp(date, out->activity[i].date) == 0) { out->activity[i].active = true; out->activity[i].session_count = sessions; out->activity[i].set_count = sets; break; } + } } - if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) + if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) { return TRAINLOG_STATUS_DATABASE_ERROR; + } return TRAINLOG_STATUS_OK; fail: - if (s != NULL) + if (s != NULL) { (void)sqlite3_finalize(s); + } return TRAINLOG_STATUS_DATABASE_ERROR; } @@ -146,8 +160,9 @@ static TrainlogStatus load_last(TrainlogDatabase *d, int64_t now, TrainlogWebLas sqlite3_stmt *s = NULL; int step; TrainlogTimestampKey start, end; - if (!prepare(d, SESSION_SQL, &s) || sqlite3_bind_int64(s, 1, now) != SQLITE_OK) + if (!prepare(d, SESSION_SQL, &s) || sqlite3_bind_int64(s, 1, now) != SQLITE_OK) { goto fail; + } step = sqlite3_step(s); if (step == SQLITE_DONE) { (void)sqlite3_finalize(s); @@ -157,8 +172,9 @@ static TrainlogStatus load_last(TrainlogDatabase *d, int64_t now, TrainlogWebLas !copy_column(s, 1, out->started_at, sizeof(out->started_at)) || !copy_column(s, 2, out->ended_at, sizeof(out->ended_at)) || !read_size(s, 3, &out->exercise_count) || !read_size(s, 4, &out->set_count) || - !read_size(s, 5, &out->continuous_count) || !read_size(s, 6, &out->max_count)) + !read_size(s, 5, &out->continuous_count) || !read_size(s, 6, &out->max_count)) { goto fail; + } out->available = true; out->has_ended_at = out->ended_at[0] != '\0'; if (!trainlog_timestamp_parse(out->started_at, strlen(out->started_at), &start)) { @@ -167,17 +183,20 @@ static TrainlogStatus load_last(TrainlogDatabase *d, int64_t now, TrainlogWebLas } if (out->has_ended_at) { if (!trainlog_timestamp_parse(out->ended_at, strlen(out->ended_at), &end) || - end.utc_second < start.utc_second) + end.utc_second < start.utc_second) { goto invalid; + } out->has_duration = true; out->duration_seconds = (uint64_t)(end.utc_second - start.utc_second); } - if (sqlite3_step(s) != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) + if (sqlite3_step(s) != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) { return TRAINLOG_STATUS_DATABASE_ERROR; + } s = NULL; if (!prepare(d, ZONE_SQL, &s) || - sqlite3_bind_text(s, 1, out->session_id, -1, SQLITE_TRANSIENT) != SQLITE_OK) + sqlite3_bind_text(s, 1, out->session_id, -1, SQLITE_TRANSIENT) != SQLITE_OK) { goto fail; + } while ((step = sqlite3_step(s)) == SQLITE_ROW) { TrainlogWebWorkedZone *z; const TrainlogBodyZone *catalog; @@ -186,25 +205,30 @@ static TrainlogStatus load_last(TrainlogDatabase *d, int64_t now, TrainlogWebLas } z = &out->zones[out->zone_count]; if (!copy_column(s, 0, z->zone_id, sizeof(z->zone_id)) || - !read_size(s, 1, &z->occurrence_count) || !read_size(s, 2, &z->set_count)) + !read_size(s, 1, &z->occurrence_count) || !read_size(s, 2, &z->set_count)) { goto fail; + } z->session_count = 1U; catalog = trainlog_body_zone_catalog_lookup(z->zone_id); - if (catalog == NULL || strlen(catalog->display_name) > TRAINLOG_NAME_MAX) + if (catalog == NULL || strlen(catalog->display_name) > TRAINLOG_NAME_MAX) { goto invalid; + } (void)snprintf(z->label, sizeof(z->label), "%s", catalog->display_name); ++out->zone_count; } - if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) + if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) { return TRAINLOG_STATUS_DATABASE_ERROR; + } return TRAINLOG_STATUS_OK; invalid: - if (s != NULL) + if (s != NULL) { (void)sqlite3_finalize(s); + } return TRAINLOG_STATUS_INVALID_ARGUMENT; fail: - if (s != NULL) + if (s != NULL) { (void)sqlite3_finalize(s); + } return TRAINLOG_STATUS_DATABASE_ERROR; } @@ -220,8 +244,9 @@ load_maxima(TrainlogDatabase *d, int64_t now, TrainlogWebDashboardSnapshot *out) sqlite3_stmt *s = NULL; int step; if (!prepare(d, SQL, &s) || sqlite3_bind_int64(s, 1, now) != SQLITE_OK || - sqlite3_bind_int64(s, 2, (sqlite3_int64)(TRAINLOG_WEB_MAX_RECORDS + 1U)) != SQLITE_OK) + sqlite3_bind_int64(s, 2, (sqlite3_int64)(TRAINLOG_WEB_MAX_RECORDS + 1U)) != SQLITE_OK) { goto fail; + } while ((step = sqlite3_step(s)) == SQLITE_ROW) { TrainlogWebMaxRecord *r; if (out->max_record_count == TRAINLOG_WEB_MAX_RECORDS) { @@ -244,12 +269,14 @@ load_maxima(TrainlogDatabase *d, int64_t now, TrainlogWebDashboardSnapshot *out) r->weight_kg = sqlite3_column_double(s, 5); ++out->max_record_count; } - if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) + if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) { return TRAINLOG_STATUS_DATABASE_ERROR; + } return TRAINLOG_STATUS_OK; fail: - if (s != NULL) + if (s != NULL) { (void)sqlite3_finalize(s); + } return TRAINLOG_STATUS_DATABASE_ERROR; } @@ -271,8 +298,9 @@ load_zones(TrainlogDatabase *d, int64_t now, TrainlogWebDashboardSnapshot *out) sqlite3_bind_text( s, 1, out->activity[TRAINLOG_WEB_ACTIVITY_DAYS - 30U].date, -1, SQLITE_TRANSIENT) != SQLITE_OK || - sqlite3_bind_int64(s, 2, now) != SQLITE_OK) + sqlite3_bind_int64(s, 2, now) != SQLITE_OK) { goto fail; + } while ((step = sqlite3_step(s)) == SQLITE_ROW) { TrainlogWebWorkedZone *z; const TrainlogBodyZone *catalog; @@ -283,8 +311,9 @@ load_zones(TrainlogDatabase *d, int64_t now, TrainlogWebDashboardSnapshot *out) z = &out->muscle_zones[out->muscle_zone_count]; if (!copy_column(s, 0, z->zone_id, sizeof(z->zone_id)) || !read_size(s, 1, &z->session_count) || !read_size(s, 2, &z->occurrence_count) || - !read_size(s, 3, &z->set_count)) + !read_size(s, 3, &z->set_count)) { goto fail; + } catalog = trainlog_body_zone_catalog_lookup(z->zone_id); if (catalog == NULL || strlen(catalog->display_name) > TRAINLOG_NAME_MAX) { out->invalid_data = true; @@ -293,12 +322,14 @@ load_zones(TrainlogDatabase *d, int64_t now, TrainlogWebDashboardSnapshot *out) (void)snprintf(z->label, sizeof(z->label), "%s", catalog->display_name); ++out->muscle_zone_count; } - if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) + if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) { return TRAINLOG_STATUS_DATABASE_ERROR; + } return TRAINLOG_STATUS_OK; fail: - if (s != NULL) + if (s != NULL) { (void)sqlite3_finalize(s); + } return TRAINLOG_STATUS_DATABASE_ERROR; } @@ -313,8 +344,9 @@ static TrainlogStatus scan_quality(TrainlogDatabase *d, TrainlogWebDashboardSnap sqlite3_stmt *s = NULL; int step; size_t count = 0U; - if (!prepare(d, SQL, &s)) + if (!prepare(d, SQL, &s)) { goto fail; + } while ((step = sqlite3_step(s)) == SQLITE_ROW) { char started[TRAINLOG_TIMESTAMP_MAX + 1U], ended[TRAINLOG_TIMESTAMP_MAX + 1U]; TrainlogTimestampKey start_key, end_key; @@ -327,15 +359,18 @@ static TrainlogStatus scan_quality(TrainlogDatabase *d, TrainlogWebDashboardSnap !copy_column(s, 1, ended, sizeof(ended)) || !trainlog_timestamp_parse(started, strlen(started), &start_key) || (ended[0] != '\0' && (!trainlog_timestamp_parse(ended, strlen(ended), &end_key) || - trainlog_timestamp_compare(&end_key, &start_key) < 0))) + trainlog_timestamp_compare(&end_key, &start_key) < 0))) { out->invalid_data = true; + } } - if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) + if (step != SQLITE_DONE || sqlite3_finalize(s) != SQLITE_OK) { return TRAINLOG_STATUS_DATABASE_ERROR; + } return TRAINLOG_STATUS_OK; fail: - if (s != NULL) + if (s != NULL) { (void)sqlite3_finalize(s); + } return TRAINLOG_STATUS_DATABASE_ERROR; } @@ -344,20 +379,24 @@ TrainlogStatus trainlog_web_dashboard_load(TrainlogDatabase *d, TrainlogWebDashboardSnapshot *out) { TrainlogStatus status, end_status; TrainlogDashboardQuery progression_query; - if (d == NULL || q == NULL || out == NULL) + if (d == NULL || q == NULL || out == NULL) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } (void)memset(out, 0, sizeof(*out)); out->next_session_reason = "no_persisted_executable_plan"; out->cardio_reason = "no_cardio_data_source"; if (!format_generated(q->reference_unix_second, out->generated_at) || - !load_user(out->user_display_name)) + !load_user(out->user_display_name)) { return TRAINLOG_STATUS_DATABASE_ERROR; + } status = trainlog_database_read_snapshot_begin(d); - if (status != TRAINLOG_STATUS_OK) + if (status != TRAINLOG_STATUS_OK) { return status; + } status = load_activity(d, q->reference_unix_second, out); - if (status == TRAINLOG_STATUS_OK) + if (status == TRAINLOG_STATUS_OK) { status = scan_quality(d, out); + } if (status == TRAINLOG_STATUS_OK) { progression_query.period = TRAINLOG_DASHBOARD_90_DAYS; progression_query.reference_unix_second = q->reference_unix_second; @@ -372,12 +411,15 @@ TrainlogStatus trainlog_web_dashboard_load(TrainlogDatabase *d, status = TRAINLOG_STATUS_OK; } } - if (status == TRAINLOG_STATUS_OK) + if (status == TRAINLOG_STATUS_OK) { status = load_maxima(d, q->reference_unix_second, out); - if (status == TRAINLOG_STATUS_OK) + } + if (status == TRAINLOG_STATUS_OK) { status = load_zones(d, q->reference_unix_second, out); + } end_status = trainlog_database_read_snapshot_end(d, status == TRAINLOG_STATUS_OK); - if (end_status != TRAINLOG_STATUS_OK) + if (end_status != TRAINLOG_STATUS_OK) { status = end_status; + } return status; } diff --git a/tui/src/web_dashboard_json.c b/tui/src/web_dashboard_json.c index c571f18..2b77909 100644 --- a/tui/src/web_dashboard_json.c +++ b/tui/src/web_dashboard_json.c @@ -23,25 +23,31 @@ static const char *tracking_name(TrainlogTrackingMode value) { return value == TRAINLOG_TRACKING_DURATION ? "duration" : "reps"; } static const char *load_name(TrainlogLoadMode value) { - if (value == TRAINLOG_LOAD_EXTERNAL) + if (value == TRAINLOG_LOAD_EXTERNAL) { return "external"; - if (value == TRAINLOG_LOAD_ASSISTANCE) + } + if (value == TRAINLOG_LOAD_ASSISTANCE) { return "assistance"; + } return "none"; } static bool point_improved(const TrainlogDashboardSnapshot *p, size_t i) { const TrainlogExercisePerformancePoint *a, *b; - if (i == 0U) + if (i == 0U) { return false; + } a = &p->performance[i - 1U]; b = &p->performance[i]; - if (!a->has_weight && !b->has_weight) + if (!a->has_weight && !b->has_weight) { return b->metric_value > a->metric_value; - if (a->has_weight != b->has_weight) + } + if (a->has_weight != b->has_weight) { return false; - if (p->performance_load_mode == TRAINLOG_LOAD_ASSISTANCE) + } + if (p->performance_load_mode == TRAINLOG_LOAD_ASSISTANCE) { return b->weight_kg < a->weight_kg || (b->weight_kg == a->weight_kg && b->metric_value > a->metric_value); + } return b->weight_kg > a->weight_kg || (b->weight_kg == a->weight_kg && b->metric_value > a->metric_value); } @@ -72,8 +78,9 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh size_t *out_size) { TrainlogJsonWriter w; size_t i; - if (s == NULL || out == NULL || out_size == NULL) + if (s == NULL || out == NULL || out_size == NULL) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } *out_size = 0U; trainlog_json_init(&w, out, cap); RAW("{\"api_version\":1,\"data\":{\"footer\":{\"user\":"); @@ -84,12 +91,14 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh (void)memcpy(date, s->last_session.started_at, 10U); date[10] = '\0'; STR(date); - } else + } else { RAW("null"); + } RAW(",\"last_zones\":["); for (i = 0U; i < s->last_session.zone_count; ++i) { - if (i > 0U) + if (i > 0U) { RAW(","); + } STR(s->last_session.zones[i].label); } RAW("]},"); @@ -99,8 +108,9 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh RAW("\"activity\":{\"available\":true,\"window_days\":90,\"days\":["); for (i = 0U; i < s->activity_count; ++i) { const TrainlogWebActivityDay *d = &s->activity[i]; - if (i > 0U) + if (i > 0U) { RAW(","); + } RAW("{\"date\":"); STR(d->date); RAW(",\"active\":"); @@ -129,26 +139,31 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh RAW(",\"load_mode\":"); STR(load_name(s->progression.performance_load_mode)); RAW(",\"dose\":"); - if (!trainlog_json_i64(&w, (long long)s->progression.performance_dose)) + if (!trainlog_json_i64(&w, (long long)s->progression.performance_dose)) { goto overflow; + } RAW("},\"points\":["); for (i = 0U; i < s->progression.performance_count; ++i) { const TrainlogExercisePerformancePoint *p = &s->progression.performance[i]; - if (i > 0U) + if (i > 0U) { RAW(","); + } RAW("{\"session_id\":"); STR(p->session_id); RAW(",\"timestamp\":"); STR(p->started_at); RAW(",\"metric_value\":"); - if (!trainlog_json_i64(&w, (long long)p->metric_value)) + if (!trainlog_json_i64(&w, (long long)p->metric_value)) { goto overflow; + } RAW(",\"weight_kg\":"); if (p->has_weight) { - if (!trainlog_json_double(&w, p->weight_kg)) + if (!trainlog_json_double(&w, p->weight_kg)) { goto overflow; - } else + } + } else { RAW("null"); + } RAW(",\"improved\":"); RAW(point_improved(&s->progression, i) ? "true" : "false"); RAW("}"); @@ -166,16 +181,19 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh RAW(",\"started_at\":"); STR(l->started_at); RAW(",\"ended_at\":"); - if (l->has_ended_at) + if (l->has_ended_at) { STR(l->ended_at); - else + } else { RAW("null"); + } RAW(",\"duration_seconds\":"); if (l->has_duration) { - if (!trainlog_json_i64(&w, (long long)l->duration_seconds)) + if (!trainlog_json_i64(&w, (long long)l->duration_seconds)) { goto overflow; - } else + } + } else { RAW("null"); + } RAW(",\"exercise_count\":"); NUM(l->exercise_count); RAW(",\"set_count\":"); @@ -186,23 +204,27 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh NUM(l->max_count); RAW(",\"primary_zones\":["); for (i = 0U; i < l->zone_count; ++i) { - if (i > 0U) + if (i > 0U) { RAW(","); - if (!write_zone(&w, &l->zones[i])) + } + if (!write_zone(&w, &l->zones[i])) { goto overflow; + } } RAW("]"); } RAW("},"); RAW("\"max_records\":{\"available\":"); RAW(s->max_record_count > 0U ? "true" : "false"); - if (s->max_record_count == 0U) + if (s->max_record_count == 0U) { RAW(",\"reason\":\"no_explicit_max_results\""); + } RAW(",\"records\":["); for (i = 0U; i < s->max_record_count; ++i) { const TrainlogWebMaxRecord *r = &s->max_records[i]; - if (i > 0U) + if (i > 0U) { RAW(","); + } RAW("{\"session_id\":"); STR(r->session_id); RAW(",\"entry_id\":"); @@ -214,8 +236,9 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh RAW(",\"equipment_id\":"); STR(r->equipment_id); RAW(",\"weight_kg\":"); - if (!trainlog_json_double(&w, r->weight_kg)) + if (!trainlog_json_double(&w, r->weight_kg)) { goto overflow; + } RAW(",\"timestamp\":"); STR(r->timestamp); RAW("}"); @@ -223,14 +246,17 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh RAW("]},"); RAW("\"muscle_distribution\":{\"available\":"); RAW(s->muscle_zone_count > 0U ? "true" : "false"); - if (s->muscle_zone_count == 0U) + if (s->muscle_zone_count == 0U) { RAW(",\"reason\":\"no_worked_primary_zones\""); + } RAW(",\"window_days\":30,\"primary_zones\":["); for (i = 0U; i < s->muscle_zone_count; ++i) { - if (i > 0U) + if (i > 0U) { RAW(","); - if (!write_zone(&w, &s->muscle_zones[i])) + } + if (!write_zone(&w, &s->muscle_zones[i])) { goto overflow; + } } RAW("]},"); RAW("\"cardio\":{\"available\":false,\"reason\":"); @@ -242,12 +268,14 @@ TrainlogStatus trainlog_web_dashboard_serialize(const TrainlogWebDashboardSnapsh RAW(",\"generated_at\":"); STR(s->generated_at); RAW("}}\n"); - if (w.failed) + if (w.failed) { goto overflow; + } *out_size = w.size; return TRAINLOG_STATUS_OK; overflow: - if (cap > 0U) + if (cap > 0U) { out[0] = '\0'; + } return TRAINLOG_STATUS_SYSTEM_ERROR; } diff --git a/tui/tests/generation_mtp_adapter_double.c b/tui/tests/generation_mtp_adapter_double.c index f6ea3b8..41e8d57 100644 --- a/tui/tests/generation_mtp_adapter_double.c +++ b/tui/tests/generation_mtp_adapter_double.c @@ -30,12 +30,13 @@ static uint32_t scan(const char *path, uint32_t parent) { const char *slash = strrchr(path, '/'); snprintf(n->name, sizeof(n->name), "%s", slash ? slash + 1 : path); if (n->folder && (d = opendir(path)) != NULL) { - while ((e = readdir(d))) + while ((e = readdir(d))) { if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { char child[1024]; snprintf(child, sizeof(child), "%s/%s", path, e->d_name); scan(child, self); } + } closedir(d); } return self; @@ -46,14 +47,17 @@ static void rebuild(void) { } static Node *node(uint32_t id) { size_t i; - for (i = 0; i < node_count; i++) - if (nodes[i].id == id) + for (i = 0; i < node_count; i++) { + if (nodes[i].id == id) { return &nodes[i]; + } + } return NULL; } static TrainlogStatus devices(TrainlogUsbDevice *o, size_t c, size_t *n) { - if (c < 1U) + if (c < 1U) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } memset(o, 0, sizeof(*o)); o->bus_number = 1; o->device_number = 1; @@ -64,8 +68,9 @@ static TrainlogStatus storages(unsigned int b, unsigned int d, TrainlogMtpStorage *o, size_t c, size_t *n) { (void)b; (void)d; - if (c < 1U) + if (c < 1U) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } memset(o, 0, sizeof(*o)); o->storage_id = 1; *n = 1; @@ -83,12 +88,14 @@ static TrainlogStatus children(unsigned int b, (void)d; (void)s; rebuild(); - if (p == UINT32_MAX) + if (p == UINT32_MAX) { p = nodes[0].id; - for (i = 0; i < node_count; i++) + } + for (i = 0; i < node_count; i++) { if (nodes[i].parent == p) { - if (k >= c) + if (k >= c) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } memset(&o[k], 0, sizeof(o[k])); o[k].item_id = nodes[i].id; o[k].parent_id = p; @@ -98,6 +105,7 @@ static TrainlogStatus children(unsigned int b, snprintf(o[k].name, sizeof(o[k].name), "%s", nodes[i].name); k++; } + } *n = k; return TRAINLOG_STATUS_OK; } @@ -115,33 +123,39 @@ static TrainlogStatus ensure(unsigned int b, (void)s; rebuild(); parent = node(p); - if (!parent) + if (!parent) { return TRAINLOG_STATUS_NOT_FOUND; + } snprintf(path, sizeof(path), "%s/%s", parent->path, name); - if (mkdir(path, 0700) == 0) + if (mkdir(path, 0700) == 0) { *created = true; - else if (access(path, F_OK) == 0) + } else if (access(path, F_OK) == 0) { *created = false; - else + } else { return TRAINLOG_STATUS_SYSTEM_ERROR; + } rebuild(); size_t i; - for (i = 0; i < node_count; i++) + for (i = 0; i < node_count; i++) { if (strcmp(nodes[i].path, path) == 0) { *id = nodes[i].id; return TRAINLOG_STATUS_OK; } + } return TRAINLOG_STATUS_SYSTEM_ERROR; } static int copy(const char *a, const char *b) { FILE *in = fopen(a, "rb"), *out = fopen(b, "wb"); char buf[8192]; size_t n; - if (!in || !out) + if (!in || !out) { return -1; - while ((n = fread(buf, 1, sizeof(buf), in)) > 0) - if (fwrite(buf, 1, n, out) != n) + } + while ((n = fread(buf, 1, sizeof(buf), in)) > 0) { + if (fwrite(buf, 1, n, out) != n) { return -1; + } + } return fclose(in) | fclose(out); } static TrainlogStatus receive(unsigned int b, unsigned int d, uint32_t id, const char *path) { @@ -166,18 +180,21 @@ static TrainlogStatus send_file(unsigned int b, (void)s; rebuild(); parent = node(p); - if (!parent) + if (!parent) { return TRAINLOG_STATUS_NOT_FOUND; + } snprintf(path, sizeof(path), "%s/%s", parent->path, name); - if (copy(local, path) != 0) + if (copy(local, path) != 0) { return TRAINLOG_STATUS_SYSTEM_ERROR; + } rebuild(); size_t i; - for (i = 0; i < node_count; i++) + for (i = 0; i < node_count; i++) { if (strcmp(nodes[i].path, path) == 0) { *id = nodes[i].id; return TRAINLOG_STATUS_OK; } + } return TRAINLOG_STATUS_SYSTEM_ERROR; } static TrainlogStatus remove_object(unsigned int b, unsigned int d, uint32_t id) { @@ -195,29 +212,41 @@ static TrainlogStatus rename_object(unsigned int b, unsigned int d, uint32_t id, (void)d; rebuild(); n = node(id); - if (!n) + if (!n) { return TRAINLOG_STATUS_NOT_FOUND; + } snprintf(path, sizeof(path), "%s", n->path); slash = strrchr(path, '/'); - if (!slash) + if (!slash) { return TRAINLOG_STATUS_SYSTEM_ERROR; + } snprintf(slash + 1, (size_t)(path + sizeof(path) - (slash + 1)), "%s", name); return rename(n->path, path) == 0 ? TRAINLOG_STATUS_OK : TRAINLOG_STATUS_SYSTEM_ERROR; } static const TrainlogGenerationMtpIo io = { - devices, storages, children, ensure, receive, send_file, remove_object, rename_object}; + .devices = devices, + .storages = storages, + .children = children, + .ensure_folder = ensure, + .receive = receive, + .send = send_file, + .remove = remove_object, + .rename = rename_object, +}; int main(int argc, char **argv) { char diag[1024] = {0}; TrainlogStatus status; remote = getenv("TRAINLOG_MTP_DOUBLE_ROOT"); - if (argc != 4 || !remote) + if (argc != 4 || !remote) { return 64; - if (strcmp(argv[1], "pull") == 0) + } + if (strcmp(argv[1], "pull") == 0) { status = trainlog_generation_mtp_pull(&io, argv[2], argv[3], diag, sizeof(diag)); - else if (strcmp(argv[1], "push") == 0) + } else if (strcmp(argv[1], "push") == 0) { status = trainlog_generation_mtp_push(&io, argv[2], argv[3], diag, sizeof(diag)); - else + } else { return 64; + } if (status != TRAINLOG_STATUS_OK) { fprintf(stderr, "double failed %d %s\n", status, diag); return 2; diff --git a/tui/tests/test_generation_mtp.c b/tui/tests/test_generation_mtp.c index e58eb31..d19f0d4 100644 --- a/tui/tests/test_generation_mtp.c +++ b/tui/tests/test_generation_mtp.c @@ -50,8 +50,9 @@ static void reset(void) { } static TrainlogStatus devices(TrainlogUsbDevice *out, size_t cap, size_t *count) { size_t i; - if (cap < device_count) + if (cap < device_count) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } *count = device_count; for (i = 0; i < device_count; i++) { memset(&out[i], 0, sizeof(out[i])); @@ -63,8 +64,9 @@ static TrainlogStatus devices(TrainlogUsbDevice *out, size_t cap, size_t *count) static TrainlogStatus storages(unsigned int bus, unsigned int dev, TrainlogMtpStorage *out, size_t cap, size_t *count) { (void)bus; - if (cap < 1U) + if (cap < 1U) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } memset(out, 0, sizeof(*out)); out->storage_id = dev; *count = 1U; @@ -80,10 +82,11 @@ static TrainlogStatus children(unsigned int bus, size_t i, n = 0; (void)bus; (void)storage; - for (i = 0; i < object_count; i++) + for (i = 0; i < object_count; i++) { if (objects[i].parent == parent && (dev == 1U || objects[i].id <= 3U)) { - if (n >= cap) + if (n >= cap) { return TRAINLOG_STATUS_INVALID_ARGUMENT; + } memset(&out[n], 0, sizeof(out[n])); out[n].item_id = objects[i].id; out[n].parent_id = parent; @@ -93,6 +96,7 @@ static TrainlogStatus children(unsigned int bus, snprintf(out[n].name, sizeof(out[n].name), "%s", objects[i].name); n++; } + } *count = n; return TRAINLOG_STATUS_OK; } @@ -107,12 +111,13 @@ static TrainlogStatus ensure_folder(unsigned int b, (void)b; (void)d; (void)s; - for (i = 0; i < object_count; i++) + for (i = 0; i < object_count; i++) { if (objects[i].parent == p && objects[i].folder && strcmp(objects[i].name, name) == 0) { *id = objects[i].id; *created = false; return TRAINLOG_STATUS_OK; } + } *id = (uint32_t)(100U + object_count); *created = true; add(*id, p, true, name, NULL); @@ -120,9 +125,11 @@ static TrainlogStatus ensure_folder(unsigned int b, } static Object *find(uint32_t id) { size_t i; - for (i = 0; i < object_count; i++) - if (objects[i].id == id) + for (i = 0; i < object_count; i++) { + if (objects[i].id == id) { return &objects[i]; + } + } return NULL; } static TrainlogStatus receive(unsigned int b, unsigned int d, uint32_t id, const char *path) { @@ -131,11 +138,13 @@ static TrainlogStatus receive(unsigned int b, unsigned int d, uint32_t id, const size_t bytes; (void)b; (void)d; - if (!o) + if (!o) { return TRAINLOG_STATUS_NOT_FOUND; + } f = fopen(path, "wb"); - if (!f) + if (!f) { return TRAINLOG_STATUS_SYSTEM_ERROR; + } bytes = id == 9U ? 3U : o->size; if (fwrite(o->data, 1, bytes, f) != bytes) { fclose(f); @@ -157,8 +166,9 @@ static TrainlogStatus send_file(unsigned int b, (void)d; (void)s; f = fopen(path, "rb"); - if (!f) + if (!f) { return TRAINLOG_STATUS_SYSTEM_ERROR; + } fseek(f, 0, SEEK_END); size = ftell(f); rewind(f); @@ -183,8 +193,9 @@ static TrainlogStatus remove_object(unsigned int b, unsigned int d, uint32_t id) Object *o = find(id); (void)b; (void)d; - if (!o) + if (!o) { return TRAINLOG_STATUS_NOT_FOUND; + } o->name[0] = '\0'; return TRAINLOG_STATUS_OK; } @@ -192,13 +203,22 @@ static TrainlogStatus rename_object(unsigned int b, unsigned int d, uint32_t id, Object *o = find(id); (void)b; (void)d; - if (!o) + if (!o) { return TRAINLOG_STATUS_NOT_FOUND; + } snprintf(o->name, sizeof(o->name), "%s", name); return TRAINLOG_STATUS_OK; } static const TrainlogGenerationMtpIo io = { - devices, storages, children, ensure_folder, receive, send_file, remove_object, rename_object}; + .devices = devices, + .storages = storages, + .children = children, + .ensure_folder = ensure_folder, + .receive = receive, + .send = send_file, + .remove = remove_object, + .rename = rename_object, +}; static int write_file(const char *path, const char *value) { FILE *f = fopen(path, "wb"); CHECK(f != NULL); diff --git a/tui/tests/test_web_server.c b/tui/tests/test_web_server.c index a970ca1..e198cfa 100644 --- a/tui/tests/test_web_server.c +++ b/tui/tests/test_web_server.c @@ -39,8 +39,9 @@ static int reserve_port(uint16_t *port, int keep_open) { struct sockaddr_in address; socklen_t length = (socklen_t)sizeof(address); int socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd < 0) + if (socket_fd < 0) { return -1; + } (void)memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); @@ -70,10 +71,12 @@ static int connect_with_retry(uint16_t port) { for (attempt = 0U; attempt < 200U; ++attempt) { int socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd >= 0 && - connect(socket_fd, (const struct sockaddr *)&address, sizeof(address)) == 0) + connect(socket_fd, (const struct sockaddr *)&address, sizeof(address)) == 0) { return socket_fd; - if (socket_fd >= 0) + } + if (socket_fd >= 0) { (void)close(socket_fd); + } (void)nanosleep(&delay, NULL); } return -1; @@ -93,8 +96,9 @@ static bool exchange(uint16_t port, const char *request, char *response, size_t (void)shutdown(socket_fd, SHUT_WR); while (used + 1U < capacity) { ssize_t count = recv(socket_fd, response + used, capacity - used - 1U, 0); - if (count == 0) + if (count == 0) { break; + } CHECK(count > 0); used += (size_t)count; } @@ -109,8 +113,9 @@ static bool asset_path(const char *html, const char *suffix, char *output, size_ while ((start = strstr(start, "/assets/")) != NULL) { const char *end = start; size_t length; - while (*end != '\0' && *end != '"' && *end != '\'' && *end != '<' && *end != '>') + while (*end != '\0' && *end != '"' && *end != '\'' && *end != '<' && *end != '>') { ++end; + } length = (size_t)(end - start); if (length >= suffix_length && memcmp(end - suffix_length, suffix, suffix_length) == 0 && length < capacity) { @@ -127,15 +132,18 @@ static bool response_header(const char *response, const char *name, char *output const char *start = strstr(response, name); const char *end; size_t length; - if (start == NULL) + if (start == NULL) { return false; + } start += strlen(name); end = strstr(start, "\r\n"); - if (end == NULL) + if (end == NULL) { return false; + } length = (size_t)(end - start); - if (length >= capacity) + if (length >= capacity) { return false; + } (void)memcpy(output, start, length); output[length] = '\0'; return true; @@ -451,10 +459,12 @@ int main(void) { char config_root[] = "/tmp/trainlog-web-config-XXXXXX"; TrainlogDatabase *database = NULL; bool passed; - if (mkdtemp(config_root) == NULL || setenv("XDG_CONFIG_HOME", config_root, 1) != 0) + if (mkdtemp(config_root) == NULL || setenv("XDG_CONFIG_HOME", config_root, 1) != 0) { return 1; - if (trainlog_database_open(":memory:", &database) != TRAINLOG_STATUS_OK) + } + if (trainlog_database_open(":memory:", &database) != TRAINLOG_STATUS_OK) { return 1; + } if (!trainlog_web_assets_available()) { volatile sig_atomic_t stop = 0; char diagnostic[256]; diff --git a/tui/tools/generation_mtp_adapter.c b/tui/tools/generation_mtp_adapter.c index 12774e2..8ffa73d 100644 --- a/tui/tools/generation_mtp_adapter.c +++ b/tui/tools/generation_mtp_adapter.c @@ -9,22 +9,24 @@ int main(int argc, char **argv) { (void)puts("usage: trainlog-generation-mtp-adapter pull|push EXPECTED_PEER LOCAL_ROOT"); return 0; } - if (argc != 4) + if (argc != 4) { return 64; - if (strcmp(argv[1], "pull") == 0) + } + if (strcmp(argv[1], "pull") == 0) { status = trainlog_generation_mtp_pull(trainlog_generation_mtp_production_io(), argv[2], argv[3], diagnostic, sizeof(diagnostic)); - else if (strcmp(argv[1], "push") == 0) + } else if (strcmp(argv[1], "push") == 0) { status = trainlog_generation_mtp_push(trainlog_generation_mtp_production_io(), argv[2], argv[3], diagnostic, sizeof(diagnostic)); - else + } else { return 64; + } if (status != TRAINLOG_STATUS_OK) { (void)fprintf( stderr, "MTP adapter failed status=%d diagnostic=%s\n", (int)status, diagnostic);