Author Topic: FTP  (Read 9975 times)

Offline hervé

  • Jr. Member
  • **
  • Posts: 98
    • View Profile
FTP
« on: January 21, 2010, 04:38:13 PM »
Hello Mark,

As I understand,
"favicon.ico" is a part of user_files.
When I upload it, I got 1150 bytes which matches sizeof(_favicon).

When I look into the file, the first byte is in fact nxp_favicon[5] : It starts after the FILE_HEADER.
And it ends with five dummy bytes outside of nxp_favicon.

It will be better to cancel this 5 bytes (HEADER size) sending no ? and correct the file size also ...

What is the use of the FILE_HEADER for these user_files ?

Regards





Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: FTP
« Reply #1 on: January 21, 2010, 05:27:10 PM »
Hi Hervé

I never tried downloading a user file via FTP!!! You will notice that they are marked as read-only since they can not be deleted or overwritten (they are a part of code and not in the file system).

But I can understand what is happening; FTP thinks that they are uFileSytem files when it gets a GET command and so increments past the header which is 'normally' there. This is why the first (usually 5) bytes are missing and the end will have 5 random bytes.

To make loading user files to a PC possible it would be necessary for FTP to distinguish between user files and file system file (which it probably can already do since it displays them as read-only) and then miss out the pointer increment past the uFile header that it it is presently obviously doing.

I'll take a look and tell you what change is required. I could image that it may be useful to be able to share user files using FTP as download method...

Regards

Mark

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: FTP
« Reply #2 on: January 21, 2010, 10:13:54 PM »
Hi Hervé


I checked this out and found that the FTP module doesn't actually know that it is working with a user file. It also doesn't need to know this since the general solution is to allow files to be read from user files as they are read from uFileSystem files.
I adapted some code in uFile.c to allows this to work - it required a little more than expected but maintains compatibility and allows general access without the header problem.

To give it a try make the following changes:

1) In uFile.c add a new local routine (add it just below the existing uGetFileLength())

Code: [Select]
#ifdef INTERNAL_USER_FILES                                               // {19}
// Local copy of the routine uGetFileLength which adjusts the file header if the file is not a user file
//
static MAX_FILE_LENGTH uGetFileLength_variable_header(MEMORY_RANGE_POINTER ptrfile, unsigned char *ptrHeaderLength)
{
    MAX_FILE_LENGTH FileLength;
    #if defined INTERNAL_USER_FILES
    FileLength = fnFilterUserFileLength(ptrfile);
    if (FileLength != 0) {
        return FileLength;
    }
    #endif
    fnGetParsFile(ptrfile, (unsigned char *)&FileLength, sizeof(MAX_FILE_LENGTH));

    *ptrHeaderLength = FILE_HEADER;                                      // adjust the length since it is a uFileSystem file
    if (FileLength == 0) {                                               // protect against corrupted file so that it can be deleted
        return _FILE_GRANULARITY;                                        // the size of a file block
    }

    if (FileLength == (MAX_FILE_LENGTH)(-1)) {                           // check for blank FLASH memory
        return 0;                                                        // no length so empty
    }
                                                                         // if a (corrupted) length should be too large, we limit it to end of the file system
    if (((CAST_EXTENDED_POINTER_ARITHMETIC)((MEMORY_RANGE_POINTER)(uFILE_START + FILE_SYSTEM_SIZE - FILE_HEADER)) - (CAST_EXTENDED_POINTER_ARITHMETIC)ptrfile) < FileLength) {
        FileLength = (MAX_FILE_LENGTH)((CAST_EXTENDED_POINTER_ARITHMETIC)(MEMORY_RANGE_POINTER)(uFILE_START + FILE_SYSTEM_SIZE - FILE_HEADER) - (CAST_EXTENDED_POINTER_ARITHMETIC)ptrfile); // the space remaining
    }
    return FileLength;
}
#endif

2) Now modify the routine uGetFileData() with the code below (the changes are only used when INTERNAL_USER_FILES is active)

Code: [Select]
extern MAX_FILE_LENGTH uGetFileData(MEMORY_RANGE_POINTER ptrFile, MAX_FILE_SYSTEM_OFFSET FileOffset, unsigned char *ucData, MAX_FILE_LENGTH DataLength)
{
    #ifdef INTERNAL_USER_FILES                                           // {19}
        #if defined _WINDOWS
    extern int iFetchingInternalMemory;
        #endif
    unsigned char ucFileHeaderLength = 0;
    MAX_FILE_SYSTEM_OFFSET RemainingLength = uGetFileLength_variable_header(ptrFile, &ucFileHeaderLength);
    #else
    MAX_FILE_SYSTEM_OFFSET RemainingLength = uGetFileLength(ptrFile);
    #endif
    if (RemainingLength) {
        RemainingLength -= FileOffset;                                   // this is remaining length in file from this position
        if (RemainingLength != 0) {
            if (RemainingLength >= DataLength) {
                 RemainingLength = DataLength;
            }
    #ifdef INTERNAL_USER_FILES                                           // {19}
        #if defined _WINDOWS
            if (!ucFileHeaderLength) {
                iFetchingInternalMemory = 1;                             // mark that the file in in code memory for simulation use
            }
        #endif
            fnGetParsFile((ptrFile + FileOffset + ucFileHeaderLength), ucData, (MAX_FILE_LENGTH)RemainingLength);
    #else
            fnGetParsFile((ptrFile + FileOffset + FILE_HEADER), ucData, (MAX_FILE_LENGTH)RemainingLength);
    #endif
        }
    }
    return ((MAX_FILE_LENGTH)RemainingLength);                           // return the length copied
}

This works on the target and on the simulator and so allows user files embedded in code to be extracted to a file via FTP (or other methods).

Tell me if it solves your requirements.

Regards

Mark

Offline hervé

  • Jr. Member
  • **
  • Posts: 98
    • View Profile
Re: FTP
« Reply #3 on: January 25, 2010, 08:45:27 AM »
Hi Mark,

I don't have the problem no more now, so you solved it.

Thanks a lot.

Offline hervé

  • Jr. Member
  • **
  • Posts: 98
    • View Profile
Re: FTP
« Reply #4 on: January 28, 2010, 08:34:54 AM »
Hello Mark,

A small note to say that with some FTP Client uses the command :RETR \mufile.txt to upload a file.
uTAsker in this case reject it because it thinks there is no name (due to backslash at first poistion).
Is it possible to add the test of a null character in second position before saying there is no name ?

Thanks

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: FTP
« Reply #5 on: January 28, 2010, 02:37:07 PM »
Hi Hervé

I believe that I had similar cases when integrating the utFAT module together with FTP. In this case '/' or '\' will be ignored.

It may be best to generally replace the fixed file position (ucIp_Data + 5) with a subroutine which scans the input and returns a pointer to the name (maybe there are, or will be, FTP clients which do similar things with other commands). This would then ensure accuracy in all possible cases.

Regards

Mark