Recuperare dati da motorola V3
/*
motoacc
A command-line program for accessing files on Motorola cellphones
via the USB bus. Requires the library p2kmoto by Dmitry Nezhevenko,
available on sourceforge. Compile with:
gcc -o motoacc motoacc.c -lp2kmoto -lusb
motoacc is (c) 2006 Volker Schatz (www.volkerschatz.com)
motoacc 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.
sndsys 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.
To obtain a copy of the GNU General Public License, see
http://www.gnu.org/licenses/ .
*/
/*----------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <p2kmoto.h>
/*----------------------------------------------------------------------*/
#define EXEC_PREINIT 0
#define EXEC_PREOPEN 1
#define EXEC_NORMAL 2
// #define EXEC_NEEDLIST 3
typedef struct {
const char *command, *doc;
int (*execute)(int argc, char**argv);
int argc, execwhen;
}
motoacc_cmd;
/*----------------------------------------------------------------------*/
void p2kerrmsg( const int status, const char *doingwhat );
void allocfilelist();
void addtofilelist(const p2k_fileInfo *entry);
int usagemessage( int argc, char **argv );
int listusbdev( int argc, char **argv );
int phoneinfo( int argc, char **argv );
void fl_print(p2k_fileInfo fileinfo);
int listfiles( int argc, char **argv );
int getfile( int argc, char **argv );
int putfile( int argc, char **argv );
void fl_buildlist(p2k_fileInfo fileinfo);
int backup( int argc, char **argv );
int remotechattr( int argc, char **argv );
int delfile( int argc, char **argv );
/*----------------------------------------------------------------------*/
motoacc_cmd commands[] = {
"help", "help\t\tdisplay this usage message", usagemessage, -1, EXEC_PREINIT,
"usbdev", "usbdev\t\tlist USB devices which might be cellphones",
listusbdev, 2, EXEC_PREOPEN,
"info","info\t\tprint phone type, drive name, free space and number of files",
phoneinfo, 2, EXEC_NORMAL,
"list", "list\t\tlists all files on the cellphone filesystem", listfiles, 2, EXEC_NORMAL,
"get", "get [-z <local>] <remote:size> [...]\n\t\tdownloads file from cellphone. -z gives local file name. Otherwise multiple remote files may be given. Remote file names must always be followed by a colon and their size. This should be used only for regular files, as the attributes of the remote file are deleted as a side effect. Use backup to retain attributes.", getfile, -3, EXEC_NORMAL,
"put", "put [-z <local>] <remote> [...]\n\t\tuploads file to cellphone. -z gives local file name. Otherwise multiple remote files may be given. Remote file names should include full paths; without -z the local files are expected to reside in the current directory. No remote file attributes are set. EXISTING REMOTE FILES WILL BE OVERWRITTEN!", putfile, -3, EXEC_NORMAL,
"rm", "rm <file> [...]\tremoves the remote file(s)", delfile, -3, EXEC_NORMAL,
"backup", "backup [<prefix>]\n\t\tdownloads all files starting with <prefix> to a local copy of the directory structure. Unlike `get', this keeps the remote files' attributes. The attributes are also reflected in the local file permissions: read-only -> no write permissions, hidden -> not group/world-readable, system -> executable, lock -> sticky flag", backup, -2, EXEC_NORMAL,
"chattr", "chattr <attributes> <file> [<file> ...]\n\t\tsets the attributes of remote files. Attributes are: r (read only), h (hidden), s (system), l (lock) or 0 (no attributes).", remotechattr, -4, EXEC_NORMAL,
NULL, NULL, NULL, 0, 0 };
#define FILELIST_BASESIZE 0x10
struct {
p2k_fileInfo *files;
int nalloc, n;
}
filelist = { NULL, 0, 0 };
char *filelist_path = NULL;
/*----------------------------------------------------------------------*/
int main(int argc, char ** argv)
{
motoacc_cmd *cmd;
int status;
if( argc < 2 ) {
usagemessage(argc, argv);
return -1;
}
for( cmd= commands; cmd->command; ++cmd )
if( !strcmp(cmd->command, argv[1]) )
break;
if( !cmd->command ) {
fprintf( stderr, "%s: Error: unknown command `%s'.\n", argv[0], argv[1] );
usagemessage(argc, argv);
return -1;
}
if( cmd->argc >= 0? (argc != cmd->argc) : (argc < -cmd->argc) ) {
fprintf(stderr, "%s: Error: wrong number of arguments for command `%s'.\n", argv[0], argv[1]);
usagemessage(argc, argv);
return -1;
}
if( cmd->execwhen == EXEC_PREINIT )
return cmd->execute(argc, argv);
p2k_init();
if( cmd->execwhen == EXEC_PREOPEN )
return cmd->execute(argc, argv);
status= p2k_findPhone();
if( status == P2K_PHONE_AT )
{
//We must switch phone to p2k mode by sending AT+MODE=8
//command.
printf("Switching phone to P2K mode ...\n");
// This is hardcoded to /dev/ttyACM0
system("echo \"AT+MODE=8\" > /dev/ttyACM0");
// Wait while phone changes mode...
sleep(5);
status= p2k_findPhone();
}
if( status == P2K_PHONE_NONE ) {
fprintf(stderr, "%s: Error: No phone found. Aborting.\n", argv[0]);
return -1;
}
else if( status == P2K_PHONE_AT ) {
fprintf(stderr, "%s: Error: Could not switch phone to P2K mode. Aborting.\n", argv[0]);
return -1;
}
p2k_openPhone();
// p2k_FSAC_Close(); // just in case somebody left something open
cmd->execute(argc, argv);
p2k_closePhone();
}
char *p2kerrstr[] = { NULL, "Cannot find P2K phone", "Cannot open phone",
"Cannot set configuration", "Cannot acquire interface", "Cannot close phone",
"No connection", "Wrong answer count", "Wrong answer size",
"Negative packet header buffer size - bug in p2kmoto library",
"Packet header ID error", "Packet header status error - expected data",
"Packet header status error - expected no data",
"Data error - expected zero datum", "Error uploading data",
"Erroneous read data size", "Error reading data (is file size correct?)",
"Error in packet header", "Incorrect SEEM size",
"Buffer too long - bug in motoacc" };
void p2kerrmsg( const int status, const char *doingwhat )
{
if( status >= 0 )
return;
if( doingwhat )
fprintf(stderr, "P2K error %s: ", doingwhat);
else
fprintf(stderr, "P2K error: ");
if( status == P2K_E_BUG )
fprintf(stderr, "Unsupported filelist answer - bug in p2kmoto library.\n");
else if( status == P2K_E_OLD )
fprintf(stderr, "Error in SEEM data packet.\n");
else if( status < -19 )
fprintf(stderr, "Error with unknown error code - blame p2kmoto library.\n");
else
fprintf(stderr, "%s.\n", p2kerrstr[-status]);
}
void allocfilelist()
{
if( !filelist.files )
free( filelist.files );
filelist.files= (p2k_fileInfo *)malloc( FILELIST_BASESIZE * sizeof(p2k_fileInfo) );
filelist.nalloc= FILELIST_BASESIZE;
filelist.n= 0;
}
void addtofilelist(const p2k_fileInfo *entry)
{
p2k_fileInfo *oldlist;
if( !filelist.files )
allocfilelist();
if( filelist.n == filelist.nalloc ) {
oldlist= filelist.files;
filelist.files= (p2k_fileInfo *)malloc( 2*filelist.nalloc * sizeof(p2k_fileInfo) );
if( !filelist.files ) {
filelist.files= oldlist;
return;
}
memcpy(filelist.files, oldlist, filelist.nalloc * sizeof(p2k_fileInfo));
filelist.nalloc *= 2;
free(oldlist);
}
memcpy(filelist.files+filelist.n, entry, sizeof(p2k_fileInfo));
++filelist.n;
}
int usagemessage( int argc, char **argv )
{
motoacc_cmd *cmd;
printf("usage: %s command [argument(s)]\n"
"Accesses a Motorola cellphone via P2K. Commands and their arguments:\n\n",
argv[0] );
for( cmd= commands; cmd->command; ++cmd )
printf("%s\n\n", cmd->doc);
return 0;
}
int listusbdev( int argc, char **argv )
{
p2k_devInfo *devinfo;
int count;
printf("USB device list:\n");
devinfo= p2k_getDevList();
while( devinfo[count].vendor>=0 )
{
printf("%04x:%04x: [%s] [%s]\n", devinfo[count].vendor,
devinfo[count].product, devinfo[count].manufacturerStr,
devinfo[count].productStr);
++count;
}
return 0;
}
int phoneinfo( int argc, char **argv )
{
unsigned char str[200];
int size, status= 0, p2kstatus;
if( (p2kstatus= p2k_getPhoneModel( str )) > 0 )
printf("Phone Model: %s\n", str);
else {
p2kerrmsg(p2kstatus, "querying phone model");
printf("Cannot get phone model\n");
status= -1;
}
if( (p2kstatus= p2k_getDriveName(str)) > 0 )
printf("Drive: %s\n", str);
else {
p2kerrmsg(p2kstatus, "querying drive name");
printf("Cannot get drive name\n");
status= -1;
}
size= p2k_freeSpace(str);
if( size > 0 )
printf("Free space: %d bytes\n", size);
else {
p2kerrmsg(size, "querying free space");
printf("Cannot get free space");
status= -1;
}
size= p2k_fileCount();
if( size > 0 )
printf("File count: %d\n", size);
else {
p2kerrmsg(p2kstatus, "querying file count");
printf("Cannot get file count");
status= -1;
}
return status;
}
void fl_print(p2k_fileInfo fileinfo)
{
static char *attrstr[]= { " ", "RO ", "Hidd", "RO+H", "Sys " };
char *thisattrstr;
if( fileinfo.attr == 68 )
thisattrstr= "Lock";
else if( fileinfo.attr > 4 )
thisattrstr= "??? ";
else
thisattrstr= attrstr[fileinfo.attr];
printf("%4d %6ld %3d %s %s\n", fileinfo.id, fileinfo.size, fileinfo.owner,
thisattrstr, fileinfo.name );
}
int listfiles( int argc, char **argv )
{
int status;
printf(" # Size Own Attr Name\n");
status= p2k_fileList(fl_print);
if( status < 0 )
p2kerrmsg(status, "getting file list");
return status;
}
int getfile( int argc, char **argv )
{
FILE *fp;
unsigned char *buf;
char *localfile, *scan;
long size;
int result, remotefile, status;
buf= malloc(0x400);
if( !buf ) {
fprintf(stderr, "%s get: Error: Could not allocate buffer.\n", argv[0]);
return -1;
}
if( !strcmp(argv[2], "-z") ) {
if( argc!=5 ) {
if( argc > 5 )
fprintf(stderr, "%s get: Only one remote file is allowed when giving -z option.\n", argv[0]);
else
fprintf(stderr, "%s get: No remote file given.\n", argv[0]);
free(buf);
return -1;
}
localfile= argv[3];
remotefile= 4;
}
else {
localfile= NULL;
remotefile= 2;
}
while( remotefile < argc ) {
for( scan= argv[remotefile]; *scan && *scan != ':'; ++scan );
if( !*scan ) {
fprintf(stderr, "%s get: no file size given for file `%s'.\n", argv[0], argv[remotefile]);
free(buf);
return -1;
}
*scan= 0;
size= strtol(scan+1, NULL, 0);
printf("Downloading file `%s', size %ld...\n", argv[remotefile], size);
if( !localfile ) {
for( scan= argv[remotefile]; *scan; ++scan );
for( --scan ; scan >= argv[remotefile] && *scan != '/'; --scan );
localfile= scan+1;
}
fp= fopen( localfile, "w" );
if( !fp ) {
fprintf(stderr, "%s get: Could not create local file `%s'.\n", argv[0], localfile);
free(buf);
return -1;
}
if( 0 > (result= p2k_FSAC_Open(argv[remotefile], 0)) ) {
p2kerrmsg(result, "opening file");
fprintf(stderr, "%s get: Could not open remote file `%s'.\n", argv[0], argv[remotefile]);
fclose(fp);
free(buf);
return -1;
}
while( size > 0x400L ) {
result= p2k_FSAC_Read(buf, 0x400);
if( result < 0 ) {
p2kerrmsg(result, "reading data");
fprintf(stderr, "%s get: Error while reading data from file `%s'.\n", argv[0], argv[remotefile]);
p2k_FSAC_Close();
fclose(fp);
free(buf);
return -1;
}
fwrite(buf, 1L, 0x400L, fp);
size -= 0x400L;
}
result= p2k_FSAC_Read(buf, (int)size);
if( result < 0 ) {
p2kerrmsg(result, "reading data");
fprintf(stderr, "%s get: Error while reading data from file `%s'.\n", argv[0], argv[remotefile]);
p2k_FSAC_Close();
fclose(fp);
free(buf);
return -1;
}
fwrite(buf, 1L, size, fp);
p2k_FSAC_Close();
fclose(fp);
localfile= NULL;
++remotefile;
}
free(buf);
return 0;
}
int putfile( int argc, char **argv )
{
FILE *fp;
unsigned char *buf;
char *localfile, *scan;
long size;
int result, remotefile, status;
buf= malloc(0x400);
if( !buf ) {
fprintf(stderr, "%s put: Error: Could not allocate buffer.\n", argv[0]);
return -1;
}
if( !strcmp(argv[2], "-z") ) {
if( argc!=5 ) {
if( argc > 5 )
fprintf(stderr, "%s put: Only one remote file is allowed when -z option is present.\n", argv[0]);
else
fprintf(stderr, "%s put: No remote file name given.\n", argv[0]);
free(buf);
return -1;
}
localfile= argv[3];
remotefile= 4;
}
else {
localfile= NULL;
remotefile= 2;
}
while( remotefile < argc )
{
if( !localfile ) {
for( scan= argv[remotefile]; *scan; ++scan );
for( --scan ; scan >= argv[remotefile] && *scan != '/'; --scan );
localfile= scan+1;
}
printf("Uploading file `%s' --> `%s'...\n", localfile, argv[remotefile]);
fp= fopen( localfile, "r" );
if( !fp ) {
fprintf(stderr, "%s put: Could not open local file `%s'.\n", argv[0], localfile);
free(buf);
return -1;
}
fseek(fp, 0L, SEEK_END);
size= ftell(fp);
fseek(fp, 0L, SEEK_SET);
if( 0 > (result= p2k_FSAC_Open(argv[remotefile], 0)) ) {
p2kerrmsg(result, "opening file");
fprintf(stderr, "%s get: Could not open remote file `%s'.\n", argv[0], argv[remotefile]);
fclose(fp);
free(buf);
return -1;
}
while( size > 0x400L ) {
fread(buf, 1L, 0x400L, fp);
result= p2k_FSAC_Write(buf, 0x400);
if( result < 0 ) {
p2kerrmsg(result, "writing data");
fprintf(stderr, "%s put: Error while writing data to file `%s'.\n", argv[0], argv[remotefile]);
p2k_FSAC_Close();
fclose(fp);
free(buf);
return -1;
}
size -= 0x400L;
}
fread(buf, 1L, size, fp);
result= p2k_FSAC_Write(buf, (int)size);
if( result < 0 ) {
p2kerrmsg(result, "writing data");
fprintf(stderr, "%s put: Error while writing data to file `%s'.\n", argv[0], argv[remotefile]);
p2k_FSAC_Close();
fclose(fp);
free(buf);
return -1;
}
p2k_FSAC_Close();
fclose(fp);
localfile= NULL;
++remotefile;
}
free(buf);
return 0;
}
void fl_buildlist(p2k_fileInfo fileinfo)
{
addtofilelist(&fileinfo);
}
int backup( int argc, char **argv )
{
p2k_fileInfo *scan, *top;
struct stat statresult;
FILE *handle;
unsigned char *buf;
char *path, *dir, *partdir, *lpath;
long size;
int status, pathlen, fmode, basemode, found, errno_;
printf("Creating file list...\n");
allocfilelist();
status= p2k_fileList(fl_buildlist);
if( status < 0 ) {
p2kerrmsg(status, "getting file list");
fprintf(stderr, "%s backup: Could not list files.\n", argv[0]);
return status;
}
if( argc > 2 ) {
path= argv[2];
pathlen= strlen(path);
if( *path == '/' ) lpath= path+1;
else lpath= path;
for( dir= path+pathlen; dir > lpath && *dir != '/'; --dir );
if( *dir == '/' ) {
*dir= 0;
status= stat(lpath, &statresult);
if( status < 0 ) {
if( errno == ENOENT ) {
partdir= lpath;
while( 13 ) {
while( *partdir && *partdir!='/' )
++partdir;
if( !*partdir )
break;
*partdir= 0;
// printf("creating %s\n", lpath);
mkdir(lpath, 0777);
*partdir= '/';
++partdir;
}
// printf("creating %s\n", lpath);
status= mkdir(lpath, 0777);
if( status < 0 ) {
perror(argv[0]);
fprintf(stderr, "%s backup: Could not create local target directory `%s'.\n", argv[0], lpath);
return -1;
}
}
else {
perror(argv[0]);
fprintf(stderr, "%s backup: Error while checking local target directory `%s'.\n", argv[0], lpath);
return -1;
}
}
*dir= '/';
}
}
else {
path= NULL;
pathlen= 0;
}
buf= malloc(0x400);
if( !buf ) {
fprintf(stderr, "%s backup: Could not allocate buffer.\n", argv[0]);
return -1;
}
basemode= umask(0);
umask(basemode);
basemode= ~basemode & 0666;
found= 0;
top= filelist.files + filelist.n;
for( scan= filelist.files; scan< top; ++scan ) {
if( !path || !strncmp(path, scan->name, pathlen) ) {
found= 1;
printf("Downloading %s ...\n", scan->name);
if( *scan->name == '/' ) lpath= scan->name+1;
else lpath= scan->name;
for( dir= scan->name+pathlen; *dir; ++dir );
for( --dir; dir > scan->name+pathlen && *dir != '/'; --dir );
if( dir > scan->name+pathlen ) {
*dir= 0;
status= stat(lpath, &statresult);
if( status < 0 && errno == ENOENT ) {
partdir= scan->name+pathlen+1;
while( *partdir && *partdir != '/' )
++partdir;
while( *partdir )
{
*partdir= 0;
// printf("creating %s\n", lpath);
mkdir(lpath, 0777);
*partdir= '/';
++partdir;
while( *partdir && *partdir != '/' )
++partdir;
}
// printf("creating %s\n", lpath);
status= mkdir(lpath, 0777);
if( status < 0 ) {
perror(argv[0]);
fprintf(stderr, "%s backup: Could not create local target directory `%s'.\n", argv[0], lpath);
continue;
}
}
*dir= '/';
}
handle= fopen(lpath, "w");
if( !handle ) {
perror(argv[0]);
fprintf(stderr, "%s backup: Could not create local file `%s'.\n", argv[0], lpath);
continue;
}
status= p2k_FSAC_Open(scan->name, scan->attr);
if( status < 0 ) {
p2kerrmsg(status, "opening remote file");
fprintf(stderr, "%s backup: Error opening remote file `%s'.\n", argv[0], scan->name);
fclose(handle);
continue;
}
errno= 0;
for( size= scan->size; size> 0x400; size -= 0x400 ) {
status= p2k_FSAC_Read(buf, 0x400);
if( status < 0 )
goto p2kreaderr;
fwrite(buf, 1L, 0x400L, handle);
}
status= p2k_FSAC_Read(buf, (int)size);
if( status < 0 ) {
p2kreaderr:
p2kerrmsg(status, "reading data");
fprintf(stderr, "%s backup: Error reading data from `%s'.\n", argv[0], lpath);
p2k_FSAC_Close();
fclose(handle);
continue;
}
p2k_FSAC_Close();
fwrite(buf, 1L, size, handle);
fclose(handle);
if( errno ) {
fprintf(stderr, "%s backup: Error writing to local file `%s'.\n", argv[0], lpath);
continue;
}
fmode= basemode;
// We map the read-only attribute to read-only local files, hidden to
// lacking read permission for group and others, "system" to executable,
// "lock" to sticky.
if( (scan->attr & 1) != 0 ) fmode &= ~0222;
if( (scan->attr & 2) != 0 ) fmode &= ~0044;
if( (scan->attr & 4) != 0 ) fmode |= ((fmode >> 2) & 0111);
if( (scan->attr & 64) != 0 ) fmode |= 01000;
status= chmod(lpath, fmode);
if( status < 0 )
fprintf(stderr, "%s backup: Could not set file mode according to attributes.\n", argv[0]);
}
}
if( !found )
fprintf(stderr, "%s backup: No suitable files found.\n", argv[0]);
free(buf);
return 0;
}
int remotechattr( int argc, char **argv )
{
unsigned char attribs;
int status, remotefile;
char *scan;
attribs= 0;
if( *argv[2] == '0' )
if( argv[2][1] ) {
fprintf(stderr, "%s chattr: 0 (no attribute) cannot be combined with any other attribute.\n", argv[0]);
return -1;
}
else;
else
for( scan= argv[2]; *scan; ++scan )
if( *scan == 'r' ) attribs |= 1;
else if( *scan == 'h' ) attribs |= 2;
else if( *scan == 's' ) attribs |= 4;
else if( *scan == 'l' ) attribs |= 64;
else {
fprintf(stderr, "%s chattr: unknown attribute `%c'.\n", argv[0], *scan);
return -1;
}
for( remotefile= 3; remotefile < argc; ++remotefile )
{
status= p2k_FSAC_Open(argv[remotefile], attribs);
if( status < 0 ) {
p2kerrmsg(status, "changing file attributes");
fprintf(stderr, "%s chattr: Could not change attributes of file `%s'.\n", argv[0], argv[remotefile]);
}
p2k_FSAC_Close();
}
return 0;
}
int delfile( int argc, char **argv )
{
int fileind, confirm, status, retcode= 0;
for( fileind= 2; fileind < argc; ++fileind )
{
printf("About to delete remote file `%s'. Please confirm by typing 'y':\n", argv[fileind]);
confirm= getchar();
if( confirm != 'y' && confirm != 'Y' )
printf("NOT deleting `%s'.\n", argv[fileind]);
else {
status= p2k_FSAC_Delete(argv[fileind]);
if( status < 0 ) {
p2kerrmsg(status, "deleting file");
fprintf(stderr, "%s rm: Error deleting `%s'.\n", argv[0], argv[fileind]);
retcode= -1;
}
}
while( getchar() != '\n' );
}
return retcode;
}
Approfondimenti: