FAT spacing

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

FAT spacing

Post 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!
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Post 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?
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

Post 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.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Post 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 
}
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Post 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.
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

Post 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.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post 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.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post 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] = ' ';
	}
}
User avatar
B.E
Member
Member
Posts: 275
Joined: Sat Oct 21, 2006 5:29 pm
Location: Brisbane Australia
Contact:

Post 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;
}

Image
Microsoft: "let everyone run after us. We'll just INNOV~1"
GLneo
Member
Member
Posts: 237
Joined: Wed Dec 20, 2006 7:56 pm

Post 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.
Post Reply