Fetching Files
You can receive files from the device if you know the specific full path of the source file. Analysis techniques have commands to create CSV files (for example), which respond with the full path of the created file. By using this path, you can retrieve the file using the File:Xfer category of commands.
Commands include:
File:Xfer:Get <filename>
File:Xfer:Next
File:Xfer:Resend
File:Xfer:DoneGet
Another way to receive a small file (less than 2 MB) is to use the "File:Fetch <pathname>" command. This receives an entire file in one transfer without flow-control or error checking.
The basic file transfer operation requires first issuing an "File:Xfer:Get <filename>" command. This will respond with a text string response containing the filename (in double-quotes), the length in bytes, the file modification date in YYYY/MM/DD format, and the file modification time in HH:MM:SS format. Using this information, you can create a file on your local system and then subsequently call repetitive "File:Xfer:Next"commands go retrieve consecutive buffers of binary byte data to fill the file with. This command responds first with three 32-bit unsigned binary values that indicate the byte-order of the 32-bit values (a "magic" number, binary 0x12345678 32-bit value), then the number of bytes in the coming buffer, then a simple arithmetic sum of the coming bytes. This 12-byte binary structure is immediately followed by the number of buffer bytes indicated in the second value. Once you've received the buffer, you can calculate the same arithmetic sum to confirm the reception. If they don't match, you can use the "File:Xfer:Resend" command to retransmit the same buffer again. The individual buffer length maximum is 4096 bytes. When completed, send a "File:Xfer:DoneGet" command to indicate completion.
The following is an example of how to program retrieving files from the device. This example runs in the Windows programming environment.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h> // getch
#include "Trace.h"
#include "UtilSocket.h"
#include "OsCompatibility.h"
int main( int argc, char *argv[] )
{
bool helpFlag=false;
bool verboseFlag=false;
char *remoteRetrieveFileName=NULL;
char *localDestinationFileName=NULL;
char *ipAddress=NULL;
int portNumber=923;
bool unknownFlag = false;
while( *(++argv) )
{
if( !strcmp( *argv, "-h" ) ) helpFlag=true;
else if( !strcmp( *argv, "-help" ) ) helpFlag=true;
else if( !strcmp( *argv, "-v" ) ) verboseFlag=true;
else if( !strcmp( *argv, "-port" ) ) portNumber = atoi(*(++argv));
else if( ipAddress==NULL ) ipAddress = *argv;
else if( remoteRetrieveFileName==NULL ) remoteRetrieveFileName = *argv;
else if( localDestinationFileName==NULL ) localDestinationFileName = *argv;
else
{
unknownFlag=true;
printf("Error: unknown argument [%s]\n", *argv );
}
}
if( helpFlag==true || unknownFlag==true )
{
printf("Usage: BwGet [options] <ip> <retrieve-file> [<destination-file-name>]\n");
printf("Options: -h ... show this help message\n");
printf(" -v ... verbose messages displayed\n");
printf("IP: IP address of host machine\n");
printf("Retrieve: Complete file path on remote machine\n");
printf("Destination: Destination file path on local machine\n");
printf("Note: If no destination is specified, uses current working directory\n");
exit(0);
}
if( ipAddress==NULL )
{
printf("Must provide IP address\n");
exit(0);
}
if( remoteRetrieveFileName==NULL )
{
printf("Must provide file path to retrieve\n");
exit(0);
}
char destBuffer[1024];
if( localDestinationFileName==NULL )
{
char fname[MAX_FNAME];
char fext[MAX_EXT];
_splitpath(remoteRetrieveFileName,NULL,NULL,fname,fext);
sprintf(destBuffer,"%s%s",fname,fext);
localDestinationFileName = destBuffer;
}
if( verboseFlag )
{
printf("IP Address...........%s\n", ipAddress );
printf("IP Port..............%u\n", portNumber );
printf("RemoteRetrieveFile...%s\n", remoteRetrieveFileName );
printf("LocalDestinationFile..%s\n", localDestinationFileName );
}
if( verboseFlag )
printf("Creating socket object\n");
UtilSocket *socket = new UtilSocket(AF_INET);
HANDLE f=INVALID_HANDLE_VALUE;
try
{
if( verboseFlag )
printf("Connecting to: %s, port %u\n", ipAddress, portNumber );
socket->Connect(ipAddress,portNumber);
if( verboseFlag )
printf("Connection successful\n");
//==========================================
// clear status and event queue
socket->Send( "stc; evc\n");
//==========================================
static const int BUFSIZE=4096;
char buffer[BUFSIZE];
int blen=0;
sprintf(buffer,"File:Xfer:Get \"%s\"\n", remoteRetrieveFileName );
socket->Send( buffer );
blen=socket->Receive( buffer, BUFSIZE );
if(blen>0) buffer[blen-1]=0; // remove newline
//==========================================
if( verboseFlag )
printf("Response to Get command: %s\n", buffer );
char filename[1024];
if( buffer[0]!='"' )
throw "[Invalid_Response_To_Get_Command]" ;
int n=1;
while( buffer[n] != 0 && buffer[n]!='"' )
{
filename[n-1] = buffer[n];
n++;
}
filename[n++]=0;
if( verboseFlag )
printf("File name is: %s\n", filename );
//==========================================
unsigned int length, year, month, day, hour, minute, second;
if( sscanf(buffer+n,"%u %u/%u/%u %u:%u:%u",
&length, &year, &month, &day, &hour, &minute, &second ) != 7 )
throw "[Invalid_Response_Length_Date_Time]" ;
if( verboseFlag )
{
printf("Length is: %u\n", length );
printf("File date is: %u/%u/%u\n", year, month, day );
printf("File time is: %u:%u:%u\n", hour, minute, second );
}
//==========================================
if( verboseFlag )
printf("Opening destination file: %s\n", localDestinationFileName );
HANDLE f = CreateFile(localDestinationFileName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if( f==INVALID_HANDLE_VALUE )
throw "[Unable_To_Create_Destination_File]";
//==========================================
SYSTEMTIME thesystemtime;
GetSystemTime(&thesystemtime);
thesystemtime.wYear = year ;
thesystemtime.wMonth = month ;
thesystemtime.wDayOfWeek = 0; // ?? hopefully ignored
thesystemtime.wDay = day;
thesystemtime.wHour = hour;
thesystemtime.wMinute = minute;
thesystemtime.wSecond = second;
thesystemtime.wMilliseconds = 0;
FILETIME thefiletime;
SystemTimeToFileTime(&thesystemtime,&thefiletime);
SetFileTime(f,(LPFILETIME) NULL,(LPFILETIME) NULL,&thefiletime);
//==========================================
struct
{
uint32_t magic; // 0x12345678
uint32_t bytes;
uint32_t sum;
} response ;
uint32_t totalTransferred=0;
while( totalTransferred<length )
{
socket->Send( "File:Xfer:Next\n" );
blen=socket->Receive( (char*) &response, sizeof(response) );
if( blen!=sizeof(response) )
throw "[No_Response_From_Next_Command]" ;
if( verboseFlag )
printf("Next: Magic %08X, Bytes %u, Sum %u\n", response.magic, response.bytes, response.sum );
if( response.bytes==0 )
break;
//==========================================
char xfer[BUFSIZE];
uint32_t cnt=0;
while( cnt < response.bytes )
{
blen=socket->Receive( xfer+cnt, response.bytes-cnt );
if( blen==0 )
throw "[Binary_Xfer_Unsuccessful]";
cnt += blen;
}
//==========================================
uint32_t sum=0;
for( uint32_t i=0; i<response.bytes; i++ )
sum += (uint8_t) xfer[i];
if( verboseFlag )
printf("Received buffer sum of bytes is: %u\n", sum );
int retry=3;
while( sum != response.sum && retry>0 )
{
socket->Send( "File:Xfer:Resend\n" );
blen=socket->Receive( (char*) &response, sizeof(response) );
if( blen!=sizeof(response) )
throw "[No_Response_From_Resend_Command]" ;
if( verboseFlag )
printf("Resend: Magic %08X, Bytes %u, Sum %u\n", response.magic, response.bytes, response.sum );
//==========================================
cnt=0;
while( cnt < response.bytes )
{
blen=socket->Receive( xfer+cnt, response.bytes-cnt );
if( blen==0 )
throw "[Binary_Resend_Xfer_Unsuccessful]";
cnt += blen;
}
sum=0;
for( uint32_t i=0; i<response.bytes; i++ )
sum += xfer[i];
if( verboseFlag )
printf("Resend received buffer sum of bytes is: %u\n", sum );
retry++ ;
}
if( retry==0 )
throw "[Binary_Transfer_Bad]" ;
//==========================================
DWORD bytesWritten ;
if( !WriteFile( f, xfer, response.bytes, &bytesWritten, NULL ) )
throw( "[Error_Writing_To_File]");
if( bytesWritten != response.bytes )
throw( "[Insufficient_Bytes_Written]");
totalTransferred += bytesWritten ;
}
//==========================================
socket->Send( "st?\n" );
blen=socket->Receive( buffer, BUFSIZE );
if(blen>0) buffer[blen-1]=0; // remove newline
if( verboseFlag )
printf("Final error status is: %s\n", buffer );
//==========================================
socket->Send( "File:Xfer:DoneGet\n" );
//==========================================
if( verboseFlag )
printf("Closing file normally\n");
CloseHandle(f);
delete socket;
}
catch(const char *msg)
{
printf("Error: %s\n", msg );
delete socket;
if( f!=INVALID_HANDLE_VALUE ) CloseHandle(f);
remove(localDestinationFileName);
}
catch(...)
{
printf("Unknown error encountered\n");
delete socket;
if( f!=INVALID_HANDLE_VALUE ) CloseHandle(f);
remove(localDestinationFileName);
}
return 0;
}