µTasker Forum
µTasker Forum => µTasker general => Topic started by: hervé 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
-
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
-
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())
#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)
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
-
Hi Mark,
I don't have the problem no more now, so you solved it.
Thanks a lot.
-
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
-
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