You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
6.1 KiB
229 lines
6.1 KiB
6 years ago
|
/*
|
||
|
* gfsec - Secret sharing tools
|
||
|
* Copyright (C) 2016 Damien Goutte-Gattat
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include <config.h>
|
||
|
#endif
|
||
|
|
||
|
#include "mtp-support.h"
|
||
|
|
||
|
#ifndef HAVE_LIBMTP
|
||
|
|
||
|
#include <errno.h>
|
||
|
|
||
|
unsigned char *
|
||
|
gfsec_get_file_from_mtp(const char *authority,
|
||
|
const char *path,
|
||
|
size_t *len)
|
||
|
{
|
||
|
(void) authority;
|
||
|
(void) path;
|
||
|
(void) len;
|
||
|
|
||
|
errno = ENOSYS;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <splitstr.h>
|
||
|
|
||
|
#define MTP_ROOT_FOLDER_ID 0xFFFFFFFF
|
||
|
|
||
|
/**
|
||
|
* Finds a connected MTP device with the specified serial number.
|
||
|
*
|
||
|
* @param[in] wanted_serial The serial number of the device to find.
|
||
|
*
|
||
|
* @return An object representing the found device (to be freed with
|
||
|
* LIBMTP_Release_Device), or NULL if no device was found.
|
||
|
*/
|
||
|
static LIBMTP_mtpdevice_t *
|
||
|
find_mtp_device(const char *wanted_serial)
|
||
|
{
|
||
|
LIBMTP_raw_device_t *raw_devices;
|
||
|
LIBMTP_mtpdevice_t *device;
|
||
|
int i, n;
|
||
|
|
||
|
if ( LIBMTP_Detect_Raw_Devices(&raw_devices, &n) != 0 )
|
||
|
return NULL;
|
||
|
|
||
|
for ( i = 0, device = NULL; i < n && device == NULL; i++ ) {
|
||
|
char *serial;
|
||
|
|
||
|
device = LIBMTP_Open_Raw_Device_Uncached(&(raw_devices[i]));
|
||
|
if ( (serial = LIBMTP_Get_Serialnumber(device)) == NULL ||
|
||
|
strcmp(serial, wanted_serial) != 0 ) {
|
||
|
LIBMTP_Release_Device(device);
|
||
|
device = NULL;
|
||
|
if ( serial )
|
||
|
free(serial);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
free(raw_devices);
|
||
|
|
||
|
return device;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Finds a file on a given MTP device.
|
||
|
*
|
||
|
* @param[in] device The MTP device.
|
||
|
* @param[in] storage Storage identifier (0 to search in all storages).
|
||
|
* @param[in] path The path of the file to find.
|
||
|
* @param[out] size If not NULL and the file is found, this will be set
|
||
|
* to the size of the file.
|
||
|
*
|
||
|
* @return The MTP identifier for the file if found, or -1 if not found.
|
||
|
*/
|
||
|
static long
|
||
|
find_mtp_file(LIBMTP_mtpdevice_t *device,
|
||
|
unsigned storage,
|
||
|
const char *path,
|
||
|
size_t *size)
|
||
|
{
|
||
|
char **components;
|
||
|
size_t n;
|
||
|
unsigned i, file_id;
|
||
|
long rc = -1;
|
||
|
|
||
|
if ( ! (components = splitstr(path, '/', &n)) )
|
||
|
return -1;
|
||
|
|
||
|
for ( i = 0, file_id = MTP_ROOT_FOLDER_ID; i < n; i++ ) {
|
||
|
LIBMTP_file_t *files, *file;
|
||
|
int found = 0;
|
||
|
|
||
|
files = LIBMTP_Get_Files_And_Folders(device, storage, file_id);
|
||
|
file = files;
|
||
|
|
||
|
while ( file && ! found ) {
|
||
|
LIBMTP_file_t *tmp;
|
||
|
|
||
|
if ( strcmp(file->filename, components[i]) == 0 ) {
|
||
|
if ( file->filetype == LIBMTP_FILETYPE_FOLDER && i < n - 1 ) {
|
||
|
file_id = file->item_id;
|
||
|
found = 1;
|
||
|
}
|
||
|
else if ( file->filetype != LIBMTP_FILETYPE_FOLDER && i == n - 1 ) {
|
||
|
rc = file->item_id;
|
||
|
found = 1;
|
||
|
|
||
|
if ( size )
|
||
|
*size = file->filesize;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tmp = file;
|
||
|
file = file->next;
|
||
|
LIBMTP_destroy_file_t(tmp);
|
||
|
}
|
||
|
|
||
|
if ( ! found )
|
||
|
i = n; /* Exit loop. */
|
||
|
}
|
||
|
|
||
|
free(components);
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
struct getfile_cb_data {
|
||
|
unsigned char *buffer;
|
||
|
unsigned written;
|
||
|
size_t expected;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Callback for the LIBMTP_Get_File_To_Handler function.
|
||
|
*
|
||
|
* @param params MTP parameters (unused).
|
||
|
* @param priv Pointer to a getfile_cb_data structure.
|
||
|
* @param sendlen Number of bytes available.
|
||
|
* @param data Actual bytes available.
|
||
|
* @param[out] putlen Number of bytes used.
|
||
|
*
|
||
|
* @return LIBMTP_HANLDER_RETURN_OK if successful, or
|
||
|
* LIBMTP_HANDLER_RETURN_ERROR if we get more bytes than we expected.
|
||
|
*/
|
||
|
static unsigned short
|
||
|
getfile_cb(void *params,
|
||
|
void *priv,
|
||
|
unsigned sendlen,
|
||
|
unsigned char *data,
|
||
|
unsigned *putlen)
|
||
|
{
|
||
|
struct getfile_cb_data *cb_data = priv;
|
||
|
(void) params;
|
||
|
|
||
|
if ( cb_data->written + sendlen > cb_data->expected )
|
||
|
return LIBMTP_HANDLER_RETURN_ERROR;
|
||
|
|
||
|
memcpy(cb_data->buffer + cb_data->written, data, sendlen);
|
||
|
cb_data->written += sendlen;
|
||
|
*putlen = sendlen;
|
||
|
|
||
|
return LIBMTP_HANDLER_RETURN_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the contents of a file on a MTP device.
|
||
|
*
|
||
|
* @param[in] authority Serial number of the MTP device.
|
||
|
* @param[in] path Path to the file on the MTP device.
|
||
|
* @param[out] len Number of bytes read from the device.
|
||
|
*
|
||
|
* @return A pointer to a newly allocated buffer containing
|
||
|
* the file data, or NULL if an error occured.
|
||
|
*/
|
||
|
unsigned char *
|
||
|
gfsec_get_file_from_mtp(const char *authority,
|
||
|
const char *path,
|
||
|
size_t *len)
|
||
|
{
|
||
|
LIBMTP_mtpdevice_t *device;
|
||
|
struct getfile_cb_data cb_data;
|
||
|
unsigned char *blob = NULL;
|
||
|
|
||
|
if ( (device = find_mtp_device(authority)) ) {
|
||
|
long file_id;
|
||
|
|
||
|
if ( (file_id = find_mtp_file(device, 0, path, len)) != -1 ) {
|
||
|
if ( (blob = malloc(*len)) ) {
|
||
|
cb_data.buffer = blob;
|
||
|
cb_data.written = 0;
|
||
|
cb_data.expected = *len;
|
||
|
|
||
|
if ( LIBMTP_Get_File_To_Handler(device, file_id,
|
||
|
getfile_cb, &cb_data, NULL, NULL) != 0 ) {
|
||
|
free(blob);
|
||
|
blob = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LIBMTP_Release_Device(device);
|
||
|
}
|
||
|
|
||
|
return blob;
|
||
|
}
|
||
|
|
||
|
#endif /* HAVE_LIBMTP */
|