Page 1 of 1

FAT spacing

Posted: Thu Apr 12, 2007 1:58 pm
by GLneo
hi, I'm now fixing up my fat driver and i am having alot of trouble with making a function that gets a string and returns a string with the 8.3 spacing, like this:

cool.bin will return cool****bin

* are spaces

i thought this would be easy but it is very hard, the code i have now is:

Code: Select all

#include <stdio.h>
#include <stdlib.h>

unsigned char *fatPad(unsigned char *str)
{
    int count = 0, temp_count = 0;
    unsigned char temp_string[11];
    for(temp_count = 0; temp_count < 11; temp_count++, count++) // loop though the string
    {
        if(str[count] != '.')   // if not a .
            temp_string[temp_count] = str[count]; // paste it over from str to temp_string
        else // other wise
            for(; temp_count < 8; temp_count++) // while were less than 8
                temp_string[temp_count] = '*';  // space the temp_string 
    }
    return memcpy(str, temp_string, 11); // temp_string will be destroyed so return to str
}

int main ()
{
    char string[11];
    puts(fatPad(gets(string)));
    system("pause");
    return 0;
}  
this output is cool**** but it should be: cool****bin

all comments welcome!

Posted: Thu Apr 12, 2007 2:09 pm
by ~
In a generic 8.3 file name for FAT, you won't find periods (except for . and ..).

If looking for short filenames, you should copy the entire 11 bytes out of the 8.3, and then figure out both the actual name and its extension by separating it in a group of 8 bytes for filename and 3 bytes for extension, and then get rid of spaces to form your final 'FILENAME.EXT' string.

By the way, aren't you iterating up to 8 bytes instead of 11?

Posted: Thu Apr 12, 2007 2:18 pm
by bsunisol
maybe you can define a string that is from beginning
filled with spaces:

Code: Select all

char* name = "***********";
and then find the dot and copy both parts with a loop like:

Code: Select all

name[i] = str[i]
start with the name at the beginning and with the extension
at the end. i would not try to build such a complex loop.
i would rather code 2 simple ones.

and take care about the \0 at the end of an c-string.

Posted: Thu Apr 12, 2007 2:38 pm
by bubach
maybe something like: (untested)

Code: Select all

unsigned char *fatPad(unsigned char *str)
{ 
    int count = 0, temp_count = 0; 
    unsigned char temp_string[11]; 
    for(temp_count = 0; temp_count < 11; temp_count++, count++) // loop though the string 
    { 
        if(str[count] != '.')   // if not a . 
            temp_string[temp_count] = str[count]; // paste it over from str to temp_string 
        else // other wise
        {
            for(; temp_count < 8; temp_count++) // while were less than 8
                temp_string[temp_count] = '*';  // space the temp_string
            temp_string[temp_count] = str[count+1];
            temp_string[temp_count+1] = str[count+2];
            temp_string[temp_count+2] = str[count+3];
        }
    } 
    return memcpy(str, temp_string, 11); // temp_string will be destroyed so return to str 
}

Posted: Thu Apr 12, 2007 2:42 pm
by ~
bsunisol wrote:maybe you can define a string that is from beginning
filled with spaces:

Code: Select all

char* name = "***********";
and then find the dot and copy both parts with a loop like:

Code: Select all

name[i] = str[i]
start with the name at the beginning and with the extension
at the end. i would not try to build such a complex loop.
i would rather code 2 simple ones.

and take care about the \0 at the end of an c-string.
Are you talking about the FAT short file names? They don't have such dots or '\0', as far as I know, except for the current directory entry '.' and for the parent directory '..', just ASCII characters and blank spaces (to be removed).

The delimitation of the 8.3 format could come from copying first the 11 bytes of the short filename entry, and then separate it into its first 8 bytes, remove spaces, optionally add a '.' in the final string, take the last 3 bytes and remove its blank spaces to build our final NAME.EXT type of display name.

Posted: Thu Apr 12, 2007 2:50 pm
by bsunisol
Are you talking about the FAT short file names? They don't have such dots or '\0', as far as I know, except for the current directory entry '.' and for the parent directory '..', just ASCII characters and blank spaces (to be removed).
yes, i know. i just wanted to point on it. c appends
to all strings a '\0'. but fat-tables are without them.
so he have to crap the string before writing it to the
fs.

Posted: Thu Apr 12, 2007 3:27 pm
by Kevin McGuire

Code: Select all

unsigned char *fatPad(unsigned char *str){
	unsigned int x;
	unsigned char e, f, g;
	/// find period in file name, less than eight, or string zero termination.
	for(x = 0; (str[x] != '.') && (x < 8) && (str[x] != 0); ++x);
	if(str[x] != '.'){
		/// filename to long (no extension found yet)
		for(; (str[x] != 0) && (str[x] != '.'); ++x);
		if(str[x] == 0){
			/// no extension found (use last three ending letters
			x -= 4;
		}
	}
	/// extension
	e = str[x+1]; f = str[x+2]; g = str[x+3];
	str[8] = e; str[9] = f; str[10] = g;
	/// pad remaining
	for(; x < 8; ++x){
		str[x] = '*'; // <---- RIGHT HERE
	}
	return str;
}
The space allocated for the data that str points to when passed to the function as a argument must be at least eleven bytes in length or the function will overwrite data at the end. So I think it is a slightly poor way when instead you might have.

padFat(unsigned char *in, unsigned char *out);

And, out points to the buffer where you are building the cluster to be written to disk - or cache of the cluster stored in RAM.

It should be faster to fill the 'out' string with the space value then write in the correct ones by scanning the 'in' string.

Posted: Thu Apr 12, 2007 4:31 pm
by pcmattman
THis won't allow any filename with more than one dot, but it works:

Code: Select all

void hConvertFilename( char* str )
{
	// start by converting to uppercase
	int i;
	for( i = 0; i < strlen( str ); i++ )
	{
		str[i] = toupper( str[i] );
	}
	
	// find the full stop
	int fullstoploc = find( str, '.', 0, strlen( str ) );
	
	// check for validity
	if( fullstoploc == -1 )
	{
		// make it the length of the string
		fullstoploc = strlen( str );
	}
	
	// shift
	for( i = fullstoploc; i < strlen( str ); i++ )
		str[i] = str[i+1];
	
	// now pad out the string if needed
	// ie. test.bin --> TEST    BIN
	if( strlen( str ) < 11 )
	{
		// get the extension length
		int extlen = strlen( str ) - fullstoploc;
		
		// first offset for the extension
		int firstoff = 11 - extlen;
		
		// move ext to the end of the string
		i = firstoff;
		while( i < 11 )
		{			
			// put it there
			str[i] = str[i-(8-fullstoploc)];
			i++;
		}
		str[i] = 0;
		
		// pad out with spaces
		for( i = fullstoploc; i < firstoff; i++ )
			str[i] = ' ';
	}
}

Posted: Thu Apr 12, 2007 4:47 pm
by B.E
try this:

Code: Select all

char *fatPad(char *str){
	int i,j;
	char tempstr[3], *tstr = str, *endStr;
	// Find '.'
	for (i=0;(i <= 8) && *str++ != '.';++i);

	endStr = str;
	if (*(str-1) != '.'){
		// TODO: make unique name
		while ( *endStr++ != '.' )
			if (!*endStr){
				for (i=9;(i <= 11);++i,tstr[i] = 0);
				return tstr;
			}
	}
	// copy extention to a temp location
	for (j=0;j < 3;tempstr[j] = endStr[j], ++j);

	// go back one so that it now point to the '.'
	str--;

	// fill rest of string with spaces
	for (;i <= 8;++i,*str++ = ' ');

	// copy extention to a temp location
	for (i=0;i < 3;*str++ = tempstr[i], ++i);
	*str = 0;
	return tstr;
}


Posted: Thu Apr 12, 2007 6:48 pm
by GLneo
B.E. = fds.... : fds*****... so that could be a problem
Kevin McGuire = looks ok
bubach = cool.exe : cool****eex

bubach is very close so i modified his code and got:

Code: Select all

unsigned char *fatPad(unsigned char *str)
{
    int count = 0, temp_count = 0;
    unsigned char temp_string[11];
    for(temp_count = 0; temp_count < 11; temp_count++, count++) // loop though the string
    {
        if(str[count] != '.')   // if not a .
            temp_string[temp_count] = str[count]; // paste it over from str to temp_string
        else // other wise
        {
            for(; temp_count < 8; temp_count++) // while were less than 8
                temp_string[temp_count] = '*';  // space the temp_string
            temp_string[temp_count] = str[count+1];
            temp_string[temp_count+1] = str[count+2];
            temp_string[temp_count+2] = str[count+3];
            break;       //<----------- NEW-------------------
        }
    }
    return memcpy(str, temp_string, 11); // temp_string will be destroyed so return to str
}
which works very good.