trainlog/tui/tools/mtp_mobile_export_probe.c

348 lines
6.4 KiB
C

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "trainlog/mtp.h"
#include "trainlog/status.h"
#include "trainlog/usb.h"
#define MAX_DEVICES 8U
#define MAX_STORAGES 8U
#define MAX_ENTRIES 512U
static TrainlogStatus find_child_folder(
const TrainlogUsbDevice *device,
uint32_t storage_id,
uint32_t parent_id,
const char *name,
uint32_t *output_id
)
{
TrainlogMtpEntry
entries[MAX_ENTRIES];
size_t count = 0U;
size_t index;
TrainlogStatus status;
if (device == NULL ||
name == NULL ||
output_id == NULL) {
return
TRAINLOG_STATUS_INVALID_ARGUMENT;
}
status =
trainlog_mtp_list_folder(
device->bus_number,
device->device_number,
storage_id,
parent_id,
entries,
MAX_ENTRIES,
&count
);
if (status != TRAINLOG_STATUS_OK) {
return status;
}
for (index = 0U;
index < count;
++index) {
if (entries[index].folder &&
strcmp(
entries[index].name,
name
) == 0) {
*output_id =
entries[index].item_id;
return
TRAINLOG_STATUS_OK;
}
}
return TRAINLOG_STATUS_NOT_FOUND;
}
static TrainlogStatus find_child_file(
const TrainlogUsbDevice *device,
uint32_t storage_id,
uint32_t parent_id,
const char *name,
uint32_t *output_id,
uint64_t *output_size
)
{
TrainlogMtpEntry
entries[MAX_ENTRIES];
size_t count = 0U;
size_t index;
TrainlogStatus status;
if (device == NULL ||
name == NULL ||
output_id == NULL ||
output_size == NULL) {
return
TRAINLOG_STATUS_INVALID_ARGUMENT;
}
status =
trainlog_mtp_list_folder(
device->bus_number,
device->device_number,
storage_id,
parent_id,
entries,
MAX_ENTRIES,
&count
);
if (status != TRAINLOG_STATUS_OK) {
return status;
}
for (index = 0U;
index < count;
++index) {
if (!entries[index].folder &&
strcmp(
entries[index].name,
name
) == 0) {
*output_id =
entries[index].item_id;
*output_size =
entries[index].size_bytes;
return
TRAINLOG_STATUS_OK;
}
}
return TRAINLOG_STATUS_NOT_FOUND;
}
static int validate_download(
const char *path
)
{
FILE *file;
char buffer[4096];
size_t used;
file =
fopen(
path,
"rb"
);
if (file == NULL) {
return 1;
}
used =
fread(
buffer,
1U,
sizeof(buffer) - 1U,
file
);
if (ferror(file) != 0) {
(void)fclose(file);
return 1;
}
buffer[used] = '\0';
if (fclose(file) != 0) {
return 1;
}
if (strstr(
buffer,
"\"format\":\"trainlog-mobile-export\""
) == NULL ||
strstr(
buffer,
"\"version\":1"
) == NULL) {
return 1;
}
return 0;
}
int main(void)
{
TrainlogUsbDevice
devices[MAX_DEVICES];
TrainlogMtpStorage
storages[MAX_STORAGES];
size_t device_count = 0U;
size_t storage_count = 0U;
uint32_t download_id = 0U;
uint32_t trainlog_id = 0U;
uint32_t export_id = 0U;
uint64_t export_size = 0U;
const char *local_path =
"/tmp/trainlog-mobile-export-v1.json";
TrainlogStatus status;
status =
trainlog_usb_list_mtp_devices(
devices,
MAX_DEVICES,
&device_count
);
if (status != TRAINLOG_STATUS_OK ||
device_count == 0U) {
(void)fprintf(
stderr,
"MTP device not found\n"
);
return 1;
}
status =
trainlog_mtp_list_storages(
devices[0].bus_number,
devices[0].device_number,
storages,
MAX_STORAGES,
&storage_count
);
if (status != TRAINLOG_STATUS_OK ||
storage_count == 0U) {
(void)fprintf(
stderr,
"MTP storage not found\n"
);
return 1;
}
status =
find_child_folder(
&devices[0],
storages[0].storage_id,
UINT32_MAX,
"Download",
&download_id
);
if (status != TRAINLOG_STATUS_OK) {
(void)fprintf(
stderr,
"Download folder not found\n"
);
return 1;
}
status =
find_child_folder(
&devices[0],
storages[0].storage_id,
download_id,
"Trainlog",
&trainlog_id
);
if (status != TRAINLOG_STATUS_OK) {
(void)fprintf(
stderr,
"Download/Trainlog not found\n"
);
return 1;
}
status =
find_child_file(
&devices[0],
storages[0].storage_id,
trainlog_id,
"trainlog-mobile-export-v1.json",
&export_id,
&export_size
);
if (status != TRAINLOG_STATUS_OK) {
(void)fprintf(
stderr,
"mobile export not found\n"
);
return 1;
}
status =
trainlog_mtp_receive_file(
devices[0].bus_number,
devices[0].device_number,
export_id,
local_path
);
if (status != TRAINLOG_STATUS_OK) {
(void)fprintf(
stderr,
"MTP receive failed\n"
);
return 1;
}
if (validate_download(
local_path
) != 0) {
(void)fprintf(
stderr,
"export validation failed\n"
);
return 1;
}
(void)printf(
"MOBILE_EXPORT_MTP=PASS\n"
);
(void)printf(
"device=%s %s\n",
devices[0].vendor,
devices[0].model
);
(void)printf(
"remote=Download/Trainlog/"
"trainlog-mobile-export-v1.json\n"
);
(void)printf(
"size=%llu\n",
(unsigned long long)
export_size
);
(void)printf(
"local=%s\n",
local_path
);
return 0;
}